Blame view

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

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

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

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

dfc6a736d   H Hartley Sweeten   kernel/sys.c: fix...
210
  			do_each_thread(g, p) {
86a264abe   David Howells   CRED: Wrap curren...
211
  				if (__task_cred(p)->uid == who)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
212
  					error = set_one_prio(p, niceval, error);
dfc6a736d   H Hartley Sweeten   kernel/sys.c: fix...
213
  			} while_each_thread(g, p);
86a264abe   David Howells   CRED: Wrap curren...
214
  			if (who != cred->uid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
215
216
217
218
219
  				free_uid(user);		/* For find_user() */
  			break;
  	}
  out_unlock:
  	read_unlock(&tasklist_lock);
d4581a239   Thomas Gleixner   sys: Fix missing ...
220
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221
222
223
224
225
226
227
228
229
230
  out:
  	return error;
  }
  
  /*
   * Ugh. To avoid negative return values, "getpriority()" will
   * not return the normal nice-value, but a negated value that
   * has been offset by 20 (ie it returns 40..1 instead of -20..19)
   * to stay compatible.
   */
754fe8d29   Heiko Carstens   [CVE-2009-0029] S...
231
  SYSCALL_DEFINE2(getpriority, int, which, int, who)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
232
233
234
  {
  	struct task_struct *g, *p;
  	struct user_struct *user;
86a264abe   David Howells   CRED: Wrap curren...
235
  	const struct cred *cred = current_cred();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
236
  	long niceval, retval = -ESRCH;
41487c65b   Eric W. Biederman   [PATCH] pid: repl...
237
  	struct pid *pgrp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238

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

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

4a00ea1e1   Eric W. Biederman   [PATCH] Refactor ...
358
  EXPORT_SYMBOL_GPL(kernel_halt);
e4c94330e   Eric W. Biederman   [PATCH] reboot: c...
359
360
361
362
363
  /**
   *	kernel_power_off - power_off the system
   *
   *	Shutdown everything and perform a clean system power_off.
   */
e4c94330e   Eric W. Biederman   [PATCH] reboot: c...
364
365
  void kernel_power_off(void)
  {
729b4d4ce   Alexey Starikovskiy   [ACPI] fix reboot...
366
  	kernel_shutdown_prepare(SYSTEM_POWER_OFF);
bd804eba1   Rafael J. Wysocki   PM: Introduce pm_...
367
368
  	if (pm_power_off_prepare)
  		pm_power_off_prepare();
4047727e5   Mark Lord   Fix SMP poweroff ...
369
  	disable_nonboot_cpus();
58b3b71df   Rafael J. Wysocki   Fix ThinkPad T42 ...
370
  	sysdev_shutdown();
40dc166cb   Rafael J. Wysocki   PM / Core: Introd...
371
  	syscore_shutdown();
4a00ea1e1   Eric W. Biederman   [PATCH] Refactor ...
372
373
  	printk(KERN_EMERG "Power down.
  ");
04c6862c0   Seiji Aguchi   kmsg_dump: add km...
374
  	kmsg_dump(KMSG_DUMP_POWEROFF);
4a00ea1e1   Eric W. Biederman   [PATCH] Refactor ...
375
376
377
  	machine_power_off();
  }
  EXPORT_SYMBOL_GPL(kernel_power_off);
6f15fa500   Thomas Gleixner   sys: Remove BKL f...
378
379
  
  static DEFINE_MUTEX(reboot_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
380
381
382
383
384
385
386
387
  /*
   * 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...
388
389
  SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
  		void __user *, arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
390
391
  {
  	char buffer[256];
3d26dcf76   Andi Kleen   kernel/sys.c: cle...
392
  	int ret = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
393
394
395
396
397
398
399
400
401
402
403
404
  
  	/* 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...
405
406
407
408
409
  	/* 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...
410
  	mutex_lock(&reboot_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
411
412
  	switch (cmd) {
  	case LINUX_REBOOT_CMD_RESTART:
4a00ea1e1   Eric W. Biederman   [PATCH] Refactor ...
413
  		kernel_restart(NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
414
415
416
417
418
419
420
421
422
423
424
  		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 ...
425
  		kernel_halt();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
426
  		do_exit(0);
3d26dcf76   Andi Kleen   kernel/sys.c: cle...
427
  		panic("cannot halt");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
428
429
  
  	case LINUX_REBOOT_CMD_POWER_OFF:
4a00ea1e1   Eric W. Biederman   [PATCH] Refactor ...
430
  		kernel_power_off();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
431
432
433
434
435
  		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...
436
437
  			ret = -EFAULT;
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
438
439
  		}
  		buffer[sizeof(buffer) - 1] = '\0';
4a00ea1e1   Eric W. Biederman   [PATCH] Refactor ...
440
  		kernel_restart(buffer);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
441
  		break;
3ab835213   Huang Ying   kexec jump
442
  #ifdef CONFIG_KEXEC
dc009d924   Eric W. Biederman   [PATCH] kexec: ad...
443
  	case LINUX_REBOOT_CMD_KEXEC:
3d26dcf76   Andi Kleen   kernel/sys.c: cle...
444
445
  		ret = kernel_kexec();
  		break;
3ab835213   Huang Ying   kexec jump
446
  #endif
4a00ea1e1   Eric W. Biederman   [PATCH] Refactor ...
447

b0cb1a19d   Rafael J. Wysocki   Replace CONFIG_SO...
448
  #ifdef CONFIG_HIBERNATION
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
449
  	case LINUX_REBOOT_CMD_SW_SUSPEND:
3d26dcf76   Andi Kleen   kernel/sys.c: cle...
450
451
  		ret = hibernate();
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
452
453
454
  #endif
  
  	default:
3d26dcf76   Andi Kleen   kernel/sys.c: cle...
455
456
  		ret = -EINVAL;
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
457
  	}
6f15fa500   Thomas Gleixner   sys: Remove BKL f...
458
  	mutex_unlock(&reboot_mutex);
3d26dcf76   Andi Kleen   kernel/sys.c: cle...
459
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
460
  }
65f27f384   David Howells   WorkStruct: Pass ...
461
  static void deferred_cad(struct work_struct *dummy)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
462
  {
abcd9e51f   Eric W. Biederman   [PATCH] Make ctrl...
463
  	kernel_restart(NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
464
465
466
467
468
469
470
471
472
  }
  
  /*
   * 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 ...
473
  	static DECLARE_WORK(cad_work, deferred_cad);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
474
475
476
477
  
  	if (C_A_D)
  		schedule_work(&cad_work);
  	else
9ec52099e   Cedric Le Goater   [PATCH] replace c...
478
  		kill_cad_pid(SIGINT, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
479
480
  }
  	
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
  /*
   * 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...
499
  SYSCALL_DEFINE2(setregid, gid_t, rgid, gid_t, egid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
500
  {
d84f4f992   David Howells   CRED: Inaugurate ...
501
502
  	const struct cred *old;
  	struct cred *new;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
503
  	int retval;
d84f4f992   David Howells   CRED: Inaugurate ...
504
505
506
507
  	new = prepare_creds();
  	if (!new)
  		return -ENOMEM;
  	old = current_cred();
d84f4f992   David Howells   CRED: Inaugurate ...
508
  	retval = -EPERM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
509
  	if (rgid != (gid_t) -1) {
d84f4f992   David Howells   CRED: Inaugurate ...
510
511
  		if (old->gid == rgid ||
  		    old->egid == rgid ||
fc832ad36   Serge E. Hallyn   userns: user name...
512
  		    nsown_capable(CAP_SETGID))
d84f4f992   David Howells   CRED: Inaugurate ...
513
  			new->gid = rgid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
514
  		else
d84f4f992   David Howells   CRED: Inaugurate ...
515
  			goto error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
516
517
  	}
  	if (egid != (gid_t) -1) {
d84f4f992   David Howells   CRED: Inaugurate ...
518
519
520
  		if (old->gid == egid ||
  		    old->egid == egid ||
  		    old->sgid == egid ||
fc832ad36   Serge E. Hallyn   userns: user name...
521
  		    nsown_capable(CAP_SETGID))
d84f4f992   David Howells   CRED: Inaugurate ...
522
  			new->egid = egid;
756184b7d   Cal Peake   [PATCH] CodingSty...
523
  		else
d84f4f992   David Howells   CRED: Inaugurate ...
524
  			goto error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
525
  	}
d84f4f992   David Howells   CRED: Inaugurate ...
526

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
527
  	if (rgid != (gid_t) -1 ||
d84f4f992   David Howells   CRED: Inaugurate ...
528
529
530
531
532
533
534
535
536
  	    (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
537
538
539
540
541
542
543
  }
  
  /*
   * setgid() is implemented like SysV w/ SAVED_IDS 
   *
   * SMP: Same implicit races as above.
   */
ae1251ab7   Heiko Carstens   [CVE-2009-0029] S...
544
  SYSCALL_DEFINE1(setgid, gid_t, gid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
545
  {
d84f4f992   David Howells   CRED: Inaugurate ...
546
547
  	const struct cred *old;
  	struct cred *new;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
548
  	int retval;
d84f4f992   David Howells   CRED: Inaugurate ...
549
550
551
552
  	new = prepare_creds();
  	if (!new)
  		return -ENOMEM;
  	old = current_cred();
d84f4f992   David Howells   CRED: Inaugurate ...
553
  	retval = -EPERM;
fc832ad36   Serge E. Hallyn   userns: user name...
554
  	if (nsown_capable(CAP_SETGID))
d84f4f992   David Howells   CRED: Inaugurate ...
555
556
557
  		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
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
562
563
564
565
  	return commit_creds(new);
  
  error:
  	abort_creds(new);
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
566
  }
54e991242   Dhaval Giani   sched: don't allo...
567

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

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

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

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

d84f4f992   David Howells   CRED: Inaugurate ...
681
682
683
684
685
  	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
686

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

d84f4f992   David Howells   CRED: Inaugurate ...
689
690
691
  error:
  	abort_creds(new);
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
692
693
694
695
696
697
698
  }
  
  
  /*
   * 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...
699
  SYSCALL_DEFINE3(setresuid, uid_t, ruid, uid_t, euid, uid_t, suid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
700
  {
d84f4f992   David Howells   CRED: Inaugurate ...
701
702
  	const struct cred *old;
  	struct cred *new;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
703
  	int retval;
d84f4f992   David Howells   CRED: Inaugurate ...
704
705
706
  	new = prepare_creds();
  	if (!new)
  		return -ENOMEM;
d84f4f992   David Howells   CRED: Inaugurate ...
707
  	old = current_cred();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
708

d84f4f992   David Howells   CRED: Inaugurate ...
709
  	retval = -EPERM;
fc832ad36   Serge E. Hallyn   userns: user name...
710
  	if (!nsown_capable(CAP_SETUID)) {
d84f4f992   David Howells   CRED: Inaugurate ...
711
712
713
714
715
716
717
718
719
  		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
720
  	}
d84f4f992   David Howells   CRED: Inaugurate ...
721

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

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

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

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

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

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

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

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

d84f4f992   David Howells   CRED: Inaugurate ...
838
839
  change_okay:
  	commit_creds(new);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
840
841
842
843
  	return old_fsuid;
  }
  
  /*
f42df9e65   John Anthony Kazos Jr   general: convert ...
844
   * Samma på svenska..
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
845
   */
ae1251ab7   Heiko Carstens   [CVE-2009-0029] S...
846
  SYSCALL_DEFINE1(setfsgid, gid_t, gid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
847
  {
d84f4f992   David Howells   CRED: Inaugurate ...
848
849
850
851
852
853
854
855
856
  	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
857

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

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

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

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

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

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

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

1c1e618dd   Jiri Slaby   rlimits: allow se...
1299
1300
1301
1302
1303
1304
  	/* 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_...
1305
  	rlim = tsk->signal->rlim + resource;
86f162f4c   Jiri Slaby   rlimits: do secur...
1306
  	task_lock(tsk->group_leader);
5b41535aa   Jiri Slaby   rlimits: redo do_...
1307
  	if (new_rlim) {
fc832ad36   Serge E. Hallyn   userns: user name...
1308
1309
  		/* Keep the capable check against init_user_ns until
  		   cgroups can contain all limits */
5b41535aa   Jiri Slaby   rlimits: redo do_...
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
  		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...
1331
  	}
7855c35da   Jiri Slaby   rlimits: split sy...
1332
  	task_unlock(tsk->group_leader);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1333

d3561f78f   Andrew Morton   [PATCH] RLIMIT_CP...
1334
1335
1336
1337
1338
1339
  	/*
  	 * 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_...
1340
1341
1342
  	 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...
1343
  out:
1c1e618dd   Jiri Slaby   rlimits: allow se...
1344
  	read_unlock(&tasklist_lock);
2fb9d2689   Oleg Nesterov   rlimits: make sur...
1345
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1346
  }
c022a0aca   Jiri Slaby   rlimits: implemen...
1347
1348
1349
1350
  /* 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...
1351
1352
  	if (current == task)
  		return 0;
c022a0aca   Jiri Slaby   rlimits: implemen...
1353

fc832ad36   Serge E. Hallyn   userns: user name...
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
  	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...
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
  }
  
  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...
1410
1411
1412
1413
1414
1415
  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_...
1416
  	return do_prlimit(current, resource, &new_rlim, NULL);
7855c35da   Jiri Slaby   rlimits: split sy...
1417
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1418
1419
1420
1421
1422
1423
1424
1425
  /*
   * 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
1426
1427
1428
1429
1430
1431
1432
   * 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...
1433
   *
de047c1bc   Ravikiran G Thirumalai   [PATCH] avoid tas...
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
   * 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...
1448
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1449
   */
f06febc96   Frank Mayhar   timers: fix itime...
1450
  static void accumulate_thread_rusage(struct task_struct *t, struct rusage *r)
679c9cd4a   Sripathi Kodi   add RUSAGE_THREAD
1451
  {
679c9cd4a   Sripathi Kodi   add RUSAGE_THREAD
1452
1453
1454
1455
1456
1457
1458
  	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
1459
1460
1461
1462
  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...
1463
  	cputime_t tgutime, tgstime, utime, stime;
1f10206cf   Jiri Pirko   getrusage: fill r...
1464
  	unsigned long maxrss = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1465
1466
  
  	memset((char *) r, 0, sizeof *r);
2dd0ebcd2   Ravikiran G Thirumalai   [PATCH] Avoid tak...
1467
  	utime = stime = cputime_zero;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1468

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

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

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

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

c4ea37c26   Heiko Carstens   [CVE-2009-0029] S...
1550
1551
  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
1552
  {
b6dff3ec5   David Howells   CRED: Separate ta...
1553
1554
1555
  	struct task_struct *me = current;
  	unsigned char comm[sizeof(me->comm)];
  	long error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1556

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

836f92adf   Heiko Carstens   [CVE-2009-0029] S...
1702
1703
  SYSCALL_DEFINE3(getcpu, unsigned __user *, cpup, unsigned __user *, nodep,
  		struct getcpu_cache __user *, unused)
3cfc348bf   Andi Kleen   [PATCH] x86: Add ...
1704
1705
1706
1707
1708
1709
1710
  {
  	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 ...
1711
1712
  	return err ? -EFAULT : 0;
  }
10a0a8d4e   Jeremy Fitzhardinge   Add common orderl...
1713
1714
  
  char poweroff_cmd[POWEROFF_CMD_PATH_LEN] = "/sbin/poweroff";
a06a4dc3a   Neil Horman   kmod: add init fu...
1715
  static void argv_cleanup(struct subprocess_info *info)
10a0a8d4e   Jeremy Fitzhardinge   Add common orderl...
1716
  {
a06a4dc3a   Neil Horman   kmod: add init fu...
1717
  	argv_free(info->argv);
10a0a8d4e   Jeremy Fitzhardinge   Add common orderl...
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
1744
  }
  
  /**
   * 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...
1745
  	info = call_usermodehelper_setup(argv[0], argv, envp, GFP_ATOMIC);
10a0a8d4e   Jeremy Fitzhardinge   Add common orderl...
1746
1747
1748
1749
  	if (info == NULL) {
  		argv_free(argv);
  		goto out;
  	}
a06a4dc3a   Neil Horman   kmod: add init fu...
1750
  	call_usermodehelper_setfns(info, NULL, argv_cleanup, NULL);
10a0a8d4e   Jeremy Fitzhardinge   Add common orderl...
1751

86313c488   Jeremy Fitzhardinge   usermodehelper: T...
1752
  	ret = call_usermodehelper_exec(info, UMH_NO_WAIT);
10a0a8d4e   Jeremy Fitzhardinge   Add common orderl...
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
  
    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);