aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve French <stfrench@microsoft.com>2018-06-14 22:56:32 -0400
committerSteve French <stfrench@microsoft.com>2018-06-15 03:38:08 -0400
commitbea851b8babe6c87c36e97c9de0dd0bea0dd5802 (patch)
tree96f368fbb78d6b4a61e9f8174e35372ea806d240
parent662bf5bc0a6f7b2abf7f9125c6319f06bb2efcf9 (diff)
smb3: Fix mode on mkdir on smb311 mounts
mkdir was not passing the mode on smb3.11 mounts with posix extensions Signed-off-by: Steve French <stfrench@microsoft.com>
-rw-r--r--fs/cifs/cifsglob.h4
-rw-r--r--fs/cifs/inode.c13
-rw-r--r--fs/cifs/smb2ops.c1
-rw-r--r--fs/cifs/smb2pdu.c153
-rw-r--r--fs/cifs/smb2proto.h4
-rw-r--r--fs/cifs/trace.h3
6 files changed, 175 insertions, 3 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 9dd5f1a3d64b..bd78da59a4fd 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -315,6 +315,10 @@ struct smb_version_operations {
315 /* send echo request */ 315 /* send echo request */
316 int (*echo)(struct TCP_Server_Info *); 316 int (*echo)(struct TCP_Server_Info *);
317 /* create directory */ 317 /* create directory */
318 int (*posix_mkdir)(const unsigned int xid, struct inode *inode,
319 umode_t mode, struct cifs_tcon *tcon,
320 const char *full_path,
321 struct cifs_sb_info *cifs_sb);
318 int (*mkdir)(const unsigned int, struct cifs_tcon *, const char *, 322 int (*mkdir)(const unsigned int, struct cifs_tcon *, const char *,
319 struct cifs_sb_info *); 323 struct cifs_sb_info *);
320 /* set info on created directory */ 324 /* set info on created directory */
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index f4697f548a39..a2cfb33e85c1 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -1575,6 +1575,17 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
1575 goto mkdir_out; 1575 goto mkdir_out;
1576 } 1576 }
1577 1577
1578 server = tcon->ses->server;
1579
1580#ifdef CONFIG_CIFS_SMB311
1581 if ((server->ops->posix_mkdir) && (tcon->posix_extensions)) {
1582 rc = server->ops->posix_mkdir(xid, inode, mode, tcon, full_path,
1583 cifs_sb);
1584 d_drop(direntry); /* for time being always refresh inode info */
1585 goto mkdir_out;
1586 }
1587#endif /* SMB311 */
1588
1578 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP & 1589 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1579 le64_to_cpu(tcon->fsUnixInfo.Capability))) { 1590 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
1580 rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb, 1591 rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb,
@@ -1583,8 +1594,6 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
1583 goto mkdir_out; 1594 goto mkdir_out;
1584 } 1595 }
1585 1596
1586 server = tcon->ses->server;
1587
1588 if (!server->ops->mkdir) { 1597 if (!server->ops->mkdir) {
1589 rc = -ENOSYS; 1598 rc = -ENOSYS;
1590 goto mkdir_out; 1599 goto mkdir_out;
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index b2390e9a6843..badcfb2f3c22 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -3313,6 +3313,7 @@ struct smb_version_operations smb311_operations = {
3313 .set_compression = smb2_set_compression, 3313 .set_compression = smb2_set_compression,
3314 .mkdir = smb2_mkdir, 3314 .mkdir = smb2_mkdir,
3315 .mkdir_setinfo = smb2_mkdir_setinfo, 3315 .mkdir_setinfo = smb2_mkdir_setinfo,
3316 .posix_mkdir = smb311_posix_mkdir,
3316 .rmdir = smb2_rmdir, 3317 .rmdir = smb2_rmdir,
3317 .unlink = smb2_unlink, 3318 .unlink = smb2_unlink,
3318 .rename = smb2_rename_path, 3319 .rename = smb2_rename_path,
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 7daf38ab814a..810b85787c91 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -1911,6 +1911,159 @@ alloc_path_with_tree_prefix(__le16 **out_path, int *out_size, int *out_len,
1911 return 0; 1911 return 0;
1912} 1912}
1913 1913
1914#ifdef CONFIG_CIFS_SMB311
1915int smb311_posix_mkdir(const unsigned int xid, struct inode *inode,
1916 umode_t mode, struct cifs_tcon *tcon,
1917 const char *full_path,
1918 struct cifs_sb_info *cifs_sb)
1919{
1920 struct smb_rqst rqst;
1921 struct smb2_create_req *req;
1922 struct smb2_create_rsp *rsp;
1923 struct TCP_Server_Info *server;
1924 struct cifs_ses *ses = tcon->ses;
1925 struct kvec iov[3]; /* make sure at least one for each open context */
1926 struct kvec rsp_iov = {NULL, 0};
1927 int resp_buftype;
1928 int uni_path_len;
1929 __le16 *copy_path = NULL;
1930 int copy_size;
1931 int rc = 0;
1932 unsigned int n_iov = 2;
1933 __u32 file_attributes = 0;
1934 char *pc_buf = NULL;
1935 int flags = 0;
1936 unsigned int total_len;
1937 __le16 *path = cifs_convert_path_to_utf16(full_path, cifs_sb);
1938
1939 if (!path)
1940 return -ENOMEM;
1941
1942 cifs_dbg(FYI, "mkdir\n");
1943
1944 if (ses && (ses->server))
1945 server = ses->server;
1946 else
1947 return -EIO;
1948
1949 rc = smb2_plain_req_init(SMB2_CREATE, tcon, (void **) &req, &total_len);
1950
1951 if (rc)
1952 return rc;
1953
1954 if (smb3_encryption_required(tcon))
1955 flags |= CIFS_TRANSFORM_REQ;
1956
1957
1958 req->ImpersonationLevel = IL_IMPERSONATION;
1959 req->DesiredAccess = cpu_to_le32(FILE_WRITE_ATTRIBUTES);
1960 /* File attributes ignored on open (used in create though) */
1961 req->FileAttributes = cpu_to_le32(file_attributes);
1962 req->ShareAccess = FILE_SHARE_ALL_LE;
1963 req->CreateDisposition = cpu_to_le32(FILE_CREATE);
1964 req->CreateOptions = cpu_to_le32(CREATE_NOT_FILE);
1965
1966 iov[0].iov_base = (char *)req;
1967 /* -1 since last byte is buf[0] which is sent below (path) */
1968 iov[0].iov_len = total_len - 1;
1969
1970 req->NameOffset = cpu_to_le16(sizeof(struct smb2_create_req));
1971
1972 /* [MS-SMB2] 2.2.13 NameOffset:
1973 * If SMB2_FLAGS_DFS_OPERATIONS is set in the Flags field of
1974 * the SMB2 header, the file name includes a prefix that will
1975 * be processed during DFS name normalization as specified in
1976 * section 3.3.5.9. Otherwise, the file name is relative to
1977 * the share that is identified by the TreeId in the SMB2
1978 * header.
1979 */
1980 if (tcon->share_flags & SHI1005_FLAGS_DFS) {
1981 int name_len;
1982
1983 req->sync_hdr.Flags |= SMB2_FLAGS_DFS_OPERATIONS;
1984 rc = alloc_path_with_tree_prefix(&copy_path, &copy_size,
1985 &name_len,
1986 tcon->treeName, path);
1987 if (rc) {
1988 cifs_small_buf_release(req);
1989 return rc;
1990 }
1991 req->NameLength = cpu_to_le16(name_len * 2);
1992 uni_path_len = copy_size;
1993 path = copy_path;
1994 } else {
1995 uni_path_len = (2 * UniStrnlen((wchar_t *)path, PATH_MAX)) + 2;
1996 /* MUST set path len (NameLength) to 0 opening root of share */
1997 req->NameLength = cpu_to_le16(uni_path_len - 2);
1998 if (uni_path_len % 8 != 0) {
1999 copy_size = roundup(uni_path_len, 8);
2000 copy_path = kzalloc(copy_size, GFP_KERNEL);
2001 if (!copy_path) {
2002 cifs_small_buf_release(req);
2003 return -ENOMEM;
2004 }
2005 memcpy((char *)copy_path, (const char *)path,
2006 uni_path_len);
2007 uni_path_len = copy_size;
2008 path = copy_path;
2009 }
2010 }
2011
2012 iov[1].iov_len = uni_path_len;
2013 iov[1].iov_base = path;
2014 req->RequestedOplockLevel = SMB2_OPLOCK_LEVEL_NONE;
2015
2016 if (tcon->posix_extensions) {
2017 if (n_iov > 2) {
2018 struct create_context *ccontext =
2019 (struct create_context *)iov[n_iov-1].iov_base;
2020 ccontext->Next =
2021 cpu_to_le32(iov[n_iov-1].iov_len);
2022 }
2023
2024 rc = add_posix_context(iov, &n_iov, mode);
2025 if (rc) {
2026 cifs_small_buf_release(req);
2027 kfree(copy_path);
2028 return rc;
2029 }
2030 pc_buf = iov[n_iov-1].iov_base;
2031 }
2032
2033
2034 memset(&rqst, 0, sizeof(struct smb_rqst));
2035 rqst.rq_iov = iov;
2036 rqst.rq_nvec = n_iov;
2037
2038 rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags,
2039 &rsp_iov);
2040
2041 cifs_small_buf_release(req);
2042 rsp = (struct smb2_create_rsp *)rsp_iov.iov_base;
2043
2044 if (rc != 0) {
2045 cifs_stats_fail_inc(tcon, SMB2_CREATE_HE);
2046 trace_smb3_posix_mkdir_err(xid, tcon->tid, ses->Suid,
2047 CREATE_NOT_FILE, FILE_WRITE_ATTRIBUTES, rc);
2048 goto smb311_mkdir_exit;
2049 } else
2050 trace_smb3_posix_mkdir_done(xid, rsp->PersistentFileId, tcon->tid,
2051 ses->Suid, CREATE_NOT_FILE,
2052 FILE_WRITE_ATTRIBUTES);
2053
2054 SMB2_close(xid, tcon, rsp->PersistentFileId, rsp->VolatileFileId);
2055
2056 /* Eventually save off posix specific response info and timestaps */
2057
2058smb311_mkdir_exit:
2059 kfree(copy_path);
2060 kfree(pc_buf);
2061 free_rsp_buf(resp_buftype, rsp);
2062 return rc;
2063
2064}
2065#endif /* SMB311 */
2066
1914int 2067int
1915SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, 2068SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
1916 __u8 *oplock, struct smb2_file_all_info *buf, 2069 __u8 *oplock, struct smb2_file_all_info *buf,
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h
index c84020057bd8..78371c1a6503 100644
--- a/fs/cifs/smb2proto.h
+++ b/fs/cifs/smb2proto.h
@@ -79,6 +79,10 @@ extern int smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon,
79 struct cifs_sb_info *cifs_sb, bool set_alloc); 79 struct cifs_sb_info *cifs_sb, bool set_alloc);
80extern int smb2_set_file_info(struct inode *inode, const char *full_path, 80extern int smb2_set_file_info(struct inode *inode, const char *full_path,
81 FILE_BASIC_INFO *buf, const unsigned int xid); 81 FILE_BASIC_INFO *buf, const unsigned int xid);
82extern int smb311_posix_mkdir(const unsigned int xid, struct inode *inode,
83 umode_t mode, struct cifs_tcon *tcon,
84 const char *full_path,
85 struct cifs_sb_info *cifs_sb);
82extern int smb2_mkdir(const unsigned int xid, struct cifs_tcon *tcon, 86extern int smb2_mkdir(const unsigned int xid, struct cifs_tcon *tcon,
83 const char *name, struct cifs_sb_info *cifs_sb); 87 const char *name, struct cifs_sb_info *cifs_sb);
84extern void smb2_mkdir_setinfo(struct inode *inode, const char *full_path, 88extern void smb2_mkdir_setinfo(struct inode *inode, const char *full_path,
diff --git a/fs/cifs/trace.h b/fs/cifs/trace.h
index 61e74d455d90..67e413f6ee4d 100644
--- a/fs/cifs/trace.h
+++ b/fs/cifs/trace.h
@@ -378,7 +378,7 @@ DEFINE_EVENT(smb3_open_err_class, smb3_##name, \
378 TP_ARGS(xid, tid, sesid, create_options, desired_access, rc)) 378 TP_ARGS(xid, tid, sesid, create_options, desired_access, rc))
379 379
380DEFINE_SMB3_OPEN_ERR_EVENT(open_err); 380DEFINE_SMB3_OPEN_ERR_EVENT(open_err);
381 381DEFINE_SMB3_OPEN_ERR_EVENT(posix_mkdir_err);
382 382
383DECLARE_EVENT_CLASS(smb3_open_done_class, 383DECLARE_EVENT_CLASS(smb3_open_done_class,
384 TP_PROTO(unsigned int xid, 384 TP_PROTO(unsigned int xid,
@@ -420,6 +420,7 @@ DEFINE_EVENT(smb3_open_done_class, smb3_##name, \
420 TP_ARGS(xid, fid, tid, sesid, create_options, desired_access)) 420 TP_ARGS(xid, fid, tid, sesid, create_options, desired_access))
421 421
422DEFINE_SMB3_OPEN_DONE_EVENT(open_done); 422DEFINE_SMB3_OPEN_DONE_EVENT(open_done);
423DEFINE_SMB3_OPEN_DONE_EVENT(posix_mkdir_done);
423 424
424#endif /* _CIFS_TRACE_H */ 425#endif /* _CIFS_TRACE_H */
425 426