From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 63C29C43463 for ; Fri, 18 Sep 2020 12:46:59 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 0941520717 for ; Fri, 18 Sep 2020 12:46:59 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 0941520717 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=arndb.de Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id 9134A6B005D; Fri, 18 Sep 2020 08:46:42 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 4A940900002; Fri, 18 Sep 2020 08:46:42 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 2D2E16B005D; Fri, 18 Sep 2020 08:46:42 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0155.hostedemail.com [216.40.44.155]) by kanga.kvack.org (Postfix) with ESMTP id 007FD6B006C for ; Fri, 18 Sep 2020 08:46:41 -0400 (EDT) Received: from smtpin28.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay02.hostedemail.com (Postfix) with ESMTP id BBA373629 for ; Fri, 18 Sep 2020 12:46:41 +0000 (UTC) X-FDA: 77276156202.28.ink64_59127112712b Received: from filter.hostedemail.com (10.5.16.251.rfc1918.com [10.5.16.251]) by smtpin28.hostedemail.com (Postfix) with ESMTP id 920EE6C04 for ; Fri, 18 Sep 2020 12:46:41 +0000 (UTC) X-HE-Tag: ink64_59127112712b X-Filterd-Recvd-Size: 11607 Received: from mout.kundenserver.de (mout.kundenserver.de [212.227.126.131]) by imf01.hostedemail.com (Postfix) with ESMTP for ; Fri, 18 Sep 2020 12:46:40 +0000 (UTC) Received: from threadripper.lan ([149.172.98.151]) by mrelayeu.kundenserver.de (mreue011 [212.227.15.129]) with ESMTPA (Nemesis) id 1Mo77T-1kquu045z1-00peri; Fri, 18 Sep 2020 14:46:36 +0200 From: Arnd Bergmann To: Christoph Hellwig , Russell King , Alexander Viro Cc: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-arch@vger.kernel.org, linux-mm@kvack.org, Arnd Bergmann Subject: [PATCH v2 6/9] ARM: oabi-compat: rework sys_semtimedop emulation Date: Fri, 18 Sep 2020 14:46:21 +0200 Message-Id: <20200918124624.1469673-7-arnd@arndb.de> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200918124624.1469673-1-arnd@arndb.de> References: <20200918124624.1469673-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:OQM9k0kPghNnhr7huCyGsgsG9yt+ewhCkjkk1yCN4GHBE0dHqyG Od/WZv9NSjWM+UYqlwIWwhouyXoZFMOcsiFMShpMX57fox3x1M7ncV7zdFB3idmqO+KtVwB hqh8dh5MWw6xajNFjIu5ze4b3eM3mpzMRjDswsqXQ6mOZQ36k9yieMcv5Wt0oy29H2sef4N IQYmuP/GhfckbDfgwbJCA== X-UI-Out-Filterresults: notjunk:1;V03:K0:MmguxKmUUwc=:9kYi+keea4iOvvMApXUH/3 UCBxQDGyd1wflj5PwUSypPMMrT38GLB6kp44alrM6DIVux2gdmxJxzN5Z2Kz38TyhzfC+3yqt yGjhvgNnbe9jC2WUBzcwTFHUEeB+OoFMGnkcCccc5y3efJL2Az017Nsrfsy5ixqwtXnKTnmdk hMf1mGT1dtD5ahraMva6u0mL7sB72KCg0//34WVI2KW/tXzXVLtbYVVHyY/doYNXI17ekVroW XcpfAkQYS0TtuICXVltbjQGDjQDdCq+hAezDQAQ/yGX8UXS19Poj185LT/OzOeVMcimBj2NiE 7nlPjX6+27Z61syeTB4kFttP7PeQ87APUxv6z65sRjoSXaipPJyMmCVn16LeYBeU3Dr8D/SWF Y3DwmZTt5SW1iR++Lf/Rt74n/CQPllFOib1Aj+6G9QfjzqO2u272HOFN08ayGpuU722l0C+wE c6Oiz2SIKCv/lkwYhPV/5AXAwb2AAxSjvdNIYUL5Huqgv+HuofY69KyF/dqLwDCf83Q4VGScB dP7UptKjdvzdK1TPrvxsPujfWgQ1WrDt/gIZ4kMUHmY4/JHO4GG7xbC2w8Wb33JQ++iYMbSN5 ge2JUEoxsjuJNV1k6rSkw0VBlWjhWtiHdauIVrWZX2hY5RXvr9h8nor2RIk47gn+IjLCJrFK9 F1aE2428ow59aogGSHk75qHNoLWcK4Q+GLBGt3CvSvhc57nVPHzxIY8uGLG1Shu/301t5zMMZ U+EctU9kNdi5xPI08R/7I65WseruLPbta21ZMw0HTLS5+6tBqOJdLkeeiWF2qLa7hb+1Vo74i z2EiAHNG3WfKwyB7xpW0BwNz49/C3GdYJGOR0GCQp+7vZxv+PSNJDrA6jXxqL8vc+QxsHFt Content-Transfer-Encoding: quoted-printable X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: sys_oabi_semtimedop() is one of the last users of set_fs() on Arm. To remove this one, expose the internal code of the actual implementation that operates on a kernel pointer and call it directly after copying. There should be no measurable impact on the normal execution of this function, and it makes the overly long function a little shorter, which may help readability. While reworking the oabi version, make it behave a little more like the native one, using kvmalloc_array() and restructure the code flow in a similar way. The naming of __do_semtimedop() is not very good, I hope someone can come up with a better name. One regression was spotted by kernel test robot and fixed before the first mailing list submission. Signed-off-by: Arnd Bergmann --- arch/arm/kernel/sys_oabi-compat.c | 38 ++++++++------ include/linux/syscalls.h | 3 ++ ipc/sem.c | 84 +++++++++++++++++++------------ 3 files changed, 77 insertions(+), 48 deletions(-) diff --git a/arch/arm/kernel/sys_oabi-compat.c b/arch/arm/kernel/sys_oabi= -compat.c index f9d8e5be6ba0..c3e63b73b6ae 100644 --- a/arch/arm/kernel/sys_oabi-compat.c +++ b/arch/arm/kernel/sys_oabi-compat.c @@ -80,6 +80,7 @@ #include #include #include +#include #include #include =20 @@ -294,46 +295,51 @@ struct oabi_sembuf { unsigned short __pad; }; =20 +#define sc_semopm sem_ctls[2] + asmlinkage long sys_oabi_semtimedop(int semid, struct oabi_sembuf __user *tsops, unsigned nsops, const struct old_timespec32 __user *timeout) { + struct ipc_namespace *ns; struct sembuf *sops; - struct old_timespec32 local_timeout; long err; int i; =20 + ns =3D current->nsproxy->ipc_ns; + if (nsops > ns->sc_semopm) + return -E2BIG; if (nsops < 1 || nsops > SEMOPM) return -EINVAL; - if (!access_ok(tsops, sizeof(*tsops) * nsops)) - return -EFAULT; - sops =3D kmalloc_array(nsops, sizeof(*sops), GFP_KERNEL); + sops =3D kvmalloc_array(nsops, sizeof(*sops), GFP_KERNEL); if (!sops) return -ENOMEM; err =3D 0; for (i =3D 0; i < nsops; i++) { struct oabi_sembuf osb; - err |=3D __copy_from_user(&osb, tsops, sizeof(osb)); + err |=3D copy_from_user(&osb, tsops, sizeof(osb)); sops[i].sem_num =3D osb.sem_num; sops[i].sem_op =3D osb.sem_op; sops[i].sem_flg =3D osb.sem_flg; tsops++; } - if (timeout) { - /* copy this as well before changing domain protection */ - err |=3D copy_from_user(&local_timeout, timeout, sizeof(*timeout)); - timeout =3D &local_timeout; - } if (err) { err =3D -EFAULT; - } else { - mm_segment_t fs =3D get_fs(); - set_fs(KERNEL_DS); - err =3D sys_semtimedop_time32(semid, sops, nsops, timeout); - set_fs(fs); + goto out; + } + + if (timeout) { + struct timespec64 ts; + err =3D get_old_timespec32(&ts, timeout); + if (err) + goto out; + err =3D __do_semtimedop(semid, sops, nsops, &ts, ns); + goto out; } - kfree(sops); + err =3D __do_semtimedop(semid, sops, nsops, NULL, ns); +out: + kvfree(sops); return err; } =20 diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 75ac7f8ae93c..bb5ed3a712a5 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -1340,6 +1340,9 @@ long ksys_old_shmctl(int shmid, int cmd, struct shm= id_ds __user *buf); long compat_ksys_semtimedop(int semid, struct sembuf __user *tsems, unsigned int nsops, const struct old_timespec32 __user *timeout); +long __do_semtimedop(int semid, struct sembuf *tsems, unsigned int nsops= , + const struct timespec64 *timeout, + struct ipc_namespace *ns); =20 int __sys_getsockopt(int fd, int level, int optname, char __user *optval= , int __user *optlen); diff --git a/ipc/sem.c b/ipc/sem.c index 8c0244e0365e..515a39a67534 100644 --- a/ipc/sem.c +++ b/ipc/sem.c @@ -1978,46 +1978,34 @@ static struct sem_undo *find_alloc_undo(struct ip= c_namespace *ns, int semid) return un; } =20 -static long do_semtimedop(int semid, struct sembuf __user *tsops, - unsigned nsops, const struct timespec64 *timeout) +long __do_semtimedop(int semid, struct sembuf *sops, + unsigned nsops, const struct timespec64 *timeout, + struct ipc_namespace *ns) { int error =3D -EINVAL; struct sem_array *sma; - struct sembuf fast_sops[SEMOPM_FAST]; - struct sembuf *sops =3D fast_sops, *sop; + struct sembuf *sop; struct sem_undo *un; int max, locknum; bool undos =3D false, alter =3D false, dupsop =3D false; struct sem_queue queue; unsigned long dup =3D 0, jiffies_left =3D 0; - struct ipc_namespace *ns; - - ns =3D current->nsproxy->ipc_ns; =20 if (nsops < 1 || semid < 0) return -EINVAL; if (nsops > ns->sc_semopm) return -E2BIG; - if (nsops > SEMOPM_FAST) { - sops =3D kvmalloc_array(nsops, sizeof(*sops), GFP_KERNEL); - if (sops =3D=3D NULL) - return -ENOMEM; - } - - if (copy_from_user(sops, tsops, nsops * sizeof(*tsops))) { - error =3D -EFAULT; - goto out_free; - } =20 if (timeout) { if (timeout->tv_sec < 0 || timeout->tv_nsec < 0 || timeout->tv_nsec >=3D 1000000000L) { error =3D -EINVAL; - goto out_free; + goto out; } jiffies_left =3D timespec64_to_jiffies(timeout); } =20 + max =3D 0; for (sop =3D sops; sop < sops + nsops; sop++) { unsigned long mask =3D 1ULL << ((sop->sem_num) % BITS_PER_LONG); @@ -2046,7 +2034,7 @@ static long do_semtimedop(int semid, struct sembuf = __user *tsops, un =3D find_alloc_undo(ns, semid); if (IS_ERR(un)) { error =3D PTR_ERR(un); - goto out_free; + goto out; } } else { un =3D NULL; @@ -2057,25 +2045,25 @@ static long do_semtimedop(int semid, struct sembu= f __user *tsops, if (IS_ERR(sma)) { rcu_read_unlock(); error =3D PTR_ERR(sma); - goto out_free; + goto out; } =20 error =3D -EFBIG; if (max >=3D sma->sem_nsems) { rcu_read_unlock(); - goto out_free; + goto out; } =20 error =3D -EACCES; if (ipcperms(ns, &sma->sem_perm, alter ? S_IWUGO : S_IRUGO)) { rcu_read_unlock(); - goto out_free; + goto out; } =20 error =3D security_sem_semop(&sma->sem_perm, sops, nsops, alter); if (error) { rcu_read_unlock(); - goto out_free; + goto out; } =20 error =3D -EIDRM; @@ -2089,7 +2077,7 @@ static long do_semtimedop(int semid, struct sembuf = __user *tsops, * entangled here and why it's RMID race safe on comments at sem_lock() */ if (!ipc_valid_object(&sma->sem_perm)) - goto out_unlock_free; + goto out_unlock; /* * semid identifiers are not unique - find_alloc_undo may have * allocated an undo structure, it was invalidated by an RMID @@ -2098,7 +2086,7 @@ static long do_semtimedop(int semid, struct sembuf = __user *tsops, * "un" itself is guaranteed by rcu. */ if (un && un->semid =3D=3D -1) - goto out_unlock_free; + goto out_unlock; =20 queue.sops =3D sops; queue.nsops =3D nsops; @@ -2124,10 +2112,10 @@ static long do_semtimedop(int semid, struct sembu= f __user *tsops, rcu_read_unlock(); wake_up_q(&wake_q); =20 - goto out_free; + goto out; } if (error < 0) /* non-blocking error path */ - goto out_unlock_free; + goto out_unlock; =20 /* * We need to sleep on this operation, so we put the current @@ -2192,14 +2180,14 @@ static long do_semtimedop(int semid, struct sembu= f __user *tsops, if (error !=3D -EINTR) { /* see SEM_BARRIER_2 for purpose/pairing */ smp_acquire__after_ctrl_dep(); - goto out_free; + goto out; } =20 rcu_read_lock(); locknum =3D sem_lock(sma, sops, nsops); =20 if (!ipc_valid_object(&sma->sem_perm)) - goto out_unlock_free; + goto out_unlock; =20 /* * No necessity for any barrier: We are protect by sem_lock() @@ -2211,7 +2199,7 @@ static long do_semtimedop(int semid, struct sembuf = __user *tsops, * Leave without unlink_queue(), but with sem_unlock(). */ if (error !=3D -EINTR) - goto out_unlock_free; + goto out_unlock; =20 /* * If an interrupt occurred we have to clean up the queue. @@ -2222,13 +2210,45 @@ static long do_semtimedop(int semid, struct sembu= f __user *tsops, =20 unlink_queue(sma, &queue); =20 -out_unlock_free: +out_unlock: sem_unlock(sma, locknum); rcu_read_unlock(); +out: + return error; +} + +static long do_semtimedop(int semid, struct sembuf __user *tsops, + unsigned nsops, const struct timespec64 *timeout) +{ + struct sembuf fast_sops[SEMOPM_FAST]; + struct sembuf *sops =3D fast_sops; + struct ipc_namespace *ns; + int ret; + + ns =3D current->nsproxy->ipc_ns; + if (nsops > ns->sc_semopm) + return -E2BIG; + if (nsops < 1) + return -EINVAL; + + if (nsops > SEMOPM_FAST) { + sops =3D kvmalloc_array(nsops, sizeof(*sops), GFP_KERNEL); + if (sops =3D=3D NULL) + return -ENOMEM; + } + + if (copy_from_user(sops, tsops, nsops * sizeof(*tsops))) { + ret =3D -EFAULT; + goto out_free; + } + + ret =3D __do_semtimedop(semid, sops, nsops, timeout, ns); + out_free: if (sops !=3D fast_sops) kvfree(sops); - return error; + + return ret; } =20 long ksys_semtimedop(int semid, struct sembuf __user *tsops, --=20 2.27.0