diff --git a/fs/open.c b/fs/open.c index a7c982d95bcbdf8cb44afa2d25c1a12646d2034e..7a3de5979dad83684bc5ef17a90629f214f5866b 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 66d970ad002c100a20b5507c956438533be14990..4f5addf6dc5bda77657df765cab842247f7b2f42 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 f94fe4c8f48d300824d1779d5f2ed0c5f27a9f5f..3cfeafa704788e46c199831eae117dfeb8132356 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 7e0c8b03319510f5d9f25f979e1446840c6c865e..75c4c9839db29f8b3b07baf8d46ad8a5fb43e153 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 8b36d3e387dabc2f1143d8435720fb601daf9182..713fc310e712efaf92d23491ea626d651411880a 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 162f97d7c52d8374335ceccc25600aac37ef8017..32f7e92fac9c3ff91be09a673e0f538bfee926ba 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 b5a5820adb326ac7fa79566eb057a33a7365c399..c681ad1628a69cfe26d41038d5741e9ddb5d6b2e 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 1fcb56267c42495216b794d5d9067d4e58314df1..585569cd804b3c548d33a446d08bf03075d338a0 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 9618874db4ffc4be2e4282715d0de8e3ddee2c06..f76b1e73ac3313b881f84091ccaf2dcfbcd8319d 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 0000000000000000000000000000000000000000..c0c9d69956962fa7bed801762f868584ae146064 --- /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 0000000000000000000000000000000000000000..68516c7e579d05c942b158d48e79c327d2b31c55 --- /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)