Blame view

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

04c6862c0   Seiji Aguchi   kmsg_dump: add km...
47
  #include <linux/kmsg_dump.h>
be27425dc   Andi Kleen   Add a personality...
48
49
  /* Move somewhere else to avoid recompiling? */
  #include <generated/utsrelease.h>
04c6862c0   Seiji Aguchi   kmsg_dump: add km...
50

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
  #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...
73
74
75
76
77
78
  #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...
79
80
81
82
83
84
  #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
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
111
112
113
114
  
  /*
   * 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...
115
116
  struct pid *cad_pid;
  EXPORT_SYMBOL(cad_pid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
117
118
  
  /*
bd804eba1   Rafael J. Wysocki   PM: Introduce pm_...
119
120
121
122
   * 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_...
123

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

3e88c553d   Daniel Walker   use defines in sy...
177
  	if (which > PRIO_USER || which < PRIO_PROCESS)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
178
179
180
181
182
183
184
185
  		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 ...
186
  	rcu_read_lock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
187
188
189
  	read_lock(&tasklist_lock);
  	switch (which) {
  		case PRIO_PROCESS:
41487c65b   Eric W. Biederman   [PATCH] pid: repl...
190
  			if (who)
228ebcbe6   Pavel Emelyanov   Uninline find_tas...
191
  				p = find_task_by_vpid(who);
41487c65b   Eric W. Biederman   [PATCH] pid: repl...
192
193
  			else
  				p = current;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
194
195
196
197
  			if (p)
  				error = set_one_prio(p, niceval, error);
  			break;
  		case PRIO_PGRP:
41487c65b   Eric W. Biederman   [PATCH] pid: repl...
198
  			if (who)
b488893a3   Pavel Emelyanov   pid namespaces: c...
199
  				pgrp = find_vpid(who);
41487c65b   Eric W. Biederman   [PATCH] pid: repl...
200
201
  			else
  				pgrp = task_pgrp(current);
2d70b68d4   Ken Chen   fix setpriority(P...
202
  			do_each_pid_thread(pgrp, PIDTYPE_PGID, p) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
203
  				error = set_one_prio(p, niceval, error);
2d70b68d4   Ken Chen   fix setpriority(P...
204
  			} while_each_pid_thread(pgrp, PIDTYPE_PGID, p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
205
206
  			break;
  		case PRIO_USER:
d84f4f992   David Howells   CRED: Inaugurate ...
207
  			user = (struct user_struct *) cred->user;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208
  			if (!who)
86a264abe   David Howells   CRED: Wrap curren...
209
210
211
212
  				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
213

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

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

dfc6a736d   H Hartley Sweeten   kernel/sys.c: fix...
278
  			do_each_thread(g, p) {
86a264abe   David Howells   CRED: Wrap curren...
279
  				if (__task_cred(p)->uid == who) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
280
281
282
283
  					niceval = 20 - task_nice(p);
  					if (niceval > retval)
  						retval = niceval;
  				}
dfc6a736d   H Hartley Sweeten   kernel/sys.c: fix...
284
  			} while_each_thread(g, p);
86a264abe   David Howells   CRED: Wrap curren...
285
  			if (who != cred->uid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
286
287
288
289
290
  				free_uid(user);		/* for find_user() */
  			break;
  	}
  out_unlock:
  	read_unlock(&tasklist_lock);
701188374   Tetsuo Handa   kernel/sys.c: fix...
291
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
292
293
294
  
  	return retval;
  }
e4c94330e   Eric W. Biederman   [PATCH] reboot: c...
295
296
297
298
299
300
301
302
  /**
   *	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...
303
304
  void emergency_restart(void)
  {
04c6862c0   Seiji Aguchi   kmsg_dump: add km...
305
  	kmsg_dump(KMSG_DUMP_EMERG);
7c9034735   Eric W. Biederman   [PATCH] Add emerg...
306
307
308
  	machine_emergency_restart();
  }
  EXPORT_SYMBOL_GPL(emergency_restart);
ca195b7f6   Huang Ying   kexec jump: remov...
309
  void kernel_restart_prepare(char *cmd)
4a00ea1e1   Eric W. Biederman   [PATCH] Refactor ...
310
  {
e041c6834   Alan Stern   [PATCH] Notifier ...
311
  	blocking_notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd);
4a00ea1e1   Eric W. Biederman   [PATCH] Refactor ...
312
  	system_state = SYSTEM_RESTART;
b50fa7c80   Kay Sievers   reboot: disable u...
313
  	usermodehelper_disable();
4a00ea1e1   Eric W. Biederman   [PATCH] Refactor ...
314
  	device_shutdown();
40dc166cb   Rafael J. Wysocki   PM / Core: Introd...
315
  	syscore_shutdown();
e4c94330e   Eric W. Biederman   [PATCH] reboot: c...
316
  }
1e5d53314   Randy Dunlap   [PATCH] more kern...
317
318
  
  /**
c5f41752f   Amerigo Wang   notifiers: sys: m...
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
   *	register_reboot_notifier - Register function to be called at reboot time
   *	@nb: Info about notifier function to be called
   *
   *	Registers a function with the list of functions
   *	to be called at reboot time.
   *
   *	Currently always returns zero, as blocking_notifier_chain_register()
   *	always returns zero.
   */
  int register_reboot_notifier(struct notifier_block *nb)
  {
  	return blocking_notifier_chain_register(&reboot_notifier_list, nb);
  }
  EXPORT_SYMBOL(register_reboot_notifier);
  
  /**
   *	unregister_reboot_notifier - Unregister previously registered reboot notifier
   *	@nb: Hook to be unregistered
   *
   *	Unregisters a previously registered reboot
   *	notifier function.
   *
   *	Returns zero on success, or %-ENOENT on failure.
   */
  int unregister_reboot_notifier(struct notifier_block *nb)
  {
  	return blocking_notifier_chain_unregister(&reboot_notifier_list, nb);
  }
  EXPORT_SYMBOL(unregister_reboot_notifier);
  
  /**
1e5d53314   Randy Dunlap   [PATCH] more kern...
350
351
   *	kernel_restart - reboot the system
   *	@cmd: pointer to buffer containing command to execute for restart
b8887e6e8   Randy Dunlap   [PATCH] kernel-do...
352
   *		or %NULL
1e5d53314   Randy Dunlap   [PATCH] more kern...
353
354
355
356
   *
   *	Shutdown everything and perform a clean reboot.
   *	This is not safe to call in interrupt context.
   */
e4c94330e   Eric W. Biederman   [PATCH] reboot: c...
357
358
359
  void kernel_restart(char *cmd)
  {
  	kernel_restart_prepare(cmd);
756184b7d   Cal Peake   [PATCH] CodingSty...
360
  	if (!cmd)
4a00ea1e1   Eric W. Biederman   [PATCH] Refactor ...
361
362
  		printk(KERN_EMERG "Restarting system.
  ");
756184b7d   Cal Peake   [PATCH] CodingSty...
363
  	else
4a00ea1e1   Eric W. Biederman   [PATCH] Refactor ...
364
365
  		printk(KERN_EMERG "Restarting system with command '%s'.
  ", cmd);
04c6862c0   Seiji Aguchi   kmsg_dump: add km...
366
  	kmsg_dump(KMSG_DUMP_RESTART);
4a00ea1e1   Eric W. Biederman   [PATCH] Refactor ...
367
368
369
  	machine_restart(cmd);
  }
  EXPORT_SYMBOL_GPL(kernel_restart);
4ef7229ff   Adrian Bunk   make kernel_shutd...
370
  static void kernel_shutdown_prepare(enum system_states state)
729b4d4ce   Alexey Starikovskiy   [ACPI] fix reboot...
371
  {
e041c6834   Alan Stern   [PATCH] Notifier ...
372
  	blocking_notifier_call_chain(&reboot_notifier_list,
729b4d4ce   Alexey Starikovskiy   [ACPI] fix reboot...
373
374
  		(state == SYSTEM_HALT)?SYS_HALT:SYS_POWER_OFF, NULL);
  	system_state = state;
b50fa7c80   Kay Sievers   reboot: disable u...
375
  	usermodehelper_disable();
729b4d4ce   Alexey Starikovskiy   [ACPI] fix reboot...
376
377
  	device_shutdown();
  }
e4c94330e   Eric W. Biederman   [PATCH] reboot: c...
378
379
380
381
382
  /**
   *	kernel_halt - halt the system
   *
   *	Shutdown everything and perform a clean system halt.
   */
e4c94330e   Eric W. Biederman   [PATCH] reboot: c...
383
384
  void kernel_halt(void)
  {
729b4d4ce   Alexey Starikovskiy   [ACPI] fix reboot...
385
  	kernel_shutdown_prepare(SYSTEM_HALT);
40dc166cb   Rafael J. Wysocki   PM / Core: Introd...
386
  	syscore_shutdown();
4a00ea1e1   Eric W. Biederman   [PATCH] Refactor ...
387
388
  	printk(KERN_EMERG "System halted.
  ");
04c6862c0   Seiji Aguchi   kmsg_dump: add km...
389
  	kmsg_dump(KMSG_DUMP_HALT);
4a00ea1e1   Eric W. Biederman   [PATCH] Refactor ...
390
391
  	machine_halt();
  }
729b4d4ce   Alexey Starikovskiy   [ACPI] fix reboot...
392

4a00ea1e1   Eric W. Biederman   [PATCH] Refactor ...
393
  EXPORT_SYMBOL_GPL(kernel_halt);
e4c94330e   Eric W. Biederman   [PATCH] reboot: c...
394
395
396
397
398
  /**
   *	kernel_power_off - power_off the system
   *
   *	Shutdown everything and perform a clean system power_off.
   */
e4c94330e   Eric W. Biederman   [PATCH] reboot: c...
399
400
  void kernel_power_off(void)
  {
729b4d4ce   Alexey Starikovskiy   [ACPI] fix reboot...
401
  	kernel_shutdown_prepare(SYSTEM_POWER_OFF);
bd804eba1   Rafael J. Wysocki   PM: Introduce pm_...
402
403
  	if (pm_power_off_prepare)
  		pm_power_off_prepare();
4047727e5   Mark Lord   Fix SMP poweroff ...
404
  	disable_nonboot_cpus();
40dc166cb   Rafael J. Wysocki   PM / Core: Introd...
405
  	syscore_shutdown();
4a00ea1e1   Eric W. Biederman   [PATCH] Refactor ...
406
407
  	printk(KERN_EMERG "Power down.
  ");
04c6862c0   Seiji Aguchi   kmsg_dump: add km...
408
  	kmsg_dump(KMSG_DUMP_POWEROFF);
4a00ea1e1   Eric W. Biederman   [PATCH] Refactor ...
409
410
411
  	machine_power_off();
  }
  EXPORT_SYMBOL_GPL(kernel_power_off);
6f15fa500   Thomas Gleixner   sys: Remove BKL f...
412
413
  
  static DEFINE_MUTEX(reboot_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
414
415
416
417
418
419
420
421
  /*
   * 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...
422
423
  SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
  		void __user *, arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
424
425
  {
  	char buffer[256];
3d26dcf76   Andi Kleen   kernel/sys.c: cle...
426
  	int ret = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
427
428
429
430
431
432
433
434
435
436
437
438
  
  	/* 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...
439
440
441
442
443
  	/* 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...
444
  	mutex_lock(&reboot_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
445
446
  	switch (cmd) {
  	case LINUX_REBOOT_CMD_RESTART:
4a00ea1e1   Eric W. Biederman   [PATCH] Refactor ...
447
  		kernel_restart(NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
448
449
450
451
452
453
454
455
456
457
458
  		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 ...
459
  		kernel_halt();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
460
  		do_exit(0);
3d26dcf76   Andi Kleen   kernel/sys.c: cle...
461
  		panic("cannot halt");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
462
463
  
  	case LINUX_REBOOT_CMD_POWER_OFF:
4a00ea1e1   Eric W. Biederman   [PATCH] Refactor ...
464
  		kernel_power_off();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
465
466
467
468
469
  		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...
470
471
  			ret = -EFAULT;
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
472
473
  		}
  		buffer[sizeof(buffer) - 1] = '\0';
4a00ea1e1   Eric W. Biederman   [PATCH] Refactor ...
474
  		kernel_restart(buffer);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
475
  		break;
3ab835213   Huang Ying   kexec jump
476
  #ifdef CONFIG_KEXEC
dc009d924   Eric W. Biederman   [PATCH] kexec: ad...
477
  	case LINUX_REBOOT_CMD_KEXEC:
3d26dcf76   Andi Kleen   kernel/sys.c: cle...
478
479
  		ret = kernel_kexec();
  		break;
3ab835213   Huang Ying   kexec jump
480
  #endif
4a00ea1e1   Eric W. Biederman   [PATCH] Refactor ...
481

b0cb1a19d   Rafael J. Wysocki   Replace CONFIG_SO...
482
  #ifdef CONFIG_HIBERNATION
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
483
  	case LINUX_REBOOT_CMD_SW_SUSPEND:
3d26dcf76   Andi Kleen   kernel/sys.c: cle...
484
485
  		ret = hibernate();
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
486
487
488
  #endif
  
  	default:
3d26dcf76   Andi Kleen   kernel/sys.c: cle...
489
490
  		ret = -EINVAL;
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
491
  	}
6f15fa500   Thomas Gleixner   sys: Remove BKL f...
492
  	mutex_unlock(&reboot_mutex);
3d26dcf76   Andi Kleen   kernel/sys.c: cle...
493
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
494
  }
65f27f384   David Howells   WorkStruct: Pass ...
495
  static void deferred_cad(struct work_struct *dummy)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
496
  {
abcd9e51f   Eric W. Biederman   [PATCH] Make ctrl...
497
  	kernel_restart(NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
498
499
500
501
502
503
504
505
506
  }
  
  /*
   * 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 ...
507
  	static DECLARE_WORK(cad_work, deferred_cad);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
508
509
510
511
  
  	if (C_A_D)
  		schedule_work(&cad_work);
  	else
9ec52099e   Cedric Le Goater   [PATCH] replace c...
512
  		kill_cad_pid(SIGINT, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
513
514
  }
  	
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
  /*
   * 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...
533
  SYSCALL_DEFINE2(setregid, gid_t, rgid, gid_t, egid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
534
  {
d84f4f992   David Howells   CRED: Inaugurate ...
535
536
  	const struct cred *old;
  	struct cred *new;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
537
  	int retval;
d84f4f992   David Howells   CRED: Inaugurate ...
538
539
540
541
  	new = prepare_creds();
  	if (!new)
  		return -ENOMEM;
  	old = current_cred();
d84f4f992   David Howells   CRED: Inaugurate ...
542
  	retval = -EPERM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
543
  	if (rgid != (gid_t) -1) {
d84f4f992   David Howells   CRED: Inaugurate ...
544
545
  		if (old->gid == rgid ||
  		    old->egid == rgid ||
fc832ad36   Serge E. Hallyn   userns: user name...
546
  		    nsown_capable(CAP_SETGID))
d84f4f992   David Howells   CRED: Inaugurate ...
547
  			new->gid = rgid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
548
  		else
d84f4f992   David Howells   CRED: Inaugurate ...
549
  			goto error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
550
551
  	}
  	if (egid != (gid_t) -1) {
d84f4f992   David Howells   CRED: Inaugurate ...
552
553
554
  		if (old->gid == egid ||
  		    old->egid == egid ||
  		    old->sgid == egid ||
fc832ad36   Serge E. Hallyn   userns: user name...
555
  		    nsown_capable(CAP_SETGID))
d84f4f992   David Howells   CRED: Inaugurate ...
556
  			new->egid = egid;
756184b7d   Cal Peake   [PATCH] CodingSty...
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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
561
  	if (rgid != (gid_t) -1 ||
d84f4f992   David Howells   CRED: Inaugurate ...
562
563
564
565
566
567
568
569
570
  	    (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
571
572
573
574
575
576
577
  }
  
  /*
   * setgid() is implemented like SysV w/ SAVED_IDS 
   *
   * SMP: Same implicit races as above.
   */
ae1251ab7   Heiko Carstens   [CVE-2009-0029] S...
578
  SYSCALL_DEFINE1(setgid, gid_t, gid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
579
  {
d84f4f992   David Howells   CRED: Inaugurate ...
580
581
  	const struct cred *old;
  	struct cred *new;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
582
  	int retval;
d84f4f992   David Howells   CRED: Inaugurate ...
583
584
585
586
  	new = prepare_creds();
  	if (!new)
  		return -ENOMEM;
  	old = current_cred();
d84f4f992   David Howells   CRED: Inaugurate ...
587
  	retval = -EPERM;
fc832ad36   Serge E. Hallyn   userns: user name...
588
  	if (nsown_capable(CAP_SETGID))
d84f4f992   David Howells   CRED: Inaugurate ...
589
590
591
  		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
592
  	else
d84f4f992   David Howells   CRED: Inaugurate ...
593
  		goto error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
594

d84f4f992   David Howells   CRED: Inaugurate ...
595
596
597
598
599
  	return commit_creds(new);
  
  error:
  	abort_creds(new);
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
600
  }
54e991242   Dhaval Giani   sched: don't allo...
601

d84f4f992   David Howells   CRED: Inaugurate ...
602
603
604
605
  /*
   * 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
606
607
  {
  	struct user_struct *new_user;
18b6e0414   Serge Hallyn   User namespaces: ...
608
  	new_user = alloc_uid(current_user_ns(), new->uid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
609
610
  	if (!new_user)
  		return -EAGAIN;
72fa59970   Vasiliy Kulikov   move RLIMIT_NPROC...
611
612
613
614
615
616
617
  	/*
  	 * 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.
  	 */
78d7d407b   Jiri Slaby   kernel core: use ...
618
  	if (atomic_read(&new_user->processes) >= rlimit(RLIMIT_NPROC) &&
72fa59970   Vasiliy Kulikov   move RLIMIT_NPROC...
619
620
621
622
  			new_user != INIT_USER)
  		current->flags |= PF_NPROC_EXCEEDED;
  	else
  		current->flags &= ~PF_NPROC_EXCEEDED;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
623

d84f4f992   David Howells   CRED: Inaugurate ...
624
625
  	free_uid(new->user);
  	new->user = new_user;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
  	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...
644
  SYSCALL_DEFINE2(setreuid, uid_t, ruid, uid_t, euid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
645
  {
d84f4f992   David Howells   CRED: Inaugurate ...
646
647
  	const struct cred *old;
  	struct cred *new;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
648
  	int retval;
d84f4f992   David Howells   CRED: Inaugurate ...
649
650
651
652
  	new = prepare_creds();
  	if (!new)
  		return -ENOMEM;
  	old = current_cred();
d84f4f992   David Howells   CRED: Inaugurate ...
653
  	retval = -EPERM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
654
  	if (ruid != (uid_t) -1) {
d84f4f992   David Howells   CRED: Inaugurate ...
655
656
657
  		new->uid = ruid;
  		if (old->uid != ruid &&
  		    old->euid != ruid &&
fc832ad36   Serge E. Hallyn   userns: user name...
658
  		    !nsown_capable(CAP_SETUID))
d84f4f992   David Howells   CRED: Inaugurate ...
659
  			goto error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
660
661
662
  	}
  
  	if (euid != (uid_t) -1) {
d84f4f992   David Howells   CRED: Inaugurate ...
663
664
665
666
  		new->euid = euid;
  		if (old->uid != euid &&
  		    old->euid != euid &&
  		    old->suid != euid &&
fc832ad36   Serge E. Hallyn   userns: user name...
667
  		    !nsown_capable(CAP_SETUID))
d84f4f992   David Howells   CRED: Inaugurate ...
668
  			goto error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
669
  	}
54e991242   Dhaval Giani   sched: don't allo...
670
671
672
673
674
  	if (new->uid != old->uid) {
  		retval = set_user(new);
  		if (retval < 0)
  			goto error;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
675
  	if (ruid != (uid_t) -1 ||
d84f4f992   David Howells   CRED: Inaugurate ...
676
677
678
  	    (euid != (uid_t) -1 && euid != old->uid))
  		new->suid = new->euid;
  	new->fsuid = new->euid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
679

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

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

d84f4f992   David Howells   CRED: Inaugurate ...
686
687
688
689
  error:
  	abort_creds(new);
  	return retval;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
690
691
692
693
694
695
696
697
698
699
700
701
  		
  /*
   * 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...
702
  SYSCALL_DEFINE1(setuid, uid_t, uid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
703
  {
d84f4f992   David Howells   CRED: Inaugurate ...
704
705
  	const struct cred *old;
  	struct cred *new;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
706
  	int retval;
d84f4f992   David Howells   CRED: Inaugurate ...
707
708
709
710
  	new = prepare_creds();
  	if (!new)
  		return -ENOMEM;
  	old = current_cred();
d84f4f992   David Howells   CRED: Inaugurate ...
711
  	retval = -EPERM;
fc832ad36   Serge E. Hallyn   userns: user name...
712
  	if (nsown_capable(CAP_SETUID)) {
d84f4f992   David Howells   CRED: Inaugurate ...
713
  		new->suid = new->uid = uid;
54e991242   Dhaval Giani   sched: don't allo...
714
715
716
717
  		if (uid != old->uid) {
  			retval = set_user(new);
  			if (retval < 0)
  				goto error;
d84f4f992   David Howells   CRED: Inaugurate ...
718
719
720
  		}
  	} else if (uid != old->uid && uid != new->suid) {
  		goto error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
721
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
722

d84f4f992   David Howells   CRED: Inaugurate ...
723
724
725
726
727
  	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
728

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

d84f4f992   David Howells   CRED: Inaugurate ...
731
732
733
  error:
  	abort_creds(new);
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
734
735
736
737
738
739
740
  }
  
  
  /*
   * 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...
741
  SYSCALL_DEFINE3(setresuid, uid_t, ruid, uid_t, euid, uid_t, suid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
742
  {
d84f4f992   David Howells   CRED: Inaugurate ...
743
744
  	const struct cred *old;
  	struct cred *new;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
745
  	int retval;
d84f4f992   David Howells   CRED: Inaugurate ...
746
747
748
  	new = prepare_creds();
  	if (!new)
  		return -ENOMEM;
d84f4f992   David Howells   CRED: Inaugurate ...
749
  	old = current_cred();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
750

d84f4f992   David Howells   CRED: Inaugurate ...
751
  	retval = -EPERM;
fc832ad36   Serge E. Hallyn   userns: user name...
752
  	if (!nsown_capable(CAP_SETUID)) {
d84f4f992   David Howells   CRED: Inaugurate ...
753
754
755
756
757
758
759
760
761
  		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
762
  	}
d84f4f992   David Howells   CRED: Inaugurate ...
763

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
764
  	if (ruid != (uid_t) -1) {
d84f4f992   David Howells   CRED: Inaugurate ...
765
  		new->uid = ruid;
54e991242   Dhaval Giani   sched: don't allo...
766
767
768
769
770
  		if (ruid != old->uid) {
  			retval = set_user(new);
  			if (retval < 0)
  				goto error;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
771
  	}
d84f4f992   David Howells   CRED: Inaugurate ...
772
773
  	if (euid != (uid_t) -1)
  		new->euid = euid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
774
  	if (suid != (uid_t) -1)
d84f4f992   David Howells   CRED: Inaugurate ...
775
776
  		new->suid = suid;
  	new->fsuid = new->euid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
777

d84f4f992   David Howells   CRED: Inaugurate ...
778
779
780
  	retval = security_task_fix_setuid(new, old, LSM_SETID_RES);
  	if (retval < 0)
  		goto error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
781

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

d84f4f992   David Howells   CRED: Inaugurate ...
784
785
786
  error:
  	abort_creds(new);
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
787
  }
dbf040d9d   Heiko Carstens   [CVE-2009-0029] S...
788
  SYSCALL_DEFINE3(getresuid, uid_t __user *, ruid, uid_t __user *, euid, uid_t __user *, suid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
789
  {
86a264abe   David Howells   CRED: Wrap curren...
790
  	const struct cred *cred = current_cred();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
791
  	int retval;
86a264abe   David Howells   CRED: Wrap curren...
792
793
  	if (!(retval   = put_user(cred->uid,  ruid)) &&
  	    !(retval   = put_user(cred->euid, euid)))
b6dff3ec5   David Howells   CRED: Separate ta...
794
  		retval = put_user(cred->suid, suid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
795
796
797
798
799
800
801
  
  	return retval;
  }
  
  /*
   * Same as above, but for rgid, egid, sgid.
   */
ae1251ab7   Heiko Carstens   [CVE-2009-0029] S...
802
  SYSCALL_DEFINE3(setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
803
  {
d84f4f992   David Howells   CRED: Inaugurate ...
804
805
  	const struct cred *old;
  	struct cred *new;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
806
  	int retval;
d84f4f992   David Howells   CRED: Inaugurate ...
807
808
809
810
  	new = prepare_creds();
  	if (!new)
  		return -ENOMEM;
  	old = current_cred();
d84f4f992   David Howells   CRED: Inaugurate ...
811
  	retval = -EPERM;
fc832ad36   Serge E. Hallyn   userns: user name...
812
  	if (!nsown_capable(CAP_SETGID)) {
d84f4f992   David Howells   CRED: Inaugurate ...
813
814
815
816
817
818
819
820
821
  		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
822
  	}
d84f4f992   David Howells   CRED: Inaugurate ...
823

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
824
  	if (rgid != (gid_t) -1)
d84f4f992   David Howells   CRED: Inaugurate ...
825
826
827
  		new->gid = rgid;
  	if (egid != (gid_t) -1)
  		new->egid = egid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
828
  	if (sgid != (gid_t) -1)
d84f4f992   David Howells   CRED: Inaugurate ...
829
830
  		new->sgid = sgid;
  	new->fsgid = new->egid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
831

d84f4f992   David Howells   CRED: Inaugurate ...
832
833
834
835
836
  	return commit_creds(new);
  
  error:
  	abort_creds(new);
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
837
  }
dbf040d9d   Heiko Carstens   [CVE-2009-0029] S...
838
  SYSCALL_DEFINE3(getresgid, gid_t __user *, rgid, gid_t __user *, egid, gid_t __user *, sgid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
839
  {
86a264abe   David Howells   CRED: Wrap curren...
840
  	const struct cred *cred = current_cred();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
841
  	int retval;
86a264abe   David Howells   CRED: Wrap curren...
842
843
  	if (!(retval   = put_user(cred->gid,  rgid)) &&
  	    !(retval   = put_user(cred->egid, egid)))
b6dff3ec5   David Howells   CRED: Separate ta...
844
  		retval = put_user(cred->sgid, sgid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
845
846
847
848
849
850
851
852
853
854
855
  
  	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...
856
  SYSCALL_DEFINE1(setfsuid, uid_t, uid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
857
  {
d84f4f992   David Howells   CRED: Inaugurate ...
858
859
860
  	const struct cred *old;
  	struct cred *new;
  	uid_t old_fsuid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
861

d84f4f992   David Howells   CRED: Inaugurate ...
862
863
864
865
866
  	new = prepare_creds();
  	if (!new)
  		return current_fsuid();
  	old = current_cred();
  	old_fsuid = old->fsuid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
867

d84f4f992   David Howells   CRED: Inaugurate ...
868
869
  	if (uid == old->uid  || uid == old->euid  ||
  	    uid == old->suid || uid == old->fsuid ||
fc832ad36   Serge E. Hallyn   userns: user name...
870
  	    nsown_capable(CAP_SETUID)) {
756184b7d   Cal Peake   [PATCH] CodingSty...
871
  		if (uid != old_fsuid) {
d84f4f992   David Howells   CRED: Inaugurate ...
872
873
874
  			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
875
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
876
  	}
d84f4f992   David Howells   CRED: Inaugurate ...
877
878
  	abort_creds(new);
  	return old_fsuid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
879

d84f4f992   David Howells   CRED: Inaugurate ...
880
881
  change_okay:
  	commit_creds(new);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
882
883
884
885
  	return old_fsuid;
  }
  
  /*
f42df9e65   John Anthony Kazos Jr   general: convert ...
886
   * Samma på svenska..
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
887
   */
ae1251ab7   Heiko Carstens   [CVE-2009-0029] S...
888
  SYSCALL_DEFINE1(setfsgid, gid_t, gid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
889
  {
d84f4f992   David Howells   CRED: Inaugurate ...
890
891
892
893
894
895
896
897
898
  	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
899

d84f4f992   David Howells   CRED: Inaugurate ...
900
901
  	if (gid == old->gid  || gid == old->egid  ||
  	    gid == old->sgid || gid == old->fsgid ||
fc832ad36   Serge E. Hallyn   userns: user name...
902
  	    nsown_capable(CAP_SETGID)) {
756184b7d   Cal Peake   [PATCH] CodingSty...
903
  		if (gid != old_fsgid) {
d84f4f992   David Howells   CRED: Inaugurate ...
904
905
  			new->fsgid = gid;
  			goto change_okay;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
906
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
907
  	}
d84f4f992   David Howells   CRED: Inaugurate ...
908

d84f4f992   David Howells   CRED: Inaugurate ...
909
910
911
912
913
  	abort_creds(new);
  	return old_fsgid;
  
  change_okay:
  	commit_creds(new);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
914
915
  	return old_fsgid;
  }
f06febc96   Frank Mayhar   timers: fix itime...
916
917
  void do_sys_times(struct tms *tms)
  {
0cf55e1ec   Hidetoshi Seto   sched, cputime: I...
918
  	cputime_t tgutime, tgstime, cutime, cstime;
f06febc96   Frank Mayhar   timers: fix itime...
919

2b5fe6de5   Oleg Nesterov   thread_group_cput...
920
  	spin_lock_irq(&current->sighand->siglock);
0cf55e1ec   Hidetoshi Seto   sched, cputime: I...
921
  	thread_group_times(current, &tgutime, &tgstime);
f06febc96   Frank Mayhar   timers: fix itime...
922
923
924
  	cutime = current->signal->cutime;
  	cstime = current->signal->cstime;
  	spin_unlock_irq(&current->sighand->siglock);
0cf55e1ec   Hidetoshi Seto   sched, cputime: I...
925
926
  	tms->tms_utime = cputime_to_clock_t(tgutime);
  	tms->tms_stime = cputime_to_clock_t(tgstime);
f06febc96   Frank Mayhar   timers: fix itime...
927
928
929
  	tms->tms_cutime = cputime_to_clock_t(cutime);
  	tms->tms_cstime = cputime_to_clock_t(cstime);
  }
58fd3aa28   Heiko Carstens   [CVE-2009-0029] S...
930
  SYSCALL_DEFINE1(times, struct tms __user *, tbuf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
931
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
932
933
  	if (tbuf) {
  		struct tms tmp;
f06febc96   Frank Mayhar   timers: fix itime...
934
935
  
  		do_sys_times(&tmp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
936
937
938
  		if (copy_to_user(tbuf, &tmp, sizeof(struct tms)))
  			return -EFAULT;
  	}
e3d5a27d5   Paul Mackerras   Allow times and t...
939
  	force_successful_syscall_return();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
  	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...
955
  SYSCALL_DEFINE2(setpgid, pid_t, pid, pid_t, pgid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
956
957
  {
  	struct task_struct *p;
ee0acf90d   Oleg Nesterov   [PATCH] setpgid: ...
958
  	struct task_struct *group_leader = current->group_leader;
4e021306c   Oleg Nesterov   sys_setpgid(): si...
959
960
  	struct pid *pgrp;
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
961
962
  
  	if (!pid)
b488893a3   Pavel Emelyanov   pid namespaces: c...
963
  		pid = task_pid_vnr(group_leader);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
964
965
966
967
  	if (!pgid)
  		pgid = pid;
  	if (pgid < 0)
  		return -EINVAL;
950eaaca6   Paul E. McKenney   pid: make setpgid...
968
  	rcu_read_lock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
969
970
971
972
973
974
975
  
  	/* 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...
976
  	p = find_task_by_vpid(pid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
977
978
979
980
981
982
  	if (!p)
  		goto out;
  
  	err = -EINVAL;
  	if (!thread_group_leader(p))
  		goto out;
4e021306c   Oleg Nesterov   sys_setpgid(): si...
983
  	if (same_thread_group(p->real_parent, group_leader)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
984
  		err = -EPERM;
41487c65b   Eric W. Biederman   [PATCH] pid: repl...
985
  		if (task_session(p) != task_session(group_leader))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
986
987
988
989
990
991
  			goto out;
  		err = -EACCES;
  		if (p->did_exec)
  			goto out;
  	} else {
  		err = -ESRCH;
ee0acf90d   Oleg Nesterov   [PATCH] setpgid: ...
992
  		if (p != group_leader)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
993
994
995
996
997
998
  			goto out;
  	}
  
  	err = -EPERM;
  	if (p->signal->leader)
  		goto out;
4e021306c   Oleg Nesterov   sys_setpgid(): si...
999
  	pgrp = task_pid(p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1000
  	if (pgid != pid) {
b488893a3   Pavel Emelyanov   pid namespaces: c...
1001
  		struct task_struct *g;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1002

4e021306c   Oleg Nesterov   sys_setpgid(): si...
1003
1004
  		pgrp = find_vpid(pgid);
  		g = pid_task(pgrp, PIDTYPE_PGID);
41487c65b   Eric W. Biederman   [PATCH] pid: repl...
1005
  		if (!g || task_session(g) != task_session(group_leader))
f020bc468   Oleg Nesterov   [PATCH] sys_setpg...
1006
  			goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1007
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1008
1009
1010
  	err = security_task_setpgid(p, pgid);
  	if (err)
  		goto out;
1b0f7ffd0   Oleg Nesterov   pids: kill signal...
1011
  	if (task_pgrp(p) != pgrp)
83beaf3c6   Oleg Nesterov   pids: sys_setpgid...
1012
  		change_pid(p, PIDTYPE_PGID, pgrp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1013
1014
1015
1016
1017
  
  	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...
1018
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1019
1020
  	return err;
  }
dbf040d9d   Heiko Carstens   [CVE-2009-0029] S...
1021
  SYSCALL_DEFINE1(getpgid, pid_t, pid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1022
  {
12a3de0a9   Oleg Nesterov   pids: sys_getpgid...
1023
1024
1025
1026
1027
  	struct task_struct *p;
  	struct pid *grp;
  	int retval;
  
  	rcu_read_lock();
756184b7d   Cal Peake   [PATCH] CodingSty...
1028
  	if (!pid)
12a3de0a9   Oleg Nesterov   pids: sys_getpgid...
1029
  		grp = task_pgrp(current);
756184b7d   Cal Peake   [PATCH] CodingSty...
1030
  	else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1031
  		retval = -ESRCH;
12a3de0a9   Oleg Nesterov   pids: sys_getpgid...
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
  		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
1042
  	}
12a3de0a9   Oleg Nesterov   pids: sys_getpgid...
1043
1044
1045
1046
  	retval = pid_vnr(grp);
  out:
  	rcu_read_unlock();
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1047
1048
1049
  }
  
  #ifdef __ARCH_WANT_SYS_GETPGRP
dbf040d9d   Heiko Carstens   [CVE-2009-0029] S...
1050
  SYSCALL_DEFINE0(getpgrp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1051
  {
12a3de0a9   Oleg Nesterov   pids: sys_getpgid...
1052
  	return sys_getpgid(0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1053
1054
1055
  }
  
  #endif
dbf040d9d   Heiko Carstens   [CVE-2009-0029] S...
1056
  SYSCALL_DEFINE1(getsid, pid_t, pid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1057
  {
1dd768c08   Oleg Nesterov   pids: sys_getsid:...
1058
1059
1060
1061
1062
  	struct task_struct *p;
  	struct pid *sid;
  	int retval;
  
  	rcu_read_lock();
756184b7d   Cal Peake   [PATCH] CodingSty...
1063
  	if (!pid)
1dd768c08   Oleg Nesterov   pids: sys_getsid:...
1064
  		sid = task_session(current);
756184b7d   Cal Peake   [PATCH] CodingSty...
1065
  	else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1066
  		retval = -ESRCH;
1dd768c08   Oleg Nesterov   pids: sys_getsid:...
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
  		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
1077
  	}
1dd768c08   Oleg Nesterov   pids: sys_getsid:...
1078
1079
1080
1081
  	retval = pid_vnr(sid);
  out:
  	rcu_read_unlock();
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1082
  }
b290ebe2c   Heiko Carstens   [CVE-2009-0029] S...
1083
  SYSCALL_DEFINE0(setsid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1084
  {
e19f247a3   Oren Laadan   [PATCH] setpgid: ...
1085
  	struct task_struct *group_leader = current->group_leader;
e4cc0a9c8   Oleg Nesterov   fix setsid() for ...
1086
1087
  	struct pid *sid = task_pid(group_leader);
  	pid_t session = pid_vnr(sid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1088
  	int err = -EPERM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1089
  	write_lock_irq(&tasklist_lock);
390e2ff07   Eric W. Biederman   [PATCH] Make sets...
1090
1091
1092
  	/* Fail if I am already a session leader */
  	if (group_leader->signal->leader)
  		goto out;
430c62312   Oleg Nesterov   start the global ...
1093
1094
  	/* Fail if a process group id already exists that equals the
  	 * proposed session id.
390e2ff07   Eric W. Biederman   [PATCH] Make sets...
1095
  	 */
6806aac6d   Oleg Nesterov   sys_setsid: remov...
1096
  	if (pid_task(sid, PIDTYPE_PGID))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1097
  		goto out;
e19f247a3   Oren Laadan   [PATCH] setpgid: ...
1098
  	group_leader->signal->leader = 1;
8520d7c7f   Oleg Nesterov   teach set_special...
1099
  	__set_special_pids(sid);
24ec839c4   Peter Zijlstra   [PATCH] tty: ->si...
1100

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

e4cc0a9c8   Oleg Nesterov   fix setsid() for ...
1103
  	err = session;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1104
1105
  out:
  	write_unlock_irq(&tasklist_lock);
5091faa44   Mike Galbraith   sched: Add 'autog...
1106
  	if (err > 0) {
0d0df599f   Christian Borntraeger   connector: fix re...
1107
  		proc_sid_connector(group_leader);
5091faa44   Mike Galbraith   sched: Add 'autog...
1108
1109
  		sched_autogroup_create_attach(group_leader);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1110
1111
  	return err;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1112
  DECLARE_RWSEM(uts_sem);
e28cbf229   Christoph Hellwig   improve sys_newun...
1113
1114
  #ifdef COMPAT_UTS_MACHINE
  #define override_architecture(name) \
46da27664   Andreas Schwab   kernel/sys.c: fix...
1115
  	(personality(current->personality) == PER_LINUX32 && \
e28cbf229   Christoph Hellwig   improve sys_newun...
1116
1117
1118
1119
1120
  	 copy_to_user(name->machine, COMPAT_UTS_MACHINE, \
  		      sizeof(COMPAT_UTS_MACHINE)))
  #else
  #define override_architecture(name)	0
  #endif
be27425dc   Andi Kleen   Add a personality...
1121
1122
1123
1124
1125
1126
1127
  /*
   * 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
   */
  static int override_release(char __user *release, int len)
  {
  	int ret = 0;
a84a79e4d   Linus Torvalds   Avoid using varia...
1128
  	char buf[65];
be27425dc   Andi Kleen   Add a personality...
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
  
  	if (current->personality & UNAME26) {
  		char *rest = UTS_RELEASE;
  		int ndots = 0;
  		unsigned v;
  
  		while (*rest) {
  			if (*rest == '.' && ++ndots >= 3)
  				break;
  			if (!isdigit(*rest) && *rest != '.')
  				break;
  			rest++;
  		}
  		v = ((LINUX_VERSION_CODE >> 8) & 0xff) + 40;
  		snprintf(buf, len, "2.6.%u%s", v, rest);
  		ret = copy_to_user(release, buf, len);
  	}
  	return ret;
  }
e48fbb699   Heiko Carstens   [CVE-2009-0029] S...
1148
  SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1149
1150
1151
1152
  {
  	int errno = 0;
  
  	down_read(&uts_sem);
e9ff3990f   Serge E. Hallyn   [PATCH] namespace...
1153
  	if (copy_to_user(name, utsname(), sizeof *name))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1154
1155
  		errno = -EFAULT;
  	up_read(&uts_sem);
e28cbf229   Christoph Hellwig   improve sys_newun...
1156

be27425dc   Andi Kleen   Add a personality...
1157
1158
  	if (!errno && override_release(name->release, sizeof(name->release)))
  		errno = -EFAULT;
e28cbf229   Christoph Hellwig   improve sys_newun...
1159
1160
  	if (!errno && override_architecture(name))
  		errno = -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1161
1162
  	return errno;
  }
5cacdb4ad   Christoph Hellwig   Add generic sys_o...
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
  #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);
be27425dc   Andi Kleen   Add a personality...
1178
1179
  	if (!error && override_release(name->release, sizeof(name->release)))
  		error = -EFAULT;
5cacdb4ad   Christoph Hellwig   Add generic sys_o...
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
  	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;
be27425dc   Andi Kleen   Add a personality...
1214
1215
  	if (!error && override_release(name->release, sizeof(name->release)))
  		error = -EFAULT;
5cacdb4ad   Christoph Hellwig   Add generic sys_o...
1216
1217
1218
  	return error ? -EFAULT : 0;
  }
  #endif
5a8a82b1d   Heiko Carstens   [CVE-2009-0029] S...
1219
  SYSCALL_DEFINE2(sethostname, char __user *, name, int, len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1220
1221
1222
  {
  	int errno;
  	char tmp[__NEW_UTS_LEN];
bb96a6f50   Serge E. Hallyn   userns: allow set...
1223
  	if (!ns_capable(current->nsproxy->uts_ns->user_ns, CAP_SYS_ADMIN))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1224
  		return -EPERM;
fc832ad36   Serge E. Hallyn   userns: user name...
1225

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1226
1227
1228
1229
1230
  	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...
1231
1232
1233
1234
  		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
1235
1236
1237
1238
1239
1240
1241
  		errno = 0;
  	}
  	up_write(&uts_sem);
  	return errno;
  }
  
  #ifdef __ARCH_WANT_SYS_GETHOSTNAME
5a8a82b1d   Heiko Carstens   [CVE-2009-0029] S...
1242
  SYSCALL_DEFINE2(gethostname, char __user *, name, int, len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1243
1244
  {
  	int i, errno;
9679e4dd6   Andrew Morton   kernel/sys.c: imp...
1245
  	struct new_utsname *u;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1246
1247
1248
1249
  
  	if (len < 0)
  		return -EINVAL;
  	down_read(&uts_sem);
9679e4dd6   Andrew Morton   kernel/sys.c: imp...
1250
1251
  	u = utsname();
  	i = 1 + strlen(u->nodename);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1252
1253
1254
  	if (i > len)
  		i = len;
  	errno = 0;
9679e4dd6   Andrew Morton   kernel/sys.c: imp...
1255
  	if (copy_to_user(name, u->nodename, i))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
  		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...
1267
  SYSCALL_DEFINE2(setdomainname, char __user *, name, int, len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1268
1269
1270
  {
  	int errno;
  	char tmp[__NEW_UTS_LEN];
fc832ad36   Serge E. Hallyn   userns: user name...
1271
  	if (!ns_capable(current->nsproxy->uts_ns->user_ns, CAP_SYS_ADMIN))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1272
1273
1274
1275
1276
1277
1278
  		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...
1279
1280
1281
1282
  		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
1283
1284
1285
1286
1287
  		errno = 0;
  	}
  	up_write(&uts_sem);
  	return errno;
  }
e48fbb699   Heiko Carstens   [CVE-2009-0029] S...
1288
  SYSCALL_DEFINE2(getrlimit, unsigned int, resource, struct rlimit __user *, rlim)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1289
  {
b95183453   Jiri Slaby   rlimits: switch m...
1290
1291
1292
1293
1294
1295
1296
1297
  	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
1298
1299
1300
1301
1302
1303
1304
1305
  }
  
  #ifdef __ARCH_WANT_SYS_OLD_GETRLIMIT
  
  /*
   *	Back compatibility for getrlimit. Needed for some apps.
   */
   
e48fbb699   Heiko Carstens   [CVE-2009-0029] S...
1306
1307
  SYSCALL_DEFINE2(old_getrlimit, unsigned int, resource,
  		struct rlimit __user *, rlim)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1308
1309
1310
1311
1312
1313
1314
1315
  {
  	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...
1316
  	if (x.rlim_cur > 0x7FFFFFFF)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1317
  		x.rlim_cur = 0x7FFFFFFF;
756184b7d   Cal Peake   [PATCH] CodingSty...
1318
  	if (x.rlim_max > 0x7FFFFFFF)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1319
1320
1321
1322
1323
  		x.rlim_max = 0x7FFFFFFF;
  	return copy_to_user(rlim, &x, sizeof(x))?-EFAULT:0;
  }
  
  #endif
c022a0aca   Jiri Slaby   rlimits: implemen...
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
  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...
1356
  /* make sure you are allowed to change @tsk limits before calling this */
5b41535aa   Jiri Slaby   rlimits: redo do_...
1357
1358
  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
1359
  {
5b41535aa   Jiri Slaby   rlimits: redo do_...
1360
  	struct rlimit *rlim;
86f162f4c   Jiri Slaby   rlimits: do secur...
1361
  	int retval = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1362
1363
1364
  
  	if (resource >= RLIM_NLIMITS)
  		return -EINVAL;
5b41535aa   Jiri Slaby   rlimits: redo do_...
1365
1366
1367
1368
1369
1370
1371
  	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
1372

1c1e618dd   Jiri Slaby   rlimits: allow se...
1373
1374
1375
1376
1377
1378
  	/* 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_...
1379
  	rlim = tsk->signal->rlim + resource;
86f162f4c   Jiri Slaby   rlimits: do secur...
1380
  	task_lock(tsk->group_leader);
5b41535aa   Jiri Slaby   rlimits: redo do_...
1381
  	if (new_rlim) {
fc832ad36   Serge E. Hallyn   userns: user name...
1382
1383
  		/* Keep the capable check against init_user_ns until
  		   cgroups can contain all limits */
5b41535aa   Jiri Slaby   rlimits: redo do_...
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
  		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...
1405
  	}
7855c35da   Jiri Slaby   rlimits: split sy...
1406
  	task_unlock(tsk->group_leader);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1407

d3561f78f   Andrew Morton   [PATCH] RLIMIT_CP...
1408
1409
1410
1411
1412
1413
  	/*
  	 * 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_...
1414
1415
1416
  	 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...
1417
  out:
1c1e618dd   Jiri Slaby   rlimits: allow se...
1418
  	read_unlock(&tasklist_lock);
2fb9d2689   Oleg Nesterov   rlimits: make sur...
1419
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1420
  }
c022a0aca   Jiri Slaby   rlimits: implemen...
1421
1422
1423
1424
  /* 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...
1425
1426
  	if (current == task)
  		return 0;
c022a0aca   Jiri Slaby   rlimits: implemen...
1427

fc832ad36   Serge E. Hallyn   userns: user name...
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
  	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...
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
  }
  
  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...
1484
1485
1486
1487
1488
1489
  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_...
1490
  	return do_prlimit(current, resource, &new_rlim, NULL);
7855c35da   Jiri Slaby   rlimits: split sy...
1491
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1492
1493
1494
1495
1496
1497
1498
1499
  /*
   * 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
1500
1501
1502
1503
1504
1505
1506
   * 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...
1507
   *
de047c1bc   Ravikiran G Thirumalai   [PATCH] avoid tas...
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
   * 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...
1522
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1523
   */
f06febc96   Frank Mayhar   timers: fix itime...
1524
  static void accumulate_thread_rusage(struct task_struct *t, struct rusage *r)
679c9cd4a   Sripathi Kodi   add RUSAGE_THREAD
1525
  {
679c9cd4a   Sripathi Kodi   add RUSAGE_THREAD
1526
1527
1528
1529
1530
1531
1532
  	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
1533
1534
1535
1536
  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...
1537
  	cputime_t tgutime, tgstime, utime, stime;
1f10206cf   Jiri Pirko   getrusage: fill r...
1538
  	unsigned long maxrss = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1539
1540
  
  	memset((char *) r, 0, sizeof *r);
2dd0ebcd2   Ravikiran G Thirumalai   [PATCH] Avoid tak...
1541
  	utime = stime = cputime_zero;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1542

679c9cd4a   Sripathi Kodi   add RUSAGE_THREAD
1543
  	if (who == RUSAGE_THREAD) {
d180c5bcc   Hidetoshi Seto   sched: Introduce ...
1544
  		task_times(current, &utime, &stime);
f06febc96   Frank Mayhar   timers: fix itime...
1545
  		accumulate_thread_rusage(p, r);
1f10206cf   Jiri Pirko   getrusage: fill r...
1546
  		maxrss = p->signal->maxrss;
679c9cd4a   Sripathi Kodi   add RUSAGE_THREAD
1547
1548
  		goto out;
  	}
d6cf723a1   Oleg Nesterov   k_getrusage: don'...
1549
  	if (!lock_task_sighand(p, &flags))
de047c1bc   Ravikiran G Thirumalai   [PATCH] avoid tas...
1550
  		return;
0f59cc4a3   Oleg Nesterov   [PATCH] simplify ...
1551

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1552
  	switch (who) {
0f59cc4a3   Oleg Nesterov   [PATCH] simplify ...
1553
  		case RUSAGE_BOTH:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1554
  		case RUSAGE_CHILDREN:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1555
1556
1557
1558
1559
1560
  			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...
1561
1562
  			r->ru_inblock = p->signal->cinblock;
  			r->ru_oublock = p->signal->coublock;
1f10206cf   Jiri Pirko   getrusage: fill r...
1563
  			maxrss = p->signal->cmaxrss;
0f59cc4a3   Oleg Nesterov   [PATCH] simplify ...
1564
1565
1566
  
  			if (who == RUSAGE_CHILDREN)
  				break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1567
  		case RUSAGE_SELF:
0cf55e1ec   Hidetoshi Seto   sched, cputime: I...
1568
1569
1570
  			thread_group_times(p, &tgutime, &tgstime);
  			utime = cputime_add(utime, tgutime);
  			stime = cputime_add(stime, tgstime);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1571
1572
1573
1574
  			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...
1575
1576
  			r->ru_inblock += p->signal->inblock;
  			r->ru_oublock += p->signal->oublock;
1f10206cf   Jiri Pirko   getrusage: fill r...
1577
1578
  			if (maxrss < p->signal->maxrss)
  				maxrss = p->signal->maxrss;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1579
1580
  			t = p;
  			do {
f06febc96   Frank Mayhar   timers: fix itime...
1581
  				accumulate_thread_rusage(t, r);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1582
1583
  				t = next_thread(t);
  			} while (t != p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1584
  			break;
0f59cc4a3   Oleg Nesterov   [PATCH] simplify ...
1585

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1586
1587
1588
  		default:
  			BUG();
  	}
de047c1bc   Ravikiran G Thirumalai   [PATCH] avoid tas...
1589
  	unlock_task_sighand(p, &flags);
de047c1bc   Ravikiran G Thirumalai   [PATCH] avoid tas...
1590

679c9cd4a   Sripathi Kodi   add RUSAGE_THREAD
1591
  out:
0f59cc4a3   Oleg Nesterov   [PATCH] simplify ...
1592
1593
  	cputime_to_timeval(utime, &r->ru_utime);
  	cputime_to_timeval(stime, &r->ru_stime);
1f10206cf   Jiri Pirko   getrusage: fill r...
1594
1595
1596
1597
1598
1599
1600
1601
1602
  
  	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
1603
1604
1605
1606
1607
  }
  
  int getrusage(struct task_struct *p, int who, struct rusage __user *ru)
  {
  	struct rusage r;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1608
  	k_getrusage(p, who, &r);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1609
1610
  	return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0;
  }
e48fbb699   Heiko Carstens   [CVE-2009-0029] S...
1611
  SYSCALL_DEFINE2(getrusage, int, who, struct rusage __user *, ru)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1612
  {
679c9cd4a   Sripathi Kodi   add RUSAGE_THREAD
1613
1614
  	if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN &&
  	    who != RUSAGE_THREAD)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1615
1616
1617
  		return -EINVAL;
  	return getrusage(current, who, ru);
  }
e48fbb699   Heiko Carstens   [CVE-2009-0029] S...
1618
  SYSCALL_DEFINE1(umask, int, mask)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1619
1620
1621
1622
  {
  	mask = xchg(&current->fs->umask, mask & S_IRWXUGO);
  	return mask;
  }
3b7391de6   Serge E. Hallyn   capabilities: int...
1623

c4ea37c26   Heiko Carstens   [CVE-2009-0029] S...
1624
1625
  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
1626
  {
b6dff3ec5   David Howells   CRED: Separate ta...
1627
1628
1629
  	struct task_struct *me = current;
  	unsigned char comm[sizeof(me->comm)];
  	long error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1630

d84f4f992   David Howells   CRED: Inaugurate ...
1631
1632
  	error = security_task_prctl(option, arg2, arg3, arg4, arg5);
  	if (error != -ENOSYS)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1633
  		return error;
d84f4f992   David Howells   CRED: Inaugurate ...
1634
  	error = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1635
1636
  	switch (option) {
  		case PR_SET_PDEATHSIG:
0730ded5b   Jesper Juhl   [PATCH] remove a ...
1637
  			if (!valid_signal(arg2)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1638
1639
1640
  				error = -EINVAL;
  				break;
  			}
b6dff3ec5   David Howells   CRED: Separate ta...
1641
1642
  			me->pdeath_signal = arg2;
  			error = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1643
1644
  			break;
  		case PR_GET_PDEATHSIG:
b6dff3ec5   David Howells   CRED: Separate ta...
1645
  			error = put_user(me->pdeath_signal, (int __user *)arg2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1646
1647
  			break;
  		case PR_GET_DUMPABLE:
b6dff3ec5   David Howells   CRED: Separate ta...
1648
  			error = get_dumpable(me->mm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1649
1650
  			break;
  		case PR_SET_DUMPABLE:
abf75a503   Marcel Holtmann   [PATCH] Fix prctl...
1651
  			if (arg2 < 0 || arg2 > 1) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1652
1653
1654
  				error = -EINVAL;
  				break;
  			}
b6dff3ec5   David Howells   CRED: Separate ta...
1655
1656
  			set_dumpable(me->mm, arg2);
  			error = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1657
1658
1659
  			break;
  
  		case PR_SET_UNALIGN:
b6dff3ec5   David Howells   CRED: Separate ta...
1660
  			error = SET_UNALIGN_CTL(me, arg2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1661
1662
  			break;
  		case PR_GET_UNALIGN:
b6dff3ec5   David Howells   CRED: Separate ta...
1663
  			error = GET_UNALIGN_CTL(me, arg2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1664
1665
  			break;
  		case PR_SET_FPEMU:
b6dff3ec5   David Howells   CRED: Separate ta...
1666
  			error = SET_FPEMU_CTL(me, arg2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1667
1668
  			break;
  		case PR_GET_FPEMU:
b6dff3ec5   David Howells   CRED: Separate ta...
1669
  			error = GET_FPEMU_CTL(me, arg2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1670
1671
  			break;
  		case PR_SET_FPEXC:
b6dff3ec5   David Howells   CRED: Separate ta...
1672
  			error = SET_FPEXC_CTL(me, arg2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1673
1674
  			break;
  		case PR_GET_FPEXC:
b6dff3ec5   David Howells   CRED: Separate ta...
1675
  			error = GET_FPEXC_CTL(me, arg2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1676
1677
1678
1679
1680
  			break;
  		case PR_GET_TIMING:
  			error = PR_TIMING_STATISTICAL;
  			break;
  		case PR_SET_TIMING:
7b26655f6   Shi Weihua   sys_prctl(): fix ...
1681
  			if (arg2 != PR_TIMING_STATISTICAL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1682
  				error = -EINVAL;
b6dff3ec5   David Howells   CRED: Separate ta...
1683
1684
  			else
  				error = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1685
  			break;
b6dff3ec5   David Howells   CRED: Separate ta...
1686
1687
1688
1689
  		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
1690
  				return -EFAULT;
b6dff3ec5   David Howells   CRED: Separate ta...
1691
  			set_task_comm(me, comm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1692
  			return 0;
b6dff3ec5   David Howells   CRED: Separate ta...
1693
1694
1695
1696
  		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
1697
1698
  				return -EFAULT;
  			return 0;
651d765d0   Anton Blanchard   [PATCH] Add a prc...
1699
  		case PR_GET_ENDIAN:
b6dff3ec5   David Howells   CRED: Separate ta...
1700
  			error = GET_ENDIAN(me, arg2);
651d765d0   Anton Blanchard   [PATCH] Add a prc...
1701
1702
  			break;
  		case PR_SET_ENDIAN:
b6dff3ec5   David Howells   CRED: Separate ta...
1703
  			error = SET_ENDIAN(me, arg2);
651d765d0   Anton Blanchard   [PATCH] Add a prc...
1704
  			break;
1d9d02fee   Andrea Arcangeli   move seccomp from...
1705
1706
1707
1708
1709
1710
  		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...
1711
1712
1713
1714
1715
1716
  		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 ...
1717
1718
  		case PR_TASK_PERF_EVENTS_DISABLE:
  			error = perf_event_task_disable();
1d1c7ddbf   Ingo Molnar   perf counters: ad...
1719
  			break;
cdd6c482c   Ingo Molnar   perf: Do the big ...
1720
1721
  		case PR_TASK_PERF_EVENTS_ENABLE:
  			error = perf_event_task_enable();
1d1c7ddbf   Ingo Molnar   perf counters: ad...
1722
  			break;
6976675d9   Arjan van de Ven   hrtimer: create a...
1723
1724
1725
1726
1727
1728
1729
1730
1731
  		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...
1732
  			error = 0;
6976675d9   Arjan van de Ven   hrtimer: create a...
1733
  			break;
4db96cf07   Andi Kleen   HWPOISON: Add PR_...
1734
1735
1736
1737
  		case PR_MCE_KILL:
  			if (arg4 | arg5)
  				return -EINVAL;
  			switch (arg2) {
1087e9b4f   Andi Kleen   HWPOISON: Clean u...
1738
  			case PR_MCE_KILL_CLEAR:
4db96cf07   Andi Kleen   HWPOISON: Add PR_...
1739
1740
1741
1742
  				if (arg3 != 0)
  					return -EINVAL;
  				current->flags &= ~PF_MCE_PROCESS;
  				break;
1087e9b4f   Andi Kleen   HWPOISON: Clean u...
1743
  			case PR_MCE_KILL_SET:
4db96cf07   Andi Kleen   HWPOISON: Add PR_...
1744
  				current->flags |= PF_MCE_PROCESS;
1087e9b4f   Andi Kleen   HWPOISON: Clean u...
1745
  				if (arg3 == PR_MCE_KILL_EARLY)
4db96cf07   Andi Kleen   HWPOISON: Add PR_...
1746
  					current->flags |= PF_MCE_EARLY;
1087e9b4f   Andi Kleen   HWPOISON: Clean u...
1747
  				else if (arg3 == PR_MCE_KILL_LATE)
4db96cf07   Andi Kleen   HWPOISON: Add PR_...
1748
  					current->flags &= ~PF_MCE_EARLY;
1087e9b4f   Andi Kleen   HWPOISON: Clean u...
1749
1750
1751
1752
1753
  				else if (arg3 == PR_MCE_KILL_DEFAULT)
  					current->flags &=
  						~(PF_MCE_EARLY|PF_MCE_PROCESS);
  				else
  					return -EINVAL;
4db96cf07   Andi Kleen   HWPOISON: Add PR_...
1754
1755
1756
1757
1758
1759
  				break;
  			default:
  				return -EINVAL;
  			}
  			error = 0;
  			break;
1087e9b4f   Andi Kleen   HWPOISON: Clean u...
1760
1761
1762
1763
1764
1765
1766
1767
1768
  		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
1769
1770
1771
1772
1773
1774
  		default:
  			error = -EINVAL;
  			break;
  	}
  	return error;
  }
3cfc348bf   Andi Kleen   [PATCH] x86: Add ...
1775

836f92adf   Heiko Carstens   [CVE-2009-0029] S...
1776
1777
  SYSCALL_DEFINE3(getcpu, unsigned __user *, cpup, unsigned __user *, nodep,
  		struct getcpu_cache __user *, unused)
3cfc348bf   Andi Kleen   [PATCH] x86: Add ...
1778
1779
1780
1781
1782
1783
1784
  {
  	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 ...
1785
1786
  	return err ? -EFAULT : 0;
  }
10a0a8d4e   Jeremy Fitzhardinge   Add common orderl...
1787
1788
  
  char poweroff_cmd[POWEROFF_CMD_PATH_LEN] = "/sbin/poweroff";
a06a4dc3a   Neil Horman   kmod: add init fu...
1789
  static void argv_cleanup(struct subprocess_info *info)
10a0a8d4e   Jeremy Fitzhardinge   Add common orderl...
1790
  {
a06a4dc3a   Neil Horman   kmod: add init fu...
1791
  	argv_free(info->argv);
10a0a8d4e   Jeremy Fitzhardinge   Add common orderl...
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
  }
  
  /**
   * 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...
1819
  	info = call_usermodehelper_setup(argv[0], argv, envp, GFP_ATOMIC);
10a0a8d4e   Jeremy Fitzhardinge   Add common orderl...
1820
1821
1822
1823
  	if (info == NULL) {
  		argv_free(argv);
  		goto out;
  	}
a06a4dc3a   Neil Horman   kmod: add init fu...
1824
  	call_usermodehelper_setfns(info, NULL, argv_cleanup, NULL);
10a0a8d4e   Jeremy Fitzhardinge   Add common orderl...
1825

86313c488   Jeremy Fitzhardinge   usermodehelper: T...
1826
  	ret = call_usermodehelper_exec(info, UMH_NO_WAIT);
10a0a8d4e   Jeremy Fitzhardinge   Add common orderl...
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
  
    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);