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)
namelen += (1 + temp->d_name.len);
temp = temp->d_parent;
}
namelen += 1; /* allow for trailing null */
full_path = kmalloc(namelen, GFP_KERNEL);
namelen--;
full_path = kmalloc(namelen+1, GFP_KERNEL);
if(full_path == NULL)
return full_path;
full_path[namelen] = 0; /* trailing null */
for (temp = direntry; !IS_ROOT(temp);) {
namelen -= 1 + temp->d_name.len;
if (namelen < 0) {
......@@ -142,10 +144,12 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(direntry);
if(full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
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) {
if ((nd->intent.open.flags & O_ACCMODE) == O_RDONLY)
desiredAccess = GENERIC_READ;
else if ((nd->intent.open.flags & O_ACCMODE) == O_WRONLY)
......@@ -173,6 +177,12 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
oplock = REQ_OPLOCK;
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,
desiredAccess, CREATE_NOT_DIR,
&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
pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(direntry);
if (pTcon->ses->capabilities & CAP_UNIX) {
if(full_path == NULL)
rc = -ENOMEM;
if (full_path && (pTcon->ses->capabilities & CAP_UNIX)) {
rc = CIFSSMBUnixSetPerms(xid, pTcon,
full_path, mode, current->euid, current->egid,
device_number, cifs_sb->local_nls);
......@@ -298,7 +310,8 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t dev
struct dentry *
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 cifsTconInfo *pTcon;
struct inode *newInode = NULL;
......@@ -321,6 +334,11 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(direntry);
if(full_path == NULL) {
FreeXid(xid);
return ERR_PTR(-ENOMEM);
}
if (direntry->d_inode != NULL) {
cFYI(1, (" non-NULL inode in lookup"));
} else {
......@@ -347,10 +365,10 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
rc = 0;
d_add(direntry, NULL);
} else {
cERROR(1,
("Error 0x%x or (%d decimal) on cifs_get_inode_info in lookup",
rc, 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 */
cERROR(1,("Error 0x%x or on cifs_get_inode_info in lookup",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 (full_path)
......
......@@ -40,8 +40,13 @@ int cifs_directory_notify(unsigned long arg, struct file * file)
cifs_sb = CIFS_SB(file->f_dentry->d_sb);
pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(file->f_dentry);
cFYI(1,("cifs dir notify on file %s",full_path));
/* CIFSSMBNotify */
if(full_path == NULL) {
rc = -ENOMEM;
} else {
cFYI(1,("cifs dir notify on file %s",full_path));
/* CIFSSMBNotify(xid, pTcon, full_path, cifs_sb->local_nls);*/
}
FreeXid(xid);
return rc;
}
......
......@@ -81,6 +81,10 @@ cifs_open(struct inode *inode, struct file *file)
}
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));
if ((file->f_flags & O_ACCMODE) == O_RDONLY)
......@@ -150,8 +154,6 @@ cifs_open(struct inode *inode, struct file *file)
cFYI(1, ("cifs_open returned 0x%x ", rc));
cFYI(1, ("oplock: %d ", oplock));
} else {
if(file->private_data)
kfree(file->private_data);
file->private_data =
kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
if (file->private_data) {
......@@ -286,6 +288,11 @@ static int cifs_reopen_file(struct inode *inode, struct file *file)
pTcon = cifs_sb->tcon;
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));
if ((file->f_flags & O_ACCMODE) == O_RDONLY)
......@@ -634,26 +641,22 @@ cifs_partialpagewrite(struct page *page,unsigned from, unsigned to)
int bytes_written = 0;
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
struct inode *inode = page->mapping->host;
struct inode *inode;
struct cifsInodeInfo *cifsInode;
struct cifsFileInfo *open_file = NULL;
struct list_head *tmp;
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) {
return -EFAULT;
} else if(!mapping->host) {
return -EFAULT;
}
inode = page->mapping->host;
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;
offset += (loff_t)from;
write_data = kmap(page);
write_data += from;
......
......@@ -346,7 +346,10 @@ cifs_unlink(struct inode *inode, struct dentry *direntry)
pTcon = cifs_sb->tcon;
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);
if (!rc) {
......@@ -428,6 +431,10 @@ cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
pTcon = cifs_sb->tcon;
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 */
rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls);
if (rc) {
......@@ -481,6 +488,10 @@ cifs_rmdir(struct inode *inode, struct dentry *direntry)
pTcon = cifs_sb->tcon;
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);
......@@ -527,6 +538,10 @@ cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
fromName = build_path_from_dentry(source_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,
cifs_sb_source->local_nls);
......@@ -549,6 +564,8 @@ cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
CIFSSMBClose(xid, pTcon, netfid);
}
}
cifs_rename_exit:
if (fromName)
kfree(fromName);
if (toName)
......@@ -587,6 +604,10 @@ cifs_revalidate(struct dentry *direntry)
cifs_sb = CIFS_SB(direntry->d_sb);
full_path = build_path_from_dentry(direntry);
if(full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
cFYI(1,
("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld",
full_path, direntry->d_inode,
......@@ -731,6 +752,10 @@ cifs_setattr(struct dentry *direntry, struct iattr *attrs)
pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(direntry);
if(full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
cifsInode = CIFS_I(direntry->d_inode);
/* 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,
fromName = build_path_from_dentry(old_file);
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)
rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName,
cifs_sb_target->local_nls);
......@@ -70,6 +75,7 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
cifsInode = CIFS_I(old_file->d_inode);
cifsInode->time = 0; /* will force revalidate to go get info when needed */
cifs_hl_exit:
if (fromName)
kfree(fromName);
if (toName)
......@@ -91,6 +97,10 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
xid = GetXid();
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));
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;
......@@ -150,6 +160,11 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(direntry);
if(full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
cFYI(1, ("Full path: %s ", full_path));
cFYI(1, ("symname is %s", symname));
......@@ -205,6 +220,11 @@ cifs_readlink(struct dentry *direntry, char *pBuffer, int buflen)
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(direntry);
if(full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
cFYI(1,
("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d",
full_path, inode, pBuffer, buflen));
......
......@@ -187,22 +187,26 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
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) {
return -ENOENT;
rc = -ENOENT;
goto out_unlock;
} else if (ses->server->tcpStatus == CifsNeedReconnect) {
cFYI(1,("tcp session dead - return to caller to retry"));
return -EAGAIN;
rc = -EAGAIN;
goto out_unlock;
} else if (ses->status != CifsGood) {
/* check if SMB session is bad because we are setting it up */
if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
(in_buf->Command != SMB_COM_NEGOTIATE)) {
return -EAGAIN;
rc = -EAGAIN;
goto out_unlock;
} /* 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);
if (midQ == NULL) {
up(&ses->server->tcpSem);
......@@ -288,7 +292,6 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
return rc;
}
if (receive_len > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE) {
cERROR(1,
("Frame too large received. Length: %d Xid: %d",
......@@ -342,4 +345,8 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
- BB add background daemon to clean up Mid entries from
killed processes & test killing process with active mid */
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