Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

s390: use generic UID16 implementation

s390 has an almost identical copy of the code in kernel/uid16.c.

The problem here is that it requires calling the regular system calls,
which the generic implementation handles correctly, but the internal
interfaces are not declared in a global header for this.

The best way forward here seems to be to just use the generic code and
delete the s390 specific implementation.

I keep the changes to uapi/asm/posix_types.h inside of an #ifdef check
so user space does not observe any changes. As some of the system calls
pass pointers, we also need wrappers in compat_wrapper.c, which I add
for all calls with at least one argument. All those wrappers can be
removed in a later step.

Link: https://lore.kernel.org/lkml/20190116131527.2071570-4-arnd@arndb.de
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Reviewed-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>

authored by

Arnd Bergmann and committed by
Martin Schwidefsky
fef747ba 58fa4a41

+41 -252
+1
arch/s390/Kconfig
··· 379 379 select COMPAT_BINFMT_ELF if BINFMT_ELF 380 380 select ARCH_WANT_OLD_COMPAT_IPC 381 381 select COMPAT_OLD_SIGACTION 382 + select HAVE_UID16 382 383 depends on MULTIUSER 383 384 help 384 385 Select this option if you want to enable your system kernel to
+6
arch/s390/include/uapi/asm/posix_types.h
··· 20 20 typedef unsigned short __kernel_old_dev_t; 21 21 #define __kernel_old_dev_t __kernel_old_dev_t 22 22 23 + #ifdef __KERNEL__ 24 + typedef unsigned short __kernel_old_uid_t; 25 + typedef unsigned short __kernel_old_gid_t; 26 + #define __kernel_old_uid_t __kernel_old_uid_t 27 + #endif 28 + 23 29 #ifndef __s390x__ 24 30 25 31 typedef unsigned long __kernel_ino_t;
-233
arch/s390/kernel/compat_linux.c
··· 34 34 #include <linux/stat.h> 35 35 #include <linux/filter.h> 36 36 #include <linux/highmem.h> 37 - #include <linux/highuid.h> 38 37 #include <linux/mman.h> 39 38 #include <linux/ipv6.h> 40 39 #include <linux/in.h> ··· 56 57 #include <net/sock.h> 57 58 58 59 #include "compat_linux.h" 59 - 60 - /* For this source file, we want overflow handling. */ 61 - 62 - #undef high2lowuid 63 - #undef high2lowgid 64 - #undef low2highuid 65 - #undef low2highgid 66 - #undef SET_UID16 67 - #undef SET_GID16 68 - #undef NEW_TO_OLD_UID 69 - #undef NEW_TO_OLD_GID 70 - #undef SET_OLDSTAT_UID 71 - #undef SET_OLDSTAT_GID 72 - #undef SET_STAT_UID 73 - #undef SET_STAT_GID 74 - 75 - #define high2lowuid(uid) ((uid) > 65535) ? (u16)overflowuid : (u16)(uid) 76 - #define high2lowgid(gid) ((gid) > 65535) ? (u16)overflowgid : (u16)(gid) 77 - #define low2highuid(uid) ((uid) == (u16)-1) ? (uid_t)-1 : (uid_t)(uid) 78 - #define low2highgid(gid) ((gid) == (u16)-1) ? (gid_t)-1 : (gid_t)(gid) 79 - #define SET_UID16(var, uid) var = high2lowuid(uid) 80 - #define SET_GID16(var, gid) var = high2lowgid(gid) 81 - #define NEW_TO_OLD_UID(uid) high2lowuid(uid) 82 - #define NEW_TO_OLD_GID(gid) high2lowgid(gid) 83 - #define SET_OLDSTAT_UID(stat, uid) (stat).st_uid = high2lowuid(uid) 84 - #define SET_OLDSTAT_GID(stat, gid) (stat).st_gid = high2lowgid(gid) 85 - #define SET_STAT_UID(stat, uid) (stat).st_uid = high2lowuid(uid) 86 - #define SET_STAT_GID(stat, gid) (stat).st_gid = high2lowgid(gid) 87 - 88 - COMPAT_SYSCALL_DEFINE3(s390_chown16, const char __user *, filename, 89 - u16, user, u16, group) 90 - { 91 - return ksys_chown(filename, low2highuid(user), low2highgid(group)); 92 - } 93 - 94 - COMPAT_SYSCALL_DEFINE3(s390_lchown16, const char __user *, 95 - filename, u16, user, u16, group) 96 - { 97 - return ksys_lchown(filename, low2highuid(user), low2highgid(group)); 98 - } 99 - 100 - COMPAT_SYSCALL_DEFINE3(s390_fchown16, unsigned int, fd, u16, user, u16, group) 101 - { 102 - return ksys_fchown(fd, low2highuid(user), low2highgid(group)); 103 - } 104 - 105 - COMPAT_SYSCALL_DEFINE2(s390_setregid16, u16, rgid, u16, egid) 106 - { 107 - return sys_setregid(low2highgid(rgid), low2highgid(egid)); 108 - } 109 - 110 - COMPAT_SYSCALL_DEFINE1(s390_setgid16, u16, gid) 111 - { 112 - return sys_setgid(low2highgid(gid)); 113 - } 114 - 115 - COMPAT_SYSCALL_DEFINE2(s390_setreuid16, u16, ruid, u16, euid) 116 - { 117 - return sys_setreuid(low2highuid(ruid), low2highuid(euid)); 118 - } 119 - 120 - COMPAT_SYSCALL_DEFINE1(s390_setuid16, u16, uid) 121 - { 122 - return sys_setuid(low2highuid(uid)); 123 - } 124 - 125 - COMPAT_SYSCALL_DEFINE3(s390_setresuid16, u16, ruid, u16, euid, u16, suid) 126 - { 127 - return sys_setresuid(low2highuid(ruid), low2highuid(euid), 128 - low2highuid(suid)); 129 - } 130 - 131 - COMPAT_SYSCALL_DEFINE3(s390_getresuid16, u16 __user *, ruidp, 132 - u16 __user *, euidp, u16 __user *, suidp) 133 - { 134 - const struct cred *cred = current_cred(); 135 - int retval; 136 - u16 ruid, euid, suid; 137 - 138 - ruid = high2lowuid(from_kuid_munged(cred->user_ns, cred->uid)); 139 - euid = high2lowuid(from_kuid_munged(cred->user_ns, cred->euid)); 140 - suid = high2lowuid(from_kuid_munged(cred->user_ns, cred->suid)); 141 - 142 - if (!(retval = put_user(ruid, ruidp)) && 143 - !(retval = put_user(euid, euidp))) 144 - retval = put_user(suid, suidp); 145 - 146 - return retval; 147 - } 148 - 149 - COMPAT_SYSCALL_DEFINE3(s390_setresgid16, u16, rgid, u16, egid, u16, sgid) 150 - { 151 - return sys_setresgid(low2highgid(rgid), low2highgid(egid), 152 - low2highgid(sgid)); 153 - } 154 - 155 - COMPAT_SYSCALL_DEFINE3(s390_getresgid16, u16 __user *, rgidp, 156 - u16 __user *, egidp, u16 __user *, sgidp) 157 - { 158 - const struct cred *cred = current_cred(); 159 - int retval; 160 - u16 rgid, egid, sgid; 161 - 162 - rgid = high2lowgid(from_kgid_munged(cred->user_ns, cred->gid)); 163 - egid = high2lowgid(from_kgid_munged(cred->user_ns, cred->egid)); 164 - sgid = high2lowgid(from_kgid_munged(cred->user_ns, cred->sgid)); 165 - 166 - if (!(retval = put_user(rgid, rgidp)) && 167 - !(retval = put_user(egid, egidp))) 168 - retval = put_user(sgid, sgidp); 169 - 170 - return retval; 171 - } 172 - 173 - COMPAT_SYSCALL_DEFINE1(s390_setfsuid16, u16, uid) 174 - { 175 - return sys_setfsuid(low2highuid(uid)); 176 - } 177 - 178 - COMPAT_SYSCALL_DEFINE1(s390_setfsgid16, u16, gid) 179 - { 180 - return sys_setfsgid(low2highgid(gid)); 181 - } 182 - 183 - static int groups16_to_user(u16 __user *grouplist, struct group_info *group_info) 184 - { 185 - struct user_namespace *user_ns = current_user_ns(); 186 - int i; 187 - u16 group; 188 - kgid_t kgid; 189 - 190 - for (i = 0; i < group_info->ngroups; i++) { 191 - kgid = group_info->gid[i]; 192 - group = (u16)from_kgid_munged(user_ns, kgid); 193 - if (put_user(group, grouplist+i)) 194 - return -EFAULT; 195 - } 196 - 197 - return 0; 198 - } 199 - 200 - static int groups16_from_user(struct group_info *group_info, u16 __user *grouplist) 201 - { 202 - struct user_namespace *user_ns = current_user_ns(); 203 - int i; 204 - u16 group; 205 - kgid_t kgid; 206 - 207 - for (i = 0; i < group_info->ngroups; i++) { 208 - if (get_user(group, grouplist+i)) 209 - return -EFAULT; 210 - 211 - kgid = make_kgid(user_ns, (gid_t)group); 212 - if (!gid_valid(kgid)) 213 - return -EINVAL; 214 - 215 - group_info->gid[i] = kgid; 216 - } 217 - 218 - return 0; 219 - } 220 - 221 - COMPAT_SYSCALL_DEFINE2(s390_getgroups16, int, gidsetsize, u16 __user *, grouplist) 222 - { 223 - const struct cred *cred = current_cred(); 224 - int i; 225 - 226 - if (gidsetsize < 0) 227 - return -EINVAL; 228 - 229 - get_group_info(cred->group_info); 230 - i = cred->group_info->ngroups; 231 - if (gidsetsize) { 232 - if (i > gidsetsize) { 233 - i = -EINVAL; 234 - goto out; 235 - } 236 - if (groups16_to_user(grouplist, cred->group_info)) { 237 - i = -EFAULT; 238 - goto out; 239 - } 240 - } 241 - out: 242 - put_group_info(cred->group_info); 243 - return i; 244 - } 245 - 246 - COMPAT_SYSCALL_DEFINE2(s390_setgroups16, int, gidsetsize, u16 __user *, grouplist) 247 - { 248 - struct group_info *group_info; 249 - int retval; 250 - 251 - if (!may_setgroups()) 252 - return -EPERM; 253 - if ((unsigned)gidsetsize > NGROUPS_MAX) 254 - return -EINVAL; 255 - 256 - group_info = groups_alloc(gidsetsize); 257 - if (!group_info) 258 - return -ENOMEM; 259 - retval = groups16_from_user(group_info, grouplist); 260 - if (retval) { 261 - put_group_info(group_info); 262 - return retval; 263 - } 264 - 265 - groups_sort(group_info); 266 - retval = set_current_groups(group_info); 267 - put_group_info(group_info); 268 - 269 - return retval; 270 - } 271 - 272 - COMPAT_SYSCALL_DEFINE0(s390_getuid16) 273 - { 274 - return high2lowuid(from_kuid_munged(current_user_ns(), current_uid())); 275 - } 276 - 277 - COMPAT_SYSCALL_DEFINE0(s390_geteuid16) 278 - { 279 - return high2lowuid(from_kuid_munged(current_user_ns(), current_euid())); 280 - } 281 - 282 - COMPAT_SYSCALL_DEFINE0(s390_getgid16) 283 - { 284 - return high2lowgid(from_kgid_munged(current_user_ns(), current_gid())); 285 - } 286 - 287 - COMPAT_SYSCALL_DEFINE0(s390_getegid16) 288 - { 289 - return high2lowgid(from_kgid_munged(current_user_ns(), current_egid())); 290 - } 291 60 292 61 #ifdef CONFIG_SYSVIPC 293 62 COMPAT_SYSCALL_DEFINE5(s390_ipc, uint, call, int, first, compat_ulong_t, second,
+15
arch/s390/kernel/compat_wrapper.c
··· 184 184 COMPAT_SYSCALL_WRAP4(s390_sthyi, unsigned long, code, void __user *, info, u64 __user *, rc, unsigned long, flags); 185 185 COMPAT_SYSCALL_WRAP5(kexec_file_load, int, kernel_fd, int, initrd_fd, unsigned long, cmdline_len, const char __user *, cmdline_ptr, unsigned long, flags) 186 186 COMPAT_SYSCALL_WRAP4(rseq, struct rseq __user *, rseq, u32, rseq_len, int, flags, u32, sig) 187 + COMPAT_SYSCALL_WRAP3(chown16, const char __user *, filename, u16, user, u16, group); 188 + COMPAT_SYSCALL_WRAP3(lchown16, const char __user *, filename, u16, user, u16, group); 189 + COMPAT_SYSCALL_WRAP3(fchown16, unsigned int, fd, u16, user, u16, group); 190 + COMPAT_SYSCALL_WRAP2(setregid16, u16, rgid, u16, egid); 191 + COMPAT_SYSCALL_WRAP1(setgid16, u16, gid); 192 + COMPAT_SYSCALL_WRAP2(setreuid16, u16, ruid, u16, euid); 193 + COMPAT_SYSCALL_WRAP1(setuid16, u16, uid); 194 + COMPAT_SYSCALL_WRAP3(setresuid16, u16, ruid, u16, euid, u16, suid); 195 + COMPAT_SYSCALL_WRAP3(getresuid16, u16 __user *, ruidp, u16 __user *, euidp, u16 __user *, suidp); 196 + COMPAT_SYSCALL_WRAP3(setresgid16, u16, rgid, u16, egid, u16, sgid); 197 + COMPAT_SYSCALL_WRAP3(getresgid16, u16 __user *, rgidp, u16 __user *, egidp, u16 __user *, sgidp); 198 + COMPAT_SYSCALL_WRAP1(setfsuid16, u16, uid); 199 + COMPAT_SYSCALL_WRAP1(setfsgid16, u16, gid); 200 + COMPAT_SYSCALL_WRAP2(getgroups16, int, gidsetsize, u16 __user *, grouplist); 201 + COMPAT_SYSCALL_WRAP2(setgroups16, int, gidsetsize, u16 __user *, grouplist);
+19 -19
arch/s390/kernel/syscalls/syscall.tbl
··· 23 23 13 32 time - compat_sys_time 24 24 14 common mknod sys_mknod compat_sys_mknod 25 25 15 common chmod sys_chmod compat_sys_chmod 26 - 16 32 lchown - compat_sys_s390_lchown16 26 + 16 32 lchown - compat_sys_lchown16 27 27 19 common lseek sys_lseek compat_sys_lseek 28 28 20 common getpid sys_getpid sys_getpid 29 29 21 common mount sys_mount compat_sys_mount 30 30 22 common umount sys_oldumount compat_sys_oldumount 31 - 23 32 setuid - compat_sys_s390_setuid16 32 - 24 32 getuid - compat_sys_s390_getuid16 31 + 23 32 setuid - compat_sys_setuid16 32 + 24 32 getuid - sys_getuid16 33 33 25 32 stime - compat_sys_stime 34 34 26 common ptrace sys_ptrace compat_sys_ptrace 35 35 27 common alarm sys_alarm sys_alarm ··· 46 46 42 common pipe sys_pipe compat_sys_pipe 47 47 43 common times sys_times compat_sys_times 48 48 45 common brk sys_brk compat_sys_brk 49 - 46 32 setgid - compat_sys_s390_setgid16 50 - 47 32 getgid - compat_sys_s390_getgid16 49 + 46 32 setgid - compat_sys_setgid16 50 + 47 32 getgid - sys_getgid16 51 51 48 common signal sys_signal compat_sys_signal 52 - 49 32 geteuid - compat_sys_s390_geteuid16 53 - 50 32 getegid - compat_sys_s390_getegid16 52 + 49 32 geteuid - sys_geteuid16 53 + 50 32 getegid - sys_getegid16 54 54 51 common acct sys_acct compat_sys_acct 55 55 52 common umount2 sys_umount compat_sys_umount 56 56 54 common ioctl sys_ioctl compat_sys_ioctl ··· 64 64 65 common getpgrp sys_getpgrp sys_getpgrp 65 65 66 common setsid sys_setsid sys_setsid 66 66 67 common sigaction sys_sigaction compat_sys_sigaction 67 - 70 32 setreuid - compat_sys_s390_setreuid16 68 - 71 32 setregid - compat_sys_s390_setregid16 67 + 70 32 setreuid - compat_sys_setreuid16 68 + 71 32 setregid - compat_sys_setregid16 69 69 72 common sigsuspend sys_sigsuspend compat_sys_sigsuspend 70 70 73 common sigpending sys_sigpending compat_sys_sigpending 71 71 74 common sethostname sys_sethostname compat_sys_sethostname ··· 74 74 77 common getrusage sys_getrusage compat_sys_getrusage 75 75 78 common gettimeofday sys_gettimeofday compat_sys_gettimeofday 76 76 79 common settimeofday sys_settimeofday compat_sys_settimeofday 77 - 80 32 getgroups - compat_sys_s390_getgroups16 78 - 81 32 setgroups - compat_sys_s390_setgroups16 77 + 80 32 getgroups - compat_sys_getgroups16 78 + 81 32 setgroups - compat_sys_setgroups16 79 79 83 common symlink sys_symlink compat_sys_symlink 80 80 85 common readlink sys_readlink compat_sys_readlink 81 81 86 common uselib sys_uselib compat_sys_uselib ··· 87 87 92 common truncate sys_truncate compat_sys_truncate 88 88 93 common ftruncate sys_ftruncate compat_sys_ftruncate 89 89 94 common fchmod sys_fchmod sys_fchmod 90 - 95 32 fchown - compat_sys_s390_fchown16 90 + 95 32 fchown - compat_sys_fchown16 91 91 96 common getpriority sys_getpriority sys_getpriority 92 92 97 common setpriority sys_setpriority sys_setpriority 93 93 99 common statfs sys_statfs compat_sys_statfs ··· 126 126 135 common sysfs sys_sysfs compat_sys_sysfs 127 127 136 common personality sys_s390_personality sys_s390_personality 128 128 137 common afs_syscall - - 129 - 138 32 setfsuid - compat_sys_s390_setfsuid16 130 - 139 32 setfsgid - compat_sys_s390_setfsgid16 129 + 138 32 setfsuid - compat_sys_setfsuid16 130 + 139 32 setfsgid - compat_sys_setfsgid16 131 131 140 32 _llseek - compat_sys_llseek 132 132 141 common getdents sys_getdents compat_sys_getdents 133 133 142 32 _newselect - compat_sys_select ··· 153 153 161 common sched_rr_get_interval sys_sched_rr_get_interval compat_sys_sched_rr_get_interval 154 154 162 common nanosleep sys_nanosleep compat_sys_nanosleep 155 155 163 common mremap sys_mremap compat_sys_mremap 156 - 164 32 setresuid - compat_sys_s390_setresuid16 157 - 165 32 getresuid - compat_sys_s390_getresuid16 156 + 164 32 setresuid - compat_sys_setresuid16 157 + 165 32 getresuid - compat_sys_getresuid16 158 158 167 common query_module - - 159 159 168 common poll sys_poll compat_sys_poll 160 160 169 common nfsservctl - - 161 - 170 32 setresgid - compat_sys_s390_setresgid16 162 - 171 32 getresgid - compat_sys_s390_getresgid16 161 + 170 32 setresgid - compat_sys_setresgid16 162 + 171 32 getresgid - compat_sys_getresgid16 163 163 172 common prctl sys_prctl compat_sys_prctl 164 164 173 common rt_sigreturn sys_rt_sigreturn compat_sys_rt_sigreturn 165 165 174 common rt_sigaction sys_rt_sigaction compat_sys_rt_sigaction ··· 170 170 179 common rt_sigsuspend sys_rt_sigsuspend compat_sys_rt_sigsuspend 171 171 180 common pread64 sys_pread64 compat_sys_s390_pread64 172 172 181 common pwrite64 sys_pwrite64 compat_sys_s390_pwrite64 173 - 182 32 chown - compat_sys_s390_chown16 173 + 182 32 chown - compat_sys_chown16 174 174 183 common getcwd sys_getcwd compat_sys_getcwd 175 175 184 common capget sys_capget compat_sys_capget 176 176 185 common capset sys_capset compat_sys_capset