aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/entry/syscalls/syscall_32.tbl2
-rw-r--r--arch/x86/entry/syscalls/syscall_64.tbl1
-rw-r--r--fs/fsopen.c57
-rw-r--r--include/linux/syscalls.h1
-rw-r--r--include/uapi/linux/mount.h8
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 @@
403389 i386 fsopen sys_fsopen __ia32_sys_fsopen 403389 i386 fsopen sys_fsopen __ia32_sys_fsopen
404390 i386 fsconfig sys_fsconfig __ia32_sys_fsconfig 404390 i386 fsconfig sys_fsconfig __ia32_sys_fsconfig
405391 i386 fsmount sys_fsmount __ia32_sys_fsmount 405391 i386 fsmount sys_fsmount __ia32_sys_fsmount
406# don't use number 392, add new calls at the end 406392 i386 fspick sys_fspick __ia32_sys_fspick
407393 i386 semget sys_semget __ia32_sys_semget 407393 i386 semget sys_semget __ia32_sys_semget
408394 i386 semctl sys_semctl __ia32_compat_sys_semctl 408394 i386 semctl sys_semctl __ia32_compat_sys_semctl
409395 i386 shmget sys_shmget __ia32_sys_shmget 409395 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 @@
348337 common fsopen __x64_sys_fsopen 348337 common fsopen __x64_sys_fsopen
349338 common fsconfig __x64_sys_fsconfig 349338 common fsconfig __x64_sys_fsconfig
350339 common fsmount __x64_sys_fsmount 350339 common fsmount __x64_sys_fsmount
351340 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
353424 common pidfd_send_signal __x64_sys_pidfd_send_signal 354424 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 */
162SYSCALL_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
208err_fc:
209 put_fs_context(fc);
210err_path:
211 path_put(&target);
212err:
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);
993asmlinkage long sys_fsconfig(int fs_fd, unsigned int cmd, const char __user *key, 993asmlinkage 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);
995asmlinkage long sys_fsmount(int fs_fd, unsigned int flags, unsigned int ms_flags); 995asmlinkage long sys_fsmount(int fs_fd, unsigned int flags, unsigned int ms_flags);
996asmlinkage long sys_fspick(int dfd, const char __user *path, unsigned int flags);
996asmlinkage long sys_pidfd_send_signal(int pidfd, int sig, 997asmlinkage 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 */
83enum fsconfig_command { 91enum fsconfig_command {