sys.c 代码分析
setregid
/* * This is done BSD-style, with no consideration of the saved gid, except * that if you set the effective gid, it sets the saved gid too. This * makes it possible for a setgid program to completely drop its privileges, * which is often a useful assertion to make when you are doing a security * audit over a program. * * The general idea is that a program which uses just setregid() will be * 100% compatible with BSD. A program which uses just setgid() will be * 100% compatible with POSIX w/ Saved ID‘s. */ int sys_setregid(int rgid, int egid)//设置real group ID ,effective group ID { if (rgid>0) { if ((current->gid == rgid) || suser()) //如果当前进程的gid == real group ID 或者拥有超级用户权限,就可以把当前进程的group ID更改为 real Group ID current->gid = rgid; else //否则setregid是不允许的,返回错误值 return(-EPERM); } if (egid>0) { if ((current->gid == egid) || //如果当前进程的gid 或者effective gid 等于egid 或者拥有超级用户权限,则可以修改当前进程的egid和sgid (current->egid == egid) || suser()) { current->egid = egid; current->sgid = egid; } else return(-EPERM); } return 0; }
setgid
/* * setgid() is implemeneted like SysV w/ SAVED_IDS */ int sys_setgid(int gid) //设置当前进程的group ID { if (suser()) //有超级用户权限就可以更改当前进程的gid,egid(effective gid) ,sgid(saved gid)都设置为gid current->gid = current->egid = current->sgid = gid; else if ((gid == current->gid) || (gid == current->sgid)) //如果当前进程的sgid 或者gid(current) 等于 gid(传入参数) ,那么把当前进程的effective gid 设置为gid current->egid = gid; else return -EPERM; return 0; }
sys_time
int sys_time(long * tloc) //设置系统时间 { int i; i = CURRENT_TIME; if (tloc) { verify_area(tloc,4); put_fs_long(i,(unsigned long *)tloc); } return i; }
sys_setreuid
/* * Unprivileged users may change the real user id to the effective uid * or vice versa. (BSD-style) * * When you set the effective uid, it sets the saved uid too. This * makes it possible for a setuid program to completely drop its privileges, * which is often a useful assertion to make when you are doing a security * audit over a program. * * The general idea is that a program which uses just setreuid() will be * 100% compatible with BSD. A program which uses just setuid() will be * 100% compatible with POSIX w/ Saved ID‘s. */ int sys_setreuid(int ruid, int euid) //uid == user ID 设置real 和 effective user ID { int old_ruid = current->uid; if (ruid>0) { if ((current->euid==ruid) || (old_ruid == ruid) || suser()) current->uid = ruid; else return(-EPERM); } if (euid>0) { if ((old_ruid == euid) || (current->euid == euid) || suser()) { current->euid = euid; current->suid = euid; } else { current->uid = old_ruid; return(-EPERM); } } return 0; }
setuid()
/* * setuid() is implemeneted like SysV w/ SAVED_IDS * * Note that SAVED_ID‘s is deficient in that a setuid root program * like sendmail, for example, cannot set its uid to be a normal * user and then switch back, because if you‘re root, setuid() sets * the saved uid too. If you don‘t like this, blame the bright people * in the POSIX commmittee and/or USG. Note that the BSD-style setreuid() * will allow a root program to temporarily drop privileges and be able to * regain them by swapping the real and effective uid. */ int sys_setuid(int uid) //设置user ID { 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); } int sys_stime(long * tptr) //设置系统时间 { if (!suser()) return -EPERM; startup_time = get_fs_long((unsigned long *)tptr) - jiffies/HZ; jiffies_offset = 0; return 0; }
sys_times
int sys_times(struct tms * tbuf) //获取系统时间把内核数据段的数据读到tbuf里去 { if (tbuf) { verify_area(tbuf,sizeof *tbuf); put_fs_long(current->utime,(unsigned long *)&tbuf->tms_utime); put_fs_long(current->stime,(unsigned long *)&tbuf->tms_stime); put_fs_long(current->cutime,(unsigned long *)&tbuf->tms_cutime); put_fs_long(current->cstime,(unsigned long *)&tbuf->tms_cstime); } return jiffies; }
sys_brk
int sys_brk(unsigned long end_data_seg) //brk 数据段结尾 { if (end_data_seg >= current->end_code && //如果end_data_seg大于当前进程的代码段结尾并且小于当前进程的(堆栈-16K),于是 //把end_date_seg作为新的数据段结尾 end_data_seg < current->start_stack - 16384) current->brk = end_data_seg; return current->brk; }
sys_setpgid
/* * This needs some heave checking ... * I just haven‘t get the stomach for it. I also don‘t fully * understand sessions/pgrp etc. Let somebody who does explain it. * * OK, I think I have the protection semantics right.... this is really * only important on a multi-user system anyway, to make sure one user * can‘t send a signal to a process owned by another. -TYT, 12/12/91 */ int sys_setpgid(int pid, int pgid) { int i; if (!pid) pid = current->pid; if (!pgid) pgid = current->pid; if (pgid < 0) return -EINVAL; for (i=0 ; i<NR_TASKS ; i++) if (task[i] && (task[i]->pid == pid) && ((task[i]->p_pptr == current) || (task[i] == current))) { if (task[i]->leader) return -EPERM; if ((task[i]->session != current->session) || ((pgid != pid) && (session_of_pgrp(pgid) != current->session))) return -EPERM; task[i]->pgrp = pgid; return 0; } return -ESRCH; }
getpgrp
int sys_getpgrp(void) //获得当前进程的pgrp == process group { return current->pgrp; }
setsid
int sys_setsid(void) //设置session ID { if (current->leader && !suser()) //当前进程不是session leader或者拥有超级权限的话是无法更改session ID的 return -EPERM; current->leader = 1; //当前进程被确认为session leader current->session = current->pgrp = current->pid; current->tty = -1; return current->pgrp; }
getgroups
/* * Supplementary group ID‘s */ int sys_getgroups(int gidsetsize, gid_t *grouplist) //这里应该有问题,一个进程不可能属于多一个进程组 //原因很简单,一个进程的group id只能是一个值!这就约束了它就只能属于一个进程组!他的group leader只能有一个! { int i; if (gidsetsize) verify_area(grouplist, sizeof(gid_t) * gidsetsize); for (i = 0; (i < NGROUPS) && (current->groups[i] != NOGROUP); i++, grouplist++) { if (gidsetsize) { if (i >= gidsetsize) return -EINVAL; put_fs_word(current->groups[i], (short *) grouplist); } } return(i); }
uname
static struct utsname thisname = { UTS_SYSNAME, UTS_NODENAME, UTS_RELEASE, UTS_VERSION, UTS_MACHINE }; int sys_uname(struct utsname * name) //获取系统名称信息 { int i; if (!name) return -ERROR; verify_area(name,sizeof *name); for(i=0;i<sizeof *name;i++) put_fs_byte(((char *) &thisname)[i],i+(char *) name); return 0; }
sethostname
/* * Only sethostname; gethostname can be implemented by calling uname() */ int sys_sethostname(char *name, int len) //设置系统名词信息 { int i; if (!suser()) return -EPERM; if (len > MAXHOSTNAMELEN) return -EINVAL; for (i=0; i < len; i++) { if ((thisname.nodename[i] = get_fs_byte(name+i)) == 0) break; } if (thisname.nodename[i]) { thisname.nodename[i>MAXHOSTNAMELEN ? MAXHOSTNAMELEN : i] = 0; } return 0; }
getrlimit
int sys_getrlimit(int resource, struct rlimit *rlim) //获取当前进程的资源界限值 { if (resource >= RLIM_NLIMITS) return -EINVAL; verify_area(rlim,sizeof *rlim); put_fs_long(current->rlim[resource].rlim_cur, (unsigned long *) rlim); put_fs_long(current->rlim[resource].rlim_max, ((unsigned long *) rlim)+1); return 0; }
setrlimit
int sys_setrlimit(int resource, struct rlimit *rlim) { struct rlimit new, *old; if (resource >= RLIM_NLIMITS) return -EINVAL; old = current->rlim + resource; new.rlim_cur = get_fs_long((unsigned long *) rlim); new.rlim_max = get_fs_long(((unsigned long *) rlim)+1); if (((new.rlim_cur > old->rlim_max) || (new.rlim_max > old->rlim_max)) && !suser()) return -EPERM; *old = new; return 0; }
umask
int sys_umask(int mask)//当设置当前进程创建文件的属性 { int old = current->umask; current->umask = mask & 0777; return (old); }