Blame view

kernel/sys.c 46.6 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
  /*
   *  linux/kernel/sys.c
   *
   *  Copyright (C) 1991, 1992  Linus Torvalds
   */
9984de1a5   Paul Gortmaker   kernel: Map most ...
6
  #include <linux/export.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7
8
9
  #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>
74da1ff71   Paul Gortmaker   kernel: fix sever...
14
  #include <linux/kmod.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>
be27425dc   Andi Kleen   Add a personality...
40
41
  #include <linux/version.h>
  #include <linux/ctype.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
43
44
  
  #include <linux/compat.h>
  #include <linux/syscalls.h>
00d7c05ab   Keshavamurthy Anil S   [PATCH] kprobes: ...
45
  #include <linux/kprobes.h>
acce292c8   Cedric Le Goater   user namespace: a...
46
  #include <linux/user_namespace.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

e4cc0a9c8   Oleg Nesterov   fix setsid() for ...
1104
  	err = session;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1105
1106
  out:
  	write_unlock_irq(&tasklist_lock);
5091faa44   Mike Galbraith   sched: Add 'autog...
1107
  	if (err > 0) {
0d0df599f   Christian Borntraeger   connector: fix re...
1108
  		proc_sid_connector(group_leader);
5091faa44   Mike Galbraith   sched: Add 'autog...
1109
1110
  		sched_autogroup_create_attach(group_leader);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1111
1112
  	return err;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1113
  DECLARE_RWSEM(uts_sem);
e28cbf229   Christoph Hellwig   improve sys_newun...
1114
1115
  #ifdef COMPAT_UTS_MACHINE
  #define override_architecture(name) \
46da27664   Andreas Schwab   kernel/sys.c: fix...
1116
  	(personality(current->personality) == PER_LINUX32 && \
e28cbf229   Christoph Hellwig   improve sys_newun...
1117
1118
1119
1120
1121
  	 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...
1122
1123
1124
1125
1126
1127
1128
  /*
   * 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...
1129
  	char buf[65];
be27425dc   Andi Kleen   Add a personality...
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
  
  	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...
1149
  SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1150
1151
1152
1153
  {
  	int errno = 0;
  
  	down_read(&uts_sem);
e9ff3990f   Serge E. Hallyn   [PATCH] namespace...
1154
  	if (copy_to_user(name, utsname(), sizeof *name))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1155
1156
  		errno = -EFAULT;
  	up_read(&uts_sem);
e28cbf229   Christoph Hellwig   improve sys_newun...
1157

be27425dc   Andi Kleen   Add a personality...
1158
1159
  	if (!errno && override_release(name->release, sizeof(name->release)))
  		errno = -EFAULT;
e28cbf229   Christoph Hellwig   improve sys_newun...
1160
1161
  	if (!errno && override_architecture(name))
  		errno = -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1162
1163
  	return errno;
  }
5cacdb4ad   Christoph Hellwig   Add generic sys_o...
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
  #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...
1179
1180
  	if (!error && override_release(name->release, sizeof(name->release)))
  		error = -EFAULT;
5cacdb4ad   Christoph Hellwig   Add generic sys_o...
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
1214
  	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...
1215
1216
  	if (!error && override_release(name->release, sizeof(name->release)))
  		error = -EFAULT;
5cacdb4ad   Christoph Hellwig   Add generic sys_o...
1217
1218
1219
  	return error ? -EFAULT : 0;
  }
  #endif
5a8a82b1d   Heiko Carstens   [CVE-2009-0029] S...
1220
  SYSCALL_DEFINE2(sethostname, char __user *, name, int, len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1221
1222
1223
  {
  	int errno;
  	char tmp[__NEW_UTS_LEN];
bb96a6f50   Serge E. Hallyn   userns: allow set...
1224
  	if (!ns_capable(current->nsproxy->uts_ns->user_ns, CAP_SYS_ADMIN))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1225
  		return -EPERM;
fc832ad36   Serge E. Hallyn   userns: user name...
1226

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

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

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

fc832ad36   Serge E. Hallyn   userns: user name...
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
  	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...
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
1484
1485
1486
  }
  
  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...
1487
1488
1489
1490
1491
1492
  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_...
1493
  	return do_prlimit(current, resource, &new_rlim, NULL);
7855c35da   Jiri Slaby   rlimits: split sy...
1494
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1495
1496
1497
1498
1499
1500
1501
1502
  /*
   * 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
1503
1504
1505
1506
1507
1508
1509
   * 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...
1510
   *
de047c1bc   Ravikiran G Thirumalai   [PATCH] avoid tas...
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
   * 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...
1525
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1526
   */
f06febc96   Frank Mayhar   timers: fix itime...
1527
  static void accumulate_thread_rusage(struct task_struct *t, struct rusage *r)
679c9cd4a   Sripathi Kodi   add RUSAGE_THREAD
1528
  {
679c9cd4a   Sripathi Kodi   add RUSAGE_THREAD
1529
1530
1531
1532
1533
1534
1535
  	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
1536
1537
1538
1539
  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...
1540
  	cputime_t tgutime, tgstime, utime, stime;
1f10206cf   Jiri Pirko   getrusage: fill r...
1541
  	unsigned long maxrss = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1542
1543
  
  	memset((char *) r, 0, sizeof *r);
648616343   Martin Schwidefsky   [S390] cputime: a...
1544
  	utime = stime = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1545

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

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

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

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

028ee4be3   Cyrill Gorcunov   c/r: prctl: add P...
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
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
  #ifdef CONFIG_CHECKPOINT_RESTORE
  static int prctl_set_mm(int opt, unsigned long addr,
  			unsigned long arg4, unsigned long arg5)
  {
  	unsigned long rlim = rlimit(RLIMIT_DATA);
  	unsigned long vm_req_flags;
  	unsigned long vm_bad_flags;
  	struct vm_area_struct *vma;
  	int error = 0;
  	struct mm_struct *mm = current->mm;
  
  	if (arg4 | arg5)
  		return -EINVAL;
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
  
  	if (addr >= TASK_SIZE)
  		return -EINVAL;
  
  	down_read(&mm->mmap_sem);
  	vma = find_vma(mm, addr);
  
  	if (opt != PR_SET_MM_START_BRK && opt != PR_SET_MM_BRK) {
  		/* It must be existing VMA */
  		if (!vma || vma->vm_start > addr)
  			goto out;
  	}
  
  	error = -EINVAL;
  	switch (opt) {
  	case PR_SET_MM_START_CODE:
  	case PR_SET_MM_END_CODE:
  		vm_req_flags = VM_READ | VM_EXEC;
  		vm_bad_flags = VM_WRITE | VM_MAYSHARE;
  
  		if ((vma->vm_flags & vm_req_flags) != vm_req_flags ||
  		    (vma->vm_flags & vm_bad_flags))
  			goto out;
  
  		if (opt == PR_SET_MM_START_CODE)
  			mm->start_code = addr;
  		else
  			mm->end_code = addr;
  		break;
  
  	case PR_SET_MM_START_DATA:
  	case PR_SET_MM_END_DATA:
  		vm_req_flags = VM_READ | VM_WRITE;
  		vm_bad_flags = VM_EXEC | VM_MAYSHARE;
  
  		if ((vma->vm_flags & vm_req_flags) != vm_req_flags ||
  		    (vma->vm_flags & vm_bad_flags))
  			goto out;
  
  		if (opt == PR_SET_MM_START_DATA)
  			mm->start_data = addr;
  		else
  			mm->end_data = addr;
  		break;
  
  	case PR_SET_MM_START_STACK:
  
  #ifdef CONFIG_STACK_GROWSUP
  		vm_req_flags = VM_READ | VM_WRITE | VM_GROWSUP;
  #else
  		vm_req_flags = VM_READ | VM_WRITE | VM_GROWSDOWN;
  #endif
  		if ((vma->vm_flags & vm_req_flags) != vm_req_flags)
  			goto out;
  
  		mm->start_stack = addr;
  		break;
  
  	case PR_SET_MM_START_BRK:
  		if (addr <= mm->end_data)
  			goto out;
  
  		if (rlim < RLIM_INFINITY &&
  		    (mm->brk - addr) +
  		    (mm->end_data - mm->start_data) > rlim)
  			goto out;
  
  		mm->start_brk = addr;
  		break;
  
  	case PR_SET_MM_BRK:
  		if (addr <= mm->end_data)
  			goto out;
  
  		if (rlim < RLIM_INFINITY &&
  		    (addr - mm->start_brk) +
  		    (mm->end_data - mm->start_data) > rlim)
  			goto out;
  
  		mm->brk = addr;
  		break;
  
  	default:
  		error = -EINVAL;
  		goto out;
  	}
  
  	error = 0;
  
  out:
  	up_read(&mm->mmap_sem);
  
  	return error;
  }
  #else /* CONFIG_CHECKPOINT_RESTORE */
  static int prctl_set_mm(int opt, unsigned long addr,
  			unsigned long arg4, unsigned long arg5)
  {
  	return -EINVAL;
  }
  #endif
c4ea37c26   Heiko Carstens   [CVE-2009-0029] S...
1744
1745
  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
1746
  {
b6dff3ec5   David Howells   CRED: Separate ta...
1747
1748
1749
  	struct task_struct *me = current;
  	unsigned char comm[sizeof(me->comm)];
  	long error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1750

d84f4f992   David Howells   CRED: Inaugurate ...
1751
1752
  	error = security_task_prctl(option, arg2, arg3, arg4, arg5);
  	if (error != -ENOSYS)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1753
  		return error;
d84f4f992   David Howells   CRED: Inaugurate ...
1754
  	error = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1755
1756
  	switch (option) {
  		case PR_SET_PDEATHSIG:
0730ded5b   Jesper Juhl   [PATCH] remove a ...
1757
  			if (!valid_signal(arg2)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1758
1759
1760
  				error = -EINVAL;
  				break;
  			}
b6dff3ec5   David Howells   CRED: Separate ta...
1761
1762
  			me->pdeath_signal = arg2;
  			error = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1763
1764
  			break;
  		case PR_GET_PDEATHSIG:
b6dff3ec5   David Howells   CRED: Separate ta...
1765
  			error = put_user(me->pdeath_signal, (int __user *)arg2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1766
1767
  			break;
  		case PR_GET_DUMPABLE:
b6dff3ec5   David Howells   CRED: Separate ta...
1768
  			error = get_dumpable(me->mm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1769
1770
  			break;
  		case PR_SET_DUMPABLE:
abf75a503   Marcel Holtmann   [PATCH] Fix prctl...
1771
  			if (arg2 < 0 || arg2 > 1) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1772
1773
1774
  				error = -EINVAL;
  				break;
  			}
b6dff3ec5   David Howells   CRED: Separate ta...
1775
1776
  			set_dumpable(me->mm, arg2);
  			error = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1777
1778
1779
  			break;
  
  		case PR_SET_UNALIGN:
b6dff3ec5   David Howells   CRED: Separate ta...
1780
  			error = SET_UNALIGN_CTL(me, arg2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1781
1782
  			break;
  		case PR_GET_UNALIGN:
b6dff3ec5   David Howells   CRED: Separate ta...
1783
  			error = GET_UNALIGN_CTL(me, arg2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1784
1785
  			break;
  		case PR_SET_FPEMU:
b6dff3ec5   David Howells   CRED: Separate ta...
1786
  			error = SET_FPEMU_CTL(me, arg2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1787
1788
  			break;
  		case PR_GET_FPEMU:
b6dff3ec5   David Howells   CRED: Separate ta...
1789
  			error = GET_FPEMU_CTL(me, arg2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1790
1791
  			break;
  		case PR_SET_FPEXC:
b6dff3ec5   David Howells   CRED: Separate ta...
1792
  			error = SET_FPEXC_CTL(me, arg2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1793
1794
  			break;
  		case PR_GET_FPEXC:
b6dff3ec5   David Howells   CRED: Separate ta...
1795
  			error = GET_FPEXC_CTL(me, arg2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1796
1797
1798
1799
1800
  			break;
  		case PR_GET_TIMING:
  			error = PR_TIMING_STATISTICAL;
  			break;
  		case PR_SET_TIMING:
7b26655f6   Shi Weihua   sys_prctl(): fix ...
1801
  			if (arg2 != PR_TIMING_STATISTICAL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1802
  				error = -EINVAL;
b6dff3ec5   David Howells   CRED: Separate ta...
1803
1804
  			else
  				error = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1805
  			break;
b6dff3ec5   David Howells   CRED: Separate ta...
1806
1807
1808
1809
  		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
1810
  				return -EFAULT;
b6dff3ec5   David Howells   CRED: Separate ta...
1811
  			set_task_comm(me, comm);
f786ecba4   Vladimir Zapolskiy   connector: add co...
1812
  			proc_comm_connector(me);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1813
  			return 0;
b6dff3ec5   David Howells   CRED: Separate ta...
1814
1815
1816
1817
  		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
1818
1819
  				return -EFAULT;
  			return 0;
651d765d0   Anton Blanchard   [PATCH] Add a prc...
1820
  		case PR_GET_ENDIAN:
b6dff3ec5   David Howells   CRED: Separate ta...
1821
  			error = GET_ENDIAN(me, arg2);
651d765d0   Anton Blanchard   [PATCH] Add a prc...
1822
1823
  			break;
  		case PR_SET_ENDIAN:
b6dff3ec5   David Howells   CRED: Separate ta...
1824
  			error = SET_ENDIAN(me, arg2);
651d765d0   Anton Blanchard   [PATCH] Add a prc...
1825
  			break;
1d9d02fee   Andrea Arcangeli   move seccomp from...
1826
1827
1828
1829
1830
1831
  		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...
1832
1833
1834
1835
1836
1837
  		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 ...
1838
1839
  		case PR_TASK_PERF_EVENTS_DISABLE:
  			error = perf_event_task_disable();
1d1c7ddbf   Ingo Molnar   perf counters: ad...
1840
  			break;
cdd6c482c   Ingo Molnar   perf: Do the big ...
1841
1842
  		case PR_TASK_PERF_EVENTS_ENABLE:
  			error = perf_event_task_enable();
1d1c7ddbf   Ingo Molnar   perf counters: ad...
1843
  			break;
6976675d9   Arjan van de Ven   hrtimer: create a...
1844
1845
1846
1847
1848
1849
1850
1851
1852
  		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...
1853
  			error = 0;
6976675d9   Arjan van de Ven   hrtimer: create a...
1854
  			break;
4db96cf07   Andi Kleen   HWPOISON: Add PR_...
1855
1856
1857
1858
  		case PR_MCE_KILL:
  			if (arg4 | arg5)
  				return -EINVAL;
  			switch (arg2) {
1087e9b4f   Andi Kleen   HWPOISON: Clean u...
1859
  			case PR_MCE_KILL_CLEAR:
4db96cf07   Andi Kleen   HWPOISON: Add PR_...
1860
1861
1862
1863
  				if (arg3 != 0)
  					return -EINVAL;
  				current->flags &= ~PF_MCE_PROCESS;
  				break;
1087e9b4f   Andi Kleen   HWPOISON: Clean u...
1864
  			case PR_MCE_KILL_SET:
4db96cf07   Andi Kleen   HWPOISON: Add PR_...
1865
  				current->flags |= PF_MCE_PROCESS;
1087e9b4f   Andi Kleen   HWPOISON: Clean u...
1866
  				if (arg3 == PR_MCE_KILL_EARLY)
4db96cf07   Andi Kleen   HWPOISON: Add PR_...
1867
  					current->flags |= PF_MCE_EARLY;
1087e9b4f   Andi Kleen   HWPOISON: Clean u...
1868
  				else if (arg3 == PR_MCE_KILL_LATE)
4db96cf07   Andi Kleen   HWPOISON: Add PR_...
1869
  					current->flags &= ~PF_MCE_EARLY;
1087e9b4f   Andi Kleen   HWPOISON: Clean u...
1870
1871
1872
1873
1874
  				else if (arg3 == PR_MCE_KILL_DEFAULT)
  					current->flags &=
  						~(PF_MCE_EARLY|PF_MCE_PROCESS);
  				else
  					return -EINVAL;
4db96cf07   Andi Kleen   HWPOISON: Add PR_...
1875
1876
1877
1878
1879
1880
  				break;
  			default:
  				return -EINVAL;
  			}
  			error = 0;
  			break;
1087e9b4f   Andi Kleen   HWPOISON: Clean u...
1881
1882
1883
1884
1885
1886
1887
1888
1889
  		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;
028ee4be3   Cyrill Gorcunov   c/r: prctl: add P...
1890
1891
1892
  		case PR_SET_MM:
  			error = prctl_set_mm(arg2, arg3, arg4, arg5);
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1893
1894
1895
1896
1897
1898
  		default:
  			error = -EINVAL;
  			break;
  	}
  	return error;
  }
3cfc348bf   Andi Kleen   [PATCH] x86: Add ...
1899

836f92adf   Heiko Carstens   [CVE-2009-0029] S...
1900
1901
  SYSCALL_DEFINE3(getcpu, unsigned __user *, cpup, unsigned __user *, nodep,
  		struct getcpu_cache __user *, unused)
3cfc348bf   Andi Kleen   [PATCH] x86: Add ...
1902
1903
1904
1905
1906
1907
1908
  {
  	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 ...
1909
1910
  	return err ? -EFAULT : 0;
  }
10a0a8d4e   Jeremy Fitzhardinge   Add common orderl...
1911
1912
  
  char poweroff_cmd[POWEROFF_CMD_PATH_LEN] = "/sbin/poweroff";
a06a4dc3a   Neil Horman   kmod: add init fu...
1913
  static void argv_cleanup(struct subprocess_info *info)
10a0a8d4e   Jeremy Fitzhardinge   Add common orderl...
1914
  {
a06a4dc3a   Neil Horman   kmod: add init fu...
1915
  	argv_free(info->argv);
10a0a8d4e   Jeremy Fitzhardinge   Add common orderl...
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
  }
  
  /**
   * 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...
1943
  	info = call_usermodehelper_setup(argv[0], argv, envp, GFP_ATOMIC);
10a0a8d4e   Jeremy Fitzhardinge   Add common orderl...
1944
1945
1946
1947
  	if (info == NULL) {
  		argv_free(argv);
  		goto out;
  	}
a06a4dc3a   Neil Horman   kmod: add init fu...
1948
  	call_usermodehelper_setfns(info, NULL, argv_cleanup, NULL);
10a0a8d4e   Jeremy Fitzhardinge   Add common orderl...
1949

86313c488   Jeremy Fitzhardinge   usermodehelper: T...
1950
  	ret = call_usermodehelper_exec(info, UMH_NO_WAIT);
10a0a8d4e   Jeremy Fitzhardinge   Add common orderl...
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
  
    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);