7 ms·
Theo de Raadt made an, I think, cogent observation about this bug and how to prevent similar ones: no signal handler should call any function that isn't a signa
by djmdjm 2y ago
Theo de Raadt made an, I think, cogent observation about this bug and how to prevent similar ones: no signal handler should call any function that isn't a signal-safe syscall. The rationale is that, over time, it's too way easy for any transitive call (where it's not always clear that it can be reached in signal context) to pick up some call that isn't async signal safe.
- fanf2 2y agoExactly, yes :-) Signal handlers have so many hazards it's vital to keep them as simple as possible.
- growse 2y agoI'm not overly familiar with the language and tooling ecosystem, but how trivial is this to detect on a static analysis?
- kccqzy 2y agoQuite easy.
- rwmj 2y agoA rule I try to follow: either set a global variable or write to a self pipe (using the write syscall), and handle the signal in the main loop.
- cesarb 2y ago> either set a global variable IIRC, the rule is also that said global variable must have the type "volatile sig_atomic_t".
- lokar 2y agoYou should read the sigsev handler at google, it’s great, doing all kinds of things. Of course it’s going to crash at some point anyway….
- ralferoo 2y agoI'm kind of surprised advocating calling any syscall other than signal to add the handler back again. It's been a long time since I looked at example code, but back in the mid 90s, everything I saw (and so informed my habits) just set a flag, listened to the signal again if it was something like SIGUSR1 and then you'd pick up the flag on the next iteration of your main loop. Maybe that's also because I think of a signal like an interrupt, and something you want to get done as soon as possible to not cause any stalls to the main program. I notice that nowadays signalfd() looks like a much better solution to the signal problem, but I've never tried using it. I think I'll give it a go in my next project.
- qhwudbebd 2y agoIn practice when I tried it, I wasn't sold on signalfd's benefits over the 90s style self-pipe, which is reliably portable too. Either way, being able to handle signals in a poll loop is much nicer than trying to do any real work in an async context.
- formerly_proven 2y agoThis isn't the case for OpenSSH but because a lot of environments (essentially all managed runtimes) actually do this transparently for you when you register a signal "handler" it might be that less people are aware that actual signal handlers require a ton of care. On the other hand "you can't even call strcmp in a signal handler or you'll randomly corrupt program state" used to be a favorite among practicing C lawyers.
- lilyball 2y agoWhy can't you call strcmp? I think a general practice of "only call functions that are explicitly blessed as async-signal-safe" is a good idea, which means not calling strcmp as it hasn't been blessed, but surely it doesn't touch any global (or per-thread) state so how can it corrupt program state? Update: according to https://man7.org/linux/man-pages/man7/signal-safety.7.html https://man7.org/linux/man-pages/man7/signal-safety.7.html strcmp() actually is async-signal-safe as of POSIX.1-2008 TC2.