Commit 0013fb4c authored by Pavel Shilovsky's avatar Pavel Shilovsky Committed by Steve French

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: default avatarPavel Shilovsky <pshilovsky@samba.org>
Signed-off-by: default avatarSteve French <sfrench@us.ibm.com>
parent 51eab603
...@@ -876,7 +876,7 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment