Example #1
0
/*
 * Return the uid and gid of the last request for the mount
 *
 * When reconstructing an autofs mount tree with active mounts
 * we need to re-connect to mounts that may have used the original
 * process uid and gid (or string variations of them) for mount
 * lookups within the map entry.
 */
static int autofs_dev_ioctl_requester(struct file *fp,
				      struct autofs_sb_info *sbi,
				      struct autofs_dev_ioctl *param)
{
	struct autofs_info *ino;
	struct nameidata nd;
	const char *path;
	dev_t devid;
	int err = -ENOENT;

	if (param->size <= sizeof(*param)) {
		err = -EINVAL;
		goto out;
	}

	path = param->path;
	devid = sbi->sb->s_dev;

	param->arg1 = param->arg2 = -1;

	/* Get nameidata of the parent directory */
	err = path_lookup(path, LOOKUP_PARENT, &nd);
	if (err)
		goto out;

	err = autofs_dev_ioctl_find_super(&nd, devid);
	if (err)
		goto out_release;

	ino = autofs4_dentry_ino(nd.path.dentry);
	if (ino) {
		err = 0;
		autofs4_expire_wait(nd.path.dentry);
		spin_lock(&sbi->fs_lock);
		param->arg1 = ino->uid;
		param->arg2 = ino->gid;
		spin_unlock(&sbi->fs_lock);
	}

out_release:
	path_put(&nd.path);
out:
	return err;
}
/*
 * Open a file descriptor on the autofs mount point corresponding
 * to the given path and device number (aka. new_encode_dev(sb->s_dev)).
 */
static int autofs_dev_ioctl_open_mountpoint(const char *path, dev_t devid)
{
	struct file *filp;
	struct nameidata nd;
	int err, fd;

	fd = get_unused_fd();
	if (likely(fd >= 0)) {
		/* Get nameidata of the parent directory */
		err = path_lookup(path, LOOKUP_PARENT, &nd);
		if (err)
			goto out;

		/*
		 * Search down, within the parent, looking for an
		 * autofs super block that has the device number
		 * corresponding to the autofs fs we want to open.
		 */
		err = autofs_dev_ioctl_find_super(&nd, devid);
		if (err) {
			path_put(&nd.path);
			goto out;
		}

		filp = dentry_open(nd.path.dentry, nd.path.mnt, O_RDONLY,
				   current_cred());
		if (IS_ERR(filp)) {
			err = PTR_ERR(filp);
			goto out;
		}

		autofs_dev_ioctl_fd_install(fd, filp);
	}

	return fd;

out:
	put_unused_fd(fd);
	return err;
}
Example #3
0
/*
 * Check if the given path is a mountpoint.
 *
 * If we are supplied with the file descriptor of an autofs
 * mount we're looking for a specific mount. In this case
 * the path is considered a mountpoint if it is itself a
 * mountpoint or contains a mount, such as a multi-mount
 * without a root mount. In this case we return 1 if the
 * path is a mount point and the super magic of the covering
 * mount if there is one or 0 if it isn't a mountpoint.
 *
 * If we aren't supplied with a file descriptor then we
 * lookup the nameidata of the path and check if it is the
 * root of a mount. If a type is given we are looking for
 * a particular autofs mount and if we don't find a match
 * we return fail. If the located nameidata path is the
 * root of a mount we return 1 along with the super magic
 * of the mount or 0 otherwise.
 *
 * In both cases the the device number (as returned by
 * new_encode_dev()) is also returned.
 */
static int autofs_dev_ioctl_ismountpoint(struct file *fp,
					 struct autofs_sb_info *sbi,
					 struct autofs_dev_ioctl *param)
{
	struct nameidata nd;
	const char *path;
	unsigned int type;
	int err = -ENOENT;

	if (param->size <= sizeof(*param)) {
		err = -EINVAL;
		goto out;
	}

	path = param->path;
	type = param->arg1;

	param->arg1 = 0;
	param->arg2 = 0;

	if (!fp || param->ioctlfd == -1) {
		if (type == AUTOFS_TYPE_ANY) {
			struct super_block *sb;

			err = path_lookup(path, LOOKUP_FOLLOW, &nd);
			if (err)
				goto out;

			sb = nd.path.dentry->d_sb;
			param->arg1 = new_encode_dev(sb->s_dev);
		} else {
			struct autofs_info *ino;

			err = path_lookup(path, LOOKUP_PARENT, &nd);
			if (err)
				goto out;

			err = autofs_dev_ioctl_find_sbi_type(&nd, type);
			if (err)
				goto out_release;

			ino = autofs4_dentry_ino(nd.path.dentry);
			param->arg1 = autofs4_get_dev(ino->sbi);
		}

		err = 0;
		if (nd.path.dentry->d_inode &&
		    nd.path.mnt->mnt_root == nd.path.dentry) {
			err = 1;
			param->arg2 = nd.path.dentry->d_inode->i_sb->s_magic;
		}
	} else {
		dev_t devid = new_encode_dev(sbi->sb->s_dev);

		err = path_lookup(path, LOOKUP_PARENT, &nd);
		if (err)
			goto out;

		err = autofs_dev_ioctl_find_super(&nd, devid);
		if (err)
			goto out_release;

		param->arg1 = autofs4_get_dev(sbi);

		err = have_submounts(nd.path.dentry);

		if (nd.path.mnt->mnt_mountpoint != nd.path.mnt->mnt_root) {
			if (follow_down(&nd.path.mnt, &nd.path.dentry)) {
				struct inode *inode = nd.path.dentry->d_inode;
				param->arg2 = inode->i_sb->s_magic;
			}
		}
	}

out_release:
	path_put(&nd.path);
out:
	return err;
}