Blame view

kernel/sys.c 41.9 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
  /*
   *  linux/kernel/sys.c
   *
   *  Copyright (C) 1991, 1992  Linus Torvalds
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6
7
8
9
  #include <linux/module.h>
  #include <linux/mm.h>
  #include <linux/utsname.h>
  #include <linux/mman.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
10
11
12
  #include <linux/notifier.h>
  #include <linux/reboot.h>
  #include <linux/prctl.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
13
14
  #include <linux/highuid.h>
  #include <linux/fs.h>
cdd6c482c   Ingo Molnar   perf: Do the big ...
15
  #include <linux/perf_event.h>
3e88c553d   Daniel Walker   use defines in sy...
16
  #include <linux/resource.h>
dc009d924   Eric W. Biederman   [PATCH] kexec: ad...
17
18
  #include <linux/kernel.h>
  #include <linux/kexec.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
  #include <linux/workqueue.h>
c59ede7b7   Randy.Dunlap   [PATCH] move capa...
20
  #include <linux/capability.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
21
22
23
24
25
26
27
28
  #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>
7ed20e1ad   Jesper Juhl   [PATCH] convert t...
29
  #include <linux/signal.h>
9f46080c4   Matt Helsley   [PATCH] Process E...
30
  #include <linux/cn_proc.h>
3cfc348bf   Andi Kleen   [PATCH] x86: Add ...
31
  #include <linux/getcpu.h>
6eaeeaba3   Eric Dumazet   getrusage(): fill...
32
  #include <linux/task_io_accounting_ops.h>
1d9d02fee   Andrea Arcangeli   move seccomp from...
33
  #include <linux/seccomp.h>
4047727e5   Mark Lord   Fix SMP poweroff ...
34
  #include <linux/cpu.h>
e28cbf229   Christoph Hellwig   improve sys_newun...
35
  #include <linux/personality.h>
e3d5a27d5   Paul Mackerras   Allow times and t...
36
  #include <linux/ptrace.h>
5ad4e53bd   Al Viro   Get rid of indire...
37
  #include <linux/fs_struct.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
38
  #include <linux/gfp.h>
40dc166cb   Rafael J. Wysocki   PM / Core: Introd...
39
  #include <linux/syscore_ops.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
41
42
  
  #include <linux/compat.h>
  #include <linux/syscalls.h>
00d7c05ab   Keshavamurthy Anil S   [PATCH] kprobes: ...
43
  #include <linux/kprobes.h>
acce292c8   Cedric Le Goater   user namespace: a...
44
  #include <linux/user_namespace.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45

04c6862c0   Seiji Aguchi   kmsg_dump: add km...
46
  #include <linux/kmsg_dump.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
  #include <asm/uaccess.h>
  #include <asm/io.h>
  #include <asm/unistd.h>
  
  #ifndef SET_UNALIGN_CTL
  # define SET_UNALIGN_CTL(a,b)	(-EINVAL)
  #endif
  #ifndef GET_UNALIGN_CTL
  # define GET_UNALIGN_CTL(a,b)	(-EINVAL)
  #endif
  #ifndef SET_FPEMU_CTL
  # define SET_FPEMU_CTL(a,b)	(-EINVAL)
  #endif
  #ifndef GET_FPEMU_CTL
  # define GET_FPEMU_CTL(a,b)	(-EINVAL)
  #endif
  #ifndef SET_FPEXC_CTL
  # define SET_FPEXC_CTL(a,b)	(-EINVAL)
  #endif
  #ifndef GET_FPEXC_CTL
  # define GET_FPEXC_CTL(a,b)	(-EINVAL)
  #endif
651d765d0   Anton Blanchard   [PATCH] Add a prc...
69
70
71
72
73
74
  #ifndef GET_ENDIAN
  # define GET_ENDIAN(a,b)	(-EINVAL)
  #endif
  #ifndef SET_ENDIAN
  # define SET_ENDIAN(a,b)	(-EINVAL)
  #endif
8fb402bcc   Erik Bosman   generic, x86: add...
75
76
77
78
79
80
  #ifndef GET_TSC_CTL
  # define GET_TSC_CTL(a)		(-EINVAL)
  #endif
  #ifndef SET_TSC_CTL
  # define SET_TSC_CTL(a)		(-EINVAL)
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
  
  /*
   * 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;
  
  #ifdef CONFIG_UID16
  EXPORT_SYMBOL(overflowuid);
  EXPORT_SYMBOL(overflowgid);
  #endif
  
  /*
   * 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;
  int fs_overflowgid = DEFAULT_FS_OVERFLOWUID;
  
  EXPORT_SYMBOL(fs_overflowuid);
  EXPORT_SYMBOL(fs_overflowgid);
  
  /*
   * this indicates whether you can reboot with ctrl-alt-del: the default is yes
   */
  
  int C_A_D = 1;
9ec52099e   Cedric Le Goater   [PATCH] replace c...
111
112
  struct pid *cad_pid;
  EXPORT_SYMBOL(cad_pid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
113
114
  
  /*
bd804eba1   Rafael J. Wysocki   PM: Introduce pm_...
115
116
117
118
   * If set, this is used for preparing the system to power off.
   */
  
  void (*pm_power_off_prepare)(void);
bd804eba1   Rafael J. Wysocki   PM: Introduce pm_...
119

c69e8d9c0   David Howells   CRED: Use RCU to ...
120
  /*
fc832ad36   Serge E. Hallyn   userns: user name...
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
   * 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);
  
  	if (pcred->user->user_ns == cred->user->user_ns &&
  	    (pcred->uid  == cred->euid ||
  	     pcred->euid == cred->euid))
  		return true;
  	if (ns_capable(pcred->user->user_ns, CAP_SYS_NICE))
  		return true;
  	return false;
  }
  
  /*
c69e8d9c0   David Howells   CRED: Use RCU to ...
140
141
142
   * set the priority of a task
   * - the caller must hold the RCU read lock
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143
144
145
  static int set_one_prio(struct task_struct *p, int niceval, int error)
  {
  	int no_nice;
fc832ad36   Serge E. Hallyn   userns: user name...
146
  	if (!set_one_prio_perm(p)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
147
148
149
  		error = -EPERM;
  		goto out;
  	}
e43379f10   Matt Mackall   [PATCH] nice and ...
150
  	if (niceval < task_nice(p) && !can_nice(p, niceval)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
151
152
153
154
155
156
157
158
159
160
161
162
163
164
  		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;
  }
754fe8d29   Heiko Carstens   [CVE-2009-0029] S...
165
  SYSCALL_DEFINE3(setpriority, int, which, int, who, int, niceval)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
166
167
168
  {
  	struct task_struct *g, *p;
  	struct user_struct *user;
86a264abe   David Howells   CRED: Wrap curren...
169
  	const struct cred *cred = current_cred();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
170
  	int error = -EINVAL;
41487c65b   Eric W. Biederman   [PATCH] pid: repl...
171
  	struct pid *pgrp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
172

3e88c553d   Daniel Walker   use defines in sy...
173
  	if (which > PRIO_USER || which < PRIO_PROCESS)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
174
175
176
177
178
179
180
181
  		goto out;
  
  	/* normalize: avoid signed division (rounding problems) */
  	error = -ESRCH;
  	if (niceval < -20)
  		niceval = -20;
  	if (niceval > 19)
  		niceval = 19;
d4581a239   Thomas Gleixner   sys: Fix missing ...
182
  	rcu_read_lock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
184
185
  	read_lock(&tasklist_lock);
  	switch (which) {
  		case PRIO_PROCESS:
41487c65b   Eric W. Biederman   [PATCH] pid: repl...
186
  			if (who)
228ebcbe6   Pavel Emelyanov   Uninline find_tas...
187
  				p = find_task_by_vpid(who);
41487c65b   Eric W. Biederman   [PATCH] pid: repl...
188
189
  			else
  				p = current;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
190
191
192
193
  			if (p)
  				error = set_one_prio(p, niceval, error);
  			break;
  		case PRIO_PGRP:
41487c65b   Eric W. Biederman   [PATCH] pid: repl...
194
  			if (who)
b488893a3   Pavel Emelyanov   pid namespaces: c...
195
  				pgrp = find_vpid(who);
41487c65b   Eric W. Biederman   [PATCH] pid: repl...
196
197
  			else
  				pgrp = task_pgrp(current);
2d70b68d4   Ken Chen   fix setpriority(P...
198
  			do_each_pid_thread(pgrp, PIDTYPE_PGID, p) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199
  				error = set_one_prio(p, niceval, error);
2d70b68d4   Ken Chen   fix setpriority(P...
200
  			} while_each_pid_thread(pgrp, PIDTYPE_PGID, p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
201
202
  			break;
  		case PRIO_USER:
d84f4f992   David Howells   CRED: Inaugurate ...
203
  			user = (struct user_struct *) cred->user;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
204
  			if (!who)
86a264abe   David Howells   CRED: Wrap curren...
205
206
207
208
  				who = cred->uid;
  			else if ((who != cred->uid) &&
  				 !(user = find_user(who)))
  				goto out_unlock;	/* No processes for this user */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
209

dfc6a736d   H Hartley Sweeten   kernel/sys.c: fix...
210
  			do_each_thread(g, p) {
86a264abe   David Howells   CRED: Wrap curren...
211
  				if (__task_cred(p)->uid == who)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
212
  					error = set_one_prio(p, niceval, error);
dfc6a736d   H Hartley Sweeten   kernel/sys.c: fix...
213
  			} while_each_thread(g, p);
86a264abe   David Howells   CRED: Wrap curren...
214
  			if (who != cred->uid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
215
216
217
218
219
  				free_uid(user);		/* For find_user() */
  			break;
  	}
  out_unlock:
  	read_unlock(&tasklist_lock);
d4581a239   Thomas Gleixner   sys: Fix missing ...
220
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221
222
223
224
225
226
227
228
229
230
  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.
   */
754fe8d29   Heiko Carstens   [CVE-2009-0029] S...
231
  SYSCALL_DEFINE2(getpriority, int, which, int, who)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
232
233
234
  {
  	struct task_struct *g, *p;
  	struct user_struct *user;
86a264abe   David Howells   CRED: Wrap curren...
235
  	const struct cred *cred = current_cred();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
236
  	long niceval, retval = -ESRCH;
41487c65b   Eric W. Biederman   [PATCH] pid: repl...
237
  	struct pid *pgrp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238

3e88c553d   Daniel Walker   use defines in sy...
239
  	if (which > PRIO_USER || which < PRIO_PROCESS)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
240
  		return -EINVAL;
701188374   Tetsuo Handa   kernel/sys.c: fix...
241
  	rcu_read_lock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
242
243
244
  	read_lock(&tasklist_lock);
  	switch (which) {
  		case PRIO_PROCESS:
41487c65b   Eric W. Biederman   [PATCH] pid: repl...
245
  			if (who)
228ebcbe6   Pavel Emelyanov   Uninline find_tas...
246
  				p = find_task_by_vpid(who);
41487c65b   Eric W. Biederman   [PATCH] pid: repl...
247
248
  			else
  				p = current;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
249
250
251
252
253
254
255
  			if (p) {
  				niceval = 20 - task_nice(p);
  				if (niceval > retval)
  					retval = niceval;
  			}
  			break;
  		case PRIO_PGRP:
41487c65b   Eric W. Biederman   [PATCH] pid: repl...
256
  			if (who)
b488893a3   Pavel Emelyanov   pid namespaces: c...
257
  				pgrp = find_vpid(who);
41487c65b   Eric W. Biederman   [PATCH] pid: repl...
258
259
  			else
  				pgrp = task_pgrp(current);
2d70b68d4   Ken Chen   fix setpriority(P...
260
  			do_each_pid_thread(pgrp, PIDTYPE_PGID, p) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
261
262
263
  				niceval = 20 - task_nice(p);
  				if (niceval > retval)
  					retval = niceval;
2d70b68d4   Ken Chen   fix setpriority(P...
264
  			} while_each_pid_thread(pgrp, PIDTYPE_PGID, p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265
266
  			break;
  		case PRIO_USER:
86a264abe   David Howells   CRED: Wrap curren...
267
  			user = (struct user_struct *) cred->user;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
268
  			if (!who)
86a264abe   David Howells   CRED: Wrap curren...
269
270
271
272
  				who = cred->uid;
  			else if ((who != cred->uid) &&
  				 !(user = find_user(who)))
  				goto out_unlock;	/* No processes for this user */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
273

dfc6a736d   H Hartley Sweeten   kernel/sys.c: fix...
274
  			do_each_thread(g, p) {
86a264abe   David Howells   CRED: Wrap curren...
275
  				if (__task_cred(p)->uid == who) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
276
277
278
279
  					niceval = 20 - task_nice(p);
  					if (niceval > retval)
  						retval = niceval;
  				}
dfc6a736d   H Hartley Sweeten   kernel/sys.c: fix...
280
  			} while_each_thread(g, p);
86a264abe   David Howells   CRED: Wrap curren...
281
  			if (who != cred->uid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
282
283
284
285
286
  				free_uid(user);		/* for find_user() */
  			break;
  	}
  out_unlock:
  	read_unlock(&tasklist_lock);
701188374   Tetsuo Handa   kernel/sys.c: fix...
287
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
288
289
290
  
  	return retval;
  }
e4c94330e   Eric W. Biederman   [PATCH] reboot: c...
291
292
293
294
295
296
297
298
  /**
   *	emergency_restart - reboot the system
   *
   *	Without shutting down any hardware or taking any locks
   *	reboot the system.  This is called when we know we are in
   *	trouble so this is our best effort to reboot.  This is
   *	safe to call in interrupt context.
   */
7c9034735   Eric W. Biederman   [PATCH] Add emerg...
299
300
  void emergency_restart(void)
  {
04c6862c0   Seiji Aguchi   kmsg_dump: add km...
301
  	kmsg_dump(KMSG_DUMP_EMERG);
7c9034735   Eric W. Biederman   [PATCH] Add emerg...
302
303
304
  	machine_emergency_restart();
  }
  EXPORT_SYMBOL_GPL(emergency_restart);
ca195b7f6   Huang Ying   kexec jump: remov...
305
  void kernel_restart_prepare(char *cmd)
4a00ea1e1   Eric W. Biederman   [PATCH] Refactor ...
306
  {
e041c6834   Alan Stern   [PATCH] Notifier ...
307
  	blocking_notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd);
4a00ea1e1   Eric W. Biederman   [PATCH] Refactor ...
308
  	system_state = SYSTEM_RESTART;
b50fa7c80   Kay Sievers   reboot: disable u...
309
  	usermodehelper_disable();
4a00ea1e1   Eric W. Biederman   [PATCH] Refactor ...
310
  	device_shutdown();
40dc166cb   Rafael J. Wysocki   PM / Core: Introd...
311
  	syscore_shutdown();
e4c94330e   Eric W. Biederman   [PATCH] reboot: c...
312
  }
1e5d53314   Randy Dunlap   [PATCH] more kern...
313
314
315
316
  
  /**
   *	kernel_restart - reboot the system
   *	@cmd: pointer to buffer containing command to execute for restart
b8887e6e8   Randy Dunlap   [PATCH] kernel-do...
317
   *		or %NULL
1e5d53314   Randy Dunlap   [PATCH] more kern...
318
319
320
321
   *
   *	Shutdown everything and perform a clean reboot.
   *	This is not safe to call in interrupt context.
   */
e4c94330e   Eric W. Biederman   [PATCH] reboot: c...
322
323
324
  void kernel_restart(char *cmd)
  {
  	kernel_restart_prepare(cmd);
756184b7d   Cal Peake   [PATCH] CodingSty...
325
  	if (!cmd)
4a00ea1e1   Eric W. Biederman   [PATCH] Refactor ...
326
327
  		printk(KERN_EMERG "Restarting system.
  ");
756184b7d   Cal Peake   [PATCH] CodingSty...
328
  	else
4a00ea1e1   Eric W. Biederman   [PATCH] Refactor ...
329
330
  		printk(KERN_EMERG "Restarting system with command '%s'.
  ", cmd);
04c6862c0   Seiji Aguchi   kmsg_dump: add km...
331
  	kmsg_dump(KMSG_DUMP_RESTART);
4a00ea1e1   Eric W. Biederman   [PATCH] Refactor ...
332
333
334
  	machine_restart(cmd);
  }
  EXPORT_SYMBOL_GPL(kernel_restart);
4ef7229ff   Adrian Bunk   make kernel_shutd...
335
  static void kernel_shutdown_prepare(enum system_states state)
729b4d4ce   Alexey Starikovskiy   [ACPI] fix reboot...
336
  {
e041c6834   Alan Stern   [PATCH] Notifier ...
337
  	blocking_notifier_call_chain(&reboot_notifier_list,
729b4d4ce   Alexey Starikovskiy   [ACPI] fix reboot...
338
339
  		(state == SYSTEM_HALT)?SYS_HALT:SYS_POWER_OFF, NULL);
  	system_state = state;
b50fa7c80   Kay Sievers   reboot: disable u...
340
  	usermodehelper_disable();
729b4d4ce   Alexey Starikovskiy   [ACPI] fix reboot...
341
342
  	device_shutdown();
  }
e4c94330e   Eric W. Biederman   [PATCH] reboot: c...
343
344
345
346
347
  /**
   *	kernel_halt - halt the system
   *
   *	Shutdown everything and perform a clean system halt.
   */
e4c94330e   Eric W. Biederman   [PATCH] reboot: c...
348
349
  void kernel_halt(void)
  {
729b4d4ce   Alexey Starikovskiy   [ACPI] fix reboot...
350
  	kernel_shutdown_prepare(SYSTEM_HALT);
40dc166cb   Rafael J. Wysocki   PM / Core: Introd...
351
  	syscore_shutdown();
4a00ea1e1   Eric W. Biederman   [PATCH] Refactor ...
352
353
  	printk(KERN_EMERG "System halted.
  ");
04c6862c0   Seiji Aguchi   kmsg_dump: add km...
354
  	kmsg_dump(KMSG_DUMP_HALT);
4a00ea1e1   Eric W. Biederman   [PATCH] Refactor ...
355
356
  	machine_halt();
  }
729b4d4ce   Alexey Starikovskiy   [ACPI] fix reboot...
357

4a00ea1e1   Eric W. Biederman   [PATCH] Refactor ...
358
  EXPORT_SYMBOL_GPL(kernel_halt);
e4c94330e   Eric W. Biederman   [PATCH] reboot: c...
359
360
361
362
363
  /**
   *	kernel_power_off - power_off the system
   *
   *	Shutdown everything and perform a clean system power_off.
   */
e4c94330e   Eric W. Biederman   [PATCH] reboot: c...
364
365
  void kernel_power_off(void)
  {
729b4d4ce   Alexey Starikovskiy   [ACPI] fix reboot...
366
  	kernel_shutdown_prepare(SYSTEM_POWER_OFF);
bd804eba1   Rafael J. Wysocki   PM: Introduce pm_...
367
368
  	if (pm_power_off_prepare)
  		pm_power_off_prepare();
4047727e5   Mark Lord   Fix SMP poweroff ...
369
  	disable_nonboot_cpus();
40dc166cb   Rafael J. Wysocki   PM / Core: Introd...
370
  	syscore_shutdown();
4a00ea1e1   Eric W. Biederman   [PATCH] Refactor ...
371
372
  	printk(KERN_EMERG "Power down.
  ");
04c6862c0   Seiji Aguchi   kmsg_dump: add km...
373
  	kmsg_dump(KMSG_DUMP_POWEROFF);
4a00ea1e1   Eric W. Biederman   [PATCH] Refactor ...
374
375
376
  	machine_power_off();
  }
  EXPORT_SYMBOL_GPL(kernel_power_off);
6f15fa500   Thomas Gleixner   sys: Remove BKL f...
377
378
  
  static DEFINE_MUTEX(reboot_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
379
380
381
382
383
384
385
386
  /*
   * Reboot system call: for obvious reasons only root may call it,
   * and even root needs to set up some magic numbers in the registers
   * so that some mistake won't make this reboot the whole machine.
   * You can also set the meaning of the ctrl-alt-del-key here.
   *
   * reboot doesn't sync: do that yourself before calling this.
   */
754fe8d29   Heiko Carstens   [CVE-2009-0029] S...
387
388
  SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
  		void __user *, arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
389
390
  {
  	char buffer[256];
3d26dcf76   Andi Kleen   kernel/sys.c: cle...
391
  	int ret = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
392
393
394
395
396
397
398
399
400
401
402
403
  
  	/* We only trust the superuser with rebooting the system. */
  	if (!capable(CAP_SYS_BOOT))
  		return -EPERM;
  
  	/* For safety, we require "magic" arguments. */
  	if (magic1 != LINUX_REBOOT_MAGIC1 ||
  	    (magic2 != LINUX_REBOOT_MAGIC2 &&
  	                magic2 != LINUX_REBOOT_MAGIC2A &&
  			magic2 != LINUX_REBOOT_MAGIC2B &&
  	                magic2 != LINUX_REBOOT_MAGIC2C))
  		return -EINVAL;
5e38291d8   Eric W. Biederman   [PATCH] Don't att...
404
405
406
407
408
  	/* Instead of trying to make the power_off code look like
  	 * halt when pm_power_off is not set do it the easy way.
  	 */
  	if ((cmd == LINUX_REBOOT_CMD_POWER_OFF) && !pm_power_off)
  		cmd = LINUX_REBOOT_CMD_HALT;
6f15fa500   Thomas Gleixner   sys: Remove BKL f...
409
  	mutex_lock(&reboot_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
410
411
  	switch (cmd) {
  	case LINUX_REBOOT_CMD_RESTART:
4a00ea1e1   Eric W. Biederman   [PATCH] Refactor ...
412
  		kernel_restart(NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
413
414
415
416
417
418
419
420
421
422
423
  		break;
  
  	case LINUX_REBOOT_CMD_CAD_ON:
  		C_A_D = 1;
  		break;
  
  	case LINUX_REBOOT_CMD_CAD_OFF:
  		C_A_D = 0;
  		break;
  
  	case LINUX_REBOOT_CMD_HALT:
4a00ea1e1   Eric W. Biederman   [PATCH] Refactor ...
424
  		kernel_halt();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
425
  		do_exit(0);
3d26dcf76   Andi Kleen   kernel/sys.c: cle...
426
  		panic("cannot halt");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
427
428
  
  	case LINUX_REBOOT_CMD_POWER_OFF:
4a00ea1e1   Eric W. Biederman   [PATCH] Refactor ...
429
  		kernel_power_off();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
430
431
432
433
434
  		do_exit(0);
  		break;
  
  	case LINUX_REBOOT_CMD_RESTART2:
  		if (strncpy_from_user(&buffer[0], arg, sizeof(buffer) - 1) < 0) {
6f15fa500   Thomas Gleixner   sys: Remove BKL f...
435
436
  			ret = -EFAULT;
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
437
438
  		}
  		buffer[sizeof(buffer) - 1] = '\0';
4a00ea1e1   Eric W. Biederman   [PATCH] Refactor ...
439
  		kernel_restart(buffer);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
440
  		break;
3ab835213   Huang Ying   kexec jump
441
  #ifdef CONFIG_KEXEC
dc009d924   Eric W. Biederman   [PATCH] kexec: ad...
442
  	case LINUX_REBOOT_CMD_KEXEC:
3d26dcf76   Andi Kleen   kernel/sys.c: cle...
443
444
  		ret = kernel_kexec();
  		break;
3ab835213   Huang Ying   kexec jump
445
  #endif
4a00ea1e1   Eric W. Biederman   [PATCH] Refactor ...
446

b0cb1a19d   Rafael J. Wysocki   Replace CONFIG_SO...
447
  #ifdef CONFIG_HIBERNATION
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
448
  	case LINUX_REBOOT_CMD_SW_SUSPEND:
3d26dcf76   Andi Kleen   kernel/sys.c: cle...
449
450
  		ret = hibernate();
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
451
452
453
  #endif
  
  	default:
3d26dcf76   Andi Kleen   kernel/sys.c: cle...
454
455
  		ret = -EINVAL;
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
456
  	}
6f15fa500   Thomas Gleixner   sys: Remove BKL f...
457
  	mutex_unlock(&reboot_mutex);
3d26dcf76   Andi Kleen   kernel/sys.c: cle...
458
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
459
  }
65f27f384   David Howells   WorkStruct: Pass ...
460
  static void deferred_cad(struct work_struct *dummy)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
461
  {
abcd9e51f   Eric W. Biederman   [PATCH] Make ctrl...
462
  	kernel_restart(NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
463
464
465
466
467
468
469
470
471
  }
  
  /*
   * This function gets called by ctrl-alt-del - ie the keyboard interrupt.
   * As it's called within an interrupt, it may NOT sync: the only choice
   * is whether to reboot at once, or just ignore the ctrl-alt-del.
   */
  void ctrl_alt_del(void)
  {
65f27f384   David Howells   WorkStruct: Pass ...
472
  	static DECLARE_WORK(cad_work, deferred_cad);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
473
474
475
476
  
  	if (C_A_D)
  		schedule_work(&cad_work);
  	else
9ec52099e   Cedric Le Goater   [PATCH] replace c...
477
  		kill_cad_pid(SIGINT, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
478
479
  }
  	
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
  /*
   * 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
   * 100% compatible with POSIX with saved IDs. 
   *
   * SMP: There are not races, the GIDs are checked only by filesystem
   *      operations (as far as semantic preservation is concerned).
   */
ae1251ab7   Heiko Carstens   [CVE-2009-0029] S...
498
  SYSCALL_DEFINE2(setregid, gid_t, rgid, gid_t, egid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
499
  {
d84f4f992   David Howells   CRED: Inaugurate ...
500
501
  	const struct cred *old;
  	struct cred *new;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
502
  	int retval;
d84f4f992   David Howells   CRED: Inaugurate ...
503
504
505
506
  	new = prepare_creds();
  	if (!new)
  		return -ENOMEM;
  	old = current_cred();
d84f4f992   David Howells   CRED: Inaugurate ...
507
  	retval = -EPERM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
508
  	if (rgid != (gid_t) -1) {
d84f4f992   David Howells   CRED: Inaugurate ...
509
510
  		if (old->gid == rgid ||
  		    old->egid == rgid ||
fc832ad36   Serge E. Hallyn   userns: user name...
511
  		    nsown_capable(CAP_SETGID))
d84f4f992   David Howells   CRED: Inaugurate ...
512
  			new->gid = rgid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
513
  		else
d84f4f992   David Howells   CRED: Inaugurate ...
514
  			goto error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
515
516
  	}
  	if (egid != (gid_t) -1) {
d84f4f992   David Howells   CRED: Inaugurate ...
517
518
519
  		if (old->gid == egid ||
  		    old->egid == egid ||
  		    old->sgid == egid ||
fc832ad36   Serge E. Hallyn   userns: user name...
520
  		    nsown_capable(CAP_SETGID))
d84f4f992   David Howells   CRED: Inaugurate ...
521
  			new->egid = egid;
756184b7d   Cal Peake   [PATCH] CodingSty...
522
  		else
d84f4f992   David Howells   CRED: Inaugurate ...
523
  			goto error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
524
  	}
d84f4f992   David Howells   CRED: Inaugurate ...
525

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
526
  	if (rgid != (gid_t) -1 ||
d84f4f992   David Howells   CRED: Inaugurate ...
527
528
529
530
531
532
533
534
535
  	    (egid != (gid_t) -1 && egid != old->gid))
  		new->sgid = new->egid;
  	new->fsgid = new->egid;
  
  	return commit_creds(new);
  
  error:
  	abort_creds(new);
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
536
537
538
539
540
541
542
  }
  
  /*
   * setgid() is implemented like SysV w/ SAVED_IDS 
   *
   * SMP: Same implicit races as above.
   */
ae1251ab7   Heiko Carstens   [CVE-2009-0029] S...
543
  SYSCALL_DEFINE1(setgid, gid_t, gid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
544
  {
d84f4f992   David Howells   CRED: Inaugurate ...
545
546
  	const struct cred *old;
  	struct cred *new;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
547
  	int retval;
d84f4f992   David Howells   CRED: Inaugurate ...
548
549
550
551
  	new = prepare_creds();
  	if (!new)
  		return -ENOMEM;
  	old = current_cred();
d84f4f992   David Howells   CRED: Inaugurate ...
552
  	retval = -EPERM;
fc832ad36   Serge E. Hallyn   userns: user name...
553
  	if (nsown_capable(CAP_SETGID))
d84f4f992   David Howells   CRED: Inaugurate ...
554
555
556
  		new->gid = new->egid = new->sgid = new->fsgid = gid;
  	else if (gid == old->gid || gid == old->sgid)
  		new->egid = new->fsgid = gid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
557
  	else
d84f4f992   David Howells   CRED: Inaugurate ...
558
  		goto error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
559

d84f4f992   David Howells   CRED: Inaugurate ...
560
561
562
563
564
  	return commit_creds(new);
  
  error:
  	abort_creds(new);
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
565
  }
54e991242   Dhaval Giani   sched: don't allo...
566

d84f4f992   David Howells   CRED: Inaugurate ...
567
568
569
570
  /*
   * change the user struct in a credentials set to match the new UID
   */
  static int set_user(struct cred *new)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
571
572
  {
  	struct user_struct *new_user;
18b6e0414   Serge Hallyn   User namespaces: ...
573
  	new_user = alloc_uid(current_user_ns(), new->uid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
574
575
  	if (!new_user)
  		return -EAGAIN;
78d7d407b   Jiri Slaby   kernel core: use ...
576
  	if (atomic_read(&new_user->processes) >= rlimit(RLIMIT_NPROC) &&
18b6e0414   Serge Hallyn   User namespaces: ...
577
  			new_user != INIT_USER) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
578
579
580
  		free_uid(new_user);
  		return -EAGAIN;
  	}
d84f4f992   David Howells   CRED: Inaugurate ...
581
582
  	free_uid(new->user);
  	new->user = new_user;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
  	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. 
   */
ae1251ab7   Heiko Carstens   [CVE-2009-0029] S...
601
  SYSCALL_DEFINE2(setreuid, uid_t, ruid, uid_t, euid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
602
  {
d84f4f992   David Howells   CRED: Inaugurate ...
603
604
  	const struct cred *old;
  	struct cred *new;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
605
  	int retval;
d84f4f992   David Howells   CRED: Inaugurate ...
606
607
608
609
  	new = prepare_creds();
  	if (!new)
  		return -ENOMEM;
  	old = current_cred();
d84f4f992   David Howells   CRED: Inaugurate ...
610
  	retval = -EPERM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
611
  	if (ruid != (uid_t) -1) {
d84f4f992   David Howells   CRED: Inaugurate ...
612
613
614
  		new->uid = ruid;
  		if (old->uid != ruid &&
  		    old->euid != ruid &&
fc832ad36   Serge E. Hallyn   userns: user name...
615
  		    !nsown_capable(CAP_SETUID))
d84f4f992   David Howells   CRED: Inaugurate ...
616
  			goto error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
617
618
619
  	}
  
  	if (euid != (uid_t) -1) {
d84f4f992   David Howells   CRED: Inaugurate ...
620
621
622
623
  		new->euid = euid;
  		if (old->uid != euid &&
  		    old->euid != euid &&
  		    old->suid != euid &&
fc832ad36   Serge E. Hallyn   userns: user name...
624
  		    !nsown_capable(CAP_SETUID))
d84f4f992   David Howells   CRED: Inaugurate ...
625
  			goto error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
626
  	}
54e991242   Dhaval Giani   sched: don't allo...
627
628
629
630
631
  	if (new->uid != old->uid) {
  		retval = set_user(new);
  		if (retval < 0)
  			goto error;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
632
  	if (ruid != (uid_t) -1 ||
d84f4f992   David Howells   CRED: Inaugurate ...
633
634
635
  	    (euid != (uid_t) -1 && euid != old->uid))
  		new->suid = new->euid;
  	new->fsuid = new->euid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
636

d84f4f992   David Howells   CRED: Inaugurate ...
637
638
639
  	retval = security_task_fix_setuid(new, old, LSM_SETID_RE);
  	if (retval < 0)
  		goto error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
640

d84f4f992   David Howells   CRED: Inaugurate ...
641
  	return commit_creds(new);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
642

d84f4f992   David Howells   CRED: Inaugurate ...
643
644
645
646
  error:
  	abort_creds(new);
  	return retval;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
647
648
649
650
651
652
653
654
655
656
657
658
  		
  /*
   * 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.  
   */
ae1251ab7   Heiko Carstens   [CVE-2009-0029] S...
659
  SYSCALL_DEFINE1(setuid, uid_t, uid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
660
  {
d84f4f992   David Howells   CRED: Inaugurate ...
661
662
  	const struct cred *old;
  	struct cred *new;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
663
  	int retval;
d84f4f992   David Howells   CRED: Inaugurate ...
664
665
666
667
  	new = prepare_creds();
  	if (!new)
  		return -ENOMEM;
  	old = current_cred();
d84f4f992   David Howells   CRED: Inaugurate ...
668
  	retval = -EPERM;
fc832ad36   Serge E. Hallyn   userns: user name...
669
  	if (nsown_capable(CAP_SETUID)) {
d84f4f992   David Howells   CRED: Inaugurate ...
670
  		new->suid = new->uid = uid;
54e991242   Dhaval Giani   sched: don't allo...
671
672
673
674
  		if (uid != old->uid) {
  			retval = set_user(new);
  			if (retval < 0)
  				goto error;
d84f4f992   David Howells   CRED: Inaugurate ...
675
676
677
  		}
  	} else if (uid != old->uid && uid != new->suid) {
  		goto error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
678
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
679

d84f4f992   David Howells   CRED: Inaugurate ...
680
681
682
683
684
  	new->fsuid = new->euid = uid;
  
  	retval = security_task_fix_setuid(new, old, LSM_SETID_ID);
  	if (retval < 0)
  		goto error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
685

d84f4f992   David Howells   CRED: Inaugurate ...
686
  	return commit_creds(new);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
687

d84f4f992   David Howells   CRED: Inaugurate ...
688
689
690
  error:
  	abort_creds(new);
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
691
692
693
694
695
696
697
  }
  
  
  /*
   * This function implements a generic ability to update ruid, euid,
   * and suid.  This allows you to implement the 4.4 compatible seteuid().
   */
ae1251ab7   Heiko Carstens   [CVE-2009-0029] S...
698
  SYSCALL_DEFINE3(setresuid, uid_t, ruid, uid_t, euid, uid_t, suid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
699
  {
d84f4f992   David Howells   CRED: Inaugurate ...
700
701
  	const struct cred *old;
  	struct cred *new;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
702
  	int retval;
d84f4f992   David Howells   CRED: Inaugurate ...
703
704
705
  	new = prepare_creds();
  	if (!new)
  		return -ENOMEM;
d84f4f992   David Howells   CRED: Inaugurate ...
706
  	old = current_cred();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
707

d84f4f992   David Howells   CRED: Inaugurate ...
708
  	retval = -EPERM;
fc832ad36   Serge E. Hallyn   userns: user name...
709
  	if (!nsown_capable(CAP_SETUID)) {
d84f4f992   David Howells   CRED: Inaugurate ...
710
711
712
713
714
715
716
717
718
  		if (ruid != (uid_t) -1 && ruid != old->uid &&
  		    ruid != old->euid  && ruid != old->suid)
  			goto error;
  		if (euid != (uid_t) -1 && euid != old->uid &&
  		    euid != old->euid  && euid != old->suid)
  			goto error;
  		if (suid != (uid_t) -1 && suid != old->uid &&
  		    suid != old->euid  && suid != old->suid)
  			goto error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
719
  	}
d84f4f992   David Howells   CRED: Inaugurate ...
720

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
721
  	if (ruid != (uid_t) -1) {
d84f4f992   David Howells   CRED: Inaugurate ...
722
  		new->uid = ruid;
54e991242   Dhaval Giani   sched: don't allo...
723
724
725
726
727
  		if (ruid != old->uid) {
  			retval = set_user(new);
  			if (retval < 0)
  				goto error;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
728
  	}
d84f4f992   David Howells   CRED: Inaugurate ...
729
730
  	if (euid != (uid_t) -1)
  		new->euid = euid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
731
  	if (suid != (uid_t) -1)
d84f4f992   David Howells   CRED: Inaugurate ...
732
733
  		new->suid = suid;
  	new->fsuid = new->euid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
734

d84f4f992   David Howells   CRED: Inaugurate ...
735
736
737
  	retval = security_task_fix_setuid(new, old, LSM_SETID_RES);
  	if (retval < 0)
  		goto error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
738

d84f4f992   David Howells   CRED: Inaugurate ...
739
  	return commit_creds(new);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
740

d84f4f992   David Howells   CRED: Inaugurate ...
741
742
743
  error:
  	abort_creds(new);
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
744
  }
dbf040d9d   Heiko Carstens   [CVE-2009-0029] S...
745
  SYSCALL_DEFINE3(getresuid, uid_t __user *, ruid, uid_t __user *, euid, uid_t __user *, suid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
746
  {
86a264abe   David Howells   CRED: Wrap curren...
747
  	const struct cred *cred = current_cred();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
748
  	int retval;
86a264abe   David Howells   CRED: Wrap curren...
749
750
  	if (!(retval   = put_user(cred->uid,  ruid)) &&
  	    !(retval   = put_user(cred->euid, euid)))
b6dff3ec5   David Howells   CRED: Separate ta...
751
  		retval = put_user(cred->suid, suid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
752
753
754
755
756
757
758
  
  	return retval;
  }
  
  /*
   * Same as above, but for rgid, egid, sgid.
   */
ae1251ab7   Heiko Carstens   [CVE-2009-0029] S...
759
  SYSCALL_DEFINE3(setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
760
  {
d84f4f992   David Howells   CRED: Inaugurate ...
761
762
  	const struct cred *old;
  	struct cred *new;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
763
  	int retval;
d84f4f992   David Howells   CRED: Inaugurate ...
764
765
766
767
  	new = prepare_creds();
  	if (!new)
  		return -ENOMEM;
  	old = current_cred();
d84f4f992   David Howells   CRED: Inaugurate ...
768
  	retval = -EPERM;
fc832ad36   Serge E. Hallyn   userns: user name...
769
  	if (!nsown_capable(CAP_SETGID)) {
d84f4f992   David Howells   CRED: Inaugurate ...
770
771
772
773
774
775
776
777
778
  		if (rgid != (gid_t) -1 && rgid != old->gid &&
  		    rgid != old->egid  && rgid != old->sgid)
  			goto error;
  		if (egid != (gid_t) -1 && egid != old->gid &&
  		    egid != old->egid  && egid != old->sgid)
  			goto error;
  		if (sgid != (gid_t) -1 && sgid != old->gid &&
  		    sgid != old->egid  && sgid != old->sgid)
  			goto error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
779
  	}
d84f4f992   David Howells   CRED: Inaugurate ...
780

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
781
  	if (rgid != (gid_t) -1)
d84f4f992   David Howells   CRED: Inaugurate ...
782
783
784
  		new->gid = rgid;
  	if (egid != (gid_t) -1)
  		new->egid = egid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
785
  	if (sgid != (gid_t) -1)
d84f4f992   David Howells   CRED: Inaugurate ...
786
787
  		new->sgid = sgid;
  	new->fsgid = new->egid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
788

d84f4f992   David Howells   CRED: Inaugurate ...
789
790
791
792
793
  	return commit_creds(new);
  
  error:
  	abort_creds(new);
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
794
  }
dbf040d9d   Heiko Carstens   [CVE-2009-0029] S...
795
  SYSCALL_DEFINE3(getresgid, gid_t __user *, rgid, gid_t __user *, egid, gid_t __user *, sgid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
796
  {
86a264abe   David Howells   CRED: Wrap curren...
797
  	const struct cred *cred = current_cred();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
798
  	int retval;
86a264abe   David Howells   CRED: Wrap curren...
799
800
  	if (!(retval   = put_user(cred->gid,  rgid)) &&
  	    !(retval   = put_user(cred->egid, egid)))
b6dff3ec5   David Howells   CRED: Separate ta...
801
  		retval = put_user(cred->sgid, sgid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
802
803
804
805
806
807
808
809
810
811
812
  
  	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..
   */
ae1251ab7   Heiko Carstens   [CVE-2009-0029] S...
813
  SYSCALL_DEFINE1(setfsuid, uid_t, uid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
814
  {
d84f4f992   David Howells   CRED: Inaugurate ...
815
816
817
  	const struct cred *old;
  	struct cred *new;
  	uid_t old_fsuid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
818

d84f4f992   David Howells   CRED: Inaugurate ...
819
820
821
822
823
  	new = prepare_creds();
  	if (!new)
  		return current_fsuid();
  	old = current_cred();
  	old_fsuid = old->fsuid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
824

d84f4f992   David Howells   CRED: Inaugurate ...
825
826
  	if (uid == old->uid  || uid == old->euid  ||
  	    uid == old->suid || uid == old->fsuid ||
fc832ad36   Serge E. Hallyn   userns: user name...
827
  	    nsown_capable(CAP_SETUID)) {
756184b7d   Cal Peake   [PATCH] CodingSty...
828
  		if (uid != old_fsuid) {
d84f4f992   David Howells   CRED: Inaugurate ...
829
830
831
  			new->fsuid = uid;
  			if (security_task_fix_setuid(new, old, LSM_SETID_FS) == 0)
  				goto change_okay;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
832
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
833
  	}
d84f4f992   David Howells   CRED: Inaugurate ...
834
835
  	abort_creds(new);
  	return old_fsuid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
836

d84f4f992   David Howells   CRED: Inaugurate ...
837
838
  change_okay:
  	commit_creds(new);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
839
840
841
842
  	return old_fsuid;
  }
  
  /*
f42df9e65   John Anthony Kazos Jr   general: convert ...
843
   * Samma på svenska..
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
844
   */
ae1251ab7   Heiko Carstens   [CVE-2009-0029] S...
845
  SYSCALL_DEFINE1(setfsgid, gid_t, gid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
846
  {
d84f4f992   David Howells   CRED: Inaugurate ...
847
848
849
850
851
852
853
854
855
  	const struct cred *old;
  	struct cred *new;
  	gid_t old_fsgid;
  
  	new = prepare_creds();
  	if (!new)
  		return current_fsgid();
  	old = current_cred();
  	old_fsgid = old->fsgid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
856

d84f4f992   David Howells   CRED: Inaugurate ...
857
858
  	if (gid == old->gid  || gid == old->egid  ||
  	    gid == old->sgid || gid == old->fsgid ||
fc832ad36   Serge E. Hallyn   userns: user name...
859
  	    nsown_capable(CAP_SETGID)) {
756184b7d   Cal Peake   [PATCH] CodingSty...
860
  		if (gid != old_fsgid) {
d84f4f992   David Howells   CRED: Inaugurate ...
861
862
  			new->fsgid = gid;
  			goto change_okay;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
863
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
864
  	}
d84f4f992   David Howells   CRED: Inaugurate ...
865

d84f4f992   David Howells   CRED: Inaugurate ...
866
867
868
869
870
  	abort_creds(new);
  	return old_fsgid;
  
  change_okay:
  	commit_creds(new);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
871
872
  	return old_fsgid;
  }
f06febc96   Frank Mayhar   timers: fix itime...
873
874
  void do_sys_times(struct tms *tms)
  {
0cf55e1ec   Hidetoshi Seto   sched, cputime: I...
875
  	cputime_t tgutime, tgstime, cutime, cstime;
f06febc96   Frank Mayhar   timers: fix itime...
876

2b5fe6de5   Oleg Nesterov   thread_group_cput...
877
  	spin_lock_irq(&current->sighand->siglock);
0cf55e1ec   Hidetoshi Seto   sched, cputime: I...
878
  	thread_group_times(current, &tgutime, &tgstime);
f06febc96   Frank Mayhar   timers: fix itime...
879
880
881
  	cutime = current->signal->cutime;
  	cstime = current->signal->cstime;
  	spin_unlock_irq(&current->sighand->siglock);
0cf55e1ec   Hidetoshi Seto   sched, cputime: I...
882
883
  	tms->tms_utime = cputime_to_clock_t(tgutime);
  	tms->tms_stime = cputime_to_clock_t(tgstime);
f06febc96   Frank Mayhar   timers: fix itime...
884
885
886
  	tms->tms_cutime = cputime_to_clock_t(cutime);
  	tms->tms_cstime = cputime_to_clock_t(cstime);
  }
58fd3aa28   Heiko Carstens   [CVE-2009-0029] S...
887
  SYSCALL_DEFINE1(times, struct tms __user *, tbuf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
888
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
889
890
  	if (tbuf) {
  		struct tms tmp;
f06febc96   Frank Mayhar   timers: fix itime...
891
892
  
  		do_sys_times(&tmp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
893
894
895
  		if (copy_to_user(tbuf, &tmp, sizeof(struct tms)))
  			return -EFAULT;
  	}
e3d5a27d5   Paul Mackerras   Allow times and t...
896
  	force_successful_syscall_return();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
  	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
   */
b290ebe2c   Heiko Carstens   [CVE-2009-0029] S...
912
  SYSCALL_DEFINE2(setpgid, pid_t, pid, pid_t, pgid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
913
914
  {
  	struct task_struct *p;
ee0acf90d   Oleg Nesterov   [PATCH] setpgid: ...
915
  	struct task_struct *group_leader = current->group_leader;
4e021306c   Oleg Nesterov   sys_setpgid(): si...
916
917
  	struct pid *pgrp;
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
918
919
  
  	if (!pid)
b488893a3   Pavel Emelyanov   pid namespaces: c...
920
  		pid = task_pid_vnr(group_leader);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
921
922
923
924
  	if (!pgid)
  		pgid = pid;
  	if (pgid < 0)
  		return -EINVAL;
950eaaca6   Paul E. McKenney   pid: make setpgid...
925
  	rcu_read_lock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
926
927
928
929
930
931
932
  
  	/* 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;
4e021306c   Oleg Nesterov   sys_setpgid(): si...
933
  	p = find_task_by_vpid(pid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
934
935
936
937
938
939
  	if (!p)
  		goto out;
  
  	err = -EINVAL;
  	if (!thread_group_leader(p))
  		goto out;
4e021306c   Oleg Nesterov   sys_setpgid(): si...
940
  	if (same_thread_group(p->real_parent, group_leader)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
941
  		err = -EPERM;
41487c65b   Eric W. Biederman   [PATCH] pid: repl...
942
  		if (task_session(p) != task_session(group_leader))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
943
944
945
946
947
948
  			goto out;
  		err = -EACCES;
  		if (p->did_exec)
  			goto out;
  	} else {
  		err = -ESRCH;
ee0acf90d   Oleg Nesterov   [PATCH] setpgid: ...
949
  		if (p != group_leader)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
950
951
952
953
954
955
  			goto out;
  	}
  
  	err = -EPERM;
  	if (p->signal->leader)
  		goto out;
4e021306c   Oleg Nesterov   sys_setpgid(): si...
956
  	pgrp = task_pid(p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
957
  	if (pgid != pid) {
b488893a3   Pavel Emelyanov   pid namespaces: c...
958
  		struct task_struct *g;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
959

4e021306c   Oleg Nesterov   sys_setpgid(): si...
960
961
  		pgrp = find_vpid(pgid);
  		g = pid_task(pgrp, PIDTYPE_PGID);
41487c65b   Eric W. Biederman   [PATCH] pid: repl...
962
  		if (!g || task_session(g) != task_session(group_leader))
f020bc468   Oleg Nesterov   [PATCH] sys_setpg...
963
  			goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
964
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
965
966
967
  	err = security_task_setpgid(p, pgid);
  	if (err)
  		goto out;
1b0f7ffd0   Oleg Nesterov   pids: kill signal...
968
  	if (task_pgrp(p) != pgrp)
83beaf3c6   Oleg Nesterov   pids: sys_setpgid...
969
  		change_pid(p, PIDTYPE_PGID, pgrp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
970
971
972
973
974
  
  	err = 0;
  out:
  	/* All paths lead to here, thus we are safe. -DaveM */
  	write_unlock_irq(&tasklist_lock);
950eaaca6   Paul E. McKenney   pid: make setpgid...
975
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
976
977
  	return err;
  }
dbf040d9d   Heiko Carstens   [CVE-2009-0029] S...
978
  SYSCALL_DEFINE1(getpgid, pid_t, pid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
979
  {
12a3de0a9   Oleg Nesterov   pids: sys_getpgid...
980
981
982
983
984
  	struct task_struct *p;
  	struct pid *grp;
  	int retval;
  
  	rcu_read_lock();
756184b7d   Cal Peake   [PATCH] CodingSty...
985
  	if (!pid)
12a3de0a9   Oleg Nesterov   pids: sys_getpgid...
986
  		grp = task_pgrp(current);
756184b7d   Cal Peake   [PATCH] CodingSty...
987
  	else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
988
  		retval = -ESRCH;
12a3de0a9   Oleg Nesterov   pids: sys_getpgid...
989
990
991
992
993
994
995
996
997
998
  		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;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
999
  	}
12a3de0a9   Oleg Nesterov   pids: sys_getpgid...
1000
1001
1002
1003
  	retval = pid_vnr(grp);
  out:
  	rcu_read_unlock();
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1004
1005
1006
  }
  
  #ifdef __ARCH_WANT_SYS_GETPGRP
dbf040d9d   Heiko Carstens   [CVE-2009-0029] S...
1007
  SYSCALL_DEFINE0(getpgrp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1008
  {
12a3de0a9   Oleg Nesterov   pids: sys_getpgid...
1009
  	return sys_getpgid(0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1010
1011
1012
  }
  
  #endif
dbf040d9d   Heiko Carstens   [CVE-2009-0029] S...
1013
  SYSCALL_DEFINE1(getsid, pid_t, pid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1014
  {
1dd768c08   Oleg Nesterov   pids: sys_getsid:...
1015
1016
1017
1018
1019
  	struct task_struct *p;
  	struct pid *sid;
  	int retval;
  
  	rcu_read_lock();
756184b7d   Cal Peake   [PATCH] CodingSty...
1020
  	if (!pid)
1dd768c08   Oleg Nesterov   pids: sys_getsid:...
1021
  		sid = task_session(current);
756184b7d   Cal Peake   [PATCH] CodingSty...
1022
  	else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1023
  		retval = -ESRCH;
1dd768c08   Oleg Nesterov   pids: sys_getsid:...
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
  		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;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1034
  	}
1dd768c08   Oleg Nesterov   pids: sys_getsid:...
1035
1036
1037
1038
  	retval = pid_vnr(sid);
  out:
  	rcu_read_unlock();
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1039
  }
b290ebe2c   Heiko Carstens   [CVE-2009-0029] S...
1040
  SYSCALL_DEFINE0(setsid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1041
  {
e19f247a3   Oren Laadan   [PATCH] setpgid: ...
1042
  	struct task_struct *group_leader = current->group_leader;
e4cc0a9c8   Oleg Nesterov   fix setsid() for ...
1043
1044
  	struct pid *sid = task_pid(group_leader);
  	pid_t session = pid_vnr(sid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1045
  	int err = -EPERM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1046
  	write_lock_irq(&tasklist_lock);
390e2ff07   Eric W. Biederman   [PATCH] Make sets...
1047
1048
1049
  	/* Fail if I am already a session leader */
  	if (group_leader->signal->leader)
  		goto out;
430c62312   Oleg Nesterov   start the global ...
1050
1051
  	/* Fail if a process group id already exists that equals the
  	 * proposed session id.
390e2ff07   Eric W. Biederman   [PATCH] Make sets...
1052
  	 */
6806aac6d   Oleg Nesterov   sys_setsid: remov...
1053
  	if (pid_task(sid, PIDTYPE_PGID))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1054
  		goto out;
e19f247a3   Oren Laadan   [PATCH] setpgid: ...
1055
  	group_leader->signal->leader = 1;
8520d7c7f   Oleg Nesterov   teach set_special...
1056
  	__set_special_pids(sid);
24ec839c4   Peter Zijlstra   [PATCH] tty: ->si...
1057

9c9f4ded9   Alan Cox   tty: Add a kref c...
1058
  	proc_clear_tty(group_leader);
24ec839c4   Peter Zijlstra   [PATCH] tty: ->si...
1059

e4cc0a9c8   Oleg Nesterov   fix setsid() for ...
1060
  	err = session;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1061
1062
  out:
  	write_unlock_irq(&tasklist_lock);
5091faa44   Mike Galbraith   sched: Add 'autog...
1063
  	if (err > 0) {
0d0df599f   Christian Borntraeger   connector: fix re...
1064
  		proc_sid_connector(group_leader);
5091faa44   Mike Galbraith   sched: Add 'autog...
1065
1066
  		sched_autogroup_create_attach(group_leader);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1067
1068
  	return err;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1069
  DECLARE_RWSEM(uts_sem);
e28cbf229   Christoph Hellwig   improve sys_newun...
1070
1071
  #ifdef COMPAT_UTS_MACHINE
  #define override_architecture(name) \
46da27664   Andreas Schwab   kernel/sys.c: fix...
1072
  	(personality(current->personality) == PER_LINUX32 && \
e28cbf229   Christoph Hellwig   improve sys_newun...
1073
1074
1075
1076
1077
  	 copy_to_user(name->machine, COMPAT_UTS_MACHINE, \
  		      sizeof(COMPAT_UTS_MACHINE)))
  #else
  #define override_architecture(name)	0
  #endif
e48fbb699   Heiko Carstens   [CVE-2009-0029] S...
1078
  SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1079
1080
1081
1082
  {
  	int errno = 0;
  
  	down_read(&uts_sem);
e9ff3990f   Serge E. Hallyn   [PATCH] namespace...
1083
  	if (copy_to_user(name, utsname(), sizeof *name))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1084
1085
  		errno = -EFAULT;
  	up_read(&uts_sem);
e28cbf229   Christoph Hellwig   improve sys_newun...
1086
1087
1088
  
  	if (!errno && override_architecture(name))
  		errno = -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1089
1090
  	return errno;
  }
5cacdb4ad   Christoph Hellwig   Add generic sys_o...
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
  #ifdef __ARCH_WANT_SYS_OLD_UNAME
  /*
   * Old cruft
   */
  SYSCALL_DEFINE1(uname, struct old_utsname __user *, name)
  {
  	int error = 0;
  
  	if (!name)
  		return -EFAULT;
  
  	down_read(&uts_sem);
  	if (copy_to_user(name, utsname(), sizeof(*name)))
  		error = -EFAULT;
  	up_read(&uts_sem);
  
  	if (!error && override_architecture(name))
  		error = -EFAULT;
  	return error;
  }
  
  SYSCALL_DEFINE1(olduname, struct oldold_utsname __user *, name)
  {
  	int error;
  
  	if (!name)
  		return -EFAULT;
  	if (!access_ok(VERIFY_WRITE, name, sizeof(struct oldold_utsname)))
  		return -EFAULT;
  
  	down_read(&uts_sem);
  	error = __copy_to_user(&name->sysname, &utsname()->sysname,
  			       __OLD_UTS_LEN);
  	error |= __put_user(0, name->sysname + __OLD_UTS_LEN);
  	error |= __copy_to_user(&name->nodename, &utsname()->nodename,
  				__OLD_UTS_LEN);
  	error |= __put_user(0, name->nodename + __OLD_UTS_LEN);
  	error |= __copy_to_user(&name->release, &utsname()->release,
  				__OLD_UTS_LEN);
  	error |= __put_user(0, name->release + __OLD_UTS_LEN);
  	error |= __copy_to_user(&name->version, &utsname()->version,
  				__OLD_UTS_LEN);
  	error |= __put_user(0, name->version + __OLD_UTS_LEN);
  	error |= __copy_to_user(&name->machine, &utsname()->machine,
  				__OLD_UTS_LEN);
  	error |= __put_user(0, name->machine + __OLD_UTS_LEN);
  	up_read(&uts_sem);
  
  	if (!error && override_architecture(name))
  		error = -EFAULT;
  	return error ? -EFAULT : 0;
  }
  #endif
5a8a82b1d   Heiko Carstens   [CVE-2009-0029] S...
1144
  SYSCALL_DEFINE2(sethostname, char __user *, name, int, len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1145
1146
1147
  {
  	int errno;
  	char tmp[__NEW_UTS_LEN];
bb96a6f50   Serge E. Hallyn   userns: allow set...
1148
  	if (!ns_capable(current->nsproxy->uts_ns->user_ns, CAP_SYS_ADMIN))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1149
  		return -EPERM;
fc832ad36   Serge E. Hallyn   userns: user name...
1150

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1151
1152
1153
1154
1155
  	if (len < 0 || len > __NEW_UTS_LEN)
  		return -EINVAL;
  	down_write(&uts_sem);
  	errno = -EFAULT;
  	if (!copy_from_user(tmp, name, len)) {
9679e4dd6   Andrew Morton   kernel/sys.c: imp...
1156
1157
1158
1159
  		struct new_utsname *u = utsname();
  
  		memcpy(u->nodename, tmp, len);
  		memset(u->nodename + len, 0, sizeof(u->nodename) - len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1160
1161
1162
1163
1164
1165
1166
  		errno = 0;
  	}
  	up_write(&uts_sem);
  	return errno;
  }
  
  #ifdef __ARCH_WANT_SYS_GETHOSTNAME
5a8a82b1d   Heiko Carstens   [CVE-2009-0029] S...
1167
  SYSCALL_DEFINE2(gethostname, char __user *, name, int, len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1168
1169
  {
  	int i, errno;
9679e4dd6   Andrew Morton   kernel/sys.c: imp...
1170
  	struct new_utsname *u;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1171
1172
1173
1174
  
  	if (len < 0)
  		return -EINVAL;
  	down_read(&uts_sem);
9679e4dd6   Andrew Morton   kernel/sys.c: imp...
1175
1176
  	u = utsname();
  	i = 1 + strlen(u->nodename);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1177
1178
1179
  	if (i > len)
  		i = len;
  	errno = 0;
9679e4dd6   Andrew Morton   kernel/sys.c: imp...
1180
  	if (copy_to_user(name, u->nodename, i))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
  		errno = -EFAULT;
  	up_read(&uts_sem);
  	return errno;
  }
  
  #endif
  
  /*
   * Only setdomainname; getdomainname can be implemented by calling
   * uname()
   */
5a8a82b1d   Heiko Carstens   [CVE-2009-0029] S...
1192
  SYSCALL_DEFINE2(setdomainname, char __user *, name, int, len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1193
1194
1195
  {
  	int errno;
  	char tmp[__NEW_UTS_LEN];
fc832ad36   Serge E. Hallyn   userns: user name...
1196
  	if (!ns_capable(current->nsproxy->uts_ns->user_ns, CAP_SYS_ADMIN))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1197
1198
1199
1200
1201
1202
1203
  		return -EPERM;
  	if (len < 0 || len > __NEW_UTS_LEN)
  		return -EINVAL;
  
  	down_write(&uts_sem);
  	errno = -EFAULT;
  	if (!copy_from_user(tmp, name, len)) {
9679e4dd6   Andrew Morton   kernel/sys.c: imp...
1204
1205
1206
1207
  		struct new_utsname *u = utsname();
  
  		memcpy(u->domainname, tmp, len);
  		memset(u->domainname + len, 0, sizeof(u->domainname) - len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1208
1209
1210
1211
1212
  		errno = 0;
  	}
  	up_write(&uts_sem);
  	return errno;
  }
e48fbb699   Heiko Carstens   [CVE-2009-0029] S...
1213
  SYSCALL_DEFINE2(getrlimit, unsigned int, resource, struct rlimit __user *, rlim)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1214
  {
b95183453   Jiri Slaby   rlimits: switch m...
1215
1216
1217
1218
1219
1220
1221
1222
  	struct rlimit value;
  	int ret;
  
  	ret = do_prlimit(current, resource, NULL, &value);
  	if (!ret)
  		ret = copy_to_user(rlim, &value, sizeof(*rlim)) ? -EFAULT : 0;
  
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1223
1224
1225
1226
1227
1228
1229
1230
  }
  
  #ifdef __ARCH_WANT_SYS_OLD_GETRLIMIT
  
  /*
   *	Back compatibility for getrlimit. Needed for some apps.
   */
   
e48fbb699   Heiko Carstens   [CVE-2009-0029] S...
1231
1232
  SYSCALL_DEFINE2(old_getrlimit, unsigned int, resource,
  		struct rlimit __user *, rlim)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1233
1234
1235
1236
1237
1238
1239
1240
  {
  	struct rlimit x;
  	if (resource >= RLIM_NLIMITS)
  		return -EINVAL;
  
  	task_lock(current->group_leader);
  	x = current->signal->rlim[resource];
  	task_unlock(current->group_leader);
756184b7d   Cal Peake   [PATCH] CodingSty...
1241
  	if (x.rlim_cur > 0x7FFFFFFF)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1242
  		x.rlim_cur = 0x7FFFFFFF;
756184b7d   Cal Peake   [PATCH] CodingSty...
1243
  	if (x.rlim_max > 0x7FFFFFFF)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1244
1245
1246
1247
1248
  		x.rlim_max = 0x7FFFFFFF;
  	return copy_to_user(rlim, &x, sizeof(x))?-EFAULT:0;
  }
  
  #endif
c022a0aca   Jiri Slaby   rlimits: implemen...
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
  static inline bool rlim64_is_infinity(__u64 rlim64)
  {
  #if BITS_PER_LONG < 64
  	return rlim64 >= ULONG_MAX;
  #else
  	return rlim64 == RLIM64_INFINITY;
  #endif
  }
  
  static void rlim_to_rlim64(const struct rlimit *rlim, struct rlimit64 *rlim64)
  {
  	if (rlim->rlim_cur == RLIM_INFINITY)
  		rlim64->rlim_cur = RLIM64_INFINITY;
  	else
  		rlim64->rlim_cur = rlim->rlim_cur;
  	if (rlim->rlim_max == RLIM_INFINITY)
  		rlim64->rlim_max = RLIM64_INFINITY;
  	else
  		rlim64->rlim_max = rlim->rlim_max;
  }
  
  static void rlim64_to_rlim(const struct rlimit64 *rlim64, struct rlimit *rlim)
  {
  	if (rlim64_is_infinity(rlim64->rlim_cur))
  		rlim->rlim_cur = RLIM_INFINITY;
  	else
  		rlim->rlim_cur = (unsigned long)rlim64->rlim_cur;
  	if (rlim64_is_infinity(rlim64->rlim_max))
  		rlim->rlim_max = RLIM_INFINITY;
  	else
  		rlim->rlim_max = (unsigned long)rlim64->rlim_max;
  }
1c1e618dd   Jiri Slaby   rlimits: allow se...
1281
  /* make sure you are allowed to change @tsk limits before calling this */
5b41535aa   Jiri Slaby   rlimits: redo do_...
1282
1283
  int do_prlimit(struct task_struct *tsk, unsigned int resource,
  		struct rlimit *new_rlim, struct rlimit *old_rlim)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1284
  {
5b41535aa   Jiri Slaby   rlimits: redo do_...
1285
  	struct rlimit *rlim;
86f162f4c   Jiri Slaby   rlimits: do secur...
1286
  	int retval = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1287
1288
1289
  
  	if (resource >= RLIM_NLIMITS)
  		return -EINVAL;
5b41535aa   Jiri Slaby   rlimits: redo do_...
1290
1291
1292
1293
1294
1295
1296
  	if (new_rlim) {
  		if (new_rlim->rlim_cur > new_rlim->rlim_max)
  			return -EINVAL;
  		if (resource == RLIMIT_NOFILE &&
  				new_rlim->rlim_max > sysctl_nr_open)
  			return -EPERM;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1297

1c1e618dd   Jiri Slaby   rlimits: allow se...
1298
1299
1300
1301
1302
1303
  	/* protect tsk->signal and tsk->sighand from disappearing */
  	read_lock(&tasklist_lock);
  	if (!tsk->sighand) {
  		retval = -ESRCH;
  		goto out;
  	}
5b41535aa   Jiri Slaby   rlimits: redo do_...
1304
  	rlim = tsk->signal->rlim + resource;
86f162f4c   Jiri Slaby   rlimits: do secur...
1305
  	task_lock(tsk->group_leader);
5b41535aa   Jiri Slaby   rlimits: redo do_...
1306
  	if (new_rlim) {
fc832ad36   Serge E. Hallyn   userns: user name...
1307
1308
  		/* Keep the capable check against init_user_ns until
  		   cgroups can contain all limits */
5b41535aa   Jiri Slaby   rlimits: redo do_...
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
  		if (new_rlim->rlim_max > rlim->rlim_max &&
  				!capable(CAP_SYS_RESOURCE))
  			retval = -EPERM;
  		if (!retval)
  			retval = security_task_setrlimit(tsk->group_leader,
  					resource, new_rlim);
  		if (resource == RLIMIT_CPU && new_rlim->rlim_cur == 0) {
  			/*
  			 * The caller is asking for an immediate RLIMIT_CPU
  			 * expiry.  But we use the zero value to mean "it was
  			 * never set".  So let's cheat and make it one second
  			 * instead
  			 */
  			new_rlim->rlim_cur = 1;
  		}
  	}
  	if (!retval) {
  		if (old_rlim)
  			*old_rlim = *rlim;
  		if (new_rlim)
  			*rlim = *new_rlim;
9926e4c74   Tom Alsberg   CPU time limit pa...
1330
  	}
7855c35da   Jiri Slaby   rlimits: split sy...
1331
  	task_unlock(tsk->group_leader);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1332

d3561f78f   Andrew Morton   [PATCH] RLIMIT_CP...
1333
1334
1335
1336
1337
1338
  	/*
  	 * RLIMIT_CPU handling.   Note that the kernel fails to return an error
  	 * code if it rejected the user's attempt to set RLIMIT_CPU.  This is a
  	 * very long-standing error, and fixing it now risks breakage of
  	 * applications, so we live with it
  	 */
5b41535aa   Jiri Slaby   rlimits: redo do_...
1339
1340
1341
  	 if (!retval && new_rlim && resource == RLIMIT_CPU &&
  			 new_rlim->rlim_cur != RLIM_INFINITY)
  		update_rlimit_cpu(tsk, new_rlim->rlim_cur);
ec9e16bac   Andrew Morton   [PATCH] sys_setrl...
1342
  out:
1c1e618dd   Jiri Slaby   rlimits: allow se...
1343
  	read_unlock(&tasklist_lock);
2fb9d2689   Oleg Nesterov   rlimits: make sur...
1344
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1345
  }
c022a0aca   Jiri Slaby   rlimits: implemen...
1346
1347
1348
1349
  /* rcu lock must be held */
  static int check_prlimit_permission(struct task_struct *task)
  {
  	const struct cred *cred = current_cred(), *tcred;
fc832ad36   Serge E. Hallyn   userns: user name...
1350
1351
  	if (current == task)
  		return 0;
c022a0aca   Jiri Slaby   rlimits: implemen...
1352

fc832ad36   Serge E. Hallyn   userns: user name...
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
  	tcred = __task_cred(task);
  	if (cred->user->user_ns == tcred->user->user_ns &&
  	    (cred->uid == tcred->euid &&
  	     cred->uid == tcred->suid &&
  	     cred->uid == tcred->uid  &&
  	     cred->gid == tcred->egid &&
  	     cred->gid == tcred->sgid &&
  	     cred->gid == tcred->gid))
  		return 0;
  	if (ns_capable(tcred->user->user_ns, CAP_SYS_RESOURCE))
  		return 0;
  
  	return -EPERM;
c022a0aca   Jiri Slaby   rlimits: implemen...
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
  }
  
  SYSCALL_DEFINE4(prlimit64, pid_t, pid, unsigned int, resource,
  		const struct rlimit64 __user *, new_rlim,
  		struct rlimit64 __user *, old_rlim)
  {
  	struct rlimit64 old64, new64;
  	struct rlimit old, new;
  	struct task_struct *tsk;
  	int ret;
  
  	if (new_rlim) {
  		if (copy_from_user(&new64, new_rlim, sizeof(new64)))
  			return -EFAULT;
  		rlim64_to_rlim(&new64, &new);
  	}
  
  	rcu_read_lock();
  	tsk = pid ? find_task_by_vpid(pid) : current;
  	if (!tsk) {
  		rcu_read_unlock();
  		return -ESRCH;
  	}
  	ret = check_prlimit_permission(tsk);
  	if (ret) {
  		rcu_read_unlock();
  		return ret;
  	}
  	get_task_struct(tsk);
  	rcu_read_unlock();
  
  	ret = do_prlimit(tsk, resource, new_rlim ? &new : NULL,
  			old_rlim ? &old : NULL);
  
  	if (!ret && old_rlim) {
  		rlim_to_rlim64(&old, &old64);
  		if (copy_to_user(old_rlim, &old64, sizeof(old64)))
  			ret = -EFAULT;
  	}
  
  	put_task_struct(tsk);
  	return ret;
  }
7855c35da   Jiri Slaby   rlimits: split sy...
1409
1410
1411
1412
1413
1414
  SYSCALL_DEFINE2(setrlimit, unsigned int, resource, struct rlimit __user *, rlim)
  {
  	struct rlimit new_rlim;
  
  	if (copy_from_user(&new_rlim, rlim, sizeof(*rlim)))
  		return -EFAULT;
5b41535aa   Jiri Slaby   rlimits: redo do_...
1415
  	return do_prlimit(current, resource, &new_rlim, NULL);
7855c35da   Jiri Slaby   rlimits: split sy...
1416
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1417
1418
1419
1420
1421
1422
1423
1424
  /*
   * It would make sense to put struct rusage in the task_struct,
   * except that would make the task_struct be *really big*.  After
   * task_struct gets moved into malloc'ed memory, it would
   * make sense to do this.  It will make moving the rest of the information
   * a lot simpler!  (Which we're not doing right now because we're not
   * measuring them yet).
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1425
1426
1427
1428
1429
1430
1431
   * When sampling multiple threads for RUSAGE_SELF, under SMP we might have
   * races with threads incrementing their own counters.  But since word
   * reads are atomic, we either get new values or old values and we don't
   * care which for the sums.  We always take the siglock to protect reading
   * the c* fields from p->signal from races with exit.c updating those
   * fields when reaping, so a sample either gets all the additions of a
   * given child after it's reaped, or none so this sample is before reaping.
2dd0ebcd2   Ravikiran G Thirumalai   [PATCH] Avoid tak...
1432
   *
de047c1bc   Ravikiran G Thirumalai   [PATCH] avoid tas...
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
   * Locking:
   * We need to take the siglock for CHILDEREN, SELF and BOTH
   * for  the cases current multithreaded, non-current single threaded
   * non-current multithreaded.  Thread traversal is now safe with
   * the siglock held.
   * Strictly speaking, we donot need to take the siglock if we are current and
   * single threaded,  as no one else can take our signal_struct away, no one
   * else can  reap the  children to update signal->c* counters, and no one else
   * can race with the signal-> fields. If we do not take any lock, the
   * signal-> fields could be read out of order while another thread was just
   * exiting. So we should  place a read memory barrier when we avoid the lock.
   * On the writer side,  write memory barrier is implied in  __exit_signal
   * as __exit_signal releases  the siglock spinlock after updating the signal->
   * fields. But we don't do this yet to keep things simple.
2dd0ebcd2   Ravikiran G Thirumalai   [PATCH] Avoid tak...
1447
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1448
   */
f06febc96   Frank Mayhar   timers: fix itime...
1449
  static void accumulate_thread_rusage(struct task_struct *t, struct rusage *r)
679c9cd4a   Sripathi Kodi   add RUSAGE_THREAD
1450
  {
679c9cd4a   Sripathi Kodi   add RUSAGE_THREAD
1451
1452
1453
1454
1455
1456
1457
  	r->ru_nvcsw += t->nvcsw;
  	r->ru_nivcsw += t->nivcsw;
  	r->ru_minflt += t->min_flt;
  	r->ru_majflt += t->maj_flt;
  	r->ru_inblock += task_io_get_inblock(t);
  	r->ru_oublock += task_io_get_oublock(t);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1458
1459
1460
1461
  static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
  {
  	struct task_struct *t;
  	unsigned long flags;
0cf55e1ec   Hidetoshi Seto   sched, cputime: I...
1462
  	cputime_t tgutime, tgstime, utime, stime;
1f10206cf   Jiri Pirko   getrusage: fill r...
1463
  	unsigned long maxrss = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1464
1465
  
  	memset((char *) r, 0, sizeof *r);
2dd0ebcd2   Ravikiran G Thirumalai   [PATCH] Avoid tak...
1466
  	utime = stime = cputime_zero;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1467

679c9cd4a   Sripathi Kodi   add RUSAGE_THREAD
1468
  	if (who == RUSAGE_THREAD) {
d180c5bcc   Hidetoshi Seto   sched: Introduce ...
1469
  		task_times(current, &utime, &stime);
f06febc96   Frank Mayhar   timers: fix itime...
1470
  		accumulate_thread_rusage(p, r);
1f10206cf   Jiri Pirko   getrusage: fill r...
1471
  		maxrss = p->signal->maxrss;
679c9cd4a   Sripathi Kodi   add RUSAGE_THREAD
1472
1473
  		goto out;
  	}
d6cf723a1   Oleg Nesterov   k_getrusage: don'...
1474
  	if (!lock_task_sighand(p, &flags))
de047c1bc   Ravikiran G Thirumalai   [PATCH] avoid tas...
1475
  		return;
0f59cc4a3   Oleg Nesterov   [PATCH] simplify ...
1476

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1477
  	switch (who) {
0f59cc4a3   Oleg Nesterov   [PATCH] simplify ...
1478
  		case RUSAGE_BOTH:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1479
  		case RUSAGE_CHILDREN:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1480
1481
1482
1483
1484
1485
  			utime = p->signal->cutime;
  			stime = p->signal->cstime;
  			r->ru_nvcsw = p->signal->cnvcsw;
  			r->ru_nivcsw = p->signal->cnivcsw;
  			r->ru_minflt = p->signal->cmin_flt;
  			r->ru_majflt = p->signal->cmaj_flt;
6eaeeaba3   Eric Dumazet   getrusage(): fill...
1486
1487
  			r->ru_inblock = p->signal->cinblock;
  			r->ru_oublock = p->signal->coublock;
1f10206cf   Jiri Pirko   getrusage: fill r...
1488
  			maxrss = p->signal->cmaxrss;
0f59cc4a3   Oleg Nesterov   [PATCH] simplify ...
1489
1490
1491
  
  			if (who == RUSAGE_CHILDREN)
  				break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1492
  		case RUSAGE_SELF:
0cf55e1ec   Hidetoshi Seto   sched, cputime: I...
1493
1494
1495
  			thread_group_times(p, &tgutime, &tgstime);
  			utime = cputime_add(utime, tgutime);
  			stime = cputime_add(stime, tgstime);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1496
1497
1498
1499
  			r->ru_nvcsw += p->signal->nvcsw;
  			r->ru_nivcsw += p->signal->nivcsw;
  			r->ru_minflt += p->signal->min_flt;
  			r->ru_majflt += p->signal->maj_flt;
6eaeeaba3   Eric Dumazet   getrusage(): fill...
1500
1501
  			r->ru_inblock += p->signal->inblock;
  			r->ru_oublock += p->signal->oublock;
1f10206cf   Jiri Pirko   getrusage: fill r...
1502
1503
  			if (maxrss < p->signal->maxrss)
  				maxrss = p->signal->maxrss;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1504
1505
  			t = p;
  			do {
f06febc96   Frank Mayhar   timers: fix itime...
1506
  				accumulate_thread_rusage(t, r);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1507
1508
  				t = next_thread(t);
  			} while (t != p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1509
  			break;
0f59cc4a3   Oleg Nesterov   [PATCH] simplify ...
1510

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1511
1512
1513
  		default:
  			BUG();
  	}
de047c1bc   Ravikiran G Thirumalai   [PATCH] avoid tas...
1514
  	unlock_task_sighand(p, &flags);
de047c1bc   Ravikiran G Thirumalai   [PATCH] avoid tas...
1515

679c9cd4a   Sripathi Kodi   add RUSAGE_THREAD
1516
  out:
0f59cc4a3   Oleg Nesterov   [PATCH] simplify ...
1517
1518
  	cputime_to_timeval(utime, &r->ru_utime);
  	cputime_to_timeval(stime, &r->ru_stime);
1f10206cf   Jiri Pirko   getrusage: fill r...
1519
1520
1521
1522
1523
1524
1525
1526
1527
  
  	if (who != RUSAGE_CHILDREN) {
  		struct mm_struct *mm = get_task_mm(p);
  		if (mm) {
  			setmax_mm_hiwater_rss(&maxrss, mm);
  			mmput(mm);
  		}
  	}
  	r->ru_maxrss = maxrss * (PAGE_SIZE / 1024); /* convert pages to KBs */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1528
1529
1530
1531
1532
  }
  
  int getrusage(struct task_struct *p, int who, struct rusage __user *ru)
  {
  	struct rusage r;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1533
  	k_getrusage(p, who, &r);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1534
1535
  	return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0;
  }
e48fbb699   Heiko Carstens   [CVE-2009-0029] S...
1536
  SYSCALL_DEFINE2(getrusage, int, who, struct rusage __user *, ru)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1537
  {
679c9cd4a   Sripathi Kodi   add RUSAGE_THREAD
1538
1539
  	if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN &&
  	    who != RUSAGE_THREAD)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1540
1541
1542
  		return -EINVAL;
  	return getrusage(current, who, ru);
  }
e48fbb699   Heiko Carstens   [CVE-2009-0029] S...
1543
  SYSCALL_DEFINE1(umask, int, mask)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1544
1545
1546
1547
  {
  	mask = xchg(&current->fs->umask, mask & S_IRWXUGO);
  	return mask;
  }
3b7391de6   Serge E. Hallyn   capabilities: int...
1548

c4ea37c26   Heiko Carstens   [CVE-2009-0029] S...
1549
1550
  SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
  		unsigned long, arg4, unsigned long, arg5)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1551
  {
b6dff3ec5   David Howells   CRED: Separate ta...
1552
1553
1554
  	struct task_struct *me = current;
  	unsigned char comm[sizeof(me->comm)];
  	long error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1555

d84f4f992   David Howells   CRED: Inaugurate ...
1556
1557
  	error = security_task_prctl(option, arg2, arg3, arg4, arg5);
  	if (error != -ENOSYS)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1558
  		return error;
d84f4f992   David Howells   CRED: Inaugurate ...
1559
  	error = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1560
1561
  	switch (option) {
  		case PR_SET_PDEATHSIG:
0730ded5b   Jesper Juhl   [PATCH] remove a ...
1562
  			if (!valid_signal(arg2)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1563
1564
1565
  				error = -EINVAL;
  				break;
  			}
b6dff3ec5   David Howells   CRED: Separate ta...
1566
1567
  			me->pdeath_signal = arg2;
  			error = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1568
1569
  			break;
  		case PR_GET_PDEATHSIG:
b6dff3ec5   David Howells   CRED: Separate ta...
1570
  			error = put_user(me->pdeath_signal, (int __user *)arg2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1571
1572
  			break;
  		case PR_GET_DUMPABLE:
b6dff3ec5   David Howells   CRED: Separate ta...
1573
  			error = get_dumpable(me->mm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1574
1575
  			break;
  		case PR_SET_DUMPABLE:
abf75a503   Marcel Holtmann   [PATCH] Fix prctl...
1576
  			if (arg2 < 0 || arg2 > 1) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1577
1578
1579
  				error = -EINVAL;
  				break;
  			}
b6dff3ec5   David Howells   CRED: Separate ta...
1580
1581
  			set_dumpable(me->mm, arg2);
  			error = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1582
1583
1584
  			break;
  
  		case PR_SET_UNALIGN:
b6dff3ec5   David Howells   CRED: Separate ta...
1585
  			error = SET_UNALIGN_CTL(me, arg2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1586
1587
  			break;
  		case PR_GET_UNALIGN:
b6dff3ec5   David Howells   CRED: Separate ta...
1588
  			error = GET_UNALIGN_CTL(me, arg2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1589
1590
  			break;
  		case PR_SET_FPEMU:
b6dff3ec5   David Howells   CRED: Separate ta...
1591
  			error = SET_FPEMU_CTL(me, arg2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1592
1593
  			break;
  		case PR_GET_FPEMU:
b6dff3ec5   David Howells   CRED: Separate ta...
1594
  			error = GET_FPEMU_CTL(me, arg2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1595
1596
  			break;
  		case PR_SET_FPEXC:
b6dff3ec5   David Howells   CRED: Separate ta...
1597
  			error = SET_FPEXC_CTL(me, arg2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1598
1599
  			break;
  		case PR_GET_FPEXC:
b6dff3ec5   David Howells   CRED: Separate ta...
1600
  			error = GET_FPEXC_CTL(me, arg2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1601
1602
1603
1604
1605
  			break;
  		case PR_GET_TIMING:
  			error = PR_TIMING_STATISTICAL;
  			break;
  		case PR_SET_TIMING:
7b26655f6   Shi Weihua   sys_prctl(): fix ...
1606
  			if (arg2 != PR_TIMING_STATISTICAL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1607
  				error = -EINVAL;
b6dff3ec5   David Howells   CRED: Separate ta...
1608
1609
  			else
  				error = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1610
  			break;
b6dff3ec5   David Howells   CRED: Separate ta...
1611
1612
1613
1614
  		case PR_SET_NAME:
  			comm[sizeof(me->comm)-1] = 0;
  			if (strncpy_from_user(comm, (char __user *)arg2,
  					      sizeof(me->comm) - 1) < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1615
  				return -EFAULT;
b6dff3ec5   David Howells   CRED: Separate ta...
1616
  			set_task_comm(me, comm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1617
  			return 0;
b6dff3ec5   David Howells   CRED: Separate ta...
1618
1619
1620
1621
  		case PR_GET_NAME:
  			get_task_comm(comm, me);
  			if (copy_to_user((char __user *)arg2, comm,
  					 sizeof(comm)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1622
1623
  				return -EFAULT;
  			return 0;
651d765d0   Anton Blanchard   [PATCH] Add a prc...
1624
  		case PR_GET_ENDIAN:
b6dff3ec5   David Howells   CRED: Separate ta...
1625
  			error = GET_ENDIAN(me, arg2);
651d765d0   Anton Blanchard   [PATCH] Add a prc...
1626
1627
  			break;
  		case PR_SET_ENDIAN:
b6dff3ec5   David Howells   CRED: Separate ta...
1628
  			error = SET_ENDIAN(me, arg2);
651d765d0   Anton Blanchard   [PATCH] Add a prc...
1629
  			break;
1d9d02fee   Andrea Arcangeli   move seccomp from...
1630
1631
1632
1633
1634
1635
  		case PR_GET_SECCOMP:
  			error = prctl_get_seccomp();
  			break;
  		case PR_SET_SECCOMP:
  			error = prctl_set_seccomp(arg2);
  			break;
8fb402bcc   Erik Bosman   generic, x86: add...
1636
1637
1638
1639
1640
1641
  		case PR_GET_TSC:
  			error = GET_TSC_CTL(arg2);
  			break;
  		case PR_SET_TSC:
  			error = SET_TSC_CTL(arg2);
  			break;
cdd6c482c   Ingo Molnar   perf: Do the big ...
1642
1643
  		case PR_TASK_PERF_EVENTS_DISABLE:
  			error = perf_event_task_disable();
1d1c7ddbf   Ingo Molnar   perf counters: ad...
1644
  			break;
cdd6c482c   Ingo Molnar   perf: Do the big ...
1645
1646
  		case PR_TASK_PERF_EVENTS_ENABLE:
  			error = perf_event_task_enable();
1d1c7ddbf   Ingo Molnar   perf counters: ad...
1647
  			break;
6976675d9   Arjan van de Ven   hrtimer: create a...
1648
1649
1650
1651
1652
1653
1654
1655
1656
  		case PR_GET_TIMERSLACK:
  			error = current->timer_slack_ns;
  			break;
  		case PR_SET_TIMERSLACK:
  			if (arg2 <= 0)
  				current->timer_slack_ns =
  					current->default_timer_slack_ns;
  			else
  				current->timer_slack_ns = arg2;
b6dff3ec5   David Howells   CRED: Separate ta...
1657
  			error = 0;
6976675d9   Arjan van de Ven   hrtimer: create a...
1658
  			break;
4db96cf07   Andi Kleen   HWPOISON: Add PR_...
1659
1660
1661
1662
  		case PR_MCE_KILL:
  			if (arg4 | arg5)
  				return -EINVAL;
  			switch (arg2) {
1087e9b4f   Andi Kleen   HWPOISON: Clean u...
1663
  			case PR_MCE_KILL_CLEAR:
4db96cf07   Andi Kleen   HWPOISON: Add PR_...
1664
1665
1666
1667
  				if (arg3 != 0)
  					return -EINVAL;
  				current->flags &= ~PF_MCE_PROCESS;
  				break;
1087e9b4f   Andi Kleen   HWPOISON: Clean u...
1668
  			case PR_MCE_KILL_SET:
4db96cf07   Andi Kleen   HWPOISON: Add PR_...
1669
  				current->flags |= PF_MCE_PROCESS;
1087e9b4f   Andi Kleen   HWPOISON: Clean u...
1670
  				if (arg3 == PR_MCE_KILL_EARLY)
4db96cf07   Andi Kleen   HWPOISON: Add PR_...
1671
  					current->flags |= PF_MCE_EARLY;
1087e9b4f   Andi Kleen   HWPOISON: Clean u...
1672
  				else if (arg3 == PR_MCE_KILL_LATE)
4db96cf07   Andi Kleen   HWPOISON: Add PR_...
1673
  					current->flags &= ~PF_MCE_EARLY;
1087e9b4f   Andi Kleen   HWPOISON: Clean u...
1674
1675
1676
1677
1678
  				else if (arg3 == PR_MCE_KILL_DEFAULT)
  					current->flags &=
  						~(PF_MCE_EARLY|PF_MCE_PROCESS);
  				else
  					return -EINVAL;
4db96cf07   Andi Kleen   HWPOISON: Add PR_...
1679
1680
1681
1682
1683
1684
  				break;
  			default:
  				return -EINVAL;
  			}
  			error = 0;
  			break;
1087e9b4f   Andi Kleen   HWPOISON: Clean u...
1685
1686
1687
1688
1689
1690
1691
1692
1693
  		case PR_MCE_KILL_GET:
  			if (arg2 | arg3 | arg4 | arg5)
  				return -EINVAL;
  			if (current->flags & PF_MCE_PROCESS)
  				error = (current->flags & PF_MCE_EARLY) ?
  					PR_MCE_KILL_EARLY : PR_MCE_KILL_LATE;
  			else
  				error = PR_MCE_KILL_DEFAULT;
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1694
1695
1696
1697
1698
1699
  		default:
  			error = -EINVAL;
  			break;
  	}
  	return error;
  }
3cfc348bf   Andi Kleen   [PATCH] x86: Add ...
1700

836f92adf   Heiko Carstens   [CVE-2009-0029] S...
1701
1702
  SYSCALL_DEFINE3(getcpu, unsigned __user *, cpup, unsigned __user *, nodep,
  		struct getcpu_cache __user *, unused)
3cfc348bf   Andi Kleen   [PATCH] x86: Add ...
1703
1704
1705
1706
1707
1708
1709
  {
  	int err = 0;
  	int cpu = raw_smp_processor_id();
  	if (cpup)
  		err |= put_user(cpu, cpup);
  	if (nodep)
  		err |= put_user(cpu_to_node(cpu), nodep);
3cfc348bf   Andi Kleen   [PATCH] x86: Add ...
1710
1711
  	return err ? -EFAULT : 0;
  }
10a0a8d4e   Jeremy Fitzhardinge   Add common orderl...
1712
1713
  
  char poweroff_cmd[POWEROFF_CMD_PATH_LEN] = "/sbin/poweroff";
a06a4dc3a   Neil Horman   kmod: add init fu...
1714
  static void argv_cleanup(struct subprocess_info *info)
10a0a8d4e   Jeremy Fitzhardinge   Add common orderl...
1715
  {
a06a4dc3a   Neil Horman   kmod: add init fu...
1716
  	argv_free(info->argv);
10a0a8d4e   Jeremy Fitzhardinge   Add common orderl...
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
  }
  
  /**
   * orderly_poweroff - Trigger an orderly system poweroff
   * @force: force poweroff if command execution fails
   *
   * This may be called from any context to trigger a system shutdown.
   * If the orderly shutdown fails, it will force an immediate shutdown.
   */
  int orderly_poweroff(bool force)
  {
  	int argc;
  	char **argv = argv_split(GFP_ATOMIC, poweroff_cmd, &argc);
  	static char *envp[] = {
  		"HOME=/",
  		"PATH=/sbin:/bin:/usr/sbin:/usr/bin",
  		NULL
  	};
  	int ret = -ENOMEM;
  	struct subprocess_info *info;
  
  	if (argv == NULL) {
  		printk(KERN_WARNING "%s failed to allocate memory for \"%s\"
  ",
  		       __func__, poweroff_cmd);
  		goto out;
  	}
ac331d158   KOSAKI Motohiro   call_usermodehelp...
1744
  	info = call_usermodehelper_setup(argv[0], argv, envp, GFP_ATOMIC);
10a0a8d4e   Jeremy Fitzhardinge   Add common orderl...
1745
1746
1747
1748
  	if (info == NULL) {
  		argv_free(argv);
  		goto out;
  	}
a06a4dc3a   Neil Horman   kmod: add init fu...
1749
  	call_usermodehelper_setfns(info, NULL, argv_cleanup, NULL);
10a0a8d4e   Jeremy Fitzhardinge   Add common orderl...
1750

86313c488   Jeremy Fitzhardinge   usermodehelper: T...
1751
  	ret = call_usermodehelper_exec(info, UMH_NO_WAIT);
10a0a8d4e   Jeremy Fitzhardinge   Add common orderl...
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
  
    out:
  	if (ret && force) {
  		printk(KERN_WARNING "Failed to start orderly shutdown: "
  		       "forcing the issue
  ");
  
  		/* I guess this should try to kick off some daemon to
  		   sync and poweroff asap.  Or not even bother syncing
  		   if we're doing an emergency shutdown? */
  		emergency_sync();
  		kernel_power_off();
  	}
  
  	return ret;
  }
  EXPORT_SYMBOL_GPL(orderly_poweroff);