From 0473c9b5f05948df780bbc7b996dd7aefc4ec41d Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 3 Mar 2014 10:44:03 +0100 Subject: compat: let architectures define __ARCH_WANT_COMPAT_SYS_GETDENTS64 For architecture dependent compat syscalls in common code an architecture must define something like __ARCH_WANT_ if it wants to use the code. This however is not true for compat_sys_getdents64 for which architectures must define __ARCH_OMIT_COMPAT_SYS_GETDENTS64 if they do not want the code. This leads to the situation where all architectures, except mips, get the compat code but only x86_64, arm64 and the generic syscall architectures actually use it. So invert the logic, so that architectures actively must do something to get the compat code. This way a couple of architectures get rid of otherwise dead code. Signed-off-by: Heiko Carstens --- include/linux/compat.h | 2 ++ include/uapi/asm-generic/unistd.h | 1 + 2 files changed, 3 insertions(+) (limited to 'include') diff --git a/include/linux/compat.h b/include/linux/compat.h index 3f448c65511b..beded18f992d 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -502,9 +502,11 @@ asmlinkage long compat_sys_old_readdir(unsigned int fd, asmlinkage long compat_sys_getdents(unsigned int fd, struct compat_linux_dirent __user *dirent, unsigned int count); +#ifdef __ARCH_WANT_COMPAT_SYS_GETDENTS64 asmlinkage long compat_sys_getdents64(unsigned int fd, struct linux_dirent64 __user *dirent, unsigned int count); +#endif asmlinkage long compat_sys_vmsplice(int fd, const struct compat_iovec __user *, unsigned int nr_segs, unsigned int flags); asmlinkage long compat_sys_open(const char __user *filename, int flags, diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h index dde8041f40d2..6db66783d268 100644 --- a/include/uapi/asm-generic/unistd.h +++ b/include/uapi/asm-generic/unistd.h @@ -191,6 +191,7 @@ __SYSCALL(__NR_quotactl, sys_quotactl) /* fs/readdir.c */ #define __NR_getdents64 61 +#define __ARCH_WANT_COMPAT_SYS_GETDENTS64 __SC_COMP(__NR_getdents64, sys_getdents64, compat_sys_getdents64) /* fs/read_write.c */ -- cgit v1.2.3 From 217f4433fc2fe768a7f13f7e5586333bb8280e9e Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 26 Feb 2014 10:56:20 +0100 Subject: compat: add COMPAT_SYSCALL_DEFINE0 macro For consistency reason add a COMPAT_SYSCALL_DEFINE0 macro. This macro should be used for compat system calls with zero parameters. Signed-off-by: Heiko Carstens --- include/linux/compat.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include') diff --git a/include/linux/compat.h b/include/linux/compat.h index beded18f992d..4c42df3fce37 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -27,6 +27,9 @@ #define __SC_DELOUSE(t,v) ((t)(unsigned long)(v)) #endif +#define COMPAT_SYSCALL_DEFINE0(name) \ + asmlinkage long compat_sys_##name(void) + #define COMPAT_SYSCALL_DEFINE1(name, ...) \ COMPAT_SYSCALL_DEFINEx(1, _##name, __VA_ARGS__) #define COMPAT_SYSCALL_DEFINE2(name, ...) \ -- cgit v1.2.3 From ab4f8bba19323eb78b7473df42b225eb14090fcc Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Sat, 1 Mar 2014 13:45:03 +0100 Subject: s390/compat: automatic zero, sign and pointer conversion of syscalls Instead of explicitly changing compat system call parameters from e.g. unsigned long to compat_ulong_t let the COMPAT_SYSCALL_WRAP macros automatically detect (unsigned) long parameters and zero and sign extend them automatically. The resulting binary is completely identical. In addition add a sys_[system call name] prototype for each system call wrapper. This will cause compile errors if the prototype does not match the prototype in include/linux/syscall.h. Therefore we should now always get the correct zero and sign extension of system call parameters. Pointers are handled like before. Signed-off-by: Heiko Carstens --- include/linux/syscalls.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index a747a77ea584..1e67b7a5968c 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -98,6 +98,8 @@ struct sigaltstack; #define __MAP(n,...) __MAP##n(__VA_ARGS__) #define __SC_DECL(t, a) t a +#define __TYPE_IS_L(t) (__same_type((t)0, 0L)) +#define __TYPE_IS_UL(t) (__same_type((t)0, 0UL)) #define __TYPE_IS_LL(t) (__same_type((t)0, 0LL) || __same_type((t)0, 0ULL)) #define __SC_LONG(t, a) __typeof(__builtin_choose_expr(__TYPE_IS_LL(t), 0LL, 0L)) a #define __SC_CAST(t, a) (t) a -- cgit v1.2.3 From 291fdb0bcebd5e8db6af767c1fdc522167dad73d Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 4 Mar 2014 12:39:03 +0100 Subject: ipc/compat_sys_msgrcv: change msgtyp type from long to compat_long_t Change the type of compat_sys_msgrcv's msgtyp parameter from long to compat_long_t, since compat user space passes only a 32 bit signed value. Let the compat wrapper do proper sign extension to 64 bit of this parameter. Signed-off-by: Heiko Carstens --- include/linux/compat.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/compat.h b/include/linux/compat.h index 4c42df3fce37..179b1da9e19f 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -321,7 +321,7 @@ asmlinkage long compat_sys_semctl(int semid, int semnum, int cmd, int arg); asmlinkage long compat_sys_msgsnd(int msqid, compat_uptr_t msgp, compat_ssize_t msgsz, int msgflg); asmlinkage long compat_sys_msgrcv(int msqid, compat_uptr_t msgp, - compat_ssize_t msgsz, long msgtyp, int msgflg); + compat_ssize_t msgsz, compat_long_t msgtyp, int msgflg); long compat_sys_msgctl(int first, int second, void __user *uptr); long compat_sys_shmctl(int first, int second, void __user *uptr); long compat_sys_semtimedop(int semid, struct sembuf __user *tsems, -- cgit v1.2.3 From 378a10f3ae2e8a67ecc8f548c8e5ff25881bd88a Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 5 Mar 2014 10:43:51 +0100 Subject: fs/compat: optional preadv64/pwrite64 compat system calls The preadv64/pwrite64 have been implemented for the x32 ABI, in order to allow passing 64 bit arguments from user space without splitting them into two 32 bit parameters, like it would be necessary for usual compat tasks. Howevert these two system calls are only being used for the x32 ABI, so add __ARCH_WANT_COMPAT defines for these two compat syscalls and make these two only visible for x86. Signed-off-by: Heiko Carstens --- include/linux/compat.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'include') diff --git a/include/linux/compat.h b/include/linux/compat.h index 179b1da9e19f..1c457428ec0a 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -340,6 +340,19 @@ asmlinkage ssize_t compat_sys_preadv(compat_ulong_t fd, asmlinkage ssize_t compat_sys_pwritev(compat_ulong_t fd, const struct compat_iovec __user *vec, compat_ulong_t vlen, u32 pos_low, u32 pos_high); + +#ifdef __ARCH_WANT_COMPAT_SYS_PREADV64 +asmlinkage long compat_sys_preadv64(unsigned long fd, + const struct compat_iovec __user *vec, + unsigned long vlen, loff_t pos); +#endif + +#ifdef __ARCH_WANT_COMPAT_SYS_PWRITEV64 +asmlinkage long compat_sys_pwritev64(unsigned long fd, + const struct compat_iovec __user *vec, + unsigned long vlen, loff_t pos); +#endif + asmlinkage long compat_sys_lseek(unsigned int, compat_off_t, unsigned int); asmlinkage long compat_sys_execve(const char __user *filename, const compat_uptr_t __user *argv, -- cgit v1.2.3 From 932602e238329da99f8482c1b721549531fbfe7f Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 4 Mar 2014 16:07:52 +0100 Subject: fs/compat: convert to COMPAT_SYSCALL_DEFINE with changing parameter types Some fs compat system calls have unsigned long parameters instead of compat_ulong_t. In order to allow the COMPAT_SYSCALL_DEFINE macro generate code that performs proper zero and sign extension convert all 64 bit parameters their corresponding 32 bit counterparts. compat_sys_io_getevents() is a bit different: the non-compat version has signed parameters for the "min_nr" and "nr" parameters while the compat version has unsigned parameters. So change this as well. For all practical purposes this shouldn't make any difference (doesn't fix a real bug). Also introduce a generic compat_aio_context_t type which can be used everywhere. The access_ok() check within compat_sys_io_getevents() got also removed since the non-compat sys_io_getevents() should be able to handle everything anyway. Signed-off-by: Heiko Carstens --- include/linux/compat.h | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/include/linux/compat.h b/include/linux/compat.h index 1c457428ec0a..fea8ee9afe22 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -71,6 +71,8 @@ typedef struct compat_sigaltstack { typedef __compat_uid32_t compat_uid_t; typedef __compat_gid32_t compat_gid_t; +typedef compat_ulong_t compat_aio_context_t; + struct compat_sel_arg_struct; struct rusage; @@ -497,20 +499,20 @@ asmlinkage long compat_sys_statfs64(const char __user *pathname, asmlinkage long compat_sys_fstatfs64(unsigned int fd, compat_size_t sz, struct compat_statfs64 __user *buf); asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd, - unsigned long arg); + compat_ulong_t arg); asmlinkage long compat_sys_fcntl(unsigned int fd, unsigned int cmd, - unsigned long arg); + compat_ulong_t arg); asmlinkage long compat_sys_io_setup(unsigned nr_reqs, u32 __user *ctx32p); -asmlinkage long compat_sys_io_getevents(aio_context_t ctx_id, - unsigned long min_nr, - unsigned long nr, +asmlinkage long compat_sys_io_getevents(compat_aio_context_t ctx_id, + compat_long_t min_nr, + compat_long_t nr, struct io_event __user *events, struct compat_timespec __user *timeout); -asmlinkage long compat_sys_io_submit(aio_context_t ctx_id, int nr, +asmlinkage long compat_sys_io_submit(compat_aio_context_t ctx_id, int nr, u32 __user *iocb); asmlinkage long compat_sys_mount(const char __user *dev_name, const char __user *dir_name, - const char __user *type, unsigned long flags, + const char __user *type, compat_ulong_t flags, const void __user *data); asmlinkage long compat_sys_old_readdir(unsigned int fd, struct compat_old_linux_dirent __user *, @@ -633,7 +635,7 @@ asmlinkage long compat_sys_rt_sigqueueinfo(compat_pid_t pid, int sig, struct compat_siginfo __user *uinfo); asmlinkage long compat_sys_sysinfo(struct compat_sysinfo __user *info); asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd, - unsigned long arg); + compat_ulong_t arg); asmlinkage long compat_sys_futex(u32 __user *uaddr, int op, u32 val, struct compat_timespec __user *utime, u32 __user *uaddr2, u32 val3); -- cgit v1.2.3 From 8eee9093cdbeb2aa89d67dc1a3fd118acabaea52 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 4 Mar 2014 16:19:16 +0100 Subject: ipc/compat: convert to COMPAT_SYSCALL_DEFINE with changing parameter types In order to allow the COMPAT_SYSCALL_DEFINE macro generate code that performs proper zero and sign extension convert all 64 bit parameters to their corresponding 32 bit compat counterparts. Signed-off-by: Heiko Carstens --- include/linux/compat.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/linux/compat.h b/include/linux/compat.h index fea8ee9afe22..f670e591aff8 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -655,11 +655,11 @@ asmlinkage long compat_sys_mq_open(const char __user *u_name, struct compat_mq_attr __user *u_attr); asmlinkage long compat_sys_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr, - size_t msg_len, unsigned int msg_prio, + compat_size_t msg_len, unsigned int msg_prio, const struct compat_timespec __user *u_abs_timeout); asmlinkage ssize_t compat_sys_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr, - size_t msg_len, unsigned int __user *u_msg_prio, + compat_size_t msg_len, unsigned int __user *u_msg_prio, const struct compat_timespec __user *u_abs_timeout); asmlinkage long compat_sys_socketcall(int call, u32 __user *args); asmlinkage long compat_sys_sysctl(struct compat_sysctl_args __user *args); -- cgit v1.2.3 From 3a49a0f7181c243aa04e6c5e44ca70a90ead8f9a Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 4 Mar 2014 17:09:57 +0100 Subject: net/compat: convert to COMPAT_SYSCALL_DEFINE with changing parameter types In order to allow the COMPAT_SYSCALL_DEFINE macro generate code that performs proper zero and sign extension convert all 64 bit parameters to their corresponding 32 bit compat counterparts. Signed-off-by: Heiko Carstens --- include/linux/compat.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/linux/compat.h b/include/linux/compat.h index f670e591aff8..8e636211f334 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -569,9 +569,9 @@ asmlinkage long compat_sys_sendmmsg(int fd, struct compat_mmsghdr __user *mmsg, unsigned vlen, unsigned int flags); asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags); -asmlinkage long compat_sys_recv(int fd, void __user *buf, size_t len, +asmlinkage long compat_sys_recv(int fd, void __user *buf, compat_size_t len, unsigned flags); -asmlinkage long compat_sys_recvfrom(int fd, void __user *buf, size_t len, +asmlinkage long compat_sys_recvfrom(int fd, void __user *buf, compat_size_t len, unsigned flags, struct sockaddr __user *addr, int __user *addrlen); asmlinkage long compat_sys_recvmmsg(int fd, struct compat_mmsghdr __user *mmsg, -- cgit v1.2.3 From ca2c405ab90591dcb1bc3765467cbdf2b99a0f6a Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 4 Mar 2014 17:13:42 +0100 Subject: kexec/compat: convert to COMPAT_SYSCALL_DEFINE with changing parameter types In order to allow the COMPAT_SYSCALL_DEFINE macro generate code that performs proper zero and sign extension convert all 64 bit parameters to their corresponding 32 bit compat counterparts. Signed-off-by: Heiko Carstens --- include/linux/compat.h | 6 +++--- include/linux/kexec.h | 6 ------ 2 files changed, 3 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/include/linux/compat.h b/include/linux/compat.h index 8e636211f334..ef4834c5bcab 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -641,10 +641,10 @@ asmlinkage long compat_sys_futex(u32 __user *uaddr, int op, u32 val, u32 val3); asmlinkage long compat_sys_getsockopt(int fd, int level, int optname, char __user *optval, int __user *optlen); -asmlinkage long compat_sys_kexec_load(unsigned long entry, - unsigned long nr_segments, +asmlinkage long compat_sys_kexec_load(compat_ulong_t entry, + compat_ulong_t nr_segments, struct compat_kexec_segment __user *, - unsigned long flags); + compat_ulong_t flags); asmlinkage long compat_sys_mq_getsetattr(mqd_t mqdes, const struct compat_mq_attr __user *u_mqstat, struct compat_mq_attr __user *u_omqstat); diff --git a/include/linux/kexec.h b/include/linux/kexec.h index 6d4066cdb5b5..a75641930049 100644 --- a/include/linux/kexec.h +++ b/include/linux/kexec.h @@ -127,12 +127,6 @@ extern asmlinkage long sys_kexec_load(unsigned long entry, struct kexec_segment __user *segments, unsigned long flags); extern int kernel_kexec(void); -#ifdef CONFIG_COMPAT -extern asmlinkage long compat_sys_kexec_load(unsigned long entry, - unsigned long nr_segments, - struct compat_kexec_segment __user *segments, - unsigned long flags); -#endif extern struct page *kimage_alloc_control_pages(struct kimage *image, unsigned int order); extern void crash_kexec(struct pt_regs *); -- cgit v1.2.3 From 2f2728f6de9837abe4b354443a45be578fbbf942 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 4 Mar 2014 17:18:23 +0100 Subject: mm/compat: convert to COMPAT_SYSCALL_DEFINE with changing parameter types In order to allow the COMPAT_SYSCALL_DEFINE macro generate code that performs proper zero and sign extension convert all 64 bit parameters to their corresponding 32 bit compat counterparts. Signed-off-by: Heiko Carstens --- include/linux/compat.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/linux/compat.h b/include/linux/compat.h index ef4834c5bcab..7c765624b7ef 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -469,7 +469,7 @@ asmlinkage long compat_sys_timerfd_settime(int ufd, int flags, asmlinkage long compat_sys_timerfd_gettime(int ufd, struct compat_itimerspec __user *otmr); -asmlinkage long compat_sys_move_pages(pid_t pid, unsigned long nr_page, +asmlinkage long compat_sys_move_pages(pid_t pid, compat_ulong_t nr_pages, __u32 __user *pages, const int __user *nodes, int __user *status, @@ -674,12 +674,12 @@ extern void __user *compat_alloc_user_space(unsigned long len); asmlinkage ssize_t compat_sys_process_vm_readv(compat_pid_t pid, const struct compat_iovec __user *lvec, - unsigned long liovcnt, const struct compat_iovec __user *rvec, - unsigned long riovcnt, unsigned long flags); + compat_ulong_t liovcnt, const struct compat_iovec __user *rvec, + compat_ulong_t riovcnt, compat_ulong_t flags); asmlinkage ssize_t compat_sys_process_vm_writev(compat_pid_t pid, const struct compat_iovec __user *lvec, - unsigned long liovcnt, const struct compat_iovec __user *rvec, - unsigned long riovcnt, unsigned long flags); + compat_ulong_t liovcnt, const struct compat_iovec __user *rvec, + compat_ulong_t riovcnt, compat_ulong_t flags); asmlinkage long compat_sys_sendfile(int out_fd, int in_fd, compat_off_t __user *offset, compat_size_t count); -- cgit v1.2.3 From f5b972e9fbd2e99a2abc3221783d089799b69394 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 20 Mar 2014 15:30:14 +0100 Subject: compat: include linux/unistd.h within linux/compat.h linux/compat.h does not include linux/unistd.h but the compat.h header file contains various conditional #ifdef __ARCH_WANT_COMPAT_... asmlinkage long compat...() #endif compat system call function declarations. If linux/unistd.h isn't included it depends on previous includes if those __ARCH_WANT_COMPAT_... defines are defined or not. So add an additional linux/unistd.h include. Should fix this compile error on tile: include/uapi/asm-generic/unistd.h:195:1: error: 'compat_sys_getdents64' undeclared make[3]: *** [arch/tile/kernel/compat.o] Error 1 Reported-by: Geert Uytterhoeven Acked-by: Geert Uytterhoeven Acked-by: Chris Metcalf Signed-off-by: Heiko Carstens --- include/linux/compat.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/linux/compat.h b/include/linux/compat.h index 7c765624b7ef..01c0aa57ccec 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -14,6 +14,7 @@ #include #include #include /* for aio_context_t */ +#include #include #include -- cgit v1.2.3