Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/viro/vfs-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6:
  [PATCH] get rid of __exit_files(), __exit_fs() and __put_fs_struct()
  [PATCH] proc_readfd_common() race fix
  [PATCH] double-free of inode on alloc_file() failure exit in create_write_pipe()
  [PATCH] teach seq_file to discard entries
  [PATCH] umount_tree() will unhash everything itself
  [PATCH] get rid of more nameidata passing in namespace.c
  [PATCH] switch a bunch of LSM hooks from nameidata to path
  [PATCH] lock exclusively in collect_mounts() and drop_collected_mounts()
  [PATCH] move a bunch of declarations to fs/internal.h
  • Loading branch information
Linus Torvalds committed Apr 23, 2008
2 parents 934b702 + 1ec7f1d commit 94bc891
Show file tree
Hide file tree
Showing 18 changed files with 118 additions and 120 deletions.
11 changes: 11 additions & 0 deletions fs/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,14 @@ extern void __init chrdev_init(void);
* namespace.c
*/
extern int copy_mount_options(const void __user *, unsigned long *);

extern void free_vfsmnt(struct vfsmount *);
extern struct vfsmount *alloc_vfsmnt(const char *);
extern struct vfsmount *__lookup_mnt(struct vfsmount *, struct dentry *, int);
extern void mnt_set_mountpoint(struct vfsmount *, struct dentry *,
struct vfsmount *);
extern void release_mounts(struct list_head *);
extern void umount_tree(struct vfsmount *, int, struct list_head *);
extern struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int);

extern void __init mnt_init(void);
66 changes: 32 additions & 34 deletions fs/namespace.c
Original file line number Diff line number Diff line change
Expand Up @@ -1091,20 +1091,20 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry,
struct vfsmount *collect_mounts(struct vfsmount *mnt, struct dentry *dentry)
{
struct vfsmount *tree;
down_read(&namespace_sem);
down_write(&namespace_sem);
tree = copy_tree(mnt, dentry, CL_COPY_ALL | CL_PRIVATE);
up_read(&namespace_sem);
up_write(&namespace_sem);
return tree;
}

void drop_collected_mounts(struct vfsmount *mnt)
{
LIST_HEAD(umount_list);
down_read(&namespace_sem);
down_write(&namespace_sem);
spin_lock(&vfsmount_lock);
umount_tree(mnt, 0, &umount_list);
spin_unlock(&vfsmount_lock);
up_read(&namespace_sem);
up_write(&namespace_sem);
release_mounts(&umount_list);
}

Expand Down Expand Up @@ -1205,32 +1205,32 @@ static int attach_recursive_mnt(struct vfsmount *source_mnt,
return 0;
}

static int graft_tree(struct vfsmount *mnt, struct nameidata *nd)
static int graft_tree(struct vfsmount *mnt, struct path *path)
{
int err;
if (mnt->mnt_sb->s_flags & MS_NOUSER)
return -EINVAL;

if (S_ISDIR(nd->path.dentry->d_inode->i_mode) !=
if (S_ISDIR(path->dentry->d_inode->i_mode) !=
S_ISDIR(mnt->mnt_root->d_inode->i_mode))
return -ENOTDIR;

err = -ENOENT;
mutex_lock(&nd->path.dentry->d_inode->i_mutex);
if (IS_DEADDIR(nd->path.dentry->d_inode))
mutex_lock(&path->dentry->d_inode->i_mutex);
if (IS_DEADDIR(path->dentry->d_inode))
goto out_unlock;

err = security_sb_check_sb(mnt, nd);
err = security_sb_check_sb(mnt, path);
if (err)
goto out_unlock;

err = -ENOENT;
if (IS_ROOT(nd->path.dentry) || !d_unhashed(nd->path.dentry))
err = attach_recursive_mnt(mnt, &nd->path, NULL);
if (IS_ROOT(path->dentry) || !d_unhashed(path->dentry))
err = attach_recursive_mnt(mnt, path, NULL);
out_unlock:
mutex_unlock(&nd->path.dentry->d_inode->i_mutex);
mutex_unlock(&path->dentry->d_inode->i_mutex);
if (!err)
security_sb_post_addmount(mnt, nd);
security_sb_post_addmount(mnt, path);
return err;
}

Expand Down Expand Up @@ -1294,7 +1294,7 @@ static noinline int do_loopback(struct nameidata *nd, char *old_name,
if (!mnt)
goto out;

err = graft_tree(mnt, nd);
err = graft_tree(mnt, &nd->path);
if (err) {
LIST_HEAD(umount_list);
spin_lock(&vfsmount_lock);
Expand Down Expand Up @@ -1501,7 +1501,7 @@ int do_add_mount(struct vfsmount *newmnt, struct nameidata *nd,
goto unlock;

newmnt->mnt_flags = mnt_flags;
if ((err = graft_tree(newmnt, nd)))
if ((err = graft_tree(newmnt, &nd->path)))
goto unlock;

if (fslist) /* add to the specified expiration list */
Expand Down Expand Up @@ -1746,7 +1746,8 @@ long do_mount(char *dev_name, char *dir_name, char *type_page,
if (retval)
return retval;

retval = security_sb_mount(dev_name, &nd, type_page, flags, data_page);
retval = security_sb_mount(dev_name, &nd.path,
type_page, flags, data_page);
if (retval)
goto dput_out;

Expand Down Expand Up @@ -1986,15 +1987,13 @@ asmlinkage long sys_pivot_root(const char __user * new_root,
const char __user * put_old)
{
struct vfsmount *tmp;
struct nameidata new_nd, old_nd, user_nd;
struct path parent_path, root_parent;
struct nameidata new_nd, old_nd;
struct path parent_path, root_parent, root;
int error;

if (!capable(CAP_SYS_ADMIN))
return -EPERM;

lock_kernel();

error = __user_walk(new_root, LOOKUP_FOLLOW | LOOKUP_DIRECTORY,
&new_nd);
if (error)
Expand All @@ -2007,24 +2006,24 @@ asmlinkage long sys_pivot_root(const char __user * new_root,
if (error)
goto out1;

error = security_sb_pivotroot(&old_nd, &new_nd);
error = security_sb_pivotroot(&old_nd.path, &new_nd.path);
if (error) {
path_put(&old_nd.path);
goto out1;
}

read_lock(&current->fs->lock);
user_nd.path = current->fs->root;
root = current->fs->root;
path_get(&current->fs->root);
read_unlock(&current->fs->lock);
down_write(&namespace_sem);
mutex_lock(&old_nd.path.dentry->d_inode->i_mutex);
error = -EINVAL;
if (IS_MNT_SHARED(old_nd.path.mnt) ||
IS_MNT_SHARED(new_nd.path.mnt->mnt_parent) ||
IS_MNT_SHARED(user_nd.path.mnt->mnt_parent))
IS_MNT_SHARED(root.mnt->mnt_parent))
goto out2;
if (!check_mnt(user_nd.path.mnt))
if (!check_mnt(root.mnt))
goto out2;
error = -ENOENT;
if (IS_DEADDIR(new_nd.path.dentry->d_inode))
Expand All @@ -2034,13 +2033,13 @@ asmlinkage long sys_pivot_root(const char __user * new_root,
if (d_unhashed(old_nd.path.dentry) && !IS_ROOT(old_nd.path.dentry))
goto out2;
error = -EBUSY;
if (new_nd.path.mnt == user_nd.path.mnt ||
old_nd.path.mnt == user_nd.path.mnt)
if (new_nd.path.mnt == root.mnt ||
old_nd.path.mnt == root.mnt)
goto out2; /* loop, on the same file system */
error = -EINVAL;
if (user_nd.path.mnt->mnt_root != user_nd.path.dentry)
if (root.mnt->mnt_root != root.dentry)
goto out2; /* not a mountpoint */
if (user_nd.path.mnt->mnt_parent == user_nd.path.mnt)
if (root.mnt->mnt_parent == root.mnt)
goto out2; /* not attached */
if (new_nd.path.mnt->mnt_root != new_nd.path.dentry)
goto out2; /* not a mountpoint */
Expand All @@ -2062,27 +2061,26 @@ asmlinkage long sys_pivot_root(const char __user * new_root,
} else if (!is_subdir(old_nd.path.dentry, new_nd.path.dentry))
goto out3;
detach_mnt(new_nd.path.mnt, &parent_path);
detach_mnt(user_nd.path.mnt, &root_parent);
detach_mnt(root.mnt, &root_parent);
/* mount old root on put_old */
attach_mnt(user_nd.path.mnt, &old_nd.path);
attach_mnt(root.mnt, &old_nd.path);
/* mount new_root on / */
attach_mnt(new_nd.path.mnt, &root_parent);
touch_mnt_namespace(current->nsproxy->mnt_ns);
spin_unlock(&vfsmount_lock);
chroot_fs_refs(&user_nd.path, &new_nd.path);
security_sb_post_pivotroot(&user_nd, &new_nd);
chroot_fs_refs(&root, &new_nd.path);
security_sb_post_pivotroot(&root, &new_nd.path);
error = 0;
path_put(&root_parent);
path_put(&parent_path);
out2:
mutex_unlock(&old_nd.path.dentry->d_inode->i_mutex);
up_write(&namespace_sem);
path_put(&user_nd.path);
path_put(&root);
path_put(&old_nd.path);
out1:
path_put(&new_nd.path);
out0:
unlock_kernel();
return error;
out3:
spin_unlock(&vfsmount_lock);
Expand Down
3 changes: 3 additions & 0 deletions fs/pipe.c
Original file line number Diff line number Diff line change
Expand Up @@ -988,7 +988,10 @@ struct file *create_write_pipe(void)
return f;

err_dentry:
free_pipe_info(inode);
dput(dentry);
return ERR_PTR(err);

err_inode:
free_pipe_info(inode);
iput(inode);
Expand Down
4 changes: 2 additions & 2 deletions fs/pnode.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <linux/mnt_namespace.h>
#include <linux/mount.h>
#include <linux/fs.h>
#include "internal.h"
#include "pnode.h"

/* return the next shared peer mount of @p */
Expand Down Expand Up @@ -211,8 +212,7 @@ int propagate_mnt(struct vfsmount *dest_mnt, struct dentry *dest_dentry,
out:
spin_lock(&vfsmount_lock);
while (!list_empty(&tmp_list)) {
child = list_entry(tmp_list.next, struct vfsmount, mnt_hash);
list_del_init(&child->mnt_hash);
child = list_first_entry(&tmp_list, struct vfsmount, mnt_hash);
umount_tree(child, 0, &umount_list);
}
spin_unlock(&vfsmount_lock);
Expand Down
1 change: 1 addition & 0 deletions fs/pnode.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,5 @@ int propagate_mnt(struct vfsmount *, struct dentry *, struct vfsmount *,
struct list_head *);
int propagate_umount(struct list_head *);
int propagate_mount_busy(struct vfsmount *, int);
void mnt_release_group_id(struct vfsmount *);
#endif /* _LINUX_PNODE_H */
4 changes: 1 addition & 3 deletions fs/proc/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -1626,7 +1626,6 @@ static int proc_readfd_common(struct file * filp, void * dirent,
unsigned int fd, ino;
int retval;
struct files_struct * files;
struct fdtable *fdt;

retval = -ENOENT;
if (!p)
Expand All @@ -1649,9 +1648,8 @@ static int proc_readfd_common(struct file * filp, void * dirent,
if (!files)
goto out;
rcu_read_lock();
fdt = files_fdtable(files);
for (fd = filp->f_pos-2;
fd < fdt->max_fds;
fd < files_fdtable(files)->max_fds;
fd++, filp->f_pos++) {
char name[PROC_NUMBUF];
int len;
Expand Down
16 changes: 12 additions & 4 deletions fs/seq_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
* into the buffer. In case of error ->start() and ->next() return
* ERR_PTR(error). In the end of sequence they return %NULL. ->show()
* returns 0 in case of success and negative number in case of error.
* Returning SEQ_SKIP means "discard this element and move on".
*/
int seq_open(struct file *file, const struct seq_operations *op)
{
Expand Down Expand Up @@ -114,8 +115,10 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
if (!p || IS_ERR(p))
break;
err = m->op->show(m, p);
if (err)
if (err < 0)
break;
if (unlikely(err))
m->count = 0;
if (m->count < m->size)
goto Fill;
m->op->stop(m, p);
Expand All @@ -140,9 +143,10 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
break;
}
err = m->op->show(m, p);
if (err || m->count == m->size) {
if (m->count == m->size || err) {
m->count = offs;
break;
if (likely(err <= 0))
break;
}
pos = next;
}
Expand Down Expand Up @@ -199,8 +203,12 @@ static int traverse(struct seq_file *m, loff_t offset)
if (IS_ERR(p))
break;
error = m->op->show(m, p);
if (error)
if (error < 0)
break;
if (unlikely(error)) {
error = 0;
m->count = 0;
}
if (m->count == m->size)
goto Eoverflow;
if (pos + m->count > offset) {
Expand Down
1 change: 1 addition & 0 deletions fs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include <linux/mutex.h>
#include <linux/file.h>
#include <asm/uaccess.h>
#include "internal.h"


LIST_HEAD(super_blocks);
Expand Down
1 change: 0 additions & 1 deletion include/linux/dcache.h
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,6 @@ static inline int d_mountpoint(struct dentry *dentry)
}

extern struct vfsmount *lookup_mnt(struct vfsmount *, struct dentry *);
extern struct vfsmount *__lookup_mnt(struct vfsmount *, struct dentry *, int);
extern struct dentry *lookup_create(struct nameidata *nd, int is_dir);

extern int sysctl_vfs_cache_pressure;
Expand Down
6 changes: 0 additions & 6 deletions include/linux/fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,6 @@ struct vfsmount;

extern void __init inode_init(void);
extern void __init inode_init_early(void);
extern void __init mnt_init(void);
extern void __init files_init(unsigned long);

struct buffer_head;
Expand Down Expand Up @@ -1536,12 +1535,7 @@ extern struct vfsmount *kern_mount_data(struct file_system_type *, void *data);
#define kern_mount(type) kern_mount_data(type, NULL)
extern int may_umount_tree(struct vfsmount *);
extern int may_umount(struct vfsmount *);
extern void umount_tree(struct vfsmount *, int, struct list_head *);
extern void release_mounts(struct list_head *);
extern long do_mount(char *, char *, char *, unsigned long, void *);
extern struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int);
extern void mnt_set_mountpoint(struct vfsmount *, struct dentry *,
struct vfsmount *);
extern struct vfsmount *collect_mounts(struct vfsmount *, struct dentry *);
extern void drop_collected_mounts(struct vfsmount *);

Expand Down
2 changes: 0 additions & 2 deletions include/linux/mount.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,6 @@ static inline void mntput(struct vfsmount *mnt)
}
}

extern void free_vfsmnt(struct vfsmount *mnt);
extern struct vfsmount *alloc_vfsmnt(const char *name);
extern struct vfsmount *do_kern_mount(const char *fstype, int flags,
const char *name, void *data);

Expand Down
Loading

0 comments on commit 94bc891

Please sign in to comment.