diff options
author | Dominik Brodowski <linux@dominikbrodowski.net> | 2018-03-11 06:34:55 -0400 |
---|---|---|
committer | Dominik Brodowski <linux@dominikbrodowski.net> | 2018-04-02 14:15:59 -0400 |
commit | 55731b3cda3a85ee888dac3bf1f36489f275c187 (patch) | |
tree | a322dc9efdd89932a35b294d221f90eccad45f23 | |
parent | cbfe20f565228966f0249f016752437df95df679 (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.c | 6 | ||||
-rw-r--r-- | fs/internal.h | 2 | ||||
-rw-r--r-- | fs/open.c | 23 | ||||
-rw-r--r-- | include/linux/syscalls.h | 17 | ||||
-rw-r--r-- | init/initramfs.c | 8 | ||||
-rw-r--r-- | kernel/uid16.c | 6 |
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 @@ | |||
89 | COMPAT_SYSCALL_DEFINE3(s390_chown16, const char __user *, filename, | 89 | COMPAT_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 | ||
95 | COMPAT_SYSCALL_DEFINE3(s390_lchown16, const char __user *, | 95 | COMPAT_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 | ||
101 | COMPAT_SYSCALL_DEFINE3(s390_fchown16, unsigned int, fd, u16, user, u16, group) | 101 | COMPAT_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 | ||
106 | COMPAT_SYSCALL_DEFINE2(s390_setregid16, u16, rgid, u16, egid) | 106 | COMPAT_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 | ||
122 | long do_faccessat(int dfd, const char __user *filename, int mode); | 122 | long do_faccessat(int dfd, const char __user *filename, int mode); |
123 | int do_fchmodat(int dfd, const char __user *filename, umode_t mode); | 123 | int do_fchmodat(int dfd, const char __user *filename, umode_t mode); |
124 | int do_fchownat(int dfd, const char __user *filename, uid_t user, gid_t group, | ||
125 | int flag); | ||
124 | 126 | ||
125 | extern int open_check_o_direct(struct file *f); | 127 | extern int open_check_o_direct(struct file *f); |
126 | extern int vfs_open(const struct path *, struct file *, const struct cred *); | 128 | extern int vfs_open(const struct path *, struct file *, const struct cred *); |
@@ -645,8 +645,8 @@ retry_deleg: | |||
645 | return error; | 645 | return error; |
646 | } | 646 | } |
647 | 647 | ||
648 | SYSCALL_DEFINE5(fchownat, int, dfd, const char __user *, filename, uid_t, user, | 648 | int 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 | ||
680 | SYSCALL_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 | |||
680 | SYSCALL_DEFINE3(chown, const char __user *, filename, uid_t, user, gid_t, group) | 686 | SYSCALL_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 | ||
685 | SYSCALL_DEFINE3(lchown, const char __user *, filename, uid_t, user, gid_t, group) | 691 | SYSCALL_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 | ||
691 | SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group) | 697 | int 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 | ||
717 | SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group) | ||
718 | { | ||
719 | return ksys_fchown(fd, user, group); | ||
720 | } | ||
721 | |||
711 | int open_check_o_direct(struct file *f) | 722 | int 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); | |||
954 | ssize_t ksys_write(unsigned int fd, const char __user *buf, size_t count); | 954 | ssize_t ksys_write(unsigned int fd, const char __user *buf, size_t count); |
955 | int ksys_chdir(const char __user *filename); | 955 | int ksys_chdir(const char __user *filename); |
956 | int ksys_fchmod(unsigned int fd, umode_t mode); | 956 | int ksys_fchmod(unsigned int fd, umode_t mode); |
957 | int 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 | ||
1025 | extern int do_fchownat(int dfd, const char __user *filename, uid_t user, | ||
1026 | gid_t group, int flag); | ||
1027 | |||
1028 | static 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 | |||
1034 | static 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 | ||
23 | SYSCALL_DEFINE3(chown16, const char __user *, filename, old_uid_t, user, old_gid_t, group) | 23 | SYSCALL_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 | ||
28 | SYSCALL_DEFINE3(lchown16, const char __user *, filename, old_uid_t, user, old_gid_t, group) | 28 | SYSCALL_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 | ||
33 | SYSCALL_DEFINE3(fchown16, unsigned int, fd, old_uid_t, user, old_gid_t, group) | 33 | SYSCALL_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 | ||
38 | SYSCALL_DEFINE2(setregid16, old_gid_t, rgid, old_gid_t, egid) | 38 | SYSCALL_DEFINE2(setregid16, old_gid_t, rgid, old_gid_t, egid) |