Require a siginfo when sending a signal

This commit is contained in:
Theodore Dubois
2019-06-22 19:48:39 -07:00
parent 7d08b45aad
commit ae689abff5
9 changed files with 101 additions and 25 deletions
+2 -2
View File
@@ -345,7 +345,7 @@ canon_wake:
if (fg_group != 0) {
for (int sig = 0; sig < NUM_SIGS; sig++) {
if (queue & (1l << sig))
send_group_signal(fg_group, sig);
send_group_signal(fg_group, sig, SIGINFO_NIL);
}
}
@@ -732,7 +732,7 @@ static int tty_ioctl(struct fd *fd, int cmd, void *arg) {
void tty_set_winsize(struct tty *tty, struct winsize_ winsize) {
tty->winsize = winsize;
if (tty->fg_group != 0)
send_group_signal(tty->fg_group, SIGWINCH_);
send_group_signal(tty->fg_group, SIGWINCH_, SIGINFO_NIL);
}
void tty_hangup(struct tty *tty) {
+11 -3
View File
@@ -211,7 +211,7 @@ void handle_interrupt(int interrupt) {
unsigned syscall_num = cpu->eax;
if (syscall_num >= NUM_SYSCALLS || syscall_table[syscall_num] == NULL) {
printk("%d missing syscall %d\n", current->pid, syscall_num);
send_signal(current, SIGSYS_);
deliver_signal(current, SIGSYS_, SIGINFO_NIL);
} else {
STRACE("%d call %-3d ", current->pid, syscall_num);
int result = syscall_table[syscall_num](cpu->ebx, cpu->ecx, cpu->edx, cpu->esi, cpu->edi, cpu->ebp);
@@ -220,7 +220,11 @@ void handle_interrupt(int interrupt) {
}
} else if (interrupt == INT_GPF) {
printk("%d page fault on 0x%x at 0x%x\n", current->pid, cpu->segfault_addr, cpu->eip);
deliver_signal(current, SIGSEGV_);
struct siginfo_ info = {
.code = SI_KERNEL_,
.fault.addr = cpu->segfault_addr,
};
deliver_signal(current, SIGSEGV_, info);
} else if (interrupt == INT_UNDEFINED) {
printk("%d illegal instruction at 0x%x: ", current->pid, cpu->eip);
for (int i = 0; i < 8; i++) {
@@ -230,7 +234,11 @@ void handle_interrupt(int interrupt) {
printk("%02x ", b);
}
printk("\n");
deliver_signal(current, SIGILL_);
struct siginfo_ info = {
.code = SI_KERNEL_,
.fault.addr = cpu->eip,
};
deliver_signal(current, SIGILL_, info);
} else if (interrupt != INT_TIMER) {
printk("%d unhandled interrupt %d\n", current->pid, interrupt);
sys_exit(interrupt);
+1 -1
View File
@@ -97,6 +97,6 @@ int err_map(int err) {
int errno_map() {
if (errno == EPIPE)
send_signal(current, SIGPIPE_);
send_signal(current, SIGPIPE_, SIGINFO_NIL);
return err_map(errno);
}
+12 -2
View File
@@ -56,6 +56,7 @@ noreturn void do_exit(int status) {
struct rusage_ rusage = rusage_get_current();
lock(&current->group->lock);
rusage_add(&current->group->rusage, &rusage);
struct rusage_ group_rusage = current->group->rusage;
unlock(&current->group->lock);
// the actual freeing needs pids_lock
@@ -83,7 +84,16 @@ noreturn void do_exit(int status) {
} else {
leader->zombie = true;
notify(&parent->group->child_exit);
send_signal(parent, leader->exit_signal);
struct siginfo_ info = {
.code = SI_KERNEL_,
.child.pid = current->pid,
.child.uid = current->uid,
.child.status = current->exit_code,
.child.utime = clock_from_timeval(group_rusage.utime),
.child.stime = clock_from_timeval(group_rusage.stime),
};
if (leader->exit_signal != 0)
send_signal(parent, leader->exit_signal, info);
}
if (exit_hook != NULL)
@@ -111,7 +121,7 @@ noreturn void do_exit_group(int status) {
// kill everyone else in the group
struct task *task;
list_for_each_entry(&group->threads, task, group_links) {
deliver_signal(task, SIGKILL_);
deliver_signal(task, SIGKILL_, SIGINFO_NIL);
task->group->stopped = false;
notify(&task->group->stopped_cond);
}
+15 -7
View File
@@ -65,13 +65,13 @@ retry:
}
}
void deliver_signal(struct task *task, int sig) {
void deliver_signal(struct task *task, int sig, struct siginfo_ UNUSED(info)) {
lock(&task->sighand->lock);
deliver_signal_unlocked(task, sig);
unlock(&task->sighand->lock);
}
void send_signal(struct task *task, int sig) {
void send_signal(struct task *task, int sig, struct siginfo_ UNUSED(info)) {
// signal zero is for testing whether a process exists
if (sig == 0)
return;
@@ -97,6 +97,8 @@ void send_signal(struct task *task, int sig) {
}
bool try_self_signal(int sig) {
assert(sig == SIGTTIN_ || sig == SIGTTOU_);
struct sighand *sighand = current->sighand;
lock(&sighand->lock);
bool can_send = signal_action(sighand, sig) != SIGNAL_IGNORE &&
@@ -107,7 +109,7 @@ bool try_self_signal(int sig) {
return can_send;
}
int send_group_signal(dword_t pgid, int sig) {
int send_group_signal(dword_t pgid, int sig, struct siginfo_ info) {
lock(&pids_lock);
struct pid *pid = pid_get(pgid);
if (pid == NULL) {
@@ -116,7 +118,7 @@ int send_group_signal(dword_t pgid, int sig) {
}
struct tgroup *tgroup;
list_for_each_entry(&pid->pgroup, tgroup, pgroup) {
send_signal(tgroup->leader, sig);
send_signal(tgroup->leader, sig, info);
}
unlock(&pids_lock);
return 0;
@@ -227,7 +229,8 @@ bool receive_signals() {
if (now_stopped) {
lock(&pids_lock);
notify(&current->parent->group->child_exit);
send_signal(current->parent, current->group->leader->exit_signal);
// TODO add siginfo
send_signal(current->parent, current->group->leader->exit_signal, SIGINFO_NIL);
unlock(&pids_lock);
}
}
@@ -462,11 +465,16 @@ int do_kill(pid_t_ pid, dword_t sig, pid_t_ tgid) {
STRACE("kill(%d, %d)", pid, sig);
if (sig >= NUM_SIGS)
return _EINVAL;
struct siginfo_ info = {
.code = SI_USER_,
.kill.pid = current->pid,
.kill.uid = current->uid,
};
// TODO check permissions
if (pid == 0)
pid = -current->group->pgid;
if (pid < 0)
return send_group_signal(-pid, sig);
return send_group_signal(-pid, sig, info);
lock(&pids_lock);
struct task *task = pid_get_task(pid);
@@ -481,7 +489,7 @@ int do_kill(pid_t_ pid, dword_t sig, pid_t_ tgid) {
return _ESRCH;
}
send_signal(task, sig);
send_signal(task, sig, info);
unlock(&pids_lock);
return 0;
}
+45 -3
View File
@@ -51,16 +51,58 @@ struct sigaction_ {
#define SIGPWR_ 30
#define SIGSYS_ 31
#define SI_USER_ 0
#define SI_TIMER_ -2
#define SI_TKILL_ -6
#define SI_KERNEL_ 128
union sigval_ {
int_t sv_int;
addr_t sv_ptr;
};
struct siginfo_ {
int_t signo;
int_t code;
int_t sig_errno;
union {
struct {
pid_t_ pid;
uid_t_ uid;
} kill;
struct {
pid_t_ pid;
uid_t_ uid;
int_t status;
clock_t_ utime;
clock_t_ stime;
} child;
struct {
addr_t addr;
} fault;
struct {
addr_t addr;
int_t syscall;
} sigsys;
char __pad[128 - 3 * sizeof(int_t)];
};
};
// a reasonable default siginfo
static const struct siginfo_ SIGINFO_NIL = {
.code = SI_KERNEL_,
};
// send a signal
// you better make sure the task isn't gonna get freed under me (pids_lock or current)
void send_signal(struct task *task, int sig);
void send_signal(struct task *task, int sig, struct siginfo_ info);
// send a signal without regard for whether the signal is blocked or ignored
void deliver_signal(struct task *task, int sig);
void deliver_signal(struct task *task, int sig, struct siginfo_ info);
// send a signal to current if it's not blocked or ignored, return whether that worked
// exists specifically for sending SIGTTIN/SIGTTOU
bool try_self_signal(int sig);
// send a signal to all processes in a group, could return ESRCH
int send_group_signal(dword_t pgid, int sig);
int send_group_signal(dword_t pgid, int sig, struct siginfo_ info);
// check for and deliver pending signals on current
// returns whether signals were received
// must be called without pids_lock
+6 -3
View File
@@ -77,7 +77,10 @@ dword_t sys_clock_settime(dword_t UNUSED(clock), addr_t UNUSED(tp)) {
}
static void itimer_notify(struct task *task) {
send_signal(task, SIGALRM_);
struct siginfo_ info = {
.code = SI_TIMER_,
};
send_signal(task, SIGALRM_, info);
}
static int itimer_set(struct tgroup *group, int which, struct timer_spec spec, struct timer_spec *old_spec) {
@@ -179,8 +182,8 @@ dword_t sys_times(addr_t tbuf) {
if (tbuf) {
struct tms_ tmp;
struct rusage_ rusage = rusage_get_current();
tmp.tms_utime = (rusage.utime.sec * 100) + (rusage.utime.usec/10000);
tmp.tms_stime = (rusage.utime.sec * 100) + (rusage.utime.usec/10000);
tmp.tms_utime = clock_from_timeval(rusage.utime);
tmp.tms_stime = clock_from_timeval(rusage.stime);
tmp.tms_cutime = tmp.tms_utime;
tmp.tms_cstime = tmp.tms_stime;
if (user_put(tbuf, tmp))
+8 -4
View File
@@ -24,6 +24,10 @@ struct timezone_ {
dword_t dsttime;
};
static inline clock_t_ clock_from_timeval(struct timeval_ timeval) {
return timeval.sec * 100 + timeval.usec / 10000;
}
#define ITIMER_REAL_ 0
#define ITIMER_VIRTUAL_ 1
#define ITIMER_PROF_ 2
@@ -33,10 +37,10 @@ struct itimerval_ {
};
struct tms_ {
dword_t tms_utime; /* user time */
dword_t tms_stime; /* system time */
dword_t tms_cutime; /* user time of children */
dword_t tms_cstime; /* system time of children */
clock_t_ tms_utime; /* user time */
clock_t_ tms_stime; /* system time */
clock_t_ tms_cutime; /* user time of children */
clock_t_ tms_cstime; /* system time of children */
};
int_t sys_setitimer(int_t which, addr_t new_val, addr_t old_val);
+1
View File
@@ -67,6 +67,7 @@ typedef sdword_t pid_t_;
typedef dword_t uid_t_;
typedef word_t mode_t_;
typedef sqword_t off_t_;
typedef dword_t clock_t_;
#define uint(size) glue3(uint,size,_t)
#define sint(size) glue3(int,size,_t)