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:
  do_add_mount() should sanitize mnt_flags
  CIFS shouldn't make mountpoints shrinkable
  mnt_flags fixes in do_remount()
  attach_recursive_mnt() needs to hold vfsmount_lock over set_mnt_shared()
  may_umount() needs namespace_sem
  Fix configfs leak
  Fix the -ESTALE handling in do_filp_open()
  ecryptfs: Fix refcnt leak on ecryptfs_follow_link() error path
  Fix ACC_MODE() for real
  Unrot uml mconsole a bit
  hppfs: handle ->put_link()
  Kill 9p readlink()
  fix autofs/afs/etc. magic mountpoint breakage
  • Loading branch information
Linus Torvalds committed Jan 17, 2010
2 parents 3a5dd79 + 27d55f1 commit 7dc9c48
Show file tree
Hide file tree
Showing 11 changed files with 71 additions and 115 deletions.
49 changes: 18 additions & 31 deletions arch/um/drivers/mconsole_kern.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,61 +125,50 @@ void mconsole_log(struct mc_request *req)
void mconsole_proc(struct mc_request *req)
{
struct nameidata nd;
struct file_system_type *proc;
struct super_block *super;
struct vfsmount *mnt = current->nsproxy->pid_ns->proc_mnt;
struct file *file;
int n, err;
char *ptr = req->request.data, *buf;
mm_segment_t old_fs = get_fs();

ptr += strlen("proc");
ptr = skip_spaces(ptr);

proc = get_fs_type("proc");
if (proc == NULL) {
mconsole_reply(req, "procfs not registered", 1, 0);
err = vfs_path_lookup(mnt->mnt_root, mnt, ptr, LOOKUP_FOLLOW, &nd);
if (err) {
mconsole_reply(req, "Failed to look up file", 1, 0);
goto out;
}

super = (*proc->get_sb)(proc, 0, NULL, NULL);
put_filesystem(proc);
if (super == NULL) {
mconsole_reply(req, "Failed to get procfs superblock", 1, 0);
err = may_open(&nd.path, MAY_READ, FMODE_READ);
if (result) {
mconsole_reply(req, "Failed to open file", 1, 0);
path_put(&nd.path);
goto out;
}
up_write(&super->s_umount);

nd.path.dentry = super->s_root;
nd.path.mnt = NULL;
nd.flags = O_RDONLY + 1;
nd.last_type = LAST_ROOT;

/* START: it was experienced that the stability problems are closed
* if commenting out these two calls + the below read cycle. To
* make UML crash again, it was enough to readd either one.*/
err = link_path_walk(ptr, &nd);
if (err) {
mconsole_reply(req, "Failed to look up file", 1, 0);
goto out_kill;
}

file = dentry_open(nd.path.dentry, nd.path.mnt, O_RDONLY,
current_cred());
err = PTR_ERR(file);
if (IS_ERR(file)) {
mconsole_reply(req, "Failed to open file", 1, 0);
goto out_kill;
path_put(&nd.path);
goto out;
}
/*END*/

buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (buf == NULL) {
mconsole_reply(req, "Failed to allocate buffer", 1, 0);
goto out_fput;
}

if ((file->f_op != NULL) && (file->f_op->read != NULL)) {
if (file->f_op->read) {
do {
n = (*file->f_op->read)(file, buf, PAGE_SIZE - 1,
&file->f_pos);
loff_t pos;
set_fs(KERNEL_DS);
n = vfs_read(file, buf, PAGE_SIZE - 1, &pos);
file_pos_write(file, pos);
set_fs(old_fs);
if (n >= 0) {
buf[n] = '\0';
mconsole_reply(req, buf, 0, (n > 0));
Expand All @@ -197,8 +186,6 @@ void mconsole_proc(struct mc_request *req)
kfree(buf);
out_fput:
fput(file);
out_kill:
deactivate_super(super);
out: ;
}
#endif
Expand Down
41 changes: 1 addition & 40 deletions fs/9p/vfs_inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1000,44 +1000,6 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
return retval;
}

/**
* v9fs_vfs_readlink - read a symlink's location
* @dentry: dentry for symlink
* @buffer: buffer to load symlink location into
* @buflen: length of buffer
*
*/

static int v9fs_vfs_readlink(struct dentry *dentry, char __user * buffer,
int buflen)
{
int retval;
int ret;
char *link = __getname();

if (unlikely(!link))
return -ENOMEM;

if (buflen > PATH_MAX)
buflen = PATH_MAX;

P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_name.name,
dentry);

retval = v9fs_readlink(dentry, link, buflen);

if (retval > 0) {
if ((ret = copy_to_user(buffer, link, retval)) != 0) {
P9_DPRINTK(P9_DEBUG_ERROR,
"problem copying to user: %d\n", ret);
retval = ret;
}
}

__putname(link);
return retval;
}

/**
* v9fs_vfs_follow_link - follow a symlink path
* @dentry: dentry for symlink
Expand Down Expand Up @@ -1230,7 +1192,6 @@ static const struct inode_operations v9fs_dir_inode_operations_ext = {
.rmdir = v9fs_vfs_rmdir,
.mknod = v9fs_vfs_mknod,
.rename = v9fs_vfs_rename,
.readlink = v9fs_vfs_readlink,
.getattr = v9fs_vfs_getattr,
.setattr = v9fs_vfs_setattr,
};
Expand All @@ -1253,7 +1214,7 @@ static const struct inode_operations v9fs_file_inode_operations = {
};

static const struct inode_operations v9fs_symlink_inode_operations = {
.readlink = v9fs_vfs_readlink,
.readlink = generic_readlink,
.follow_link = v9fs_vfs_follow_link,
.put_link = v9fs_vfs_put_link,
.getattr = v9fs_vfs_getattr,
Expand Down
3 changes: 1 addition & 2 deletions fs/cifs/cifs_dfs_ref.c
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ static int add_mount_helper(struct vfsmount *newmnt, struct nameidata *nd,
int err;

mntget(newmnt);
err = do_add_mount(newmnt, &nd->path, nd->path.mnt->mnt_flags, mntlist);
err = do_add_mount(newmnt, &nd->path, nd->path.mnt->mnt_flags | MNT_SHRINKABLE, mntlist);
switch (err) {
case 0:
path_put(&nd->path);
Expand Down Expand Up @@ -371,7 +371,6 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
if (IS_ERR(mnt))
goto out_err;

nd->path.mnt->mnt_flags |= MNT_SHRINKABLE;
rc = add_mount_helper(mnt, nd, &cifs_dfs_automount_list);

out:
Expand Down
4 changes: 3 additions & 1 deletion fs/configfs/symlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,10 @@ static int get_target(const char *symname, struct path *path,
ret = -ENOENT;
path_put(path);
}
} else
} else {
ret = -EPERM;
path_put(path);
}
}

return ret;
Expand Down
24 changes: 12 additions & 12 deletions fs/ecryptfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -715,31 +715,31 @@ static void *ecryptfs_follow_link(struct dentry *dentry, struct nameidata *nd)
/* Released in ecryptfs_put_link(); only release here on error */
buf = kmalloc(len, GFP_KERNEL);
if (!buf) {
rc = -ENOMEM;
buf = ERR_PTR(-ENOMEM);
goto out;
}
old_fs = get_fs();
set_fs(get_ds());
rc = dentry->d_inode->i_op->readlink(dentry, (char __user *)buf, len);
set_fs(old_fs);
if (rc < 0)
goto out_free;
else
if (rc < 0) {
kfree(buf);
buf = ERR_PTR(rc);
} else
buf[rc] = '\0';
rc = 0;
nd_set_link(nd, buf);
goto out;
out_free:
kfree(buf);
out:
return ERR_PTR(rc);
nd_set_link(nd, buf);
return NULL;
}

static void
ecryptfs_put_link(struct dentry *dentry, struct nameidata *nd, void *ptr)
{
/* Free the char* */
kfree(nd_get_link(nd));
char *buf = nd_get_link(nd);
if (!IS_ERR(buf)) {
/* Free the char* */
kfree(buf);
}
}

/**
Expand Down
18 changes: 12 additions & 6 deletions fs/hppfs/hppfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -646,29 +646,35 @@ static const struct super_operations hppfs_sbops = {
static int hppfs_readlink(struct dentry *dentry, char __user *buffer,
int buflen)
{
struct dentry *proc_dentry;

proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry;
struct dentry *proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry;
return proc_dentry->d_inode->i_op->readlink(proc_dentry, buffer,
buflen);
}

static void *hppfs_follow_link(struct dentry *dentry, struct nameidata *nd)
{
struct dentry *proc_dentry;

proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry;
struct dentry *proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry;

return proc_dentry->d_inode->i_op->follow_link(proc_dentry, nd);
}

static void hppfs_put_link(struct dentry *dentry, struct nameidata *nd,
void *cookie)
{
struct dentry *proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry;

if (proc_dentry->d_inode->i_op->put_link)
proc_dentry->d_inode->i_op->put_link(proc_dentry, nd, cookie);
}

static const struct inode_operations hppfs_dir_iops = {
.lookup = hppfs_lookup,
};

static const struct inode_operations hppfs_link_iops = {
.readlink = hppfs_readlink,
.follow_link = hppfs_follow_link,
.put_link = hppfs_put_link,
};

static struct inode *get_inode(struct super_block *sb, struct dentry *dentry)
Expand Down
23 changes: 11 additions & 12 deletions fs/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,7 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata
dget(dentry);
}
mntget(path->mnt);
nd->last_type = LAST_BIND;
cookie = dentry->d_inode->i_op->follow_link(dentry, nd);
error = PTR_ERR(cookie);
if (!IS_ERR(cookie)) {
Expand Down Expand Up @@ -1603,11 +1604,12 @@ struct file *do_filp_open(int dfd, const char *pathname,
struct file *filp;
struct nameidata nd;
int error;
struct path path, save;
struct path path;
struct dentry *dir;
int count = 0;
int will_truncate;
int flag = open_to_namei_flags(open_flag);
int force_reval = 0;

/*
* O_SYNC is implemented as __O_SYNC|O_DSYNC. As many places only
Expand All @@ -1619,7 +1621,7 @@ struct file *do_filp_open(int dfd, const char *pathname,
open_flag |= O_DSYNC;

if (!acc_mode)
acc_mode = MAY_OPEN | ACC_MODE(flag);
acc_mode = MAY_OPEN | ACC_MODE(open_flag);

/* O_TRUNC implies we need access checks for write permissions */
if (flag & O_TRUNC)
Expand Down Expand Up @@ -1659,9 +1661,12 @@ struct file *do_filp_open(int dfd, const char *pathname,
/*
* Create - we need to know the parent.
*/
reval:
error = path_init(dfd, pathname, LOOKUP_PARENT, &nd);
if (error)
return ERR_PTR(error);
if (force_reval)
nd.flags |= LOOKUP_REVAL;
error = path_walk(pathname, &nd);
if (error) {
if (nd.root.mnt)
Expand Down Expand Up @@ -1853,17 +1858,7 @@ struct file *do_filp_open(int dfd, const char *pathname,
error = security_inode_follow_link(path.dentry, &nd);
if (error)
goto exit_dput;
save = nd.path;
path_get(&save);
error = __do_follow_link(&path, &nd);
if (error == -ESTALE) {
/* nd.path had been dropped */
nd.path = save;
path_get(&nd.path);
nd.flags |= LOOKUP_REVAL;
error = __do_follow_link(&path, &nd);
}
path_put(&save);
path_put(&path);
if (error) {
/* Does someone understand code flow here? Or it is only
Expand All @@ -1873,6 +1868,10 @@ struct file *do_filp_open(int dfd, const char *pathname,
release_open_intent(&nd);
if (nd.root.mnt)
path_put(&nd.root);
if (error == -ESTALE && !force_reval) {
force_reval = 1;
goto reval;
}
return ERR_PTR(error);
}
nd.flags &= ~LOOKUP_PARENT;
Expand Down
14 changes: 11 additions & 3 deletions fs/namespace.c
Original file line number Diff line number Diff line change
Expand Up @@ -965,10 +965,12 @@ EXPORT_SYMBOL(may_umount_tree);
int may_umount(struct vfsmount *mnt)
{
int ret = 1;
down_read(&namespace_sem);
spin_lock(&vfsmount_lock);
if (propagate_mount_busy(mnt, 2))
ret = 0;
spin_unlock(&vfsmount_lock);
up_read(&namespace_sem);
return ret;
}

Expand Down Expand Up @@ -1352,12 +1354,12 @@ static int attach_recursive_mnt(struct vfsmount *source_mnt,
if (err)
goto out_cleanup_ids;

spin_lock(&vfsmount_lock);

if (IS_MNT_SHARED(dest_mnt)) {
for (p = source_mnt; p; p = next_mnt(p, source_mnt))
set_mnt_shared(p);
}

spin_lock(&vfsmount_lock);
if (parent_path) {
detach_mnt(source_mnt, parent_path);
attach_mnt(source_mnt, path);
Expand Down Expand Up @@ -1534,8 +1536,12 @@ static int do_remount(struct path *path, int flags, int mnt_flags,
err = change_mount_flags(path->mnt, flags);
else
err = do_remount_sb(sb, flags, data, 0);
if (!err)
if (!err) {
spin_lock(&vfsmount_lock);
mnt_flags |= path->mnt->mnt_flags & MNT_PNODE_MASK;
path->mnt->mnt_flags = mnt_flags;
spin_unlock(&vfsmount_lock);
}
up_write(&sb->s_umount);
if (!err) {
security_sb_post_remount(path->mnt, flags, data);
Expand Down Expand Up @@ -1665,6 +1671,8 @@ int do_add_mount(struct vfsmount *newmnt, struct path *path,
{
int err;

mnt_flags &= ~(MNT_SHARED | MNT_WRITE_HOLD);

down_write(&namespace_sem);
/* Something was mounted here while we slept */
while (d_mountpoint(path->dentry) &&
Expand Down
1 change: 0 additions & 1 deletion fs/proc/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -1419,7 +1419,6 @@ static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
goto out;

error = PROC_I(inode)->op.proc_get_link(inode, &nd->path);
nd->last_type = LAST_BIND;
out:
return ERR_PTR(error);
}
Expand Down
Loading

0 comments on commit 7dc9c48

Please sign in to comment.