1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 09:48:11 +00:00

LibC: Ignore signals that don't have a name in getsignalbyname()

This prevents a segfault in `kill` and `killall` when an invalid
signal name is given.
This commit is contained in:
Tim Ledbetter 2023-05-30 18:12:06 +01:00 committed by Jelle Raaijmakers
parent f0edf00dc0
commit a041f1671c
2 changed files with 58 additions and 73 deletions

View file

@ -128,39 +128,53 @@ int sigpending(sigset_t* set)
__RETURN_WITH_ERRNO(rc, rc, -1); __RETURN_WITH_ERRNO(rc, rc, -1);
} }
// Signal 0 (the null signal) and Signal 32 (SIGCANCEL) are deliberately set to null here.
// They are not intended to be resolved by strsignal(), getsignalname() or getsignalbyname().
#define ENUMERATE_SIGNALS \
__ENUMERATE_SIGNAL(nullptr, nullptr) \
__ENUMERATE_SIGNAL("HUP", "Hangup") \
__ENUMERATE_SIGNAL("INT", "Interrupt") \
__ENUMERATE_SIGNAL("QUIT", "Quit") \
__ENUMERATE_SIGNAL("ILL", "Illegal instruction") \
__ENUMERATE_SIGNAL("TRAP", "Trap") \
__ENUMERATE_SIGNAL("ABRT", "Aborted") \
__ENUMERATE_SIGNAL("BUS", "Bus error") \
__ENUMERATE_SIGNAL("FPE", "Division by zero") \
__ENUMERATE_SIGNAL("KILL", "Killed") \
__ENUMERATE_SIGNAL("USR1", "User signal 1") \
__ENUMERATE_SIGNAL("SEGV", "Segmentation violation") \
__ENUMERATE_SIGNAL("USR2", "User signal 2") \
__ENUMERATE_SIGNAL("PIPE", "Broken pipe") \
__ENUMERATE_SIGNAL("ALRM", "Alarm clock") \
__ENUMERATE_SIGNAL("TERM", "Terminated") \
__ENUMERATE_SIGNAL("STKFLT", "Stack fault") \
__ENUMERATE_SIGNAL("CHLD", "Child exited") \
__ENUMERATE_SIGNAL("CONT", "Continued") \
__ENUMERATE_SIGNAL("STOP", "Stopped (signal)") \
__ENUMERATE_SIGNAL("TSTP", "Stopped") \
__ENUMERATE_SIGNAL("TTIN", "Stopped (tty input)") \
__ENUMERATE_SIGNAL("TTOU", "Stopped (tty output)") \
__ENUMERATE_SIGNAL("URG", "Urgent I/O condition)") \
__ENUMERATE_SIGNAL("XCPU", "CPU limit exceeded") \
__ENUMERATE_SIGNAL("XFSZ", "File size limit exceeded") \
__ENUMERATE_SIGNAL("VTALRM", "Virtual timer expired") \
__ENUMERATE_SIGNAL("PROF", "Profiling timer expired") \
__ENUMERATE_SIGNAL("WINCH", "Window changed") \
__ENUMERATE_SIGNAL("IO", "I/O possible") \
__ENUMERATE_SIGNAL("INFO", "Power failure") \
__ENUMERATE_SIGNAL("SYS", "Bad system call") \
__ENUMERATE_SIGNAL(nullptr, nullptr)
char const* sys_siglist[NSIG] = { char const* sys_siglist[NSIG] = {
"Invalid signal number", #define __ENUMERATE_SIGNAL(name, description) description,
"Hangup", ENUMERATE_SIGNALS
"Interrupt", #undef __ENUMERATE_SIGNAL
"Quit", };
"Illegal instruction",
"Trap", char const* sys_signame[NSIG] = {
"Aborted", #define __ENUMERATE_SIGNAL(name, description) name,
"Bus error", ENUMERATE_SIGNALS
"Division by zero", #undef __ENUMERATE_SIGNAL
"Killed",
"User signal 1",
"Segmentation violation",
"User signal 2",
"Broken pipe",
"Alarm clock",
"Terminated",
"Stack fault",
"Child exited",
"Continued",
"Stopped (signal)",
"Stopped",
"Stopped (tty input)",
"Stopped (tty output)",
"Urgent I/O condition)",
"CPU limit exceeded",
"File size limit exceeded",
"Virtual timer expired",
"Profiling timer expired",
"Window changed",
"I/O possible",
"Power failure",
"Bad system call",
}; };
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/siglongjmp.html // https://pubs.opengroup.org/onlinepubs/9699919799/functions/siglongjmp.html
@ -210,48 +224,14 @@ int sigtimedwait(sigset_t const* set, siginfo_t* info, struct timespec const* ti
__RETURN_WITH_ERRNO(rc, rc, -1); __RETURN_WITH_ERRNO(rc, rc, -1);
} }
char const* sys_signame[] = {
"INVAL",
"HUP",
"INT",
"QUIT",
"ILL",
"TRAP",
"ABRT",
"BUS",
"FPE",
"KILL",
"USR1",
"SEGV",
"USR2",
"PIPE",
"ALRM",
"TERM",
"STKFLT",
"CHLD",
"CONT",
"STOP",
"TSTP",
"TTIN",
"TTOU",
"URG",
"XCPU",
"XFSZ",
"VTALRM",
"PROF",
"WINCH",
"IO",
"INFO",
"SYS",
};
static_assert(sizeof(sys_signame) == sizeof(char const*) * NSIG);
int getsignalbyname(char const* name) int getsignalbyname(char const* name)
{ {
VERIFY(name); VERIFY(name);
StringView name_sv { name, strlen(name) }; StringView name_sv { name, strlen(name) };
for (size_t i = 0; i < NSIG; ++i) { for (size_t i = 1; i < NSIG; ++i) {
if (!sys_signame[i])
continue;
StringView signal_name { sys_signame[i], strlen(sys_signame[i]) }; StringView signal_name { sys_signame[i], strlen(sys_signame[i]) };
if (signal_name == name_sv || (name_sv.starts_with("SIG"sv) && signal_name == name_sv.substring_view(3))) if (signal_name == name_sv || (name_sv.starts_with("SIG"sv) && signal_name == name_sv.substring_view(3)))
return i; return i;
@ -262,10 +242,15 @@ int getsignalbyname(char const* name)
char const* getsignalname(int signal) char const* getsignalname(int signal)
{ {
if (signal < 0 || signal >= NSIG) { if (signal <= 0 || signal >= NSIG) {
errno = EINVAL; errno = EINVAL;
return nullptr; return nullptr;
} }
return sys_signame[signal];
auto const* result = sys_signame[signal];
if (!result)
errno = EINVAL;
return result;
} }
} }

View file

@ -340,7 +340,7 @@ char* strerror(int errnum)
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/strsignal.html // https://pubs.opengroup.org/onlinepubs/9699919799/functions/strsignal.html
char* strsignal(int signum) char* strsignal(int signum)
{ {
if (signum >= NSIG) { if (signum <= 0 || signum >= NSIG || !sys_siglist[signum]) {
dbgln("strsignal() missing string for signum={}", signum); dbgln("strsignal() missing string for signum={}", signum);
return const_cast<char*>("Unknown signal"); return const_cast<char*>("Unknown signal");
} }