this repo has no description
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix(waitid): Proper marshalling for siginfo_t

Linux and BSD siginfo_t has different layouts, making processes calling waitid confused about the output.

+106 -10
+19 -4
src/kernel/emulation/linux/process/waitid.c
··· 6 6 #include <linux-syscalls/linux.h> 7 7 #include <stddef.h> 8 8 9 - long sys_waitid(int idtype, int id, struct simple_siginfo* si, int options) 9 + static void siginfo_linux_to_bsd(const linux_siginfo_t* linux_si, siginfo_t* si); 10 + 11 + long sys_waitid(int idtype, int id, siginfo_t* si, int options) 10 12 { 11 13 int ret, linux_options; 12 14 13 15 linux_options = waitopts_bsd_to_linux(options); 14 16 15 - ret = LINUX_SYSCALL(__NR_waitid, idtype, id, si, linux_options); 17 + linux_siginfo_t linux_si; 18 + ret = LINUX_SYSCALL(__NR_waitid, idtype, id, &linux_si, linux_options); 16 19 if (ret < 0) 17 20 return errno_linux_to_bsd(ret); 18 21 19 22 if (si != NULL) 20 23 { 21 - si->si_signo = signum_linux_to_bsd(si->si_signo); 22 - si->si_errno = errno_linux_to_bsd(si->si_errno); 24 + siginfo_linux_to_bsd(&linux_si, si); 23 25 } 24 26 25 27 return ret; 26 28 } 27 29 30 + static void siginfo_linux_to_bsd(const linux_siginfo_t* linux_si, siginfo_t* si) 31 + { 32 + si->si_signo = signum_linux_to_bsd(linux_si->si_signo); 33 + si->si_errno = errno_linux_to_bsd(linux_si->si_errno); 34 + si->si_code = linux_si->si_code; 35 + si->si_pid = linux_si->linux_si_pid; 36 + si->si_uid = linux_si->linux_si_uid; 37 + si->si_status = linux_si->linux_si_status; 38 + si->si_addr = linux_si->linux_si_addr; 39 + si->si_value = linux_si->linux_si_value; 40 + si->si_band = linux_si->linux_si_band; 41 + } 42 +
+87 -6
src/kernel/emulation/linux/process/waitid.h
··· 1 1 #ifndef LINUX_WAITID_H 2 2 #define LINUX_WAITID_H 3 3 4 - struct simple_siginfo 4 + #include <sys/signal.h> 5 + 6 + #define LINUX_SI_MAX_SIZE 128 7 + #if __WORDSIZE == 64 8 + # define LINUX_SI_PAD_SIZE ((LINUX_SI_MAX_SIZE / sizeof (int)) - 4) 9 + #else 10 + # define LINUX_SI_PAD_SIZE ((LINUX_SI_MAX_SIZE / sizeof (int)) - 3) 11 + #endif 12 + 13 + // TODO: see when this is defind in Linux 14 + #ifndef LINUX_SI_ERRNO_THEN_CODE 15 + # define LINUX_SI_ERRNO_THEN_CODE 1 16 + #endif 17 + 18 + // This struct is heavily simplified. 19 + typedef struct 5 20 { 6 - int si_signo; 7 - int si_errno; 8 - int si_code; 9 - }; 21 + int si_signo; /* Signal number. */ 22 + #if LINUX_SI_ERRNO_THEN_CODE 23 + int si_errno; /* If non-zero, an errno value associated with 24 + this signal, as defined in <errno.h>. */ 25 + int si_code; /* Signal code. */ 26 + #else 27 + int si_code; 28 + int si_errno; 29 + #endif 30 + #if __WORDSIZE == 64 31 + int __pad0; /* Explicit padding. */ 32 + #endif 33 + union 34 + { 35 + int _pad[LINUX_SI_PAD_SIZE]; 36 + /* kill(). */ 37 + struct 38 + { 39 + pid_t si_pid; /* Sending process ID. */ 40 + uid_t si_uid; /* Real user ID of sending process. */ 41 + } _kill; 42 + /* POSIX.1b timers. */ 43 + struct 44 + { 45 + int si_tid; /* Timer ID. */ 46 + int si_overrun; /* Overrun count. */ 47 + union sigval si_sigval; /* Signal value. */ 48 + } _timer; 49 + /* POSIX.1b signals. */ 50 + struct 51 + { 52 + pid_t si_pid; /* Sending process ID. */ 53 + uid_t si_uid; /* Real user ID of sending process. */ 54 + union sigval si_sigval; /* Signal value. */ 55 + } _rt; 56 + /* SIGCHLD. */ 57 + struct 58 + { 59 + pid_t si_pid; /* Which child. */ 60 + uid_t si_uid; /* Real user ID of sending process. */ 61 + int si_status; /* Exit value or signal. */ 62 + } _sigchld; 63 + /* SIGILL, SIGFPE, SIGSEGV, SIGBUS. */ 64 + struct 65 + { 66 + void *si_addr; /* Faulting insn/memory ref. */ 67 + } _sigfault; 68 + /* SIGPOLL. */ 69 + struct 70 + { 71 + long si_band; /* Band event for SIGPOLL. */ 72 + int si_fd; 73 + } _sigpoll; 74 + /* SIGSYS. */ 75 + struct 76 + { 77 + void *_call_addr; /* Calling user insn. */ 78 + int _syscall; /* Triggering system call number. */ 79 + unsigned int _arch; /* AUDIT_ARCH_* of syscall. */ 80 + } _sigsys; 81 + } _sifields; 82 + } linux_siginfo_t; 10 83 11 - long sys_waitid(int idtype, int id, struct simple_siginfo* si, int options); 84 + // We keep only the fields defined in the BSD version. 85 + #define linux_si_pid _sifields._kill.si_pid 86 + #define linux_si_uid _sifields._kill.si_uid 87 + #define linux_si_status _sifields._sigchld.si_status 88 + #define linux_si_value _sifields._rt.si_sigval 89 + #define linux_si_addr _sifields._sigfault.si_addr 90 + #define linux_si_band _sifields._sigpoll.si_band 91 + 92 + long sys_waitid(int idtype, int id, siginfo_t* si, int options); 12 93 13 94 #endif 14 95