Blame view

fs/exec.c 45.6 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  /*
   *  linux/fs/exec.c
   *
   *  Copyright (C) 1991, 1992  Linus Torvalds
   */
  
  /*
   * #!-checking implemented by tytso.
   */
  /*
   * Demand-loading implemented 01.12.91 - no need to read anything but
   * the header into memory. The inode of the executable is put into
   * "current->executable", and page faults do the actual loading. Clean.
   *
   * Once more I can proudly say that linux stood up to being changed: it
   * was less than 2 hours work to get demand-loading completely implemented.
   *
   * Demand loading changed July 1993 by Eric Youngdale.   Use mmap instead,
   * current->executable is only used by the procfs.  This allows a dispatch
   * table to check for several different types  of binary formats.  We keep
   * trying until we recognize the file or we run out of supported binary
   * formats. 
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
25
  #include <linux/slab.h>
  #include <linux/file.h>
9f3acc314   Al Viro   [PATCH] split lin...
26
  #include <linux/fdtable.h>
ba92a43db   Hugh Dickins   exec: remove some...
27
  #include <linux/mm.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
29
30
  #include <linux/stat.h>
  #include <linux/fcntl.h>
  #include <linux/smp_lock.h>
ba92a43db   Hugh Dickins   exec: remove some...
31
  #include <linux/swap.h>
74aadce98   Neil Horman   core_pattern: all...
32
  #include <linux/string.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33
  #include <linux/init.h>
ca5b172bd   Hugh Dickins   exec: include pag...
34
  #include <linux/pagemap.h>
cdd6c482c   Ingo Molnar   perf: Do the big ...
35
  #include <linux/perf_event.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
37
38
39
40
  #include <linux/highmem.h>
  #include <linux/spinlock.h>
  #include <linux/key.h>
  #include <linux/personality.h>
  #include <linux/binfmts.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
  #include <linux/utsname.h>
84d737866   Sukadev Bhattiprolu   [PATCH] add child...
42
  #include <linux/pid_namespace.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
43
44
45
  #include <linux/module.h>
  #include <linux/namei.h>
  #include <linux/proc_fs.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
47
48
  #include <linux/mount.h>
  #include <linux/security.h>
  #include <linux/syscalls.h>
8f0ab5147   Jay Lan   [PATCH] csa: conv...
49
  #include <linux/tsacct_kern.h>
9f46080c4   Matt Helsley   [PATCH] Process E...
50
  #include <linux/cn_proc.h>
473ae30bc   Al Viro   [PATCH] execve ar...
51
  #include <linux/audit.h>
6341c393f   Roland McGrath   tracehook: exec
52
  #include <linux/tracehook.h>
5f4123be3   Johannes Berg   remove CONFIG_KMO...
53
  #include <linux/kmod.h>
6110e3abb   Eric Paris   sys_execve and sy...
54
  #include <linux/fsnotify.h>
5ad4e53bd   Al Viro   Get rid of indire...
55
  #include <linux/fs_struct.h>
61be228a0   Neil Horman   exec: allow do_co...
56
  #include <linux/pipe_fs_i.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57
58
59
  
  #include <asm/uaccess.h>
  #include <asm/mmu_context.h>
b6a2fea39   Ollie Wild   mm: variable leng...
60
  #include <asm/tlb.h>
a6f76f23d   David Howells   CRED: Make execve...
61
  #include "internal.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
62

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
63
  int core_uses_pid;
71ce92f3f   Dan Aloni   make sysctl/kerne...
64
  char core_pattern[CORENAME_MAX_SIZE] = "core";
a293980c2   Neil Horman   exec: let do_core...
65
  unsigned int core_pipe_limit;
d6e711448   Alan Cox   [PATCH] setuid co...
66
  int suid_dumpable = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
67
  /* The maximal length of core_pattern is also specified in sysctl.c */
e4dc1b14d   Alexey Dobriyan   Use list_head in ...
68
  static LIST_HEAD(formats);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
  static DEFINE_RWLOCK(binfmt_lock);
74641f584   Ivan Kokshaysky   alpha: binfmt_aou...
70
  int __register_binfmt(struct linux_binfmt * fmt, int insert)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
71
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72
73
  	if (!fmt)
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74
  	write_lock(&binfmt_lock);
74641f584   Ivan Kokshaysky   alpha: binfmt_aou...
75
76
  	insert ? list_add(&fmt->lh, &formats) :
  		 list_add_tail(&fmt->lh, &formats);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
77
78
79
  	write_unlock(&binfmt_lock);
  	return 0;	
  }
74641f584   Ivan Kokshaysky   alpha: binfmt_aou...
80
  EXPORT_SYMBOL(__register_binfmt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
81

f6b450d48   Alexey Dobriyan   Make unregister_b...
82
  void unregister_binfmt(struct linux_binfmt * fmt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
83
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
84
  	write_lock(&binfmt_lock);
e4dc1b14d   Alexey Dobriyan   Use list_head in ...
85
  	list_del(&fmt->lh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86
  	write_unlock(&binfmt_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
  }
  
  EXPORT_SYMBOL(unregister_binfmt);
  
  static inline void put_binfmt(struct linux_binfmt * fmt)
  {
  	module_put(fmt->module);
  }
  
  /*
   * Note that a shared library must be both readable and executable due to
   * security reasons.
   *
   * Also note that we take the address to load from from the file itself.
   */
1e7bfb213   Heiko Carstens   [CVE-2009-0029] S...
102
  SYSCALL_DEFINE1(uselib, const char __user *, library)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
103
  {
964bd1836   Al Viro   [PATCH] get rid o...
104
  	struct file *file;
964bd1836   Al Viro   [PATCH] get rid o...
105
106
  	char *tmp = getname(library);
  	int error = PTR_ERR(tmp);
6e8341a11   Al Viro   Switch open_exec(...
107
108
109
110
111
112
113
114
115
  	if (IS_ERR(tmp))
  		goto out;
  
  	file = do_filp_open(AT_FDCWD, tmp,
  				O_LARGEFILE | O_RDONLY | FMODE_EXEC, 0,
  				MAY_READ | MAY_EXEC | MAY_OPEN);
  	putname(tmp);
  	error = PTR_ERR(file);
  	if (IS_ERR(file))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
116
117
118
  		goto out;
  
  	error = -EINVAL;
6e8341a11   Al Viro   Switch open_exec(...
119
  	if (!S_ISREG(file->f_path.dentry->d_inode->i_mode))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120
  		goto exit;
30524472c   Al Viro   [PATCH] take noex...
121
  	error = -EACCES;
6e8341a11   Al Viro   Switch open_exec(...
122
  	if (file->f_path.mnt->mnt_flags & MNT_NOEXEC)
6146f0d5e   Mimi Zohar   integrity: IMA hooks
123
  		goto exit;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
124

6110e3abb   Eric Paris   sys_execve and sy...
125
  	fsnotify_open(file->f_path.dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126
127
128
129
130
  	error = -ENOEXEC;
  	if(file->f_op) {
  		struct linux_binfmt * fmt;
  
  		read_lock(&binfmt_lock);
e4dc1b14d   Alexey Dobriyan   Use list_head in ...
131
  		list_for_each_entry(fmt, &formats, lh) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
132
133
134
135
136
137
138
139
140
141
142
143
144
  			if (!fmt->load_shlib)
  				continue;
  			if (!try_module_get(fmt->module))
  				continue;
  			read_unlock(&binfmt_lock);
  			error = fmt->load_shlib(file);
  			read_lock(&binfmt_lock);
  			put_binfmt(fmt);
  			if (error != -ENOEXEC)
  				break;
  		}
  		read_unlock(&binfmt_lock);
  	}
6e8341a11   Al Viro   Switch open_exec(...
145
  exit:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
146
147
148
  	fput(file);
  out:
    	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
149
  }
b6a2fea39   Ollie Wild   mm: variable leng...
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
  #ifdef CONFIG_MMU
  
  static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
  		int write)
  {
  	struct page *page;
  	int ret;
  
  #ifdef CONFIG_STACK_GROWSUP
  	if (write) {
  		ret = expand_stack_downwards(bprm->vma, pos);
  		if (ret < 0)
  			return NULL;
  	}
  #endif
  	ret = get_user_pages(current, bprm->mm, pos,
  			1, write, 1, &page, NULL);
  	if (ret <= 0)
  		return NULL;
  
  	if (write) {
b6a2fea39   Ollie Wild   mm: variable leng...
171
  		unsigned long size = bprm->vma->vm_end - bprm->vma->vm_start;
a64e715fc   Linus Torvalds   Allow ARG_MAX exe...
172
173
174
175
176
177
178
179
  		struct rlimit *rlim;
  
  		/*
  		 * We've historically supported up to 32 pages (ARG_MAX)
  		 * of argument strings even with small stacks
  		 */
  		if (size <= ARG_MAX)
  			return page;
b6a2fea39   Ollie Wild   mm: variable leng...
180
181
182
183
184
185
186
187
  
  		/*
  		 * Limit to 1/4-th the stack size for the argv+env strings.
  		 * This ensures that:
  		 *  - the remaining binfmt code will not run out of stack space,
  		 *  - the program will have a reasonable amount of stack left
  		 *    to work from.
  		 */
a64e715fc   Linus Torvalds   Allow ARG_MAX exe...
188
  		rlim = current->signal->rlim;
d554ed895   Jiri Slaby   fs: use rlimit he...
189
  		if (size > ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur) / 4) {
b6a2fea39   Ollie Wild   mm: variable leng...
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
  			put_page(page);
  			return NULL;
  		}
  	}
  
  	return page;
  }
  
  static void put_arg_page(struct page *page)
  {
  	put_page(page);
  }
  
  static void free_arg_page(struct linux_binprm *bprm, int i)
  {
  }
  
  static void free_arg_pages(struct linux_binprm *bprm)
  {
  }
  
  static void flush_arg_page(struct linux_binprm *bprm, unsigned long pos,
  		struct page *page)
  {
  	flush_cache_page(bprm->vma, pos, page_to_pfn(page));
  }
  
  static int __bprm_mm_init(struct linux_binprm *bprm)
  {
eaccbfa56   Luiz Fernando N. Capitulino   fs/exec.c:__bprm_...
219
  	int err;
b6a2fea39   Ollie Wild   mm: variable leng...
220
221
222
223
224
  	struct vm_area_struct *vma = NULL;
  	struct mm_struct *mm = bprm->mm;
  
  	bprm->vma = vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
  	if (!vma)
eaccbfa56   Luiz Fernando N. Capitulino   fs/exec.c:__bprm_...
225
  		return -ENOMEM;
b6a2fea39   Ollie Wild   mm: variable leng...
226
227
228
229
230
231
232
233
234
235
236
237
  
  	down_write(&mm->mmap_sem);
  	vma->vm_mm = mm;
  
  	/*
  	 * Place the stack at the largest stack address the architecture
  	 * supports. Later, we'll move this to an appropriate place. We don't
  	 * use STACK_TOP because that can depend on attributes which aren't
  	 * configured yet.
  	 */
  	vma->vm_end = STACK_TOP_MAX;
  	vma->vm_start = vma->vm_end - PAGE_SIZE;
b6a2fea39   Ollie Wild   mm: variable leng...
238
  	vma->vm_flags = VM_STACK_FLAGS;
3ed75eb8f   Coly Li   setup vma->vm_pag...
239
  	vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
5beb49305   Rik van Riel   mm: change anon_v...
240
  	INIT_LIST_HEAD(&vma->anon_vma_chain);
b6a2fea39   Ollie Wild   mm: variable leng...
241
  	err = insert_vm_struct(mm, vma);
eaccbfa56   Luiz Fernando N. Capitulino   fs/exec.c:__bprm_...
242
  	if (err)
b6a2fea39   Ollie Wild   mm: variable leng...
243
  		goto err;
b6a2fea39   Ollie Wild   mm: variable leng...
244
245
246
  
  	mm->stack_vm = mm->total_vm = 1;
  	up_write(&mm->mmap_sem);
b6a2fea39   Ollie Wild   mm: variable leng...
247
  	bprm->p = vma->vm_end - sizeof(void *);
b6a2fea39   Ollie Wild   mm: variable leng...
248
  	return 0;
b6a2fea39   Ollie Wild   mm: variable leng...
249
  err:
eaccbfa56   Luiz Fernando N. Capitulino   fs/exec.c:__bprm_...
250
251
252
  	up_write(&mm->mmap_sem);
  	bprm->vma = NULL;
  	kmem_cache_free(vm_area_cachep, vma);
b6a2fea39   Ollie Wild   mm: variable leng...
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
  	return err;
  }
  
  static bool valid_arg_len(struct linux_binprm *bprm, long len)
  {
  	return len <= MAX_ARG_STRLEN;
  }
  
  #else
  
  static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
  		int write)
  {
  	struct page *page;
  
  	page = bprm->page[pos / PAGE_SIZE];
  	if (!page && write) {
  		page = alloc_page(GFP_HIGHUSER|__GFP_ZERO);
  		if (!page)
  			return NULL;
  		bprm->page[pos / PAGE_SIZE] = page;
  	}
  
  	return page;
  }
  
  static void put_arg_page(struct page *page)
  {
  }
  
  static void free_arg_page(struct linux_binprm *bprm, int i)
  {
  	if (bprm->page[i]) {
  		__free_page(bprm->page[i]);
  		bprm->page[i] = NULL;
  	}
  }
  
  static void free_arg_pages(struct linux_binprm *bprm)
  {
  	int i;
  
  	for (i = 0; i < MAX_ARG_PAGES; i++)
  		free_arg_page(bprm, i);
  }
  
  static void flush_arg_page(struct linux_binprm *bprm, unsigned long pos,
  		struct page *page)
  {
  }
  
  static int __bprm_mm_init(struct linux_binprm *bprm)
  {
  	bprm->p = PAGE_SIZE * MAX_ARG_PAGES - sizeof(void *);
  	return 0;
  }
  
  static bool valid_arg_len(struct linux_binprm *bprm, long len)
  {
  	return len <= bprm->p;
  }
  
  #endif /* CONFIG_MMU */
  
  /*
   * Create a new mm_struct and populate it with a temporary stack
   * vm_area_struct.  We don't have enough context at this point to set the stack
   * flags, permissions, and offset, so we use temporary values.  We'll update
   * them later in setup_arg_pages().
   */
  int bprm_mm_init(struct linux_binprm *bprm)
  {
  	int err;
  	struct mm_struct *mm = NULL;
  
  	bprm->mm = mm = mm_alloc();
  	err = -ENOMEM;
  	if (!mm)
  		goto err;
  
  	err = init_new_context(current, mm);
  	if (err)
  		goto err;
  
  	err = __bprm_mm_init(bprm);
  	if (err)
  		goto err;
  
  	return 0;
  
  err:
  	if (mm) {
  		bprm->mm = NULL;
  		mmdrop(mm);
  	}
  
  	return err;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
  /*
   * count() counts the number of strings in array ARGV.
   */
  static int count(char __user * __user * argv, int max)
  {
  	int i = 0;
  
  	if (argv != NULL) {
  		for (;;) {
  			char __user * p;
  
  			if (get_user(p, argv))
  				return -EFAULT;
  			if (!p)
  				break;
  			argv++;
362e6663e   Jason Baron   exec.c, compat.c:...
367
  			if (i++ >= max)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
368
369
370
371
372
373
374
375
  				return -E2BIG;
  			cond_resched();
  		}
  	}
  	return i;
  }
  
  /*
b6a2fea39   Ollie Wild   mm: variable leng...
376
377
378
   * 'copy_strings()' copies argument/environment strings from the old
   * processes's memory to the new process's stack.  The call to get_user_pages()
   * ensures the destination page is created and not swapped out.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
379
   */
75c96f858   Adrian Bunk   [PATCH] make some...
380
381
  static int copy_strings(int argc, char __user * __user * argv,
  			struct linux_binprm *bprm)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
382
383
384
  {
  	struct page *kmapped_page = NULL;
  	char *kaddr = NULL;
b6a2fea39   Ollie Wild   mm: variable leng...
385
  	unsigned long kpos = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
386
387
388
389
390
391
392
393
  	int ret;
  
  	while (argc-- > 0) {
  		char __user *str;
  		int len;
  		unsigned long pos;
  
  		if (get_user(str, argv+argc) ||
b6a2fea39   Ollie Wild   mm: variable leng...
394
  				!(len = strnlen_user(str, MAX_ARG_STRLEN))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
395
396
397
  			ret = -EFAULT;
  			goto out;
  		}
b6a2fea39   Ollie Wild   mm: variable leng...
398
  		if (!valid_arg_len(bprm, len)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
399
400
401
  			ret = -E2BIG;
  			goto out;
  		}
b6a2fea39   Ollie Wild   mm: variable leng...
402
  		/* We're going to work our way backwords. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
403
  		pos = bprm->p;
b6a2fea39   Ollie Wild   mm: variable leng...
404
405
  		str += len;
  		bprm->p -= len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
406
407
  
  		while (len > 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
408
  			int offset, bytes_to_copy;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
409
410
  
  			offset = pos % PAGE_SIZE;
b6a2fea39   Ollie Wild   mm: variable leng...
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
  			if (offset == 0)
  				offset = PAGE_SIZE;
  
  			bytes_to_copy = offset;
  			if (bytes_to_copy > len)
  				bytes_to_copy = len;
  
  			offset -= bytes_to_copy;
  			pos -= bytes_to_copy;
  			str -= bytes_to_copy;
  			len -= bytes_to_copy;
  
  			if (!kmapped_page || kpos != (pos & PAGE_MASK)) {
  				struct page *page;
  
  				page = get_arg_page(bprm, pos, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
427
  				if (!page) {
b6a2fea39   Ollie Wild   mm: variable leng...
428
  					ret = -E2BIG;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
429
430
  					goto out;
  				}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
431

b6a2fea39   Ollie Wild   mm: variable leng...
432
433
  				if (kmapped_page) {
  					flush_kernel_dcache_page(kmapped_page);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
434
  					kunmap(kmapped_page);
b6a2fea39   Ollie Wild   mm: variable leng...
435
436
  					put_arg_page(kmapped_page);
  				}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
437
438
  				kmapped_page = page;
  				kaddr = kmap(kmapped_page);
b6a2fea39   Ollie Wild   mm: variable leng...
439
440
  				kpos = pos & PAGE_MASK;
  				flush_arg_page(bprm, kpos, kmapped_page);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
441
  			}
b6a2fea39   Ollie Wild   mm: variable leng...
442
  			if (copy_from_user(kaddr+offset, str, bytes_to_copy)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
443
444
445
  				ret = -EFAULT;
  				goto out;
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
446
447
448
449
  		}
  	}
  	ret = 0;
  out:
b6a2fea39   Ollie Wild   mm: variable leng...
450
451
  	if (kmapped_page) {
  		flush_kernel_dcache_page(kmapped_page);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
452
  		kunmap(kmapped_page);
b6a2fea39   Ollie Wild   mm: variable leng...
453
454
  		put_arg_page(kmapped_page);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
  	return ret;
  }
  
  /*
   * Like copy_strings, but get argv and its values from kernel memory.
   */
  int copy_strings_kernel(int argc,char ** argv, struct linux_binprm *bprm)
  {
  	int r;
  	mm_segment_t oldfs = get_fs();
  	set_fs(KERNEL_DS);
  	r = copy_strings(argc, (char __user * __user *)argv, bprm);
  	set_fs(oldfs);
  	return r;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
470
471
472
  EXPORT_SYMBOL(copy_strings_kernel);
  
  #ifdef CONFIG_MMU
b6a2fea39   Ollie Wild   mm: variable leng...
473

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
474
  /*
b6a2fea39   Ollie Wild   mm: variable leng...
475
476
477
   * During bprm_mm_init(), we create a temporary stack at STACK_TOP_MAX.  Once
   * the binfmt code determines where the new stack should reside, we shift it to
   * its final location.  The process proceeds as follows:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
478
   *
b6a2fea39   Ollie Wild   mm: variable leng...
479
480
481
482
483
484
   * 1) Use shift to calculate the new vma endpoints.
   * 2) Extend vma to cover both the old and new ranges.  This ensures the
   *    arguments passed to subsequent functions are consistent.
   * 3) Move vma's page tables to the new range.
   * 4) Free up any cleared pgd range.
   * 5) Shrink the vma to cover only the new range.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
485
   */
b6a2fea39   Ollie Wild   mm: variable leng...
486
  static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
487
488
  {
  	struct mm_struct *mm = vma->vm_mm;
b6a2fea39   Ollie Wild   mm: variable leng...
489
490
491
492
493
494
  	unsigned long old_start = vma->vm_start;
  	unsigned long old_end = vma->vm_end;
  	unsigned long length = old_end - old_start;
  	unsigned long new_start = old_start - shift;
  	unsigned long new_end = old_end - shift;
  	struct mmu_gather *tlb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
495

b6a2fea39   Ollie Wild   mm: variable leng...
496
  	BUG_ON(new_start > new_end);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
497

b6a2fea39   Ollie Wild   mm: variable leng...
498
499
500
501
502
503
504
505
506
507
  	/*
  	 * ensure there are no vmas between where we want to go
  	 * and where we are
  	 */
  	if (vma != find_vma(mm, new_start))
  		return -EFAULT;
  
  	/*
  	 * cover the whole range: [new_start, old_end)
  	 */
5beb49305   Rik van Riel   mm: change anon_v...
508
509
  	if (vma_adjust(vma, new_start, old_end, vma->vm_pgoff, NULL))
  		return -ENOMEM;
b6a2fea39   Ollie Wild   mm: variable leng...
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
  
  	/*
  	 * move the page tables downwards, on failure we rely on
  	 * process cleanup to remove whatever mess we made.
  	 */
  	if (length != move_page_tables(vma, old_start,
  				       vma, new_start, length))
  		return -ENOMEM;
  
  	lru_add_drain();
  	tlb = tlb_gather_mmu(mm, 0);
  	if (new_end > old_start) {
  		/*
  		 * when the old and new regions overlap clear from new_end.
  		 */
42b777281   Jan Beulich   mm: remove double...
525
  		free_pgd_range(tlb, new_end, old_end, new_end,
b6a2fea39   Ollie Wild   mm: variable leng...
526
527
528
529
530
531
532
533
  			vma->vm_next ? vma->vm_next->vm_start : 0);
  	} else {
  		/*
  		 * otherwise, clean from old_start; this is done to not touch
  		 * the address space in [new_end, old_start) some architectures
  		 * have constraints on va-space that make this illegal (IA64) -
  		 * for the others its just a little faster.
  		 */
42b777281   Jan Beulich   mm: remove double...
534
  		free_pgd_range(tlb, old_start, old_end, new_end,
b6a2fea39   Ollie Wild   mm: variable leng...
535
  			vma->vm_next ? vma->vm_next->vm_start : 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
536
  	}
b6a2fea39   Ollie Wild   mm: variable leng...
537
538
539
  	tlb_finish_mmu(tlb, new_end, old_end);
  
  	/*
5beb49305   Rik van Riel   mm: change anon_v...
540
  	 * Shrink the vma to just the new range.  Always succeeds.
b6a2fea39   Ollie Wild   mm: variable leng...
541
542
543
544
  	 */
  	vma_adjust(vma, new_start, new_end, vma->vm_pgoff, NULL);
  
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
545
  }
b6a2fea39   Ollie Wild   mm: variable leng...
546
547
548
549
  /*
   * Finalizes the stack vm_area_struct. The flags and permissions are updated,
   * the stack is optionally relocated, and some extra space is added.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
550
551
552
553
  int setup_arg_pages(struct linux_binprm *bprm,
  		    unsigned long stack_top,
  		    int executable_stack)
  {
b6a2fea39   Ollie Wild   mm: variable leng...
554
555
  	unsigned long ret;
  	unsigned long stack_shift;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
556
  	struct mm_struct *mm = current->mm;
b6a2fea39   Ollie Wild   mm: variable leng...
557
558
559
560
  	struct vm_area_struct *vma = bprm->vma;
  	struct vm_area_struct *prev = NULL;
  	unsigned long vm_flags;
  	unsigned long stack_base;
803bf5ec2   Michael Neuling   fs/exec.c: restri...
561
562
563
  	unsigned long stack_size;
  	unsigned long stack_expand;
  	unsigned long rlim_stack;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
564
565
  
  #ifdef CONFIG_STACK_GROWSUP
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
566
  	/* Limit stack size to 1GB */
d554ed895   Jiri Slaby   fs: use rlimit he...
567
  	stack_base = rlimit_max(RLIMIT_STACK);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
568
569
  	if (stack_base > (1 << 30))
  		stack_base = 1 << 30;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
570

b6a2fea39   Ollie Wild   mm: variable leng...
571
572
573
  	/* Make sure we didn't let the argument array grow too large. */
  	if (vma->vm_end - vma->vm_start > stack_base)
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
574

b6a2fea39   Ollie Wild   mm: variable leng...
575
  	stack_base = PAGE_ALIGN(stack_top - stack_base);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
576

b6a2fea39   Ollie Wild   mm: variable leng...
577
578
579
  	stack_shift = vma->vm_start - stack_base;
  	mm->arg_start = bprm->p - stack_shift;
  	bprm->p = vma->vm_end - stack_shift;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
580
  #else
b6a2fea39   Ollie Wild   mm: variable leng...
581
582
583
584
585
  	stack_top = arch_align_stack(stack_top);
  	stack_top = PAGE_ALIGN(stack_top);
  	stack_shift = vma->vm_end - stack_top;
  
  	bprm->p -= stack_shift;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
586
  	mm->arg_start = bprm->p;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
587
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
588
  	if (bprm->loader)
b6a2fea39   Ollie Wild   mm: variable leng...
589
590
  		bprm->loader -= stack_shift;
  	bprm->exec -= stack_shift;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
591

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
592
  	down_write(&mm->mmap_sem);
96a8e13ed   Hugh Dickins   exec: fix stack e...
593
  	vm_flags = VM_STACK_FLAGS;
b6a2fea39   Ollie Wild   mm: variable leng...
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
  
  	/*
  	 * Adjust stack execute permissions; explicitly enable for
  	 * EXSTACK_ENABLE_X, disable for EXSTACK_DISABLE_X and leave alone
  	 * (arch default) otherwise.
  	 */
  	if (unlikely(executable_stack == EXSTACK_ENABLE_X))
  		vm_flags |= VM_EXEC;
  	else if (executable_stack == EXSTACK_DISABLE_X)
  		vm_flags &= ~VM_EXEC;
  	vm_flags |= mm->def_flags;
  
  	ret = mprotect_fixup(vma, &prev, vma->vm_start, vma->vm_end,
  			vm_flags);
  	if (ret)
  		goto out_unlock;
  	BUG_ON(prev != vma);
  
  	/* Move stack pages down in memory. */
  	if (stack_shift) {
  		ret = shift_arg_pages(vma, stack_shift);
fc63cf237   Anton Blanchard   exec: setup_arg_p...
615
616
  		if (ret)
  			goto out_unlock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
617
  	}
5ef097dd7   Michael Neuling   exec: create init...
618
  	stack_expand = 131072UL; /* randomly 32*4k (or 2*64k) pages */
803bf5ec2   Michael Neuling   fs/exec.c: restri...
619
620
621
622
623
624
  	stack_size = vma->vm_end - vma->vm_start;
  	/*
  	 * Align this down to a page boundary as expand_stack
  	 * will align it up.
  	 */
  	rlim_stack = rlimit(RLIMIT_STACK) & PAGE_MASK;
b6a2fea39   Ollie Wild   mm: variable leng...
625
  #ifdef CONFIG_STACK_GROWSUP
803bf5ec2   Michael Neuling   fs/exec.c: restri...
626
627
628
629
  	if (stack_size + stack_expand > rlim_stack)
  		stack_base = vma->vm_start + rlim_stack;
  	else
  		stack_base = vma->vm_end + stack_expand;
b6a2fea39   Ollie Wild   mm: variable leng...
630
  #else
803bf5ec2   Michael Neuling   fs/exec.c: restri...
631
632
633
634
  	if (stack_size + stack_expand > rlim_stack)
  		stack_base = vma->vm_end - rlim_stack;
  	else
  		stack_base = vma->vm_start - stack_expand;
b6a2fea39   Ollie Wild   mm: variable leng...
635
636
637
638
639
640
  #endif
  	ret = expand_stack(vma, stack_base);
  	if (ret)
  		ret = -EFAULT;
  
  out_unlock:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
641
  	up_write(&mm->mmap_sem);
fc63cf237   Anton Blanchard   exec: setup_arg_p...
642
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
643
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
644
  EXPORT_SYMBOL(setup_arg_pages);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
645
646
647
648
  #endif /* CONFIG_MMU */
  
  struct file *open_exec(const char *name)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
649
  	struct file *file;
e56b6a5dd   Christoph Hellwig   Re: [PATCH 3/6] v...
650
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
651

6e8341a11   Al Viro   Switch open_exec(...
652
653
654
655
  	file = do_filp_open(AT_FDCWD, name,
  				O_LARGEFILE | O_RDONLY | FMODE_EXEC, 0,
  				MAY_EXEC | MAY_OPEN);
  	if (IS_ERR(file))
e56b6a5dd   Christoph Hellwig   Re: [PATCH 3/6] v...
656
657
658
  		goto out;
  
  	err = -EACCES;
6e8341a11   Al Viro   Switch open_exec(...
659
660
  	if (!S_ISREG(file->f_path.dentry->d_inode->i_mode))
  		goto exit;
e56b6a5dd   Christoph Hellwig   Re: [PATCH 3/6] v...
661

6e8341a11   Al Viro   Switch open_exec(...
662
663
  	if (file->f_path.mnt->mnt_flags & MNT_NOEXEC)
  		goto exit;
e56b6a5dd   Christoph Hellwig   Re: [PATCH 3/6] v...
664

6110e3abb   Eric Paris   sys_execve and sy...
665
  	fsnotify_open(file->f_path.dentry);
e56b6a5dd   Christoph Hellwig   Re: [PATCH 3/6] v...
666
  	err = deny_write_access(file);
6e8341a11   Al Viro   Switch open_exec(...
667
668
  	if (err)
  		goto exit;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
669

6e8341a11   Al Viro   Switch open_exec(...
670
  out:
e56b6a5dd   Christoph Hellwig   Re: [PATCH 3/6] v...
671
  	return file;
6e8341a11   Al Viro   Switch open_exec(...
672
673
  exit:
  	fput(file);
e56b6a5dd   Christoph Hellwig   Re: [PATCH 3/6] v...
674
675
  	return ERR_PTR(err);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
676
  EXPORT_SYMBOL(open_exec);
6777d773a   Mimi Zohar   kernel_read: rede...
677
678
  int kernel_read(struct file *file, loff_t offset,
  		char *addr, unsigned long count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
  {
  	mm_segment_t old_fs;
  	loff_t pos = offset;
  	int result;
  
  	old_fs = get_fs();
  	set_fs(get_ds());
  	/* The cast to a user pointer is valid due to the set_fs() */
  	result = vfs_read(file, (void __user *)addr, count, &pos);
  	set_fs(old_fs);
  	return result;
  }
  
  EXPORT_SYMBOL(kernel_read);
  
  static int exec_mmap(struct mm_struct *mm)
  {
  	struct task_struct *tsk;
  	struct mm_struct * old_mm, *active_mm;
  
  	/* Notify parent that we're no longer interested in the old VM */
  	tsk = current;
  	old_mm = current->mm;
34e55232e   KAMEZAWA Hiroyuki   mm: avoid false s...
702
  	sync_mm_rss(tsk, old_mm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
703
704
705
706
707
708
709
  	mm_release(tsk, old_mm);
  
  	if (old_mm) {
  		/*
  		 * Make sure that if there is a core dump in progress
  		 * for the old mm, we get out and die instead of going
  		 * through with the exec.  We must hold mmap_sem around
999d9fc16   Oleg Nesterov   coredump: move mm...
710
  		 * checking core_state and changing tsk->mm.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
711
712
  		 */
  		down_read(&old_mm->mmap_sem);
999d9fc16   Oleg Nesterov   coredump: move mm...
713
  		if (unlikely(old_mm->core_state)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
714
715
716
717
718
719
720
721
722
723
724
725
726
  			up_read(&old_mm->mmap_sem);
  			return -EINTR;
  		}
  	}
  	task_lock(tsk);
  	active_mm = tsk->active_mm;
  	tsk->mm = mm;
  	tsk->active_mm = mm;
  	activate_mm(active_mm, mm);
  	task_unlock(tsk);
  	arch_pick_mmap_layout(mm);
  	if (old_mm) {
  		up_read(&old_mm->mmap_sem);
7dddb12c6   Eric Sesterhenn   BUG_ON() Conversi...
727
  		BUG_ON(active_mm != old_mm);
31a78f23b   Balbir Singh   mm owner: fix rac...
728
  		mm_update_next_owner(old_mm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
729
730
731
732
733
734
735
736
737
738
739
740
741
  		mmput(old_mm);
  		return 0;
  	}
  	mmdrop(active_mm);
  	return 0;
  }
  
  /*
   * This function makes sure the current process has its own signal table,
   * so that flush_signal_handlers can later reset the handlers without
   * disturbing other processes.  (Other processes might share the signal
   * table via the CLONE_SIGHAND option to clone().)
   */
858119e15   Arjan van de Ven   [PATCH] Unlinline...
742
  static int de_thread(struct task_struct *tsk)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
743
744
  {
  	struct signal_struct *sig = tsk->signal;
b2c903b87   Oleg Nesterov   exec: simplify th...
745
  	struct sighand_struct *oldsighand = tsk->sighand;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
746
747
  	spinlock_t *lock = &oldsighand->siglock;
  	int count;
aafe6c2a2   Eric W. Biederman   [PATCH] de_thread...
748
  	if (thread_group_empty(tsk))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
749
750
751
752
  		goto no_thread_group;
  
  	/*
  	 * Kill all other threads in the thread group.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
753
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
754
  	spin_lock_irq(lock);
ed5d2cac1   Oleg Nesterov   exec: rework the ...
755
  	if (signal_group_exit(sig)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
756
757
758
759
760
  		/*
  		 * Another group action in progress, just
  		 * return so that the signal is processed.
  		 */
  		spin_unlock_irq(lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
761
762
  		return -EAGAIN;
  	}
ed5d2cac1   Oleg Nesterov   exec: rework the ...
763
  	sig->group_exit_task = tsk;
aafe6c2a2   Eric W. Biederman   [PATCH] de_thread...
764
  	zap_other_threads(tsk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
765

fea9d1755   Oleg Nesterov   ITIMER_REAL: conv...
766
767
  	/* Account for the thread group leader hanging around: */
  	count = thread_group_leader(tsk) ? 1 : 2;
6db840fa7   Oleg Nesterov   exec: RT sub-thre...
768
  	sig->notify_count = count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
769
  	while (atomic_read(&sig->count) > count) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
770
771
772
773
774
  		__set_current_state(TASK_UNINTERRUPTIBLE);
  		spin_unlock_irq(lock);
  		schedule();
  		spin_lock_irq(lock);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
775
776
777
778
779
780
781
  	spin_unlock_irq(lock);
  
  	/*
  	 * At this point all other threads have exited, all we have to
  	 * do is to wait for the thread group leader to become inactive,
  	 * and to assume its PID:
  	 */
aafe6c2a2   Eric W. Biederman   [PATCH] de_thread...
782
  	if (!thread_group_leader(tsk)) {
8187926bd   Oleg Nesterov   posix-timers: sim...
783
  		struct task_struct *leader = tsk->group_leader;
6db840fa7   Oleg Nesterov   exec: RT sub-thre...
784

2800d8d19   Oleg Nesterov   document de_threa...
785
  		sig->notify_count = -1;	/* for exit_notify() */
6db840fa7   Oleg Nesterov   exec: RT sub-thre...
786
787
788
789
790
791
792
793
  		for (;;) {
  			write_lock_irq(&tasklist_lock);
  			if (likely(leader->exit_state))
  				break;
  			__set_current_state(TASK_UNINTERRUPTIBLE);
  			write_unlock_irq(&tasklist_lock);
  			schedule();
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
794

f5e902817   Roland McGrath   [PATCH] process a...
795
796
797
798
799
800
801
802
803
804
  		/*
  		 * The only record we have of the real-time age of a
  		 * process, regardless of execs it's done, is start_time.
  		 * All the past CPU time is accumulated in signal_struct
  		 * from sister threads now dead.  But in this non-leader
  		 * exec, nothing survives from the original leader thread,
  		 * whose birth marks the true age of this process now.
  		 * When we take on its identity by switching to its PID, we
  		 * also take its birthdate (always earlier than our own).
  		 */
aafe6c2a2   Eric W. Biederman   [PATCH] de_thread...
805
  		tsk->start_time = leader->start_time;
f5e902817   Roland McGrath   [PATCH] process a...
806

bac0abd61   Pavel Emelyanov   Isolate some expl...
807
808
  		BUG_ON(!same_thread_group(leader, tsk));
  		BUG_ON(has_group_leader_pid(tsk));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
809
810
811
812
813
814
  		/*
  		 * An exec() starts a new thread group with the
  		 * TGID of the previous thread group. Rehash the
  		 * two threads with a switched PID, and release
  		 * the former thread group leader:
  		 */
d73d65293   Eric W. Biederman   [PATCH] pidhash: ...
815
816
  
  		/* Become a process group leader with the old leader's pid.
c18258c6f   Eric W. Biederman   [PATCH] pid: Impl...
817
818
  		 * The old leader becomes a thread of the this thread group.
  		 * Note: The old leader also uses this pid until release_task
d73d65293   Eric W. Biederman   [PATCH] pidhash: ...
819
820
  		 *       is called.  Odd but simple and correct.
  		 */
aafe6c2a2   Eric W. Biederman   [PATCH] de_thread...
821
822
  		detach_pid(tsk, PIDTYPE_PID);
  		tsk->pid = leader->pid;
3743ca05f   Sukadev Bhattiprolu   pid namespaces: u...
823
  		attach_pid(tsk, PIDTYPE_PID,  task_pid(leader));
aafe6c2a2   Eric W. Biederman   [PATCH] de_thread...
824
825
  		transfer_pid(leader, tsk, PIDTYPE_PGID);
  		transfer_pid(leader, tsk, PIDTYPE_SID);
9cd80bbb0   Oleg Nesterov   do_wait() optimiz...
826

aafe6c2a2   Eric W. Biederman   [PATCH] de_thread...
827
  		list_replace_rcu(&leader->tasks, &tsk->tasks);
9cd80bbb0   Oleg Nesterov   do_wait() optimiz...
828
  		list_replace_init(&leader->sibling, &tsk->sibling);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
829

aafe6c2a2   Eric W. Biederman   [PATCH] de_thread...
830
831
  		tsk->group_leader = tsk;
  		leader->group_leader = tsk;
de12a7878   Eric W. Biederman   [PATCH] de_thread...
832

aafe6c2a2   Eric W. Biederman   [PATCH] de_thread...
833
  		tsk->exit_signal = SIGCHLD;
962b564cf   Oleg Nesterov   [PATCH] fix do_wa...
834
835
836
  
  		BUG_ON(leader->exit_state != EXIT_ZOMBIE);
  		leader->exit_state = EXIT_DEAD;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
837
  		write_unlock_irq(&tasklist_lock);
8187926bd   Oleg Nesterov   posix-timers: sim...
838
839
  
  		release_task(leader);
ed5d2cac1   Oleg Nesterov   exec: rework the ...
840
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
841

6db840fa7   Oleg Nesterov   exec: RT sub-thre...
842
843
  	sig->group_exit_task = NULL;
  	sig->notify_count = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
844
845
  
  no_thread_group:
1f10206cf   Jiri Pirko   getrusage: fill r...
846
847
  	if (current->mm)
  		setmax_mm_hiwater_rss(&sig->maxrss, current->mm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
848
  	exit_itimers(sig);
cbaffba12   Oleg Nesterov   posix timers: dis...
849
  	flush_itimer_signals();
329f7dba5   Oleg Nesterov   [PATCH] fix de_th...
850

b2c903b87   Oleg Nesterov   exec: simplify th...
851
852
  	if (atomic_read(&oldsighand->count) != 1) {
  		struct sighand_struct *newsighand;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
853
  		/*
b2c903b87   Oleg Nesterov   exec: simplify th...
854
855
  		 * This ->sighand is shared with the CLONE_SIGHAND
  		 * but not CLONE_THREAD task, switch to the new one.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
856
  		 */
b2c903b87   Oleg Nesterov   exec: simplify th...
857
858
859
  		newsighand = kmem_cache_alloc(sighand_cachep, GFP_KERNEL);
  		if (!newsighand)
  			return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
860
861
862
863
864
865
  		atomic_set(&newsighand->count, 1);
  		memcpy(newsighand->action, oldsighand->action,
  		       sizeof(newsighand->action));
  
  		write_lock_irq(&tasklist_lock);
  		spin_lock(&oldsighand->siglock);
aafe6c2a2   Eric W. Biederman   [PATCH] de_thread...
866
  		rcu_assign_pointer(tsk->sighand, newsighand);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
867
868
  		spin_unlock(&oldsighand->siglock);
  		write_unlock_irq(&tasklist_lock);
fba2afaae   Davide Libenzi   signal/timer/even...
869
  		__cleanup_sighand(oldsighand);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
870
  	}
aafe6c2a2   Eric W. Biederman   [PATCH] de_thread...
871
  	BUG_ON(!thread_group_leader(tsk));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
872
873
  	return 0;
  }
0840a90d9   Oleg Nesterov   exec: simplify ->...
874

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
875
876
877
878
  /*
   * These functions flushes out all traces of the currently running executable
   * so that a new one can be started
   */
858119e15   Arjan van de Ven   [PATCH] Unlinline...
879
  static void flush_old_files(struct files_struct * files)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
880
881
  {
  	long j = -1;
badf16621   Dipankar Sarma   [PATCH] files: br...
882
  	struct fdtable *fdt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
883
884
885
886
887
888
889
  
  	spin_lock(&files->file_lock);
  	for (;;) {
  		unsigned long set, i;
  
  		j++;
  		i = j * __NFDBITS;
badf16621   Dipankar Sarma   [PATCH] files: br...
890
  		fdt = files_fdtable(files);
bbea9f696   Vadim Lobanov   [PATCH] fdtable: ...
891
  		if (i >= fdt->max_fds)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
892
  			break;
badf16621   Dipankar Sarma   [PATCH] files: br...
893
  		set = fdt->close_on_exec->fds_bits[j];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
894
895
  		if (!set)
  			continue;
badf16621   Dipankar Sarma   [PATCH] files: br...
896
  		fdt->close_on_exec->fds_bits[j] = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
897
898
899
900
901
902
903
904
905
906
907
  		spin_unlock(&files->file_lock);
  		for ( ; set ; i++,set >>= 1) {
  			if (set & 1) {
  				sys_close(i);
  			}
  		}
  		spin_lock(&files->file_lock);
  
  	}
  	spin_unlock(&files->file_lock);
  }
59714d65d   Andrew Morton   get_task_comm(): ...
908
  char *get_task_comm(char *buf, struct task_struct *tsk)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
909
910
911
912
913
  {
  	/* buf must be at least sizeof(tsk->comm) in size */
  	task_lock(tsk);
  	strncpy(buf, tsk->comm, sizeof(tsk->comm));
  	task_unlock(tsk);
59714d65d   Andrew Morton   get_task_comm(): ...
914
  	return buf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
915
916
917
918
919
  }
  
  void set_task_comm(struct task_struct *tsk, char *buf)
  {
  	task_lock(tsk);
4614a696b   John Stultz   procfs: allow thr...
920
921
922
923
924
925
926
927
928
  
  	/*
  	 * Threads may access current->comm without holding
  	 * the task lock, so write the string carefully.
  	 * Readers without a lock may see incomplete new
  	 * names but are safe from non-terminating string reads.
  	 */
  	memset(tsk->comm, 0, TASK_COMM_LEN);
  	wmb();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
929
930
  	strlcpy(tsk->comm, buf, sizeof(tsk->comm));
  	task_unlock(tsk);
cdd6c482c   Ingo Molnar   perf: Do the big ...
931
  	perf_event_comm(tsk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
932
933
934
935
  }
  
  int flush_old_exec(struct linux_binprm * bprm)
  {
221af7f87   Linus Torvalds   Split 'flush_old_...
936
  	int retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
937
938
939
940
941
942
943
944
  
  	/*
  	 * Make sure we have a private signal table and that
  	 * we are unassociated from the previous thread group.
  	 */
  	retval = de_thread(current);
  	if (retval)
  		goto out;
925d1c401   Matt Helsley   procfs task exe s...
945
  	set_mm_exe_file(bprm->mm, bprm->file);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
946
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
947
948
949
950
  	 * Release all of the old mmap stuff
  	 */
  	retval = exec_mmap(bprm->mm);
  	if (retval)
fd8328be8   Al Viro   [PATCH] sanitize ...
951
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
952
953
  
  	bprm->mm = NULL;		/* We're using it now */
7ab02af42   Linus Torvalds   Fix 'flush_old_ex...
954
955
956
957
  
  	current->flags &= ~PF_RANDOMIZE;
  	flush_thread();
  	current->personality &= ~bprm->per_clear;
221af7f87   Linus Torvalds   Split 'flush_old_...
958
959
960
961
962
963
964
965
966
967
968
969
970
971
  	return 0;
  
  out:
  	return retval;
  }
  EXPORT_SYMBOL(flush_old_exec);
  
  void setup_new_exec(struct linux_binprm * bprm)
  {
  	int i, ch;
  	char * name;
  	char tcomm[sizeof(current->comm)];
  
  	arch_pick_mmap_layout(current->mm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
972
973
  
  	/* This is the point of no return */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
974
  	current->sas_ss_sp = current->sas_ss_size = 0;
da9592ede   David Howells   CRED: Wrap task c...
975
  	if (current_euid() == current_uid() && current_egid() == current_gid())
6c5d52382   Kawai, Hidehiro   coredump masking:...
976
  		set_dumpable(current->mm, 1);
d6e711448   Alan Cox   [PATCH] setuid co...
977
  	else
6c5d52382   Kawai, Hidehiro   coredump masking:...
978
  		set_dumpable(current->mm, suid_dumpable);
d6e711448   Alan Cox   [PATCH] setuid co...
979

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
980
  	name = bprm->filename;
367720923   Paolo 'Blaisorblade' Giarrusso   [PATCH] comments ...
981
982
  
  	/* Copies the binary name from after last slash */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
983
984
  	for (i=0; (ch = *(name++)) != '\0';) {
  		if (ch == '/')
367720923   Paolo 'Blaisorblade' Giarrusso   [PATCH] comments ...
985
  			i = 0; /* overwrite what we wrote */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
986
987
988
989
990
991
  		else
  			if (i < (sizeof(tcomm) - 1))
  				tcomm[i++] = ch;
  	}
  	tcomm[i] = '\0';
  	set_task_comm(current, tcomm);
0551fbd29   Benjamin Herrenschmidt   [PATCH] Add mm->t...
992
993
994
995
996
  	/* Set the new mm task size. We have to do that late because it may
  	 * depend on TIF_32BIT which is only updated in flush_thread() on
  	 * some architectures like powerpc
  	 */
  	current->mm->task_size = TASK_SIZE;
a6f76f23d   David Howells   CRED: Make execve...
997
998
999
  	/* install the new credentials */
  	if (bprm->cred->uid != current_euid() ||
  	    bprm->cred->gid != current_egid()) {
d2d56c5f5   Marcel Holtmann   Reset current->pd...
1000
1001
  		current->pdeath_signal = 0;
  	} else if (file_permission(bprm->file, MAY_READ) ||
a6f76f23d   David Howells   CRED: Make execve...
1002
  		   bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP) {
6c5d52382   Kawai, Hidehiro   coredump masking:...
1003
  		set_dumpable(current->mm, suid_dumpable);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1004
  	}
f65cb45cb   Ingo Molnar   perfcounters: flu...
1005
1006
1007
1008
1009
  	/*
  	 * Flush performance counters when crossing a
  	 * security domain:
  	 */
  	if (!get_dumpable(current->mm))
cdd6c482c   Ingo Molnar   perf: Do the big ...
1010
  		perf_event_exit_task(current);
f65cb45cb   Ingo Molnar   perfcounters: flu...
1011

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1012
1013
1014
1015
1016
1017
1018
  	/* An exec changes our domain. We are no longer part of the thread
  	   group */
  
  	current->self_exec_id++;
  			
  	flush_signal_handlers(current, 0);
  	flush_old_files(current->files);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1019
  }
221af7f87   Linus Torvalds   Split 'flush_old_...
1020
  EXPORT_SYMBOL(setup_new_exec);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1021

a6f76f23d   David Howells   CRED: Make execve...
1022
  /*
a2a8474c3   Oleg Nesterov   exec: do not slee...
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
   * Prepare credentials and lock ->cred_guard_mutex.
   * install_exec_creds() commits the new creds and drops the lock.
   * Or, if exec fails before, free_bprm() should release ->cred and
   * and unlock.
   */
  int prepare_bprm_creds(struct linux_binprm *bprm)
  {
  	if (mutex_lock_interruptible(&current->cred_guard_mutex))
  		return -ERESTARTNOINTR;
  
  	bprm->cred = prepare_exec_creds();
  	if (likely(bprm->cred))
  		return 0;
  
  	mutex_unlock(&current->cred_guard_mutex);
  	return -ENOMEM;
  }
  
  void free_bprm(struct linux_binprm *bprm)
  {
  	free_arg_pages(bprm);
  	if (bprm->cred) {
  		mutex_unlock(&current->cred_guard_mutex);
  		abort_creds(bprm->cred);
  	}
  	kfree(bprm);
  }
  
  /*
a6f76f23d   David Howells   CRED: Make execve...
1052
1053
1054
1055
1056
1057
1058
1059
   * install the new credentials for this executable
   */
  void install_exec_creds(struct linux_binprm *bprm)
  {
  	security_bprm_committing_creds(bprm);
  
  	commit_creds(bprm->cred);
  	bprm->cred = NULL;
a2a8474c3   Oleg Nesterov   exec: do not slee...
1060
1061
  	/*
  	 * cred_guard_mutex must be held at least to this point to prevent
a6f76f23d   David Howells   CRED: Make execve...
1062
  	 * ptrace_attach() from altering our determination of the task's
a2a8474c3   Oleg Nesterov   exec: do not slee...
1063
1064
  	 * credentials; any time after this it may be unlocked.
  	 */
a6f76f23d   David Howells   CRED: Make execve...
1065
  	security_bprm_committed_creds(bprm);
a2a8474c3   Oleg Nesterov   exec: do not slee...
1066
  	mutex_unlock(&current->cred_guard_mutex);
a6f76f23d   David Howells   CRED: Make execve...
1067
1068
1069
1070
1071
  }
  EXPORT_SYMBOL(install_exec_creds);
  
  /*
   * determine how safe it is to execute the proposed program
5e751e992   David Howells   CRED: Rename cred...
1072
   * - the caller must hold current->cred_guard_mutex to protect against
a6f76f23d   David Howells   CRED: Make execve...
1073
1074
   *   PTRACE_ATTACH
   */
498052bba   Al Viro   New locking/refco...
1075
  int check_unsafe_exec(struct linux_binprm *bprm)
a6f76f23d   David Howells   CRED: Make execve...
1076
  {
0bf2f3aec   David Howells   CRED: Fix SUID ex...
1077
  	struct task_struct *p = current, *t;
f1191b50e   Al Viro   check_unsafe_exec...
1078
  	unsigned n_fs;
498052bba   Al Viro   New locking/refco...
1079
  	int res = 0;
a6f76f23d   David Howells   CRED: Make execve...
1080
1081
  
  	bprm->unsafe = tracehook_unsafe_exec(p);
0bf2f3aec   David Howells   CRED: Fix SUID ex...
1082
  	n_fs = 1;
498052bba   Al Viro   New locking/refco...
1083
  	write_lock(&p->fs->lock);
437f7fdb6   Oleg Nesterov   check_unsafe_exec...
1084
  	rcu_read_lock();
0bf2f3aec   David Howells   CRED: Fix SUID ex...
1085
1086
1087
  	for (t = next_thread(p); t != p; t = next_thread(t)) {
  		if (t->fs == p->fs)
  			n_fs++;
0bf2f3aec   David Howells   CRED: Fix SUID ex...
1088
  	}
437f7fdb6   Oleg Nesterov   check_unsafe_exec...
1089
  	rcu_read_unlock();
0bf2f3aec   David Howells   CRED: Fix SUID ex...
1090

f1191b50e   Al Viro   check_unsafe_exec...
1091
  	if (p->fs->users > n_fs) {
a6f76f23d   David Howells   CRED: Make execve...
1092
  		bprm->unsafe |= LSM_UNSAFE_SHARE;
498052bba   Al Viro   New locking/refco...
1093
  	} else {
8c652f96d   Oleg Nesterov   do_execve() must ...
1094
1095
1096
1097
1098
  		res = -EAGAIN;
  		if (!p->fs->in_exec) {
  			p->fs->in_exec = 1;
  			res = 1;
  		}
498052bba   Al Viro   New locking/refco...
1099
  	}
498052bba   Al Viro   New locking/refco...
1100
1101
1102
  	write_unlock(&p->fs->lock);
  
  	return res;
a6f76f23d   David Howells   CRED: Make execve...
1103
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1104
1105
1106
  /* 
   * Fill the binprm structure from the inode. 
   * Check permissions, then read the first 128 (BINPRM_BUF_SIZE) bytes
a6f76f23d   David Howells   CRED: Make execve...
1107
1108
   *
   * This may be called multiple times for binary chains (scripts for example).
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1109
1110
1111
   */
  int prepare_binprm(struct linux_binprm *bprm)
  {
a6f76f23d   David Howells   CRED: Make execve...
1112
  	umode_t mode;
0f7fc9e4d   Josef "Jeff" Sipek   [PATCH] VFS: chan...
1113
  	struct inode * inode = bprm->file->f_path.dentry->d_inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1114
1115
1116
  	int retval;
  
  	mode = inode->i_mode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1117
1118
  	if (bprm->file->f_op == NULL)
  		return -EACCES;
a6f76f23d   David Howells   CRED: Make execve...
1119
1120
1121
  	/* clear any previous set[ug]id data from a previous binary */
  	bprm->cred->euid = current_euid();
  	bprm->cred->egid = current_egid();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1122

a6f76f23d   David Howells   CRED: Make execve...
1123
  	if (!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1124
1125
  		/* Set-uid? */
  		if (mode & S_ISUID) {
a6f76f23d   David Howells   CRED: Make execve...
1126
1127
  			bprm->per_clear |= PER_CLEAR_ON_SETID;
  			bprm->cred->euid = inode->i_uid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1128
1129
1130
1131
1132
1133
1134
1135
1136
  		}
  
  		/* Set-gid? */
  		/*
  		 * If setgid is set but no group execute bit then this
  		 * is a candidate for mandatory locking, not a setgid
  		 * executable.
  		 */
  		if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
a6f76f23d   David Howells   CRED: Make execve...
1137
1138
  			bprm->per_clear |= PER_CLEAR_ON_SETID;
  			bprm->cred->egid = inode->i_gid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1139
1140
1141
1142
  		}
  	}
  
  	/* fill in binprm security blob */
a6f76f23d   David Howells   CRED: Make execve...
1143
  	retval = security_bprm_set_creds(bprm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1144
1145
  	if (retval)
  		return retval;
a6f76f23d   David Howells   CRED: Make execve...
1146
  	bprm->cred_prepared = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1147

a6f76f23d   David Howells   CRED: Make execve...
1148
1149
  	memset(bprm->buf, 0, BINPRM_BUF_SIZE);
  	return kernel_read(bprm->file, 0, bprm->buf, BINPRM_BUF_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1150
1151
1152
  }
  
  EXPORT_SYMBOL(prepare_binprm);
4fc75ff48   Nick Piggin   exec: fix remove_...
1153
1154
1155
1156
1157
  /*
   * Arguments are '\0' separated strings found at the location bprm->p
   * points to; chop off the first by relocating brpm->p to right after
   * the first '\0' encountered.
   */
b6a2fea39   Ollie Wild   mm: variable leng...
1158
  int remove_arg_zero(struct linux_binprm *bprm)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1159
  {
b6a2fea39   Ollie Wild   mm: variable leng...
1160
1161
1162
1163
  	int ret = 0;
  	unsigned long offset;
  	char *kaddr;
  	struct page *page;
4fc75ff48   Nick Piggin   exec: fix remove_...
1164

b6a2fea39   Ollie Wild   mm: variable leng...
1165
1166
  	if (!bprm->argc)
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1167

b6a2fea39   Ollie Wild   mm: variable leng...
1168
1169
1170
1171
1172
1173
1174
1175
  	do {
  		offset = bprm->p & ~PAGE_MASK;
  		page = get_arg_page(bprm, bprm->p, 0);
  		if (!page) {
  			ret = -EFAULT;
  			goto out;
  		}
  		kaddr = kmap_atomic(page, KM_USER0);
4fc75ff48   Nick Piggin   exec: fix remove_...
1176

b6a2fea39   Ollie Wild   mm: variable leng...
1177
1178
1179
  		for (; offset < PAGE_SIZE && kaddr[offset];
  				offset++, bprm->p++)
  			;
4fc75ff48   Nick Piggin   exec: fix remove_...
1180

b6a2fea39   Ollie Wild   mm: variable leng...
1181
1182
  		kunmap_atomic(kaddr, KM_USER0);
  		put_arg_page(page);
4fc75ff48   Nick Piggin   exec: fix remove_...
1183

b6a2fea39   Ollie Wild   mm: variable leng...
1184
1185
1186
  		if (offset == PAGE_SIZE)
  			free_arg_page(bprm, (bprm->p >> PAGE_SHIFT) - 1);
  	} while (offset == PAGE_SIZE);
4fc75ff48   Nick Piggin   exec: fix remove_...
1187

b6a2fea39   Ollie Wild   mm: variable leng...
1188
1189
1190
  	bprm->p++;
  	bprm->argc--;
  	ret = 0;
4fc75ff48   Nick Piggin   exec: fix remove_...
1191

b6a2fea39   Ollie Wild   mm: variable leng...
1192
1193
  out:
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1194
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1195
1196
1197
1198
1199
1200
1201
  EXPORT_SYMBOL(remove_arg_zero);
  
  /*
   * cycle the list of binary formats handler, until one recognizes the image
   */
  int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
  {
85f334666   Roland McGrath   tracehook: exec d...
1202
  	unsigned int depth = bprm->recursion_depth;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1203
1204
  	int try,retval;
  	struct linux_binfmt *fmt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1205

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1206
1207
1208
1209
1210
1211
1212
  	retval = security_bprm_check(bprm);
  	if (retval)
  		return retval;
  
  	/* kernel module loader fixup */
  	/* so we don't try to load run modprobe in kernel space. */
  	set_fs(USER_DS);
473ae30bc   Al Viro   [PATCH] execve ar...
1213
1214
1215
1216
  
  	retval = audit_bprm(bprm);
  	if (retval)
  		return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1217
1218
1219
  	retval = -ENOENT;
  	for (try=0; try<2; try++) {
  		read_lock(&binfmt_lock);
e4dc1b14d   Alexey Dobriyan   Use list_head in ...
1220
  		list_for_each_entry(fmt, &formats, lh) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1221
1222
1223
1224
1225
1226
1227
  			int (*fn)(struct linux_binprm *, struct pt_regs *) = fmt->load_binary;
  			if (!fn)
  				continue;
  			if (!try_module_get(fmt->module))
  				continue;
  			read_unlock(&binfmt_lock);
  			retval = fn(bprm, regs);
85f334666   Roland McGrath   tracehook: exec d...
1228
1229
1230
1231
1232
1233
  			/*
  			 * Restore the depth counter to its starting value
  			 * in this call, so we don't have to rely on every
  			 * load_binary function to restore it on return.
  			 */
  			bprm->recursion_depth = depth;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1234
  			if (retval >= 0) {
85f334666   Roland McGrath   tracehook: exec d...
1235
1236
  				if (depth == 0)
  					tracehook_report_exec(fmt, bprm, regs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1237
1238
1239
1240
1241
1242
  				put_binfmt(fmt);
  				allow_write_access(bprm->file);
  				if (bprm->file)
  					fput(bprm->file);
  				bprm->file = NULL;
  				current->did_exec = 1;
9f46080c4   Matt Helsley   [PATCH] Process E...
1243
  				proc_exec_connector(current);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
  				return retval;
  			}
  			read_lock(&binfmt_lock);
  			put_binfmt(fmt);
  			if (retval != -ENOEXEC || bprm->mm == NULL)
  				break;
  			if (!bprm->file) {
  				read_unlock(&binfmt_lock);
  				return retval;
  			}
  		}
  		read_unlock(&binfmt_lock);
  		if (retval != -ENOEXEC || bprm->mm == NULL) {
  			break;
5f4123be3   Johannes Berg   remove CONFIG_KMO...
1258
1259
  #ifdef CONFIG_MODULES
  		} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
  #define printable(c) (((c)=='\t') || ((c)=='
  ') || (0x20<=(c) && (c)<=0x7e))
  			if (printable(bprm->buf[0]) &&
  			    printable(bprm->buf[1]) &&
  			    printable(bprm->buf[2]) &&
  			    printable(bprm->buf[3]))
  				break; /* -ENOEXEC */
  			request_module("binfmt-%04x", *(unsigned short *)(&bprm->buf[2]));
  #endif
  		}
  	}
  	return retval;
  }
  
  EXPORT_SYMBOL(search_binary_handler);
  
  /*
   * sys_execve() executes a new program.
   */
  int do_execve(char * filename,
  	char __user *__user *argv,
  	char __user *__user *envp,
  	struct pt_regs * regs)
  {
  	struct linux_binprm *bprm;
  	struct file *file;
3b1253880   Al Viro   [PATCH] sanitize ...
1286
  	struct files_struct *displaced;
8c652f96d   Oleg Nesterov   do_execve() must ...
1287
  	bool clear_in_exec;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1288
  	int retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1289

3b1253880   Al Viro   [PATCH] sanitize ...
1290
  	retval = unshare_files(&displaced);
fd8328be8   Al Viro   [PATCH] sanitize ...
1291
1292
  	if (retval)
  		goto out_ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1293
  	retval = -ENOMEM;
11b0b5abb   Oliver Neukum   [PATCH] use kzall...
1294
  	bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1295
  	if (!bprm)
fd8328be8   Al Viro   [PATCH] sanitize ...
1296
  		goto out_files;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1297

a2a8474c3   Oleg Nesterov   exec: do not slee...
1298
1299
  	retval = prepare_bprm_creds(bprm);
  	if (retval)
a6f76f23d   David Howells   CRED: Make execve...
1300
  		goto out_free;
498052bba   Al Viro   New locking/refco...
1301
1302
  
  	retval = check_unsafe_exec(bprm);
8c652f96d   Oleg Nesterov   do_execve() must ...
1303
  	if (retval < 0)
a2a8474c3   Oleg Nesterov   exec: do not slee...
1304
  		goto out_free;
8c652f96d   Oleg Nesterov   do_execve() must ...
1305
  	clear_in_exec = retval;
a2a8474c3   Oleg Nesterov   exec: do not slee...
1306
  	current->in_execve = 1;
a6f76f23d   David Howells   CRED: Make execve...
1307

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1308
1309
1310
  	file = open_exec(filename);
  	retval = PTR_ERR(file);
  	if (IS_ERR(file))
498052bba   Al Viro   New locking/refco...
1311
  		goto out_unmark;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1312
1313
  
  	sched_exec();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1314
1315
1316
  	bprm->file = file;
  	bprm->filename = filename;
  	bprm->interp = filename;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1317

b6a2fea39   Ollie Wild   mm: variable leng...
1318
1319
1320
  	retval = bprm_mm_init(bprm);
  	if (retval)
  		goto out_file;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1321

b6a2fea39   Ollie Wild   mm: variable leng...
1322
  	bprm->argc = count(argv, MAX_ARG_STRINGS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1323
  	if ((retval = bprm->argc) < 0)
a6f76f23d   David Howells   CRED: Make execve...
1324
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1325

b6a2fea39   Ollie Wild   mm: variable leng...
1326
  	bprm->envc = count(envp, MAX_ARG_STRINGS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1327
  	if ((retval = bprm->envc) < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
  		goto out;
  
  	retval = prepare_binprm(bprm);
  	if (retval < 0)
  		goto out;
  
  	retval = copy_strings_kernel(1, &bprm->filename, bprm);
  	if (retval < 0)
  		goto out;
  
  	bprm->exec = bprm->p;
  	retval = copy_strings(bprm->envc, envp, bprm);
  	if (retval < 0)
  		goto out;
  
  	retval = copy_strings(bprm->argc, argv, bprm);
  	if (retval < 0)
  		goto out;
7b34e4283   Oleg Nesterov   introduce PF_KTHR...
1346
  	current->flags &= ~PF_KTHREAD;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1347
  	retval = search_binary_handler(bprm,regs);
a6f76f23d   David Howells   CRED: Make execve...
1348
1349
  	if (retval < 0)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1350

d899bf7b5   Stefani Seibold   procfs: provide s...
1351
  	current->stack_start = current->mm->start_stack;
a6f76f23d   David Howells   CRED: Make execve...
1352
  	/* execve succeeded */
498052bba   Al Viro   New locking/refco...
1353
  	current->fs->in_exec = 0;
f9ce1f1cd   Kentaro Takeda   Add in_execve fla...
1354
  	current->in_execve = 0;
a6f76f23d   David Howells   CRED: Make execve...
1355
1356
1357
1358
1359
  	acct_update_integrals(current);
  	free_bprm(bprm);
  	if (displaced)
  		put_files_struct(displaced);
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1360

a6f76f23d   David Howells   CRED: Make execve...
1361
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1362
  	if (bprm->mm)
b6a2fea39   Ollie Wild   mm: variable leng...
1363
  		mmput (bprm->mm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1364
1365
1366
1367
1368
1369
  
  out_file:
  	if (bprm->file) {
  		allow_write_access(bprm->file);
  		fput(bprm->file);
  	}
a6f76f23d   David Howells   CRED: Make execve...
1370

498052bba   Al Viro   New locking/refco...
1371
  out_unmark:
8c652f96d   Oleg Nesterov   do_execve() must ...
1372
1373
  	if (clear_in_exec)
  		current->fs->in_exec = 0;
f9ce1f1cd   Kentaro Takeda   Add in_execve fla...
1374
  	current->in_execve = 0;
a6f76f23d   David Howells   CRED: Make execve...
1375
1376
  
  out_free:
08a6fac1c   Al Viro   [PATCH] get rid o...
1377
  	free_bprm(bprm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1378

fd8328be8   Al Viro   [PATCH] sanitize ...
1379
  out_files:
3b1253880   Al Viro   [PATCH] sanitize ...
1380
1381
  	if (displaced)
  		reset_files_struct(displaced);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1382
1383
1384
  out_ret:
  	return retval;
  }
964ee7df9   Oleg Nesterov   exec: fix set_bin...
1385
  void set_binfmt(struct linux_binfmt *new)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1386
  {
801460d0c   Hiroshi Shimamoto   task_struct clean...
1387
1388
1389
1390
  	struct mm_struct *mm = current->mm;
  
  	if (mm->binfmt)
  		module_put(mm->binfmt->module);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1391

801460d0c   Hiroshi Shimamoto   task_struct clean...
1392
  	mm->binfmt = new;
964ee7df9   Oleg Nesterov   exec: fix set_bin...
1393
1394
  	if (new)
  		__module_get(new->module);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1395
1396
1397
  }
  
  EXPORT_SYMBOL(set_binfmt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1398
1399
1400
1401
  /* format_corename will inspect the pattern parameter, and output a
   * name into corename, which must have space for at least
   * CORENAME_MAX_SIZE bytes plus one byte for the zero terminator.
   */
6409324b3   Oleg Nesterov   coredump: format_...
1402
  static int format_corename(char *corename, long signr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1403
  {
86a264abe   David Howells   CRED: Wrap curren...
1404
  	const struct cred *cred = current_cred();
565b9b14e   Oleg Nesterov   coredump: format_...
1405
1406
  	const char *pat_ptr = core_pattern;
  	int ispipe = (*pat_ptr == '|');
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
  	char *out_ptr = corename;
  	char *const out_end = corename + CORENAME_MAX_SIZE;
  	int rc;
  	int pid_in_pattern = 0;
  
  	/* Repeat as long as we have more pattern to process and more output
  	   space */
  	while (*pat_ptr) {
  		if (*pat_ptr != '%') {
  			if (out_ptr == out_end)
  				goto out;
  			*out_ptr++ = *pat_ptr++;
  		} else {
  			switch (*++pat_ptr) {
  			case 0:
  				goto out;
  			/* Double percent, output one percent */
  			case '%':
  				if (out_ptr == out_end)
  					goto out;
  				*out_ptr++ = '%';
  				break;
  			/* pid */
  			case 'p':
  				pid_in_pattern = 1;
  				rc = snprintf(out_ptr, out_end - out_ptr,
b488893a3   Pavel Emelyanov   pid namespaces: c...
1433
  					      "%d", task_tgid_vnr(current));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1434
1435
1436
1437
1438
1439
1440
  				if (rc > out_end - out_ptr)
  					goto out;
  				out_ptr += rc;
  				break;
  			/* uid */
  			case 'u':
  				rc = snprintf(out_ptr, out_end - out_ptr,
86a264abe   David Howells   CRED: Wrap curren...
1441
  					      "%d", cred->uid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1442
1443
1444
1445
1446
1447
1448
  				if (rc > out_end - out_ptr)
  					goto out;
  				out_ptr += rc;
  				break;
  			/* gid */
  			case 'g':
  				rc = snprintf(out_ptr, out_end - out_ptr,
86a264abe   David Howells   CRED: Wrap curren...
1449
  					      "%d", cred->gid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
  				if (rc > out_end - out_ptr)
  					goto out;
  				out_ptr += rc;
  				break;
  			/* signal that caused the coredump */
  			case 's':
  				rc = snprintf(out_ptr, out_end - out_ptr,
  					      "%ld", signr);
  				if (rc > out_end - out_ptr)
  					goto out;
  				out_ptr += rc;
  				break;
  			/* UNIX time of coredump */
  			case 't': {
  				struct timeval tv;
  				do_gettimeofday(&tv);
  				rc = snprintf(out_ptr, out_end - out_ptr,
  					      "%lu", tv.tv_sec);
  				if (rc > out_end - out_ptr)
  					goto out;
  				out_ptr += rc;
  				break;
  			}
  			/* hostname */
  			case 'h':
  				down_read(&uts_sem);
  				rc = snprintf(out_ptr, out_end - out_ptr,
e9ff3990f   Serge E. Hallyn   [PATCH] namespace...
1477
  					      "%s", utsname()->nodename);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
  				up_read(&uts_sem);
  				if (rc > out_end - out_ptr)
  					goto out;
  				out_ptr += rc;
  				break;
  			/* executable */
  			case 'e':
  				rc = snprintf(out_ptr, out_end - out_ptr,
  					      "%s", current->comm);
  				if (rc > out_end - out_ptr)
  					goto out;
  				out_ptr += rc;
  				break;
74aadce98   Neil Horman   core_pattern: all...
1491
1492
1493
  			/* core limit size */
  			case 'c':
  				rc = snprintf(out_ptr, out_end - out_ptr,
d554ed895   Jiri Slaby   fs: use rlimit he...
1494
  					      "%lu", rlimit(RLIMIT_CORE));
74aadce98   Neil Horman   core_pattern: all...
1495
1496
1497
1498
  				if (rc > out_end - out_ptr)
  					goto out;
  				out_ptr += rc;
  				break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
  			default:
  				break;
  			}
  			++pat_ptr;
  		}
  	}
  	/* Backward compatibility with core_uses_pid:
  	 *
  	 * If core_pattern does not include a %p (as is the default)
  	 * and core_uses_pid is set, then .%pid will be appended to
c4bbafda7   Alan Cox   exec.c: fix cored...
1509
  	 * the filename. Do not do this for piped commands. */
6409324b3   Oleg Nesterov   coredump: format_...
1510
  	if (!ispipe && !pid_in_pattern && core_uses_pid) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1511
  		rc = snprintf(out_ptr, out_end - out_ptr,
b488893a3   Pavel Emelyanov   pid namespaces: c...
1512
  			      ".%d", task_tgid_vnr(current));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1513
1514
1515
1516
  		if (rc > out_end - out_ptr)
  			goto out;
  		out_ptr += rc;
  	}
c4bbafda7   Alan Cox   exec.c: fix cored...
1517
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1518
  	*out_ptr = 0;
c4bbafda7   Alan Cox   exec.c: fix cored...
1519
  	return ispipe;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1520
  }
5c99cbf49   Oleg Nesterov   coredump: set ->g...
1521
  static int zap_process(struct task_struct *start, int exit_code)
aceecc041   Oleg Nesterov   [PATCH] coredump:...
1522
1523
  {
  	struct task_struct *t;
8cd9c2491   Oleg Nesterov   coredump: simplif...
1524
  	int nr = 0;
281de339c   Oleg Nesterov   [PATCH] coredump:...
1525

d5f70c00a   Oleg Nesterov   [PATCH] coredump:...
1526
  	start->signal->flags = SIGNAL_GROUP_EXIT;
5c99cbf49   Oleg Nesterov   coredump: set ->g...
1527
  	start->signal->group_exit_code = exit_code;
d5f70c00a   Oleg Nesterov   [PATCH] coredump:...
1528
  	start->signal->group_stop_count = 0;
aceecc041   Oleg Nesterov   [PATCH] coredump:...
1529
1530
1531
1532
  
  	t = start;
  	do {
  		if (t != current && t->mm) {
281de339c   Oleg Nesterov   [PATCH] coredump:...
1533
1534
  			sigaddset(&t->pending.signal, SIGKILL);
  			signal_wake_up(t, 1);
8cd9c2491   Oleg Nesterov   coredump: simplif...
1535
  			nr++;
aceecc041   Oleg Nesterov   [PATCH] coredump:...
1536
  		}
e4901f92a   Oleg Nesterov   coredump: zap_thr...
1537
  	} while_each_thread(start, t);
8cd9c2491   Oleg Nesterov   coredump: simplif...
1538
1539
  
  	return nr;
aceecc041   Oleg Nesterov   [PATCH] coredump:...
1540
  }
dcf560c59   Oleg Nesterov   [PATCH] coredump:...
1541
  static inline int zap_threads(struct task_struct *tsk, struct mm_struct *mm,
8cd9c2491   Oleg Nesterov   coredump: simplif...
1542
  				struct core_state *core_state, int exit_code)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1543
1544
  {
  	struct task_struct *g, *p;
5debfa6da   Oleg Nesterov   [PATCH] coredump:...
1545
  	unsigned long flags;
8cd9c2491   Oleg Nesterov   coredump: simplif...
1546
  	int nr = -EAGAIN;
dcf560c59   Oleg Nesterov   [PATCH] coredump:...
1547
1548
  
  	spin_lock_irq(&tsk->sighand->siglock);
ed5d2cac1   Oleg Nesterov   exec: rework the ...
1549
  	if (!signal_group_exit(tsk->signal)) {
8cd9c2491   Oleg Nesterov   coredump: simplif...
1550
  		mm->core_state = core_state;
5c99cbf49   Oleg Nesterov   coredump: set ->g...
1551
  		nr = zap_process(tsk, exit_code);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1552
  	}
dcf560c59   Oleg Nesterov   [PATCH] coredump:...
1553
  	spin_unlock_irq(&tsk->sighand->siglock);
8cd9c2491   Oleg Nesterov   coredump: simplif...
1554
1555
  	if (unlikely(nr < 0))
  		return nr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1556

8cd9c2491   Oleg Nesterov   coredump: simplif...
1557
  	if (atomic_read(&mm->mm_users) == nr + 1)
5debfa6da   Oleg Nesterov   [PATCH] coredump:...
1558
  		goto done;
e4901f92a   Oleg Nesterov   coredump: zap_thr...
1559
1560
  	/*
  	 * We should find and kill all tasks which use this mm, and we should
999d9fc16   Oleg Nesterov   coredump: move mm...
1561
  	 * count them correctly into ->nr_threads. We don't take tasklist
e4901f92a   Oleg Nesterov   coredump: zap_thr...
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
  	 * lock, but this is safe wrt:
  	 *
  	 * fork:
  	 *	None of sub-threads can fork after zap_process(leader). All
  	 *	processes which were created before this point should be
  	 *	visible to zap_threads() because copy_process() adds the new
  	 *	process to the tail of init_task.tasks list, and lock/unlock
  	 *	of ->siglock provides a memory barrier.
  	 *
  	 * do_exit:
  	 *	The caller holds mm->mmap_sem. This means that the task which
  	 *	uses this mm can't pass exit_mm(), so it can't exit or clear
  	 *	its ->mm.
  	 *
  	 * de_thread:
  	 *	It does list_replace_rcu(&leader->tasks, &current->tasks),
  	 *	we must see either old or new leader, this does not matter.
  	 *	However, it can change p->sighand, so lock_task_sighand(p)
  	 *	must be used. Since p->mm != NULL and we hold ->mmap_sem
  	 *	it can't fail.
  	 *
  	 *	Note also that "g" can be the old leader with ->mm == NULL
  	 *	and already unhashed and thus removed from ->thread_group.
  	 *	This is OK, __unhash_process()->list_del_rcu() does not
  	 *	clear the ->next pointer, we will find the new leader via
  	 *	next_thread().
  	 */
7b1c6154f   Oleg Nesterov   [PATCH] coredump:...
1589
  	rcu_read_lock();
aceecc041   Oleg Nesterov   [PATCH] coredump:...
1590
  	for_each_process(g) {
5debfa6da   Oleg Nesterov   [PATCH] coredump:...
1591
1592
  		if (g == tsk->group_leader)
  			continue;
15b9f360c   Oleg Nesterov   coredump: zap_thr...
1593
1594
  		if (g->flags & PF_KTHREAD)
  			continue;
aceecc041   Oleg Nesterov   [PATCH] coredump:...
1595
1596
1597
  		p = g;
  		do {
  			if (p->mm) {
15b9f360c   Oleg Nesterov   coredump: zap_thr...
1598
  				if (unlikely(p->mm == mm)) {
5debfa6da   Oleg Nesterov   [PATCH] coredump:...
1599
  					lock_task_sighand(p, &flags);
5c99cbf49   Oleg Nesterov   coredump: set ->g...
1600
  					nr += zap_process(p, exit_code);
5debfa6da   Oleg Nesterov   [PATCH] coredump:...
1601
1602
  					unlock_task_sighand(p, &flags);
  				}
aceecc041   Oleg Nesterov   [PATCH] coredump:...
1603
1604
  				break;
  			}
e4901f92a   Oleg Nesterov   coredump: zap_thr...
1605
  		} while_each_thread(g, p);
aceecc041   Oleg Nesterov   [PATCH] coredump:...
1606
  	}
7b1c6154f   Oleg Nesterov   [PATCH] coredump:...
1607
  	rcu_read_unlock();
5debfa6da   Oleg Nesterov   [PATCH] coredump:...
1608
  done:
c5f1cc8c1   Oleg Nesterov   coredump: turn co...
1609
  	atomic_set(&core_state->nr_threads, nr);
8cd9c2491   Oleg Nesterov   coredump: simplif...
1610
  	return nr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1611
  }
9d5b327bf   Oleg Nesterov   coredump: make mm...
1612
  static int coredump_wait(int exit_code, struct core_state *core_state)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1613
  {
dcf560c59   Oleg Nesterov   [PATCH] coredump:...
1614
1615
  	struct task_struct *tsk = current;
  	struct mm_struct *mm = tsk->mm;
dcf560c59   Oleg Nesterov   [PATCH] coredump:...
1616
  	struct completion *vfork_done;
2384f55f8   Oleg Nesterov   [PATCH] coredump_...
1617
  	int core_waiters;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1618

9d5b327bf   Oleg Nesterov   coredump: make mm...
1619
  	init_completion(&core_state->startup);
b564daf80   Oleg Nesterov   coredump: constru...
1620
1621
  	core_state->dumper.task = tsk;
  	core_state->dumper.next = NULL;
9d5b327bf   Oleg Nesterov   coredump: make mm...
1622
  	core_waiters = zap_threads(tsk, mm, core_state, exit_code);
2384f55f8   Oleg Nesterov   [PATCH] coredump_...
1623
  	up_write(&mm->mmap_sem);
dcf560c59   Oleg Nesterov   [PATCH] coredump:...
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
  	if (unlikely(core_waiters < 0))
  		goto fail;
  
  	/*
  	 * Make sure nobody is waiting for us to release the VM,
  	 * otherwise we can deadlock when we wait on each other
  	 */
  	vfork_done = tsk->vfork_done;
  	if (vfork_done) {
  		tsk->vfork_done = NULL;
  		complete(vfork_done);
  	}
2384f55f8   Oleg Nesterov   [PATCH] coredump_...
1636
  	if (core_waiters)
9d5b327bf   Oleg Nesterov   coredump: make mm...
1637
  		wait_for_completion(&core_state->startup);
dcf560c59   Oleg Nesterov   [PATCH] coredump:...
1638
  fail:
dcf560c59   Oleg Nesterov   [PATCH] coredump:...
1639
  	return core_waiters;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1640
  }
a94e2d408   Oleg Nesterov   coredump: kill mm...
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
  static void coredump_finish(struct mm_struct *mm)
  {
  	struct core_thread *curr, *next;
  	struct task_struct *task;
  
  	next = mm->core_state->dumper.next;
  	while ((curr = next) != NULL) {
  		next = curr->next;
  		task = curr->task;
  		/*
  		 * see exit_mm(), curr->task must not see
  		 * ->task == NULL before we read ->next.
  		 */
  		smp_mb();
  		curr->task = NULL;
  		wake_up_process(task);
  	}
  
  	mm->core_state = NULL;
  }
6c5d52382   Kawai, Hidehiro   coredump masking:...
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
  /*
   * set_dumpable converts traditional three-value dumpable to two flags and
   * stores them into mm->flags.  It modifies lower two bits of mm->flags, but
   * these bits are not changed atomically.  So get_dumpable can observe the
   * intermediate state.  To avoid doing unexpected behavior, get get_dumpable
   * return either old dumpable or new one by paying attention to the order of
   * modifying the bits.
   *
   * dumpable |   mm->flags (binary)
   * old  new | initial interim  final
   * ---------+-----------------------
   *  0    1  |   00      01      01
   *  0    2  |   00      10(*)   11
   *  1    0  |   01      00      00
   *  1    2  |   01      11      11
   *  2    0  |   11      10(*)   00
   *  2    1  |   11      11      01
   *
   * (*) get_dumpable regards interim value of 10 as 11.
   */
  void set_dumpable(struct mm_struct *mm, int value)
  {
  	switch (value) {
  	case 0:
  		clear_bit(MMF_DUMPABLE, &mm->flags);
  		smp_wmb();
  		clear_bit(MMF_DUMP_SECURELY, &mm->flags);
  		break;
  	case 1:
  		set_bit(MMF_DUMPABLE, &mm->flags);
  		smp_wmb();
  		clear_bit(MMF_DUMP_SECURELY, &mm->flags);
  		break;
  	case 2:
  		set_bit(MMF_DUMP_SECURELY, &mm->flags);
  		smp_wmb();
  		set_bit(MMF_DUMPABLE, &mm->flags);
  		break;
  	}
  }
6c5d52382   Kawai, Hidehiro   coredump masking:...
1701

30736a4d4   Masami Hiramatsu   coredump: pass mm...
1702
  static int __get_dumpable(unsigned long mm_flags)
6c5d52382   Kawai, Hidehiro   coredump masking:...
1703
1704
  {
  	int ret;
30736a4d4   Masami Hiramatsu   coredump: pass mm...
1705
  	ret = mm_flags & MMF_DUMPABLE_MASK;
6c5d52382   Kawai, Hidehiro   coredump masking:...
1706
1707
  	return (ret >= 2) ? 2 : ret;
  }
30736a4d4   Masami Hiramatsu   coredump: pass mm...
1708
1709
1710
1711
  int get_dumpable(struct mm_struct *mm)
  {
  	return __get_dumpable(mm->flags);
  }
61be228a0   Neil Horman   exec: allow do_co...
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
  static void wait_for_dump_helpers(struct file *file)
  {
  	struct pipe_inode_info *pipe;
  
  	pipe = file->f_path.dentry->d_inode->i_pipe;
  
  	pipe_lock(pipe);
  	pipe->readers++;
  	pipe->writers--;
  
  	while ((pipe->readers > 1) && (!signal_pending(current))) {
  		wake_up_interruptible_sync(&pipe->wait);
  		kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
  		pipe_wait(pipe);
  	}
  
  	pipe->readers--;
  	pipe->writers++;
  	pipe_unlock(pipe);
  
  }
8cd3ac3ac   WANG Cong   fs/exec.c: make d...
1733
  void do_coredump(long signr, int exit_code, struct pt_regs *regs)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1734
  {
9d5b327bf   Oleg Nesterov   coredump: make mm...
1735
  	struct core_state core_state;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1736
1737
1738
1739
  	char corename[CORENAME_MAX_SIZE + 1];
  	struct mm_struct *mm = current->mm;
  	struct linux_binfmt * binfmt;
  	struct inode * inode;
d84f4f992   David Howells   CRED: Inaugurate ...
1740
1741
  	const struct cred *old_cred;
  	struct cred *cred;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1742
  	int retval = 0;
d6e711448   Alan Cox   [PATCH] setuid co...
1743
  	int flag = 0;
d025c9db7   Andi Kleen   [PATCH] Support p...
1744
  	int ispipe = 0;
74aadce98   Neil Horman   core_pattern: all...
1745
1746
  	char **helper_argv = NULL;
  	int helper_argc = 0;
a293980c2   Neil Horman   exec: let do_core...
1747
1748
  	int dump_count = 0;
  	static atomic_t core_dump_count = ATOMIC_INIT(0);
f6151dfea   Masami Hiramatsu   mm: introduce cor...
1749
1750
1751
  	struct coredump_params cprm = {
  		.signr = signr,
  		.regs = regs,
d554ed895   Jiri Slaby   fs: use rlimit he...
1752
  		.limit = rlimit(RLIMIT_CORE),
30736a4d4   Masami Hiramatsu   coredump: pass mm...
1753
1754
1755
1756
1757
1758
  		/*
  		 * We must use the same mm->flags while dumping core to avoid
  		 * inconsistency of bit flags, since this flag is not protected
  		 * by any locks.
  		 */
  		.mm_flags = mm->flags,
f6151dfea   Masami Hiramatsu   mm: introduce cor...
1759
  	};
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1760

0a4ff8c25   Steve Grubb   [PATCH] Abnormal ...
1761
  	audit_core_dumps(signr);
801460d0c   Hiroshi Shimamoto   task_struct clean...
1762
  	binfmt = mm->binfmt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1763
1764
  	if (!binfmt || !binfmt->core_dump)
  		goto fail;
d84f4f992   David Howells   CRED: Inaugurate ...
1765
1766
1767
1768
1769
1770
  
  	cred = prepare_creds();
  	if (!cred) {
  		retval = -ENOMEM;
  		goto fail;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1771
  	down_write(&mm->mmap_sem);
00ec99da4   Roland McGrath   core dump: remain...
1772
1773
1774
  	/*
  	 * If another thread got here first, or we are not dumpable, bail out.
  	 */
30736a4d4   Masami Hiramatsu   coredump: pass mm...
1775
  	if (mm->core_state || !__get_dumpable(cprm.mm_flags)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1776
  		up_write(&mm->mmap_sem);
d84f4f992   David Howells   CRED: Inaugurate ...
1777
  		put_cred(cred);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1778
1779
  		goto fail;
  	}
d6e711448   Alan Cox   [PATCH] setuid co...
1780
1781
1782
1783
1784
1785
  
  	/*
  	 *	We cannot trust fsuid as being the "true" uid of the
  	 *	process nor do we know its entire history. We only know it
  	 *	was tainted so we dump it as root in mode 2.
  	 */
30736a4d4   Masami Hiramatsu   coredump: pass mm...
1786
1787
  	if (__get_dumpable(cprm.mm_flags) == 2) {
  		/* Setuid core dump mode */
d6e711448   Alan Cox   [PATCH] setuid co...
1788
  		flag = O_EXCL;		/* Stop rewrite attacks */
d84f4f992   David Howells   CRED: Inaugurate ...
1789
  		cred->fsuid = 0;	/* Dump root private */
d6e711448   Alan Cox   [PATCH] setuid co...
1790
  	}
1291cf416   Oleg Nesterov   [PATCH] fix de_th...
1791

9d5b327bf   Oleg Nesterov   coredump: make mm...
1792
  	retval = coredump_wait(exit_code, &core_state);
d84f4f992   David Howells   CRED: Inaugurate ...
1793
1794
  	if (retval < 0) {
  		put_cred(cred);
1291cf416   Oleg Nesterov   [PATCH] fix de_th...
1795
  		goto fail;
d84f4f992   David Howells   CRED: Inaugurate ...
1796
1797
1798
  	}
  
  	old_cred = override_creds(cred);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1799
1800
1801
1802
1803
  
  	/*
  	 * Clear any false indication of pending signals that might
  	 * be seen by the filesystem code called to write the core file.
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1804
  	clear_thread_flag(TIF_SIGPENDING);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1805
1806
1807
1808
1809
  	/*
  	 * lock_kernel() because format_corename() is controlled by sysctl, which
  	 * uses lock_kernel()
  	 */
   	lock_kernel();
6409324b3   Oleg Nesterov   coredump: format_...
1810
  	ispipe = format_corename(corename, signr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1811
  	unlock_kernel();
725eae32d   Neil Horman   exec: make do_cor...
1812

f6151dfea   Masami Hiramatsu   mm: introduce cor...
1813
  	if ((!ispipe) && (cprm.limit < binfmt->min_coredump))
7dc0b22e3   Neil Horman   core_pattern: ign...
1814
  		goto fail_unlock;
c4bbafda7   Alan Cox   exec.c: fix cored...
1815
   	if (ispipe) {
f6151dfea   Masami Hiramatsu   mm: introduce cor...
1816
  		if (cprm.limit == 0) {
725eae32d   Neil Horman   exec: make do_cor...
1817
1818
1819
  			/*
  			 * Normally core limits are irrelevant to pipes, since
  			 * we're not writing to the file system, but we use
f6151dfea   Masami Hiramatsu   mm: introduce cor...
1820
  			 * cprm.limit of 0 here as a speacial value. Any
725eae32d   Neil Horman   exec: make do_cor...
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
  			 * non-zero limit gets set to RLIM_INFINITY below, but
  			 * a limit of 0 skips the dump.  This is a consistent
  			 * way to catch recursive crashes.  We can still crash
  			 * if the core_pattern binary sets RLIM_CORE =  !0
  			 * but it runs as root, and can do lots of stupid things
  			 * Note that we use task_tgid_vnr here to grab the pid
  			 * of the process group leader.  That way we get the
  			 * right pid if a thread in a multi-threaded
  			 * core_pattern process dies.
  			 */
  			printk(KERN_WARNING
  				"Process %d(%s) has RLIMIT_CORE set to 0
  ",
  				task_tgid_vnr(current), current->comm);
  			printk(KERN_WARNING "Aborting core
  ");
  			goto fail_unlock;
  		}
a293980c2   Neil Horman   exec: let do_core...
1839
1840
1841
1842
1843
1844
1845
1846
1847
  		dump_count = atomic_inc_return(&core_dump_count);
  		if (core_pipe_limit && (core_pipe_limit < dump_count)) {
  			printk(KERN_WARNING "Pid %d(%s) over core_pipe_limit
  ",
  			       task_tgid_vnr(current), current->comm);
  			printk(KERN_WARNING "Skipping core dump
  ");
  			goto fail_dropcount;
  		}
74aadce98   Neil Horman   core_pattern: all...
1848
  		helper_argv = argv_split(GFP_KERNEL, corename+1, &helper_argc);
350eaf791   Tetsuo Handa   do_coredump(): ch...
1849
1850
1851
1852
  		if (!helper_argv) {
  			printk(KERN_WARNING "%s failed to allocate memory
  ",
  			       __func__);
a293980c2   Neil Horman   exec: let do_core...
1853
  			goto fail_dropcount;
350eaf791   Tetsuo Handa   do_coredump(): ch...
1854
  		}
323211371   Neil Horman   core_pattern: fix...
1855

f6151dfea   Masami Hiramatsu   mm: introduce cor...
1856
  		cprm.limit = RLIM_INFINITY;
323211371   Neil Horman   core_pattern: fix...
1857

d025c9db7   Andi Kleen   [PATCH] Support p...
1858
  		/* SIGPIPE can happen, but it's just never processed */
a293980c2   Neil Horman   exec: let do_core...
1859
  		if (call_usermodehelper_pipe(helper_argv[0], helper_argv, NULL,
f6151dfea   Masami Hiramatsu   mm: introduce cor...
1860
  				&cprm.file)) {
d025c9db7   Andi Kleen   [PATCH] Support p...
1861
1862
1863
   			printk(KERN_INFO "Core dump to %s pipe failed
  ",
  			       corename);
a293980c2   Neil Horman   exec: let do_core...
1864
  			goto fail_dropcount;
d025c9db7   Andi Kleen   [PATCH] Support p...
1865
   		}
d025c9db7   Andi Kleen   [PATCH] Support p...
1866
   	} else
f6151dfea   Masami Hiramatsu   mm: introduce cor...
1867
  		cprm.file = filp_open(corename,
6d4df677f   Alexey Dobriyan   [PATCH] do_coredu...
1868
1869
  				 O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag,
  				 0600);
f6151dfea   Masami Hiramatsu   mm: introduce cor...
1870
  	if (IS_ERR(cprm.file))
a293980c2   Neil Horman   exec: let do_core...
1871
  		goto fail_dropcount;
f6151dfea   Masami Hiramatsu   mm: introduce cor...
1872
  	inode = cprm.file->f_path.dentry->d_inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1873
1874
  	if (inode->i_nlink > 1)
  		goto close_fail;	/* multiple links - don't dump */
f6151dfea   Masami Hiramatsu   mm: introduce cor...
1875
  	if (!ispipe && d_unhashed(cprm.file->f_path.dentry))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1876
  		goto close_fail;
d025c9db7   Andi Kleen   [PATCH] Support p...
1877
1878
1879
  	/* AK: actually i see no reason to not allow this for named pipes etc.,
  	   but keep the previous behaviour for now. */
  	if (!ispipe && !S_ISREG(inode->i_mode))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1880
  		goto close_fail;
c46f739dd   Ingo Molnar   vfs: coredumping fix
1881
1882
1883
  	/*
  	 * Dont allow local users get cute and trick others to coredump
  	 * into their pre-created files:
76595f79d   Neil Horman   coredump: suppres...
1884
  	 * Note, this is not relevant for pipes
c46f739dd   Ingo Molnar   vfs: coredumping fix
1885
  	 */
76595f79d   Neil Horman   coredump: suppres...
1886
  	if (!ispipe && (inode->i_uid != current_fsuid()))
c46f739dd   Ingo Molnar   vfs: coredumping fix
1887
  		goto close_fail;
f6151dfea   Masami Hiramatsu   mm: introduce cor...
1888
  	if (!cprm.file->f_op)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1889
  		goto close_fail;
f6151dfea   Masami Hiramatsu   mm: introduce cor...
1890
  	if (!cprm.file->f_op->write)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1891
  		goto close_fail;
f6151dfea   Masami Hiramatsu   mm: introduce cor...
1892
1893
  	if (!ispipe &&
  	    do_truncate(cprm.file->f_path.dentry, 0, 0, cprm.file) != 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1894
  		goto close_fail;
f6151dfea   Masami Hiramatsu   mm: introduce cor...
1895
  	retval = binfmt->core_dump(&cprm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1896
1897
1898
1899
  
  	if (retval)
  		current->signal->group_exit_code |= 0x80;
  close_fail:
61be228a0   Neil Horman   exec: allow do_co...
1900
  	if (ispipe && core_pipe_limit)
f6151dfea   Masami Hiramatsu   mm: introduce cor...
1901
1902
  		wait_for_dump_helpers(cprm.file);
  	filp_close(cprm.file, NULL);
a293980c2   Neil Horman   exec: let do_core...
1903
1904
1905
  fail_dropcount:
  	if (dump_count)
  		atomic_dec(&core_dump_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1906
  fail_unlock:
74aadce98   Neil Horman   core_pattern: all...
1907
1908
  	if (helper_argv)
  		argv_free(helper_argv);
d84f4f992   David Howells   CRED: Inaugurate ...
1909
1910
  	revert_creds(old_cred);
  	put_cred(cred);
a94e2d408   Oleg Nesterov   coredump: kill mm...
1911
  	coredump_finish(mm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1912
  fail:
8cd3ac3ac   WANG Cong   fs/exec.c: make d...
1913
  	return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1914
  }