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

📄 sys.c

📁 linux 2.6.19 kernel source code before patching
💻 C
📖 第 1 页 / 共 4 页
字号:
		    (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 = suid_dumpable;		smp_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;	key_fsuid_changed(current);	proc_id_connector(current, PROC_EVENT_UID);	return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RE);}		/* * 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_suid;	int retval;	retval = security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_ID);	if (retval)		return retval;	old_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 = suid_dumpable;		smp_wmb();	}	current->fsuid = current->euid = uid;	current->suid = new_suid;	key_fsuid_changed(current);	proc_id_connector(current, PROC_EVENT_UID);	return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_ID);}/* * 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;	int retval;	retval = security_task_setuid(ruid, euid, suid, LSM_SETID_RES);	if (retval)		return retval;	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 = suid_dumpable;			smp_wmb();		}		current->euid = euid;	}	current->fsuid = current->euid;	if (suid != (uid_t) -1)		current->suid = suid;	key_fsuid_changed(current);	proc_id_connector(current, PROC_EVENT_UID);	return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RES);}asmlinkage long sys_getresuid(uid_t __user *ruid, uid_t __user *euid, uid_t __user *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){	int retval;	retval = security_task_setgid(rgid, egid, sgid, LSM_SETID_RES);	if (retval)		return retval;	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 = suid_dumpable;			smp_wmb();		}		current->egid = egid;	}	current->fsgid = current->egid;	if (rgid != (gid_t) -1)		current->gid = rgid;	if (sgid != (gid_t) -1)		current->sgid = sgid;	key_fsgid_changed(current);	proc_id_connector(current, PROC_EVENT_GID);	return 0;}asmlinkage long sys_getresgid(gid_t __user *rgid, gid_t __user *egid, gid_t __user *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 (security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS))		return old_fsuid;	if (uid == current->uid || uid == current->euid ||	    uid == current->suid || uid == current->fsuid || 	    capable(CAP_SETUID)) {		if (uid != old_fsuid) {			current->mm->dumpable = suid_dumpable;			smp_wmb();		}		current->fsuid = uid;	}	key_fsuid_changed(current);	proc_id_connector(current, PROC_EVENT_UID);	security_task_post_setuid(old_fsuid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS);	return old_fsuid;}/* * Samma på svenska.. */asmlinkage long sys_setfsgid(gid_t gid){	int old_fsgid;	old_fsgid = current->fsgid;	if (security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_FS))		return old_fsgid;	if (gid == current->gid || gid == current->egid ||	    gid == current->sgid || gid == current->fsgid || 	    capable(CAP_SETGID)) {		if (gid != old_fsgid) {			current->mm->dumpable = suid_dumpable;			smp_wmb();		}		current->fsgid = gid;		key_fsgid_changed(current);		proc_id_connector(current, PROC_EVENT_GID);	}	return old_fsgid;}asmlinkage long sys_times(struct tms __user * 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) {		struct tms tmp;		struct task_struct *tsk = current;		struct task_struct *t;		cputime_t utime, stime, cutime, cstime;		spin_lock_irq(&tsk->sighand->siglock);		utime = tsk->signal->utime;		stime = tsk->signal->stime;		t = tsk;		do {			utime = cputime_add(utime, t->utime);			stime = cputime_add(stime, t->stime);			t = next_thread(t);		} while (t != tsk);		cutime = tsk->signal->cutime;		cstime = tsk->signal->cstime;		spin_unlock_irq(&tsk->sighand->siglock);		tmp.tms_utime = cputime_to_clock_t(utime);		tmp.tms_stime = cputime_to_clock_t(stime);		tmp.tms_cutime = cputime_to_clock_t(cutime);		tmp.tms_cstime = cputime_to_clock_t(cstime);		if (copy_to_user(tbuf, &tmp, sizeof(struct tms)))			return -EFAULT;	}	return (long) jiffies_64_to_clock_t(get_jiffies_64());}/* * 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;	struct task_struct *group_leader = current->group_leader;	int err = -EINVAL;	if (!pid)		pid = group_leader->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->real_parent == group_leader) {		err = -EPERM;		if (task_session(p) != task_session(group_leader))			goto out;		err = -EACCES;		if (p->did_exec)			goto out;	} else {		err = -ESRCH;		if (p != group_leader)			goto out;	}	err = -EPERM;	if (p->signal->leader)		goto out;	if (pgid != pid) {		struct task_struct *g =			find_task_by_pid_type(PIDTYPE_PGID, pgid);		if (!g || task_session(g) != task_session(group_leader))			goto out;	}	err = security_task_setpgid(p, pgid);	if (err)		goto out;	if (process_group(p) != pgid) {		detach_pid(p, PIDTYPE_PGID);		p->signal->pgrp = pgid;		attach_pid(p, PIDTYPE_PGID, find_pid(pgid));	}	err = 0;out:	/* All paths lead to here, thus we are safe. -DaveM */	write_unlock_irq(&tasklist_lock);	return err;}asmlinkage long sys_getpgid(pid_t pid){	if (!pid)		return process_group(current);	else {		int retval;		struct task_struct *p;		read_lock(&tasklist_lock);		p = find_task_by_pid(pid);		retval = -ESRCH;		if (p) {			retval = security_task_getpgid(p);			if (!retval)				retval = process_group(p);		}		read_unlock(&tasklist_lock);		return retval;	}}#ifdef __ARCH_WANT_SYS_GETPGRPasmlinkage long sys_getpgrp(void){	/* SMP - assuming writes are word atomic this is fine */	return process_group(current);}#endifasmlinkage long sys_getsid(pid_t pid){	if (!pid)		return process_session(current);	else {		int retval;		struct task_struct *p;		read_lock(&tasklist_lock);		p = find_task_by_pid(pid);		retval = -ESRCH;		if (p) {			retval = security_task_getsid(p);			if (!retval)				retval = process_session(p);		}		read_unlock(&tasklist_lock);		return retval;	}}asmlinkage long sys_setsid(void){	struct task_struct *group_leader = current->group_leader;	pid_t session;	int err = -EPERM;	write_lock_irq(&tasklist_lock);	/* Fail if I am already a session leader */	if (group_leader->signal->leader)		goto out;	session = group_leader->pid;	/* Fail if a process group id already exists that equals the	 * proposed session id.	 *	 * Don't check if session id == 1 because kernel threads use this	 * session id and so the check will always fail and make it so	 * init cannot successfully call setsid.	 */	if (session > 1 && find_task_by_pid_type(PIDTYPE_PGID, session))		goto out;	group_leader->signal->leader = 1;	__set_special_pids(session, session);	spin_lock(&group_leader->sighand->siglock);	group_leader->signal->tty = NULL;	spin_unlock(&group_leader->sighand->siglock);	err = process_group(group_leader);out:	write_unlock_irq(&tasklist_lock);	return err;}/* * Supplementary group IDs *//* init to 2 - one for init_task, one to ensure it is never freed */struct group_info init_groups = { .usage = ATOMIC_INIT(2) };struct group_info *groups_alloc(int gidsetsize){	struct group_info *group_info;	int nblocks;	int i;	nblocks = (gidsetsize + NGROUPS_PER_BLOCK - 1) / NGROUPS_PER_BLOCK;	/* Make sure we always allocate at least one indirect block pointer */	nblocks = nblocks ? : 1;	group_info = kmalloc(sizeof(*group_info) + nblocks*sizeof(gid_t *), GFP_USER);	if (!group_info)		return NULL;	group_info->ngroups = gidsetsize;	group_info->nblocks = nblocks;	atomic_set(&group_info->usage, 1);	if (gidsetsize <= NGROUPS_SMALL)		group_info->blocks[0] = group_info->small_block;	else {		for (i = 0; i < nblocks; i++) {			gid_t *b;			b = (void *)__get_free_page(GFP_USER);			if (!b)				goto out_undo_partial_alloc;			group_info->blocks[i] = b;		}	}	return group_info;out_undo_partial_alloc:	while (--i >= 0) {		free_page((unsigned long)group_info->blocks[i]);	}	kfree(group_info);	return NULL;}EXPORT_SYMBOL(groups_alloc);void groups_free(struct group_info *group_info){	if (group_info->blocks[0] != group_info->small_block) {		int i;		for (i = 0; i < group_info->nblocks; i++)			free_page((unsigned long)group_info->blocks[i]);	}	kfree(group_info);}EXPORT_SYMBOL(groups_free);/* export the group_info to a user-space array */static int groups_to_user(gid_t __user *grouplist,    struct group_info *group_info){	int i;	int count = group_info->ngroups;	for (i = 0; i < group_info->nblocks; i++) {		int cp_count = min(NGROUPS_PER_BLOCK, count);		int off = i * NGROUPS_PER_BLOCK;		int len = cp_count * sizeof(*grouplist);		if (copy_to_user(grouplist+off, group_info->blocks[i], len))			return -EFAULT;		count -= cp_count;	}	return 0;}/* fill a group_info from a user-space array - it must be allocated already */static int groups_from_user(struct group_info *group_info,    gid_t __user *grouplist){	int i;	int count = group_info->ngroups;	for (i = 0; i < group_info->nblocks; i++) {		int cp_count = min(NGROUPS_PER_BLOCK, count);		int off = i * NGROUPS_PER_BLOCK;		int len = cp_count * sizeof(*grouplist);		if (copy_from_user(group_info->blocks[i], grouplist+off, len))			return -EFAULT;		count -= cp_count;	}	return 0;}/* a simple Shell sort */static void groups_sort(struct group_info *group_info){	int base, max, stride;	int gidsetsize = group_info->ngroups;	for (stride = 1; stride < gidsetsize; stride = 3 * stride + 1)		; /* nothing */	stride /= 3;	while (stride) {		max = gidsetsize - stride;		for (base = 0; base < max; base++) {			int left = base;			int right = left + stride;			gid_t tmp = GROUP_AT(group_info, right);			while (left >= 0 && GROUP_AT(group_info, left) > tmp) {				GROUP_AT(group_info, right) =				    GROUP_AT(group_info, left);				right = left;				left -= stride;

⌨️ 快捷键说明

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