History

Merge tag '6.17-rc1-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull smb client fixes from Steve French: - Fix unlink race and rename races - SMB3.1.1 compression fix - Avoid unneeded strlen calls in cifs_get_spnego_key - Fix slab out of bounds in parse_server_interfaces() - Fix mid leak and server buffer leak - smbdirect send error path fix - update internal version # - Fix unneeded response time update in negotiate protocol * tag '6.17-rc1-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6: smb: client: remove redundant lstrp update in negotiate protocol cifs: update internal version number smb: client: don't wait for info->send_pending == 0 on error smb: client: fix mid_q_entry memleak leak with per-mid locking smb3: fix for slab out of bounds on mount to ksmbd cifs: avoid extra calls to strlen() in cifs_get_spnego_key() cifs: Fix collect_sample() to handle any iterator type smb: client: fix race with concurrent opens in rename(2) smb: client: fix race with concurrent opens in unlink(2)

Linus Torvalds committed 1 year ago

Commit 55ddcff2 parents d7ee5bd e19d8dd11 files · +128 −110Browse files

Unified · Split

11 files
  1. fs/smb/client/cifs_spnego.c +18 −29
  2. fs/smb/client/cifsfs.h +2 −2
  3. fs/smb/client/cifsglob.h +21 −0
  4. fs/smb/client/cifstransport.c +9 −10
  5. fs/smb/client/compress.c +21 −50
  6. fs/smb/client/connect.c +4 −5
  7. fs/smb/client/inode.c +32 −2
  8. fs/smb/client/smb2ops.c +12 −3
  9. fs/smb/client/smb2transport.c +1 −0
  10. fs/smb/client/smbdirect.c +5 −5
  11. fs/smb/client/transport.c +3 −4
fs/smb/client/cifs_spnego.c+18−29
@@ -124,55 +124,44 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo, · 123 unmodified lines
124 dp = description;124 dp = description;
125 /* start with version and hostname portion of UNC string */125 /* start with version and hostname portion of UNC string */
126 spnego_key = ERR_PTR(-EINVAL);126 spnego_key = ERR_PTR(-EINVAL);
127 sprintf(dp, "ver=0x%x;host=%s;", CIFS_SPNEGO_UPCALL_VERSION,127 dp += sprintf(dp, "ver=0x%x;host=%s;", CIFS_SPNEGO_UPCALL_VERSION,
128 hostname);128 hostname);
129 dp = description + strlen(description);
130 129
131 /* add the server address */130 /* add the server address */
132 if (server->dstaddr.ss_family == AF_INET)131 if (server->dstaddr.ss_family == AF_INET)
133 sprintf(dp, "ip4=%pI4", &sa->sin_addr);132 dp += sprintf(dp, "ip4=%pI4", &sa->sin_addr);
134 else if (server->dstaddr.ss_family == AF_INET6)133 else if (server->dstaddr.ss_family == AF_INET6)
135 sprintf(dp, "ip6=%pI6", &sa6->sin6_addr);134 dp += sprintf(dp, "ip6=%pI6", &sa6->sin6_addr);
136 else135 else
137 goto out;136 goto out;
138 137
139 dp = description + strlen(description);
140
141 /* for now, only sec=krb5 and sec=mskrb5 and iakerb are valid */138 /* for now, only sec=krb5 and sec=mskrb5 and iakerb are valid */
142 if (server->sec_kerberos)139 if (server->sec_kerberos)
143 sprintf(dp, ";sec=krb5");140 dp += sprintf(dp, ";sec=krb5");
144 else if (server->sec_mskerberos)141 else if (server->sec_mskerberos)
145 sprintf(dp, ";sec=mskrb5");142 dp += sprintf(dp, ";sec=mskrb5");
146 else if (server->sec_iakerb)143 else if (server->sec_iakerb)
147 sprintf(dp, ";sec=iakerb");144 dp += sprintf(dp, ";sec=iakerb");
148 else {145 else {
149 cifs_dbg(VFS, "unknown or missing server auth type, use krb5\n");146 cifs_dbg(VFS, "unknown or missing server auth type, use krb5\n");
150 sprintf(dp, ";sec=krb5");147 dp += sprintf(dp, ";sec=krb5");
151 }148 }
152 149
153 dp = description + strlen(description);150 dp += sprintf(dp, ";uid=0x%x",
154 sprintf(dp, ";uid=0x%x",151 from_kuid_munged(&init_user_ns, sesInfo->linux_uid));
155 from_kuid_munged(&init_user_ns, sesInfo->linux_uid));
156 152
157 dp = description + strlen(description);153 dp += sprintf(dp, ";creduid=0x%x",
158 sprintf(dp, ";creduid=0x%x",
159 from_kuid_munged(&init_user_ns, sesInfo->cred_uid));154 from_kuid_munged(&init_user_ns, sesInfo->cred_uid));
160 155
161 if (sesInfo->user_name) {156 if (sesInfo->user_name)
162 dp = description + strlen(description);157 dp += sprintf(dp, ";user=%s", sesInfo->user_name);
163 sprintf(dp, ";user=%s", sesInfo->user_name);
164 }
165 158
166 dp = description + strlen(description);159 dp += sprintf(dp, ";pid=0x%x", current->pid);
167 sprintf(dp, ";pid=0x%x", current->pid);
168 160
169 if (sesInfo->upcall_target == UPTARGET_MOUNT) {161 if (sesInfo->upcall_target == UPTARGET_MOUNT)
170 dp = description + strlen(description);162 dp += sprintf(dp, ";upcall_target=mount");
171 sprintf(dp, ";upcall_target=mount");163 else
172 } else {164 dp += sprintf(dp, ";upcall_target=app");
173 dp = description + strlen(description);
174 sprintf(dp, ";upcall_target=app");
175 }
176 165
177 cifs_dbg(FYI, "key description = %s\n", description);166 cifs_dbg(FYI, "key description = %s\n", description);
178 saved_cred = override_creds(spnego_cred);167 saved_cred = override_creds(spnego_cred);
fs/smb/client/cifsfs.h+2−2
@@ -145,6 +145,6 @@ extern const struct export_operations cifs_export_ops; · 144 unmodified lines
145#endif /* CONFIG_CIFS_NFSD_EXPORT */145#endif /* CONFIG_CIFS_NFSD_EXPORT */
146 146
147/* when changing internal version - update following two lines at same time */147/* when changing internal version - update following two lines at same time */
148#define SMB3_PRODUCT_BUILD 55148#define SMB3_PRODUCT_BUILD 56
149#define CIFS_VERSION "2.55"149#define CIFS_VERSION "2.56"
150#endif /* _CIFSFS_H */150#endif /* _CIFSFS_H */
fs/smb/client/cifsglob.h+21−0
@@ -1732,6 +1732,7 @@ struct mid_q_entry { · 1731 unmodified lines
1732 int mid_rc; /* rc for MID_RC */1732 int mid_rc; /* rc for MID_RC */
1733 __le16 command; /* smb command code */1733 __le16 command; /* smb command code */
1734 unsigned int optype; /* operation type */1734 unsigned int optype; /* operation type */
1735 spinlock_t mid_lock;
1735 bool wait_cancelled:1; /* Cancelled while waiting for response */1736 bool wait_cancelled:1; /* Cancelled while waiting for response */
1736 bool deleted_from_q:1; /* Whether Mid has been dequeued frem pending_mid_q */1737 bool deleted_from_q:1; /* Whether Mid has been dequeued frem pending_mid_q */
1737 bool large_buf:1; /* if valid response, is pointer to large buf */1738 bool large_buf:1; /* if valid response, is pointer to large buf */
@@ -2036,6 +2037,9 @@ require use of the stronger protocol */ · 298 unmodified lines
2036 * cifsFileInfo->file_info_lock cifsFileInfo->count cifs_new_fileinfo2037 * cifsFileInfo->file_info_lock cifsFileInfo->count cifs_new_fileinfo
2037 * ->invalidHandle initiate_cifs_search2038 * ->invalidHandle initiate_cifs_search
2038 * ->oplock_break_cancelled2039 * ->oplock_break_cancelled
2040 * mid_q_entry->mid_lock mid_q_entry->callback alloc_mid
2041 * smb2_mid_entry_alloc
2042 * (Any fields of mid_q_entry that will need protection)
2039 ****************************************************************************/2043 ****************************************************************************/
2040 2044
2041#ifdef DECLARE_GLOBALS_HERE2045#ifdef DECLARE_GLOBALS_HERE
@@ -2375,6 +2379,23 @@ static inline bool cifs_netbios_name(const char *name, size_t namelen) · 333 unmodified lines
2375 return ret;2379 return ret;
2376}2380}
2377 2381
2382/*
2383 * Execute mid callback atomically - ensures callback runs exactly once
2384 * and prevents sleeping in atomic context.
2385 */
2386static inline void mid_execute_callback(struct mid_q_entry *mid)
2387{
2388 void (*callback)(struct mid_q_entry *mid);
2389
2390 spin_lock(&mid->mid_lock);
2391 callback = mid->callback;
2392 mid->callback = NULL; /* Mark as executed, */
2393 spin_unlock(&mid->mid_lock);
2394
2395 if (callback)
2396 callback(mid);
2397}
2398
2378#define CIFS_REPARSE_SUPPORT(tcon) \2399#define CIFS_REPARSE_SUPPORT(tcon) \
2379 ((tcon)->posix_extensions || \2400 ((tcon)->posix_extensions || \
2380 (le32_to_cpu((tcon)->fsAttrInfo.Attributes) & \2401 (le32_to_cpu((tcon)->fsAttrInfo.Attributes) & \
fs/smb/client/cifstransport.c+9−10
@@ -46,6 +46,7 @@ alloc_mid(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server) · 45 unmodified lines
46 temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);46 temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
47 memset(temp, 0, sizeof(struct mid_q_entry));47 memset(temp, 0, sizeof(struct mid_q_entry));
48 kref_init(&temp->refcount);48 kref_init(&temp->refcount);
49 spin_lock_init(&temp->mid_lock);
49 temp->mid = get_mid(smb_buffer);50 temp->mid = get_mid(smb_buffer);
50 temp->pid = current->pid;51 temp->pid = current->pid;
51 temp->command = cpu_to_le16(smb_buffer->Command);52 temp->command = cpu_to_le16(smb_buffer->Command);
@@ -345,16 +346,15 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses, · 293 unmodified lines
345 rc = wait_for_response(server, midQ);346 rc = wait_for_response(server, midQ);
346 if (rc != 0) {347 if (rc != 0) {
347 send_cancel(server, &rqst, midQ);348 send_cancel(server, &rqst, midQ);
348 spin_lock(&server->mid_queue_lock);349 spin_lock(&midQ->mid_lock);
349 if (midQ->mid_state == MID_REQUEST_SUBMITTED ||350 if (midQ->callback) {
350 midQ->mid_state == MID_RESPONSE_RECEIVED) {
351 /* no longer considered to be "in-flight" */351 /* no longer considered to be "in-flight" */
352 midQ->callback = release_mid;352 midQ->callback = release_mid;
353 spin_unlock(&server->mid_queue_lock);353 spin_unlock(&midQ->mid_lock);
354 add_credits(server, &credits, 0);354 add_credits(server, &credits, 0);
355 return rc;355 return rc;
356 }356 }
357 spin_unlock(&server->mid_queue_lock);357 spin_unlock(&midQ->mid_lock);
358 }358 }
359 359
360 rc = cifs_sync_mid_result(midQ, server);360 rc = cifs_sync_mid_result(midQ, server);
@@ -527,15 +527,14 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, · 166 unmodified lines
527 rc = wait_for_response(server, midQ);527 rc = wait_for_response(server, midQ);
528 if (rc) {528 if (rc) {
529 send_cancel(server, &rqst, midQ);529 send_cancel(server, &rqst, midQ);
530 spin_lock(&server->mid_queue_lock);530 spin_lock(&midQ->mid_lock);
531 if (midQ->mid_state == MID_REQUEST_SUBMITTED ||531 if (midQ->callback) {
532 midQ->mid_state == MID_RESPONSE_RECEIVED) {
533 /* no longer considered to be "in-flight" */532 /* no longer considered to be "in-flight" */
534 midQ->callback = release_mid;533 midQ->callback = release_mid;
535 spin_unlock(&server->mid_queue_lock);534 spin_unlock(&midQ->mid_lock);
536 return rc;535 return rc;
537 }536 }
538 spin_unlock(&server->mid_queue_lock);537 spin_unlock(&midQ->mid_lock);
539 }538 }
540 539
541 /* We got the response - restart system call. */540 /* We got the response - restart system call. */
fs/smb/client/compress.c+21−50
@@ -155,58 +155,29 @@ static int cmp_bkt(const void *_a, const void *_b) · 154 unmodified lines
155}155}
156 156
157/*157/*
158 * TODO:158 * Collect some 2K samples with 2K gaps between.
159 * Support other iter types, if required.
160 * Only ITER_XARRAY is supported for now.
161 */159 */
162static int collect_sample(const struct iov_iter *iter, ssize_t max, u8 *sample)160static int collect_sample(const struct iov_iter *source, ssize_t max, u8 *sample)
163{161{
164 struct folio *folios[16], *folio;162 struct iov_iter iter = *source;
165 unsigned int nr, i, j, npages;163 size_t s = 0;
166 loff_t start = iter->xarray_start + iter->iov_offset;164
167 pgoff_t last, index = start / PAGE_SIZE;165 while (iov_iter_count(&iter) >= SZ_2K) {
168 size_t len, off, foff;166 size_t part = umin(umin(iov_iter_count(&iter), SZ_2K), max);
169 void *p;167 size_t n;
170 int s = 0;168
171 169 n = copy_from_iter(sample + s, part, &iter);
172 last = (start + max - 1) / PAGE_SIZE;170 if (n != part)
173 do {171 return -EFAULT;
174 nr = xa_extract(iter->xarray, (void **)folios, index, last, ARRAY_SIZE(folios),172
175 XA_PRESENT);173 s += n;
176 if (nr == 0)174 max -= n;
177 return -EIO;175
178 176 if (iov_iter_count(&iter) < PAGE_SIZE - SZ_2K)
179 for (i = 0; i < nr; i++) {177 break;
180 folio = folios[i];178
181 npages = folio_nr_pages(folio);179 iov_iter_advance(&iter, SZ_2K);
182 foff = start - folio_pos(folio);180 }
183 off = foff % PAGE_SIZE;
184
185 for (j = foff / PAGE_SIZE; j < npages; j++) {
186 size_t len2;
187
188 len = min_t(size_t, max, PAGE_SIZE - off);
189 len2 = min_t(size_t, len, SZ_2K);
190
191 p = kmap_local_page(folio_page(folio, j));
192 memcpy(&sample[s], p, len2);
193 kunmap_local(p);
194
195 s += len2;
196
197 if (len2 < SZ_2K || s >= max - SZ_2K)
198 return s;
199
200 max -= len;
201 if (max <= 0)
202 return s;
203
204 start += len;
205 off = 0;
206 index++;
207 }
208 }
209 } while (nr == ARRAY_SIZE(folios));
210 181
211 return s;182 return s;
212}183}
fs/smb/client/connect.c+4−5
@@ -335,7 +335,7 @@ cifs_abort_connection(struct TCP_Server_Info *server) · 334 unmodified lines
335 cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);335 cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);
336 list_for_each_entry_safe(mid, nmid, &retry_list, qhead) {336 list_for_each_entry_safe(mid, nmid, &retry_list, qhead) {
337 list_del_init(&mid->qhead);337 list_del_init(&mid->qhead);
338 mid->callback(mid);338 mid_execute_callback(mid);
339 release_mid(mid);339 release_mid(mid);
340 }340 }
341 341
@@ -919,7 +919,7 @@ is_smb_response(struct TCP_Server_Info *server, unsigned char type) · 577 unmodified lines
919 list_del_init(&mid->qhead);919 list_del_init(&mid->qhead);
920 mid->mid_rc = mid_rc;920 mid->mid_rc = mid_rc;
921 mid->mid_state = MID_RC;921 mid->mid_state = MID_RC;
922 mid->callback(mid);922 mid_execute_callback(mid);
923 release_mid(mid);923 release_mid(mid);
924 }924 }
925 925
@@ -1117,7 +1117,7 @@ clean_demultiplex_info(struct TCP_Server_Info *server) · 191 unmodified lines
1117 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);1117 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
1118 cifs_dbg(FYI, "Callback mid %llu\n", mid_entry->mid);1118 cifs_dbg(FYI, "Callback mid %llu\n", mid_entry->mid);
1119 list_del_init(&mid_entry->qhead);1119 list_del_init(&mid_entry->qhead);
1120 mid_entry->callback(mid_entry);1120 mid_execute_callback(mid_entry);
1121 release_mid(mid_entry);1121 release_mid(mid_entry);
1122 }1122 }
1123 /* 1/8th of sec is more than enough time for them to exit */1123 /* 1/8th of sec is more than enough time for them to exit */
@@ -1394,7 +1394,7 @@ next_pdu: · 270 unmodified lines
1394 }1394 }
1395 1395
1396 if (!mids[i]->multiRsp || mids[i]->multiEnd)1396 if (!mids[i]->multiRsp || mids[i]->multiEnd)
1397 mids[i]->callback(mids[i]);1397 mid_execute_callback(mids[i]);
1398 1398
1399 release_mid(mids[i]);1399 release_mid(mids[i]);
1400 } else if (server->ops->is_oplock_break &&1400 } else if (server->ops->is_oplock_break &&
@@ -4205,7 +4205,6 @@ retry: · 2804 unmodified lines
4205 return 0;4205 return 0;
4206 }4206 }
4207 4207
4208 server->lstrp = jiffies;
4209 server->tcpStatus = CifsInNegotiate;4208 server->tcpStatus = CifsInNegotiate;
4210 server->neg_start = jiffies;4209 server->neg_start = jiffies;
4211 spin_unlock(&server->srv_lock);4210 spin_unlock(&server->srv_lock);
fs/smb/client/inode.c+32−2
@@ -1943,15 +1943,24 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) · 1942 unmodified lines
1943 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);1943 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
1944 struct tcon_link *tlink;1944 struct tcon_link *tlink;
1945 struct cifs_tcon *tcon;1945 struct cifs_tcon *tcon;
1946 __u32 dosattr = 0, origattr = 0;
1946 struct TCP_Server_Info *server;1947 struct TCP_Server_Info *server;
1947 struct iattr *attrs = NULL;1948 struct iattr *attrs = NULL;
1948 __u32 dosattr = 0, origattr = 0;1949 bool rehash = false;
1949 1950
1950 cifs_dbg(FYI, "cifs_unlink, dir=0x%p, dentry=0x%p\n", dir, dentry);1951 cifs_dbg(FYI, "cifs_unlink, dir=0x%p, dentry=0x%p\n", dir, dentry);
1951 1952
1952 if (unlikely(cifs_forced_shutdown(cifs_sb)))1953 if (unlikely(cifs_forced_shutdown(cifs_sb)))
1953 return -EIO;1954 return -EIO;
1954 1955
1956 /* Unhash dentry in advance to prevent any concurrent opens */
1957 spin_lock(&dentry->d_lock);
1958 if (!d_unhashed(dentry)) {
1959 __d_drop(dentry);
1960 rehash = true;
1961 }
1962 spin_unlock(&dentry->d_lock);
1963
1955 tlink = cifs_sb_tlink(cifs_sb);1964 tlink = cifs_sb_tlink(cifs_sb);
1956 if (IS_ERR(tlink))1965 if (IS_ERR(tlink))
1957 return PTR_ERR(tlink);1966 return PTR_ERR(tlink);
@@ -2003,7 +2012,8 @@ psx_del_no_retry: · 45 unmodified lines
2003 cifs_drop_nlink(inode);2012 cifs_drop_nlink(inode);
2004 }2013 }
2005 } else if (rc == -ENOENT) {2014 } else if (rc == -ENOENT) {
2006 d_drop(dentry);2015 if (simple_positive(dentry))
2016 d_delete(dentry);
2007 } else if (rc == -EBUSY) {2017 } else if (rc == -EBUSY) {
2008 if (server->ops->rename_pending_delete) {2018 if (server->ops->rename_pending_delete) {
2009 rc = server->ops->rename_pending_delete(full_path,2019 rc = server->ops->rename_pending_delete(full_path,
@@ -2056,6 +2066,8 @@ unlink_out: · 46 unmodified lines
2056 kfree(attrs);2066 kfree(attrs);
2057 free_xid(xid);2067 free_xid(xid);
2058 cifs_put_tlink(tlink);2068 cifs_put_tlink(tlink);
2069 if (rehash)
2070 d_rehash(dentry);
2059 return rc;2071 return rc;
2060}2072}
2061 2073
@@ -2462,6 +2474,7 @@ cifs_rename2(struct mnt_idmap *idmap, struct inode *source_dir, · 400 unmodified lines
2462 struct cifs_sb_info *cifs_sb;2474 struct cifs_sb_info *cifs_sb;
2463 struct tcon_link *tlink;2475 struct tcon_link *tlink;
2464 struct cifs_tcon *tcon;2476 struct cifs_tcon *tcon;
2477 bool rehash = false;
2465 unsigned int xid;2478 unsigned int xid;
2466 int rc, tmprc;2479 int rc, tmprc;
2467 int retry_count = 0;2480 int retry_count = 0;
@@ -2477,6 +2490,17 @@ cifs_rename2(struct mnt_idmap *idmap, struct inode *source_dir, · 9 unmodified lines
2477 if (unlikely(cifs_forced_shutdown(cifs_sb)))2490 if (unlikely(cifs_forced_shutdown(cifs_sb)))
2478 return -EIO;2491 return -EIO;
2479 2492
2493 /*
2494 * Prevent any concurrent opens on the target by unhashing the dentry.
2495 * VFS already unhashes the target when renaming directories.
2496 */
2497 if (d_is_positive(target_dentry) && !d_is_dir(target_dentry)) {
2498 if (!d_unhashed(target_dentry)) {
2499 d_drop(target_dentry);
2500 rehash = true;
2501 }
2502 }
2503
2480 tlink = cifs_sb_tlink(cifs_sb);2504 tlink = cifs_sb_tlink(cifs_sb);
2481 if (IS_ERR(tlink))2505 if (IS_ERR(tlink))
2482 return PTR_ERR(tlink);2506 return PTR_ERR(tlink);
@@ -2518,6 +2542,8 @@ cifs_rename2(struct mnt_idmap *idmap, struct inode *source_dir, · 35 unmodified lines
2518 }2542 }
2519 }2543 }
2520 2544
2545 if (!rc)
2546 rehash = false;
2521 /*2547 /*
2522 * No-replace is the natural behavior for CIFS, so skip unlink hacks.2548 * No-replace is the natural behavior for CIFS, so skip unlink hacks.
2523 */2549 */
@@ -2576,12 +2602,16 @@ unlink_target: · 52 unmodified lines
2576 goto cifs_rename_exit;2602 goto cifs_rename_exit;
2577 rc = cifs_do_rename(xid, source_dentry, from_name,2603 rc = cifs_do_rename(xid, source_dentry, from_name,
2578 target_dentry, to_name);2604 target_dentry, to_name);
2605 if (!rc)
2606 rehash = false;
2579 }2607 }
2580 2608
2581 /* force revalidate to go get info when needed */2609 /* force revalidate to go get info when needed */
2582 CIFS_I(source_dir)->time = CIFS_I(target_dir)->time = 0;2610 CIFS_I(source_dir)->time = CIFS_I(target_dir)->time = 0;
2583 2611
2584cifs_rename_exit:2612cifs_rename_exit:
2613 if (rehash)
2614 d_rehash(target_dentry);
2585 kfree(info_buf_source);2615 kfree(info_buf_source);
2586 free_dentry_path(page2);2616 free_dentry_path(page2);
2587 free_dentry_path(page1);2617 free_dentry_path(page1);
fs/smb/client/smb2ops.c+12−3
@@ -772,6 +772,13 @@ next_iface: · 771 unmodified lines
772 bytes_left -= sizeof(*p);772 bytes_left -= sizeof(*p);
773 break;773 break;
774 }774 }
775 /* Validate that Next doesn't point beyond the buffer */
776 if (next > bytes_left) {
777 cifs_dbg(VFS, "%s: invalid Next pointer %zu > %zd\n",
778 __func__, next, bytes_left);
779 rc = -EINVAL;
780 goto out;
781 }
775 p = (struct network_interface_info_ioctl_rsp *)((u8 *)p+next);782 p = (struct network_interface_info_ioctl_rsp *)((u8 *)p+next);
776 bytes_left -= next;783 bytes_left -= next;
777 }784 }
@@ -783,7 +790,9 @@ next_iface: · 5 unmodified lines
783 }790 }
784 791
785 /* Azure rounds the buffer size up 8, to a 16 byte boundary */792 /* Azure rounds the buffer size up 8, to a 16 byte boundary */
786 if ((bytes_left > 8) || p->Next)793 if ((bytes_left > 8) ||
794 (bytes_left >= offsetof(struct network_interface_info_ioctl_rsp, Next)
795 + sizeof(p->Next) && p->Next))
787 cifs_dbg(VFS, "%s: incomplete interface info\n", __func__);796 cifs_dbg(VFS, "%s: incomplete interface info\n", __func__);
788 797
789 ses->iface_last_update = jiffies;798 ses->iface_last_update = jiffies;
@@ -4805,7 +4814,7 @@ static void smb2_decrypt_offload(struct work_struct *work) · 4015 unmodified lines
4805 dw->server->ops->is_network_name_deleted(dw->buf,4814 dw->server->ops->is_network_name_deleted(dw->buf,
4806 dw->server);4815 dw->server);
4807 4816
4808 mid->callback(mid);4817 mid_execute_callback(mid);
4809 } else {4818 } else {
4810 spin_lock(&dw->server->srv_lock);4819 spin_lock(&dw->server->srv_lock);
4811 if (dw->server->tcpStatus == CifsNeedReconnect) {4820 if (dw->server->tcpStatus == CifsNeedReconnect) {
@@ -4813,7 +4822,7 @@ static void smb2_decrypt_offload(struct work_struct *work) · 1 unmodified line
4813 mid->mid_state = MID_RETRY_NEEDED;4822 mid->mid_state = MID_RETRY_NEEDED;
4814 spin_unlock(&dw->server->mid_queue_lock);4823 spin_unlock(&dw->server->mid_queue_lock);
4815 spin_unlock(&dw->server->srv_lock);4824 spin_unlock(&dw->server->srv_lock);
4816 mid->callback(mid);4825 mid_execute_callback(mid);
4817 } else {4826 } else {
4818 spin_lock(&dw->server->mid_queue_lock);4827 spin_lock(&dw->server->mid_queue_lock);
4819 mid->mid_state = MID_REQUEST_SUBMITTED;4828 mid->mid_state = MID_REQUEST_SUBMITTED;
fs/smb/client/smb2transport.c+1−0
@@ -771,6 +771,7 @@ smb2_mid_entry_alloc(const struct smb2_hdr *shdr, · 770 unmodified lines
771 temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);771 temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
772 memset(temp, 0, sizeof(struct mid_q_entry));772 memset(temp, 0, sizeof(struct mid_q_entry));
773 kref_init(&temp->refcount);773 kref_init(&temp->refcount);
774 spin_lock_init(&temp->mid_lock);
774 temp->mid = le64_to_cpu(shdr->MessageId);775 temp->mid = le64_to_cpu(shdr->MessageId);
775 temp->credits = credits > 0 ? credits : 1;776 temp->credits = credits > 0 ? credits : 1;
776 temp->pid = current->pid;777 temp->pid = current->pid;
fs/smb/client/smbdirect.c+5−5
@@ -1337,10 +1337,6 @@ void smbd_destroy(struct TCP_Server_Info *server) · 1336 unmodified lines
1337 log_rdma_event(INFO, "cancelling idle timer\n");1337 log_rdma_event(INFO, "cancelling idle timer\n");
1338 cancel_delayed_work_sync(&info->idle_timer_work);1338 cancel_delayed_work_sync(&info->idle_timer_work);
1339 1339
1340 log_rdma_event(INFO, "wait for all send posted to IB to finish\n");
1341 wait_event(info->wait_send_pending,
1342 atomic_read(&info->send_pending) == 0);
1343
1344 /* It's not possible for upper layer to get to reassembly */1340 /* It's not possible for upper layer to get to reassembly */
1345 log_rdma_event(INFO, "drain the reassembly queue\n");1341 log_rdma_event(INFO, "drain the reassembly queue\n");
1346 do {1342 do {
@@ -1986,7 +1982,11 @@ int smbd_send(struct TCP_Server_Info *server, · 639 unmodified lines
1986 */1982 */
1987 1983
1988 wait_event(info->wait_send_pending,1984 wait_event(info->wait_send_pending,
1989 atomic_read(&info->send_pending) == 0);1985 atomic_read(&info->send_pending) == 0 ||
1986 sc->status != SMBDIRECT_SOCKET_CONNECTED);
1987
1988 if (sc->status != SMBDIRECT_SOCKET_CONNECTED && rc == 0)
1989 rc = -EAGAIN;
1990 1990
1991 return rc;1991 return rc;
1992}1992}
fs/smb/client/transport.c+3−4
@@ -1005,15 +1005,14 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, · 1004 unmodified lines
1005 cifs_server_dbg(FYI, "Cancelling wait for mid %llu cmd: %d\n",1005 cifs_server_dbg(FYI, "Cancelling wait for mid %llu cmd: %d\n",
1006 midQ[i]->mid, le16_to_cpu(midQ[i]->command));1006 midQ[i]->mid, le16_to_cpu(midQ[i]->command));
1007 send_cancel(server, &rqst[i], midQ[i]);1007 send_cancel(server, &rqst[i], midQ[i]);
1008 spin_lock(&server->mid_queue_lock);1008 spin_lock(&midQ[i]->mid_lock);
1009 midQ[i]->wait_cancelled = true;1009 midQ[i]->wait_cancelled = true;
1010 if (midQ[i]->mid_state == MID_REQUEST_SUBMITTED ||1010 if (midQ[i]->callback) {
1011 midQ[i]->mid_state == MID_RESPONSE_RECEIVED) {
1012 midQ[i]->callback = cifs_cancelled_callback;1011 midQ[i]->callback = cifs_cancelled_callback;
1013 cancelled_mid[i] = true;1012 cancelled_mid[i] = true;
1014 credits[i].value = 0;1013 credits[i].value = 0;
1015 }1014 }
1016 spin_unlock(&server->mid_queue_lock);1015 spin_unlock(&midQ[i]->mid_lock);
1017 }1016 }
1018 }1017 }
1019 1018