Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e6c42c29 authored by Stanislaw Gruszka's avatar Stanislaw Gruszka Committed by Thomas Gleixner
Browse files

posix-cpu-timers: Fix nanosleep task_struct leak



The trinity fuzzer triggered a task_struct reference leak via
clock_nanosleep with CPU_TIMERs. do_cpu_nanosleep() calls
posic_cpu_timer_create(), but misses a corresponding
posix_cpu_timer_del() which leads to the task_struct reference leak.

Reported-and-tested-by: default avatarTommi Rantala <tt.rantala@gmail.com>
Signed-off-by: default avatarStanislaw Gruszka <sgruszka@redhat.com>
Cc: Dave Jones <davej@redhat.com>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: stable@vger.kernel.org
Link: http://lkml.kernel.org/r/20130215100810.GF4392@redhat.com


Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent 9f4646d2
Loading
Loading
Loading
Loading
+21 −2
Original line number Diff line number Diff line
@@ -1401,8 +1401,10 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
		while (!signal_pending(current)) {
			if (timer.it.cpu.expires.sched == 0) {
				/*
				 * Our timer fired and was reset.
				 * Our timer fired and was reset, below
				 * deletion can not fail.
				 */
				posix_cpu_timer_del(&timer);
				spin_unlock_irq(&timer.it_lock);
				return 0;
			}
@@ -1420,8 +1422,25 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
		 * We were interrupted by a signal.
		 */
		sample_to_timespec(which_clock, timer.it.cpu.expires, rqtp);
		posix_cpu_timer_set(&timer, 0, &zero_it, it);
		error = posix_cpu_timer_set(&timer, 0, &zero_it, it);
		if (!error) {
			/*
			 * Timer is now unarmed, deletion can not fail.
			 */
			posix_cpu_timer_del(&timer);
		}
		spin_unlock_irq(&timer.it_lock);

		while (error == TIMER_RETRY) {
			/*
			 * We need to handle case when timer was or is in the
			 * middle of firing. In other cases we already freed
			 * resources.
			 */
			spin_lock_irq(&timer.it_lock);
			error = posix_cpu_timer_del(&timer);
			spin_unlock_irq(&timer.it_lock);
		}

		if ((it->it_value.tv_sec | it->it_value.tv_nsec) == 0) {
			/*