2697 lines · 62.9 KB · C
RawDownload
 */long __sys_setreuid(uid_t ruid, uid_t euid){	struct user_namespace *ns = current_user_ns();	const struct cred *old;	struct cred *new;	int retval;	kuid_t kruid, keuid; 	kruid = make_kuid(ns, ruid);	keuid = make_kuid(ns, euid); 	if ((ruid != (uid_t) -1) && !uid_valid(kruid))		return -EINVAL;	if ((euid != (uid_t) -1) && !uid_valid(keuid))		return -EINVAL; 	new = prepare_creds();	if (!new)		return -ENOMEM;	old = current_cred(); 	retval = -EPERM;	if (ruid != (uid_t) -1) {		new->uid = kruid;		if (!uid_eq(old->uid, kruid) &&		    !uid_eq(old->euid, kruid) &&		    !ns_capable_setid(old->user_ns, CAP_SETUID))			goto error;	} 	if (euid != (uid_t) -1) {		new->euid = keuid;		if (!uid_eq(old->uid, keuid) &&		    !uid_eq(old->euid, keuid) &&		    !uid_eq(old->suid, keuid) &&		    !ns_capable_setid(old->user_ns, CAP_SETUID))			goto error;	} 	if (!uid_eq(new->uid, old->uid)) {		retval = set_user(new);		if (retval < 0)			goto error;	}	if (ruid != (uid_t) -1 ||	    (euid != (uid_t) -1 && !uid_eq(keuid, old->uid)))		new->suid = new->euid;	new->fsuid = new->euid; 	retval = security_task_fix_setuid(new, old, LSM_SETID_RE);	if (retval < 0)		goto error; 	return commit_creds(new); error:	abort_creds(new);	return retval;} SYSCALL_DEFINE2(setreuid, uid_t, ruid, uid_t, euid){	return __sys_setreuid(ruid, euid);} /* * 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. */long __sys_setuid(uid_t uid){	struct user_namespace *ns = current_user_ns();	const struct cred *old;	struct cred *new;	int retval;	kuid_t kuid; 	kuid = make_kuid(ns, uid);	if (!uid_valid(kuid))		return -EINVAL; 	new = prepare_creds();	if (!new)		return -ENOMEM;	old = current_cred(); 	retval = -EPERM;	if (ns_capable_setid(old->user_ns, CAP_SETUID)) {		new->suid = new->uid = kuid;		if (!uid_eq(kuid, old->uid)) {			retval = set_user(new);			if (retval < 0)				goto error;		}	} else if (!uid_eq(kuid, old->uid) && !uid_eq(kuid, new->suid)) {		goto error;	} 	new->fsuid = new->euid = kuid; 	retval = security_task_fix_setuid(new, old, LSM_SETID_ID);	if (retval < 0)		goto error; 	return commit_creds(new); error:	abort_creds(new);	return retval;} SYSCALL_DEFINE1(setuid, uid_t, uid){	return __sys_setuid(uid);}  /* * This function implements a generic ability to update ruid, euid, * and suid.  This allows you to implement the 4.4 compatible seteuid(). */long __sys_setresuid(uid_t ruid, uid_t euid, uid_t suid){	struct user_namespace *ns = current_user_ns();	const struct cred *old;	struct cred *new;	int retval;	kuid_t kruid, keuid, ksuid; 	kruid = make_kuid(ns, ruid);	keuid = make_kuid(ns, euid);	ksuid = make_kuid(ns, suid); 	if ((ruid != (uid_t) -1) && !uid_valid(kruid))		return -EINVAL; 	if ((euid != (uid_t) -1) && !uid_valid(keuid))		return -EINVAL; 	if ((suid != (uid_t) -1) && !uid_valid(ksuid))		return -EINVAL; 	new = prepare_creds();	if (!new)		return -ENOMEM; 	old = current_cred(); 	retval = -EPERM;	if (!ns_capable_setid(old->user_ns, CAP_SETUID)) {		if (ruid != (uid_t) -1        && !uid_eq(kruid, old->uid) &&		    !uid_eq(kruid, old->euid) && !uid_eq(kruid, old->suid))			goto error;		if (euid != (uid_t) -1        && !uid_eq(keuid, old->uid) &&		    !uid_eq(keuid, old->euid) && !uid_eq(keuid, old->suid))			goto error;		if (suid != (uid_t) -1        && !uid_eq(ksuid, old->uid) &&		    !uid_eq(ksuid, old->euid) && !uid_eq(ksuid, old->suid))			goto error;	} 	if (ruid != (uid_t) -1) {		new->uid = kruid;		if (!uid_eq(kruid, old->uid)) {			retval = set_user(new);			if (retval < 0)				goto error;		}	}	if (euid != (uid_t) -1)		new->euid = keuid;	if (suid != (uid_t) -1)		new->suid = ksuid;	new->fsuid = new->euid; 	retval = security_task_fix_setuid(new, old, LSM_SETID_RES);	if (retval < 0)		goto error; 	return commit_creds(new); error:	abort_creds(new);	return retval;} SYSCALL_DEFINE3(setresuid, uid_t, ruid, uid_t, euid, uid_t, suid){	return __sys_setresuid(ruid, euid, suid);} SYSCALL_DEFINE3(getresuid, uid_t __user *, ruidp, uid_t __user *, euidp, uid_t __user *, suidp){	const struct cred *cred = current_cred();	int retval;	uid_t ruid, euid, suid; 	ruid = from_kuid_munged(cred->user_ns, cred->uid);	euid = from_kuid_munged(cred->user_ns, cred->euid);	suid = from_kuid_munged(cred->user_ns, cred->suid); 	retval = put_user(ruid, ruidp);	if (!retval) {		retval = put_user(euid, euidp);		if (!retval)			return put_user(suid, suidp);	}	return retval;} /* * Same as above, but for rgid, egid, sgid. */long __sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid){	struct user_namespace *ns = current_user_ns();	const struct cred *old;	struct cred *new;	int retval;	kgid_t krgid, kegid, ksgid; 	krgid = make_kgid(ns, rgid);	kegid = make_kgid(ns, egid);	ksgid = make_kgid(ns, sgid); 	if ((rgid != (gid_t) -1) && !gid_valid(krgid))		return -EINVAL;	if ((egid != (gid_t) -1) && !gid_valid(kegid))		return -EINVAL;	if ((sgid != (gid_t) -1) && !gid_valid(ksgid))		return -EINVAL; 	new = prepare_creds();	if (!new)		return -ENOMEM;	old = current_cred(); 	retval = -EPERM;	if (!ns_capable(old->user_ns, CAP_SETGID)) {		if (rgid != (gid_t) -1        && !gid_eq(krgid, old->gid) &&		    !gid_eq(krgid, old->egid) && !gid_eq(krgid, old->sgid))			goto error;		if (egid != (gid_t) -1        && !gid_eq(kegid, old->gid) &&		    !gid_eq(kegid, old->egid) && !gid_eq(kegid, old->sgid))			goto error;		if (sgid != (gid_t) -1        && !gid_eq(ksgid, old->gid) &&		    !gid_eq(ksgid, old->egid) && !gid_eq(ksgid, old->sgid))			goto error;	} 	if (rgid != (gid_t) -1)		new->gid = krgid;	if (egid != (gid_t) -1)		new->egid = kegid;	if (sgid != (gid_t) -1)		new->sgid = ksgid;	new->fsgid = new->egid; 	retval = security_task_fix_setgid(new, old, LSM_SETID_RES);	if (retval < 0)		goto error; 	return commit_creds(new); error:	abort_creds(new);	return retval;} SYSCALL_DEFINE3(setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid){	return __sys_setresgid(rgid, egid, sgid);} SYSCALL_DEFINE3(getresgid, gid_t __user *, rgidp, gid_t __user *, egidp, gid_t __user *, sgidp){	const struct cred *cred = current_cred();	int retval;	gid_t rgid, egid, sgid; 	rgid = from_kgid_munged(cred->user_ns, cred->gid);	egid = from_kgid_munged(cred->user_ns, cred->egid);	sgid = from_kgid_munged(cred->user_ns, cred->sgid); 	retval = put_user(rgid, rgidp);	if (!retval) {		retval = put_user(egid, egidp);		if (!retval)			retval = put_user(sgid, sgidp);	} 	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.. */long __sys_setfsuid(uid_t uid){	const struct cred *old;	struct cred *new;	uid_t old_fsuid;	kuid_t kuid; 	old = current_cred();	old_fsuid = from_kuid_munged(old->user_ns, old->fsuid); 	kuid = make_kuid(old->user_ns, uid);	if (!uid_valid(kuid))		return old_fsuid; 	new = prepare_creds();	if (!new)		return old_fsuid; 	if (uid_eq(kuid, old->uid)  || uid_eq(kuid, old->euid)  ||	    uid_eq(kuid, old->suid) || uid_eq(kuid, old->fsuid) ||	    ns_capable_setid(old->user_ns, CAP_SETUID)) {		if (!uid_eq(kuid, old->fsuid)) {			new->fsuid = kuid;			if (security_task_fix_setuid(new, old, LSM_SETID_FS) == 0)				goto change_okay;		}	} 	abort_creds(new);	return old_fsuid; change_okay:	commit_creds(new);	return old_fsuid;} SYSCALL_DEFINE1(setfsuid, uid_t, uid){	return __sys_setfsuid(uid);} /* * Samma på svenska.. */long __sys_setfsgid(gid_t gid){	const struct cred *old;	struct cred *new;	gid_t old_fsgid;	kgid_t kgid; 	old = current_cred();	old_fsgid = from_kgid_munged(old->user_ns, old->fsgid); 	kgid = make_kgid(old->user_ns, gid);	if (!gid_valid(kgid))		return old_fsgid; 	new = prepare_creds();	if (!new)		return old_fsgid; 	if (gid_eq(kgid, old->gid)  || gid_eq(kgid, old->egid)  ||	    gid_eq(kgid, old->sgid) || gid_eq(kgid, old->fsgid) ||	    ns_capable(old->user_ns, CAP_SETGID)) {		if (!gid_eq(kgid, old->fsgid)) {			new->fsgid = kgid;			if (security_task_fix_setgid(new,old,LSM_SETID_FS) == 0)				goto change_okay;		}	} 	abort_creds(new);	return old_fsgid; change_okay:	commit_creds(new);	return old_fsgid;} SYSCALL_DEFINE1(setfsgid, gid_t, gid){	return __sys_setfsgid(gid);}#endif /* CONFIG_MULTIUSER */ /** * sys_getpid - return the thread group id of the current process * * Note, despite the name, this returns the tgid not the pid.  The tgid and * the pid are identical unless CLONE_THREAD was specified on clone() in * which case the tgid is the same in all threads of the same group. * * This is SMP safe as current->tgid does not change. */SYSCALL_DEFINE0(getpid){	return task_tgid_vnr(current);} /* Thread ID - the internal kernel "pid" */SYSCALL_DEFINE0(gettid){	return task_pid_vnr(current);} /* * Accessing ->real_parent is not SMP-safe, it could * change from under us. However, we can use a stale * value of ->real_parent under rcu_read_lock(), see * release_task()->call_rcu(delayed_put_task_struct). */SYSCALL_DEFINE0(getppid){	int pid; 	rcu_read_lock();	pid = task_tgid_vnr(rcu_dereference(current->real_parent));	rcu_read_unlock(); 	return pid;} SYSCALL_DEFINE0(getuid){	/* Only we change this so SMP safe */	return from_kuid_munged(current_user_ns(), current_uid());} SYSCALL_DEFINE0(geteuid){	/* Only we change this so SMP safe */	return from_kuid_munged(current_user_ns(), current_euid());} SYSCALL_DEFINE0(getgid){	/* Only we change this so SMP safe */	return from_kgid_munged(current_user_ns(), current_gid());} SYSCALL_DEFINE0(getegid){	/* Only we change this so SMP safe */	return from_kgid_munged(current_user_ns(), current_egid());} static void do_sys_times(struct tms *tms){	u64 tgutime, tgstime, cutime, cstime; 	thread_group_cputime_adjusted(current, &tgutime, &tgstime);	cutime = current->signal->cutime;	cstime = current->signal->cstime;	tms->tms_utime = nsec_to_clock_t(tgutime);	tms->tms_stime = nsec_to_clock_t(tgstime);	tms->tms_cutime = nsec_to_clock_t(cutime);	tms->tms_cstime = nsec_to_clock_t(cstime);} SYSCALL_DEFINE1(times, struct tms __user *, tbuf){	if (tbuf) {		struct tms tmp; 		do_sys_times(&tmp);		if (copy_to_user(tbuf, &tmp, sizeof(struct tms)))			return -EFAULT;	}	force_successful_syscall_return();	return (long) jiffies_64_to_clock_t(get_jiffies_64());} #ifdef CONFIG_COMPATstatic compat_clock_t clock_t_to_compat_clock_t(clock_t x){	return compat_jiffies_to_clock_t(clock_t_to_jiffies(x));} COMPAT_SYSCALL_DEFINE1(times, struct compat_tms __user *, tbuf){	if (tbuf) {		struct tms tms;		struct compat_tms tmp; 		do_sys_times(&tms);		/* Convert our struct tms to the compat version. */		tmp.tms_utime = clock_t_to_compat_clock_t(tms.tms_utime);		tmp.tms_stime = clock_t_to_compat_clock_t(tms.tms_stime);		tmp.tms_cutime = clock_t_to_compat_clock_t(tms.tms_cutime);		tmp.tms_cstime = clock_t_to_compat_clock_t(tms.tms_cstime);

Lines 501–1000 of 2697. Previous lines

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t