Message ID | 524f69650904171416y3807d6d2w7de57a711c5e5428@mail.gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Fri, 17 Apr 2009 16:16:23 -0500 Steve French <smfrench@gmail.com> wrote: > I merged this, adding the CC: stable, but think we need to also > consistently check for inode == NULL in cifs_unlink (we only check in > two branches now) > > Any objections if I also add the following check: > I think it would be preferable to just check once for inode==NULL in cifs_unlink near the top and BUG() if it is. Note that vfs_unlink takes the i_mutex on this before calling the .unlink inode op, so we're guaranteed that the d_inode won't be NULL from that codepath. I think if we get an unlink on a negative dentry then we should probably consider that a BUG(). Other .unlink ops also seem to assume that you can't call .unlink with a negative dentry.
On Fri, Apr 17, 2009 at 6:02 PM, Jeff Layton <jlayton@redhat.com> wrote: > On Fri, 17 Apr 2009 16:16:23 -0500 > Steve French <smfrench@gmail.com> wrote: > >> I merged this, adding the CC: stable, but think we need to also >> consistently check for inode == NULL in cifs_unlink (we only check in >> two branches now) >> >> Any objections if I also add the following check: >> > > I think it would be preferable to just check once for inode==NULL in > cifs_unlink near the top and BUG() if it is. Note that vfs_unlink takes > the i_mutex on this before calling the .unlink inode op, so we're > guaranteed that the d_inode won't be NULL from that codepath. > > I think if we get an unlink on a negative dentry then we should > probably consider that a BUG(). > > Other .unlink ops also seem to assume that you can't call .unlink with > a negative dentry. I am more worried about internal calls to unlink from cifs slipping through with inode null. If we check in one branch we should check in the other, or as you suggest move it to the top
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 09082ac..42572b7 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -968,7 +968,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) int xid; char *full_path = NULL; struct inode *inode = dentry->d_inode; - struct cifsInodeInfo *cifsInode = CIFS_I(inode); + struct cifsInodeInfo *cifs_inode; struct super_block *sb = dir->i_sb; struct cifs_sb_info *cifs_sb = CIFS_SB(sb); struct cifsTconInfo *tcon = cifs_sb->tcon; @@ -1012,7 +1012,7 @@ psx_del_no_retry: rc = cifs_rename_pending_delete(full_path, dentry, xid); if (rc == 0) drop_nlink(inode); - } else if (rc == -EACCES && dosattr == 0) { + } else if ((rc == -EACCES) && (dosattr == 0) && inode) { attrs = kzalloc(sizeof(*attrs), GFP_KERNEL); if (attrs == NULL) { rc = -ENOMEM; @@ -1020,7 +1020,8 @@ psx_del_no_retry: } /* try to reset dos attributes */ - origattr = cifsInode->cifsAttrs; + cifs_inode = CIFS_I(inode); + origattr = cifs_inode->cifsAttrs; if (origattr == 0) origattr |= ATTR_NORMAL; dosattr = origattr & ~ATTR_READONLY; @@ -1041,13 +1042,13 @@ psx_del_no_retry: out_reval: if (inode) { - cifsInode = CIFS_I(inode); - cifsInode->time = 0; /* will force revalidate to get info + cifs_inode = CIFS_I(inode); + cifs_inode->time = 0; /* will force revalidate to get info when needed */ inode->i_ctime = current_fs_time(sb); } dir->i_ctime = dir->i_mtime = current_fs_time(sb); - cifsInode = CIFS_I(dir); + cifs_inode = CIFS_I(dir); CIFS_I(dir)->time = 0; /* force revalidate of dir as well */ kfree(full_path);