⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sys.c

📁 .添加系统调用.采用编译内核的方法
💻 C
📖 第 1 页 / 共 3 页
字号:
			return -EPERM;	}	if (egid != (gid_t) -1) {		if ((old_rgid == egid) ||		    (current->egid == egid) ||		    (current->sgid == egid) ||		    capable(CAP_SETGID))			new_egid = egid;		else {			return -EPERM;		}	}	if (new_egid != old_egid)	{		current->mm->dumpable = 0;		wmb();	}	if (rgid != (gid_t) -1 ||	    (egid != (gid_t) -1 && egid != old_rgid))		current->sgid = new_egid;	current->fsgid = new_egid;	current->egid = new_egid;	current->gid = new_rgid;	return 0;}/* * setgid() is implemented like SysV w/ SAVED_IDS  * * SMP: Same implicit races as above. */asmlinkage long sys_setgid(gid_t gid){	int old_egid = current->egid;	if (capable(CAP_SETGID))	{		if(old_egid != gid)		{			current->mm->dumpable=0;			wmb();		}		current->gid = current->egid = current->sgid = current->fsgid = gid;	}	else if ((gid == current->gid) || (gid == current->sgid))	{		if(old_egid != gid)		{			current->mm->dumpable=0;			wmb();		}		current->egid = current->fsgid = gid;	}	else		return -EPERM;	return 0;}  /*  * cap_emulate_setxuid() fixes the effective / permitted capabilities of * a process after a call to setuid, setreuid, or setresuid. * *  1) When set*uiding _from_ one of {r,e,s}uid == 0 _to_ all of *  {r,e,s}uid != 0, the permitted and effective capabilities are *  cleared. * *  2) When set*uiding _from_ euid == 0 _to_ euid != 0, the effective *  capabilities of the process are cleared. * *  3) When set*uiding _from_ euid != 0 _to_ euid == 0, the effective *  capabilities are set to the permitted capabilities. * *  fsuid is handled elsewhere. fsuid == 0 and {r,e,s}uid!= 0 should  *  never happen. * *  -astor  * * cevans - New behaviour, Oct '99 * A process may, via prctl(), elect to keep its capabilities when it * calls setuid() and switches away from uid==0. Both permitted and * effective sets will be retained. * Without this change, it was impossible for a daemon to drop only some * of its privilege. The call to setuid(!=0) would drop all privileges! * Keeping uid 0 is not an option because uid 0 owns too many vital * files.. * Thanks to Olaf Kirch and Peter Benie for spotting this. */static inline void cap_emulate_setxuid(int old_ruid, int old_euid, 				       int old_suid){	if ((old_ruid == 0 || old_euid == 0 || old_suid == 0) &&	    (current->uid != 0 && current->euid != 0 && current->suid != 0) &&	    !current->keep_capabilities) {		cap_clear(current->cap_permitted);		cap_clear(current->cap_effective);	}	if (old_euid == 0 && current->euid != 0) {		cap_clear(current->cap_effective);	}	if (old_euid != 0 && current->euid == 0) {		current->cap_effective = current->cap_permitted;	}}int set_user(uid_t new_ruid, int dumpclear){	struct user_struct *new_user, *old_user;	struct task_struct *this_task = current;	/* What if a process setreuid()'s and this brings the	 * new uid over his NPROC rlimit?  We can check this now	 * cheaply with the new uid cache, so if it matters	 * we should be checking for it.  -DaveM	 */	new_user = alloc_uid(new_ruid);	if (!new_user)		return -EAGAIN;	old_user = this_task->user;	atomic_inc(&new_user->processes);	atomic_dec(&old_user->processes);	if (dumpclear && this_task->mm) {		this_task->mm->dumpable = 0;		wmb();	}	this_task->uid = new_ruid;	this_task->user = new_user;	free_uid(old_user);	return 0;}/* * Unprivileged users may change the real uid to the effective uid * or vice versa.  (BSD-style) * * If you set the real uid at all, or set the effective uid to a value not * equal to the real uid, then the saved uid is set to the new effective uid. * * 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 with saved IDs.  */asmlinkage long sys_setreuid(uid_t ruid, uid_t euid){	int old_ruid, old_euid, old_suid, new_ruid, new_euid;	new_ruid = old_ruid = current->uid;	new_euid = old_euid = current->euid;	old_suid = current->suid;	if (ruid != (uid_t) -1) {		new_ruid = ruid;		if ((old_ruid != ruid) &&		    (current->euid != ruid) &&		    !capable(CAP_SETUID))			return -EPERM;	}	if (euid != (uid_t) -1) {		new_euid = euid;		if ((old_ruid != euid) &&		    (current->euid != euid) &&		    (current->suid != euid) &&		    !capable(CAP_SETUID))			return -EPERM;	}	if (new_ruid != old_ruid && set_user(new_ruid, new_euid != old_euid) < 0)		return -EAGAIN;	if (new_euid != old_euid)	{		current->mm->dumpable=0;		wmb();	}	current->fsuid = current->euid = new_euid;	if (ruid != (uid_t) -1 ||	    (euid != (uid_t) -1 && euid != old_ruid))		current->suid = current->euid;	current->fsuid = current->euid;	if (!issecure(SECURE_NO_SETUID_FIXUP)) {		cap_emulate_setxuid(old_ruid, old_euid, old_suid);	}	return 0;}		/* * setuid() is implemented like SysV with 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 committee 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.   */asmlinkage long sys_setuid(uid_t uid){	int old_euid = current->euid;	int old_ruid, old_suid, new_ruid, new_suid;	old_ruid = new_ruid = current->uid;	old_suid = current->suid;	new_suid = old_suid;		if (capable(CAP_SETUID)) {		if (uid != old_ruid && set_user(uid, old_euid != uid) < 0)			return -EAGAIN;		new_suid = uid;	} else if ((uid != current->uid) && (uid != new_suid))		return -EPERM;	if (old_euid != uid)	{		current->mm->dumpable = 0;		wmb();	}	current->fsuid = current->euid = uid;	current->suid = new_suid;	if (!issecure(SECURE_NO_SETUID_FIXUP)) {		cap_emulate_setxuid(old_ruid, old_euid, old_suid);	}	return 0;}/* * This function implements a generic ability to update ruid, euid, * and suid.  This allows you to implement the 4.4 compatible seteuid(). */asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid){	int old_ruid = current->uid;	int old_euid = current->euid;	int old_suid = current->suid;	if (!capable(CAP_SETUID)) {		if ((ruid != (uid_t) -1) && (ruid != current->uid) &&		    (ruid != current->euid) && (ruid != current->suid))			return -EPERM;		if ((euid != (uid_t) -1) && (euid != current->uid) &&		    (euid != current->euid) && (euid != current->suid))			return -EPERM;		if ((suid != (uid_t) -1) && (suid != current->uid) &&		    (suid != current->euid) && (suid != current->suid))			return -EPERM;	}	if (ruid != (uid_t) -1) {		if (ruid != current->uid && set_user(ruid, euid != current->euid) < 0)			return -EAGAIN;	}	if (euid != (uid_t) -1) {		if (euid != current->euid)		{			current->mm->dumpable = 0;			wmb();		}		current->euid = euid;	}	current->fsuid = current->euid;	if (suid != (uid_t) -1)		current->suid = suid;	if (!issecure(SECURE_NO_SETUID_FIXUP)) {		cap_emulate_setxuid(old_ruid, old_euid, old_suid);	}	return 0;}asmlinkage long sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid){	int retval;	if (!(retval = put_user(current->uid, ruid)) &&	    !(retval = put_user(current->euid, euid)))		retval = put_user(current->suid, suid);	return retval;}/* * Same as above, but for rgid, egid, sgid. */asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid){	if (!capable(CAP_SETGID)) {		if ((rgid != (gid_t) -1) && (rgid != current->gid) &&		    (rgid != current->egid) && (rgid != current->sgid))			return -EPERM;		if ((egid != (gid_t) -1) && (egid != current->gid) &&		    (egid != current->egid) && (egid != current->sgid))			return -EPERM;		if ((sgid != (gid_t) -1) && (sgid != current->gid) &&		    (sgid != current->egid) && (sgid != current->sgid))			return -EPERM;	}	if (egid != (gid_t) -1) {		if (egid != current->egid)		{			current->mm->dumpable = 0;			wmb();		}		current->egid = egid;	}	current->fsgid = current->egid;	if (rgid != (gid_t) -1)		current->gid = rgid;	if (sgid != (gid_t) -1)		current->sgid = sgid;	return 0;}asmlinkage long sys_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid){	int retval;	if (!(retval = put_user(current->gid, rgid)) &&	    !(retval = put_user(current->egid, egid)))		retval = put_user(current->sgid, sgid);	return retval;}/* * "setfsuid()" sets the fsuid - the uid used for filesystem checks. This * is used for "access()" and for the NFS daemon (letting nfsd stay at * whatever uid it wants to). It normally shadows "euid", except when * explicitly set by setfsuid() or for access.. */asmlinkage long sys_setfsuid(uid_t uid){	int old_fsuid;	old_fsuid = current->fsuid;	if (uid == current->uid || uid == current->euid ||	    uid == current->suid || uid == current->fsuid || 	    capable(CAP_SETUID))	{		if (uid != old_fsuid)		{			current->mm->dumpable = 0;			wmb();		}		current->fsuid = uid;	}	/* We emulate fsuid by essentially doing a scaled-down version	 * of what we did in setresuid and friends. However, we only	 * operate on the fs-specific bits of the process' effective	 * capabilities 	 *	 * FIXME - is fsuser used for all CAP_FS_MASK capabilities?	 *          if not, we might be a bit too harsh here.	 */		if (!issecure(SECURE_NO_SETUID_FIXUP)) {		if (old_fsuid == 0 && current->fsuid != 0) {			cap_t(current->cap_effective) &= ~CAP_FS_MASK;		}		if (old_fsuid != 0 && current->fsuid == 0) {			cap_t(current->cap_effective) |=				(cap_t(current->cap_permitted) & CAP_FS_MASK);		}	}	return old_fsuid;}/* * Samma på svenska.. */asmlinkage long sys_setfsgid(gid_t gid){	int old_fsgid;	old_fsgid = current->fsgid;	if (gid == current->gid || gid == current->egid ||	    gid == current->sgid || gid == current->fsgid || 	    capable(CAP_SETGID))	{		if (gid != old_fsgid)		{			current->mm->dumpable = 0;			wmb();		}		current->fsgid = gid;	}	return old_fsgid;}asmlinkage long sys_times(struct tms * tbuf){	/*	 *	In the SMP world we might just be unlucky and have one of	 *	the times increment as we use it. Since the value is an	 *	atomically safe type this is just fine. Conceptually its	 *	as if the syscall took an instant longer to occur.	 */	if (tbuf)		if (copy_to_user(tbuf, &current->times, sizeof(struct tms)))			return -EFAULT;	return jiffies;}/* * This needs some heavy checking ... * I just haven't 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 * * Auch. Had to add the 'did_exec' flag to conform completely to POSIX. * LBT 04.03.94 */asmlinkage long sys_setpgid(pid_t pid, pid_t pgid){	struct task_struct * p;	int err = -EINVAL;	if (!pid)		pid = current->pid;	if (!pgid)		pgid = pid;	if (pgid < 0)		return -EINVAL;	/* From this point forward we keep holding onto the tasklist lock	 * so that our parent does not change from under us. -DaveM	 */	write_lock_irq(&tasklist_lock);	err = -ESRCH;	p = find_task_by_pid(pid);	if (!p)		goto out;	err = -EINVAL;	if (!thread_group_leader(p))		goto out;	if (p->parent == current || p->real_parent == current) {		err = -EPERM;		if (p->session != current->session)			goto out;		err = -EACCES;		if (p->did_exec)			goto out;	} else {		err = -ESRCH;		if (p != current)			goto out;	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -