Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7dc9c484 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* '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
parents 3a5dd791 27d55f1f
Loading
Loading
Loading
Loading
+18 −31
Original line number Diff line number Diff line
@@ -125,50 +125,36 @@ 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) {
@@ -176,10 +162,13 @@ void mconsole_proc(struct mc_request *req)
		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));
@@ -197,8 +186,6 @@ void mconsole_proc(struct mc_request *req)
	kfree(buf);
 out_fput:
	fput(file);
 out_kill:
	deactivate_super(super);
 out: ;
}
#endif
+1 −40
Original line number Diff line number Diff line
@@ -1000,44 +1000,6 @@ done:
	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
@@ -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,
};
@@ -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,
+1 −2
Original line number Diff line number Diff line
@@ -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);
@@ -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:
+3 −1
Original line number Diff line number Diff line
@@ -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;
+12 −12
Original line number Diff line number Diff line
@@ -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
		buf[rc] = '\0';
	rc = 0;
	nd_set_link(nd, buf);
	goto out;
out_free:
	if (rc < 0) {
		kfree(buf);
		buf = ERR_PTR(rc);
	} else
		buf[rc] = '\0';
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)
{
	char *buf = nd_get_link(nd);
	if (!IS_ERR(buf)) {
		/* Free the char* */
	kfree(nd_get_link(nd));
		kfree(buf);
	}
}

/**
Loading