sys.c 62 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0
Linus Torvalds's avatar
Linus Torvalds committed
2 3 4 5 6 7
/*
 *  linux/kernel/sys.c
 *
 *  Copyright (C) 1991, 1992  Linus Torvalds
 */

8
#include <linux/export.h>
Linus Torvalds's avatar
Linus Torvalds committed
9 10 11 12 13 14 15
#include <linux/mm.h>
#include <linux/utsname.h>
#include <linux/mman.h>
#include <linux/reboot.h>
#include <linux/prctl.h>
#include <linux/highuid.h>
#include <linux/fs.h>
16
#include <linux/kmod.h>
17
#include <linux/perf_event.h>
18
#include <linux/resource.h>
19
#include <linux/kernel.h>
Linus Torvalds's avatar
Linus Torvalds committed
20
#include <linux/workqueue.h>
21
#include <linux/capability.h>
Linus Torvalds's avatar
Linus Torvalds committed
22 23 24 25 26 27 28 29
#include <linux/device.h>
#include <linux/key.h>
#include <linux/times.h>
#include <linux/posix-timers.h>
#include <linux/security.h>
#include <linux/dcookies.h>
#include <linux/suspend.h>
#include <linux/tty.h>
30
#include <linux/signal.h>
31
#include <linux/cn_proc.h>
32
#include <linux/getcpu.h>
33
#include <linux/task_io_accounting_ops.h>
34
#include <linux/seccomp.h>
Mark Lord's avatar
Mark Lord committed
35
#include <linux/cpu.h>
36
#include <linux/personality.h>
37
#include <linux/ptrace.h>
38
#include <linux/fs_struct.h>
39 40
#include <linux/file.h>
#include <linux/mount.h>
41
#include <linux/gfp.h>
42
#include <linux/syscore_ops.h>
43 44
#include <linux/version.h>
#include <linux/ctype.h>
Linus Torvalds's avatar
Linus Torvalds committed
45 46 47

#include <linux/compat.h>
#include <linux/syscalls.h>
48
#include <linux/kprobes.h>
49
#include <linux/user_namespace.h>
50
#include <linux/binfmts.h>
Linus Torvalds's avatar
Linus Torvalds committed
51

52
#include <linux/sched.h>
53
#include <linux/sched/autogroup.h>
54
#include <linux/sched/loadavg.h>
55
#include <linux/sched/stat.h>
56
#include <linux/sched/mm.h>
57
#include <linux/sched/coredump.h>
58
#include <linux/sched/task.h>
59
#include <linux/sched/cputime.h>
60 61 62 63
#include <linux/rcupdate.h>
#include <linux/uidgid.h>
#include <linux/cred.h>

64 65
#include <linux/nospec.h>

66
#include <linux/kmsg_dump.h>
67 68
/* Move somewhere else to avoid recompiling? */
#include <generated/utsrelease.h>
69

70
#include <linux/uaccess.h>
Linus Torvalds's avatar
Linus Torvalds committed
71 72 73
#include <asm/io.h>
#include <asm/unistd.h>

74 75
#include "uid16.h"

Linus Torvalds's avatar
Linus Torvalds committed
76
#ifndef SET_UNALIGN_CTL
77
# define SET_UNALIGN_CTL(a, b)	(-EINVAL)
Linus Torvalds's avatar
Linus Torvalds committed
78 79
#endif
#ifndef GET_UNALIGN_CTL
80
# define GET_UNALIGN_CTL(a, b)	(-EINVAL)
Linus Torvalds's avatar
Linus Torvalds committed
81 82
#endif
#ifndef SET_FPEMU_CTL
83
# define SET_FPEMU_CTL(a, b)	(-EINVAL)
Linus Torvalds's avatar
Linus Torvalds committed
84 85
#endif
#ifndef GET_FPEMU_CTL
86
# define GET_FPEMU_CTL(a, b)	(-EINVAL)
Linus Torvalds's avatar
Linus Torvalds committed
87 88
#endif
#ifndef SET_FPEXC_CTL
89
# define SET_FPEXC_CTL(a, b)	(-EINVAL)
Linus Torvalds's avatar
Linus Torvalds committed
90 91
#endif
#ifndef GET_FPEXC_CTL
92
# define GET_FPEXC_CTL(a, b)	(-EINVAL)
Linus Torvalds's avatar
Linus Torvalds committed
93
#endif
94
#ifndef GET_ENDIAN
95
# define GET_ENDIAN(a, b)	(-EINVAL)
96 97
#endif
#ifndef SET_ENDIAN
98
# define SET_ENDIAN(a, b)	(-EINVAL)
99
#endif
100 101 102 103 104 105
#ifndef GET_TSC_CTL
# define GET_TSC_CTL(a)		(-EINVAL)
#endif
#ifndef SET_TSC_CTL
# define SET_TSC_CTL(a)		(-EINVAL)
#endif
106
#ifndef MPX_ENABLE_MANAGEMENT
107
# define MPX_ENABLE_MANAGEMENT()	(-EINVAL)
108 109
#endif
#ifndef MPX_DISABLE_MANAGEMENT
110
# define MPX_DISABLE_MANAGEMENT()	(-EINVAL)
111
#endif
112 113 114 115 116 117
#ifndef GET_FP_MODE
# define GET_FP_MODE(a)		(-EINVAL)
#endif
#ifndef SET_FP_MODE
# define SET_FP_MODE(a,b)	(-EINVAL)
#endif
118 119 120 121 122 123
#ifndef SVE_SET_VL
# define SVE_SET_VL(a)		(-EINVAL)
#endif
#ifndef SVE_GET_VL
# define SVE_GET_VL()		(-EINVAL)
#endif
124 125 126
#ifndef PAC_RESET_KEYS
# define PAC_RESET_KEYS(a, b)	(-EINVAL)
#endif
Linus Torvalds's avatar
Linus Torvalds committed
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144

/*
 * this is where the system-wide overflow UID and GID are defined, for
 * architectures that now have 32-bit UID/GID but didn't in the past
 */

int overflowuid = DEFAULT_OVERFLOWUID;
int overflowgid = DEFAULT_OVERFLOWGID;

EXPORT_SYMBOL(overflowuid);
EXPORT_SYMBOL(overflowgid);

/*
 * the same as above, but for filesystems which can only store a 16-bit
 * UID and GID. as such, this is needed on all architectures
 */

int fs_overflowuid = DEFAULT_FS_OVERFLOWUID;
145
int fs_overflowgid = DEFAULT_FS_OVERFLOWGID;
Linus Torvalds's avatar
Linus Torvalds committed
146 147 148 149

EXPORT_SYMBOL(fs_overflowuid);
EXPORT_SYMBOL(fs_overflowgid);

150 151 152 153 154 155 156 157 158 159
/*
 * Returns true if current's euid is same as p's uid or euid,
 * or has CAP_SYS_NICE to p's user_ns.
 *
 * Called with rcu_read_lock, creds are safe
 */
static bool set_one_prio_perm(struct task_struct *p)
{
	const struct cred *cred = current_cred(), *pcred = __task_cred(p);

160 161
	if (uid_eq(pcred->uid,  cred->euid) ||
	    uid_eq(pcred->euid, cred->euid))
162
		return true;
163
	if (ns_capable(pcred->user_ns, CAP_SYS_NICE))
164 165 166 167
		return true;
	return false;
}

168 169 170 171
/*
 * set the priority of a task
 * - the caller must hold the RCU read lock
 */
Linus Torvalds's avatar
Linus Torvalds committed
172 173 174 175
static int set_one_prio(struct task_struct *p, int niceval, int error)
{
	int no_nice;

176
	if (!set_one_prio_perm(p)) {
Linus Torvalds's avatar
Linus Torvalds committed
177 178 179
		error = -EPERM;
		goto out;
	}
180
	if (niceval < task_nice(p) && !can_nice(p, niceval)) {
Linus Torvalds's avatar
Linus Torvalds committed
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
		error = -EACCES;
		goto out;
	}
	no_nice = security_task_setnice(p, niceval);
	if (no_nice) {
		error = no_nice;
		goto out;
	}
	if (error == -ESRCH)
		error = 0;
	set_user_nice(p, niceval);
out:
	return error;
}

196
SYSCALL_DEFINE3(setpriority, int, which, int, who, int, niceval)
Linus Torvalds's avatar
Linus Torvalds committed
197 198 199
{
	struct task_struct *g, *p;
	struct user_struct *user;
200
	const struct cred *cred = current_cred();
Linus Torvalds's avatar
Linus Torvalds committed
201
	int error = -EINVAL;
202
	struct pid *pgrp;
203
	kuid_t uid;
Linus Torvalds's avatar
Linus Torvalds committed
204

205
	if (which > PRIO_USER || which < PRIO_PROCESS)
Linus Torvalds's avatar
Linus Torvalds committed
206 207 208 209
		goto out;

	/* normalize: avoid signed division (rounding problems) */
	error = -ESRCH;
210 211 212 213
	if (niceval < MIN_NICE)
		niceval = MIN_NICE;
	if (niceval > MAX_NICE)
		niceval = MAX_NICE;
Linus Torvalds's avatar
Linus Torvalds committed
214

215
	rcu_read_lock();
Linus Torvalds's avatar
Linus Torvalds committed
216 217
	read_lock(&tasklist_lock);
	switch (which) {
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
	case PRIO_PROCESS:
		if (who)
			p = find_task_by_vpid(who);
		else
			p = current;
		if (p)
			error = set_one_prio(p, niceval, error);
		break;
	case PRIO_PGRP:
		if (who)
			pgrp = find_vpid(who);
		else
			pgrp = task_pgrp(current);
		do_each_pid_thread(pgrp, PIDTYPE_PGID, p) {
			error = set_one_prio(p, niceval, error);
		} while_each_pid_thread(pgrp, PIDTYPE_PGID, p);
		break;
	case PRIO_USER:
		uid = make_kuid(cred->user_ns, who);
		user = cred->user;
		if (!who)
			uid = cred->uid;
		else if (!uid_eq(uid, cred->uid)) {
			user = find_user(uid);
			if (!user)
243
				goto out_unlock;	/* No processes for this user */
244 245
		}
		do_each_thread(g, p) {
246
			if (uid_eq(task_uid(p), uid) && task_pid_vnr(p))
247 248 249 250 251
				error = set_one_prio(p, niceval, error);
		} while_each_thread(g, p);
		if (!uid_eq(uid, cred->uid))
			free_uid(user);		/* For find_user() */
		break;
Linus Torvalds's avatar
Linus Torvalds committed
252 253 254
	}
out_unlock:
	read_unlock(&tasklist_lock);
255
	rcu_read_unlock();
Linus Torvalds's avatar
Linus Torvalds committed
256 257 258 259 260 261 262 263 264 265
out:
	return error;
}

/*
 * Ugh. To avoid negative return values, "getpriority()" will
 * not return the normal nice-value, but a negated value that
 * has been offset by 20 (ie it returns 40..1 instead of -20..19)
 * to stay compatible.
 */
266
SYSCALL_DEFINE2(getpriority, int, which, int, who)
Linus Torvalds's avatar
Linus Torvalds committed
267 268 269
{
	struct task_struct *g, *p;
	struct user_struct *user;
270
	const struct cred *cred = current_cred();
Linus Torvalds's avatar
Linus Torvalds committed
271
	long niceval, retval = -ESRCH;
272
	struct pid *pgrp;
273
	kuid_t uid;
Linus Torvalds's avatar
Linus Torvalds committed
274

275
	if (which > PRIO_USER || which < PRIO_PROCESS)
Linus Torvalds's avatar
Linus Torvalds committed
276 277
		return -EINVAL;

278
	rcu_read_lock();
Linus Torvalds's avatar
Linus Torvalds committed
279 280
	read_lock(&tasklist_lock);
	switch (which) {
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313
	case PRIO_PROCESS:
		if (who)
			p = find_task_by_vpid(who);
		else
			p = current;
		if (p) {
			niceval = nice_to_rlimit(task_nice(p));
			if (niceval > retval)
				retval = niceval;
		}
		break;
	case PRIO_PGRP:
		if (who)
			pgrp = find_vpid(who);
		else
			pgrp = task_pgrp(current);
		do_each_pid_thread(pgrp, PIDTYPE_PGID, p) {
			niceval = nice_to_rlimit(task_nice(p));
			if (niceval > retval)
				retval = niceval;
		} while_each_pid_thread(pgrp, PIDTYPE_PGID, p);
		break;
	case PRIO_USER:
		uid = make_kuid(cred->user_ns, who);
		user = cred->user;
		if (!who)
			uid = cred->uid;
		else if (!uid_eq(uid, cred->uid)) {
			user = find_user(uid);
			if (!user)
				goto out_unlock;	/* No processes for this user */
		}
		do_each_thread(g, p) {
314
			if (uid_eq(task_uid(p), uid) && task_pid_vnr(p)) {
315
				niceval = nice_to_rlimit(task_nice(p));
Linus Torvalds's avatar
Linus Torvalds committed
316 317 318
				if (niceval > retval)
					retval = niceval;
			}
319 320 321 322
		} while_each_thread(g, p);
		if (!uid_eq(uid, cred->uid))
			free_uid(user);		/* for find_user() */
		break;
Linus Torvalds's avatar
Linus Torvalds committed
323 324 325
	}
out_unlock:
	read_unlock(&tasklist_lock);
326
	rcu_read_unlock();
Linus Torvalds's avatar
Linus Torvalds committed
327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343

	return retval;
}

/*
 * Unprivileged users may change the real gid to the effective gid
 * or vice versa.  (BSD-style)
 *
 * If you set the real gid at all, or set the effective gid to a value not
 * equal to the real gid, then the saved gid is set to the new effective gid.
 *
 * 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
344
 * 100% compatible with POSIX with saved IDs.
Linus Torvalds's avatar
Linus Torvalds committed
345 346 347 348
 *
 * SMP: There are not races, the GIDs are checked only by filesystem
 *      operations (as far as semantic preservation is concerned).
 */
349
#ifdef CONFIG_MULTIUSER
350
long __sys_setregid(gid_t rgid, gid_t egid)
Linus Torvalds's avatar
Linus Torvalds committed
351
{
352
	struct user_namespace *ns = current_user_ns();
353 354
	const struct cred *old;
	struct cred *new;
Linus Torvalds's avatar
Linus Torvalds committed
355
	int retval;
356 357 358 359 360 361 362 363 364
	kgid_t krgid, kegid;

	krgid = make_kgid(ns, rgid);
	kegid = make_kgid(ns, egid);

	if ((rgid != (gid_t) -1) && !gid_valid(krgid))
		return -EINVAL;
	if ((egid != (gid_t) -1) && !gid_valid(kegid))
		return -EINVAL;
Linus Torvalds's avatar
Linus Torvalds committed
365

366 367 368 369 370 371
	new = prepare_creds();
	if (!new)
		return -ENOMEM;
	old = current_cred();

	retval = -EPERM;
Linus Torvalds's avatar
Linus Torvalds committed
372
	if (rgid != (gid_t) -1) {
373 374
		if (gid_eq(old->gid, krgid) ||
		    gid_eq(old->egid, krgid) ||
375
		    ns_capable(old->user_ns, CAP_SETGID))
376
			new->gid = krgid;
Linus Torvalds's avatar
Linus Torvalds committed
377
		else
378
			goto error;
Linus Torvalds's avatar
Linus Torvalds committed
379 380
	}
	if (egid != (gid_t) -1) {
381 382 383
		if (gid_eq(old->gid, kegid) ||
		    gid_eq(old->egid, kegid) ||
		    gid_eq(old->sgid, kegid) ||
384
		    ns_capable(old->user_ns, CAP_SETGID))
385
			new->egid = kegid;
386
		else
387
			goto error;
Linus Torvalds's avatar
Linus Torvalds committed
388
	}
389

Linus Torvalds's avatar
Linus Torvalds committed
390
	if (rgid != (gid_t) -1 ||
391
	    (egid != (gid_t) -1 && !gid_eq(kegid, old->gid)))
392 393 394 395 396 397 398 399
		new->sgid = new->egid;
	new->fsgid = new->egid;

	return commit_creds(new);

error:
	abort_creds(new);
	return retval;
Linus Torvalds's avatar
Linus Torvalds committed
400 401
}

402 403 404 405 406
SYSCALL_DEFINE2(setregid, gid_t, rgid, gid_t, egid)
{
	return __sys_setregid(rgid, egid);
}

Linus Torvalds's avatar
Linus Torvalds committed
407
/*
408
 * setgid() is implemented like SysV w/ SAVED_IDS
Linus Torvalds's avatar
Linus Torvalds committed
409 410 411
 *
 * SMP: Same implicit races as above.
 */
412
long __sys_setgid(gid_t gid)
Linus Torvalds's avatar
Linus Torvalds committed
413
{
414
	struct user_namespace *ns = current_user_ns();
415 416
	const struct cred *old;
	struct cred *new;
Linus Torvalds's avatar
Linus Torvalds committed
417
	int retval;
418 419 420 421 422
	kgid_t kgid;

	kgid = make_kgid(ns, gid);
	if (!gid_valid(kgid))
		return -EINVAL;
Linus Torvalds's avatar
Linus Torvalds committed
423

424 425 426 427 428 429
	new = prepare_creds();
	if (!new)
		return -ENOMEM;
	old = current_cred();

	retval = -EPERM;
430
	if (ns_capable(old->user_ns, CAP_SETGID))
431 432 433
		new->gid = new->egid = new->sgid = new->fsgid = kgid;
	else if (gid_eq(kgid, old->gid) || gid_eq(kgid, old->sgid))
		new->egid = new->fsgid = kgid;
Linus Torvalds's avatar
Linus Torvalds committed
434
	else
435
		goto error;
Linus Torvalds's avatar
Linus Torvalds committed
436

437 438 439 440 441
	return commit_creds(new);

error:
	abort_creds(new);
	return retval;
Linus Torvalds's avatar
Linus Torvalds committed
442
}
443

444 445 446 447 448
SYSCALL_DEFINE1(setgid, gid_t, gid)
{
	return __sys_setgid(gid);
}

449 450 451 452
/*
 * change the user struct in a credentials set to match the new UID
 */
static int set_user(struct cred *new)
Linus Torvalds's avatar
Linus Torvalds committed
453 454 455
{
	struct user_struct *new_user;

456
	new_user = alloc_uid(new->uid);
Linus Torvalds's avatar
Linus Torvalds committed
457 458 459
	if (!new_user)
		return -EAGAIN;

460 461 462 463 464 465 466
	/*
	 * We don't fail in case of NPROC limit excess here because too many
	 * poorly written programs don't check set*uid() return code, assuming
	 * it never fails if called by root.  We may still enforce NPROC limit
	 * for programs doing set*uid()+execve() by harmlessly deferring the
	 * failure to the execve() stage.
	 */
467
	if (atomic_read(&new_user->processes) >= rlimit(RLIMIT_NPROC) &&
468 469 470 471
			new_user != INIT_USER)
		current->flags |= PF_NPROC_EXCEEDED;
	else
		current->flags &= ~PF_NPROC_EXCEEDED;
Linus Torvalds's avatar
Linus Torvalds committed
472

473 474
	free_uid(new->user);
	new->user = new_user;
Linus Torvalds's avatar
Linus Torvalds committed
475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490
	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
491
 * 100% compatible with POSIX with saved IDs.
Linus Torvalds's avatar
Linus Torvalds committed
492
 */
493
long __sys_setreuid(uid_t ruid, uid_t euid)
Linus Torvalds's avatar
Linus Torvalds committed
494
{
495
	struct user_namespace *ns = current_user_ns();
496 497
	const struct cred *old;
	struct cred *new;
Linus Torvalds's avatar
Linus Torvalds committed
498
	int retval;
499 500 501 502 503 504 505 506 507
	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;
Linus Torvalds's avatar
Linus Torvalds committed
508

509 510 511 512 513 514
	new = prepare_creds();
	if (!new)
		return -ENOMEM;
	old = current_cred();

	retval = -EPERM;
Linus Torvalds's avatar
Linus Torvalds committed
515
	if (ruid != (uid_t) -1) {
516 517 518
		new->uid = kruid;
		if (!uid_eq(old->uid, kruid) &&
		    !uid_eq(old->euid, kruid) &&
519
		    !ns_capable(old->user_ns, CAP_SETUID))
520
			goto error;
Linus Torvalds's avatar
Linus Torvalds committed
521 522 523
	}

	if (euid != (uid_t) -1) {
524 525 526 527
		new->euid = keuid;
		if (!uid_eq(old->uid, keuid) &&
		    !uid_eq(old->euid, keuid) &&
		    !uid_eq(old->suid, keuid) &&
528
		    !ns_capable(old->user_ns, CAP_SETUID))
529
			goto error;
Linus Torvalds's avatar
Linus Torvalds committed
530 531
	}

532
	if (!uid_eq(new->uid, old->uid)) {
533 534 535 536
		retval = set_user(new);
		if (retval < 0)
			goto error;
	}
Linus Torvalds's avatar
Linus Torvalds committed
537
	if (ruid != (uid_t) -1 ||
538
	    (euid != (uid_t) -1 && !uid_eq(keuid, old->uid)))
539 540
		new->suid = new->euid;
	new->fsuid = new->euid;
Linus Torvalds's avatar
Linus Torvalds committed
541

542 543 544
	retval = security_task_fix_setuid(new, old, LSM_SETID_RE);
	if (retval < 0)
		goto error;
Linus Torvalds's avatar
Linus Torvalds committed
545

546
	return commit_creds(new);
Linus Torvalds's avatar
Linus Torvalds committed
547

548 549 550 551
error:
	abort_creds(new);
	return retval;
}
552

553 554 555 556 557
SYSCALL_DEFINE2(setreuid, uid_t, ruid, uid_t, euid)
{
	return __sys_setreuid(ruid, euid);
}

Linus Torvalds's avatar
Linus Torvalds committed
558
/*
559 560
 * setuid() is implemented like SysV with SAVED_IDS
 *
Linus Torvalds's avatar
Linus Torvalds committed
561
 * Note that SAVED_ID's is deficient in that a setuid root program
562
 * like sendmail, for example, cannot set its uid to be a normal
Linus Torvalds's avatar
Linus Torvalds committed
563 564 565 566
 * 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
567
 * regain them by swapping the real and effective uid.
Linus Torvalds's avatar
Linus Torvalds committed
568
 */
569
long __sys_setuid(uid_t uid)
Linus Torvalds's avatar
Linus Torvalds committed
570
{
571
	struct user_namespace *ns = current_user_ns();
572 573
	const struct cred *old;
	struct cred *new;
Linus Torvalds's avatar
Linus Torvalds committed
574
	int retval;
575 576 577 578 579
	kuid_t kuid;

	kuid = make_kuid(ns, uid);
	if (!uid_valid(kuid))
		return -EINVAL;
Linus Torvalds's avatar
Linus Torvalds committed
580

581 582 583 584 585 586
	new = prepare_creds();
	if (!new)
		return -ENOMEM;
	old = current_cred();

	retval = -EPERM;
587
	if (ns_capable(old->user_ns, CAP_SETUID)) {
588 589
		new->suid = new->uid = kuid;
		if (!uid_eq(kuid, old->uid)) {
590 591 592
			retval = set_user(new);
			if (retval < 0)
				goto error;
593
		}
594
	} else if (!uid_eq(kuid, old->uid) && !uid_eq(kuid, new->suid)) {
595
		goto error;
Linus Torvalds's avatar
Linus Torvalds committed
596 597
	}

598
	new->fsuid = new->euid = kuid;
599 600 601 602

	retval = security_task_fix_setuid(new, old, LSM_SETID_ID);
	if (retval < 0)
		goto error;
Linus Torvalds's avatar
Linus Torvalds committed
603

604
	return commit_creds(new);
Linus Torvalds's avatar
Linus Torvalds committed
605

606 607 608
error:
	abort_creds(new);
	return retval;
Linus Torvalds's avatar
Linus Torvalds committed
609 610
}

611 612 613 614 615
SYSCALL_DEFINE1(setuid, uid_t, uid)
{
	return __sys_setuid(uid);
}

Linus Torvalds's avatar
Linus Torvalds committed
616 617 618 619 620

/*
 * This function implements a generic ability to update ruid, euid,
 * and suid.  This allows you to implement the 4.4 compatible seteuid().
 */
621
long __sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
Linus Torvalds's avatar
Linus Torvalds committed
622
{
623
	struct user_namespace *ns = current_user_ns();
624 625
	const struct cred *old;
	struct cred *new;
Linus Torvalds's avatar
Linus Torvalds committed
626
	int retval;
627 628 629 630 631 632 633 634 635 636 637 638 639 640
	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;
Linus Torvalds's avatar
Linus Torvalds committed
641

642 643 644 645 646
	new = prepare_creds();
	if (!new)
		return -ENOMEM;

	old = current_cred();
Linus Torvalds's avatar
Linus Torvalds committed
647

648
	retval = -EPERM;
649
	if (!ns_capable(old->user_ns, CAP_SETUID)) {
650 651
		if (ruid != (uid_t) -1        && !uid_eq(kruid, old->uid) &&
		    !uid_eq(kruid, old->euid) && !uid_eq(kruid, old->suid))
652
			goto error;
653 654
		if (euid != (uid_t) -1        && !uid_eq(keuid, old->uid) &&
		    !uid_eq(keuid, old->euid) && !uid_eq(keuid, old->suid))
655
			goto error;
656 657
		if (suid != (uid_t) -1        && !uid_eq(ksuid, old->uid) &&
		    !uid_eq(ksuid, old->euid) && !uid_eq(ksuid, old->suid))
658
			goto error;
Linus Torvalds's avatar
Linus Torvalds committed
659
	}
660

Linus Torvalds's avatar
Linus Torvalds committed
661
	if (ruid != (uid_t) -1) {
662 663
		new->uid = kruid;
		if (!uid_eq(kruid, old->uid)) {
664 665 666 667
			retval = set_user(new);
			if (retval < 0)
				goto error;
		}
Linus Torvalds's avatar
Linus Torvalds committed
668
	}
669
	if (euid != (uid_t) -1)
670
		new->euid = keuid;
Linus Torvalds's avatar
Linus Torvalds committed
671
	if (suid != (uid_t) -1)
672
		new->suid = ksuid;
673
	new->fsuid = new->euid;
Linus Torvalds's avatar
Linus Torvalds committed
674

675 676 677
	retval = security_task_fix_setuid(new, old, LSM_SETID_RES);
	if (retval < 0)
		goto error;
Linus Torvalds's avatar
Linus Torvalds committed
678

679
	return commit_creds(new);
Linus Torvalds's avatar
Linus Torvalds committed
680

681 682 683
error:
	abort_creds(new);
	return retval;
Linus Torvalds's avatar
Linus Torvalds committed
684 685
}

686 687 688 689 690
SYSCALL_DEFINE3(setresuid, uid_t, ruid, uid_t, euid, uid_t, suid)
{
	return __sys_setresuid(ruid, euid, suid);
}

691
SYSCALL_DEFINE3(getresuid, uid_t __user *, ruidp, uid_t __user *, euidp, uid_t __user *, suidp)
Linus Torvalds's avatar
Linus Torvalds committed
692
{
693
	const struct cred *cred = current_cred();
Linus Torvalds's avatar
Linus Torvalds committed
694
	int retval;
695 696 697 698 699
	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);
Linus Torvalds's avatar
Linus Torvalds committed
700

701 702 703 704 705 706
	retval = put_user(ruid, ruidp);
	if (!retval) {
		retval = put_user(euid, euidp);
		if (!retval)
			return put_user(suid, suidp);
	}
Linus Torvalds's avatar
Linus Torvalds committed
707 708 709 710 711 712
	return retval;
}

/*
 * Same as above, but for rgid, egid, sgid.
 */
713
long __sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
Linus Torvalds's avatar
Linus Torvalds committed
714
{
715
	struct user_namespace *ns = current_user_ns();
716 717
	const struct cred *old;
	struct cred *new;
Linus Torvalds's avatar
Linus Torvalds committed
718
	int retval;
719 720 721 722 723 724 725 726 727 728 729 730
	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;
Linus Torvalds's avatar
Linus Torvalds committed
731

732 733 734 735 736 737
	new = prepare_creds();
	if (!new)
		return -ENOMEM;
	old = current_cred();

	retval = -EPERM;
738
	if (!ns_capable(old->user_ns, CAP_SETGID)) {
739 740
		if (rgid != (gid_t) -1        && !gid_eq(krgid, old->gid) &&
		    !gid_eq(krgid, old->egid) && !gid_eq(krgid, old->sgid))
741
			goto error;
742 743
		if (egid != (gid_t) -1        && !gid_eq(kegid, old->gid) &&
		    !gid_eq(kegid, old->egid) && !gid_eq(kegid, old->sgid))
744
			goto error;
745 746
		if (sgid != (gid_t) -1        && !gid_eq(ksgid, old->gid) &&
		    !gid_eq(ksgid, old->egid) && !gid_eq(ksgid, old->sgid))
747
			goto error;
Linus Torvalds's avatar
Linus Torvalds committed
748
	}
749

Linus Torvalds's avatar
Linus Torvalds committed
750
	if (rgid != (gid_t) -1)
751
		new->gid = krgid;
752
	if (egid != (gid_t) -1)
753
		new->egid = kegid;
Linus Torvalds's avatar
Linus Torvalds committed
754
	if (sgid != (gid_t) -1)
755
		new->sgid = ksgid;
756
	new->fsgid = new->egid;
Linus Torvalds's avatar
Linus Torvalds committed
757

758 759 760 761 762
	return commit_creds(new);

error:
	abort_creds(new);
	return retval;
Linus Torvalds's avatar
Linus Torvalds committed
763 764
}

765 766 767 768 769
SYSCALL_DEFINE3(setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid)
{
	return __sys_setresgid(rgid, egid, sgid);
}

770
SYSCALL_DEFINE3(getresgid, gid_t __user *, rgidp, gid_t __user *, egidp, gid_t __user *, sgidp)
Linus Torvalds's avatar
Linus Torvalds committed
771
{
772
	const struct cred *cred = current_cred();
Linus Torvalds's avatar
Linus Torvalds committed
773
	int retval;
774 775 776 777 778
	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);
Linus Torvalds's avatar
Linus Torvalds committed
779

780 781 782 783 784 785
	retval = put_user(rgid, rgidp);
	if (!retval) {
		retval = put_user(egid, egidp);
		if (!retval)
			retval = put_user(sgid, sgidp);
	}
Linus Torvalds's avatar
Linus Torvalds committed
786 787 788 789 790 791 792 793 794 795 796

	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..
 */
797
long __sys_setfsuid(uid_t uid)
Linus Torvalds's avatar
Linus Torvalds committed
798
{
799 800 801
	const struct cred *old;
	struct cred *new;
	uid_t old_fsuid;
802 803 804 805 806 807 808 809
	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;
Linus Torvalds's avatar
Linus Torvalds committed
810

811 812
	new = prepare_creds();
	if (!new)
813
		return old_fsuid;
Linus Torvalds's avatar
Linus Torvalds committed
814

815 816
	if (uid_eq(kuid, old->uid)  || uid_eq(kuid, old->euid)  ||
	    uid_eq(kuid, old->suid) || uid_eq(kuid, old->fsuid) ||
817
	    ns_capable(old->user_ns, CAP_SETUID)) {
818 819
		if (!uid_eq(kuid, old->fsuid)) {
			new->fsuid = kuid;
820 821
			if (security_task_fix_setuid(new, old, LSM_SETID_FS) == 0)
				goto change_okay;
Linus Torvalds's avatar
Linus Torvalds committed
822 823 824
		}
	}

825 826
	abort_creds(new);
	return old_fsuid;
Linus Torvalds's avatar
Linus Torvalds committed
827

828 829
change_okay:
	commit_creds(new);
Linus Torvalds's avatar
Linus Torvalds committed
830 831 832
	return old_fsuid;
}

833 834 835 836 837
SYSCALL_DEFINE1(setfsuid, uid_t, uid)
{
	return __sys_setfsuid(uid);
}

Linus Torvalds's avatar
Linus Torvalds committed
838
/*
839
 * Samma på svenska..
Linus Torvalds's avatar
Linus Torvalds committed
840
 */
841
long __sys_setfsgid(gid_t gid)
Linus Torvalds's avatar
Linus Torvalds committed
842
{
843 844 845
	const struct cred *old;
	struct cred *new;
	gid_t old_fsgid;
846 847 848 849 850 851 852 853
	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;
854 855 856

	new = prepare_creds();
	if (!new)
857
		return old_fsgid;
Linus Torvalds's avatar
Linus Torvalds committed
858

859 860
	if (gid_eq(kgid, old->gid)  || gid_eq(kgid, old->egid)  ||
	    gid_eq(kgid, old->sgid) || gid_eq(kgid, old->fsgid) ||
861
	    ns_capable(old->user_ns, CAP_SETGID)) {
862 863
		if (!gid_eq(kgid, old->fsgid)) {
			new->fsgid = kgid;
864
			goto change_okay;
Linus Torvalds's avatar
Linus Torvalds committed
865 866
		}
	}
867 868 869 870 871 872

	abort_creds(new);
	return old_fsgid;

change_okay:
	commit_creds(new);
Linus Torvalds's avatar
Linus Torvalds committed
873 874
	return old_fsgid;
}
875 876 877 878 879

SYSCALL_DEFINE1(setfsgid, gid_t, gid)
{
	return __sys_setfsgid(gid);
}
880
#endif /* CONFIG_MULTIUSER */
Linus Torvalds's avatar
Linus Torvalds committed
881

882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942
/**
 * 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());
}

943
static void do_sys_times(struct tms *tms)
944
{
945
	u64 tgutime, tgstime, cutime, cstime;
946

947
	thread_group_cputime_adjusted(current, &tgutime, &tgstime);
948 949
	cutime = current->signal->cutime;
	cstime = current->signal->cstime;
950 951 952 953
	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);
954 955
}

956
SYSCALL_DEFINE1(times, struct tms __user *, tbuf)
Linus Torvalds's avatar
Linus Torvalds committed
957 958 959
{
	if (tbuf) {
		struct tms tmp;
960 961

		do_sys_times(&tmp);
Linus Torvalds's avatar
Linus Torvalds committed
962 963 964
		if (copy_to_user(tbuf, &tmp, sizeof(struct tms)))
			return -EFAULT;
	}
965
	force_successful_syscall_return();
Linus Torvalds's avatar
Linus Torvalds committed
966 967 968
	return (long) jiffies_64_to_clock_t(get_jiffies_64());
}

969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994
#ifdef CONFIG_COMPAT
static 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

Linus Torvalds's avatar
Linus Torvalds committed
995 996 997 998 999 1000 1001 1002 1003
/*
 * 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
 *
1004
 * !PF_FORKNOEXEC check to conform completely to POSIX.
Linus Torvalds's avatar
Linus Torvalds committed
1005
 */
1006
SYSCALL_DEFINE2(setpgid, pid_t, pid, pid_t, pgid)
Linus Torvalds's avatar
Linus Torvalds committed
1007 1008
{
	struct task_struct *p;
1009
	struct task_struct *group_leader = current->group_leader;
1010 1011
	struct pid *pgrp;
	int err;
Linus Torvalds's avatar
Linus Torvalds committed
1012 1013

	if (!pid)
1014
		pid = task_pid_vnr(group_leader);
Linus Torvalds's avatar
Linus Torvalds committed
1015 1016 1017 1018
	if (!pgid)
		pgid = pid;
	if (pgid < 0)
		return -EINVAL;
1019
	rcu_read_lock();
Linus Torvalds's avatar
Linus Torvalds committed
1020 1021 1022 1023 1024 1025 1026

	/* 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;
1027
	p = find_task_by_vpid(pid);
Linus Torvalds's avatar
Linus Torvalds committed
1028 1029 1030 1031 1032 1033 1034
	if (!p)
		goto out;

	err = -EINVAL;
	if (!thread_group_leader(p))
		goto out;

1035
	if (same_thread_group(p->real_parent, group_leader)) {
Linus Torvalds's avatar
Linus Torvalds committed
1036
		err = -EPERM;
1037
		if (task_session(p) != task_session(group_leader))
Linus Torvalds's avatar
Linus Torvalds committed
1038 1039
			goto out;
		err = -EACCES;
1040
		if (!(p->flags & PF_FORKNOEXEC))
Linus Torvalds's avatar
Linus Torvalds committed
1041 1042 1043
			goto out;
	} else {
		err = -ESRCH;
1044
		if (p != group_leader)
Linus Torvalds's avatar
Linus Torvalds committed
1045 1046 1047 1048 1049 1050 1051
			goto out;
	}

	err = -EPERM;
	if (p->signal->leader)
		goto out;

1052
	pgrp = task_pid(p);
Linus Torvalds's avatar
Linus Torvalds committed
1053
	if (pgid != pid) {
1054
		struct task_struct *g;
Linus Torvalds's avatar
Linus Torvalds committed
1055

1056 1057
		pgrp = find_vpid(pgid);
		g = pid_task(pgrp, PIDTYPE_PGID);
1058
		if (!g || task_session(g) != task_session(group_leader))
1059
			goto out;
Linus Torvalds's avatar
Linus Torvalds committed
1060 1061 1062 1063 1064 1065
	}

	err = security_task_setpgid(p, pgid);
	if (err)
		goto out;

1066
	if (task_pgrp(p) != pgrp)
1067
		change_pid(p, PIDTYPE_PGID, pgrp);
Linus Torvalds's avatar
Linus Torvalds committed
1068 1069 1070 1071 1072

	err = 0;
out:
	/* All paths lead to here, thus we are safe. -DaveM */
	write_unlock_irq(&tasklist_lock);
1073
	rcu_read_unlock();
Linus Torvalds's avatar
Linus Torvalds committed
1074 1075 1076
	return err;
}

1077
static int do_getpgid(pid_t pid)
Linus Torvalds's avatar
Linus Torvalds committed
1078
{
1079 1080 1081 1082 1083
	struct task_struct *p;
	struct pid *grp;
	int retval;

	rcu_read_lock();
1084
	if (!pid)
1085
		grp = task_pgrp(current);
1086
	else {
Linus Torvalds's avatar
Linus Torvalds committed
1087
		retval = -ESRCH;
1088 1089 1090 1091 1092 1093 1094 1095 1096 1097
		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;
Linus Torvalds's avatar
Linus Torvalds committed
1098
	}
1099 1100 1101 1102
	retval = pid_vnr(grp);
out:
	rcu_read_unlock();
	return retval;
Linus Torvalds's avatar
Linus Torvalds committed
1103 1104
}

1105 1106 1107 1108 1109
SYSCALL_DEFINE1(getpgid, pid_t, pid)
{
	return do_getpgid(pid);
}

Linus Torvalds's avatar
Linus Torvalds committed
1110 1111
#ifdef __ARCH_WANT_SYS_GETPGRP

1112
SYSCALL_DEFINE0(getpgrp)
Linus Torvalds's avatar
Linus Torvalds committed
1113
{
1114
	return do_getpgid(0);
Linus Torvalds's avatar
Linus Torvalds committed
1115 1116 1117 1118
}

#endif

1119
SYSCALL_DEFINE1(getsid, pid_t, pid)
Linus Torvalds's avatar
Linus Torvalds committed
1120
{
1121 1122 1123 1124 1125
	struct task_struct *p;
	struct pid *sid;
	int retval;

	rcu_read_lock();
1126
	if (!pid)
1127
		sid = task_session(current);
1128
	else {
Linus Torvalds's avatar
Linus Torvalds committed
1129
		retval = -ESRCH;
1130 1131 1132 1133 1134 1135 1136 1137 1138 1139
		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;
Linus Torvalds's avatar
Linus Torvalds committed
1140
	}
1141 1142 1143 1144
	retval = pid_vnr(sid);
out:
	rcu_read_unlock();
	return retval;
Linus Torvalds's avatar
Linus Torvalds committed
1145 1146
}

1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157
static void set_special_pids(struct pid *pid)
{
	struct task_struct *curr = current->group_leader;

	if (task_session(curr) != pid)
		change_pid(curr, PIDTYPE_SID, pid);

	if (task_pgrp(curr) != pid)
		change_pid(curr, PIDTYPE_PGID, pid);
}

1158
int ksys_setsid(void)
Linus Torvalds's avatar
Linus Torvalds committed
1159
{
1160
	struct task_struct *group_leader = current->group_leader;
1161 1162
	struct pid *sid = task_pid(group_leader);
	pid_t session = pid_vnr(sid);
Linus Torvalds's avatar
Linus Torvalds committed
1163 1164 1165
	int err = -EPERM;

	write_lock_irq(&tasklist_lock);
1166 1167 1168 1169
	/* Fail if I am already a session leader */
	if (group_leader->signal->leader)
		goto out;

1170 1171
	/* Fail if a process group id already exists that equals the
	 * proposed session id.
1172
	 */
1173
	if (pid_task(sid, PIDTYPE_PGID))
Linus Torvalds's avatar
Linus Torvalds committed
1174 1175
		goto out;

1176
	group_leader->signal->leader = 1;
1177
	set_special_pids(sid);
1178

Alan Cox's avatar
Alan Cox committed
1179
	proc_clear_tty(group_leader);
1180

1181
	err = session;
Linus Torvalds's avatar
Linus Torvalds committed
1182 1183
out:
	write_unlock_irq(&tasklist_lock);
1184
	if (err > 0) {
1185
		proc_sid_connector(group_leader);
1186 1187
		sched_autogroup_create_attach(group_leader);
	}
Linus Torvalds's avatar
Linus Torvalds committed
1188 1189 1190
	return err;
}

1191 1192 1193 1194 1195
SYSCALL_DEFINE0(setsid)
{
	return ksys_setsid();
}

Linus Torvalds's avatar
Linus Torvalds committed
1196 1197
DECLARE_RWSEM(uts_sem);

1198 1199
#ifdef COMPAT_UTS_MACHINE
#define override_architecture(name) \
1200
	(personality(current->personality) == PER_LINUX32 && \
1201 1202 1203 1204 1205 1206
	 copy_to_user(name->machine, COMPAT_UTS_MACHINE, \
		      sizeof(COMPAT_UTS_MACHINE)))
#else
#define override_architecture(name)	0
#endif

1207 1208 1209
/*
 * 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
1210 1211
 * 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.
1212
 */
1213
static int override_release(char __user *release, size_t len)
1214 1215 1216 1217
{
	int ret = 0;

	if (current->personality & UNAME26) {
1218 1219
		const char *rest = UTS_RELEASE;
		char buf[65] = { 0 };
1220 1221
		int ndots = 0;
		unsigned v;
1222
		size_t copy;
1223 1224 1225 1226 1227 1228 1229 1230

		while (*rest) {
			if (*rest == '.' && ++ndots >= 3)
				break;
			if (!isdigit(*rest) && *rest != '.')
				break;
			rest++;
		}
1231
		v = ((LINUX_VERSION_CODE >> 8) & 0xff) + 60;
Kees Cook's avatar
Kees Cook committed
1232
		copy = clamp_t(size_t, len, 1, sizeof(buf));
1233 1234
		copy = scnprintf(buf, copy, "2.6.%u%s", v, rest);
		ret = copy_to_user(release, buf, copy + 1);
1235 1236 1237 1238
	}
	return ret;
}

1239
SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name)
Linus Torvalds's avatar
Linus Torvalds committed
1240
{
1241
	struct new_utsname tmp;
Linus Torvalds's avatar
Linus Torvalds committed
1242 1243

	down_read(&uts_sem);
1244
	memcpy(&tmp, utsname(), sizeof(tmp));
Linus Torvalds's avatar
Linus Torvalds committed
1245
	up_read(&uts_sem);
1246 1247
	if (copy_to_user(name, &tmp, sizeof(tmp)))
		return -EFAULT;
1248

1249 1250 1251 1252 1253
	if (override_release(name->release, sizeof(name->release)))
		return -EFAULT;
	if (override_architecture(name))
		return -EFAULT;
	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
1254 1255
}

1256 1257 1258 1259 1260 1261
#ifdef __ARCH_WANT_SYS_OLD_UNAME
/*
 * Old cruft
 */
SYSCALL_DEFINE1(uname, struct old_utsname __user *, name)
{
1262
	struct old_utsname tmp;
1263 1264 1265 1266 1267

	if (!name)
		return -EFAULT;

	down_read(&uts_sem);
1268
	memcpy(&tmp, utsname(), sizeof(tmp));
1269
	up_read(&uts_sem);
1270 1271
	if (copy_to_user(name, &tmp, sizeof(tmp)))
		return -EFAULT;
1272

1273 1274 1275 1276 1277
	if (override_release(name->release, sizeof(name->release)))
		return -EFAULT;
	if (override_architecture(name))
		return -EFAULT;
	return 0;
1278 1279 1280 1281
}

SYSCALL_DEFINE1(olduname, struct oldold_utsname __user *, name)
{
1282
	struct oldold_utsname tmp = {};
1283 1284 1285 1286 1287

	if (!name)
		return -EFAULT;

	down_read(&uts_sem);
1288 1289 1290 1291 1292
	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);
1293
	up_read(&uts_sem);
1294 1295
	if (copy_to_user(name, &tmp, sizeof(tmp)))
		return -EFAULT;
1296

1297 1298 1299 1300 1301
	if (override_architecture(name))
		return -EFAULT;
	if (override_release(name->release, sizeof(name->release)))
		return -EFAULT;
	return 0;
1302 1303 1304
}
#endif

1305
SYSCALL_DEFINE2(sethostname, char __user *, name, int, len)
Linus Torvalds's avatar
Linus Torvalds committed
1306 1307 1308 1309
{
	int errno;
	char tmp[__NEW_UTS_LEN];

1310
	if (!ns_capable(current->nsproxy->uts_ns->user_ns, CAP_SYS_ADMIN))
Linus Torvalds's avatar
Linus Torvalds committed
1311
		return -EPERM;
1312

Linus Torvalds's avatar
Linus Torvalds committed
1313 1314 1315 1316
	if (len < 0 || len > __NEW_UTS_LEN)
		return -EINVAL;
	errno = -EFAULT;
	if (!copy_from_user(tmp, name, len)) {
1317
		struct new_utsname *u;
1318