Skip to content

Commit cf3cba4

Browse files
dhowellsAl Viro
authored andcommitted
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: David Howells <[email protected]> cc: [email protected] Signed-off-by: Al Viro <[email protected]>
1 parent 93766fb commit cf3cba4

File tree

5 files changed

+68
-1
lines changed

5 files changed

+68
-1
lines changed

arch/x86/entry/syscalls/syscall_32.tbl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@
403403
389 i386 fsopen sys_fsopen __ia32_sys_fsopen
404404
390 i386 fsconfig sys_fsconfig __ia32_sys_fsconfig
405405
391 i386 fsmount sys_fsmount __ia32_sys_fsmount
406-
# don't use number 392, add new calls at the end
406+
392 i386 fspick sys_fspick __ia32_sys_fspick
407407
393 i386 semget sys_semget __ia32_sys_semget
408408
394 i386 semctl sys_semctl __ia32_compat_sys_semctl
409409
395 i386 shmget sys_shmget __ia32_sys_shmget

arch/x86/entry/syscalls/syscall_64.tbl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,7 @@
348348
337 common fsopen __x64_sys_fsopen
349349
338 common fsconfig __x64_sys_fsconfig
350350
339 common fsmount __x64_sys_fsmount
351+
340 common fspick __x64_sys_fspick
351352
# don't use numbers 387 through 423, add new calls after the last
352353
# 'common' entry
353354
424 common pidfd_send_signal __x64_sys_pidfd_send_signal

fs/fsopen.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,63 @@ SYSCALL_DEFINE2(fsopen, const char __user *, _fs_name, unsigned int, flags)
156156
return ret;
157157
}
158158

159+
/*
160+
* Pick a superblock into a context for reconfiguration.
161+
*/
162+
SYSCALL_DEFINE3(fspick, int, dfd, const char __user *, path, unsigned int, flags)
163+
{
164+
struct fs_context *fc;
165+
struct path target;
166+
unsigned int lookup_flags;
167+
int ret;
168+
169+
if (!ns_capable(current->nsproxy->mnt_ns->user_ns, CAP_SYS_ADMIN))
170+
return -EPERM;
171+
172+
if ((flags & ~(FSPICK_CLOEXEC |
173+
FSPICK_SYMLINK_NOFOLLOW |
174+
FSPICK_NO_AUTOMOUNT |
175+
FSPICK_EMPTY_PATH)) != 0)
176+
return -EINVAL;
177+
178+
lookup_flags = LOOKUP_FOLLOW | LOOKUP_AUTOMOUNT;
179+
if (flags & FSPICK_SYMLINK_NOFOLLOW)
180+
lookup_flags &= ~LOOKUP_FOLLOW;
181+
if (flags & FSPICK_NO_AUTOMOUNT)
182+
lookup_flags &= ~LOOKUP_AUTOMOUNT;
183+
if (flags & FSPICK_EMPTY_PATH)
184+
lookup_flags |= LOOKUP_EMPTY;
185+
ret = user_path_at(dfd, path, lookup_flags, &target);
186+
if (ret < 0)
187+
goto err;
188+
189+
ret = -EINVAL;
190+
if (target.mnt->mnt_root != target.dentry)
191+
goto err_path;
192+
193+
fc = fs_context_for_reconfigure(target.dentry, 0, 0);
194+
if (IS_ERR(fc)) {
195+
ret = PTR_ERR(fc);
196+
goto err_path;
197+
}
198+
199+
fc->phase = FS_CONTEXT_RECONF_PARAMS;
200+
201+
ret = fscontext_alloc_log(fc);
202+
if (ret < 0)
203+
goto err_fc;
204+
205+
path_put(&target);
206+
return fscontext_create_fd(fc, flags & FSPICK_CLOEXEC ? O_CLOEXEC : 0);
207+
208+
err_fc:
209+
put_fs_context(fc);
210+
err_path:
211+
path_put(&target);
212+
err:
213+
return ret;
214+
}
215+
159216
/*
160217
* Check the state and apply the configuration. Note that this function is
161218
* allowed to 'steal' the value by setting param->xxx to NULL before returning.

include/linux/syscalls.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -993,6 +993,7 @@ asmlinkage long sys_fsopen(const char __user *fs_name, unsigned int flags);
993993
asmlinkage long sys_fsconfig(int fs_fd, unsigned int cmd, const char __user *key,
994994
const void __user *value, int aux);
995995
asmlinkage long sys_fsmount(int fs_fd, unsigned int flags, unsigned int ms_flags);
996+
asmlinkage long sys_fspick(int dfd, const char __user *path, unsigned int flags);
996997
asmlinkage long sys_pidfd_send_signal(int pidfd, int sig,
997998
siginfo_t __user *info,
998999
unsigned int flags);

include/uapi/linux/mount.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,14 @@
7777
*/
7878
#define FSOPEN_CLOEXEC 0x00000001
7979

80+
/*
81+
* fspick() flags.
82+
*/
83+
#define FSPICK_CLOEXEC 0x00000001
84+
#define FSPICK_SYMLINK_NOFOLLOW 0x00000002
85+
#define FSPICK_NO_AUTOMOUNT 0x00000004
86+
#define FSPICK_EMPTY_PATH 0x00000008
87+
8088
/*
8189
* The type of fsconfig() call made.
8290
*/

0 commit comments

Comments
 (0)