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

Commit 8bfd9a7a authored by Thomas Gleixner's avatar Thomas Gleixner Committed by Linus Torvalds
Browse files

[PATCH] hrtimers: prevent possible itimer DoS



Fix potential setitimer DoS with high-res timers by pushing itimer rearm
processing to process context.

[Fixes from: Ingo Molnar <mingo@elte.hu>]
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
Cc: john stultz <johnstul@us.ibm.com>
Cc: Roman Zippel <zippel@linux-m68k.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 54cdfdb4
Loading
Loading
Loading
Loading
+6 −8
Original line number Diff line number Diff line
@@ -135,11 +135,6 @@ enum hrtimer_restart it_real_fn(struct hrtimer *timer)

	send_group_sig_info(SIGALRM, SEND_SIG_PRIV, sig->tsk);

	if (sig->it_real_incr.tv64 != 0) {
		hrtimer_forward(timer, hrtimer_cb_get_time(timer),
				sig->it_real_incr);
		return HRTIMER_RESTART;
	}
	return HRTIMER_NORESTART;
}

@@ -231,11 +226,14 @@ int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
			spin_unlock_irq(&tsk->sighand->siglock);
			goto again;
		}
		expires = timeval_to_ktime(value->it_value);
		if (expires.tv64 != 0) {
			tsk->signal->it_real_incr =
				timeval_to_ktime(value->it_interval);
		expires = timeval_to_ktime(value->it_value);
		if (expires.tv64 != 0)
			hrtimer_start(timer, expires, HRTIMER_MODE_REL);
		} else
			tsk->signal->it_real_incr.tv64 = 0;

		spin_unlock_irq(&tsk->sighand->siglock);
		break;
	case ITIMER_VIRTUAL:
+41 −17
Original line number Diff line number Diff line
@@ -456,9 +456,33 @@ static int __dequeue_signal(struct sigpending *pending, sigset_t *mask,
int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
{
	int signr = __dequeue_signal(&tsk->pending, mask, info);
	if (!signr)
	if (!signr) {
		signr = __dequeue_signal(&tsk->signal->shared_pending,
					 mask, info);
		/*
		 * itimer signal ?
		 *
		 * itimers are process shared and we restart periodic
		 * itimers in the signal delivery path to prevent DoS
		 * attacks in the high resolution timer case. This is
		 * compliant with the old way of self restarting
		 * itimers, as the SIGALRM is a legacy signal and only
		 * queued once. Changing the restart behaviour to
		 * restart the timer in the signal dequeue path is
		 * reducing the timer noise on heavy loaded !highres
		 * systems too.
		 */
		if (unlikely(signr == SIGALRM)) {
			struct hrtimer *tmr = &tsk->signal->real_timer;

			if (!hrtimer_is_queued(tmr) &&
			    tsk->signal->it_real_incr.tv64 != 0) {
				hrtimer_forward(tmr, tmr->base->get_time(),
						tsk->signal->it_real_incr);
				hrtimer_restart(tmr);
			}
		}
	}
	recalc_sigpending_tsk(tsk);
	if (signr && unlikely(sig_kernel_stop(signr))) {
		/*