From e533870f11da47819000b126e34871e3815c39de Mon Sep 17 00:00:00 2001 From: hinus Date: Sat, 14 Aug 2021 23:52:17 +0800 Subject: [PATCH] Title: Some system calls. Issue: https://gitee.com/hinus/linux_kernel_011/issues/I451NK Description: Some system calls. --- fs/open.c | 39 ++++++++++++++++++++++++++++ include/linux/sys.h | 6 ++--- include/unistd.h | 4 ++- kernel/chr_drv/tty_ioctl.c | 18 +++++++++++++ kernel/exit.c | 42 ++++++++++++++++++++++++++++++ kernel/main.c | 37 ++++++++++++++++++++++++++- kernel/sched.c | 8 ++++-- kernel/sys.c | 52 +++++++++++++++++++++++++++++++++++++- lib/Makefile | 11 +++++++- lib/_exit.c | 13 ++++++++++ lib/setsid.c | 10 ++++++++ 11 files changed, 231 insertions(+), 9 deletions(-) create mode 100644 lib/_exit.c create mode 100644 lib/setsid.c diff --git a/fs/open.c b/fs/open.c index a7c982d..7a3de59 100644 --- a/fs/open.c +++ b/fs/open.c @@ -126,6 +126,36 @@ int sys_chdir(const char * filename) { return (0); } +static int check_char_dev(struct m_inode * inode, int dev, int flag) { + struct tty_struct *tty; + int min; + + if (MAJOR(dev) == 4 || MAJOR(dev) == 5) { + if (MAJOR(dev) == 5) + min = current->tty; + else + min = MINOR(dev); + if (min < 0) + return -1; + tty = tty_table + min; + + if (!(flag & O_NOCTTY) && + current->leader && + current->tty<0 && + tty->session==0) { + current->tty = min; + tty->session= current->session; + tty->pgrp = current->pgrp; + } + if (flag & O_NONBLOCK) { + tty->termios.c_cc[VMIN] =0; + tty->termios.c_cc[VTIME] =0; + tty->termios.c_lflag &= ~ICANON; + } + } + return 0; +} + int sys_open(const char * filename,int flag,int mode) { struct m_inode * inode; struct file * f; @@ -154,6 +184,15 @@ int sys_open(const char * filename,int flag,int mode) { return i; } + if (S_ISCHR(inode->i_mode)) { + if (check_char_dev(inode,inode->i_zone[0],flag)) { + iput(inode); + current->filp[fd]=NULL; + f->f_count=0; + return -EAGAIN; + } + } + f->f_mode = inode->i_mode; f->f_flags = flag; f->f_count = 1; diff --git a/include/linux/sys.h b/include/linux/sys.h index 66d970a..4f5addf 100644 --- a/include/linux/sys.h +++ b/include/linux/sys.h @@ -35,7 +35,7 @@ extern int sys_access(); extern int sys_nice(); extern int sys_ftime(); extern int sys_sync(); -//extern int sys_kill(); +extern int sys_kill(); extern int sys_rename(); extern int sys_mkdir(); extern int sys_rmdir(); @@ -64,7 +64,7 @@ extern int sys_chroot(); extern int sys_dup2(); extern int sys_getppid(); //extern int sys_getpgrp(); -//extern int sys_setsid(); +extern int sys_setsid(); extern int sys_sigaction(); //extern int sys_sgetmask(); //extern int sys_ssetmask(); @@ -162,7 +162,7 @@ fn_ptr sys_call_table[] = { sys_dup2, sys_getppid, 0, // sys_getpgrp, - 0, // sys_setsid, + sys_setsid, sys_sigaction, 0, // sys_sgetmask, 0, // sys_ssetmask, diff --git a/include/unistd.h b/include/unistd.h index f94fe4c..3cfeafa 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -156,6 +156,7 @@ extern int errno; int chdir(const char* pathname); int close(int fildes); int dup(int fildes); +volatile void _exit(int status); int execve(const char * filename, char ** argv, char ** envp); int fcntl(int fildes, int cmd, ...); int fork(); @@ -168,10 +169,11 @@ int read(int fildes, const char * buf, off_t count); int lseek(int fildes, off_t offset, int origin); int rmdir(const char* pathname); - +pid_t setsid(void); time_t time(time_t * tloc); mode_t umask(mode_t mask); int uname(struct utsname * name); int utime(const char * filename, struct utimbuf * times); +pid_t wait(int * wait_stat); #endif diff --git a/kernel/chr_drv/tty_ioctl.c b/kernel/chr_drv/tty_ioctl.c index 7e0c8b0..75c4c98 100644 --- a/kernel/chr_drv/tty_ioctl.c +++ b/kernel/chr_drv/tty_ioctl.c @@ -9,6 +9,7 @@ #include #include +extern int session_of_pgrp(int pgrp); extern int tty_signal(int sig, struct tty_struct *tty); static void flush(struct tty_queue * queue) { @@ -89,6 +90,7 @@ static int set_termio(struct tty_struct * tty, struct termio * termio, int tty_ioctl(int dev, int cmd, int arg) { struct tty_struct * tty; + int pgrp; if (MAJOR(dev) == 5) { dev=current->tty; @@ -152,6 +154,22 @@ int tty_ioctl(int dev, int cmd, int arg) { flush(&tty->write_q); } else return -EINVAL; + case TIOCGPGRP: + verify_area((void *) arg,4); + put_fs_long(tty->pgrp,(unsigned long *) arg); + return 0; + case TIOCSPGRP: + if ((current->tty < 0) || + (current->tty != dev) || + (tty->session != current->session)) + return -ENOTTY; + pgrp=get_fs_long((unsigned long *) arg); + if (pgrp < 0) + return -EINVAL; + if (session_of_pgrp(pgrp) != current->session) + return -EPERM; + tty->pgrp = pgrp; + return 0; case TIOCOUTQ: verify_area((void *) arg,4); put_fs_long(CHARS(tty->write_q),(unsigned long *) arg); diff --git a/kernel/exit.c b/kernel/exit.c index 8b36d3e..713fc31 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -58,6 +58,16 @@ static inline int send_sig(long sig,struct task_struct * p,int priv) { return 0; } +int session_of_pgrp(int pgrp) { + struct task_struct **p; + for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) { + if ((*p)->pgrp == pgrp) + return((*p)->session); + } + + return -1; +} + int kill_pg(int pgrp, int sig, int priv) { struct task_struct **p; int err,retval = -ESRCH; @@ -77,6 +87,38 @@ int kill_pg(int pgrp, int sig, int priv) { return(found ? 0 : retval); } +int kill_proc(int pid, int sig, int priv) { + struct task_struct **p; + + if (sig<1 || sig>32) + return -EINVAL; + for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) { + if ((*p)->pid == pid) + return(sig ? send_sig(sig,*p,priv) : 0); + } + + return(-ESRCH); +} + +int sys_kill(int pid,int sig) { + struct task_struct **p = NR_TASKS + task; + int err, retval = 0; + + if (!pid) + return(kill_pg(current->pid,sig,0)); + if (pid == -1) { + while (--p > &FIRST_TASK) { + if (err = send_sig(sig,*p,0)) + retval = err; + } + return retval; + } + + if (pid < 0) + return(kill_pg(-pid,sig,0)); + return(kill_proc(pid,sig,0)); +} + int is_orphaned_pgrp(int pgrp) { struct task_struct **p; diff --git a/kernel/main.c b/kernel/main.c index 162f97d..32f7e92 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -175,14 +175,49 @@ static void run_sh() { } void init() { + int pid,i; + setup((void *) &drive_info); (void)open("/dev/tty0", O_RDWR, 0); (void) dup(0); (void) dup(0); - run_sh(); + //run_sh(); //easy_shell(); printf("Free mem: %d bytes\n\r",memory_end-main_memory_start); + if (!(pid=fork())) { + close(0); + if (open("/etc/rc",O_RDONLY,0)) + _exit(1); + execve("/bin/sh",argv_rc,envp_rc); + _exit(2); + } + + if (pid>0) { + while (pid != wait(&i)) + ; + } + + while (1) { + if ((pid=fork())<0) { + printf("Fork failed in init\r\n"); + continue; + } + if (!pid) { + close(0);close(1);close(2); + setsid(); + (void) open("/dev/tty0",O_RDWR,0); + (void) dup(0); + (void) dup(0); + _exit(execve("/bin/sh",argv,envp)); + } + while (1) + if (pid == wait(&i)) + break; + printf("\n\rchild %d died with code %04x\n\r",pid,i); + sync(); + } + _exit(0); } diff --git a/kernel/sched.c b/kernel/sched.c index b5a5820..c681ad1 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -280,8 +280,12 @@ int sys_getegid() { } int sys_alarm(long seconds) { - printk("unimplement sys call alarm\n"); - return 0; + int old = current->alarm; + + if (old) + old = (old - jiffies) / HZ; + current->alarm = (seconds>0)?(jiffies+HZ*seconds):0; + return (old); } int sys_nice(long increment) { diff --git a/kernel/sys.c b/kernel/sys.c index 1fcb562..585569c 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -32,6 +32,51 @@ int sys_prof() { return -ENOSYS; } +int sys_setregid(int rgid, int egid) { + if (rgid>0) { + if ((current->gid == rgid) || + suser()) + current->gid = rgid; + } + else { + return(-EPERM); + } + + if (egid>0) { + if ((current->gid == egid) || + (current->egid == egid) || + suser()) { + current->egid = egid; + current->sgid = egid; + } + else { + return(-EPERM); + } + } + + return 0; +} + +int sys_setgid(int gid) { + if (suser()) + current->gid = current->egid = current->sgid = gid; + else if ((gid == current->gid) || (gid == current->sgid)) + current->egid = gid; + else + return -EPERM; + return 0; +} + +int sys_setsid() { + if (current->leader && !suser()) + return -EPERM; + current->leader = 1; + current->session = current->pgrp = current->pid; + current->tty = -1; + + return current->pgrp; +} + int sys_rename() { return -ENOSYS; } @@ -103,7 +148,12 @@ int sys_uname(struct utsname * name) { } int sys_setuid(int uid) { - printk("unimplement sys call setuid\n"); + if (suser()) + current->uid = current->euid = current->suid = uid; + else if ((uid == current->uid) || (uid == current->suid)) + current->euid = uid; + else + return -EPERM; return 0; } diff --git a/lib/Makefile b/lib/Makefile index 9618874..f76b1e7 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -2,7 +2,7 @@ AR := ar LD := ld GCC := gcc CCFLAG := -m32 -I../include -nostdinc -ffreestanding -fno-pic -Wall -fomit-frame-pointer -fno-stack-protector -c -OBJS := ctype.o write.o string.o open.o dup.o execve.o close.o +OBJS := ctype.o write.o string.o open.o dup.o execve.o close.o _exit.o wait.o setsid.o lib.a : $(OBJS) $(AR) rcs $@ $^ @@ -29,6 +29,15 @@ execve.o : execve.c close.o : close.c $(GCC) $(CCFLAG) -o $@ $< +_exit.o : _exit.c + $(GCC) $(CCFLAG) -o $@ $< + +wait.o : wait.c + $(GCC) $(CCFLAG) -o $@ $< + +setsid.o : setsid.c + $(GCC) $(CCFLAG) -o $@ $< + clean : -rm *.o -rm lib.a diff --git a/lib/_exit.c b/lib/_exit.c new file mode 100644 index 0000000..c0c9d69 --- /dev/null +++ b/lib/_exit.c @@ -0,0 +1,13 @@ +/* + * linux/lib/_exit.c + * + * (C) 1991 Linus Torvalds + */ + +#define __LIBRARY__ +#include + +volatile void _exit(int exit_code) +{ + __asm__("int $0x80"::"a" (__NR_exit),"b" (exit_code)); +} diff --git a/lib/setsid.c b/lib/setsid.c new file mode 100644 index 0000000..68516c7 --- /dev/null +++ b/lib/setsid.c @@ -0,0 +1,10 @@ +/* + * linux/lib/setsid.c + * + * (C) 1991 Linus Torvalds + */ + +#define __LIBRARY__ +#include + +_syscall0(pid_t,setsid) -- Gitee