Blame view

fs/exec.c 47 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
  /*
   *  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
613cc2b6f   Aleksa Sarai   fs: exec: apply C...
22
   * formats.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
   */
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>
615d6e875   Davidlohr Bueso   mm: per-thread vm...
28
  #include <linux/vmacache.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
30
  #include <linux/stat.h>
  #include <linux/fcntl.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>
6e84f3152   Ingo Molnar   sched/headers: Pr...
34
  #include <linux/sched/mm.h>
f7ccbae45   Ingo Molnar   sched/headers: Pr...
35
  #include <linux/sched/coredump.h>
3f07c0144   Ingo Molnar   sched/headers: Pr...
36
  #include <linux/sched/signal.h>
6a3827d75   Ingo Molnar   sched/headers: Pr...
37
  #include <linux/sched/numa_balancing.h>
299300258   Ingo Molnar   sched/headers: Pr...
38
  #include <linux/sched/task.h>
ca5b172bd   Hugh Dickins   exec: include pag...
39
  #include <linux/pagemap.h>
cdd6c482c   Ingo Molnar   perf: Do the big ...
40
  #include <linux/perf_event.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
42
43
44
45
  #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
46
  #include <linux/utsname.h>
84d737866   Sukadev Bhattiprolu   [PATCH] add child...
47
  #include <linux/pid_namespace.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48
49
  #include <linux/module.h>
  #include <linux/namei.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50
51
52
  #include <linux/mount.h>
  #include <linux/security.h>
  #include <linux/syscalls.h>
8f0ab5147   Jay Lan   [PATCH] csa: conv...
53
  #include <linux/tsacct_kern.h>
9f46080c4   Matt Helsley   [PATCH] Process E...
54
  #include <linux/cn_proc.h>
473ae30bc   Al Viro   [PATCH] execve ar...
55
  #include <linux/audit.h>
6341c393f   Roland McGrath   tracehook: exec
56
  #include <linux/tracehook.h>
5f4123be3   Johannes Berg   remove CONFIG_KMO...
57
  #include <linux/kmod.h>
6110e3abb   Eric Paris   sys_execve and sy...
58
  #include <linux/fsnotify.h>
5ad4e53bd   Al Viro   Get rid of indire...
59
  #include <linux/fs_struct.h>
61be228a0   Neil Horman   exec: allow do_co...
60
  #include <linux/pipe_fs_i.h>
3d5992d2a   Ying Han   oom: add per-mm o...
61
  #include <linux/oom.h>
0e028465d   Oleg Nesterov   exec: unify do_ex...
62
  #include <linux/compat.h>
b44a7dfc6   Mimi Zohar   vfs: define a gen...
63
  #include <linux/vmalloc.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64

7c0f6ba68   Linus Torvalds   Replace <asm/uacc...
65
  #include <linux/uaccess.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
  #include <asm/mmu_context.h>
b6a2fea39   Ollie Wild   mm: variable leng...
67
  #include <asm/tlb.h>
43d2b1132   KAMEZAWA Hiroyuki   tracepoint: add t...
68
69
  
  #include <trace/events/task.h>
a6f76f23d   David Howells   CRED: Make execve...
70
  #include "internal.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
71

4ff16c25e   David Smith   tracepoint, vfs, ...
72
  #include <trace/events/sched.h>
d6e711448   Alan Cox   [PATCH] setuid co...
73
  int suid_dumpable = 0;
e4dc1b14d   Alexey Dobriyan   Use list_head in ...
74
  static LIST_HEAD(formats);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
75
  static DEFINE_RWLOCK(binfmt_lock);
8fc3dc5a3   Al Viro   __register_binfmt...
76
  void __register_binfmt(struct linux_binfmt * fmt, int insert)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
77
  {
8fc3dc5a3   Al Viro   __register_binfmt...
78
  	BUG_ON(!fmt);
92eaa565a   Oleg Nesterov   exec: kill ->load...
79
80
  	if (WARN_ON(!fmt->load_binary))
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
81
  	write_lock(&binfmt_lock);
74641f584   Ivan Kokshaysky   alpha: binfmt_aou...
82
83
  	insert ? list_add(&fmt->lh, &formats) :
  		 list_add_tail(&fmt->lh, &formats);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
84
  	write_unlock(&binfmt_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
85
  }
74641f584   Ivan Kokshaysky   alpha: binfmt_aou...
86
  EXPORT_SYMBOL(__register_binfmt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
87

f6b450d48   Alexey Dobriyan   Make unregister_b...
88
  void unregister_binfmt(struct linux_binfmt * fmt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
  	write_lock(&binfmt_lock);
e4dc1b14d   Alexey Dobriyan   Use list_head in ...
91
  	list_del(&fmt->lh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92
  	write_unlock(&binfmt_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
93
94
95
96
97
98
99
100
  }
  
  EXPORT_SYMBOL(unregister_binfmt);
  
  static inline void put_binfmt(struct linux_binfmt * fmt)
  {
  	module_put(fmt->module);
  }
90f8572b0   Eric W. Biederman   vfs: Commit to ne...
101
102
103
104
105
  bool path_noexec(const struct path *path)
  {
  	return (path->mnt->mnt_flags & MNT_NOEXEC) ||
  	       (path->mnt->mnt_sb->s_iflags & SB_I_NOEXEC);
  }
69369a700   Josh Triplett   fs, kernel: permi...
106
  #ifdef CONFIG_USELIB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
108
109
110
111
112
  /*
   * 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...
113
  SYSCALL_DEFINE1(uselib, const char __user *, library)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
114
  {
72c2d5319   Al Viro   file->f_op is nev...
115
  	struct linux_binfmt *fmt;
964bd1836   Al Viro   [PATCH] get rid o...
116
  	struct file *file;
91a27b2a7   Jeff Layton   vfs: define struc...
117
  	struct filename *tmp = getname(library);
964bd1836   Al Viro   [PATCH] get rid o...
118
  	int error = PTR_ERR(tmp);
47c805dc2   Al Viro   switch do_filp_op...
119
120
  	static const struct open_flags uselib_flags = {
  		.open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC,
62fb4a155   Al Viro   don't carry MAY_O...
121
  		.acc_mode = MAY_READ | MAY_EXEC,
f9652e10c   Al Viro   allow build_open_...
122
123
  		.intent = LOOKUP_OPEN,
  		.lookup_flags = LOOKUP_FOLLOW,
47c805dc2   Al Viro   switch do_filp_op...
124
  	};
964bd1836   Al Viro   [PATCH] get rid o...
125

6e8341a11   Al Viro   Switch open_exec(...
126
127
  	if (IS_ERR(tmp))
  		goto out;
f9652e10c   Al Viro   allow build_open_...
128
  	file = do_filp_open(AT_FDCWD, tmp, &uselib_flags);
6e8341a11   Al Viro   Switch open_exec(...
129
130
131
  	putname(tmp);
  	error = PTR_ERR(file);
  	if (IS_ERR(file))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
132
133
134
  		goto out;
  
  	error = -EINVAL;
496ad9aa8   Al Viro   new helper: file_...
135
  	if (!S_ISREG(file_inode(file)->i_mode))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136
  		goto exit;
30524472c   Al Viro   [PATCH] take noex...
137
  	error = -EACCES;
90f8572b0   Eric W. Biederman   vfs: Commit to ne...
138
  	if (path_noexec(&file->f_path))
6146f0d5e   Mimi Zohar   integrity: IMA hooks
139
  		goto exit;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
140

2a12a9d78   Eric Paris   fsnotify: pass a ...
141
  	fsnotify_open(file);
6110e3abb   Eric Paris   sys_execve and sy...
142

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143
  	error = -ENOEXEC;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
144

72c2d5319   Al Viro   file->f_op is nev...
145
146
147
148
149
150
  	read_lock(&binfmt_lock);
  	list_for_each_entry(fmt, &formats, lh) {
  		if (!fmt->load_shlib)
  			continue;
  		if (!try_module_get(fmt->module))
  			continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
151
  		read_unlock(&binfmt_lock);
72c2d5319   Al Viro   file->f_op is nev...
152
153
154
155
156
  		error = fmt->load_shlib(file);
  		read_lock(&binfmt_lock);
  		put_binfmt(fmt);
  		if (error != -ENOEXEC)
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
157
  	}
72c2d5319   Al Viro   file->f_op is nev...
158
  	read_unlock(&binfmt_lock);
6e8341a11   Al Viro   Switch open_exec(...
159
  exit:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
160
161
162
  	fput(file);
  out:
    	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
  }
69369a700   Josh Triplett   fs, kernel: permi...
164
  #endif /* #ifdef CONFIG_USELIB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
165

b6a2fea39   Ollie Wild   mm: variable leng...
166
  #ifdef CONFIG_MMU
ae6b585ee   Oleg Nesterov   exec: document ac...
167
168
169
170
171
172
  /*
   * The nascent bprm->mm is not visible until exec_mmap() but it can
   * use a lot of memory, account these pages in current->mm temporary
   * for oom_badness()->get_mm_rss(). Once exec succeeds or fails, we
   * change the counter back via acct_arg_size(0).
   */
0e028465d   Oleg Nesterov   exec: unify do_ex...
173
  static void acct_arg_size(struct linux_binprm *bprm, unsigned long pages)
3c77f8457   Oleg Nesterov   exec: make argv/e...
174
175
176
177
178
179
180
181
  {
  	struct mm_struct *mm = current->mm;
  	long diff = (long)(pages - bprm->vma_pages);
  
  	if (!mm || !diff)
  		return;
  
  	bprm->vma_pages = pages;
3c77f8457   Oleg Nesterov   exec: make argv/e...
182
  	add_mm_counter(mm, MM_ANONPAGES, diff);
3c77f8457   Oleg Nesterov   exec: make argv/e...
183
  }
0e028465d   Oleg Nesterov   exec: unify do_ex...
184
  static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
b6a2fea39   Ollie Wild   mm: variable leng...
185
186
187
188
  		int write)
  {
  	struct page *page;
  	int ret;
9beae1ea8   Lorenzo Stoakes   mm: replace get_u...
189
  	unsigned int gup_flags = FOLL_FORCE;
b6a2fea39   Ollie Wild   mm: variable leng...
190
191
192
  
  #ifdef CONFIG_STACK_GROWSUP
  	if (write) {
d05f3169c   Michal Hocko   mm: make expand_d...
193
  		ret = expand_downwards(bprm->vma, pos);
b6a2fea39   Ollie Wild   mm: variable leng...
194
195
196
197
  		if (ret < 0)
  			return NULL;
  	}
  #endif
9beae1ea8   Lorenzo Stoakes   mm: replace get_u...
198
199
200
  
  	if (write)
  		gup_flags |= FOLL_WRITE;
1e9877902   Dave Hansen   mm/gup: Introduce...
201
202
203
204
  	/*
  	 * We are doing an exec().  'current' is the process
  	 * doing the exec and bprm->mm is the new process's mm.
  	 */
9beae1ea8   Lorenzo Stoakes   mm: replace get_u...
205
  	ret = get_user_pages_remote(current, bprm->mm, pos, 1, gup_flags,
5b56d49fc   Lorenzo Stoakes   mm: add locked pa...
206
  			&page, NULL, NULL);
b6a2fea39   Ollie Wild   mm: variable leng...
207
208
209
210
  	if (ret <= 0)
  		return NULL;
  
  	if (write) {
b6a2fea39   Ollie Wild   mm: variable leng...
211
  		unsigned long size = bprm->vma->vm_end - bprm->vma->vm_start;
da029c11e   Kees Cook   exec: Limit arg s...
212
  		unsigned long ptr_size, limit;
a64e715fc   Linus Torvalds   Allow ARG_MAX exe...
213

98da7d088   Kees Cook   fs/exec.c: accoun...
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
  		/*
  		 * Since the stack will hold pointers to the strings, we
  		 * must account for them as well.
  		 *
  		 * The size calculation is the entire vma while each arg page is
  		 * built, so each time we get here it's calculating how far it
  		 * is currently (rather than each call being just the newly
  		 * added size from the arg page).  As a result, we need to
  		 * always add the entire size of the pointers, so that on the
  		 * last call to get_arg_page() we'll actually have the entire
  		 * correct size.
  		 */
  		ptr_size = (bprm->argc + bprm->envc) * sizeof(void *);
  		if (ptr_size > ULONG_MAX - size)
  			goto fail;
  		size += ptr_size;
3c77f8457   Oleg Nesterov   exec: make argv/e...
230
  		acct_arg_size(bprm, size / PAGE_SIZE);
a64e715fc   Linus Torvalds   Allow ARG_MAX exe...
231
232
233
234
235
236
  		/*
  		 * 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...
237
238
  
  		/*
da029c11e   Kees Cook   exec: Limit arg s...
239
240
  		 * Limit to 1/4 of the max stack size or 3/4 of _STK_LIM
  		 * (whichever is smaller) for the argv+env strings.
b6a2fea39   Ollie Wild   mm: variable leng...
241
242
243
244
245
  		 * 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.
  		 */
da029c11e   Kees Cook   exec: Limit arg s...
246
  		limit = _STK_LIM / 4 * 3;
c31dbb146   Kees Cook   exec: pin stack l...
247
  		limit = min(limit, bprm->rlim_stack.rlim_cur / 4);
da029c11e   Kees Cook   exec: Limit arg s...
248
  		if (size > limit)
98da7d088   Kees Cook   fs/exec.c: accoun...
249
  			goto fail;
b6a2fea39   Ollie Wild   mm: variable leng...
250
251
252
  	}
  
  	return page;
98da7d088   Kees Cook   fs/exec.c: accoun...
253
254
255
256
  
  fail:
  	put_page(page);
  	return NULL;
b6a2fea39   Ollie Wild   mm: variable leng...
257
258
259
260
261
262
  }
  
  static void put_arg_page(struct page *page)
  {
  	put_page(page);
  }
b6a2fea39   Ollie Wild   mm: variable leng...
263
264
265
266
267
268
269
270
271
272
273
274
  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_...
275
  	int err;
b6a2fea39   Ollie Wild   mm: variable leng...
276
277
  	struct vm_area_struct *vma = NULL;
  	struct mm_struct *mm = bprm->mm;
490fc0538   Linus Torvalds   mm: make vm_area_...
278
  	bprm->vma = vma = vm_area_alloc(mm);
b6a2fea39   Ollie Wild   mm: variable leng...
279
  	if (!vma)
eaccbfa56   Luiz Fernando N. Capitulino   fs/exec.c:__bprm_...
280
  		return -ENOMEM;
bfd40eaff   Kirill A. Shutemov   mm: fix vma_is_an...
281
  	vma_set_anonymous(vma);
b6a2fea39   Ollie Wild   mm: variable leng...
282

f268dfe90   Michal Hocko   exec: make exec p...
283
284
285
286
  	if (down_write_killable(&mm->mmap_sem)) {
  		err = -EINTR;
  		goto err_free;
  	}
b6a2fea39   Ollie Wild   mm: variable leng...
287
288
289
290
291
292
293
  
  	/*
  	 * 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.
  	 */
aacb3d17a   Michal Hocko   fs/exec.c: use BU...
294
  	BUILD_BUG_ON(VM_STACK_FLAGS & VM_STACK_INCOMPLETE_SETUP);
b6a2fea39   Ollie Wild   mm: variable leng...
295
296
  	vma->vm_end = STACK_TOP_MAX;
  	vma->vm_start = vma->vm_end - PAGE_SIZE;
d9104d1ca   Cyrill Gorcunov   mm: track vma cha...
297
  	vma->vm_flags = VM_SOFTDIRTY | VM_STACK_FLAGS | VM_STACK_INCOMPLETE_SETUP;
3ed75eb8f   Coly Li   setup vma->vm_pag...
298
  	vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
462e635e5   Tavis Ormandy   install_special_m...
299

b6a2fea39   Ollie Wild   mm: variable leng...
300
  	err = insert_vm_struct(mm, vma);
eaccbfa56   Luiz Fernando N. Capitulino   fs/exec.c:__bprm_...
301
  	if (err)
b6a2fea39   Ollie Wild   mm: variable leng...
302
  		goto err;
b6a2fea39   Ollie Wild   mm: variable leng...
303
304
  
  	mm->stack_vm = mm->total_vm = 1;
fe3d197f8   Dave Hansen   x86, mpx: On-dema...
305
  	arch_bprm_mm_init(mm, vma);
b6a2fea39   Ollie Wild   mm: variable leng...
306
  	up_write(&mm->mmap_sem);
b6a2fea39   Ollie Wild   mm: variable leng...
307
  	bprm->p = vma->vm_end - sizeof(void *);
b6a2fea39   Ollie Wild   mm: variable leng...
308
  	return 0;
b6a2fea39   Ollie Wild   mm: variable leng...
309
  err:
eaccbfa56   Luiz Fernando N. Capitulino   fs/exec.c:__bprm_...
310
  	up_write(&mm->mmap_sem);
f268dfe90   Michal Hocko   exec: make exec p...
311
  err_free:
eaccbfa56   Luiz Fernando N. Capitulino   fs/exec.c:__bprm_...
312
  	bprm->vma = NULL;
3928d4f5e   Linus Torvalds   mm: use helper fu...
313
  	vm_area_free(vma);
b6a2fea39   Ollie Wild   mm: variable leng...
314
315
316
317
318
319
320
321
322
  	return err;
  }
  
  static bool valid_arg_len(struct linux_binprm *bprm, long len)
  {
  	return len <= MAX_ARG_STRLEN;
  }
  
  #else
0e028465d   Oleg Nesterov   exec: unify do_ex...
323
  static inline void acct_arg_size(struct linux_binprm *bprm, unsigned long pages)
3c77f8457   Oleg Nesterov   exec: make argv/e...
324
325
  {
  }
0e028465d   Oleg Nesterov   exec: unify do_ex...
326
  static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
b6a2fea39   Ollie Wild   mm: variable leng...
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
  		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().
   */
9cc64ceaa   Yuanhan Liu   fs/exec.c: make b...
386
  static int bprm_mm_init(struct linux_binprm *bprm)
b6a2fea39   Ollie Wild   mm: variable leng...
387
388
389
390
391
392
393
394
  {
  	int err;
  	struct mm_struct *mm = NULL;
  
  	bprm->mm = mm = mm_alloc();
  	err = -ENOMEM;
  	if (!mm)
  		goto err;
c31dbb146   Kees Cook   exec: pin stack l...
395
396
397
398
  	/* Save current stack limit for all calculations made during exec. */
  	task_lock(current->group_leader);
  	bprm->rlim_stack = current->signal->rlim[RLIMIT_STACK];
  	task_unlock(current->group_leader);
b6a2fea39   Ollie Wild   mm: variable leng...
399
400
401
402
403
404
405
406
407
408
409
410
411
412
  	err = __bprm_mm_init(bprm);
  	if (err)
  		goto err;
  
  	return 0;
  
  err:
  	if (mm) {
  		bprm->mm = NULL;
  		mmdrop(mm);
  	}
  
  	return err;
  }
ba2d01629   Oleg Nesterov   exec: introduce s...
413
  struct user_arg_ptr {
0e028465d   Oleg Nesterov   exec: unify do_ex...
414
415
416
417
418
419
  #ifdef CONFIG_COMPAT
  	bool is_compat;
  #endif
  	union {
  		const char __user *const __user *native;
  #ifdef CONFIG_COMPAT
38b983b34   Al Viro   generic sys_execve()
420
  		const compat_uptr_t __user *compat;
0e028465d   Oleg Nesterov   exec: unify do_ex...
421
422
  #endif
  	} ptr;
ba2d01629   Oleg Nesterov   exec: introduce s...
423
424
425
  };
  
  static const char __user *get_user_arg_ptr(struct user_arg_ptr argv, int nr)
1d1dbf813   Oleg Nesterov   exec: introduce g...
426
  {
0e028465d   Oleg Nesterov   exec: unify do_ex...
427
428
429
430
431
432
433
434
  	const char __user *native;
  
  #ifdef CONFIG_COMPAT
  	if (unlikely(argv.is_compat)) {
  		compat_uptr_t compat;
  
  		if (get_user(compat, argv.ptr.compat + nr))
  			return ERR_PTR(-EFAULT);
1d1dbf813   Oleg Nesterov   exec: introduce g...
435

0e028465d   Oleg Nesterov   exec: unify do_ex...
436
437
438
439
440
  		return compat_ptr(compat);
  	}
  #endif
  
  	if (get_user(native, argv.ptr.native + nr))
1d1dbf813   Oleg Nesterov   exec: introduce g...
441
  		return ERR_PTR(-EFAULT);
0e028465d   Oleg Nesterov   exec: unify do_ex...
442
  	return native;
1d1dbf813   Oleg Nesterov   exec: introduce g...
443
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
444
445
446
  /*
   * count() counts the number of strings in array ARGV.
   */
ba2d01629   Oleg Nesterov   exec: introduce s...
447
  static int count(struct user_arg_ptr argv, int max)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
448
449
  {
  	int i = 0;
0e028465d   Oleg Nesterov   exec: unify do_ex...
450
  	if (argv.ptr.native != NULL) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
451
  		for (;;) {
1d1dbf813   Oleg Nesterov   exec: introduce g...
452
  			const char __user *p = get_user_arg_ptr(argv, i);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
453

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
454
455
  			if (!p)
  				break;
1d1dbf813   Oleg Nesterov   exec: introduce g...
456
457
458
  
  			if (IS_ERR(p))
  				return -EFAULT;
6d92d4f6a   Xi Wang   fs/exec.c: work a...
459
  			if (i >= max)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
460
  				return -E2BIG;
6d92d4f6a   Xi Wang   fs/exec.c: work a...
461
  			++i;
9aea5a65a   Roland McGrath   execve: make resp...
462
463
464
  
  			if (fatal_signal_pending(current))
  				return -ERESTARTNOHAND;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
465
466
467
468
469
470
471
  			cond_resched();
  		}
  	}
  	return i;
  }
  
  /*
b6a2fea39   Ollie Wild   mm: variable leng...
472
473
474
   * '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
475
   */
ba2d01629   Oleg Nesterov   exec: introduce s...
476
  static int copy_strings(int argc, struct user_arg_ptr argv,
75c96f858   Adrian Bunk   [PATCH] make some...
477
  			struct linux_binprm *bprm)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
478
479
480
  {
  	struct page *kmapped_page = NULL;
  	char *kaddr = NULL;
b6a2fea39   Ollie Wild   mm: variable leng...
481
  	unsigned long kpos = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
482
483
484
  	int ret;
  
  	while (argc-- > 0) {
d7627467b   David Howells   Make do_execve() ...
485
  		const char __user *str;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
486
487
  		int len;
  		unsigned long pos;
1d1dbf813   Oleg Nesterov   exec: introduce g...
488
489
490
  		ret = -EFAULT;
  		str = get_user_arg_ptr(argv, argc);
  		if (IS_ERR(str))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
491
  			goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
492

1d1dbf813   Oleg Nesterov   exec: introduce g...
493
494
495
496
497
498
  		len = strnlen_user(str, MAX_ARG_STRLEN);
  		if (!len)
  			goto out;
  
  		ret = -E2BIG;
  		if (!valid_arg_len(bprm, len))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
499
  			goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
500

b6a2fea39   Ollie Wild   mm: variable leng...
501
  		/* We're going to work our way backwords. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
502
  		pos = bprm->p;
b6a2fea39   Ollie Wild   mm: variable leng...
503
504
  		str += len;
  		bprm->p -= len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
505
506
  
  		while (len > 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
507
  			int offset, bytes_to_copy;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
508

9aea5a65a   Roland McGrath   execve: make resp...
509
510
511
512
  			if (fatal_signal_pending(current)) {
  				ret = -ERESTARTNOHAND;
  				goto out;
  			}
7993bc1f4   Roland McGrath   execve: improve i...
513
  			cond_resched();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
514
  			offset = pos % PAGE_SIZE;
b6a2fea39   Ollie Wild   mm: variable leng...
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
  			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
531
  				if (!page) {
b6a2fea39   Ollie Wild   mm: variable leng...
532
  					ret = -E2BIG;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
533
534
  					goto out;
  				}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
535

b6a2fea39   Ollie Wild   mm: variable leng...
536
537
  				if (kmapped_page) {
  					flush_kernel_dcache_page(kmapped_page);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
538
  					kunmap(kmapped_page);
b6a2fea39   Ollie Wild   mm: variable leng...
539
540
  					put_arg_page(kmapped_page);
  				}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
541
542
  				kmapped_page = page;
  				kaddr = kmap(kmapped_page);
b6a2fea39   Ollie Wild   mm: variable leng...
543
544
  				kpos = pos & PAGE_MASK;
  				flush_arg_page(bprm, kpos, kmapped_page);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
545
  			}
b6a2fea39   Ollie Wild   mm: variable leng...
546
  			if (copy_from_user(kaddr+offset, str, bytes_to_copy)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
547
548
549
  				ret = -EFAULT;
  				goto out;
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
550
551
552
553
  		}
  	}
  	ret = 0;
  out:
b6a2fea39   Ollie Wild   mm: variable leng...
554
555
  	if (kmapped_page) {
  		flush_kernel_dcache_page(kmapped_page);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
556
  		kunmap(kmapped_page);
b6a2fea39   Ollie Wild   mm: variable leng...
557
558
  		put_arg_page(kmapped_page);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
559
560
561
562
563
564
  	return ret;
  }
  
  /*
   * Like copy_strings, but get argv and its values from kernel memory.
   */
ba2d01629   Oleg Nesterov   exec: introduce s...
565
  int copy_strings_kernel(int argc, const char *const *__argv,
d7627467b   David Howells   Make do_execve() ...
566
  			struct linux_binprm *bprm)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
567
568
569
  {
  	int r;
  	mm_segment_t oldfs = get_fs();
ba2d01629   Oleg Nesterov   exec: introduce s...
570
  	struct user_arg_ptr argv = {
0e028465d   Oleg Nesterov   exec: unify do_ex...
571
  		.ptr.native = (const char __user *const  __user *)__argv,
ba2d01629   Oleg Nesterov   exec: introduce s...
572
  	};
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
573
  	set_fs(KERNEL_DS);
ba2d01629   Oleg Nesterov   exec: introduce s...
574
  	r = copy_strings(argc, argv, bprm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
575
  	set_fs(oldfs);
ba2d01629   Oleg Nesterov   exec: introduce s...
576

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
577
578
  	return r;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
579
580
581
  EXPORT_SYMBOL(copy_strings_kernel);
  
  #ifdef CONFIG_MMU
b6a2fea39   Ollie Wild   mm: variable leng...
582

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
583
  /*
b6a2fea39   Ollie Wild   mm: variable leng...
584
585
586
   * 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
587
   *
b6a2fea39   Ollie Wild   mm: variable leng...
588
589
590
591
592
593
   * 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
594
   */
b6a2fea39   Ollie Wild   mm: variable leng...
595
  static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
596
597
  {
  	struct mm_struct *mm = vma->vm_mm;
b6a2fea39   Ollie Wild   mm: variable leng...
598
599
600
601
602
  	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;
d16dfc550   Peter Zijlstra   mm: mmu_gather re...
603
  	struct mmu_gather tlb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
604

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

b6a2fea39   Ollie Wild   mm: variable leng...
607
608
609
610
611
612
613
614
615
616
  	/*
  	 * 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...
617
618
  	if (vma_adjust(vma, new_start, old_end, vma->vm_pgoff, NULL))
  		return -ENOMEM;
b6a2fea39   Ollie Wild   mm: variable leng...
619
620
621
622
623
624
  
  	/*
  	 * 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,
38a76013a   Michel Lespinasse   mm: avoid taking ...
625
  				       vma, new_start, length, false))
b6a2fea39   Ollie Wild   mm: variable leng...
626
627
628
  		return -ENOMEM;
  
  	lru_add_drain();
2b047252d   Linus Torvalds   Fix TLB gather vi...
629
  	tlb_gather_mmu(&tlb, mm, old_start, old_end);
b6a2fea39   Ollie Wild   mm: variable leng...
630
631
632
633
  	if (new_end > old_start) {
  		/*
  		 * when the old and new regions overlap clear from new_end.
  		 */
d16dfc550   Peter Zijlstra   mm: mmu_gather re...
634
  		free_pgd_range(&tlb, new_end, old_end, new_end,
6ee8630e0   Hugh Dickins   mm: allow arch co...
635
  			vma->vm_next ? vma->vm_next->vm_start : USER_PGTABLES_CEILING);
b6a2fea39   Ollie Wild   mm: variable leng...
636
637
638
639
640
641
642
  	} 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.
  		 */
d16dfc550   Peter Zijlstra   mm: mmu_gather re...
643
  		free_pgd_range(&tlb, old_start, old_end, new_end,
6ee8630e0   Hugh Dickins   mm: allow arch co...
644
  			vma->vm_next ? vma->vm_next->vm_start : USER_PGTABLES_CEILING);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
645
  	}
2b047252d   Linus Torvalds   Fix TLB gather vi...
646
  	tlb_finish_mmu(&tlb, old_start, old_end);
b6a2fea39   Ollie Wild   mm: variable leng...
647
648
  
  	/*
5beb49305   Rik van Riel   mm: change anon_v...
649
  	 * Shrink the vma to just the new range.  Always succeeds.
b6a2fea39   Ollie Wild   mm: variable leng...
650
651
652
653
  	 */
  	vma_adjust(vma, new_start, new_end, vma->vm_pgoff, NULL);
  
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
654
  }
b6a2fea39   Ollie Wild   mm: variable leng...
655
656
657
658
  /*
   * 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
659
660
661
662
  int setup_arg_pages(struct linux_binprm *bprm,
  		    unsigned long stack_top,
  		    int executable_stack)
  {
b6a2fea39   Ollie Wild   mm: variable leng...
663
664
  	unsigned long ret;
  	unsigned long stack_shift;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
665
  	struct mm_struct *mm = current->mm;
b6a2fea39   Ollie Wild   mm: variable leng...
666
667
668
669
  	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...
670
671
672
  	unsigned long stack_size;
  	unsigned long stack_expand;
  	unsigned long rlim_stack;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
673
674
  
  #ifdef CONFIG_STACK_GROWSUP
d71f290b4   James Hogan   metag: Reduce max...
675
  	/* Limit stack size */
c31dbb146   Kees Cook   exec: pin stack l...
676
  	stack_base = bprm->rlim_stack.rlim_max;
d71f290b4   James Hogan   metag: Reduce max...
677
678
  	if (stack_base > STACK_SIZE_MAX)
  		stack_base = STACK_SIZE_MAX;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
679

d045c77c1   Helge Deller   parisc,metag: Fix...
680
681
  	/* Add space for stack randomization. */
  	stack_base += (STACK_RND_MASK << PAGE_SHIFT);
b6a2fea39   Ollie Wild   mm: variable leng...
682
683
684
  	/* 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
685

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

b6a2fea39   Ollie Wild   mm: variable leng...
688
689
690
  	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
691
  #else
b6a2fea39   Ollie Wild   mm: variable leng...
692
693
  	stack_top = arch_align_stack(stack_top);
  	stack_top = PAGE_ALIGN(stack_top);
1b528181b   Roland McGrath   setup_arg_pages: ...
694
695
696
697
  
  	if (unlikely(stack_top < mmap_min_addr) ||
  	    unlikely(vma->vm_end - vma->vm_start >= stack_top - mmap_min_addr))
  		return -ENOMEM;
b6a2fea39   Ollie Wild   mm: variable leng...
698
699
700
  	stack_shift = vma->vm_end - stack_top;
  
  	bprm->p -= stack_shift;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
701
  	mm->arg_start = bprm->p;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
702
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
703
  	if (bprm->loader)
b6a2fea39   Ollie Wild   mm: variable leng...
704
705
  		bprm->loader -= stack_shift;
  	bprm->exec -= stack_shift;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
706

f268dfe90   Michal Hocko   exec: make exec p...
707
708
  	if (down_write_killable(&mm->mmap_sem))
  		return -EINTR;
96a8e13ed   Hugh Dickins   exec: fix stack e...
709
  	vm_flags = VM_STACK_FLAGS;
b6a2fea39   Ollie Wild   mm: variable leng...
710
711
712
713
714
715
716
717
718
719
720
  
  	/*
  	 * 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;
a8bef8ff6   Mel Gorman   mm: migration: av...
721
  	vm_flags |= VM_STACK_INCOMPLETE_SETUP;
b6a2fea39   Ollie Wild   mm: variable leng...
722
723
724
725
726
727
728
729
730
731
  
  	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...
732
733
  		if (ret)
  			goto out_unlock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
734
  	}
a8bef8ff6   Mel Gorman   mm: migration: av...
735
736
  	/* mprotect_fixup is overkill to remove the temporary stack flags */
  	vma->vm_flags &= ~VM_STACK_INCOMPLETE_SETUP;
5ef097dd7   Michael Neuling   exec: create init...
737
  	stack_expand = 131072UL; /* randomly 32*4k (or 2*64k) pages */
803bf5ec2   Michael Neuling   fs/exec.c: restri...
738
739
740
741
742
  	stack_size = vma->vm_end - vma->vm_start;
  	/*
  	 * Align this down to a page boundary as expand_stack
  	 * will align it up.
  	 */
c31dbb146   Kees Cook   exec: pin stack l...
743
  	rlim_stack = bprm->rlim_stack.rlim_cur & PAGE_MASK;
b6a2fea39   Ollie Wild   mm: variable leng...
744
  #ifdef CONFIG_STACK_GROWSUP
803bf5ec2   Michael Neuling   fs/exec.c: restri...
745
746
747
748
  	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...
749
  #else
803bf5ec2   Michael Neuling   fs/exec.c: restri...
750
751
752
753
  	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...
754
  #endif
3af9e8592   Eric B Munson   perf: Add non-exe...
755
  	current->mm->start_stack = bprm->p;
b6a2fea39   Ollie Wild   mm: variable leng...
756
757
758
759
760
  	ret = expand_stack(vma, stack_base);
  	if (ret)
  		ret = -EFAULT;
  
  out_unlock:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
761
  	up_write(&mm->mmap_sem);
fc63cf237   Anton Blanchard   exec: setup_arg_p...
762
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
763
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
764
  EXPORT_SYMBOL(setup_arg_pages);
7e7ec6a93   Nicolas Pitre   elf_fdpic_transfe...
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
  #else
  
  /*
   * Transfer the program arguments and environment from the holding pages
   * onto the stack. The provided stack pointer is adjusted accordingly.
   */
  int transfer_args_to_stack(struct linux_binprm *bprm,
  			   unsigned long *sp_location)
  {
  	unsigned long index, stop, sp;
  	int ret = 0;
  
  	stop = bprm->p >> PAGE_SHIFT;
  	sp = *sp_location;
  
  	for (index = MAX_ARG_PAGES - 1; index >= stop; index--) {
  		unsigned int offset = index == stop ? bprm->p & ~PAGE_MASK : 0;
  		char *src = kmap(bprm->page[index]) + offset;
  		sp -= PAGE_SIZE - offset;
  		if (copy_to_user((void *) sp, src, PAGE_SIZE - offset) != 0)
  			ret = -EFAULT;
  		kunmap(bprm->page[index]);
  		if (ret)
  			goto out;
  	}
  
  	*sp_location = sp;
  
  out:
  	return ret;
  }
  EXPORT_SYMBOL(transfer_args_to_stack);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
797
  #endif /* CONFIG_MMU */
51f39a1f0   David Drysdale   syscalls: impleme...
798
  static struct file *do_open_execat(int fd, struct filename *name, int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
799
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
800
  	struct file *file;
e56b6a5dd   Christoph Hellwig   Re: [PATCH 3/6] v...
801
  	int err;
51f39a1f0   David Drysdale   syscalls: impleme...
802
  	struct open_flags open_exec_flags = {
47c805dc2   Al Viro   switch do_filp_op...
803
  		.open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC,
62fb4a155   Al Viro   don't carry MAY_O...
804
  		.acc_mode = MAY_EXEC,
f9652e10c   Al Viro   allow build_open_...
805
806
  		.intent = LOOKUP_OPEN,
  		.lookup_flags = LOOKUP_FOLLOW,
47c805dc2   Al Viro   switch do_filp_op...
807
  	};
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
808

51f39a1f0   David Drysdale   syscalls: impleme...
809
810
811
812
813
814
815
816
  	if ((flags & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) != 0)
  		return ERR_PTR(-EINVAL);
  	if (flags & AT_SYMLINK_NOFOLLOW)
  		open_exec_flags.lookup_flags &= ~LOOKUP_FOLLOW;
  	if (flags & AT_EMPTY_PATH)
  		open_exec_flags.lookup_flags |= LOOKUP_EMPTY;
  
  	file = do_filp_open(fd, name, &open_exec_flags);
6e8341a11   Al Viro   Switch open_exec(...
817
  	if (IS_ERR(file))
e56b6a5dd   Christoph Hellwig   Re: [PATCH 3/6] v...
818
819
820
  		goto out;
  
  	err = -EACCES;
496ad9aa8   Al Viro   new helper: file_...
821
  	if (!S_ISREG(file_inode(file)->i_mode))
6e8341a11   Al Viro   Switch open_exec(...
822
  		goto exit;
e56b6a5dd   Christoph Hellwig   Re: [PATCH 3/6] v...
823

90f8572b0   Eric W. Biederman   vfs: Commit to ne...
824
  	if (path_noexec(&file->f_path))
6e8341a11   Al Viro   Switch open_exec(...
825
  		goto exit;
e56b6a5dd   Christoph Hellwig   Re: [PATCH 3/6] v...
826
827
  
  	err = deny_write_access(file);
6e8341a11   Al Viro   Switch open_exec(...
828
829
  	if (err)
  		goto exit;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
830

51f39a1f0   David Drysdale   syscalls: impleme...
831
832
  	if (name->name[0] != '\0')
  		fsnotify_open(file);
6e8341a11   Al Viro   Switch open_exec(...
833
  out:
e56b6a5dd   Christoph Hellwig   Re: [PATCH 3/6] v...
834
  	return file;
6e8341a11   Al Viro   Switch open_exec(...
835
836
  exit:
  	fput(file);
e56b6a5dd   Christoph Hellwig   Re: [PATCH 3/6] v...
837
838
  	return ERR_PTR(err);
  }
c4ad8f98b   Linus Torvalds   execve: use 'stru...
839
840
841
  
  struct file *open_exec(const char *name)
  {
516891041   Paul Moore   fs: create proper...
842
843
844
845
846
847
848
849
  	struct filename *filename = getname_kernel(name);
  	struct file *f = ERR_CAST(filename);
  
  	if (!IS_ERR(filename)) {
  		f = do_open_execat(AT_FDCWD, filename, 0);
  		putname(filename);
  	}
  	return f;
c4ad8f98b   Linus Torvalds   execve: use 'stru...
850
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
851
  EXPORT_SYMBOL(open_exec);
b44a7dfc6   Mimi Zohar   vfs: define a gen...
852
  int kernel_read_file(struct file *file, void **buf, loff_t *size,
bc8ca5b92   Mimi Zohar   vfs: define kerne...
853
  		     loff_t max_size, enum kernel_read_file_id id)
b44a7dfc6   Mimi Zohar   vfs: define a gen...
854
855
856
857
858
859
860
  {
  	loff_t i_size, pos;
  	ssize_t bytes = 0;
  	int ret;
  
  	if (!S_ISREG(file_inode(file)->i_mode) || max_size < 0)
  		return -EINVAL;
7bd698b3c   Kees Cook   exec: Set file un...
861
  	ret = deny_write_access(file);
39eeb4fb9   Mimi Zohar   security: define ...
862
863
  	if (ret)
  		return ret;
7bd698b3c   Kees Cook   exec: Set file un...
864
  	ret = security_kernel_read_file(file, id);
39d637af5   Dmitry Kasatkin   vfs: forbid write...
865
  	if (ret)
7bd698b3c   Kees Cook   exec: Set file un...
866
  		goto out;
39d637af5   Dmitry Kasatkin   vfs: forbid write...
867

b44a7dfc6   Mimi Zohar   vfs: define a gen...
868
  	i_size = i_size_read(file_inode(file));
39d637af5   Dmitry Kasatkin   vfs: forbid write...
869
870
871
872
873
874
875
876
  	if (max_size > 0 && i_size > max_size) {
  		ret = -EFBIG;
  		goto out;
  	}
  	if (i_size <= 0) {
  		ret = -EINVAL;
  		goto out;
  	}
b44a7dfc6   Mimi Zohar   vfs: define a gen...
877

a098ecd2f   Stephen Boyd   firmware: support...
878
879
  	if (id != READING_FIRMWARE_PREALLOC_BUFFER)
  		*buf = vmalloc(i_size);
39d637af5   Dmitry Kasatkin   vfs: forbid write...
880
881
882
883
  	if (!*buf) {
  		ret = -ENOMEM;
  		goto out;
  	}
b44a7dfc6   Mimi Zohar   vfs: define a gen...
884
885
886
  
  	pos = 0;
  	while (pos < i_size) {
bdd1d2d3d   Christoph Hellwig   fs: fix kernel_re...
887
  		bytes = kernel_read(file, *buf + pos, i_size - pos, &pos);
b44a7dfc6   Mimi Zohar   vfs: define a gen...
888
889
  		if (bytes < 0) {
  			ret = bytes;
b60d90b2d   YueHaibing   exec: Fix mem lea...
890
  			goto out_free;
b44a7dfc6   Mimi Zohar   vfs: define a gen...
891
892
893
894
  		}
  
  		if (bytes == 0)
  			break;
b44a7dfc6   Mimi Zohar   vfs: define a gen...
895
896
897
898
  	}
  
  	if (pos != i_size) {
  		ret = -EIO;
39d637af5   Dmitry Kasatkin   vfs: forbid write...
899
  		goto out_free;
b44a7dfc6   Mimi Zohar   vfs: define a gen...
900
  	}
bc8ca5b92   Mimi Zohar   vfs: define kerne...
901
  	ret = security_kernel_post_read_file(file, *buf, i_size, id);
b44a7dfc6   Mimi Zohar   vfs: define a gen...
902
903
  	if (!ret)
  		*size = pos;
39d637af5   Dmitry Kasatkin   vfs: forbid write...
904
  out_free:
b44a7dfc6   Mimi Zohar   vfs: define a gen...
905
  	if (ret < 0) {
a098ecd2f   Stephen Boyd   firmware: support...
906
907
908
909
  		if (id != READING_FIRMWARE_PREALLOC_BUFFER) {
  			vfree(*buf);
  			*buf = NULL;
  		}
b44a7dfc6   Mimi Zohar   vfs: define a gen...
910
  	}
39d637af5   Dmitry Kasatkin   vfs: forbid write...
911
912
913
  
  out:
  	allow_write_access(file);
b44a7dfc6   Mimi Zohar   vfs: define a gen...
914
915
916
  	return ret;
  }
  EXPORT_SYMBOL_GPL(kernel_read_file);
711aab1db   Mimi Zohar   vfs: constify pat...
917
  int kernel_read_file_from_path(const char *path, void **buf, loff_t *size,
09596b94f   Mimi Zohar   vfs: define kerne...
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
  			       loff_t max_size, enum kernel_read_file_id id)
  {
  	struct file *file;
  	int ret;
  
  	if (!path || !*path)
  		return -EINVAL;
  
  	file = filp_open(path, O_RDONLY, 0);
  	if (IS_ERR(file))
  		return PTR_ERR(file);
  
  	ret = kernel_read_file(file, buf, size, max_size, id);
  	fput(file);
  	return ret;
  }
  EXPORT_SYMBOL_GPL(kernel_read_file_from_path);
b844f0ecb   Mimi Zohar   vfs: define kerne...
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
  int kernel_read_file_from_fd(int fd, void **buf, loff_t *size, loff_t max_size,
  			     enum kernel_read_file_id id)
  {
  	struct fd f = fdget(fd);
  	int ret = -EBADF;
  
  	if (!f.file)
  		goto out;
  
  	ret = kernel_read_file(f.file, buf, size, max_size, id);
  out:
  	fdput(f);
  	return ret;
  }
  EXPORT_SYMBOL_GPL(kernel_read_file_from_fd);
3dc20cb28   Al Viro   new helper: read_...
950
951
  ssize_t read_code(struct file *file, unsigned long addr, loff_t pos, size_t len)
  {
ec6955798   Al Viro   read_code(): go t...
952
  	ssize_t res = vfs_read(file, (void __user *)addr, len, &pos);
3dc20cb28   Al Viro   new helper: read_...
953
954
955
956
957
  	if (res > 0)
  		flush_icache_range(addr, addr + len);
  	return res;
  }
  EXPORT_SYMBOL(read_code);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
958
959
960
  static int exec_mmap(struct mm_struct *mm)
  {
  	struct task_struct *tsk;
615d6e875   Davidlohr Bueso   mm: per-thread vm...
961
  	struct mm_struct *old_mm, *active_mm;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
962
963
964
965
966
967
968
  
  	/* Notify parent that we're no longer interested in the old VM */
  	tsk = current;
  	old_mm = current->mm;
  	mm_release(tsk, old_mm);
  
  	if (old_mm) {
4fe7efdbd   Konstantin Khlebnikov   mm: correctly syn...
969
  		sync_mm_rss(old_mm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
970
971
972
973
  		/*
  		 * 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...
974
  		 * checking core_state and changing tsk->mm.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
975
976
  		 */
  		down_read(&old_mm->mmap_sem);
999d9fc16   Oleg Nesterov   coredump: move mm...
977
  		if (unlikely(old_mm->core_state)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
978
979
980
981
982
983
984
985
986
  			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);
615d6e875   Davidlohr Bueso   mm: per-thread vm...
987
988
  	tsk->mm->vmacache_seqnum = 0;
  	vmacache_flush(tsk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
989
  	task_unlock(tsk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
990
991
  	if (old_mm) {
  		up_read(&old_mm->mmap_sem);
7dddb12c6   Eric Sesterhenn   BUG_ON() Conversi...
992
  		BUG_ON(active_mm != old_mm);
701085b21   Oleg Nesterov   exec: move de_thr...
993
  		setmax_mm_hiwater_rss(&tsk->signal->maxrss, old_mm);
31a78f23b   Balbir Singh   mm owner: fix rac...
994
  		mm_update_next_owner(old_mm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
  		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...
1008
  static int de_thread(struct task_struct *tsk)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1009
1010
  {
  	struct signal_struct *sig = tsk->signal;
b2c903b87   Oleg Nesterov   exec: simplify th...
1011
  	struct sighand_struct *oldsighand = tsk->sighand;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1012
  	spinlock_t *lock = &oldsighand->siglock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1013

aafe6c2a2   Eric W. Biederman   [PATCH] de_thread...
1014
  	if (thread_group_empty(tsk))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1015
1016
1017
1018
  		goto no_thread_group;
  
  	/*
  	 * Kill all other threads in the thread group.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1019
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1020
  	spin_lock_irq(lock);
ed5d2cac1   Oleg Nesterov   exec: rework the ...
1021
  	if (signal_group_exit(sig)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1022
1023
1024
1025
1026
  		/*
  		 * 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
1027
1028
  		return -EAGAIN;
  	}
d344193a0   Oleg Nesterov   exit: avoid sig->...
1029

ed5d2cac1   Oleg Nesterov   exec: rework the ...
1030
  	sig->group_exit_task = tsk;
d344193a0   Oleg Nesterov   exit: avoid sig->...
1031
1032
1033
  	sig->notify_count = zap_other_threads(tsk);
  	if (!thread_group_leader(tsk))
  		sig->notify_count--;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1034

d344193a0   Oleg Nesterov   exit: avoid sig->...
1035
  	while (sig->notify_count) {
d5bbd43d5   Oleg Nesterov   exec: make de_thr...
1036
  		__set_current_state(TASK_KILLABLE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1037
1038
  		spin_unlock_irq(lock);
  		schedule();
d5bbd43d5   Oleg Nesterov   exec: make de_thr...
1039
1040
  		if (unlikely(__fatal_signal_pending(tsk)))
  			goto killed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1041
1042
  		spin_lock_irq(lock);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1043
1044
1045
1046
1047
1048
1049
  	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...
1050
  	if (!thread_group_leader(tsk)) {
8187926bd   Oleg Nesterov   posix-timers: sim...
1051
  		struct task_struct *leader = tsk->group_leader;
6db840fa7   Oleg Nesterov   exec: RT sub-thre...
1052

6db840fa7   Oleg Nesterov   exec: RT sub-thre...
1053
  		for (;;) {
780de9dd2   Ingo Molnar   sched/headers, cg...
1054
  			cgroup_threadgroup_change_begin(tsk);
6db840fa7   Oleg Nesterov   exec: RT sub-thre...
1055
  			write_lock_irq(&tasklist_lock);
dfcce791f   Kirill Tkhai   fs/exec.c:de_thre...
1056
1057
1058
1059
1060
  			/*
  			 * Do this under tasklist_lock to ensure that
  			 * exit_notify() can't miss ->group_exit_task
  			 */
  			sig->notify_count = -1;
6db840fa7   Oleg Nesterov   exec: RT sub-thre...
1061
1062
  			if (likely(leader->exit_state))
  				break;
d5bbd43d5   Oleg Nesterov   exec: make de_thr...
1063
  			__set_current_state(TASK_KILLABLE);
6db840fa7   Oleg Nesterov   exec: RT sub-thre...
1064
  			write_unlock_irq(&tasklist_lock);
780de9dd2   Ingo Molnar   sched/headers, cg...
1065
  			cgroup_threadgroup_change_end(tsk);
6db840fa7   Oleg Nesterov   exec: RT sub-thre...
1066
  			schedule();
d5bbd43d5   Oleg Nesterov   exec: make de_thr...
1067
1068
  			if (unlikely(__fatal_signal_pending(tsk)))
  				goto killed;
6db840fa7   Oleg Nesterov   exec: RT sub-thre...
1069
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1070

f5e902817   Roland McGrath   [PATCH] process a...
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
  		/*
  		 * 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...
1081
  		tsk->start_time = leader->start_time;
266b7a021   Oleg Nesterov   fs/exec.c:de_thre...
1082
  		tsk->real_start_time = leader->real_start_time;
f5e902817   Roland McGrath   [PATCH] process a...
1083

bac0abd61   Pavel Emelyanov   Isolate some expl...
1084
1085
  		BUG_ON(!same_thread_group(leader, tsk));
  		BUG_ON(has_group_leader_pid(tsk));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1086
1087
1088
1089
1090
1091
  		/*
  		 * 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: ...
1092
1093
  
  		/* Become a process group leader with the old leader's pid.
c18258c6f   Eric W. Biederman   [PATCH] pid: Impl...
1094
1095
  		 * 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: ...
1096
1097
  		 *       is called.  Odd but simple and correct.
  		 */
aafe6c2a2   Eric W. Biederman   [PATCH] de_thread...
1098
  		tsk->pid = leader->pid;
3f4185483   Oleg Nesterov   fs/exec.c:de_thre...
1099
  		change_pid(tsk, PIDTYPE_PID, task_pid(leader));
6883f81aa   Eric W. Biederman   pid: Implement PI...
1100
  		transfer_pid(leader, tsk, PIDTYPE_TGID);
aafe6c2a2   Eric W. Biederman   [PATCH] de_thread...
1101
1102
  		transfer_pid(leader, tsk, PIDTYPE_PGID);
  		transfer_pid(leader, tsk, PIDTYPE_SID);
9cd80bbb0   Oleg Nesterov   do_wait() optimiz...
1103

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

aafe6c2a2   Eric W. Biederman   [PATCH] de_thread...
1107
1108
  		tsk->group_leader = tsk;
  		leader->group_leader = tsk;
de12a7878   Eric W. Biederman   [PATCH] de_thread...
1109

aafe6c2a2   Eric W. Biederman   [PATCH] de_thread...
1110
  		tsk->exit_signal = SIGCHLD;
087806b12   Oleg Nesterov   redefine thread_g...
1111
  		leader->exit_signal = -1;
962b564cf   Oleg Nesterov   [PATCH] fix do_wa...
1112
1113
1114
  
  		BUG_ON(leader->exit_state != EXIT_ZOMBIE);
  		leader->exit_state = EXIT_DEAD;
eac1b5e57   Oleg Nesterov   ptrace: do_wait(t...
1115
1116
1117
1118
1119
1120
1121
1122
  
  		/*
  		 * We are going to release_task()->ptrace_unlink() silently,
  		 * the tracer can sleep in do_wait(). EXIT_DEAD guarantees
  		 * the tracer wont't block again waiting for this thread.
  		 */
  		if (unlikely(leader->ptrace))
  			__wake_up_parent(leader, leader->parent);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1123
  		write_unlock_irq(&tasklist_lock);
780de9dd2   Ingo Molnar   sched/headers, cg...
1124
  		cgroup_threadgroup_change_end(tsk);
8187926bd   Oleg Nesterov   posix-timers: sim...
1125
1126
  
  		release_task(leader);
ed5d2cac1   Oleg Nesterov   exec: rework the ...
1127
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1128

6db840fa7   Oleg Nesterov   exec: RT sub-thre...
1129
1130
  	sig->group_exit_task = NULL;
  	sig->notify_count = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1131
1132
  
  no_thread_group:
e63682534   Oleg Nesterov   exit_signal: simp...
1133
1134
  	/* we have changed execution domain */
  	tsk->exit_signal = SIGCHLD;
baa73d9e4   Nicolas Pitre   posix-timers: Mak...
1135
  #ifdef CONFIG_POSIX_TIMERS
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1136
  	exit_itimers(sig);
cbaffba12   Oleg Nesterov   posix timers: dis...
1137
  	flush_itimer_signals();
baa73d9e4   Nicolas Pitre   posix-timers: Mak...
1138
  #endif
329f7dba5   Oleg Nesterov   [PATCH] fix de_th...
1139

b2c903b87   Oleg Nesterov   exec: simplify th...
1140
1141
  	if (atomic_read(&oldsighand->count) != 1) {
  		struct sighand_struct *newsighand;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1142
  		/*
b2c903b87   Oleg Nesterov   exec: simplify th...
1143
1144
  		 * 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
1145
  		 */
b2c903b87   Oleg Nesterov   exec: simplify th...
1146
1147
1148
  		newsighand = kmem_cache_alloc(sighand_cachep, GFP_KERNEL);
  		if (!newsighand)
  			return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1149
1150
1151
1152
1153
1154
  		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...
1155
  		rcu_assign_pointer(tsk->sighand, newsighand);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1156
1157
  		spin_unlock(&oldsighand->siglock);
  		write_unlock_irq(&tasklist_lock);
fba2afaae   Davide Libenzi   signal/timer/even...
1158
  		__cleanup_sighand(oldsighand);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1159
  	}
aafe6c2a2   Eric W. Biederman   [PATCH] de_thread...
1160
  	BUG_ON(!thread_group_leader(tsk));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1161
  	return 0;
d5bbd43d5   Oleg Nesterov   exec: make de_thr...
1162
1163
1164
1165
1166
1167
1168
1169
  
  killed:
  	/* protects against exit_notify() and __exit_signal() */
  	read_lock(&tasklist_lock);
  	sig->group_exit_task = NULL;
  	sig->notify_count = 0;
  	read_unlock(&tasklist_lock);
  	return -EAGAIN;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1170
  }
0840a90d9   Oleg Nesterov   exec: simplify ->...
1171

3756f6401   Arnd Bergmann   exec: avoid gcc-8...
1172
  char *__get_task_comm(char *buf, size_t buf_size, struct task_struct *tsk)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1173
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1174
  	task_lock(tsk);
3756f6401   Arnd Bergmann   exec: avoid gcc-8...
1175
  	strncpy(buf, tsk->comm, buf_size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1176
  	task_unlock(tsk);
59714d65d   Andrew Morton   get_task_comm(): ...
1177
  	return buf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1178
  }
3756f6401   Arnd Bergmann   exec: avoid gcc-8...
1179
  EXPORT_SYMBOL_GPL(__get_task_comm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1180

6a6d27de3   Al Viro   take close-on-exe...
1181
1182
1183
1184
  /*
   * These functions flushes out all traces of the currently running executable
   * so that a new one can be started
   */
82b897782   Adrian Hunter   perf: Differentia...
1185
  void __set_task_comm(struct task_struct *tsk, const char *buf, bool exec)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1186
1187
  {
  	task_lock(tsk);
43d2b1132   KAMEZAWA Hiroyuki   tracepoint: add t...
1188
  	trace_task_rename(tsk, buf);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1189
1190
  	strlcpy(tsk->comm, buf, sizeof(tsk->comm));
  	task_unlock(tsk);
82b897782   Adrian Hunter   perf: Differentia...
1191
  	perf_event_comm(tsk, exec);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1192
  }
a9208e42b   Kees Cook   exec: Correct com...
1193
1194
1195
1196
1197
1198
  /*
   * Calling this is the point of no return. None of the failures will be
   * seen by userspace since either the process is already taking a fatal
   * signal (via de_thread() or coredump), or will have SEGV raised
   * (after exec_mmap()) by search_binary_handlers (see below).
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1199
1200
  int flush_old_exec(struct linux_binprm * bprm)
  {
221af7f87   Linus Torvalds   Split 'flush_old_...
1201
  	int retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1202
1203
1204
1205
1206
1207
1208
1209
  
  	/*
  	 * 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;
6e399cd14   Davidlohr Bueso   prctl: avoid usin...
1210
1211
1212
1213
1214
  	/*
  	 * Must be called _before_ exec_mmap() as bprm->mm is
  	 * not visibile until then. This also enables the update
  	 * to be lockless.
  	 */
925d1c401   Matt Helsley   procfs task exe s...
1215
  	set_mm_exe_file(bprm->mm, bprm->file);
6e399cd14   Davidlohr Bueso   prctl: avoid usin...
1216

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1217
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1218
1219
  	 * Release all of the old mmap stuff
  	 */
3c77f8457   Oleg Nesterov   exec: make argv/e...
1220
  	acct_arg_size(bprm, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1221
1222
  	retval = exec_mmap(bprm->mm);
  	if (retval)
fd8328be8   Al Viro   [PATCH] sanitize ...
1223
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1224

a9208e42b   Kees Cook   exec: Correct com...
1225
1226
1227
1228
1229
1230
1231
  	/*
  	 * After clearing bprm->mm (to mark that current is using the
  	 * prepared mm now), we have nothing left of the original
  	 * process. If anything from here on returns an error, the check
  	 * in search_binary_handler() will SEGV current.
  	 */
  	bprm->mm = NULL;
7ab02af42   Linus Torvalds   Fix 'flush_old_ex...
1232

dac853ae8   Mathias Krause   exec: delay addre...
1233
  	set_fs(USER_DS);
b88fae644   Zhang Yi   exec: avoid propa...
1234
1235
  	current->flags &= ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD |
  					PF_NOFREEZE | PF_NO_SETAFFINITY);
7ab02af42   Linus Torvalds   Fix 'flush_old_ex...
1236
1237
  	flush_thread();
  	current->personality &= ~bprm->per_clear;
613cc2b6f   Aleksa Sarai   fs: exec: apply C...
1238
1239
1240
1241
1242
1243
1244
  	/*
  	 * We have to apply CLOEXEC before we change whether the process is
  	 * dumpable (in setup_new_exec) to avoid a race with a process in userspace
  	 * trying to access the should-be-closed file descriptors of a process
  	 * undergoing exec(2).
  	 */
  	do_close_on_exec(current->files);
221af7f87   Linus Torvalds   Split 'flush_old_...
1245
1246
1247
1248
1249
1250
  	return 0;
  
  out:
  	return retval;
  }
  EXPORT_SYMBOL(flush_old_exec);
1b5d783c9   Al Viro   consolidate BINPR...
1251
1252
  void would_dump(struct linux_binprm *bprm, struct file *file)
  {
f84df2a6f   Eric W. Biederman   exec: Ensure mm->...
1253
1254
1255
  	struct inode *inode = file_inode(file);
  	if (inode_permission(inode, MAY_READ) < 0) {
  		struct user_namespace *old, *user_ns;
1b5d783c9   Al Viro   consolidate BINPR...
1256
  		bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP;
f84df2a6f   Eric W. Biederman   exec: Ensure mm->...
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
  
  		/* Ensure mm->user_ns contains the executable */
  		user_ns = old = bprm->mm->user_ns;
  		while ((user_ns != &init_user_ns) &&
  		       !privileged_wrt_inode_uidgid(user_ns, inode))
  			user_ns = user_ns->parent;
  
  		if (old != user_ns) {
  			bprm->mm->user_ns = get_user_ns(user_ns);
  			put_user_ns(old);
  		}
  	}
1b5d783c9   Al Viro   consolidate BINPR...
1269
1270
  }
  EXPORT_SYMBOL(would_dump);
221af7f87   Linus Torvalds   Split 'flush_old_...
1271
1272
  void setup_new_exec(struct linux_binprm * bprm)
  {
46d98eb4e   Kees Cook   commoncap: Refact...
1273
1274
1275
1276
1277
1278
  	/*
  	 * Once here, prepare_binrpm() will not be called any more, so
  	 * the final state of setuid/setgid/fscaps can be merged into the
  	 * secureexec flag.
  	 */
  	bprm->secureexec |= bprm->cap_elevated;
64701dee4   Kees Cook   exec: Use sane st...
1279
  	if (bprm->secureexec) {
fe8993b3a   Kees Cook   exec: Consolidate...
1280
1281
  		/* Make sure parent cannot signal privileged process. */
  		current->pdeath_signal = 0;
64701dee4   Kees Cook   exec: Use sane st...
1282
1283
1284
1285
1286
  		/*
  		 * For secureexec, reset the stack limit to sane default to
  		 * avoid bad behavior from the prior rlimits. This has to
  		 * happen before arch_pick_mmap_layout(), which examines
  		 * RLIMIT_STACK, but after the point of no return to avoid
779f4e1c6   Kees Cook   Revert "exec: avo...
1287
  		 * needing to clean up the change on failure.
64701dee4   Kees Cook   exec: Use sane st...
1288
  		 */
c31dbb146   Kees Cook   exec: pin stack l...
1289
1290
  		if (bprm->rlim_stack.rlim_cur > _STK_LIM)
  			bprm->rlim_stack.rlim_cur = _STK_LIM;
64701dee4   Kees Cook   exec: Use sane st...
1291
  	}
c31dbb146   Kees Cook   exec: pin stack l...
1292
  	arch_pick_mmap_layout(current->mm, &bprm->rlim_stack);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1293

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1294
  	current->sas_ss_sp = current->sas_ss_size = 0;
e816c201a   Kees Cook   exec: Weaken dump...
1295
1296
1297
1298
1299
  	/*
  	 * Figure out dumpability. Note that this checking only of current
  	 * is wrong, but userspace depends on it. This should be testing
  	 * bprm->secureexec instead.
  	 */
473d89639   Kees Cook   exec: Consolidate...
1300
  	if (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP ||
e816c201a   Kees Cook   exec: Weaken dump...
1301
1302
  	    !(uid_eq(current_euid(), current_uid()) &&
  	      gid_eq(current_egid(), current_gid())))
6c5d52382   Kawai, Hidehiro   coredump masking:...
1303
  		set_dumpable(current->mm, suid_dumpable);
473d89639   Kees Cook   exec: Consolidate...
1304
1305
  	else
  		set_dumpable(current->mm, SUID_DUMP_USER);
d6e711448   Alan Cox   [PATCH] setuid co...
1306

e9ea1e7f5   Kyle Huey   x86/arch_prctl: A...
1307
  	arch_setup_new_exec();
e041e328c   Peter Zijlstra   perf: Fix perf_ev...
1308
  	perf_event_exec();
82b897782   Adrian Hunter   perf: Differentia...
1309
  	__set_task_comm(current, kbasename(bprm->filename), true);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1310

0551fbd29   Benjamin Herrenschmidt   [PATCH] Add mm->t...
1311
1312
1313
1314
1315
  	/* 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;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1316
1317
  	/* An exec changes our domain. We are no longer part of the thread
  	   group */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1318
  	current->self_exec_id++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1319
  	flush_signal_handlers(current, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1320
  }
221af7f87   Linus Torvalds   Split 'flush_old_...
1321
  EXPORT_SYMBOL(setup_new_exec);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1322

b83838313   Kees Cook   exec: introduce f...
1323
1324
1325
  /* Runs immediately before start_thread() takes over. */
  void finalize_exec(struct linux_binprm *bprm)
  {
c31dbb146   Kees Cook   exec: pin stack l...
1326
1327
1328
1329
  	/* Store any stack rlimit changes before starting thread. */
  	task_lock(current->group_leader);
  	current->signal->rlim[RLIMIT_STACK] = bprm->rlim_stack;
  	task_unlock(current->group_leader);
b83838313   Kees Cook   exec: introduce f...
1330
1331
  }
  EXPORT_SYMBOL(finalize_exec);
a6f76f23d   David Howells   CRED: Make execve...
1332
  /*
a2a8474c3   Oleg Nesterov   exec: do not slee...
1333
1334
1335
1336
1337
1338
1339
   * 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)
  {
9b1bf12d5   KOSAKI Motohiro   signals: move cre...
1340
  	if (mutex_lock_interruptible(&current->signal->cred_guard_mutex))
a2a8474c3   Oleg Nesterov   exec: do not slee...
1341
1342
1343
1344
1345
  		return -ERESTARTNOINTR;
  
  	bprm->cred = prepare_exec_creds();
  	if (likely(bprm->cred))
  		return 0;
9b1bf12d5   KOSAKI Motohiro   signals: move cre...
1346
  	mutex_unlock(&current->signal->cred_guard_mutex);
a2a8474c3   Oleg Nesterov   exec: do not slee...
1347
1348
  	return -ENOMEM;
  }
c4ad8f98b   Linus Torvalds   execve: use 'stru...
1349
  static void free_bprm(struct linux_binprm *bprm)
a2a8474c3   Oleg Nesterov   exec: do not slee...
1350
1351
1352
  {
  	free_arg_pages(bprm);
  	if (bprm->cred) {
9b1bf12d5   KOSAKI Motohiro   signals: move cre...
1353
  		mutex_unlock(&current->signal->cred_guard_mutex);
a2a8474c3   Oleg Nesterov   exec: do not slee...
1354
1355
  		abort_creds(bprm->cred);
  	}
63e46b95e   Oleg Nesterov   exec: move the fi...
1356
1357
1358
1359
  	if (bprm->file) {
  		allow_write_access(bprm->file);
  		fput(bprm->file);
  	}
b66c59840   Kees Cook   exec: do not leav...
1360
1361
1362
  	/* If a binfmt changed the interp, free it. */
  	if (bprm->interp != bprm->filename)
  		kfree(bprm->interp);
a2a8474c3   Oleg Nesterov   exec: do not slee...
1363
1364
  	kfree(bprm);
  }
c2315c187   Oleg Nesterov   exec: load_script...
1365
  int bprm_change_interp(const char *interp, struct linux_binprm *bprm)
b66c59840   Kees Cook   exec: do not leav...
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
  {
  	/* If a binfmt changed the interp, free it first. */
  	if (bprm->interp != bprm->filename)
  		kfree(bprm->interp);
  	bprm->interp = kstrdup(interp, GFP_KERNEL);
  	if (!bprm->interp)
  		return -ENOMEM;
  	return 0;
  }
  EXPORT_SYMBOL(bprm_change_interp);
a2a8474c3   Oleg Nesterov   exec: do not slee...
1376
  /*
a6f76f23d   David Howells   CRED: Make execve...
1377
1378
1379
1380
1381
1382
1383
1384
   * 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;
2976b10f0   Stephane Eranian   perf: Disable mon...
1385
1386
1387
1388
1389
1390
1391
1392
1393
  
  	/*
  	 * Disable monitoring for regular users
  	 * when executing setuid binaries. Must
  	 * wait until new credentials are committed
  	 * by commit_creds() above
  	 */
  	if (get_dumpable(current->mm) != SUID_DUMP_USER)
  		perf_event_exit_task(current);
a2a8474c3   Oleg Nesterov   exec: do not slee...
1394
1395
  	/*
  	 * cred_guard_mutex must be held at least to this point to prevent
a6f76f23d   David Howells   CRED: Make execve...
1396
  	 * ptrace_attach() from altering our determination of the task's
a2a8474c3   Oleg Nesterov   exec: do not slee...
1397
1398
  	 * credentials; any time after this it may be unlocked.
  	 */
a6f76f23d   David Howells   CRED: Make execve...
1399
  	security_bprm_committed_creds(bprm);
9b1bf12d5   KOSAKI Motohiro   signals: move cre...
1400
  	mutex_unlock(&current->signal->cred_guard_mutex);
a6f76f23d   David Howells   CRED: Make execve...
1401
1402
1403
1404
1405
  }
  EXPORT_SYMBOL(install_exec_creds);
  
  /*
   * determine how safe it is to execute the proposed program
9b1bf12d5   KOSAKI Motohiro   signals: move cre...
1406
   * - the caller must hold ->cred_guard_mutex to protect against
c2e1f2e30   Kees Cook   seccomp: implemen...
1407
   *   PTRACE_ATTACH or seccomp thread-sync
a6f76f23d   David Howells   CRED: Make execve...
1408
   */
9e00cdb09   Oleg Nesterov   exec:check_unsafe...
1409
  static void check_unsafe_exec(struct linux_binprm *bprm)
a6f76f23d   David Howells   CRED: Make execve...
1410
  {
0bf2f3aec   David Howells   CRED: Fix SUID ex...
1411
  	struct task_struct *p = current, *t;
f1191b50e   Al Viro   check_unsafe_exec...
1412
  	unsigned n_fs;
a6f76f23d   David Howells   CRED: Make execve...
1413

9227dd2a8   Eric W. Biederman   exec: Remove LSM_...
1414
1415
  	if (p->ptrace)
  		bprm->unsafe |= LSM_UNSAFE_PTRACE;
a6f76f23d   David Howells   CRED: Make execve...
1416

259e5e6c7   Andy Lutomirski   Add PR_{GET,SET}_...
1417
1418
1419
1420
  	/*
  	 * This isn't strictly necessary, but it makes it harder for LSMs to
  	 * mess up.
  	 */
1d4457f99   Kees Cook   sched: move no_ne...
1421
  	if (task_no_new_privs(current))
259e5e6c7   Andy Lutomirski   Add PR_{GET,SET}_...
1422
  		bprm->unsafe |= LSM_UNSAFE_NO_NEW_PRIVS;
83f62a2ea   Oleg Nesterov   exec:check_unsafe...
1423
  	t = p;
0bf2f3aec   David Howells   CRED: Fix SUID ex...
1424
  	n_fs = 1;
2a4419b5b   Nick Piggin   fs: fs_struct rwl...
1425
  	spin_lock(&p->fs->lock);
437f7fdb6   Oleg Nesterov   check_unsafe_exec...
1426
  	rcu_read_lock();
83f62a2ea   Oleg Nesterov   exec:check_unsafe...
1427
  	while_each_thread(p, t) {
0bf2f3aec   David Howells   CRED: Fix SUID ex...
1428
1429
  		if (t->fs == p->fs)
  			n_fs++;
0bf2f3aec   David Howells   CRED: Fix SUID ex...
1430
  	}
437f7fdb6   Oleg Nesterov   check_unsafe_exec...
1431
  	rcu_read_unlock();
0bf2f3aec   David Howells   CRED: Fix SUID ex...
1432

9e00cdb09   Oleg Nesterov   exec:check_unsafe...
1433
  	if (p->fs->users > n_fs)
a6f76f23d   David Howells   CRED: Make execve...
1434
  		bprm->unsafe |= LSM_UNSAFE_SHARE;
9e00cdb09   Oleg Nesterov   exec:check_unsafe...
1435
1436
  	else
  		p->fs->in_exec = 1;
2a4419b5b   Nick Piggin   fs: fs_struct rwl...
1437
  	spin_unlock(&p->fs->lock);
a6f76f23d   David Howells   CRED: Make execve...
1438
  }
8b01fc86b   Jann Horn   fs: take i_mutex ...
1439
1440
1441
1442
1443
1444
  static void bprm_fill_uid(struct linux_binprm *bprm)
  {
  	struct inode *inode;
  	unsigned int mode;
  	kuid_t uid;
  	kgid_t gid;
cb6fd68fd   Kees Cook   exec: clarify rea...
1445
1446
1447
1448
1449
1450
  	/*
  	 * Since this can be called multiple times (via prepare_binprm),
  	 * we must clear any previous work done when setting set[ug]id
  	 * bits from any earlier bprm->file uses (for example when run
  	 * first for a setuid script then again for its interpreter).
  	 */
8b01fc86b   Jann Horn   fs: take i_mutex ...
1451
1452
  	bprm->cred->euid = current_euid();
  	bprm->cred->egid = current_egid();
380cf5ba6   Andy Lutomirski   fs: Treat foreign...
1453
  	if (!mnt_may_suid(bprm->file->f_path.mnt))
8b01fc86b   Jann Horn   fs: take i_mutex ...
1454
1455
1456
1457
  		return;
  
  	if (task_no_new_privs(current))
  		return;
fea6d2a61   Vivek Goyal   vfs: Use upper fi...
1458
  	inode = bprm->file->f_path.dentry->d_inode;
8b01fc86b   Jann Horn   fs: take i_mutex ...
1459
1460
1461
1462
1463
  	mode = READ_ONCE(inode->i_mode);
  	if (!(mode & (S_ISUID|S_ISGID)))
  		return;
  
  	/* Be careful if suid/sgid is set */
5955102c9   Al Viro   wrappers for ->i_...
1464
  	inode_lock(inode);
8b01fc86b   Jann Horn   fs: take i_mutex ...
1465
1466
1467
1468
1469
  
  	/* reload atomically mode/uid/gid now that lock held */
  	mode = inode->i_mode;
  	uid = inode->i_uid;
  	gid = inode->i_gid;
5955102c9   Al Viro   wrappers for ->i_...
1470
  	inode_unlock(inode);
8b01fc86b   Jann Horn   fs: take i_mutex ...
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
  
  	/* We ignore suid/sgid if there are no mappings for them in the ns */
  	if (!kuid_has_mapping(bprm->cred->user_ns, uid) ||
  		 !kgid_has_mapping(bprm->cred->user_ns, gid))
  		return;
  
  	if (mode & S_ISUID) {
  		bprm->per_clear |= PER_CLEAR_ON_SETID;
  		bprm->cred->euid = uid;
  	}
  
  	if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
  		bprm->per_clear |= PER_CLEAR_ON_SETID;
  		bprm->cred->egid = gid;
  	}
  }
9e00cdb09   Oleg Nesterov   exec:check_unsafe...
1487
1488
  /*
   * Fill the binprm structure from the inode.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1489
   * Check permissions, then read the first 128 (BINPRM_BUF_SIZE) bytes
a6f76f23d   David Howells   CRED: Make execve...
1490
1491
   *
   * This may be called multiple times for binary chains (scripts for example).
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1492
1493
1494
   */
  int prepare_binprm(struct linux_binprm *bprm)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1495
  	int retval;
bdd1d2d3d   Christoph Hellwig   fs: fix kernel_re...
1496
  	loff_t pos = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1497

8b01fc86b   Jann Horn   fs: take i_mutex ...
1498
  	bprm_fill_uid(bprm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1499
1500
  
  	/* fill in binprm security blob */
a6f76f23d   David Howells   CRED: Make execve...
1501
  	retval = security_bprm_set_creds(bprm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1502
1503
  	if (retval)
  		return retval;
ddb4a1442   Kees Cook   exec: Rename bprm...
1504
  	bprm->called_set_creds = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1505

a6f76f23d   David Howells   CRED: Make execve...
1506
  	memset(bprm->buf, 0, BINPRM_BUF_SIZE);
bdd1d2d3d   Christoph Hellwig   fs: fix kernel_re...
1507
  	return kernel_read(bprm->file, bprm->buf, BINPRM_BUF_SIZE, &pos);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1508
1509
1510
  }
  
  EXPORT_SYMBOL(prepare_binprm);
4fc75ff48   Nick Piggin   exec: fix remove_...
1511
1512
1513
1514
1515
  /*
   * 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...
1516
  int remove_arg_zero(struct linux_binprm *bprm)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1517
  {
b6a2fea39   Ollie Wild   mm: variable leng...
1518
1519
1520
1521
  	int ret = 0;
  	unsigned long offset;
  	char *kaddr;
  	struct page *page;
4fc75ff48   Nick Piggin   exec: fix remove_...
1522

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

b6a2fea39   Ollie Wild   mm: variable leng...
1526
1527
1528
1529
1530
1531
1532
  	do {
  		offset = bprm->p & ~PAGE_MASK;
  		page = get_arg_page(bprm, bprm->p, 0);
  		if (!page) {
  			ret = -EFAULT;
  			goto out;
  		}
e8e3c3d66   Cong Wang   fs: remove the se...
1533
  		kaddr = kmap_atomic(page);
4fc75ff48   Nick Piggin   exec: fix remove_...
1534

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

e8e3c3d66   Cong Wang   fs: remove the se...
1539
  		kunmap_atomic(kaddr);
b6a2fea39   Ollie Wild   mm: variable leng...
1540
  		put_arg_page(page);
b6a2fea39   Ollie Wild   mm: variable leng...
1541
  	} while (offset == PAGE_SIZE);
4fc75ff48   Nick Piggin   exec: fix remove_...
1542

b6a2fea39   Ollie Wild   mm: variable leng...
1543
1544
1545
  	bprm->p++;
  	bprm->argc--;
  	ret = 0;
4fc75ff48   Nick Piggin   exec: fix remove_...
1546

b6a2fea39   Ollie Wild   mm: variable leng...
1547
1548
  out:
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1549
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1550
  EXPORT_SYMBOL(remove_arg_zero);
cb7b6b1cb   Oleg Nesterov   exec: cleanup the...
1551
1552
  #define printable(c) (((c)=='\t') || ((c)=='
  ') || (0x20<=(c) && (c)<=0x7e))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1553
1554
1555
  /*
   * cycle the list of binary formats handler, until one recognizes the image
   */
3c456bfc4   Al Viro   get rid of pt_reg...
1556
  int search_binary_handler(struct linux_binprm *bprm)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1557
  {
cb7b6b1cb   Oleg Nesterov   exec: cleanup the...
1558
  	bool need_retry = IS_ENABLED(CONFIG_MODULES);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1559
  	struct linux_binfmt *fmt;
cb7b6b1cb   Oleg Nesterov   exec: cleanup the...
1560
  	int retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1561

d74026986   Kees Cook   exec: use -ELOOP ...
1562
  	/* This allows 4 levels of binfmt rewrites before failing hard. */
131b2f9f1   Oleg Nesterov   exec: kill "int d...
1563
  	if (bprm->recursion_depth > 5)
d74026986   Kees Cook   exec: use -ELOOP ...
1564
  		return -ELOOP;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1565
1566
1567
  	retval = security_bprm_check(bprm);
  	if (retval)
  		return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1568
  	retval = -ENOENT;
cb7b6b1cb   Oleg Nesterov   exec: cleanup the...
1569
1570
1571
1572
1573
1574
1575
1576
   retry:
  	read_lock(&binfmt_lock);
  	list_for_each_entry(fmt, &formats, lh) {
  		if (!try_module_get(fmt->module))
  			continue;
  		read_unlock(&binfmt_lock);
  		bprm->recursion_depth++;
  		retval = fmt->load_binary(bprm);
19d860a14   Al Viro   handle suicide on...
1577
1578
  		read_lock(&binfmt_lock);
  		put_binfmt(fmt);
cb7b6b1cb   Oleg Nesterov   exec: cleanup the...
1579
  		bprm->recursion_depth--;
19d860a14   Al Viro   handle suicide on...
1580
1581
1582
1583
1584
1585
1586
1587
  		if (retval < 0 && !bprm->mm) {
  			/* we got to flush_old_exec() and failed after it */
  			read_unlock(&binfmt_lock);
  			force_sigsegv(SIGSEGV, current);
  			return retval;
  		}
  		if (retval != -ENOEXEC || !bprm->file) {
  			read_unlock(&binfmt_lock);
cb7b6b1cb   Oleg Nesterov   exec: cleanup the...
1588
  			return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1589
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1590
  	}
cb7b6b1cb   Oleg Nesterov   exec: cleanup the...
1591
  	read_unlock(&binfmt_lock);
19d860a14   Al Viro   handle suicide on...
1592
  	if (need_retry) {
cb7b6b1cb   Oleg Nesterov   exec: cleanup the...
1593
1594
1595
  		if (printable(bprm->buf[0]) && printable(bprm->buf[1]) &&
  		    printable(bprm->buf[2]) && printable(bprm->buf[3]))
  			return retval;
4e0621a07   Oleg Nesterov   exec: don't retry...
1596
1597
  		if (request_module("binfmt-%04x", *(ushort *)(bprm->buf + 2)) < 0)
  			return retval;
cb7b6b1cb   Oleg Nesterov   exec: cleanup the...
1598
1599
1600
  		need_retry = false;
  		goto retry;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1601
1602
  	return retval;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1603
  EXPORT_SYMBOL(search_binary_handler);
5d1baf3b6   Oleg Nesterov   exec: introduce e...
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
  static int exec_binprm(struct linux_binprm *bprm)
  {
  	pid_t old_pid, old_vpid;
  	int ret;
  
  	/* Need to fetch pid before load_binary changes it */
  	old_pid = current->pid;
  	rcu_read_lock();
  	old_vpid = task_pid_nr_ns(current, task_active_pid_ns(current->parent));
  	rcu_read_unlock();
  
  	ret = search_binary_handler(bprm);
  	if (ret >= 0) {
3eaded86a   Linus Torvalds   Merge git://git.i...
1617
  		audit_bprm(bprm);
5d1baf3b6   Oleg Nesterov   exec: introduce e...
1618
1619
  		trace_sched_process_exec(current, old_pid, bprm);
  		ptrace_event(PTRACE_EVENT_EXEC, old_vpid);
9beb266f2   Oleg Nesterov   exec: proc_exec_c...
1620
  		proc_exec_connector(current);
5d1baf3b6   Oleg Nesterov   exec: introduce e...
1621
1622
1623
1624
  	}
  
  	return ret;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1625
1626
1627
  /*
   * sys_execve() executes a new program.
   */
449325b52   Alexei Starovoitov   umh: introduce fo...
1628
1629
1630
1631
  static int __do_execve_file(int fd, struct filename *filename,
  			    struct user_arg_ptr argv,
  			    struct user_arg_ptr envp,
  			    int flags, struct file *file)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1632
  {
51f39a1f0   David Drysdale   syscalls: impleme...
1633
  	char *pathbuf = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1634
  	struct linux_binprm *bprm;
3b1253880   Al Viro   [PATCH] sanitize ...
1635
  	struct files_struct *displaced;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1636
  	int retval;
72fa59970   Vasiliy Kulikov   move RLIMIT_NPROC...
1637

c4ad8f98b   Linus Torvalds   execve: use 'stru...
1638
1639
  	if (IS_ERR(filename))
  		return PTR_ERR(filename);
72fa59970   Vasiliy Kulikov   move RLIMIT_NPROC...
1640
1641
1642
1643
1644
1645
1646
  	/*
  	 * We move the actual failure in case of RLIMIT_NPROC excess from
  	 * set*uid() to execve() because too many poorly written programs
  	 * don't check setuid() return code.  Here we additionally recheck
  	 * whether NPROC limit is still exceeded.
  	 */
  	if ((current->flags & PF_NPROC_EXCEEDED) &&
bd9d43f47   Oleg Nesterov   fs/exec.c: do_exe...
1647
  	    atomic_read(&current_user()->processes) > rlimit(RLIMIT_NPROC)) {
72fa59970   Vasiliy Kulikov   move RLIMIT_NPROC...
1648
1649
1650
1651
1652
1653
1654
  		retval = -EAGAIN;
  		goto out_ret;
  	}
  
  	/* We're below the limit (still or again), so we don't want to make
  	 * further execve() calls fail. */
  	current->flags &= ~PF_NPROC_EXCEEDED;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1655

3b1253880   Al Viro   [PATCH] sanitize ...
1656
  	retval = unshare_files(&displaced);
fd8328be8   Al Viro   [PATCH] sanitize ...
1657
1658
  	if (retval)
  		goto out_ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1659
  	retval = -ENOMEM;
11b0b5abb   Oliver Neukum   [PATCH] use kzall...
1660
  	bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1661
  	if (!bprm)
fd8328be8   Al Viro   [PATCH] sanitize ...
1662
  		goto out_files;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1663

a2a8474c3   Oleg Nesterov   exec: do not slee...
1664
1665
  	retval = prepare_bprm_creds(bprm);
  	if (retval)
a6f76f23d   David Howells   CRED: Make execve...
1666
  		goto out_free;
498052bba   Al Viro   New locking/refco...
1667

9e00cdb09   Oleg Nesterov   exec:check_unsafe...
1668
  	check_unsafe_exec(bprm);
a2a8474c3   Oleg Nesterov   exec: do not slee...
1669
  	current->in_execve = 1;
a6f76f23d   David Howells   CRED: Make execve...
1670

449325b52   Alexei Starovoitov   umh: introduce fo...
1671
1672
  	if (!file)
  		file = do_open_execat(fd, filename, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1673
1674
  	retval = PTR_ERR(file);
  	if (IS_ERR(file))
498052bba   Al Viro   New locking/refco...
1675
  		goto out_unmark;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1676
1677
  
  	sched_exec();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1678
  	bprm->file = file;
449325b52   Alexei Starovoitov   umh: introduce fo...
1679
1680
1681
  	if (!filename) {
  		bprm->filename = "none";
  	} else if (fd == AT_FDCWD || filename->name[0] == '/') {
51f39a1f0   David Drysdale   syscalls: impleme...
1682
1683
1684
  		bprm->filename = filename->name;
  	} else {
  		if (filename->name[0] == '\0')
0ee931c4e   Michal Hocko   mm: treewide: rem...
1685
  			pathbuf = kasprintf(GFP_KERNEL, "/dev/fd/%d", fd);
51f39a1f0   David Drysdale   syscalls: impleme...
1686
  		else
0ee931c4e   Michal Hocko   mm: treewide: rem...
1687
  			pathbuf = kasprintf(GFP_KERNEL, "/dev/fd/%d/%s",
51f39a1f0   David Drysdale   syscalls: impleme...
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
  					    fd, filename->name);
  		if (!pathbuf) {
  			retval = -ENOMEM;
  			goto out_unmark;
  		}
  		/*
  		 * Record that a name derived from an O_CLOEXEC fd will be
  		 * inaccessible after exec. Relies on having exclusive access to
  		 * current->files (due to unshare_files above).
  		 */
  		if (close_on_exec(fd, rcu_dereference_raw(current->files->fdt)))
  			bprm->interp_flags |= BINPRM_FLAGS_PATH_INACCESSIBLE;
  		bprm->filename = pathbuf;
  	}
  	bprm->interp = bprm->filename;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1703

b6a2fea39   Ollie Wild   mm: variable leng...
1704
1705
  	retval = bprm_mm_init(bprm);
  	if (retval)
63e46b95e   Oleg Nesterov   exec: move the fi...
1706
  		goto out_unmark;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1707

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

b6a2fea39   Ollie Wild   mm: variable leng...
1712
  	bprm->envc = count(envp, MAX_ARG_STRINGS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1713
  	if ((retval = bprm->envc) < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
  		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;
f84df2a6f   Eric W. Biederman   exec: Ensure mm->...
1732
  	would_dump(bprm, bprm->file);
5d1baf3b6   Oleg Nesterov   exec: introduce e...
1733
  	retval = exec_binprm(bprm);
a6f76f23d   David Howells   CRED: Make execve...
1734
1735
  	if (retval < 0)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1736

a6f76f23d   David Howells   CRED: Make execve...
1737
  	/* execve succeeded */
498052bba   Al Viro   New locking/refco...
1738
  	current->fs->in_exec = 0;
f9ce1f1cd   Kentaro Takeda   Add in_execve fla...
1739
  	current->in_execve = 0;
a961e4091   Mathieu Desnoyers   membarrier: Provi...
1740
  	membarrier_execve(current);
d7822b1e2   Mathieu Desnoyers   rseq: Introduce r...
1741
  	rseq_execve(current);
a6f76f23d   David Howells   CRED: Make execve...
1742
  	acct_update_integrals(current);
82727018b   Rik van Riel   sched/numa: Call ...
1743
  	task_numa_free(current);
a6f76f23d   David Howells   CRED: Make execve...
1744
  	free_bprm(bprm);
51f39a1f0   David Drysdale   syscalls: impleme...
1745
  	kfree(pathbuf);
449325b52   Alexei Starovoitov   umh: introduce fo...
1746
1747
  	if (filename)
  		putname(filename);
a6f76f23d   David Howells   CRED: Make execve...
1748
1749
1750
  	if (displaced)
  		put_files_struct(displaced);
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1751

a6f76f23d   David Howells   CRED: Make execve...
1752
  out:
3c77f8457   Oleg Nesterov   exec: make argv/e...
1753
1754
1755
1756
  	if (bprm->mm) {
  		acct_arg_size(bprm, 0);
  		mmput(bprm->mm);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1757

498052bba   Al Viro   New locking/refco...
1758
  out_unmark:
9e00cdb09   Oleg Nesterov   exec:check_unsafe...
1759
  	current->fs->in_exec = 0;
f9ce1f1cd   Kentaro Takeda   Add in_execve fla...
1760
  	current->in_execve = 0;
a6f76f23d   David Howells   CRED: Make execve...
1761
1762
  
  out_free:
08a6fac1c   Al Viro   [PATCH] get rid o...
1763
  	free_bprm(bprm);
51f39a1f0   David Drysdale   syscalls: impleme...
1764
  	kfree(pathbuf);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1765

fd8328be8   Al Viro   [PATCH] sanitize ...
1766
  out_files:
3b1253880   Al Viro   [PATCH] sanitize ...
1767
1768
  	if (displaced)
  		reset_files_struct(displaced);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1769
  out_ret:
449325b52   Alexei Starovoitov   umh: introduce fo...
1770
1771
  	if (filename)
  		putname(filename);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1772
1773
  	return retval;
  }
449325b52   Alexei Starovoitov   umh: introduce fo...
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
  static int do_execveat_common(int fd, struct filename *filename,
  			      struct user_arg_ptr argv,
  			      struct user_arg_ptr envp,
  			      int flags)
  {
  	return __do_execve_file(fd, filename, argv, envp, flags, NULL);
  }
  
  int do_execve_file(struct file *file, void *__argv, void *__envp)
  {
  	struct user_arg_ptr argv = { .ptr.native = __argv };
  	struct user_arg_ptr envp = { .ptr.native = __envp };
  
  	return __do_execve_file(AT_FDCWD, NULL, argv, envp, 0, file);
  }
c4ad8f98b   Linus Torvalds   execve: use 'stru...
1789
  int do_execve(struct filename *filename,
ba2d01629   Oleg Nesterov   exec: introduce s...
1790
  	const char __user *const __user *__argv,
da3d4c5fa   Al Viro   get rid of pt_reg...
1791
  	const char __user *const __user *__envp)
ba2d01629   Oleg Nesterov   exec: introduce s...
1792
  {
0e028465d   Oleg Nesterov   exec: unify do_ex...
1793
1794
  	struct user_arg_ptr argv = { .ptr.native = __argv };
  	struct user_arg_ptr envp = { .ptr.native = __envp };
51f39a1f0   David Drysdale   syscalls: impleme...
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
  	return do_execveat_common(AT_FDCWD, filename, argv, envp, 0);
  }
  
  int do_execveat(int fd, struct filename *filename,
  		const char __user *const __user *__argv,
  		const char __user *const __user *__envp,
  		int flags)
  {
  	struct user_arg_ptr argv = { .ptr.native = __argv };
  	struct user_arg_ptr envp = { .ptr.native = __envp };
  
  	return do_execveat_common(fd, filename, argv, envp, flags);
0e028465d   Oleg Nesterov   exec: unify do_ex...
1807
1808
1809
  }
  
  #ifdef CONFIG_COMPAT
c4ad8f98b   Linus Torvalds   execve: use 'stru...
1810
  static int compat_do_execve(struct filename *filename,
38b983b34   Al Viro   generic sys_execve()
1811
  	const compat_uptr_t __user *__argv,
d03d26e58   Al Viro   make compat_do_ex...
1812
  	const compat_uptr_t __user *__envp)
0e028465d   Oleg Nesterov   exec: unify do_ex...
1813
1814
1815
1816
1817
1818
1819
1820
1821
  {
  	struct user_arg_ptr argv = {
  		.is_compat = true,
  		.ptr.compat = __argv,
  	};
  	struct user_arg_ptr envp = {
  		.is_compat = true,
  		.ptr.compat = __envp,
  	};
51f39a1f0   David Drysdale   syscalls: impleme...
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
  	return do_execveat_common(AT_FDCWD, filename, argv, envp, 0);
  }
  
  static int compat_do_execveat(int fd, struct filename *filename,
  			      const compat_uptr_t __user *__argv,
  			      const compat_uptr_t __user *__envp,
  			      int flags)
  {
  	struct user_arg_ptr argv = {
  		.is_compat = true,
  		.ptr.compat = __argv,
  	};
  	struct user_arg_ptr envp = {
  		.is_compat = true,
  		.ptr.compat = __envp,
  	};
  	return do_execveat_common(fd, filename, argv, envp, flags);
ba2d01629   Oleg Nesterov   exec: introduce s...
1839
  }
0e028465d   Oleg Nesterov   exec: unify do_ex...
1840
  #endif
ba2d01629   Oleg Nesterov   exec: introduce s...
1841

964ee7df9   Oleg Nesterov   exec: fix set_bin...
1842
  void set_binfmt(struct linux_binfmt *new)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1843
  {
801460d0c   Hiroshi Shimamoto   task_struct clean...
1844
1845
1846
1847
  	struct mm_struct *mm = current->mm;
  
  	if (mm->binfmt)
  		module_put(mm->binfmt->module);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1848

801460d0c   Hiroshi Shimamoto   task_struct clean...
1849
  	mm->binfmt = new;
964ee7df9   Oleg Nesterov   exec: fix set_bin...
1850
1851
  	if (new)
  		__module_get(new->module);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1852
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1853
  EXPORT_SYMBOL(set_binfmt);
6c5d52382   Kawai, Hidehiro   coredump masking:...
1854
  /*
7288e1187   Oleg Nesterov   coredump: kill MM...
1855
   * set_dumpable stores three-value SUID_DUMP_* into mm->flags.
6c5d52382   Kawai, Hidehiro   coredump masking:...
1856
1857
1858
   */
  void set_dumpable(struct mm_struct *mm, int value)
  {
abacd2fe3   Oleg Nesterov   coredump: set_dum...
1859
  	unsigned long old, new;
7288e1187   Oleg Nesterov   coredump: kill MM...
1860
1861
  	if (WARN_ON((unsigned)value > SUID_DUMP_ROOT))
  		return;
abacd2fe3   Oleg Nesterov   coredump: set_dum...
1862
  	do {
6aa7de059   Mark Rutland   locking/atomics: ...
1863
  		old = READ_ONCE(mm->flags);
7288e1187   Oleg Nesterov   coredump: kill MM...
1864
  		new = (old & ~MMF_DUMPABLE_MASK) | value;
abacd2fe3   Oleg Nesterov   coredump: set_dum...
1865
  	} while (cmpxchg(&mm->flags, old, new) != old);
6c5d52382   Kawai, Hidehiro   coredump masking:...
1866
  }
6c5d52382   Kawai, Hidehiro   coredump masking:...
1867

38b983b34   Al Viro   generic sys_execve()
1868
1869
1870
1871
1872
  SYSCALL_DEFINE3(execve,
  		const char __user *, filename,
  		const char __user *const __user *, argv,
  		const char __user *const __user *, envp)
  {
c4ad8f98b   Linus Torvalds   execve: use 'stru...
1873
  	return do_execve(getname(filename), argv, envp);
38b983b34   Al Viro   generic sys_execve()
1874
  }
51f39a1f0   David Drysdale   syscalls: impleme...
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
  
  SYSCALL_DEFINE5(execveat,
  		int, fd, const char __user *, filename,
  		const char __user *const __user *, argv,
  		const char __user *const __user *, envp,
  		int, flags)
  {
  	int lookup_flags = (flags & AT_EMPTY_PATH) ? LOOKUP_EMPTY : 0;
  
  	return do_execveat(fd,
  			   getname_flags(filename, lookup_flags, NULL),
  			   argv, envp, flags);
  }
38b983b34   Al Viro   generic sys_execve()
1888
  #ifdef CONFIG_COMPAT
625b1d7e8   Heiko Carstens   fs/compat: conver...
1889
1890
1891
  COMPAT_SYSCALL_DEFINE3(execve, const char __user *, filename,
  	const compat_uptr_t __user *, argv,
  	const compat_uptr_t __user *, envp)
38b983b34   Al Viro   generic sys_execve()
1892
  {
c4ad8f98b   Linus Torvalds   execve: use 'stru...
1893
  	return compat_do_execve(getname(filename), argv, envp);
38b983b34   Al Viro   generic sys_execve()
1894
  }
51f39a1f0   David Drysdale   syscalls: impleme...
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
  
  COMPAT_SYSCALL_DEFINE5(execveat, int, fd,
  		       const char __user *, filename,
  		       const compat_uptr_t __user *, argv,
  		       const compat_uptr_t __user *, envp,
  		       int,  flags)
  {
  	int lookup_flags = (flags & AT_EMPTY_PATH) ? LOOKUP_EMPTY : 0;
  
  	return compat_do_execveat(fd,
  				  getname_flags(filename, lookup_flags, NULL),
  				  argv, envp, flags);
  }
38b983b34   Al Viro   generic sys_execve()
1908
  #endif