From 017d11c190a58a98a81e57c9b793141aa23c3d90 Mon Sep 17 00:00:00 2001 From: hinus Date: Wed, 11 Aug 2021 16:25:35 +0800 Subject: [PATCH] Title: System call 'sigaction' Issue: https://gitee.com/hinus/linux_kernel_011/issues/I429PD Description: System call 'sigaction' --- include/linux/kernel.h | 1 + include/linux/sys.h | 5 +- kernel/main.c | 6 +- kernel/signal.c | 124 +++++++++++++++++++++++++++++++++++++++++ kernel/sys_call.S | 48 +++++++++++++++- 5 files changed, 177 insertions(+), 7 deletions(-) diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 00249dc..4b370f1 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -3,6 +3,7 @@ void verify_area(void * addr,int count); void panic(const char * str); +volatile void do_exit(long error_code); int printk(const char* fmt, ...); #define suser() (current->euid == 0) diff --git a/include/linux/sys.h b/include/linux/sys.h index 14ab8c4..1643a18 100644 --- a/include/linux/sys.h +++ b/include/linux/sys.h @@ -65,7 +65,7 @@ extern int sys_chroot(); extern int sys_getppid(); //extern int sys_getpgrp(); //extern int sys_setsid(); -//extern int sys_sigaction(); +extern int sys_sigaction(); //extern int sys_sgetmask(); //extern int sys_ssetmask(); //extern int sys_setreuid(); @@ -161,10 +161,9 @@ fn_ptr sys_call_table[] = { 0, // sys_ustat, 0, // sys_dup2, sys_getppid, - 0, // 0, // sys_getpgrp, 0, // sys_setsid, - 0, // sys_sigaction, + sys_sigaction, 0, // sys_sgetmask, 0, // sys_ssetmask, 0, // diff --git a/kernel/main.c b/kernel/main.c index ba5f2df..162f97d 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -80,8 +80,8 @@ static void time_init() { static char * argv_rc[] = { "/bin/sh", NULL }; static char * envp_rc[] = { "HOME=/", NULL ,NULL }; -//static char * argv[] = { "-/bin/sh",NULL }; -static char * argv[] = { "/usr/bin", NULL }; +static char * argv[] = { "-/bin/sh",NULL }; +//static char * argv[] = { "/usr/bin", NULL }; static char * envp[] = { "HOME=/usr/root", NULL, NULL }; void main() { @@ -170,7 +170,7 @@ static void run_sh() { int pid; if (!(pid=fork())) { printf("read to start shell\n"); - execve("/tmp/et", argv,envp); + execve("/bin/sh", argv,envp); } } diff --git a/kernel/signal.c b/kernel/signal.c index 018dd04..eb451a9 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -20,3 +20,127 @@ int sys_signal(int signum, long handler, long restorer) { return handler; } +inline void save_old(char * from,char * to) { + int i; + verify_area(to, sizeof(struct sigaction)); + for (i=0 ; i< sizeof(struct sigaction) ; i++) { + put_fs_byte(*from,to); + from++; + to++; + } +} + +inline void get_new(char * from,char * to) { + int i; + + for (i=0 ; i< sizeof(struct sigaction) ; i++) + *(to++) = get_fs_byte(from++); +} + +int sys_sigaction(int signum, const struct sigaction * action, + struct sigaction * oldaction) { + struct sigaction tmp; + + if (signum<1 || signum>32 || signum==SIGKILL || signum==SIGSTOP) { + return -EINVAL; + } + + tmp = current->sigaction[signum-1]; + get_new((char *) action, + (char *) (signum-1+current->sigaction)); + + if (oldaction) + save_old((char *) &tmp,(char *) oldaction); + if (current->sigaction[signum-1].sa_flags & SA_NOMASK) + current->sigaction[signum-1].sa_mask = 0; + else + current->sigaction[signum-1].sa_mask |= (1<<(signum-1)); + return 0; +} + +int core_dump(long signr) { + return 0; +} + +int do_signal(long signr,long eax,long ebx, long ecx, long edx, long orig_eax, + long fs, long es, long ds, + long eip, long cs, long eflags, + unsigned long * esp, long ss) { + unsigned long sa_handler; + long old_eip=eip; + struct sigaction * sa = current->sigaction + signr - 1; + int longs; + + unsigned long * tmp_esp; + + printk("pid: %d, signr: %x, eax=%d, oeax = %d, int=%d\n", + current->pid, signr, eax, orig_eax, + sa->sa_flags & SA_INTERRUPT); + + if ((orig_eax != -1) && + ((eax == -ERESTARTSYS) || (eax == -ERESTARTNOINTR))) { + if ((eax == -ERESTARTSYS) && ((sa->sa_flags & SA_INTERRUPT) || + signr < SIGCONT || signr > SIGTTOU)) { + *(&eax) = -EINTR; + } + else { + *(&eax) = orig_eax; + *(&eip) = old_eip -= 2; + } + } + + sa_handler = (unsigned long) sa->sa_handler; + if (sa_handler == 1) + return(1); + + if (!sa_handler) { + switch (signr) { + case SIGCONT: + case SIGCHLD: + return(1); + case SIGSTOP: + case SIGTSTP: + case SIGTTIN: + case SIGTTOU: + current->state = TASK_STOPPED; + current->exit_code = signr; + if (!(current->p_pptr->sigaction[SIGCHLD-1].sa_flags & + SA_NOCLDSTOP)) { + current->p_pptr->signal |= (1<<(SIGCHLD-1)); + } + return(1); + case SIGQUIT: + case SIGILL: + case SIGTRAP: + case SIGIOT: + case SIGFPE: + case SIGSEGV: + if (core_dump(signr)) + do_exit(signr|0x80); + default: + do_exit(signr); + } + } + + if (sa->sa_flags & SA_ONESHOT) + sa->sa_handler = NULL; + + *(&eip) = sa_handler; + longs = (sa->sa_flags & SA_NOMASK)?7:8; + *(&esp) -= longs; + verify_area(esp,longs*4); + tmp_esp=esp; + put_fs_long((long) sa->sa_restorer,tmp_esp++); + put_fs_long(signr,tmp_esp++); + if (!(sa->sa_flags & SA_NOMASK)) + put_fs_long(current->blocked,tmp_esp++); + put_fs_long(eax,tmp_esp++); + put_fs_long(ecx,tmp_esp++); + put_fs_long(edx,tmp_esp++); + put_fs_long(eflags,tmp_esp++); + put_fs_long(old_eip,tmp_esp++); + current->blocked |= sa->sa_mask; + + return(0); +} + diff --git a/kernel/sys_call.S b/kernel/sys_call.S index 1f0ca52..8b2311b 100644 --- a/kernel/sys_call.S +++ b/kernel/sys_call.S @@ -17,12 +17,30 @@ EFLAGS = 0x28 OLDESP = 0x2c OLDSS = 0x30 +state = 0 +counter = 4 +priority = 8 +signal = 12 +sigaction = 16 +blocked = (33*16) + +sa_handler = 0 +sa_mask = 4 +sa_flags = 8 +sa_restorer = 12 + int_msg: .asciz "In kernel interrupt\n\r" show_ind: .asciz "sys call %d\n" +.align 4 +reschedule: + pushl $ret_from_sys_call + jmp schedule + +.align 4 system_call: pushl %ds pushl %es @@ -46,9 +64,37 @@ system_call: call *sys_call_table(, %eax, 4) pushl %eax +2: movl current, %eax + cmpl $0, state(%eax) + jne reschedule + cmpl $0, counter(%eax) + je reschedule + ret_from_sys_call: - popl %eax + movl current, %eax + cmpl task, %eax + je 3f + cmpw $0x0f, CS(%esp) + jne 3f + cmpw $0x17, OLDSS(%esp) + jne 3f + movl signal(%eax), %ebx + movl blocked(%eax), %ecx + notl %ecx + andl %ebx,%ecx + bsfl %ecx,%ecx + je 3f + btrl %ecx, %ebx + movl %ebx, signal(%eax) + incl %ecx + pushl %ecx + call do_signal + popl %ecx + testl %eax, %eax + jne 2b + +3: popl %eax popl %ebx popl %ecx popl %edx -- Gitee