Commit cf3035f7 authored by Steve French's avatar Steve French

Check for kmalloc failure on building full path

parent b29e527a
...@@ -53,10 +53,12 @@ build_path_from_dentry(struct dentry *direntry) ...@@ -53,10 +53,12 @@ build_path_from_dentry(struct dentry *direntry)
namelen += (1 + temp->d_name.len); namelen += (1 + temp->d_name.len);
temp = temp->d_parent; temp = temp->d_parent;
} }
namelen += 1; /* allow for trailing null */
full_path = kmalloc(namelen, GFP_KERNEL); full_path = kmalloc(namelen+1, GFP_KERNEL);
namelen--; if(full_path == NULL)
return full_path;
full_path[namelen] = 0; /* trailing null */ full_path[namelen] = 0; /* trailing null */
for (temp = direntry; !IS_ROOT(temp);) { for (temp = direntry; !IS_ROOT(temp);) {
namelen -= 1 + temp->d_name.len; namelen -= 1 + temp->d_name.len;
if (namelen < 0) { if (namelen < 0) {
...@@ -142,10 +144,12 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -142,10 +144,12 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if(full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
if(nd) { if(nd) {
cFYI(1,("In create for inode %p dentry->inode %p nd flags = 0x%x for %s",inode, direntry->d_inode, nd->flags,full_path));
if ((nd->intent.open.flags & O_ACCMODE) == O_RDONLY) if ((nd->intent.open.flags & O_ACCMODE) == O_RDONLY)
desiredAccess = GENERIC_READ; desiredAccess = GENERIC_READ;
else if ((nd->intent.open.flags & O_ACCMODE) == O_WRONLY) else if ((nd->intent.open.flags & O_ACCMODE) == O_WRONLY)
...@@ -173,6 +177,12 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -173,6 +177,12 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
oplock = REQ_OPLOCK; oplock = REQ_OPLOCK;
buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL); buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
if(buf == NULL) {
kfree(full_path);
FreeXid(xid);
return -ENOMEM;
}
rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, rc = CIFSSMBOpen(xid, pTcon, full_path, disposition,
desiredAccess, CREATE_NOT_DIR, desiredAccess, CREATE_NOT_DIR,
&fileHandle, &oplock, buf, cifs_sb->local_nls); &fileHandle, &oplock, buf, cifs_sb->local_nls);
...@@ -273,8 +283,10 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t dev ...@@ -273,8 +283,10 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t dev
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if(full_path == NULL)
if (pTcon->ses->capabilities & CAP_UNIX) { rc = -ENOMEM;
if (full_path && (pTcon->ses->capabilities & CAP_UNIX)) {
rc = CIFSSMBUnixSetPerms(xid, pTcon, rc = CIFSSMBUnixSetPerms(xid, pTcon,
full_path, mode, current->euid, current->egid, full_path, mode, current->euid, current->egid,
device_number, cifs_sb->local_nls); device_number, cifs_sb->local_nls);
...@@ -298,7 +310,8 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t dev ...@@ -298,7 +310,8 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t dev
struct dentry * struct dentry *
cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct nameidata *nd) cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct nameidata *nd)
{ {
int rc, xid; int xid;
int rc = 0; /* to get around spurious gcc warning, set to zero here */
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
struct inode *newInode = NULL; struct inode *newInode = NULL;
...@@ -321,6 +334,11 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name ...@@ -321,6 +334,11 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if(full_path == NULL) {
FreeXid(xid);
return ERR_PTR(-ENOMEM);
}
if (direntry->d_inode != NULL) { if (direntry->d_inode != NULL) {
cFYI(1, (" non-NULL inode in lookup")); cFYI(1, (" non-NULL inode in lookup"));
} else { } else {
...@@ -347,10 +365,10 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name ...@@ -347,10 +365,10 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
rc = 0; rc = 0;
d_add(direntry, NULL); d_add(direntry, NULL);
} else { } else {
cERROR(1, cERROR(1,("Error 0x%x or on cifs_get_inode_info in lookup",rc));
("Error 0x%x or (%d decimal) on cifs_get_inode_info in lookup", /* BB special case check for Access Denied - watch security
rc, rc)); exposure of returning dir info implicitly via different rc
/* BB special case check for Access Denied - watch security exposure of returning dir info implicitly via different rc if file exists or not but no access BB */ if file exists or not but no access BB */
} }
if (full_path) if (full_path)
......
...@@ -40,8 +40,13 @@ int cifs_directory_notify(unsigned long arg, struct file * file) ...@@ -40,8 +40,13 @@ int cifs_directory_notify(unsigned long arg, struct file * file)
cifs_sb = CIFS_SB(file->f_dentry->d_sb); cifs_sb = CIFS_SB(file->f_dentry->d_sb);
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(file->f_dentry); full_path = build_path_from_dentry(file->f_dentry);
cFYI(1,("cifs dir notify on file %s",full_path)); if(full_path == NULL) {
/* CIFSSMBNotify */ rc = -ENOMEM;
} else {
cFYI(1,("cifs dir notify on file %s",full_path));
/* CIFSSMBNotify(xid, pTcon, full_path, cifs_sb->local_nls);*/
}
FreeXid(xid); FreeXid(xid);
return rc; return rc;
} }
......
...@@ -81,6 +81,10 @@ cifs_open(struct inode *inode, struct file *file) ...@@ -81,6 +81,10 @@ cifs_open(struct inode *inode, struct file *file)
} }
full_path = build_path_from_dentry(file->f_dentry); full_path = build_path_from_dentry(file->f_dentry);
if(full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
cFYI(1, (" inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags,full_path)); cFYI(1, (" inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags,full_path));
if ((file->f_flags & O_ACCMODE) == O_RDONLY) if ((file->f_flags & O_ACCMODE) == O_RDONLY)
...@@ -150,8 +154,6 @@ cifs_open(struct inode *inode, struct file *file) ...@@ -150,8 +154,6 @@ cifs_open(struct inode *inode, struct file *file)
cFYI(1, ("cifs_open returned 0x%x ", rc)); cFYI(1, ("cifs_open returned 0x%x ", rc));
cFYI(1, ("oplock: %d ", oplock)); cFYI(1, ("oplock: %d ", oplock));
} else { } else {
if(file->private_data)
kfree(file->private_data);
file->private_data = file->private_data =
kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL); kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
if (file->private_data) { if (file->private_data) {
...@@ -286,6 +288,11 @@ static int cifs_reopen_file(struct inode *inode, struct file *file) ...@@ -286,6 +288,11 @@ static int cifs_reopen_file(struct inode *inode, struct file *file)
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(file->f_dentry); full_path = build_path_from_dentry(file->f_dentry);
if(full_path == NULL) {
up(&pCifsFile->fh_sem);
FreeXid(xid);
return -ENOMEM;
}
cFYI(1, (" inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags,full_path)); cFYI(1, (" inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags,full_path));
if ((file->f_flags & O_ACCMODE) == O_RDONLY) if ((file->f_flags & O_ACCMODE) == O_RDONLY)
...@@ -634,26 +641,22 @@ cifs_partialpagewrite(struct page *page,unsigned from, unsigned to) ...@@ -634,26 +641,22 @@ cifs_partialpagewrite(struct page *page,unsigned from, unsigned to)
int bytes_written = 0; int bytes_written = 0;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
struct inode *inode = page->mapping->host; struct inode *inode;
struct cifsInodeInfo *cifsInode; struct cifsInodeInfo *cifsInode;
struct cifsFileInfo *open_file = NULL; struct cifsFileInfo *open_file = NULL;
struct list_head *tmp; struct list_head *tmp;
struct list_head *tmp1; struct list_head *tmp1;
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;
/* figure out which file struct to use
if (file->private_data == NULL) {
return -EBADF;
}
*/
if (!mapping) { if (!mapping) {
return -EFAULT; return -EFAULT;
} else if(!mapping->host) { } else if(!mapping->host) {
return -EFAULT; return -EFAULT;
} }
inode = page->mapping->host;
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;
offset += (loff_t)from; offset += (loff_t)from;
write_data = kmap(page); write_data = kmap(page);
write_data += from; write_data += from;
......
...@@ -346,7 +346,10 @@ cifs_unlink(struct inode *inode, struct dentry *direntry) ...@@ -346,7 +346,10 @@ cifs_unlink(struct inode *inode, struct dentry *direntry)
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if(full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls); rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls);
if (!rc) { if (!rc) {
...@@ -428,6 +431,10 @@ cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) ...@@ -428,6 +431,10 @@ cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if(full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
/* BB add setting the equivalent of mode via CreateX w/ACLs */ /* BB add setting the equivalent of mode via CreateX w/ACLs */
rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls); rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls);
if (rc) { if (rc) {
...@@ -481,6 +488,10 @@ cifs_rmdir(struct inode *inode, struct dentry *direntry) ...@@ -481,6 +488,10 @@ cifs_rmdir(struct inode *inode, struct dentry *direntry)
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if(full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls); rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls);
...@@ -527,6 +538,10 @@ cifs_rename(struct inode *source_inode, struct dentry *source_direntry, ...@@ -527,6 +538,10 @@ cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
fromName = build_path_from_dentry(source_direntry); fromName = build_path_from_dentry(source_direntry);
toName = build_path_from_dentry(target_direntry); toName = build_path_from_dentry(target_direntry);
if((fromName == NULL) || (toName == NULL)) {
rc = -ENOMEM;
goto cifs_rename_exit;
}
rc = CIFSSMBRename(xid, pTcon, fromName, toName, rc = CIFSSMBRename(xid, pTcon, fromName, toName,
cifs_sb_source->local_nls); cifs_sb_source->local_nls);
...@@ -549,6 +564,8 @@ cifs_rename(struct inode *source_inode, struct dentry *source_direntry, ...@@ -549,6 +564,8 @@ cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
CIFSSMBClose(xid, pTcon, netfid); CIFSSMBClose(xid, pTcon, netfid);
} }
} }
cifs_rename_exit:
if (fromName) if (fromName)
kfree(fromName); kfree(fromName);
if (toName) if (toName)
...@@ -587,6 +604,10 @@ cifs_revalidate(struct dentry *direntry) ...@@ -587,6 +604,10 @@ cifs_revalidate(struct dentry *direntry)
cifs_sb = CIFS_SB(direntry->d_sb); cifs_sb = CIFS_SB(direntry->d_sb);
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if(full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
cFYI(1, cFYI(1,
("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld", ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld",
full_path, direntry->d_inode, full_path, direntry->d_inode,
...@@ -731,6 +752,10 @@ cifs_setattr(struct dentry *direntry, struct iattr *attrs) ...@@ -731,6 +752,10 @@ cifs_setattr(struct dentry *direntry, struct iattr *attrs)
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if(full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
cifsInode = CIFS_I(direntry->d_inode); cifsInode = CIFS_I(direntry->d_inode);
/* BB check if we need to refresh inode from server now ? BB */ /* BB check if we need to refresh inode from server now ? BB */
......
...@@ -48,6 +48,11 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode, ...@@ -48,6 +48,11 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
fromName = build_path_from_dentry(old_file); fromName = build_path_from_dentry(old_file);
toName = build_path_from_dentry(direntry); toName = build_path_from_dentry(direntry);
if((fromName == NULL) || (toName == NULL)) {
rc = -ENOMEM;
goto cifs_hl_exit;
}
if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX) if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX)
rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName, rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName,
cifs_sb_target->local_nls); cifs_sb_target->local_nls);
...@@ -70,6 +75,7 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode, ...@@ -70,6 +75,7 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
cifsInode = CIFS_I(old_file->d_inode); cifsInode = CIFS_I(old_file->d_inode);
cifsInode->time = 0; /* will force revalidate to go get info when needed */ cifsInode->time = 0; /* will force revalidate to go get info when needed */
cifs_hl_exit:
if (fromName) if (fromName)
kfree(fromName); kfree(fromName);
if (toName) if (toName)
...@@ -91,6 +97,10 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd) ...@@ -91,6 +97,10 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
xid = GetXid(); xid = GetXid();
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if(full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode)); cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode));
cifs_sb = CIFS_SB(inode->i_sb); cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
...@@ -150,6 +160,11 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) ...@@ -150,6 +160,11 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if(full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
cFYI(1, ("Full path: %s ", full_path)); cFYI(1, ("Full path: %s ", full_path));
cFYI(1, ("symname is %s", symname)); cFYI(1, ("symname is %s", symname));
...@@ -205,6 +220,11 @@ cifs_readlink(struct dentry *direntry, char *pBuffer, int buflen) ...@@ -205,6 +220,11 @@ cifs_readlink(struct dentry *direntry, char *pBuffer, int buflen)
cifs_sb = CIFS_SB(inode->i_sb); cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if(full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
cFYI(1, cFYI(1,
("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d", ("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d",
full_path, inode, pBuffer, buflen)); full_path, inode, pBuffer, buflen));
......
...@@ -187,22 +187,26 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -187,22 +187,26 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
return -EIO; return -EIO;
} }
/* make sure that we sign in the same order that we send on this socket
and avoid races inside tcp sendmsg code that could cause corruption
of smb data */
down(&ses->server->tcpSem);
if (ses->server->tcpStatus == CifsExiting) { if (ses->server->tcpStatus == CifsExiting) {
return -ENOENT; rc = -ENOENT;
goto out_unlock;
} else if (ses->server->tcpStatus == CifsNeedReconnect) { } else if (ses->server->tcpStatus == CifsNeedReconnect) {
cFYI(1,("tcp session dead - return to caller to retry")); cFYI(1,("tcp session dead - return to caller to retry"));
return -EAGAIN; rc = -EAGAIN;
goto out_unlock;
} else if (ses->status != CifsGood) { } else if (ses->status != CifsGood) {
/* check if SMB session is bad because we are setting it up */ /* check if SMB session is bad because we are setting it up */
if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
(in_buf->Command != SMB_COM_NEGOTIATE)) { (in_buf->Command != SMB_COM_NEGOTIATE)) {
return -EAGAIN; rc = -EAGAIN;
goto out_unlock;
} /* else ok - we are setting up session */ } /* else ok - we are setting up session */
} }
/* make sure that we sign in the same order that we send on this socket
and avoid races inside tcp sendmsg code that could cause corruption
of smb data */
down(&ses->server->tcpSem);
midQ = AllocMidQEntry(in_buf, ses); midQ = AllocMidQEntry(in_buf, ses);
if (midQ == NULL) { if (midQ == NULL) {
up(&ses->server->tcpSem); up(&ses->server->tcpSem);
...@@ -288,7 +292,6 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -288,7 +292,6 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
return rc; return rc;
} }
if (receive_len > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE) { if (receive_len > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE) {
cERROR(1, cERROR(1,
("Frame too large received. Length: %d Xid: %d", ("Frame too large received. Length: %d Xid: %d",
...@@ -342,4 +345,8 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -342,4 +345,8 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
- BB add background daemon to clean up Mid entries from - BB add background daemon to clean up Mid entries from
killed processes & test killing process with active mid */ killed processes & test killing process with active mid */
return rc; return rc;
out_unlock:
up(&ses->server->tcpSem);
return rc;
} }
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