From patchwork Mon Jun 19 06:45:09 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Deepa Dinamani X-Patchwork-Id: 9795259 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id DCCD36020B for ; Mon, 19 Jun 2017 06:46:44 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C5BFA27E71 for ; Mon, 19 Jun 2017 06:46:44 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BA57127FAD; Mon, 19 Jun 2017 06:46:44 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 07C1727E71 for ; Mon, 19 Jun 2017 06:46:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753735AbdFSGpv (ORCPT ); Mon, 19 Jun 2017 02:45:51 -0400 Received: from mail-pg0-f67.google.com ([74.125.83.67]:34162 "EHLO mail-pg0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751438AbdFSGpt (ORCPT ); Mon, 19 Jun 2017 02:45:49 -0400 Received: by mail-pg0-f67.google.com with SMTP id j186so14290679pge.1; Sun, 18 Jun 2017 23:45:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=kYdUhomd25WmCcE7Mm9e8hXgrxVVsTzYm7lko9oJS2s=; b=piZgxsuiJBX1wWVznHzVLSBpRkOqHVGYvrH/+C3MRMehNptWPhxYmLcdsiR2K/iuiu N//09HR7wk0mKql0AfbWGYOzRCy2+G0EvZxwGJySfluZotOkoOjbbn1ArDGRPaVOx+ar orjZjgyEBdxQ1xrUavDY8gTRqTsN7bQ5IQ3UZ5zzY51TYfNtvYUcieo1RcgpySLrZ72+ r/S1p2GqDUbDVbRs9+ZYvCLEtuh38pB6e9QQOXdwVMCApa4q8mI7ieNc3koIx9Cfz6KH MMhJy9XgoAWlxmNSd/aG0/tZQpoxyyXygFF4ttHsMWC05IGmATkndWslqjabkdjR6Qrx u2UA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=kYdUhomd25WmCcE7Mm9e8hXgrxVVsTzYm7lko9oJS2s=; b=tAaTr0cabLNPLqPbZBTCSOHdc1PHXN0mRkogZO8jZg8vYrPOIdsO+ra7zmU4BgI8U7 42k7EV937ZSh3qrpxXqjw/2YPShQvJjK0YhZfNUhdV9M1O5HyL2PRTZFg9shBTj31Wls +Kr/OTGO6lz0/JAs6UG+E0QcHKPhkQD1WF74ZF0kiZnAip8jIXowAZ9G3qmS598vdfaR DUvF3EfDD/Xglu550L0kpsceC+QttT1f770uCf7OG9J++LFqF33R5lNTdYvY2HyvDTUA MQwz+RcJytwQidUh8L67zNyByR6ArNQeX2kxGpIBMX7hL5ObNZvtU/AqyrNG81ZZQYaO ntIw== X-Gm-Message-State: AKS2vOylWpvwM67F83R3t08Zs9LyThN5/M2I6t8/PqspdzYebr+yJT1g LQytIQtAmObPsg== X-Received: by 10.98.86.132 with SMTP id h4mr23431042pfj.205.1497854743497; Sun, 18 Jun 2017 23:45:43 -0700 (PDT) Received: from localhost.localdomain ([2601:647:5000:6620:ecf7:aabb:b31b:424d]) by smtp.gmail.com with ESMTPSA id o66sm19620318pga.64.2017.06.18.23.45.42 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 18 Jun 2017 23:45:43 -0700 (PDT) From: Deepa Dinamani To: tglx@linutronix.de, viro@zeniv.linux.org.uk, linux-kernel@vger.kernel.org Cc: john.stultz@linaro.org, nicolas.pitre@linaro.org, arnd@arndb.de, y2038@lists.linaro.org, linux-fsdevel@vger.kernel.org Subject: [PATCH 2/8] nanosleep: Move native and compat syscalls Date: Sun, 18 Jun 2017 23:45:09 -0700 Message-Id: <20170619064515.922-3-deepa.kernel@gmail.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170619064515.922-1-deepa.kernel@gmail.com> References: <20170619064515.922-1-deepa.kernel@gmail.com> Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Move nanosleep syscall to a new file that is compiled unconditionally. This helps share common nanosleep code between posix-timers and posix-stubs. The latter part is addressed in subsequent patches in the series. In this series, this also servers as a preparatory patch to eliminate the use of set_fs()/get_fs() in the compat syscall path. Note that the clock_nanosleep compat syscalls have to be moved twice, once into each file: posix_timers.c and posix-stubs.c. Signed-off-by: Deepa Dinamani --- kernel/compat.c | 131 --------------------------------------------- kernel/time/hrtimer.c | 17 +----- kernel/time/nanosleep.c | 94 ++++++++++++++++++++++++++++++++ kernel/time/posix-stubs.c | 56 +++++++++++++++++++ kernel/time/posix-timers.c | 58 ++++++++++++++++++++ 5 files changed, 209 insertions(+), 147 deletions(-) create mode 100644 kernel/time/nanosleep.c diff --git a/kernel/compat.c b/kernel/compat.c index c7a01a01222d..89d10cf47e9c 100644 --- a/kernel/compat.c +++ b/kernel/compat.c @@ -257,82 +257,6 @@ int compat_convert_timespec(struct timespec __user **kts, return 0; } -static long compat_nanosleep_restart(struct restart_block *restart) -{ - struct compat_timespec __user *rmtp; - struct timespec rmt; - mm_segment_t oldfs; - long ret; - - restart->nanosleep.rmtp = (struct timespec __user *) &rmt; - oldfs = get_fs(); - set_fs(KERNEL_DS); - ret = hrtimer_nanosleep_restart(restart); - set_fs(oldfs); - - if (ret == -ERESTART_RESTARTBLOCK) { - rmtp = restart->nanosleep.compat_rmtp; - - if (rmtp && compat_put_timespec(&rmt, rmtp)) - return -EFAULT; - } - - return ret; -} - -COMPAT_SYSCALL_DEFINE2(nanosleep, struct compat_timespec __user *, rqtp, - struct compat_timespec __user *, rmtp) -{ - struct timespec tu, rmt; - struct timespec64 tu64; - mm_segment_t oldfs; - long ret; - - if (compat_get_timespec(&tu, rqtp)) - return -EFAULT; - - tu64 = timespec_to_timespec64(tu); - if (!timespec64_valid(&tu64)) - return -EINVAL; - - oldfs = get_fs(); - set_fs(KERNEL_DS); - ret = hrtimer_nanosleep(&tu64, - rmtp ? (struct timespec __user *)&rmt : NULL, - HRTIMER_MODE_REL, CLOCK_MONOTONIC); - set_fs(oldfs); - - /* - * hrtimer_nanosleep() can only return 0 or - * -ERESTART_RESTARTBLOCK here because: - * - * - we call it with HRTIMER_MODE_REL and therefor exclude the - * -ERESTARTNOHAND return path. - * - * - we supply the rmtp argument from the task stack (due to - * the necessary compat conversion. So the update cannot - * fail, which excludes the -EFAULT return path as well. If - * it fails nevertheless we have a bigger problem and wont - * reach this place anymore. - * - * - if the return value is 0, we do not have to update rmtp - * because there is no remaining time. - * - * We check for -ERESTART_RESTARTBLOCK nevertheless if the - * core implementation decides to return random nonsense. - */ - if (ret == -ERESTART_RESTARTBLOCK) { - struct restart_block *restart = ¤t->restart_block; - - restart->fn = compat_nanosleep_restart; - restart->nanosleep.compat_rmtp = rmtp; - - if (rmtp && compat_put_timespec(&rmt, rmtp)) - return -EFAULT; - } - return ret; -} - static inline long get_compat_itimerval(struct itimerval *o, struct compat_itimerval __user *i) { @@ -865,61 +789,6 @@ COMPAT_SYSCALL_DEFINE2(clock_getres, clockid_t, which_clock, return err; } -static long compat_clock_nanosleep_restart(struct restart_block *restart) -{ - long err; - mm_segment_t oldfs; - struct timespec tu; - struct compat_timespec __user *rmtp = restart->nanosleep.compat_rmtp; - - restart->nanosleep.rmtp = (struct timespec __user *) &tu; - oldfs = get_fs(); - set_fs(KERNEL_DS); - err = clock_nanosleep_restart(restart); - set_fs(oldfs); - - if ((err == -ERESTART_RESTARTBLOCK) && rmtp && - compat_put_timespec(&tu, rmtp)) - return -EFAULT; - - if (err == -ERESTART_RESTARTBLOCK) { - restart->fn = compat_clock_nanosleep_restart; - restart->nanosleep.compat_rmtp = rmtp; - } - return err; -} - -COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags, - struct compat_timespec __user *, rqtp, - struct compat_timespec __user *, rmtp) -{ - long err; - mm_segment_t oldfs; - struct timespec in, out; - struct restart_block *restart; - - if (compat_get_timespec(&in, rqtp)) - return -EFAULT; - - oldfs = get_fs(); - set_fs(KERNEL_DS); - err = sys_clock_nanosleep(which_clock, flags, - (struct timespec __user *) &in, - (struct timespec __user *) &out); - set_fs(oldfs); - - if ((err == -ERESTART_RESTARTBLOCK) && rmtp && - compat_put_timespec(&out, rmtp)) - return -EFAULT; - - if (err == -ERESTART_RESTARTBLOCK) { - restart = ¤t->restart_block; - restart->fn = compat_clock_nanosleep_restart; - restart->nanosleep.compat_rmtp = rmtp; - } - return err; -} - /* * We currently only need the following fields from the sigevent * structure: sigev_value, sigev_signo, sig_notify and (sometimes diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index ac053bb5296e..e95628910b00 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -1544,22 +1545,6 @@ long hrtimer_nanosleep(struct timespec64 *rqtp, struct timespec __user *rmtp, return ret; } -SYSCALL_DEFINE2(nanosleep, struct timespec __user *, rqtp, - struct timespec __user *, rmtp) -{ - struct timespec64 tu64; - struct timespec tu; - - if (copy_from_user(&tu, rqtp, sizeof(tu))) - return -EFAULT; - - tu64 = timespec_to_timespec64(tu); - if (!timespec64_valid(&tu64)) - return -EINVAL; - - return hrtimer_nanosleep(&tu64, rmtp, HRTIMER_MODE_REL, CLOCK_MONOTONIC); -} - /* * Functions related to boot-time initialization: */ diff --git a/kernel/time/nanosleep.c b/kernel/time/nanosleep.c new file mode 100644 index 000000000000..2b6e6980b65d --- /dev/null +++ b/kernel/time/nanosleep.c @@ -0,0 +1,94 @@ +SYSCALL_DEFINE2(nanosleep, struct timespec __user *, rqtp, + struct timespec __user *, rmtp) +{ + struct timespec64 tu64; + struct timespec tu; + + if (copy_from_user(&tu, rqtp, sizeof(tu))) + return -EFAULT; + + tu64 = timespec_to_timespec64(tu); + if (!timespec64_valid(&tu64)) + return -EINVAL; + + return hrtimer_nanosleep(&tu64, rmtp, HRTIMER_MODE_REL, CLOCK_MONOTONIC); +} + +#ifdef CONFIG_COMPAT +static long compat_nanosleep_restart(struct restart_block *restart) +{ + struct compat_timespec __user *rmtp; + struct timespec rmt; + mm_segment_t oldfs; + long ret; + + restart->nanosleep.rmtp = (struct timespec __user *) &rmt; + oldfs = get_fs(); + set_fs(KERNEL_DS); + ret = hrtimer_nanosleep_restart(restart); + set_fs(oldfs); + + if (ret == -ERESTART_RESTARTBLOCK) { + rmtp = restart->nanosleep.compat_rmtp; + + if (rmtp && compat_put_timespec(&rmt, rmtp)) + return -EFAULT; + } + + return ret; +} + +COMPAT_SYSCALL_DEFINE2(nanosleep, struct compat_timespec __user *, rqtp, + struct compat_timespec __user *, rmtp) +{ + struct timespec tu, rmt; + struct timespec64 tu64; + mm_segment_t oldfs; + long ret; + + if (compat_get_timespec(&tu, rqtp)) + return -EFAULT; + + tu64 = timespec_to_timespec64(tu); + if (!timespec64_valid(&tu64)) + return -EINVAL; + + oldfs = get_fs(); + set_fs(KERNEL_DS); + ret = hrtimer_nanosleep(&tu64, + rmtp ? (struct timespec __user *)&rmt : NULL, + HRTIMER_MODE_REL, CLOCK_MONOTONIC); + set_fs(oldfs); + + /* + * hrtimer_nanosleep() can only return 0 or + * -ERESTART_RESTARTBLOCK here because: + * + * - we call it with HRTIMER_MODE_REL and therefor exclude the + * -ERESTARTNOHAND return path. + * + * - we supply the rmtp argument from the task stack (due to + * the necessary compat conversion. So the update cannot + * fail, which excludes the -EFAULT return path as well. If + * it fails nevertheless we have a bigger problem and wont + * reach this place anymore. + * + * - if the return value is 0, we do not have to update rmtp + * because there is no remaining time. + * + * We check for -ERESTART_RESTARTBLOCK nevertheless if the + * core implementation decides to return random nonsense. + */ + if (ret == -ERESTART_RESTARTBLOCK) { + struct restart_block *restart = ¤t->restart_block; + + restart->fn = compat_nanosleep_restart; + restart->nanosleep.compat_rmtp = rmtp; + + if (rmtp && compat_put_timespec(&rmt, rmtp)) + return -EFAULT; + } + return ret; +} +#endif + diff --git a/kernel/time/posix-stubs.c b/kernel/time/posix-stubs.c index c0cd53eb018a..3031a28921ba 100644 --- a/kernel/time/posix-stubs.c +++ b/kernel/time/posix-stubs.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -128,4 +129,59 @@ long clock_nanosleep_restart(struct restart_block *restart_block) { return hrtimer_nanosleep_restart(restart_block); } + +static long compat_clock_nanosleep_restart(struct restart_block *restart) +{ + long err; + mm_segment_t oldfs; + struct timespec tu; + struct compat_timespec __user *rmtp = restart->nanosleep.compat_rmtp; + + restart->nanosleep.rmtp = (struct timespec __user *) &tu; + oldfs = get_fs(); + set_fs(KERNEL_DS); + err = clock_nanosleep_restart(restart); + set_fs(oldfs); + + if ((err == -ERESTART_RESTARTBLOCK) && rmtp && + compat_put_timespec(&tu, rmtp)) + return -EFAULT; + + if (err == -ERESTART_RESTARTBLOCK) { + restart->fn = compat_clock_nanosleep_restart; + restart->nanosleep.compat_rmtp = rmtp; + } + return err; +} + +COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags, + struct compat_timespec __user *, rqtp, + struct compat_timespec __user *, rmtp) +{ + long err; + mm_segment_t oldfs; + struct timespec in, out; + struct restart_block *restart; + + if (compat_get_timespec(&in, rqtp)) + return -EFAULT; + + oldfs = get_fs(); + set_fs(KERNEL_DS); + err = sys_clock_nanosleep(which_clock, flags, + (struct timespec __user *) &in, + (struct timespec __user *) &out); + set_fs(oldfs); + + if ((err == -ERESTART_RESTARTBLOCK) && rmtp && + compat_put_timespec(&out, rmtp)) + return -EFAULT; + + if (err == -ERESTART_RESTARTBLOCK) { + restart = ¤t->restart_block; + restart->fn = compat_clock_nanosleep_restart; + restart->nanosleep.compat_rmtp = rmtp; + } + return err; +} #endif diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c index 6e7a70b1bf37..cf32adccd062 100644 --- a/kernel/time/posix-timers.c +++ b/kernel/time/posix-timers.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -1176,3 +1177,60 @@ static const struct k_clock *clockid_to_kclock(const clockid_t id) return NULL; return posix_clocks[id]; } + +#ifdef CONFIG_COMPAT +static long compat_clock_nanosleep_restart(struct restart_block *restart) +{ + long err; + mm_segment_t oldfs; + struct timespec tu; + struct compat_timespec __user *rmtp = restart->nanosleep.compat_rmtp; + + restart->nanosleep.rmtp = (struct timespec __user *) &tu; + oldfs = get_fs(); + set_fs(KERNEL_DS); + err = clock_nanosleep_restart(restart); + set_fs(oldfs); + + if ((err == -ERESTART_RESTARTBLOCK) && rmtp && + compat_put_timespec(&tu, rmtp)) + return -EFAULT; + + if (err == -ERESTART_RESTARTBLOCK) { + restart->fn = compat_clock_nanosleep_restart; + restart->nanosleep.compat_rmtp = rmtp; + } + return err; +} + +COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags, + struct compat_timespec __user *, rqtp, + struct compat_timespec __user *, rmtp) +{ + long err; + mm_segment_t oldfs; + struct timespec in, out; + struct restart_block *restart; + + if (compat_get_timespec(&in, rqtp)) + return -EFAULT; + + oldfs = get_fs(); + set_fs(KERNEL_DS); + err = sys_clock_nanosleep(which_clock, flags, + (struct timespec __user *) &in, + (struct timespec __user *) &out); + set_fs(oldfs); + + if ((err == -ERESTART_RESTARTBLOCK) && rmtp && + compat_put_timespec(&out, rmtp)) + return -EFAULT; + + if (err == -ERESTART_RESTARTBLOCK) { + restart = ¤t->restart_block; + restart->fn = compat_clock_nanosleep_restart; + restart->nanosleep.compat_rmtp = rmtp; + } + return err; +} +#endif