Skip to content

Commit 6d9b5f6

Browse files
committed
Merge tag 'v6.16-rc-part1-smb-client-fixes' of git://git.samba.org/sfrench/cifs-2.6
Pull smb client updates from Steve French: - multichannel fixes (mostly reconnect related), and clarification of locking documentation - automount null pointer check fix - fixes to add support for ParentLeaseKey - minor cleanup - smb1/cifs fixes * tag 'v6.16-rc-part1-smb-client-fixes' of git://git.samba.org/sfrench/cifs-2.6: cifs: update the lock ordering comments with new mutex cifs: dns resolution is needed only for primary channel cifs: update dstaddr whenever channel iface is updated cifs: reset connections for all channels when reconnect requested smb: client: use ParentLeaseKey in cifs_do_create smb: client: use ParentLeaseKey in open_cached_dir smb: client: add ParentLeaseKey support cifs: Fix cifs_query_path_info() for Windows NT servers cifs: Fix validation of SMB1 query reparse point response cifs: Correctly set SMB1 SessionKey field in Session Setup Request cifs: Fix encoding of SMB1 Session Setup NTLMSSP Request in non-UNICODE mode smb: client: add NULL check in automount_fullpath smb: client: Remove an unused function and variable
2 parents 3c72728 + 8a5ebd2 commit 6d9b5f6

File tree

13 files changed

+130
-97
lines changed

13 files changed

+130
-97
lines changed

fs/smb/client/cached_dir.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
155155
struct cached_fids *cfids;
156156
const char *npath;
157157
int retries = 0, cur_sleep = 1;
158+
__le32 lease_flags = 0;
158159

159160
if (cifs_sb->root == NULL)
160161
return -ENOENT;
@@ -201,6 +202,8 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
201202
}
202203
spin_unlock(&cfids->cfid_list_lock);
203204

205+
pfid = &cfid->fid;
206+
204207
/*
205208
* Skip any prefix paths in @path as lookup_noperm_positive_unlocked() ends up
206209
* calling ->lookup() which already adds those through
@@ -222,6 +225,25 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
222225
rc = -ENOENT;
223226
goto out;
224227
}
228+
if (dentry->d_parent && server->dialect >= SMB30_PROT_ID) {
229+
struct cached_fid *parent_cfid;
230+
231+
spin_lock(&cfids->cfid_list_lock);
232+
list_for_each_entry(parent_cfid, &cfids->entries, entry) {
233+
if (parent_cfid->dentry == dentry->d_parent) {
234+
cifs_dbg(FYI, "found a parent cached file handle\n");
235+
if (parent_cfid->has_lease && parent_cfid->time) {
236+
lease_flags
237+
|= SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE;
238+
memcpy(pfid->parent_lease_key,
239+
parent_cfid->fid.lease_key,
240+
SMB2_LEASE_KEY_SIZE);
241+
}
242+
break;
243+
}
244+
}
245+
spin_unlock(&cfids->cfid_list_lock);
246+
}
225247
}
226248
cfid->dentry = dentry;
227249
cfid->tcon = tcon;
@@ -236,7 +258,6 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
236258
if (smb3_encryption_required(tcon))
237259
flags |= CIFS_TRANSFORM_REQ;
238260

239-
pfid = &cfid->fid;
240261
server->ops->new_lease_key(pfid);
241262

242263
memset(rqst, 0, sizeof(rqst));
@@ -256,6 +277,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
256277
FILE_READ_EA,
257278
.disposition = FILE_OPEN,
258279
.fid = pfid,
280+
.lease_flags = lease_flags,
259281
.replay = !!(retries),
260282
};
261283

fs/smb/client/cifsfs.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ bool require_gcm_256; /* false by default */
7070
bool enable_negotiate_signing; /* false by default */
7171
unsigned int global_secflags = CIFSSEC_DEF;
7272
/* unsigned int ntlmv2_support = 0; */
73-
unsigned int sign_CIFS_PDUs = 1;
7473

7574
/*
7675
* Global transaction id (XID) information

fs/smb/client/cifsglob.h

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,7 @@ struct smb_version_operations {
556556
void (*set_oplock_level)(struct cifsInodeInfo *cinode, __u32 oplock, __u16 epoch,
557557
bool *purge_cache);
558558
/* create lease context buffer for CREATE request */
559-
char * (*create_lease_buf)(u8 *lease_key, u8 oplock);
559+
char * (*create_lease_buf)(u8 *lease_key, u8 oplock, u8 *parent_lease_key, __le32 le_flags);
560560
/* parse lease context buffer and return oplock/epoch info */
561561
__u8 (*parse_lease_buf)(void *buf, __u16 *epoch, char *lkey);
562562
ssize_t (*copychunk_range)(const unsigned int,
@@ -773,6 +773,7 @@ struct TCP_Server_Info {
773773
char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL];
774774
__u32 sequence_number; /* for signing, protected by srv_mutex */
775775
__u32 reconnect_instance; /* incremented on each reconnect */
776+
__le32 session_key_id; /* retrieved from negotiate response and send in session setup request */
776777
struct session_key session_key;
777778
unsigned long lstrp; /* when we got last response from this server */
778779
struct cifs_secmech secmech; /* crypto sec mech functs, descriptors */
@@ -1441,13 +1442,15 @@ struct cifs_open_parms {
14411442
bool reconnect:1;
14421443
bool replay:1; /* indicates that this open is for a replay */
14431444
struct kvec *ea_cctx;
1445+
__le32 lease_flags;
14441446
};
14451447

14461448
struct cifs_fid {
14471449
__u16 netfid;
14481450
__u64 persistent_fid; /* persist file id for smb2 */
14491451
__u64 volatile_fid; /* volatile file id for smb2 */
14501452
__u8 lease_key[SMB2_LEASE_KEY_SIZE]; /* lease key for smb2 */
1453+
__u8 parent_lease_key[SMB2_LEASE_KEY_SIZE];
14511454
__u8 create_guid[16];
14521455
__u32 access;
14531456
struct cifs_pending_open *pending_open;
@@ -1988,8 +1991,7 @@ require use of the stronger protocol */
19881991
* TCP_Server_Info-> TCP_Server_Info cifs_get_tcp_session
19891992
* reconnect_mutex
19901993
* TCP_Server_Info->srv_mutex TCP_Server_Info cifs_get_tcp_session
1991-
* cifs_ses->session_mutex cifs_ses sesInfoAlloc
1992-
* cifs_tcon
1994+
* cifs_ses->session_mutex cifs_ses sesInfoAlloc
19931995
* cifs_tcon->open_file_lock cifs_tcon->openFileList tconInfoAlloc
19941996
* cifs_tcon->pending_opens
19951997
* cifs_tcon->stat_lock cifs_tcon->bytes_read tconInfoAlloc
@@ -2008,21 +2010,25 @@ require use of the stronger protocol */
20082010
* ->oplock_credits
20092011
* ->reconnect_instance
20102012
* cifs_ses->ses_lock (anything that is not protected by another lock and can change)
2013+
* sesInfoAlloc
20112014
* cifs_ses->iface_lock cifs_ses->iface_list sesInfoAlloc
20122015
* ->iface_count
20132016
* ->iface_last_update
2014-
* cifs_ses->chan_lock cifs_ses->chans
2017+
* cifs_ses->chan_lock cifs_ses->chans sesInfoAlloc
20152018
* ->chans_need_reconnect
20162019
* ->chans_in_reconnect
20172020
* cifs_tcon->tc_lock (anything that is not protected by another lock and can change)
2021+
* tcon_info_alloc
20182022
* inode->i_rwsem, taken by fs/netfs/locking.c e.g. should be taken before cifsInodeInfo locks
20192023
* cifsInodeInfo->open_file_lock cifsInodeInfo->openFileList cifs_alloc_inode
20202024
* cifsInodeInfo->writers_lock cifsInodeInfo->writers cifsInodeInfo_alloc
20212025
* cifsInodeInfo->lock_sem cifsInodeInfo->llist cifs_init_once
20222026
* ->can_cache_brlcks
20232027
* cifsInodeInfo->deferred_lock cifsInodeInfo->deferred_closes cifsInodeInfo_alloc
2024-
* cached_fids->cfid_list_lock cifs_tcon->cfids->entries init_cached_dirs
2025-
* cifsFileInfo->fh_mutex cifsFileInfo cifs_new_fileinfo
2028+
* cached_fids->cfid_list_lock cifs_tcon->cfids->entries init_cached_dirs
2029+
* cached_fid->fid_lock (anything that is not protected by another lock and can change)
2030+
* init_cached_dir
2031+
* cifsFileInfo->fh_mutex cifsFileInfo cifs_new_fileinfo
20262032
* cifsFileInfo->file_info_lock cifsFileInfo->count cifs_new_fileinfo
20272033
* ->invalidHandle initiate_cifs_search
20282034
* ->oplock_break_cancelled

fs/smb/client/cifspdu.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -597,7 +597,7 @@ typedef union smb_com_session_setup_andx {
597597
__le16 MaxBufferSize;
598598
__le16 MaxMpxCount;
599599
__le16 VcNumber;
600-
__u32 SessionKey;
600+
__le32 SessionKey;
601601
__le16 SecurityBlobLength;
602602
__u32 Reserved;
603603
__le32 Capabilities; /* see below */
@@ -616,7 +616,7 @@ typedef union smb_com_session_setup_andx {
616616
__le16 MaxBufferSize;
617617
__le16 MaxMpxCount;
618618
__le16 VcNumber;
619-
__u32 SessionKey;
619+
__le32 SessionKey;
620620
__le16 CaseInsensitivePasswordLength; /* ASCII password len */
621621
__le16 CaseSensitivePasswordLength; /* Unicode password length*/
622622
__u32 Reserved; /* see below */
@@ -654,7 +654,7 @@ typedef union smb_com_session_setup_andx {
654654
__le16 MaxBufferSize;
655655
__le16 MaxMpxCount;
656656
__le16 VcNumber;
657-
__u32 SessionKey;
657+
__le32 SessionKey;
658658
__le16 PasswordLength;
659659
__u32 Reserved; /* encrypt key len and offset */
660660
__le16 ByteCount;

fs/smb/client/cifssmb.c

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,7 @@ CIFSSMBNegotiate(const unsigned int xid,
498498
server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
499499
cifs_dbg(NOISY, "Max buf = %d\n", ses->server->maxBuf);
500500
server->capabilities = le32_to_cpu(pSMBr->Capabilities);
501+
server->session_key_id = pSMBr->SessionKey;
501502
server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
502503
server->timeAdj *= 60;
503504

@@ -2753,10 +2754,10 @@ int cifs_query_reparse_point(const unsigned int xid,
27532754

27542755
io_req->TotalParameterCount = 0;
27552756
io_req->TotalDataCount = 0;
2756-
io_req->MaxParameterCount = cpu_to_le32(2);
2757+
io_req->MaxParameterCount = cpu_to_le32(0);
27572758
/* BB find exact data count max from sess structure BB */
27582759
io_req->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
2759-
io_req->MaxSetupCount = 4;
2760+
io_req->MaxSetupCount = 1;
27602761
io_req->Reserved = 0;
27612762
io_req->ParameterOffset = 0;
27622763
io_req->DataCount = 0;
@@ -2783,6 +2784,22 @@ int cifs_query_reparse_point(const unsigned int xid,
27832784
goto error;
27842785
}
27852786

2787+
/* SetupCount must be 1, otherwise offset to ByteCount is incorrect. */
2788+
if (io_rsp->SetupCount != 1) {
2789+
rc = -EIO;
2790+
goto error;
2791+
}
2792+
2793+
/*
2794+
* ReturnedDataLen is output length of executed IOCTL.
2795+
* DataCount is output length transferred over network.
2796+
* Check that we have full FSCTL_GET_REPARSE_POINT buffer.
2797+
*/
2798+
if (data_count != le16_to_cpu(io_rsp->ReturnedDataLen)) {
2799+
rc = -EIO;
2800+
goto error;
2801+
}
2802+
27862803
end = 2 + get_bcc(&io_rsp->hdr) + (__u8 *)&io_rsp->ByteCount;
27872804
start = (__u8 *)&io_rsp->hdr.Protocol + data_offset;
27882805
if (start >= end) {

fs/smb/client/connect.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,13 @@ static int __cifs_reconnect(struct TCP_Server_Info *server,
377377
if (!cifs_tcp_ses_needs_reconnect(server, 1))
378378
return 0;
379379

380+
/*
381+
* if smb session has been marked for reconnect, also reconnect all
382+
* connections. This way, the other connections do not end up bad.
383+
*/
384+
if (mark_smb_session)
385+
cifs_signal_cifsd_for_reconnect(server, mark_smb_session);
386+
380387
cifs_mark_tcp_ses_conns_for_reconnect(server, mark_smb_session);
381388

382389
cifs_abort_connection(server);
@@ -385,7 +392,8 @@ static int __cifs_reconnect(struct TCP_Server_Info *server,
385392
try_to_freeze();
386393
cifs_server_lock(server);
387394

388-
if (!cifs_swn_set_server_dstaddr(server)) {
395+
if (!cifs_swn_set_server_dstaddr(server) &&
396+
!SERVER_IS_CHAN(server)) {
389397
/* resolve the hostname again to make sure that IP address is up-to-date */
390398
rc = reconn_set_ipaddr_from_hostname(server);
391399
cifs_dbg(FYI, "%s: reconn_set_ipaddr_from_hostname: rc=%d\n", __func__, rc);

fs/smb/client/dir.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "fs_context.h"
2424
#include "cifs_ioctl.h"
2525
#include "fscache.h"
26+
#include "cached_dir.h"
2627

2728
static void
2829
renew_parental_timestamps(struct dentry *direntry)
@@ -190,6 +191,7 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned
190191
struct TCP_Server_Info *server = tcon->ses->server;
191192
struct cifs_open_parms oparms;
192193
int rdwr_for_fscache = 0;
194+
__le32 lease_flags = 0;
193195

194196
*oplock = 0;
195197
if (tcon->ses->server->oplocks)
@@ -312,6 +314,26 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned
312314
create_options |= CREATE_OPTION_READONLY;
313315

314316
retry_open:
317+
if (tcon->cfids && direntry->d_parent && server->dialect >= SMB30_PROT_ID) {
318+
struct cached_fid *parent_cfid;
319+
320+
spin_lock(&tcon->cfids->cfid_list_lock);
321+
list_for_each_entry(parent_cfid, &tcon->cfids->entries, entry) {
322+
if (parent_cfid->dentry == direntry->d_parent) {
323+
cifs_dbg(FYI, "found a parent cached file handle\n");
324+
if (parent_cfid->has_lease && parent_cfid->time) {
325+
lease_flags
326+
|= SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE;
327+
memcpy(fid->parent_lease_key,
328+
parent_cfid->fid.lease_key,
329+
SMB2_LEASE_KEY_SIZE);
330+
}
331+
break;
332+
}
333+
}
334+
spin_unlock(&tcon->cfids->cfid_list_lock);
335+
}
336+
315337
oparms = (struct cifs_open_parms) {
316338
.tcon = tcon,
317339
.cifs_sb = cifs_sb,
@@ -320,6 +342,7 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned
320342
.disposition = disposition,
321343
.path = full_path,
322344
.fid = fid,
345+
.lease_flags = lease_flags,
323346
.mode = mode,
324347
};
325348
rc = server->ops->open(xid, &oparms, oplock, buf);

fs/smb/client/misc.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,14 @@ check_smb_hdr(struct smb_hdr *smb)
326326
if (smb->Command == SMB_COM_LOCKING_ANDX)
327327
return 0;
328328

329+
/*
330+
* Windows NT server returns error resposne (e.g. STATUS_DELETE_PENDING
331+
* or STATUS_OBJECT_NAME_NOT_FOUND or ERRDOS/ERRbadfile or any other)
332+
* for some TRANS2 requests without the RESPONSE flag set in header.
333+
*/
334+
if (smb->Command == SMB_COM_TRANSACTION2 && smb->Status.CifsError != 0)
335+
return 0;
336+
329337
cifs_dbg(VFS, "Server sent request, not response. mid=%u\n",
330338
get_mid(smb));
331339
return 1;

fs/smb/client/namespace.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,9 @@ static char *automount_fullpath(struct dentry *dentry, void *page)
146146
}
147147
spin_unlock(&tcon->tc_lock);
148148

149+
if (unlikely(!page))
150+
return ERR_PTR(-ENOMEM);
151+
149152
s = dentry_path_raw(dentry, page, PATH_MAX);
150153
if (IS_ERR(s))
151154
return s;

fs/smb/client/sess.c

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,10 @@ cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server)
445445

446446
ses->chans[chan_index].iface = iface;
447447
spin_unlock(&ses->chan_lock);
448+
449+
spin_lock(&server->srv_lock);
450+
memcpy(&server->dstaddr, &iface->sockaddr, sizeof(server->dstaddr));
451+
spin_unlock(&server->srv_lock);
448452
}
449453

450454
static int
@@ -628,6 +632,7 @@ static __u32 cifs_ssetup_hdr(struct cifs_ses *ses,
628632
USHRT_MAX));
629633
pSMB->req.MaxMpxCount = cpu_to_le16(server->maxReq);
630634
pSMB->req.VcNumber = cpu_to_le16(1);
635+
pSMB->req.SessionKey = server->session_key_id;
631636

632637
/* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */
633638

@@ -1684,22 +1689,22 @@ _sess_auth_rawntlmssp_assemble_req(struct sess_data *sess_data)
16841689
pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
16851690

16861691
capabilities = cifs_ssetup_hdr(ses, server, pSMB);
1687-
if ((pSMB->req.hdr.Flags2 & SMBFLG2_UNICODE) == 0) {
1688-
cifs_dbg(VFS, "NTLMSSP requires Unicode support\n");
1689-
return -ENOSYS;
1690-
}
1691-
16921692
pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
16931693
capabilities |= CAP_EXTENDED_SECURITY;
16941694
pSMB->req.Capabilities |= cpu_to_le32(capabilities);
16951695

16961696
bcc_ptr = sess_data->iov[2].iov_base;
1697-
/* unicode strings must be word aligned */
1698-
if (!IS_ALIGNED(sess_data->iov[0].iov_len + sess_data->iov[1].iov_len, 2)) {
1699-
*bcc_ptr = 0;
1700-
bcc_ptr++;
1697+
1698+
if (pSMB->req.hdr.Flags2 & SMBFLG2_UNICODE) {
1699+
/* unicode strings must be word aligned */
1700+
if (!IS_ALIGNED(sess_data->iov[0].iov_len + sess_data->iov[1].iov_len, 2)) {
1701+
*bcc_ptr = 0;
1702+
bcc_ptr++;
1703+
}
1704+
unicode_oslm_strings(&bcc_ptr, sess_data->nls_cp);
1705+
} else {
1706+
ascii_oslm_strings(&bcc_ptr, sess_data->nls_cp);
17011707
}
1702-
unicode_oslm_strings(&bcc_ptr, sess_data->nls_cp);
17031708

17041709
sess_data->iov[2].iov_len = (long) bcc_ptr -
17051710
(long) sess_data->iov[2].iov_base;

0 commit comments

Comments
 (0)