Christian Brauner (Amutable)exec_state: relocate dumpable information6b1c66c5 months agoHistory
3074 lines · 72.8 KB · C
RawDownload
	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);		if (copy_to_user(tbuf, &tmp, sizeof(tmp)))			return -EFAULT;	}	force_successful_syscall_return();	return compat_jiffies_to_clock_t(jiffies);}#endif /* * 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 * * !PF_FORKNOEXEC check to conform completely to POSIX. */SYSCALL_DEFINE2(setpgid, pid_t, pid, pid_t, pgid){	struct task_struct *p;	struct task_struct *group_leader = current->group_leader;	struct pid *pids[PIDTYPE_MAX] = { 0 };	struct pid *pgrp;	int err; 	if (!pid)		pid = task_pid_vnr(group_leader);	if (!pgid)		pgid = pid;	if (pgid < 0)		return -EINVAL;	rcu_read_lock(); 	/* 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_vpid(pid);	if (!p)		goto out; 	err = -EINVAL;	if (!thread_group_leader(p))		goto out; 	if (same_thread_group(p->real_parent, group_leader)) {		err = -EPERM;		if (task_session(p) != task_session(group_leader))			goto out;		err = -EACCES;		if (!(p->flags & PF_FORKNOEXEC))			goto out;	} else {		err = -ESRCH;		if (p != group_leader)			goto out;	} 	err = -EPERM;	if (p->signal->leader)		goto out; 	pgrp = task_pid(p);	if (pgid != pid) {		struct task_struct *g; 		pgrp = find_vpid(pgid);		g = pid_task(pgrp, PIDTYPE_PGID);		if (!g || task_session(g) != task_session(group_leader))			goto out;	} 	err = security_task_setpgid(p, pgid);	if (err)		goto out; 	if (task_pgrp(p) != pgrp)		change_pid(pids, p, PIDTYPE_PGID, pgrp); 	err = 0;out:	/* All paths lead to here, thus we are safe. -DaveM */	write_unlock_irq(&tasklist_lock);	rcu_read_unlock();	free_pids(pids);	return err;} static int do_getpgid(pid_t pid){	struct task_struct *p;	struct pid *grp;	int retval; 	rcu_read_lock();	if (!pid)		grp = task_pgrp(current);	else {		retval = -ESRCH;		p = find_task_by_vpid(pid);		if (!p)			goto out;		grp = task_pgrp(p);		if (!grp)			goto out; 		retval = security_task_getpgid(p);		if (retval)			goto out;	}	retval = pid_vnr(grp);out:	rcu_read_unlock();	return retval;} SYSCALL_DEFINE1(getpgid, pid_t, pid){	return do_getpgid(pid);} #ifdef __ARCH_WANT_SYS_GETPGRP SYSCALL_DEFINE0(getpgrp){	return do_getpgid(0);} #endif SYSCALL_DEFINE1(getsid, pid_t, pid){	struct task_struct *p;	struct pid *sid;	int retval; 	rcu_read_lock();	if (!pid)		sid = task_session(current);	else {		retval = -ESRCH;		p = find_task_by_vpid(pid);		if (!p)			goto out;		sid = task_session(p);		if (!sid)			goto out; 		retval = security_task_getsid(p);		if (retval)			goto out;	}	retval = pid_vnr(sid);out:	rcu_read_unlock();	return retval;} static void set_special_pids(struct pid **pids, struct pid *pid){	struct task_struct *curr = current->group_leader; 	if (task_session(curr) != pid)		change_pid(pids, curr, PIDTYPE_SID, pid); 	if (task_pgrp(curr) != pid)		change_pid(pids, curr, PIDTYPE_PGID, pid);} int ksys_setsid(void){	struct task_struct *group_leader = current->group_leader;	struct pid *sid = task_pid(group_leader);	struct pid *pids[PIDTYPE_MAX] = { 0 };	pid_t session = pid_vnr(sid);	int err = -EPERM; 	write_lock_irq(&tasklist_lock);	/* Fail if I am already a session leader */	if (group_leader->signal->leader)		goto out; 	/* Fail if a process group id already exists that equals the	 * proposed session id.	 */	if (pid_task(sid, PIDTYPE_PGID))		goto out; 	group_leader->signal->leader = 1;	set_special_pids(pids, sid); 	proc_clear_tty(group_leader); 	err = session;out:	write_unlock_irq(&tasklist_lock);	free_pids(pids);	if (err > 0) {		proc_sid_connector(group_leader);		sched_autogroup_create_attach(group_leader);	}	return err;} SYSCALL_DEFINE0(setsid){	return ksys_setsid();} DECLARE_RWSEM(uts_sem); #ifdef COMPAT_UTS_MACHINE#define override_architecture(name) \	(personality(current->personality) == PER_LINUX32 && \	 copy_to_user(name->machine, COMPAT_UTS_MACHINE, \		      sizeof(COMPAT_UTS_MACHINE)))#else#define override_architecture(name)	0#endif /* * Work around broken programs that cannot handle "Linux 3.0". * Instead we map 3.x to 2.6.40+x, so e.g. 3.0 would be 2.6.40 * And we map 4.x and later versions to 2.6.60+x, so 4.0/5.0/6.0/... would be * 2.6.60. */static int override_release(char __user *release, size_t len){	int ret = 0; 	if (current->personality & UNAME26) {		const char *rest = UTS_RELEASE;		char buf[65] = { 0 };		int ndots = 0;		unsigned v;		size_t copy; 		while (*rest) {			if (*rest == '.' && ++ndots >= 3)				break;			if (!isdigit(*rest) && *rest != '.')				break;			rest++;		}		v = LINUX_VERSION_PATCHLEVEL + 60;		copy = clamp_t(size_t, len, 1, sizeof(buf));		copy = scnprintf(buf, copy, "2.6.%u%s", v, rest);		ret = copy_to_user(release, buf, copy + 1);	}	return ret;} SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name){	struct new_utsname tmp; 	down_read(&uts_sem);	memcpy(&tmp, utsname(), sizeof(tmp));	up_read(&uts_sem);	if (copy_to_user(name, &tmp, sizeof(tmp)))		return -EFAULT; 	if (override_release(name->release, sizeof(name->release)))		return -EFAULT;	if (override_architecture(name))		return -EFAULT;	return 0;} #ifdef __ARCH_WANT_SYS_OLD_UNAME/* * Old cruft */SYSCALL_DEFINE1(uname, struct old_utsname __user *, name){	struct old_utsname tmp; 	if (!name)		return -EFAULT; 	down_read(&uts_sem);	memcpy(&tmp, utsname(), sizeof(tmp));	up_read(&uts_sem);	if (copy_to_user(name, &tmp, sizeof(tmp)))		return -EFAULT; 	if (override_release(name->release, sizeof(name->release)))		return -EFAULT;	if (override_architecture(name))		return -EFAULT;	return 0;} SYSCALL_DEFINE1(olduname, struct oldold_utsname __user *, name){	struct oldold_utsname tmp; 	if (!name)		return -EFAULT; 	memset(&tmp, 0, sizeof(tmp)); 	down_read(&uts_sem);	memcpy(&tmp.sysname, &utsname()->sysname, __OLD_UTS_LEN);	memcpy(&tmp.nodename, &utsname()->nodename, __OLD_UTS_LEN);	memcpy(&tmp.release, &utsname()->release, __OLD_UTS_LEN);	memcpy(&tmp.version, &utsname()->version, __OLD_UTS_LEN);	memcpy(&tmp.machine, &utsname()->machine, __OLD_UTS_LEN);	up_read(&uts_sem);	if (copy_to_user(name, &tmp, sizeof(tmp)))		return -EFAULT; 	if (override_architecture(name))		return -EFAULT;	if (override_release(name->release, sizeof(name->release)))		return -EFAULT;	return 0;}#endif SYSCALL_DEFINE2(sethostname, char __user *, name, int, len){	int errno;	char tmp[__NEW_UTS_LEN]; 	if (!ns_capable(current->nsproxy->uts_ns->user_ns, CAP_SYS_ADMIN))		return -EPERM; 	if (len < 0 || len > __NEW_UTS_LEN)		return -EINVAL;	errno = -EFAULT;	if (!copy_from_user(tmp, name, len)) {		struct new_utsname *u; 		add_device_randomness(tmp, len);		down_write(&uts_sem);		u = utsname();		memcpy(u->nodename, tmp, len);		memset(u->nodename + len, 0, sizeof(u->nodename) - len);		errno = 0;		uts_proc_notify(UTS_PROC_HOSTNAME);		up_write(&uts_sem);	}	return errno;} #ifdef __ARCH_WANT_SYS_GETHOSTNAME SYSCALL_DEFINE2(gethostname, char __user *, name, int, len){	int i;	struct new_utsname *u;	char tmp[__NEW_UTS_LEN + 1]; 	if (len < 0)		return -EINVAL;	down_read(&uts_sem);	u = utsname();	i = 1 + strlen(u->nodename);	if (i > len)		i = len;	memcpy(tmp, u->nodename, i);	up_read(&uts_sem);	if (copy_to_user(name, tmp, i))		return -EFAULT;	return 0;} #endif /* * Only setdomainname; getdomainname can be implemented by calling * uname() */SYSCALL_DEFINE2(setdomainname, char __user *, name, int, len){	int errno;	char tmp[__NEW_UTS_LEN]; 	if (!ns_capable(current->nsproxy->uts_ns->user_ns, CAP_SYS_ADMIN))		return -EPERM;	if (len < 0 || len > __NEW_UTS_LEN)		return -EINVAL; 	errno = -EFAULT;	if (!copy_from_user(tmp, name, len)) {		struct new_utsname *u; 		add_device_randomness(tmp, len);		down_write(&uts_sem);		u = utsname();		memcpy(u->domainname, tmp, len);		memset(u->domainname + len, 0, sizeof(u->domainname) - len);		errno = 0;		uts_proc_notify(UTS_PROC_DOMAINNAME);		up_write(&uts_sem);	}	return errno;} /* make sure you are allowed to change @tsk limits before calling this */static int do_prlimit(struct task_struct *tsk, unsigned int resource,

Lines 1001–1500 of 3074. 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