diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2024-10-10 11:56:27 -0400 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2024-10-10 11:56:27 -0400 |
commit | 39ff273df97e51b1285358b9e6808b117ea8adb1 (patch) | |
tree | de29177b5af341791096d0f303ef6bb4fae8302b | |
parent | 7b33959d38374d18950b16a2f3ff2ca42406a895 (diff) | |
download | bfs-39ff273df97e51b1285358b9e6808b117ea8adb1.tar.xz |
sighook: Don't forget to reset list->tail on the last sigpop()
This was causing a UAF if we ever unregistered the last hook for a
signal and then re-registered one.
Fixes: 75b7f70 ("sighook: Make sigunhook() O(1)")
-rw-r--r-- | src/sighook.c | 2 | ||||
-rw-r--r-- | tests/sighook.c | 7 |
2 files changed, 9 insertions, 0 deletions
diff --git a/src/sighook.c b/src/sighook.c index 4356fdb..0cc81fa 100644 --- a/src/sighook.c +++ b/src/sighook.c @@ -291,6 +291,8 @@ static void sigpop(struct siglist *list, struct sighook *hook) { rcu_update(hook->self, next); if (next) { next->self = hook->self; + } else { + list->tail = &list->head; } } diff --git a/tests/sighook.c b/tests/sighook.c index d785a55..0cb8de2 100644 --- a/tests/sighook.c +++ b/tests/sighook.c @@ -60,6 +60,13 @@ void check_sighook(void) { return; } + // Check that we can unregister and re-register a hook + sigunhook(hook); + hook = sighook(SIGALRM, alrm_hook, NULL, SH_CONTINUE); + if (!bfs_echeck(hook, "sighook(SIGALRM)")) { + return; + } + // Create a timer that sends SIGALRM every 100 microseconds struct timespec ival = { .tv_nsec = 100 * 1000 }; struct timer *timer = xtimer_start(&ival); |