CIFS: Fix possible wrong memory allocation
when cifs_reconnect sets maxBuf to 0 and we try to calculate a size of memory we need to store locks. Signed-off-by: Pavel Shilovsky <pshilovsky@samba.org> Signed-off-by: Steve French <sfrench@us.ibm.com>
This commit is contained in:
parent
51eab603f5
commit
0013fb4ca3
@ -876,7 +876,7 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile)
|
|||||||
struct cifsLockInfo *li, *tmp;
|
struct cifsLockInfo *li, *tmp;
|
||||||
struct cifs_tcon *tcon;
|
struct cifs_tcon *tcon;
|
||||||
struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
|
struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
|
||||||
unsigned int num, max_num;
|
unsigned int num, max_num, max_buf;
|
||||||
LOCKING_ANDX_RANGE *buf, *cur;
|
LOCKING_ANDX_RANGE *buf, *cur;
|
||||||
int types[] = {LOCKING_ANDX_LARGE_FILES,
|
int types[] = {LOCKING_ANDX_LARGE_FILES,
|
||||||
LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES};
|
LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES};
|
||||||
@ -892,8 +892,19 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
max_num = (tcon->ses->server->maxBuf - sizeof(struct smb_hdr)) /
|
/*
|
||||||
sizeof(LOCKING_ANDX_RANGE);
|
* Accessing maxBuf is racy with cifs_reconnect - need to store value
|
||||||
|
* and check it for zero before using.
|
||||||
|
*/
|
||||||
|
max_buf = tcon->ses->server->maxBuf;
|
||||||
|
if (!max_buf) {
|
||||||
|
mutex_unlock(&cinode->lock_mutex);
|
||||||
|
FreeXid(xid);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
max_num = (max_buf - sizeof(struct smb_hdr)) /
|
||||||
|
sizeof(LOCKING_ANDX_RANGE);
|
||||||
buf = kzalloc(max_num * sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL);
|
buf = kzalloc(max_num * sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL);
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
mutex_unlock(&cinode->lock_mutex);
|
mutex_unlock(&cinode->lock_mutex);
|
||||||
@ -1218,7 +1229,7 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, int xid)
|
|||||||
int types[] = {LOCKING_ANDX_LARGE_FILES,
|
int types[] = {LOCKING_ANDX_LARGE_FILES,
|
||||||
LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES};
|
LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES};
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
unsigned int max_num, num;
|
unsigned int max_num, num, max_buf;
|
||||||
LOCKING_ANDX_RANGE *buf, *cur;
|
LOCKING_ANDX_RANGE *buf, *cur;
|
||||||
struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
|
struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
|
||||||
struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
|
struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
|
||||||
@ -1228,8 +1239,16 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, int xid)
|
|||||||
|
|
||||||
INIT_LIST_HEAD(&tmp_llist);
|
INIT_LIST_HEAD(&tmp_llist);
|
||||||
|
|
||||||
max_num = (tcon->ses->server->maxBuf - sizeof(struct smb_hdr)) /
|
/*
|
||||||
sizeof(LOCKING_ANDX_RANGE);
|
* Accessing maxBuf is racy with cifs_reconnect - need to store value
|
||||||
|
* and check it for zero before using.
|
||||||
|
*/
|
||||||
|
max_buf = tcon->ses->server->maxBuf;
|
||||||
|
if (!max_buf)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
max_num = (max_buf - sizeof(struct smb_hdr)) /
|
||||||
|
sizeof(LOCKING_ANDX_RANGE);
|
||||||
buf = kzalloc(max_num * sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL);
|
buf = kzalloc(max_num * sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
Loading…
Reference in New Issue
Block a user