diff options
| -rw-r--r-- | arch/x86/entry/syscalls/syscall_32.tbl | 2 | ||||
| -rw-r--r-- | arch/x86/entry/syscalls/syscall_64.tbl | 1 | ||||
| -rw-r--r-- | fs/fsopen.c | 57 | ||||
| -rw-r--r-- | include/linux/syscalls.h | 1 | ||||
| -rw-r--r-- | include/uapi/linux/mount.h | 8 |
5 files changed, 68 insertions, 1 deletions
diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl index 5b5c9189c507..4cd5f982b1e5 100644 --- a/arch/x86/entry/syscalls/syscall_32.tbl +++ b/arch/x86/entry/syscalls/syscall_32.tbl | |||
| @@ -403,7 +403,7 @@ | |||
| 403 | 389 i386 fsopen sys_fsopen __ia32_sys_fsopen | 403 | 389 i386 fsopen sys_fsopen __ia32_sys_fsopen |
| 404 | 390 i386 fsconfig sys_fsconfig __ia32_sys_fsconfig | 404 | 390 i386 fsconfig sys_fsconfig __ia32_sys_fsconfig |
| 405 | 391 i386 fsmount sys_fsmount __ia32_sys_fsmount | 405 | 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 |
| 407 | 393 i386 semget sys_semget __ia32_sys_semget | 407 | 393 i386 semget sys_semget __ia32_sys_semget |
| 408 | 394 i386 semctl sys_semctl __ia32_compat_sys_semctl | 408 | 394 i386 semctl sys_semctl __ia32_compat_sys_semctl |
| 409 | 395 i386 shmget sys_shmget __ia32_sys_shmget | 409 | 395 i386 shmget sys_shmget __ia32_sys_shmget |
diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl index 984ad594bb2b..64ca0d06259a 100644 --- a/arch/x86/entry/syscalls/syscall_64.tbl +++ b/arch/x86/entry/syscalls/syscall_64.tbl | |||
| @@ -348,6 +348,7 @@ | |||
| 348 | 337 common fsopen __x64_sys_fsopen | 348 | 337 common fsopen __x64_sys_fsopen |
| 349 | 338 common fsconfig __x64_sys_fsconfig | 349 | 338 common fsconfig __x64_sys_fsconfig |
| 350 | 339 common fsmount __x64_sys_fsmount | 350 | 339 common fsmount __x64_sys_fsmount |
| 351 | 340 common fspick __x64_sys_fspick | ||
| 351 | # don't use numbers 387 through 423, add new calls after the last | 352 | # don't use numbers 387 through 423, add new calls after the last |
| 352 | # 'common' entry | 353 | # 'common' entry |
| 353 | 424 common pidfd_send_signal __x64_sys_pidfd_send_signal | 354 | 424 common pidfd_send_signal __x64_sys_pidfd_send_signal |
diff --git a/fs/fsopen.c b/fs/fsopen.c index 65cc2f68f994..3bb9c0c8cbcc 100644 --- a/fs/fsopen.c +++ b/fs/fsopen.c | |||
| @@ -157,6 +157,63 @@ err_fc: | |||
| 157 | } | 157 | } |
| 158 | 158 | ||
| 159 | /* | 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 | |||
| 216 | /* | ||
| 160 | * Check the state and apply the configuration. Note that this function is | 217 | * Check the state and apply the configuration. Note that this function is |
| 161 | * allowed to 'steal' the value by setting param->xxx to NULL before returning. | 218 | * allowed to 'steal' the value by setting param->xxx to NULL before returning. |
| 162 | */ | 219 | */ |
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 0e697f595278..e2870fe1be5b 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h | |||
| @@ -993,6 +993,7 @@ asmlinkage long sys_fsopen(const char __user *fs_name, unsigned int flags); | |||
| 993 | asmlinkage long sys_fsconfig(int fs_fd, unsigned int cmd, const char __user *key, | 993 | asmlinkage long sys_fsconfig(int fs_fd, unsigned int cmd, const char __user *key, |
| 994 | const void __user *value, int aux); | 994 | const void __user *value, int aux); |
| 995 | asmlinkage long sys_fsmount(int fs_fd, unsigned int flags, unsigned int ms_flags); | 995 | 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); | ||
| 996 | asmlinkage long sys_pidfd_send_signal(int pidfd, int sig, | 997 | asmlinkage long sys_pidfd_send_signal(int pidfd, int sig, |
| 997 | siginfo_t __user *info, | 998 | siginfo_t __user *info, |
| 998 | unsigned int flags); | 999 | unsigned int flags); |
diff --git a/include/uapi/linux/mount.h b/include/uapi/linux/mount.h index 3888d3b91dc5..96a0240f23fe 100644 --- a/include/uapi/linux/mount.h +++ b/include/uapi/linux/mount.h | |||
| @@ -78,6 +78,14 @@ | |||
| 78 | #define FSOPEN_CLOEXEC 0x00000001 | 78 | #define FSOPEN_CLOEXEC 0x00000001 |
| 79 | 79 | ||
| 80 | /* | 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 | |||
| 88 | /* | ||
| 81 | * The type of fsconfig() call made. | 89 | * The type of fsconfig() call made. |
| 82 | */ | 90 | */ |
| 83 | enum fsconfig_command { | 91 | enum fsconfig_command { |
