Commit cf3cba4a authored by David Howells's avatar David Howells Committed by Al Viro

vfs: syscall: Add fspick() to select a superblock for reconfiguration

Provide an fspick() system call that can be used to pick an existing
mountpoint into an fs_context which can thereafter be used to reconfigure a
superblock (equivalent of the superblock side of -o remount).

This looks like:

	int fd = fspick(AT_FDCWD, "/mnt",
			FSPICK_CLOEXEC | FSPICK_NO_AUTOMOUNT);
	fsconfig(fd, FSCONFIG_SET_FLAG, "intr", NULL, 0);
	fsconfig(fd, FSCONFIG_SET_FLAG, "noac", NULL, 0);
	fsconfig(fd, FSCONFIG_CMD_RECONFIGURE, NULL, NULL, 0);

At the point of fspick being called, the file descriptor referring to the
filesystem context is in exactly the same state as the one that was created
by fsopen() after fsmount() has been successfully called.
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
cc: linux-api@vger.kernel.org
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 93766fbd
...@@ -403,7 +403,7 @@ ...@@ -403,7 +403,7 @@
389 i386 fsopen sys_fsopen __ia32_sys_fsopen 389 i386 fsopen sys_fsopen __ia32_sys_fsopen
390 i386 fsconfig sys_fsconfig __ia32_sys_fsconfig 390 i386 fsconfig sys_fsconfig __ia32_sys_fsconfig
391 i386 fsmount sys_fsmount __ia32_sys_fsmount 391 i386 fsmount sys_fsmount __ia32_sys_fsmount
# don't use number 392, add new calls at the end 392 i386 fspick sys_fspick __ia32_sys_fspick
393 i386 semget sys_semget __ia32_sys_semget 393 i386 semget sys_semget __ia32_sys_semget
394 i386 semctl sys_semctl __ia32_compat_sys_semctl 394 i386 semctl sys_semctl __ia32_compat_sys_semctl
395 i386 shmget sys_shmget __ia32_sys_shmget 395 i386 shmget sys_shmget __ia32_sys_shmget
......
...@@ -348,6 +348,7 @@ ...@@ -348,6 +348,7 @@
337 common fsopen __x64_sys_fsopen 337 common fsopen __x64_sys_fsopen
338 common fsconfig __x64_sys_fsconfig 338 common fsconfig __x64_sys_fsconfig
339 common fsmount __x64_sys_fsmount 339 common fsmount __x64_sys_fsmount
340 common fspick __x64_sys_fspick
# don't use numbers 387 through 423, add new calls after the last # don't use numbers 387 through 423, add new calls after the last
# 'common' entry # 'common' entry
424 common pidfd_send_signal __x64_sys_pidfd_send_signal 424 common pidfd_send_signal __x64_sys_pidfd_send_signal
......
...@@ -156,6 +156,63 @@ SYSCALL_DEFINE2(fsopen, const char __user *, _fs_name, unsigned int, flags) ...@@ -156,6 +156,63 @@ SYSCALL_DEFINE2(fsopen, const char __user *, _fs_name, unsigned int, flags)
return ret; return ret;
} }
/*
* Pick a superblock into a context for reconfiguration.
*/
SYSCALL_DEFINE3(fspick, int, dfd, const char __user *, path, unsigned int, flags)
{
struct fs_context *fc;
struct path target;
unsigned int lookup_flags;
int ret;
if (!ns_capable(current->nsproxy->mnt_ns->user_ns, CAP_SYS_ADMIN))
return -EPERM;
if ((flags & ~(FSPICK_CLOEXEC |
FSPICK_SYMLINK_NOFOLLOW |
FSPICK_NO_AUTOMOUNT |
FSPICK_EMPTY_PATH)) != 0)
return -EINVAL;
lookup_flags = LOOKUP_FOLLOW | LOOKUP_AUTOMOUNT;
if (flags & FSPICK_SYMLINK_NOFOLLOW)
lookup_flags &= ~LOOKUP_FOLLOW;
if (flags & FSPICK_NO_AUTOMOUNT)
lookup_flags &= ~LOOKUP_AUTOMOUNT;
if (flags & FSPICK_EMPTY_PATH)
lookup_flags |= LOOKUP_EMPTY;
ret = user_path_at(dfd, path, lookup_flags, &target);
if (ret < 0)
goto err;
ret = -EINVAL;
if (target.mnt->mnt_root != target.dentry)
goto err_path;
fc = fs_context_for_reconfigure(target.dentry, 0, 0);
if (IS_ERR(fc)) {
ret = PTR_ERR(fc);
goto err_path;
}
fc->phase = FS_CONTEXT_RECONF_PARAMS;
ret = fscontext_alloc_log(fc);
if (ret < 0)
goto err_fc;
path_put(&target);
return fscontext_create_fd(fc, flags & FSPICK_CLOEXEC ? O_CLOEXEC : 0);
err_fc:
put_fs_context(fc);
err_path:
path_put(&target);
err:
return ret;
}
/* /*
* Check the state and apply the configuration. Note that this function is * Check the state and apply the configuration. Note that this function is
* allowed to 'steal' the value by setting param->xxx to NULL before returning. * allowed to 'steal' the value by setting param->xxx to NULL before returning.
......
...@@ -993,6 +993,7 @@ asmlinkage long sys_fsopen(const char __user *fs_name, unsigned int flags); ...@@ -993,6 +993,7 @@ asmlinkage long sys_fsopen(const char __user *fs_name, unsigned int flags);
asmlinkage long sys_fsconfig(int fs_fd, unsigned int cmd, const char __user *key, asmlinkage long sys_fsconfig(int fs_fd, unsigned int cmd, const char __user *key,
const void __user *value, int aux); const void __user *value, int aux);
asmlinkage long sys_fsmount(int fs_fd, unsigned int flags, unsigned int ms_flags); asmlinkage long sys_fsmount(int fs_fd, unsigned int flags, unsigned int ms_flags);
asmlinkage long sys_fspick(int dfd, const char __user *path, unsigned int flags);
asmlinkage long sys_pidfd_send_signal(int pidfd, int sig, asmlinkage long sys_pidfd_send_signal(int pidfd, int sig,
siginfo_t __user *info, siginfo_t __user *info,
unsigned int flags); unsigned int flags);
......
...@@ -77,6 +77,14 @@ ...@@ -77,6 +77,14 @@
*/ */
#define FSOPEN_CLOEXEC 0x00000001 #define FSOPEN_CLOEXEC 0x00000001
/*
* fspick() flags.
*/
#define FSPICK_CLOEXEC 0x00000001
#define FSPICK_SYMLINK_NOFOLLOW 0x00000002
#define FSPICK_NO_AUTOMOUNT 0x00000004
#define FSPICK_EMPTY_PATH 0x00000008
/* /*
* The type of fsconfig() call made. * The type of fsconfig() call made.
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment