Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6: fs/dcache: allow d_obtain_alias() to return unhashed dentries Check for immutable/append flag in fallocate path sysctl: the include of rcupdate.h is only needed in the kernel fat: fix d_revalidate oopsen on NFS exports jfs: fix d_revalidate oopsen on NFS exports ocfs2: fix d_revalidate oopsen on NFS exports gfs2: fix d_revalidate oopsen on NFS exports fuse: fix d_revalidate oopsen on NFS exports ceph: fix d_revalidate oopsen on NFS exports reiserfs xattr ->d_revalidate() shouldn't care about RCU /proc/self is never going to be invalidated...
This commit is contained in:
commit
4afcc10a65
@ -993,7 +993,7 @@ static int ceph_d_revalidate(struct dentry *dentry, struct nameidata *nd)
|
||||
{
|
||||
struct inode *dir;
|
||||
|
||||
if (nd->flags & LOOKUP_RCU)
|
||||
if (nd && nd->flags & LOOKUP_RCU)
|
||||
return -ECHILD;
|
||||
|
||||
dir = dentry->d_parent->d_inode;
|
||||
|
26
fs/dcache.c
26
fs/dcache.c
@ -1523,6 +1523,28 @@ struct dentry * d_alloc_root(struct inode * root_inode)
|
||||
}
|
||||
EXPORT_SYMBOL(d_alloc_root);
|
||||
|
||||
static struct dentry * __d_find_any_alias(struct inode *inode)
|
||||
{
|
||||
struct dentry *alias;
|
||||
|
||||
if (list_empty(&inode->i_dentry))
|
||||
return NULL;
|
||||
alias = list_first_entry(&inode->i_dentry, struct dentry, d_alias);
|
||||
__dget(alias);
|
||||
return alias;
|
||||
}
|
||||
|
||||
static struct dentry * d_find_any_alias(struct inode *inode)
|
||||
{
|
||||
struct dentry *de;
|
||||
|
||||
spin_lock(&inode->i_lock);
|
||||
de = __d_find_any_alias(inode);
|
||||
spin_unlock(&inode->i_lock);
|
||||
return de;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* d_obtain_alias - find or allocate a dentry for a given inode
|
||||
* @inode: inode to allocate the dentry for
|
||||
@ -1552,7 +1574,7 @@ struct dentry *d_obtain_alias(struct inode *inode)
|
||||
if (IS_ERR(inode))
|
||||
return ERR_CAST(inode);
|
||||
|
||||
res = d_find_alias(inode);
|
||||
res = d_find_any_alias(inode);
|
||||
if (res)
|
||||
goto out_iput;
|
||||
|
||||
@ -1565,7 +1587,7 @@ struct dentry *d_obtain_alias(struct inode *inode)
|
||||
|
||||
|
||||
spin_lock(&inode->i_lock);
|
||||
res = __d_find_alias(inode, 0);
|
||||
res = __d_find_any_alias(inode);
|
||||
if (res) {
|
||||
spin_unlock(&inode->i_lock);
|
||||
dput(tmp);
|
||||
|
@ -43,7 +43,7 @@ static int vfat_revalidate_shortname(struct dentry *dentry)
|
||||
|
||||
static int vfat_revalidate(struct dentry *dentry, struct nameidata *nd)
|
||||
{
|
||||
if (nd->flags & LOOKUP_RCU)
|
||||
if (nd && nd->flags & LOOKUP_RCU)
|
||||
return -ECHILD;
|
||||
|
||||
/* This is not negative dentry. Always valid. */
|
||||
@ -54,7 +54,7 @@ static int vfat_revalidate(struct dentry *dentry, struct nameidata *nd)
|
||||
|
||||
static int vfat_revalidate_ci(struct dentry *dentry, struct nameidata *nd)
|
||||
{
|
||||
if (nd->flags & LOOKUP_RCU)
|
||||
if (nd && nd->flags & LOOKUP_RCU)
|
||||
return -ECHILD;
|
||||
|
||||
/*
|
||||
|
@ -158,7 +158,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
|
||||
{
|
||||
struct inode *inode;
|
||||
|
||||
if (nd->flags & LOOKUP_RCU)
|
||||
if (nd && nd->flags & LOOKUP_RCU)
|
||||
return -ECHILD;
|
||||
|
||||
inode = entry->d_inode;
|
||||
|
@ -44,7 +44,7 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd)
|
||||
int error;
|
||||
int had_lock = 0;
|
||||
|
||||
if (nd->flags & LOOKUP_RCU)
|
||||
if (nd && nd->flags & LOOKUP_RCU)
|
||||
return -ECHILD;
|
||||
|
||||
parent = dget_parent(dentry);
|
||||
|
@ -1600,7 +1600,7 @@ out:
|
||||
|
||||
static int jfs_ci_revalidate(struct dentry *dentry, struct nameidata *nd)
|
||||
{
|
||||
if (nd->flags & LOOKUP_RCU)
|
||||
if (nd && nd->flags & LOOKUP_RCU)
|
||||
return -ECHILD;
|
||||
/*
|
||||
* This is not negative dentry. Always valid.
|
||||
|
@ -56,7 +56,7 @@ static int ocfs2_dentry_revalidate(struct dentry *dentry,
|
||||
int ret = 0; /* if all else fails, just return false */
|
||||
struct ocfs2_super *osb;
|
||||
|
||||
if (nd->flags & LOOKUP_RCU)
|
||||
if (nd && nd->flags & LOOKUP_RCU)
|
||||
return -ECHILD;
|
||||
|
||||
inode = dentry->d_inode;
|
||||
|
@ -233,6 +233,14 @@ int do_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
|
||||
|
||||
if (!(file->f_mode & FMODE_WRITE))
|
||||
return -EBADF;
|
||||
|
||||
/* It's not possible punch hole on append only file */
|
||||
if (mode & FALLOC_FL_PUNCH_HOLE && IS_APPEND(inode))
|
||||
return -EPERM;
|
||||
|
||||
if (IS_IMMUTABLE(inode))
|
||||
return -EPERM;
|
||||
|
||||
/*
|
||||
* Revalidate the write permissions, in case security policy has
|
||||
* changed since the files were opened.
|
||||
|
@ -2620,35 +2620,6 @@ static const struct pid_entry proc_base_stuff[] = {
|
||||
&proc_self_inode_operations, NULL, {}),
|
||||
};
|
||||
|
||||
/*
|
||||
* Exceptional case: normally we are not allowed to unhash a busy
|
||||
* directory. In this case, however, we can do it - no aliasing problems
|
||||
* due to the way we treat inodes.
|
||||
*/
|
||||
static int proc_base_revalidate(struct dentry *dentry, struct nameidata *nd)
|
||||
{
|
||||
struct inode *inode;
|
||||
struct task_struct *task;
|
||||
|
||||
if (nd->flags & LOOKUP_RCU)
|
||||
return -ECHILD;
|
||||
|
||||
inode = dentry->d_inode;
|
||||
task = get_proc_task(inode);
|
||||
if (task) {
|
||||
put_task_struct(task);
|
||||
return 1;
|
||||
}
|
||||
d_drop(dentry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dentry_operations proc_base_dentry_operations =
|
||||
{
|
||||
.d_revalidate = proc_base_revalidate,
|
||||
.d_delete = pid_delete_dentry,
|
||||
};
|
||||
|
||||
static struct dentry *proc_base_instantiate(struct inode *dir,
|
||||
struct dentry *dentry, struct task_struct *task, const void *ptr)
|
||||
{
|
||||
@ -2685,7 +2656,6 @@ static struct dentry *proc_base_instantiate(struct inode *dir,
|
||||
if (p->fop)
|
||||
inode->i_fop = p->fop;
|
||||
ei->op = p->op;
|
||||
d_set_d_op(dentry, &proc_base_dentry_operations);
|
||||
d_add(dentry, inode);
|
||||
error = NULL;
|
||||
out:
|
||||
|
@ -978,8 +978,6 @@ int reiserfs_permission(struct inode *inode, int mask, unsigned int flags)
|
||||
|
||||
static int xattr_hide_revalidate(struct dentry *dentry, struct nameidata *nd)
|
||||
{
|
||||
if (nd->flags & LOOKUP_RCU)
|
||||
return -ECHILD;
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user