Patch "posix-timer: Properly check sigevent->sigev_notify" has been added to the 4.14-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
posix-timer: Properly check sigevent->sigev_notify
to the 4.14-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
posix-timer-properly-check-sigevent-sigev_notify.patch
and it can be found in the queue-4.14 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
cef31d9af908243421258f1df35a4a644604efbeMon Sep 17 00:00:00 2001
From: Thomas Gleixner <[email protected]>
Date: Fri, 15 Dec 2017 10:32:03 +0100
Subject: posix-timer: Properly check sigevent->sigev_notify
From: Thomas Gleixner <[email protected]>
commit cef31d9af908243421258f1df35a4a644604efbe upstream.
timer_create() specifies via sigevent->sigev_notify the signal delivery for the new timer. The valid modes are SIGEV_NONE, SIGEV_SIGNAL, SIGEV_THREAD and (SIGEV_SIGNAL | SIGEV_THREAD_ID).
The sanity check in good_sigevent() is only checking the valid combination for the SIGEV_THREAD_ID bit, i.e. SIGEV_SIGNAL, but if SIGEV_THREAD_ID is not set it accepts any random value.
This has no real effects on the posix timer and signal delivery code, but it affects show_timer() which handles the output of /proc/$PID/timers. That function uses a string array to pretty print sigev_notify. The access to that array has no bound checks, so random sigev_notify cause access beyond the array bounds.
Add proper checks for the valid notify modes and remove the SIGEV_THREAD_ID masking from various code pathes as SIGEV_NONE can never be set in combination with SIGEV_THREAD_ID.
--- kernel/time/posix-timers.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-)
kernel/time/posix-timers.c +17 -12
@@ -434,17 +434,22 @@ static struct pid *good_sigevent(sigeven {struct task_struct *rtn = current->group_leader; -if ((event->sigev_notify &SIGEV_THREAD_ID ) && - (!(rtn =find_task_by_vpid (event->sigev_notify_thread_id)) || - !same_thread_group (rtn, current) || - (event->sigev_notify & ~SIGEV_THREAD_ID ) !=SIGEV_SIGNAL )) +switch (event->sigev_notify) { +case SIGEV_SIGNAL |SIGEV_THREAD_ID : + rtn =find_task_by_vpid (event->sigev_notify_thread_id); +if (!rtn || !same_thread_group (rtn, current)) +return NULL ; +/* FALLTHRU */ +case SIGEV_SIGNAL : +case SIGEV_THREAD : +if (event->sigev_signo <=0 || event->sigev_signo >SIGRTMAX ) +return NULL ; +/* FALLTHRU */ +case SIGEV_NONE : +return task_pid (rtn); +default :return NULL ; - -if (((event->sigev_notify & ~SIGEV_THREAD_ID ) !=SIGEV_NONE ) && - ((event->sigev_signo <=0 ) || (event->sigev_signo >SIGRTMAX ))) -return NULL ; - -return task_pid (rtn); + } }static struct k_itimer *alloc_posix_timer (void )
@@ -669,7 +674,7 @@ void common_timer_get(struct k_itimer *tstruct timespec64 ts64;bool sig_none; - sig_none = (timr->it_sigev_notify & ~SIGEV_THREAD_ID ) ==SIGEV_NONE ; + sig_none = timr->it_sigev_notify ==SIGEV_NONE ; iv = timr->it_interval;/* interval timer ? */
@@ -856,7 +861,7 @@ int common_timer_set(struct k_itimer *ti timr->it_interval =timespec64_to_ktime (new_setting->it_interval); expires =timespec64_to_ktime (new_setting->it_value); - sigev_none = (timr->it_sigev_notify & ~SIGEV_THREAD_ID ) ==SIGEV_NONE ; + sigev_none = timr->it_sigev_notify ==SIGEV_NONE ; kc->timer_arm (timr, expires, flags &TIMER_ABSTIME , sigev_none); timr->it_active = !sigev_none;
Patches currently in stable-queue which might be from [email protected] are
queue-4.14/sched-rt-do-not-pull-from-current-cpu-if-only-one-cpu-to-pull.patch queue-4.14/x86-boot-compressed-64-print-error-if-5-level-paging-is-not-supported.patch queue-4.14/posix-timer-properly-check-sigevent-sigev_notify.patch queue-4.14/x86-boot-compressed-64-detect-and-handle-5-level-paging-at-boot-time.patch