Skip to content

Commit 55f626f

Browse files
committed
Merge tag '6.8-rc4-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6
Pull smb client fixes from Steve French: "Five smb3 client fixes, most also for stable: - Two multichannel fixes (one to fix potential handle leak on retry) - Work around possible serious data corruption (due to change in folios in 6.3, for cases when non standard maximum write size negotiated) - Symlink creation fix - Multiuser automount fix" * tag '6.8-rc4-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6: smb: Fix regression in writes when non-standard maximum write size negotiated smb: client: handle path separator of created SMB symlinks smb: client: set correct id, uid and cruid for multiuser automounts cifs: update the same create_guid on replay cifs: fix underflow in parse_server_interfaces()
2 parents c1ca10c + 4860abb commit 55f626f

File tree

7 files changed

+60
-7
lines changed

7 files changed

+60
-7
lines changed

fs/smb/client/cached_dir.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
242242
.desired_access = FILE_READ_DATA | FILE_READ_ATTRIBUTES,
243243
.disposition = FILE_OPEN,
244244
.fid = pfid,
245+
.replay = !!(retries),
245246
};
246247

247248
rc = SMB2_open_init(tcon, server,

fs/smb/client/cifsglob.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1378,6 +1378,7 @@ struct cifs_open_parms {
13781378
struct cifs_fid *fid;
13791379
umode_t mode;
13801380
bool reconnect:1;
1381+
bool replay:1; /* indicates that this open is for a replay */
13811382
};
13821383

13831384
struct cifs_fid {

fs/smb/client/connect.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3444,8 +3444,18 @@ int cifs_mount_get_tcon(struct cifs_mount_ctx *mnt_ctx)
34443444
* the user on mount
34453445
*/
34463446
if ((cifs_sb->ctx->wsize == 0) ||
3447-
(cifs_sb->ctx->wsize > server->ops->negotiate_wsize(tcon, ctx)))
3448-
cifs_sb->ctx->wsize = server->ops->negotiate_wsize(tcon, ctx);
3447+
(cifs_sb->ctx->wsize > server->ops->negotiate_wsize(tcon, ctx))) {
3448+
cifs_sb->ctx->wsize =
3449+
round_down(server->ops->negotiate_wsize(tcon, ctx), PAGE_SIZE);
3450+
/*
3451+
* in the very unlikely event that the server sent a max write size under PAGE_SIZE,
3452+
* (which would get rounded down to 0) then reset wsize to absolute minimum eg 4096
3453+
*/
3454+
if (cifs_sb->ctx->wsize == 0) {
3455+
cifs_sb->ctx->wsize = PAGE_SIZE;
3456+
cifs_dbg(VFS, "wsize too small, reset to minimum ie PAGE_SIZE, usually 4096\n");
3457+
}
3458+
}
34493459
if ((cifs_sb->ctx->rsize == 0) ||
34503460
(cifs_sb->ctx->rsize > server->ops->negotiate_rsize(tcon, ctx)))
34513461
cifs_sb->ctx->rsize = server->ops->negotiate_rsize(tcon, ctx);

fs/smb/client/fs_context.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1111,6 +1111,17 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
11111111
case Opt_wsize:
11121112
ctx->wsize = result.uint_32;
11131113
ctx->got_wsize = true;
1114+
if (ctx->wsize % PAGE_SIZE != 0) {
1115+
ctx->wsize = round_down(ctx->wsize, PAGE_SIZE);
1116+
if (ctx->wsize == 0) {
1117+
ctx->wsize = PAGE_SIZE;
1118+
cifs_dbg(VFS, "wsize too small, reset to minimum %ld\n", PAGE_SIZE);
1119+
} else {
1120+
cifs_dbg(VFS,
1121+
"wsize rounded down to %d to multiple of PAGE_SIZE %ld\n",
1122+
ctx->wsize, PAGE_SIZE);
1123+
}
1124+
}
11141125
break;
11151126
case Opt_acregmax:
11161127
ctx->acregmax = HZ * result.uint_32;

fs/smb/client/namespace.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,21 @@ static char *automount_fullpath(struct dentry *dentry, void *page)
168168
return s;
169169
}
170170

171+
static void fs_context_set_ids(struct smb3_fs_context *ctx)
172+
{
173+
kuid_t uid = current_fsuid();
174+
kgid_t gid = current_fsgid();
175+
176+
if (ctx->multiuser) {
177+
if (!ctx->uid_specified)
178+
ctx->linux_uid = uid;
179+
if (!ctx->gid_specified)
180+
ctx->linux_gid = gid;
181+
}
182+
if (!ctx->cruid_specified)
183+
ctx->cred_uid = uid;
184+
}
185+
171186
/*
172187
* Create a vfsmount that we can automount
173188
*/
@@ -205,6 +220,7 @@ static struct vfsmount *cifs_do_automount(struct path *path)
205220
tmp.leaf_fullpath = NULL;
206221
tmp.UNC = tmp.prepath = NULL;
207222
tmp.dfs_root_ses = NULL;
223+
fs_context_set_ids(&tmp);
208224

209225
rc = smb3_fs_context_dup(ctx, &tmp);
210226
if (rc) {

fs/smb/client/smb2ops.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -619,7 +619,7 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
619619
goto out;
620620
}
621621

622-
while (bytes_left >= sizeof(*p)) {
622+
while (bytes_left >= (ssize_t)sizeof(*p)) {
623623
memset(&tmp_iface, 0, sizeof(tmp_iface));
624624
tmp_iface.speed = le64_to_cpu(p->LinkSpeed);
625625
tmp_iface.rdma_capable = le32_to_cpu(p->Capability & RDMA_CAPABLE) ? 1 : 0;
@@ -1204,6 +1204,7 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
12041204
.disposition = FILE_OPEN,
12051205
.create_options = cifs_create_options(cifs_sb, 0),
12061206
.fid = &fid,
1207+
.replay = !!(retries),
12071208
};
12081209

12091210
rc = SMB2_open_init(tcon, server,
@@ -1569,6 +1570,7 @@ smb2_ioctl_query_info(const unsigned int xid,
15691570
.disposition = FILE_OPEN,
15701571
.create_options = cifs_create_options(cifs_sb, create_options),
15711572
.fid = &fid,
1573+
.replay = !!(retries),
15721574
};
15731575

15741576
if (qi.flags & PASSTHRU_FSCTL) {
@@ -2295,6 +2297,7 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
22952297
.disposition = FILE_OPEN,
22962298
.create_options = cifs_create_options(cifs_sb, 0),
22972299
.fid = fid,
2300+
.replay = !!(retries),
22982301
};
22992302

23002303
rc = SMB2_open_init(tcon, server,
@@ -2681,6 +2684,7 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon,
26812684
.disposition = FILE_OPEN,
26822685
.create_options = cifs_create_options(cifs_sb, 0),
26832686
.fid = &fid,
2687+
.replay = !!(retries),
26842688
};
26852689

26862690
rc = SMB2_open_init(tcon, server,
@@ -5213,7 +5217,7 @@ static int smb2_create_reparse_symlink(const unsigned int xid,
52135217
struct inode *new;
52145218
struct kvec iov;
52155219
__le16 *path;
5216-
char *sym;
5220+
char *sym, sep = CIFS_DIR_SEP(cifs_sb);
52175221
u16 len, plen;
52185222
int rc = 0;
52195223

@@ -5227,7 +5231,8 @@ static int smb2_create_reparse_symlink(const unsigned int xid,
52275231
.symlink_target = sym,
52285232
};
52295233

5230-
path = cifs_convert_path_to_utf16(symname, cifs_sb);
5234+
convert_delimiter(sym, sep);
5235+
path = cifs_convert_path_to_utf16(sym, cifs_sb);
52315236
if (!path) {
52325237
rc = -ENOMEM;
52335238
goto out;
@@ -5250,7 +5255,10 @@ static int smb2_create_reparse_symlink(const unsigned int xid,
52505255
buf->PrintNameLength = cpu_to_le16(plen);
52515256
memcpy(buf->PathBuffer, path, plen);
52525257
buf->Flags = cpu_to_le32(*symname != '/' ? SYMLINK_FLAG_RELATIVE : 0);
5258+
if (*sym != sep)
5259+
buf->Flags = cpu_to_le32(SYMLINK_FLAG_RELATIVE);
52535260

5261+
convert_delimiter(sym, '/');
52545262
iov.iov_base = buf;
52555263
iov.iov_len = len;
52565264
new = smb2_get_reparse_inode(&data, inode->i_sb, xid,

fs/smb/client/smb2pdu.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2404,8 +2404,13 @@ create_durable_v2_buf(struct cifs_open_parms *oparms)
24042404
*/
24052405
buf->dcontext.Timeout = cpu_to_le32(oparms->tcon->handle_timeout);
24062406
buf->dcontext.Flags = cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT);
2407-
generate_random_uuid(buf->dcontext.CreateGuid);
2408-
memcpy(pfid->create_guid, buf->dcontext.CreateGuid, 16);
2407+
2408+
/* for replay, we should not overwrite the existing create guid */
2409+
if (!oparms->replay) {
2410+
generate_random_uuid(buf->dcontext.CreateGuid);
2411+
memcpy(pfid->create_guid, buf->dcontext.CreateGuid, 16);
2412+
} else
2413+
memcpy(buf->dcontext.CreateGuid, pfid->create_guid, 16);
24092414

24102415
/* SMB2_CREATE_DURABLE_HANDLE_REQUEST is "DH2Q" */
24112416
buf->Name[0] = 'D';
@@ -3142,6 +3147,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
31423147
/* reinitialize for possible replay */
31433148
flags = 0;
31443149
server = cifs_pick_channel(ses);
3150+
oparms->replay = !!(retries);
31453151

31463152
cifs_dbg(FYI, "create/open\n");
31473153
if (!ses || !server)

0 commit comments

Comments
 (0)