summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDominik Brodowski <linux@dominikbrodowski.net>2018-03-11 06:34:55 -0400
committerDominik Brodowski <linux@dominikbrodowski.net>2018-04-02 14:15:59 -0400
commit55731b3cda3a85ee888dac3bf1f36489f275c187 (patch)
treea322dc9efdd89932a35b294d221f90eccad45f23
parentcbfe20f565228966f0249f016752437df95df679 (diff)
fs: add do_fchownat(), ksys_fchown() helpers and ksys_{,l}chown() wrappers
Using the fs-interal do_fchownat() wrapper allows us to get rid of fs-internal calls to the sys_fchownat() syscall. Introducing the ksys_fchown() helper and the ksys_{,}chown() wrappers allows us to avoid the in-kernel calls to the sys_{,l,f}chown() syscalls. The ksys_ prefix denotes that these functions are meant as a drop-in replacement for the syscalls. In particular, they use the same calling convention as sys_{,l,f}chown(). This patch is part of a series which removes in-kernel calls to syscalls. On this basis, the syscall entry path can be streamlined. For details, see http://lkml.kernel.org/r/20180325162527.GA17492@light.dominikbrodowski.net Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
-rw-r--r--arch/s390/kernel/compat_linux.c6
-rw-r--r--fs/internal.h2
-rw-r--r--fs/open.c23
-rw-r--r--include/linux/syscalls.h17
-rw-r--r--init/initramfs.c8
-rw-r--r--kernel/uid16.c6
6 files changed, 46 insertions, 16 deletions
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
index 5a9cfde5fc28..9a9bb395359c 100644
--- a/arch/s390/kernel/compat_linux.c
+++ b/arch/s390/kernel/compat_linux.c
@@ -89,18 +89,18 @@
89COMPAT_SYSCALL_DEFINE3(s390_chown16, const char __user *, filename, 89COMPAT_SYSCALL_DEFINE3(s390_chown16, const char __user *, filename,
90 u16, user, u16, group) 90 u16, user, u16, group)
91{ 91{
92 return sys_chown(filename, low2highuid(user), low2highgid(group)); 92 return ksys_chown(filename, low2highuid(user), low2highgid(group));
93} 93}
94 94
95COMPAT_SYSCALL_DEFINE3(s390_lchown16, const char __user *, 95COMPAT_SYSCALL_DEFINE3(s390_lchown16, const char __user *,
96 filename, u16, user, u16, group) 96 filename, u16, user, u16, group)
97{ 97{
98 return sys_lchown(filename, low2highuid(user), low2highgid(group)); 98 return ksys_lchown(filename, low2highuid(user), low2highgid(group));
99} 99}
100 100
101COMPAT_SYSCALL_DEFINE3(s390_fchown16, unsigned int, fd, u16, user, u16, group) 101COMPAT_SYSCALL_DEFINE3(s390_fchown16, unsigned int, fd, u16, user, u16, group)
102{ 102{
103 return sys_fchown(fd, low2highuid(user), low2highgid(group)); 103 return ksys_fchown(fd, low2highuid(user), low2highgid(group));
104} 104}
105 105
106COMPAT_SYSCALL_DEFINE2(s390_setregid16, u16, rgid, u16, egid) 106COMPAT_SYSCALL_DEFINE2(s390_setregid16, u16, rgid, u16, egid)
diff --git a/fs/internal.h b/fs/internal.h
index 26f4f05b52ef..c797480cbd6f 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -121,6 +121,8 @@ extern struct file *do_file_open_root(struct dentry *, struct vfsmount *,
121 121
122long do_faccessat(int dfd, const char __user *filename, int mode); 122long do_faccessat(int dfd, const char __user *filename, int mode);
123int do_fchmodat(int dfd, const char __user *filename, umode_t mode); 123int do_fchmodat(int dfd, const char __user *filename, umode_t mode);
124int do_fchownat(int dfd, const char __user *filename, uid_t user, gid_t group,
125 int flag);
124 126
125extern int open_check_o_direct(struct file *f); 127extern int open_check_o_direct(struct file *f);
126extern int vfs_open(const struct path *, struct file *, const struct cred *); 128extern int vfs_open(const struct path *, struct file *, const struct cred *);
diff --git a/fs/open.c b/fs/open.c
index 0fc8188be31a..7b2eccb541f2 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -645,8 +645,8 @@ retry_deleg:
645 return error; 645 return error;
646} 646}
647 647
648SYSCALL_DEFINE5(fchownat, int, dfd, const char __user *, filename, uid_t, user, 648int do_fchownat(int dfd, const char __user *filename, uid_t user, gid_t group,
649 gid_t, group, int, flag) 649 int flag)
650{ 650{
651 struct path path; 651 struct path path;
652 int error = -EINVAL; 652 int error = -EINVAL;
@@ -677,18 +677,24 @@ out:
677 return error; 677 return error;
678} 678}
679 679
680SYSCALL_DEFINE5(fchownat, int, dfd, const char __user *, filename, uid_t, user,
681 gid_t, group, int, flag)
682{
683 return do_fchownat(dfd, filename, user, group, flag);
684}
685
680SYSCALL_DEFINE3(chown, const char __user *, filename, uid_t, user, gid_t, group) 686SYSCALL_DEFINE3(chown, const char __user *, filename, uid_t, user, gid_t, group)
681{ 687{
682 return sys_fchownat(AT_FDCWD, filename, user, group, 0); 688 return do_fchownat(AT_FDCWD, filename, user, group, 0);
683} 689}
684 690
685SYSCALL_DEFINE3(lchown, const char __user *, filename, uid_t, user, gid_t, group) 691SYSCALL_DEFINE3(lchown, const char __user *, filename, uid_t, user, gid_t, group)
686{ 692{
687 return sys_fchownat(AT_FDCWD, filename, user, group, 693 return do_fchownat(AT_FDCWD, filename, user, group,
688 AT_SYMLINK_NOFOLLOW); 694 AT_SYMLINK_NOFOLLOW);
689} 695}
690 696
691SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group) 697int ksys_fchown(unsigned int fd, uid_t user, gid_t group)
692{ 698{
693 struct fd f = fdget(fd); 699 struct fd f = fdget(fd);
694 int error = -EBADF; 700 int error = -EBADF;
@@ -708,6 +714,11 @@ out:
708 return error; 714 return error;
709} 715}
710 716
717SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group)
718{
719 return ksys_fchown(fd, user, group);
720}
721
711int open_check_o_direct(struct file *f) 722int open_check_o_direct(struct file *f)
712{ 723{
713 /* NB: we're sure to have correct a_ops only after f_op->open */ 724 /* NB: we're sure to have correct a_ops only after f_op->open */
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 33f06de090ea..df0d1e818a6e 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -954,6 +954,7 @@ int ksys_chroot(const char __user *filename);
954ssize_t ksys_write(unsigned int fd, const char __user *buf, size_t count); 954ssize_t ksys_write(unsigned int fd, const char __user *buf, size_t count);
955int ksys_chdir(const char __user *filename); 955int ksys_chdir(const char __user *filename);
956int ksys_fchmod(unsigned int fd, umode_t mode); 956int ksys_fchmod(unsigned int fd, umode_t mode);
957int ksys_fchown(unsigned int fd, uid_t user, gid_t group);
957 958
958/* 959/*
959 * The following kernel syscall equivalents are just wrappers to fs-internal 960 * The following kernel syscall equivalents are just wrappers to fs-internal
@@ -1021,4 +1022,20 @@ static inline long ksys_access(const char __user *filename, int mode)
1021 return do_faccessat(AT_FDCWD, filename, mode); 1022 return do_faccessat(AT_FDCWD, filename, mode);
1022} 1023}
1023 1024
1025extern int do_fchownat(int dfd, const char __user *filename, uid_t user,
1026 gid_t group, int flag);
1027
1028static inline long ksys_chown(const char __user *filename, uid_t user,
1029 gid_t group)
1030{
1031 return do_fchownat(AT_FDCWD, filename, user, group, 0);
1032}
1033
1034static inline long ksys_lchown(const char __user *filename, uid_t user,
1035 gid_t group)
1036{
1037 return do_fchownat(AT_FDCWD, filename, user, group,
1038 AT_SYMLINK_NOFOLLOW);
1039}
1040
1024#endif 1041#endif
diff --git a/init/initramfs.c b/init/initramfs.c
index 16c3c23076e2..35173bef7c00 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -343,7 +343,7 @@ static int __init do_name(void)
343 wfd = sys_open(collected, openflags, mode); 343 wfd = sys_open(collected, openflags, mode);
344 344
345 if (wfd >= 0) { 345 if (wfd >= 0) {
346 sys_fchown(wfd, uid, gid); 346 ksys_fchown(wfd, uid, gid);
347 ksys_fchmod(wfd, mode); 347 ksys_fchmod(wfd, mode);
348 if (body_len) 348 if (body_len)
349 sys_ftruncate(wfd, body_len); 349 sys_ftruncate(wfd, body_len);
@@ -353,14 +353,14 @@ static int __init do_name(void)
353 } 353 }
354 } else if (S_ISDIR(mode)) { 354 } else if (S_ISDIR(mode)) {
355 ksys_mkdir(collected, mode); 355 ksys_mkdir(collected, mode);
356 sys_chown(collected, uid, gid); 356 ksys_chown(collected, uid, gid);
357 ksys_chmod(collected, mode); 357 ksys_chmod(collected, mode);
358 dir_add(collected, mtime); 358 dir_add(collected, mtime);
359 } else if (S_ISBLK(mode) || S_ISCHR(mode) || 359 } else if (S_ISBLK(mode) || S_ISCHR(mode) ||
360 S_ISFIFO(mode) || S_ISSOCK(mode)) { 360 S_ISFIFO(mode) || S_ISSOCK(mode)) {
361 if (maybe_link() == 0) { 361 if (maybe_link() == 0) {
362 ksys_mknod(collected, mode, rdev); 362 ksys_mknod(collected, mode, rdev);
363 sys_chown(collected, uid, gid); 363 ksys_chown(collected, uid, gid);
364 ksys_chmod(collected, mode); 364 ksys_chmod(collected, mode);
365 do_utime(collected, mtime); 365 do_utime(collected, mtime);
366 } 366 }
@@ -393,7 +393,7 @@ static int __init do_symlink(void)
393 collected[N_ALIGN(name_len) + body_len] = '\0'; 393 collected[N_ALIGN(name_len) + body_len] = '\0';
394 clean_path(collected, 0); 394 clean_path(collected, 0);
395 ksys_symlink(collected + N_ALIGN(name_len), collected); 395 ksys_symlink(collected + N_ALIGN(name_len), collected);
396 sys_lchown(collected, uid, gid); 396 ksys_lchown(collected, uid, gid);
397 do_utime(collected, mtime); 397 do_utime(collected, mtime);
398 state = SkipIt; 398 state = SkipIt;
399 next_state = Reset; 399 next_state = Reset;
diff --git a/kernel/uid16.c b/kernel/uid16.c
index 7b930edfe461..af6925d8599b 100644
--- a/kernel/uid16.c
+++ b/kernel/uid16.c
@@ -22,17 +22,17 @@
22 22
23SYSCALL_DEFINE3(chown16, const char __user *, filename, old_uid_t, user, old_gid_t, group) 23SYSCALL_DEFINE3(chown16, const char __user *, filename, old_uid_t, user, old_gid_t, group)
24{ 24{
25 return sys_chown(filename, low2highuid(user), low2highgid(group)); 25 return ksys_chown(filename, low2highuid(user), low2highgid(group));
26} 26}
27 27
28SYSCALL_DEFINE3(lchown16, const char __user *, filename, old_uid_t, user, old_gid_t, group) 28SYSCALL_DEFINE3(lchown16, const char __user *, filename, old_uid_t, user, old_gid_t, group)
29{ 29{
30 return sys_lchown(filename, low2highuid(user), low2highgid(group)); 30 return ksys_lchown(filename, low2highuid(user), low2highgid(group));
31} 31}
32 32
33SYSCALL_DEFINE3(fchown16, unsigned int, fd, old_uid_t, user, old_gid_t, group) 33SYSCALL_DEFINE3(fchown16, unsigned int, fd, old_uid_t, user, old_gid_t, group)
34{ 34{
35 return sys_fchown(fd, low2highuid(user), low2highgid(group)); 35 return ksys_fchown(fd, low2highuid(user), low2highgid(group));
36} 36}
37 37
38SYSCALL_DEFINE2(setregid16, old_gid_t, rgid, old_gid_t, egid) 38SYSCALL_DEFINE2(setregid16, old_gid_t, rgid, old_gid_t, egid)