Message ID | 20191108211323.1806194-11-arnd@arndb.de |
---|---|
State | Accepted |
Commit | ddbc7d0657e9fd38b69f16bd0310703367b52d29 |
Headers | show |
Series | y2038 cleanups | expand |
On Fri, Nov 8, 2019 at 10:18 PM Arnd Bergmann <arnd@arndb.de> wrote: > Preparing for a change to the itimer internals, stop using the > do_setitimer() symbol and instead use a new higher-level interface. > > The do_getitimer()/do_setitimer functions can now be made static, > allowing the compiler to potentially produce better object code. > > Signed-off-by: Arnd Bergmann <arnd@arndb.de> > --- > include/linux/time.h | 9 +++++---- > kernel/time/itimer.c | 15 +++++++++++++-- > security/selinux/hooks.c | 10 +++------- > 3 files changed, 21 insertions(+), 13 deletions(-) > > diff --git a/include/linux/time.h b/include/linux/time.h > index 27d83fd2ae61..0760a4f5a15c 100644 > --- a/include/linux/time.h > +++ b/include/linux/time.h > @@ -35,10 +35,11 @@ extern time64_t mktime64(const unsigned int year, const unsigned int mon, > extern u32 (*arch_gettimeoffset)(void); > #endif > > -struct itimerval; > -extern int do_setitimer(int which, struct itimerval *value, > - struct itimerval *ovalue); > -extern int do_getitimer(int which, struct itimerval *value); > +#ifdef CONFIG_POSIX_TIMERS > +extern void clear_itimer(void); > +#else > +static inline void clear_itimer(void) {} > +#endif > > extern long do_utimes(int dfd, const char __user *filename, struct timespec64 *times, int flags); > > diff --git a/kernel/time/itimer.c b/kernel/time/itimer.c > index 4664c6addf69..ce9cd19ce72e 100644 > --- a/kernel/time/itimer.c > +++ b/kernel/time/itimer.c > @@ -73,7 +73,7 @@ static void get_cpu_itimer(struct task_struct *tsk, unsigned int clock_id, > value->it_interval = ns_to_timeval(interval); > } > > -int do_getitimer(int which, struct itimerval *value) > +static int do_getitimer(int which, struct itimerval *value) > { > struct task_struct *tsk = current; > > @@ -197,7 +197,7 @@ static void set_cpu_itimer(struct task_struct *tsk, unsigned int clock_id, > #define timeval_valid(t) \ > (((t)->tv_sec >= 0) && (((unsigned long) (t)->tv_usec) < USEC_PER_SEC)) > > -int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue) > +static int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue) > { > struct task_struct *tsk = current; > struct hrtimer *timer; > @@ -249,6 +249,17 @@ int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue) > return 0; > } > > +#ifdef CONFIG_SECURITY_SELINUX Did you mean "#ifdef CONFIG_POSIX_TIMERS" here to match the header? > +void clear_itimer(void) > +{ > + struct itimerval v = {}; > + int i; > + > + for (i = 0; i < 3; i++) > + do_setitimer(i, &v, NULL); > +} > +#endif > + > #ifdef __ARCH_WANT_SYS_ALARM > > /** > diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c > index 9625b99e677f..c3f2e89acb87 100644 > --- a/security/selinux/hooks.c > +++ b/security/selinux/hooks.c > @@ -2549,9 +2549,8 @@ static void selinux_bprm_committing_creds(struct linux_binprm *bprm) > static void selinux_bprm_committed_creds(struct linux_binprm *bprm) > { > const struct task_security_struct *tsec = selinux_cred(current_cred()); > - struct itimerval itimer; > u32 osid, sid; > - int rc, i; > + int rc; > > osid = tsec->osid; > sid = tsec->sid; > @@ -2569,11 +2568,8 @@ static void selinux_bprm_committed_creds(struct linux_binprm *bprm) > rc = avc_has_perm(&selinux_state, > osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL); > if (rc) { > - if (IS_ENABLED(CONFIG_POSIX_TIMERS)) { > - memset(&itimer, 0, sizeof itimer); > - for (i = 0; i < 3; i++) > - do_setitimer(i, &itimer, NULL); > - } > + if (IS_ENABLED(CONFIG_POSIX_TIMERS)) > + clear_itimer(); Since you already define a no-op fallback for the case of !IS_ENABLED(CONFIG_POSIX_TIMERS) in time.h, why not simply call clear_itimer() unconditionally? > spin_lock_irq(¤t->sighand->siglock); > if (!fatal_signal_pending(current)) { > flush_sigqueue(¤t->pending); > -- > 2.20.0 > -- Ondrej Mosnacek <omosnace at redhat dot com> Software Engineer, Security Technologies Red Hat, Inc.
On Sat, Nov 9, 2019 at 2:43 PM Ondrej Mosnacek <omosnace@redhat.com> wrote: > > -struct itimerval; > > -extern int do_setitimer(int which, struct itimerval *value, > > - struct itimerval *ovalue); > > -extern int do_getitimer(int which, struct itimerval *value); > > +#ifdef CONFIG_POSIX_TIMERS > > +extern void clear_itimer(void); > > +#else > > +static inline void clear_itimer(void) {} > > +#endif > > > > @@ -249,6 +249,17 @@ int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue) > > return 0; > > } > > > > +#ifdef CONFIG_SECURITY_SELINUX > > Did you mean "#ifdef CONFIG_POSIX_TIMERS" here to match the header? No, this part is intentional, CONFIG_POSIX_TIMERS already controls whether itimer.c is compiled in the first place, but this function is only needed when called from the selinux driver. > > - } > > + if (IS_ENABLED(CONFIG_POSIX_TIMERS)) > > + clear_itimer(); > > Since you already define a no-op fallback for the case of > !IS_ENABLED(CONFIG_POSIX_TIMERS) in time.h, why not simply call > clear_itimer() unconditionally? Ah right, that was indeed my plan here when I changed the declaration in the header, I just forgot to remove the if(). Fixed now. Thanks for the review! Arnd
On Sat, Nov 9, 2019 at 10:03 PM Arnd Bergmann <arnd@arndb.de> wrote: > > On Sat, Nov 9, 2019 at 2:43 PM Ondrej Mosnacek <omosnace@redhat.com> wrote: > > > > -struct itimerval; > > > -extern int do_setitimer(int which, struct itimerval *value, > > > - struct itimerval *ovalue); > > > -extern int do_getitimer(int which, struct itimerval *value); > > > +#ifdef CONFIG_POSIX_TIMERS > > > +extern void clear_itimer(void); > > > +#else > > > +static inline void clear_itimer(void) {} > > > +#endif > > > > > > > @@ -249,6 +249,17 @@ int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue) > > > return 0; > > > } > > > > > > +#ifdef CONFIG_SECURITY_SELINUX > > > > Did you mean "#ifdef CONFIG_POSIX_TIMERS" here to match the header? > > No, this part is intentional, CONFIG_POSIX_TIMERS already controls > whether itimer.c is > compiled in the first place, but this function is only needed when called from > the selinux driver. All right, but you declare the function in time.h even if CONFIG_SECURITY_SELINUX is not enabled... it is kind of awkward when it can happen that the function is declared but not defined anywhere (even if it shouldn't be used by new users). Maybe you could at least put the header declaration/definition inside #ifdef CONFIG_SECURITY_SELINUX as well so it is clear that this function is intended for SELinux only? -- Ondrej Mosnacek <omosnace at redhat dot com> Software Engineer, Security Technologies Red Hat, Inc.
On Sun, Nov 10, 2019 at 12:07 AM Ondrej Mosnacek <omosnace@redhat.com> wrote: > > On Sat, Nov 9, 2019 at 10:03 PM Arnd Bergmann <arnd@arndb.de> wrote: > > > > On Sat, Nov 9, 2019 at 2:43 PM Ondrej Mosnacek <omosnace@redhat.com> wrote: > > > > > > -struct itimerval; > > > > -extern int do_setitimer(int which, struct itimerval *value, > > > > - struct itimerval *ovalue); > > > > -extern int do_getitimer(int which, struct itimerval *value); > > > > +#ifdef CONFIG_POSIX_TIMERS > > > > +extern void clear_itimer(void); > > > > +#else > > > > +static inline void clear_itimer(void) {} > > > > +#endif > > > > > > > > > > @@ -249,6 +249,17 @@ int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue) > > > > return 0; > > > > } > > > > > > > > +#ifdef CONFIG_SECURITY_SELINUX > > > > > > Did you mean "#ifdef CONFIG_POSIX_TIMERS" here to match the header? > > > > No, this part is intentional, CONFIG_POSIX_TIMERS already controls > > whether itimer.c is > > compiled in the first place, but this function is only needed when called from > > the selinux driver. > > All right, but you declare the function in time.h even if > CONFIG_SECURITY_SELINUX is not enabled... it is kind of awkward when > it can happen that the function is declared but not defined anywhere > (even if it shouldn't be used by new users). Maybe you could at least > put the header declaration/definition inside #ifdef > CONFIG_SECURITY_SELINUX as well so it is clear that this function is > intended for SELinux only? I don't see that as a problem, we rarely put declarations inside of an #ifdef. The main effect that would have is forcing any file that includes linux/time.h to be rebuilt when selinux is turned on or off in the .config. Arnd
On Fri, 8 Nov 2019, Arnd Bergmann wrote: > Preparing for a change to the itimer internals, stop using the > do_setitimer() symbol and instead use a new higher-level interface. > > The do_getitimer()/do_setitimer functions can now be made static, > allowing the compiler to potentially produce better object code. > > Signed-off-by: Arnd Bergmann <arnd@arndb.de> Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
On Mon, Nov 11, 2019 at 11:58 AM Arnd Bergmann <arnd@arndb.de> wrote: > > On Sun, Nov 10, 2019 at 12:07 AM Ondrej Mosnacek <omosnace@redhat.com> wrote: > > > > On Sat, Nov 9, 2019 at 10:03 PM Arnd Bergmann <arnd@arndb.de> wrote: > > > > > > On Sat, Nov 9, 2019 at 2:43 PM Ondrej Mosnacek <omosnace@redhat.com> wrote: > > > > > > > > -struct itimerval; > > > > > -extern int do_setitimer(int which, struct itimerval *value, > > > > > - struct itimerval *ovalue); > > > > > -extern int do_getitimer(int which, struct itimerval *value); > > > > > +#ifdef CONFIG_POSIX_TIMERS > > > > > +extern void clear_itimer(void); > > > > > +#else > > > > > +static inline void clear_itimer(void) {} > > > > > +#endif > > > > > > > > > > > > > @@ -249,6 +249,17 @@ int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue) > > > > > return 0; > > > > > } > > > > > > > > > > +#ifdef CONFIG_SECURITY_SELINUX > > > > > > > > Did you mean "#ifdef CONFIG_POSIX_TIMERS" here to match the header? > > > > > > No, this part is intentional, CONFIG_POSIX_TIMERS already controls > > > whether itimer.c is > > > compiled in the first place, but this function is only needed when called from > > > the selinux driver. > > > > All right, but you declare the function in time.h even if > > CONFIG_SECURITY_SELINUX is not enabled... it is kind of awkward when > > it can happen that the function is declared but not defined anywhere > > (even if it shouldn't be used by new users). Maybe you could at least > > put the header declaration/definition inside #ifdef > > CONFIG_SECURITY_SELINUX as well so it is clear that this function is > > intended for SELinux only? > > I don't see that as a problem, we rarely put declarations inside of an #ifdef. > The main effect that would have is forcing any file that includes linux/time.h > to be rebuilt when selinux is turned on or off in the .config. OK, but with this patch if someone tries to use the function elsewhere, the build will succeed if SELinux is enabled in the config, but fail if it isn't. Is that intended? I would suggest at least clearly documenting it above the declaration that the function isn't supposed to be used by new users and doing so will cause build to fail under CONFIG_SECURITY_SELINUX=n. -- Ondrej Mosnacek <omosnace at redhat dot com> Software Engineer, Security Technologies Red Hat, Inc.
On Thu, 14 Nov 2019, Ondrej Mosnacek wrote: > On Mon, Nov 11, 2019 at 11:58 AM Arnd Bergmann <arnd@arndb.de> wrote: > > I don't see that as a problem, we rarely put declarations inside of an #ifdef. > > The main effect that would have is forcing any file that includes linux/time.h > > to be rebuilt when selinux is turned on or off in the .config. > > OK, but with this patch if someone tries to use the function > elsewhere, the build will succeed if SELinux is enabled in the config, > but fail if it isn't. Is that intended? I would suggest at least > clearly documenting it above the declaration that the function isn't > supposed to be used by new users and doing so will cause build to fail > under CONFIG_SECURITY_SELINUX=n. Come on. We have enough functions in the kernel which are only available under a certain config option and if you (ab)use them elsewhere then the build fails. So what? The #ifdef documents the limited scope and intended use clearly. If something else really needs that function, then removing the #ifdef shouldn't be rocket science either. Thanks, tglx
diff --git a/include/linux/time.h b/include/linux/time.h index 27d83fd2ae61..0760a4f5a15c 100644 --- a/include/linux/time.h +++ b/include/linux/time.h @@ -35,10 +35,11 @@ extern time64_t mktime64(const unsigned int year, const unsigned int mon, extern u32 (*arch_gettimeoffset)(void); #endif -struct itimerval; -extern int do_setitimer(int which, struct itimerval *value, - struct itimerval *ovalue); -extern int do_getitimer(int which, struct itimerval *value); +#ifdef CONFIG_POSIX_TIMERS +extern void clear_itimer(void); +#else +static inline void clear_itimer(void) {} +#endif extern long do_utimes(int dfd, const char __user *filename, struct timespec64 *times, int flags); diff --git a/kernel/time/itimer.c b/kernel/time/itimer.c index 4664c6addf69..ce9cd19ce72e 100644 --- a/kernel/time/itimer.c +++ b/kernel/time/itimer.c @@ -73,7 +73,7 @@ static void get_cpu_itimer(struct task_struct *tsk, unsigned int clock_id, value->it_interval = ns_to_timeval(interval); } -int do_getitimer(int which, struct itimerval *value) +static int do_getitimer(int which, struct itimerval *value) { struct task_struct *tsk = current; @@ -197,7 +197,7 @@ static void set_cpu_itimer(struct task_struct *tsk, unsigned int clock_id, #define timeval_valid(t) \ (((t)->tv_sec >= 0) && (((unsigned long) (t)->tv_usec) < USEC_PER_SEC)) -int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue) +static int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue) { struct task_struct *tsk = current; struct hrtimer *timer; @@ -249,6 +249,17 @@ int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue) return 0; } +#ifdef CONFIG_SECURITY_SELINUX +void clear_itimer(void) +{ + struct itimerval v = {}; + int i; + + for (i = 0; i < 3; i++) + do_setitimer(i, &v, NULL); +} +#endif + #ifdef __ARCH_WANT_SYS_ALARM /** diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 9625b99e677f..c3f2e89acb87 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2549,9 +2549,8 @@ static void selinux_bprm_committing_creds(struct linux_binprm *bprm) static void selinux_bprm_committed_creds(struct linux_binprm *bprm) { const struct task_security_struct *tsec = selinux_cred(current_cred()); - struct itimerval itimer; u32 osid, sid; - int rc, i; + int rc; osid = tsec->osid; sid = tsec->sid; @@ -2569,11 +2568,8 @@ static void selinux_bprm_committed_creds(struct linux_binprm *bprm) rc = avc_has_perm(&selinux_state, osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL); if (rc) { - if (IS_ENABLED(CONFIG_POSIX_TIMERS)) { - memset(&itimer, 0, sizeof itimer); - for (i = 0; i < 3; i++) - do_setitimer(i, &itimer, NULL); - } + if (IS_ENABLED(CONFIG_POSIX_TIMERS)) + clear_itimer(); spin_lock_irq(¤t->sighand->siglock); if (!fatal_signal_pending(current)) { flush_sigqueue(¤t->pending);
Preparing for a change to the itimer internals, stop using the do_setitimer() symbol and instead use a new higher-level interface. The do_getitimer()/do_setitimer functions can now be made static, allowing the compiler to potentially produce better object code. Signed-off-by: Arnd Bergmann <arnd@arndb.de> --- include/linux/time.h | 9 +++++---- kernel/time/itimer.c | 15 +++++++++++++-- security/selinux/hooks.c | 10 +++------- 3 files changed, 21 insertions(+), 13 deletions(-) -- 2.20.0