Skip to content

Commit ce558b0

Browse files
committed
smb3: Add posix create context for smb3.11 posix mounts
Signed-off-by: Steve French <smfrench@gmail.com>
1 parent 28d5936 commit ce558b0

File tree

5 files changed

+101
-3
lines changed

5 files changed

+101
-3
lines changed

fs/cifs/cifsglob.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,6 +1082,7 @@ struct cifs_open_parms {
10821082
int create_options;
10831083
const char *path;
10841084
struct cifs_fid *fid;
1085+
umode_t mode;
10851086
bool reconnect:1;
10861087
};
10871088

fs/cifs/connect.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3963,6 +3963,12 @@ cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
39633963
goto remote_path_check;
39643964
}
39653965

3966+
#ifdef CONFIG_CIFS_SMB311
3967+
/* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
3968+
if (tcon->posix_extensions)
3969+
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
3970+
#endif /* SMB3.11 */
3971+
39663972
/* tell server which Unix caps we support */
39673973
if (cap_unix(tcon->ses)) {
39683974
/* reset of caps checks mount to see if unix extensions
@@ -4424,6 +4430,11 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
44244430
goto out;
44254431
}
44264432

4433+
#ifdef CONFIG_CIFS_SMB311
4434+
/* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
4435+
if (tcon->posix_extensions)
4436+
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
4437+
#endif /* SMB3.11 */
44274438
if (cap_unix(ses))
44284439
reset_cifs_unix_caps(0, tcon, NULL, vol_info);
44294440

fs/cifs/dir.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
369369
oparms.path = full_path;
370370
oparms.fid = fid;
371371
oparms.reconnect = false;
372-
372+
oparms.mode = mode;
373373
rc = server->ops->open(xid, &oparms, oplock, buf);
374374
if (rc) {
375375
cifs_dbg(FYI, "cifs_create returned 0x%x\n", rc);

fs/cifs/smb2misc.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,8 +455,14 @@ cifs_convert_path_to_utf16(const char *from, struct cifs_sb_info *cifs_sb)
455455
/* Windows doesn't allow paths beginning with \ */
456456
if (from[0] == '\\')
457457
start_of_path = from + 1;
458+
#ifdef CONFIG_CIFS_SMB311
459+
/* SMB311 POSIX extensions paths do not include leading slash */
460+
else if (cifs_sb_master_tcon(cifs_sb)->posix_extensions)
461+
start_of_path = from + 1;
462+
#endif /* 311 */
458463
else
459464
start_of_path = from;
465+
460466
to = cifs_strndup_to_utf16(start_of_path, PATH_MAX, &len,
461467
cifs_sb->local_nls, map_type);
462468
return to;

fs/cifs/smb2pdu.c

Lines changed: 82 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,64 @@ static int smb311_decode_neg_context(struct smb2_negotiate_rsp *rsp,
519519
return rc;
520520
}
521521

522+
static struct create_posix *
523+
create_posix_buf(umode_t mode)
524+
{
525+
struct create_posix *buf;
526+
527+
buf = kzalloc(sizeof(struct create_posix),
528+
GFP_KERNEL);
529+
if (!buf)
530+
return NULL;
531+
532+
buf->ccontext.DataOffset =
533+
cpu_to_le16(offsetof(struct create_posix, Mode));
534+
buf->ccontext.DataLength = cpu_to_le32(4);
535+
buf->ccontext.NameOffset =
536+
cpu_to_le16(offsetof(struct create_posix, Name));
537+
buf->ccontext.NameLength = cpu_to_le16(16);
538+
539+
/* SMB2_CREATE_TAG_POSIX is "0x93AD25509CB411E7B42383DE968BCD7C" */
540+
buf->Name[0] = 0x93;
541+
buf->Name[1] = 0xAD;
542+
buf->Name[2] = 0x25;
543+
buf->Name[3] = 0x50;
544+
buf->Name[4] = 0x9C;
545+
buf->Name[5] = 0xB4;
546+
buf->Name[6] = 0x11;
547+
buf->Name[7] = 0xE7;
548+
buf->Name[8] = 0xB4;
549+
buf->Name[9] = 0x23;
550+
buf->Name[10] = 0x83;
551+
buf->Name[11] = 0xDE;
552+
buf->Name[12] = 0x96;
553+
buf->Name[13] = 0x8B;
554+
buf->Name[14] = 0xCD;
555+
buf->Name[15] = 0x7C;
556+
buf->Mode = cpu_to_le32(mode);
557+
cifs_dbg(FYI, "mode on posix create 0%o", mode);
558+
return buf;
559+
}
560+
561+
static int
562+
add_posix_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode)
563+
{
564+
struct smb2_create_req *req = iov[0].iov_base;
565+
unsigned int num = *num_iovec;
566+
567+
iov[num].iov_base = create_posix_buf(mode);
568+
if (iov[num].iov_base == NULL)
569+
return -ENOMEM;
570+
iov[num].iov_len = sizeof(struct create_posix);
571+
if (!req->CreateContextsOffset)
572+
req->CreateContextsOffset = cpu_to_le32(
573+
sizeof(struct smb2_create_req) +
574+
iov[num - 1].iov_len);
575+
le32_add_cpu(&req->CreateContextsLength, sizeof(struct create_posix));
576+
*num_iovec = num + 1;
577+
return 0;
578+
}
579+
522580
#else
523581
static void assemble_neg_contexts(struct smb2_negotiate_req *req,
524582
unsigned int *total_len)
@@ -1837,7 +1895,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
18371895
struct TCP_Server_Info *server;
18381896
struct cifs_tcon *tcon = oparms->tcon;
18391897
struct cifs_ses *ses = tcon->ses;
1840-
struct kvec iov[4];
1898+
struct kvec iov[5]; /* make sure at least one for each open context */
18411899
struct kvec rsp_iov = {NULL, 0};
18421900
int resp_buftype;
18431901
int uni_path_len;
@@ -1846,7 +1904,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
18461904
int rc = 0;
18471905
unsigned int n_iov = 2;
18481906
__u32 file_attributes = 0;
1849-
char *dhc_buf = NULL, *lc_buf = NULL;
1907+
char *dhc_buf = NULL, *lc_buf = NULL, *pc_buf = NULL;
18501908
int flags = 0;
18511909
unsigned int total_len;
18521910

@@ -1963,6 +2021,27 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
19632021
dhc_buf = iov[n_iov-1].iov_base;
19642022
}
19652023

2024+
#ifdef CONFIG_CIFS_SMB311
2025+
if (tcon->posix_extensions) {
2026+
if (n_iov > 2) {
2027+
struct create_context *ccontext =
2028+
(struct create_context *)iov[n_iov-1].iov_base;
2029+
ccontext->Next =
2030+
cpu_to_le32(iov[n_iov-1].iov_len);
2031+
}
2032+
2033+
rc = add_posix_context(iov, &n_iov, oparms->mode);
2034+
if (rc) {
2035+
cifs_small_buf_release(req);
2036+
kfree(copy_path);
2037+
kfree(lc_buf);
2038+
kfree(dhc_buf);
2039+
return rc;
2040+
}
2041+
pc_buf = iov[n_iov-1].iov_base;
2042+
}
2043+
#endif /* SMB311 */
2044+
19662045
rc = smb2_send_recv(xid, ses, iov, n_iov, &resp_buftype, flags,
19672046
&rsp_iov);
19682047
cifs_small_buf_release(req);
@@ -2004,6 +2083,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
20042083
kfree(copy_path);
20052084
kfree(lc_buf);
20062085
kfree(dhc_buf);
2086+
kfree(pc_buf);
20072087
free_rsp_buf(resp_buftype, rsp);
20082088
return rc;
20092089
}

0 commit comments

Comments
 (0)