A fix for a long standing issue in the alarmtimer code:
Posix-timers armed with a short interval with an ignored signal result in an unpriviledged DoS. Due to the ignored signal the timer switches into self rearm mode. This issue had been "fixed" before but a rework of the alarmtimer code 5 years ago lost that workaround. There is no real good solution for this issue, which is also worked around in the core posix-timer code in the same way, but it certainly moved way up on the ever growing todo list. -----BEGIN PGP SIGNATURE----- iQJHBAABCgAxFiEEQp8+kY+LLUocC4bMphj1TA10mKEFAmPxYIwTHHRnbHhAbGlu dXRyb25peC5kZQAKCRCmGPVMDXSYocQ5D/45vfKxvXsF0mCHPpF+Dgx96T3rzpXY aN/OeKWJ50A7IB5QKdxR3/VdDSuD6/HroFTfKTQIUVzkzAq47r7Ref7a0bgDsNbT SLTX8oBUA1ALKVew3wGo5qkY317xyGb2WPiSCzfjAZk07MplOzDRC4YYgEfnYAWW DzmzmkZQaAhKg3JONEB+kOas/E/T1MwTSs2NNJiY0hM6ATFK2+q2b706wjDHWspk QwjCfUCbrFKSxol+hSQgvQpzV18FmS328xU4Ht4pioflch0dv1/HDrml9OGrCCzs 8hEmCcjxFwM2FXTPIix8/Jn4S8ppZwYQCi10bBjjF+0N9s897s/4dom88EbfwjfB 4YpE62SI8VZIyK0JauSuRcCAfnN7BwfgL9UpS3MEgHq4K+fnydZOItBYI3Rg4JY/ hAKizX5VzBSAq/iUFC9+DFKjonOz3cCvY5xoPLPfCXukykbYfOCz1BiBqrTP7n1z /qWgDm+YvEyYNmoEqPjD5kktpHAvwGiMl6dmJJOUxaV6KNXWremykvI491oZK7fI P3eWMPhJwJV7ukjUF6Wc5ylwupsakf+x802MF03rgmajXtzxnnFATotb/21g9SSD /FYfdjS85CRArvYKuN59Yty8iMbjX4T1tRBaKgLYjpOdqgA6H6T3vmI+ShKS/FAM T92uQTZMpVm7+w== =s5VW -----END PGP SIGNATURE----- Merge tag 'timers-urgent-2023-02-19' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip Pull timer fix from Thomas Gleixner: "A fix for a long standing issue in the alarmtimer code. Posix-timers armed with a short interval with an ignored signal result in an unpriviledged DoS. Due to the ignored signal the timer switches into self rearm mode. This issue had been "fixed" before but a rework of the alarmtimer code 5 years ago lost that workaround. There is no real good solution for this issue, which is also worked around in the core posix-timer code in the same way, but it certainly moved way up on the ever growing todo list" * tag 'timers-urgent-2023-02-19' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: alarmtimer: Prevent starvation by small intervals and SIG_IGN
This commit is contained in:
commit
0097c18e45
@ -470,11 +470,35 @@ u64 alarm_forward(struct alarm *alarm, ktime_t now, ktime_t interval)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(alarm_forward);
|
||||
|
||||
u64 alarm_forward_now(struct alarm *alarm, ktime_t interval)
|
||||
static u64 __alarm_forward_now(struct alarm *alarm, ktime_t interval, bool throttle)
|
||||
{
|
||||
struct alarm_base *base = &alarm_bases[alarm->type];
|
||||
ktime_t now = base->get_ktime();
|
||||
|
||||
return alarm_forward(alarm, base->get_ktime(), interval);
|
||||
if (IS_ENABLED(CONFIG_HIGH_RES_TIMERS) && throttle) {
|
||||
/*
|
||||
* Same issue as with posix_timer_fn(). Timers which are
|
||||
* periodic but the signal is ignored can starve the system
|
||||
* with a very small interval. The real fix which was
|
||||
* promised in the context of posix_timer_fn() never
|
||||
* materialized, but someone should really work on it.
|
||||
*
|
||||
* To prevent DOS fake @now to be 1 jiffie out which keeps
|
||||
* the overrun accounting correct but creates an
|
||||
* inconsistency vs. timer_gettime(2).
|
||||
*/
|
||||
ktime_t kj = NSEC_PER_SEC / HZ;
|
||||
|
||||
if (interval < kj)
|
||||
now = ktime_add(now, kj);
|
||||
}
|
||||
|
||||
return alarm_forward(alarm, now, interval);
|
||||
}
|
||||
|
||||
u64 alarm_forward_now(struct alarm *alarm, ktime_t interval)
|
||||
{
|
||||
return __alarm_forward_now(alarm, interval, false);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(alarm_forward_now);
|
||||
|
||||
@ -551,9 +575,10 @@ static enum alarmtimer_restart alarm_handle_timer(struct alarm *alarm,
|
||||
if (posix_timer_event(ptr, si_private) && ptr->it_interval) {
|
||||
/*
|
||||
* Handle ignored signals and rearm the timer. This will go
|
||||
* away once we handle ignored signals proper.
|
||||
* away once we handle ignored signals proper. Ensure that
|
||||
* small intervals cannot starve the system.
|
||||
*/
|
||||
ptr->it_overrun += alarm_forward_now(alarm, ptr->it_interval);
|
||||
ptr->it_overrun += __alarm_forward_now(alarm, ptr->it_interval, true);
|
||||
++ptr->it_requeue_pending;
|
||||
ptr->it_active = 1;
|
||||
result = ALARMTIMER_RESTART;
|
||||
|
Loading…
x
Reference in New Issue
Block a user