Commit 29f1b2b0 authored by Nick Desaulniers's avatar Nick Desaulniers Committed by Thomas Gleixner

posix-timers: Prevent UB from shifting negative signed value

Shifting a negative signed number is undefined behavior. Looking at the
macros MAKE_PROCESS_CPUCLOCK and FD_TO_CLOCKID, it seems that the
subexpression:

(~(clockid_t) (pid) << 3)

where clockid_t resolves to a signed int, which once negated, is
undefined behavior to shift the value of if the results thus far are
negative.

It was further suggested to make these macros into inline functions.
Suggested-by: default avatarThomas Gleixner <tglx@linutronix.de>
Signed-off-by: default avatarNick Desaulniers <nick.desaulniers@gmail.com>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Cc: Dimitri Sivanich <sivanich@hpe.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: linux-kselftest@vger.kernel.org
Cc: Shuah Khan <shuah@kernel.org>
Cc: Deepa Dinamani <deepa.kernel@gmail.com>
Link: https://lkml.kernel.org/r/1514517100-18051-1-git-send-email-nick.desaulniers@gmail.com
parent 00a5ae21
...@@ -42,13 +42,26 @@ struct cpu_timer_list { ...@@ -42,13 +42,26 @@ struct cpu_timer_list {
#define CLOCKFD CPUCLOCK_MAX #define CLOCKFD CPUCLOCK_MAX
#define CLOCKFD_MASK (CPUCLOCK_PERTHREAD_MASK|CPUCLOCK_CLOCK_MASK) #define CLOCKFD_MASK (CPUCLOCK_PERTHREAD_MASK|CPUCLOCK_CLOCK_MASK)
#define MAKE_PROCESS_CPUCLOCK(pid, clock) \ static inline clockid_t make_process_cpuclock(const unsigned int pid,
((~(clockid_t) (pid) << 3) | (clockid_t) (clock)) const clockid_t clock)
#define MAKE_THREAD_CPUCLOCK(tid, clock) \ {
MAKE_PROCESS_CPUCLOCK((tid), (clock) | CPUCLOCK_PERTHREAD_MASK) return ((~pid) << 3) | clock;
}
static inline clockid_t make_thread_cpuclock(const unsigned int tid,
const clockid_t clock)
{
return make_process_cpuclock(tid, clock | CPUCLOCK_PERTHREAD_MASK);
}
#define FD_TO_CLOCKID(fd) ((~(clockid_t) (fd) << 3) | CLOCKFD) static inline clockid_t fd_to_clockid(const int fd)
#define CLOCKID_TO_FD(clk) ((unsigned int) ~((clk) >> 3)) {
return make_process_cpuclock((unsigned int) fd, CLOCKFD);
}
static inline int clockid_to_fd(const clockid_t clk)
{
return ~(clk >> 3);
}
#define REQUEUE_PENDING 1 #define REQUEUE_PENDING 1
......
...@@ -216,7 +216,7 @@ struct posix_clock_desc { ...@@ -216,7 +216,7 @@ struct posix_clock_desc {
static int get_clock_desc(const clockid_t id, struct posix_clock_desc *cd) static int get_clock_desc(const clockid_t id, struct posix_clock_desc *cd)
{ {
struct file *fp = fget(CLOCKID_TO_FD(id)); struct file *fp = fget(clockid_to_fd(id));
int err = -EINVAL; int err = -EINVAL;
if (!fp) if (!fp)
......
...@@ -1363,8 +1363,8 @@ static long posix_cpu_nsleep_restart(struct restart_block *restart_block) ...@@ -1363,8 +1363,8 @@ static long posix_cpu_nsleep_restart(struct restart_block *restart_block)
return do_cpu_nanosleep(which_clock, TIMER_ABSTIME, &t); return do_cpu_nanosleep(which_clock, TIMER_ABSTIME, &t);
} }
#define PROCESS_CLOCK MAKE_PROCESS_CPUCLOCK(0, CPUCLOCK_SCHED) #define PROCESS_CLOCK make_process_cpuclock(0, CPUCLOCK_SCHED)
#define THREAD_CLOCK MAKE_THREAD_CPUCLOCK(0, CPUCLOCK_SCHED) #define THREAD_CLOCK make_thread_cpuclock(0, CPUCLOCK_SCHED)
static int process_cpu_clock_getres(const clockid_t which_clock, static int process_cpu_clock_getres(const clockid_t which_clock,
struct timespec64 *tp) struct timespec64 *tp)
......
...@@ -60,9 +60,7 @@ static int clock_adjtime(clockid_t id, struct timex *tx) ...@@ -60,9 +60,7 @@ static int clock_adjtime(clockid_t id, struct timex *tx)
static clockid_t get_clockid(int fd) static clockid_t get_clockid(int fd)
{ {
#define CLOCKFD 3 #define CLOCKFD 3
#define FD_TO_CLOCKID(fd) ((~(clockid_t) (fd) << 3) | CLOCKFD) return (((unsigned int) ~fd) << 3) | CLOCKFD;
return FD_TO_CLOCKID(fd);
} }
static void handle_alarm(int s) static void handle_alarm(int s)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment