mirror of https://github.com/torvalds/linux.git
three smb client fixes
-----BEGIN PGP SIGNATURE----- iQGzBAABCgAdFiEE6fsu8pdIjtWE/DpLiiy9cAdyT1EFAmkPhxAACgkQiiy9cAdy T1H0jQv+Ixfm//dkrOfJ6xGFVUaJFRyscy9bX6rGTnUpUWxRSdHtaiufClqW2QvZ f4fsLC1e7VFeXM/BxaXrC2XM9Ltmzpb4n4phoL3cLT+NjQDiUM7veJBfsJCGMICc CVxnczjr+QGx8sl2bCliNWYojsUTkcm6jagBrozfBdSl802C23xaNny6KeNkivxY QvNbNTl5+63KeQZhM/5QWEzDBFON+5xRCKRMFExySHtMS6h5hn7fdRPScLfD9TOo MrJ4VbZ0V3qQ6R2PQhIykq6/FMg9qO3NildZegE5C12a5NPaupPeIlEwZgzdQ/jf S49UGjpNTniRoeBRFyNy4OSDzeD1G6ikb5sU/NRnnD8VPaiW+7OqqyJCFKTIA2aI FGl7W5qcuW/WSR1Uvcsfco/hCcxN0I6cqpOF+4Q/oSZFGgSuaj4nX+/Vtg4wpTCE uUP2K3f5vwcAIMPXUg22k4iu4XHPt2ZKzqQ5LyNpO5tpPBYkUxf+6XzNdvn4qjpN zJZ/0wfW =fdZF -----END PGP SIGNATURE----- Merge tag 'v6.18rc4-SMB-client-fixes' of git://git.samba.org/sfrench/cifs-2.6 Pull smb client fixes from Steve French: - Fix change notify packet validation check - Refcount fix (e.g. rename error paths) - Fix potential UAF due to missing locks on directory lease refcount * tag 'v6.18rc4-SMB-client-fixes' of git://git.samba.org/sfrench/cifs-2.6: smb: client: validate change notify buffer before copy smb: client: fix refcount leak in smb2_set_path_attr smb: client: fix potential UAF in smb2_close_cached_fid()
This commit is contained in:
commit
7bb4d65125
|
|
@ -388,11 +388,11 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
|
||||||
* lease. Release one here, and the second below.
|
* lease. Release one here, and the second below.
|
||||||
*/
|
*/
|
||||||
cfid->has_lease = false;
|
cfid->has_lease = false;
|
||||||
kref_put(&cfid->refcount, smb2_close_cached_fid);
|
close_cached_dir(cfid);
|
||||||
}
|
}
|
||||||
spin_unlock(&cfids->cfid_list_lock);
|
spin_unlock(&cfids->cfid_list_lock);
|
||||||
|
|
||||||
kref_put(&cfid->refcount, smb2_close_cached_fid);
|
close_cached_dir(cfid);
|
||||||
} else {
|
} else {
|
||||||
*ret_cfid = cfid;
|
*ret_cfid = cfid;
|
||||||
atomic_inc(&tcon->num_remote_opens);
|
atomic_inc(&tcon->num_remote_opens);
|
||||||
|
|
@ -438,12 +438,14 @@ int open_cached_dir_by_dentry(struct cifs_tcon *tcon,
|
||||||
|
|
||||||
static void
|
static void
|
||||||
smb2_close_cached_fid(struct kref *ref)
|
smb2_close_cached_fid(struct kref *ref)
|
||||||
|
__releases(&cfid->cfids->cfid_list_lock)
|
||||||
{
|
{
|
||||||
struct cached_fid *cfid = container_of(ref, struct cached_fid,
|
struct cached_fid *cfid = container_of(ref, struct cached_fid,
|
||||||
refcount);
|
refcount);
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
spin_lock(&cfid->cfids->cfid_list_lock);
|
lockdep_assert_held(&cfid->cfids->cfid_list_lock);
|
||||||
|
|
||||||
if (cfid->on_list) {
|
if (cfid->on_list) {
|
||||||
list_del(&cfid->entry);
|
list_del(&cfid->entry);
|
||||||
cfid->on_list = false;
|
cfid->on_list = false;
|
||||||
|
|
@ -478,7 +480,7 @@ void drop_cached_dir_by_name(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
spin_lock(&cfid->cfids->cfid_list_lock);
|
spin_lock(&cfid->cfids->cfid_list_lock);
|
||||||
if (cfid->has_lease) {
|
if (cfid->has_lease) {
|
||||||
cfid->has_lease = false;
|
cfid->has_lease = false;
|
||||||
kref_put(&cfid->refcount, smb2_close_cached_fid);
|
close_cached_dir(cfid);
|
||||||
}
|
}
|
||||||
spin_unlock(&cfid->cfids->cfid_list_lock);
|
spin_unlock(&cfid->cfids->cfid_list_lock);
|
||||||
close_cached_dir(cfid);
|
close_cached_dir(cfid);
|
||||||
|
|
@ -487,7 +489,7 @@ void drop_cached_dir_by_name(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
|
|
||||||
void close_cached_dir(struct cached_fid *cfid)
|
void close_cached_dir(struct cached_fid *cfid)
|
||||||
{
|
{
|
||||||
kref_put(&cfid->refcount, smb2_close_cached_fid);
|
kref_put_lock(&cfid->refcount, smb2_close_cached_fid, &cfid->cfids->cfid_list_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -596,7 +598,7 @@ cached_dir_offload_close(struct work_struct *work)
|
||||||
|
|
||||||
WARN_ON(cfid->on_list);
|
WARN_ON(cfid->on_list);
|
||||||
|
|
||||||
kref_put(&cfid->refcount, smb2_close_cached_fid);
|
close_cached_dir(cfid);
|
||||||
cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_cached_close);
|
cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_cached_close);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -762,7 +764,7 @@ static void cfids_laundromat_worker(struct work_struct *work)
|
||||||
* Drop the ref-count from above, either the lease-ref (if there
|
* Drop the ref-count from above, either the lease-ref (if there
|
||||||
* was one) or the extra one acquired.
|
* was one) or the extra one acquired.
|
||||||
*/
|
*/
|
||||||
kref_put(&cfid->refcount, smb2_close_cached_fid);
|
close_cached_dir(cfid);
|
||||||
}
|
}
|
||||||
queue_delayed_work(cfid_put_wq, &cfids->laundromat_work,
|
queue_delayed_work(cfid_put_wq, &cfids->laundromat_work,
|
||||||
dir_cache_timeout * HZ);
|
dir_cache_timeout * HZ);
|
||||||
|
|
|
||||||
|
|
@ -1294,6 +1294,8 @@ static int smb2_set_path_attr(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
smb2_to_name = cifs_convert_path_to_utf16(to_name, cifs_sb);
|
smb2_to_name = cifs_convert_path_to_utf16(to_name, cifs_sb);
|
||||||
if (smb2_to_name == NULL) {
|
if (smb2_to_name == NULL) {
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
|
if (cfile)
|
||||||
|
cifsFileInfo_put(cfile);
|
||||||
goto smb2_rename_path;
|
goto smb2_rename_path;
|
||||||
}
|
}
|
||||||
in_iov.iov_base = smb2_to_name;
|
in_iov.iov_base = smb2_to_name;
|
||||||
|
|
|
||||||
|
|
@ -4054,9 +4054,12 @@ SMB2_change_notify(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
|
|
||||||
smb_rsp = (struct smb2_change_notify_rsp *)rsp_iov.iov_base;
|
smb_rsp = (struct smb2_change_notify_rsp *)rsp_iov.iov_base;
|
||||||
|
|
||||||
smb2_validate_iov(le16_to_cpu(smb_rsp->OutputBufferOffset),
|
rc = smb2_validate_iov(le16_to_cpu(smb_rsp->OutputBufferOffset),
|
||||||
le32_to_cpu(smb_rsp->OutputBufferLength), &rsp_iov,
|
le32_to_cpu(smb_rsp->OutputBufferLength),
|
||||||
|
&rsp_iov,
|
||||||
sizeof(struct file_notify_information));
|
sizeof(struct file_notify_information));
|
||||||
|
if (rc)
|
||||||
|
goto cnotify_exit;
|
||||||
|
|
||||||
*out_data = kmemdup((char *)smb_rsp + le16_to_cpu(smb_rsp->OutputBufferOffset),
|
*out_data = kmemdup((char *)smb_rsp + le16_to_cpu(smb_rsp->OutputBufferOffset),
|
||||||
le32_to_cpu(smb_rsp->OutputBufferLength), GFP_KERNEL);
|
le32_to_cpu(smb_rsp->OutputBufferLength), GFP_KERNEL);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue