Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag '5.1-rc5-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull smb3 fixes from Steve French:
"Five small SMB3 fixes, all also for stable - an important fix for an
oplock (lease) bug, a handle leak, and three bugs spotted by KASAN"

* tag '5.1-rc5-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6:
CIFS: keep FileInfo handle live during oplock break
cifs: fix handle leak in smb2_query_symlink()
cifs: Fix lease buffer length error
cifs: Fix use-after-free in SMB2_read
cifs: Fix use-after-free in SMB2_write

+62 -14
+2
fs/cifs/cifsglob.h
··· 1333 1333 } 1334 1334 1335 1335 struct cifsFileInfo *cifsFileInfo_get(struct cifsFileInfo *cifs_file); 1336 + void _cifsFileInfo_put(struct cifsFileInfo *cifs_file, bool wait_oplock_hdlr); 1336 1337 void cifsFileInfo_put(struct cifsFileInfo *cifs_file); 1337 1338 1338 1339 #define CIFS_CACHE_READ_FLG 1 ··· 1856 1855 #endif /* CONFIG_CIFS_ACL */ 1857 1856 1858 1857 void cifs_oplock_break(struct work_struct *work); 1858 + void cifs_queue_oplock_break(struct cifsFileInfo *cfile); 1859 1859 1860 1860 extern const struct slow_work_ops cifs_oplock_break_ops; 1861 1861 extern struct workqueue_struct *cifsiod_wq;
+25 -5
fs/cifs/file.c
··· 360 360 return cifs_file; 361 361 } 362 362 363 - /* 364 - * Release a reference on the file private data. This may involve closing 365 - * the filehandle out on the server. Must be called without holding 366 - * tcon->open_file_lock and cifs_file->file_info_lock. 363 + /** 364 + * cifsFileInfo_put - release a reference of file priv data 365 + * 366 + * Always potentially wait for oplock handler. See _cifsFileInfo_put(). 367 367 */ 368 368 void cifsFileInfo_put(struct cifsFileInfo *cifs_file) 369 + { 370 + _cifsFileInfo_put(cifs_file, true); 371 + } 372 + 373 + /** 374 + * _cifsFileInfo_put - release a reference of file priv data 375 + * 376 + * This may involve closing the filehandle @cifs_file out on the 377 + * server. Must be called without holding tcon->open_file_lock and 378 + * cifs_file->file_info_lock. 379 + * 380 + * If @wait_for_oplock_handler is true and we are releasing the last 381 + * reference, wait for any running oplock break handler of the file 382 + * and cancel any pending one. If calling this function from the 383 + * oplock break handler, you need to pass false. 384 + * 385 + */ 386 + void _cifsFileInfo_put(struct cifsFileInfo *cifs_file, bool wait_oplock_handler) 369 387 { 370 388 struct inode *inode = d_inode(cifs_file->dentry); 371 389 struct cifs_tcon *tcon = tlink_tcon(cifs_file->tlink); ··· 432 414 433 415 spin_unlock(&tcon->open_file_lock); 434 416 435 - oplock_break_cancelled = cancel_work_sync(&cifs_file->oplock_break); 417 + oplock_break_cancelled = wait_oplock_handler ? 418 + cancel_work_sync(&cifs_file->oplock_break) : false; 436 419 437 420 if (!tcon->need_reconnect && !cifs_file->invalidHandle) { 438 421 struct TCP_Server_Info *server = tcon->ses->server; ··· 4622 4603 cinode); 4623 4604 cifs_dbg(FYI, "Oplock release rc = %d\n", rc); 4624 4605 } 4606 + _cifsFileInfo_put(cfile, false /* do not wait for ourself */); 4625 4607 cifs_done_oplock_break(cinode); 4626 4608 } 4627 4609
+23 -2
fs/cifs/misc.c
··· 501 501 CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2, 502 502 &pCifsInode->flags); 503 503 504 - queue_work(cifsoplockd_wq, 505 - &netfile->oplock_break); 504 + cifs_queue_oplock_break(netfile); 506 505 netfile->oplock_break_cancelled = false; 507 506 508 507 spin_unlock(&tcon->open_file_lock); ··· 604 605 wake_up_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS); 605 606 } 606 607 spin_unlock(&cinode->writers_lock); 608 + } 609 + 610 + /** 611 + * cifs_queue_oplock_break - queue the oplock break handler for cfile 612 + * 613 + * This function is called from the demultiplex thread when it 614 + * receives an oplock break for @cfile. 615 + * 616 + * Assumes the tcon->open_file_lock is held. 617 + * Assumes cfile->file_info_lock is NOT held. 618 + */ 619 + void cifs_queue_oplock_break(struct cifsFileInfo *cfile) 620 + { 621 + /* 622 + * Bump the handle refcount now while we hold the 623 + * open_file_lock to enforce the validity of it for the oplock 624 + * break handler. The matching put is done at the end of the 625 + * handler. 626 + */ 627 + cifsFileInfo_get(cfile); 628 + 629 + queue_work(cifsoplockd_wq, &cfile->oplock_break); 607 630 } 608 631 609 632 void cifs_done_oplock_break(struct cifsInodeInfo *cinode)
+3 -3
fs/cifs/smb2misc.c
··· 555 555 clear_bit(CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2, 556 556 &cinode->flags); 557 557 558 - queue_work(cifsoplockd_wq, &cfile->oplock_break); 558 + cifs_queue_oplock_break(cfile); 559 559 kfree(lw); 560 560 return true; 561 561 } ··· 712 712 CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2, 713 713 &cinode->flags); 714 714 spin_unlock(&cfile->file_info_lock); 715 - queue_work(cifsoplockd_wq, 716 - &cfile->oplock_break); 715 + 716 + cifs_queue_oplock_break(cfile); 717 717 718 718 spin_unlock(&tcon->open_file_lock); 719 719 spin_unlock(&cifs_tcp_ses_lock);
+2
fs/cifs/smb2ops.c
··· 2389 2389 2390 2390 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, &err_iov, 2391 2391 &resp_buftype); 2392 + if (!rc) 2393 + SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); 2392 2394 if (!rc || !err_iov.iov_base) { 2393 2395 rc = -ENOENT; 2394 2396 goto free_path;
+7 -4
fs/cifs/smb2pdu.c
··· 832 832 } else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID)) { 833 833 /* ops set to 3.0 by default for default so update */ 834 834 ses->server->ops = &smb21_operations; 835 - } else if (rsp->DialectRevision == cpu_to_le16(SMB311_PROT_ID)) 835 + ses->server->vals = &smb21_values; 836 + } else if (rsp->DialectRevision == cpu_to_le16(SMB311_PROT_ID)) { 836 837 ses->server->ops = &smb311_operations; 838 + ses->server->vals = &smb311_values; 839 + } 837 840 } else if (le16_to_cpu(rsp->DialectRevision) != 838 841 ses->server->vals->protocol_id) { 839 842 /* if requested single dialect ensure returned dialect matched */ ··· 3451 3448 rqst.rq_nvec = 1; 3452 3449 3453 3450 rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); 3454 - cifs_small_buf_release(req); 3455 - 3456 3451 rsp = (struct smb2_read_rsp *)rsp_iov.iov_base; 3457 3452 3458 3453 if (rc) { ··· 3471 3470 trace_smb3_read_done(xid, req->PersistentFileId, 3472 3471 io_parms->tcon->tid, ses->Suid, 3473 3472 io_parms->offset, io_parms->length); 3473 + 3474 + cifs_small_buf_release(req); 3474 3475 3475 3476 *nbytes = le32_to_cpu(rsp->DataLength); 3476 3477 if ((*nbytes > CIFS_MAX_MSGSIZE) || ··· 3772 3769 3773 3770 rc = cifs_send_recv(xid, io_parms->tcon->ses, &rqst, 3774 3771 &resp_buftype, flags, &rsp_iov); 3775 - cifs_small_buf_release(req); 3776 3772 rsp = (struct smb2_write_rsp *)rsp_iov.iov_base; 3777 3773 3778 3774 if (rc) { ··· 3789 3787 io_parms->offset, *nbytes); 3790 3788 } 3791 3789 3790 + cifs_small_buf_release(req); 3792 3791 free_rsp_buf(resp_buftype, rsp); 3793 3792 return rc; 3794 3793 }