Blame view

fs/proc/base.c 83.5 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
  /*
   *  linux/fs/proc/base.c
   *
   *  Copyright (C) 1991, 1992 Linus Torvalds
   *
   *  proc base directory handling functions
   *
   *  1999, Al Viro. Rewritten. Now it covers the whole per-process part.
   *  Instead of using magical inumbers to determine the kind of object
   *  we allocate and fill in-core inodes upon lookup. They don't even
   *  go into icache. We cache the reference to task_struct upon lookup too.
   *  Eventually it should become a filesystem in its own. We don't use the
   *  rest of procfs anymore.
e070ad49f   Mauricio Lin   [PATCH] add /proc...
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
   *
   *
   *  Changelog:
   *  17-Jan-2005
   *  Allan Bezerra
   *  Bruna Moreira <bruna.moreira@indt.org.br>
   *  Edjard Mota <edjard.mota@indt.org.br>
   *  Ilias Biris <ilias.biris@indt.org.br>
   *  Mauricio Lin <mauricio.lin@indt.org.br>
   *
   *  Embedded Linux Lab - 10LE Instituto Nokia de Tecnologia - INdT
   *
   *  A new process specific entry (smaps) included in /proc. It shows the
   *  size of rss for each memory area. The maps entry lacks information
   *  about physical memory size (rss) for each mapped file, i.e.,
   *  rss information for executables and library files.
   *  This additional information is useful for any tools that need to know
   *  about physical memory consumption for a process specific library.
   *
   *  Changelog:
   *  21-Feb-2005
   *  Embedded Linux Lab - 10LE Instituto Nokia de Tecnologia - INdT
   *  Pud inclusion in the page table walking.
   *
   *  ChangeLog:
   *  10-Mar-2005
   *  10LE Instituto Nokia de Tecnologia - INdT:
   *  A better way to walks through the page table as suggested by Hugh Dickins.
   *
   *  Simo Piiroinen <simo.piiroinen@nokia.com>:
   *  Smaps information related to shared, private, clean and dirty pages.
   *
   *  Paul Mundt <paul.mundt@nokia.com>:
   *  Overall revision about smaps.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48
49
50
   */
  
  #include <asm/uaccess.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
52
53
54
  #include <linux/errno.h>
  #include <linux/time.h>
  #include <linux/proc_fs.h>
  #include <linux/stat.h>
5995477ab   Andrea Righi   task IO accountin...
55
  #include <linux/task_io_accounting_ops.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
  #include <linux/init.h>
16f7e0fe2   Randy Dunlap   [PATCH] capable/c...
57
  #include <linux/capability.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
  #include <linux/file.h>
9f3acc314   Al Viro   [PATCH] split lin...
59
  #include <linux/fdtable.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
61
62
  #include <linux/string.h>
  #include <linux/seq_file.h>
  #include <linux/namei.h>
6b3286ed1   Kirill Korotaev   [PATCH] rename st...
63
  #include <linux/mnt_namespace.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
  #include <linux/mm.h>
a63d83f42   David Rientjes   oom: badness heur...
65
  #include <linux/swap.h>
b835996f6   Dipankar Sarma   [PATCH] files: lo...
66
  #include <linux/rcupdate.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
67
  #include <linux/kallsyms.h>
2ec220e27   Ken Chen   proc: add /proc/*...
68
  #include <linux/stacktrace.h>
d85f50d5e   Neil Horman   proc: export a pr...
69
  #include <linux/resource.h>
5096add84   Kees Cook   proc: maps protec...
70
  #include <linux/module.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
71
72
73
  #include <linux/mount.h>
  #include <linux/security.h>
  #include <linux/ptrace.h>
0d094efeb   Roland McGrath   tracehook: traceh...
74
  #include <linux/tracehook.h>
87ebdc00e   Andrew Morton   fs/proc: clean up...
75
  #include <linux/printk.h>
a424316ca   Paul Menage   Task Control Grou...
76
  #include <linux/cgroup.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
77
78
  #include <linux/cpuset.h>
  #include <linux/audit.h>
5addc5dd8   Al Viro   [PATCH] make /pro...
79
  #include <linux/poll.h>
1651e14e2   Serge E. Hallyn   [PATCH] namespace...
80
  #include <linux/nsproxy.h>
8ac773b4f   Alexey Dobriyan   [PATCH] OOM kille...
81
  #include <linux/oom.h>
3cb4a0bb1   Kawai, Hidehiro   coredump masking:...
82
  #include <linux/elf.h>
60347f671   Pavel Emelyanov   pid namespaces: p...
83
  #include <linux/pid_namespace.h>
22d917d80   Eric W. Biederman   userns: Rework th...
84
  #include <linux/user_namespace.h>
5ad4e53bd   Al Viro   Get rid of indire...
85
  #include <linux/fs_struct.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
86
  #include <linux/slab.h>
640708a2c   Pavel Emelyanov   procfs: introduce...
87
  #include <linux/flex_array.h>
48f6a7a51   Pavel Emelyanov   posix-timers: Int...
88
  #include <linux/posix-timers.h>
f133ecca9   Chris Metcalf   arch/tile: more /...
89
90
91
  #ifdef CONFIG_HARDWALL
  #include <asm/hardwall.h>
  #endif
43d2b1132   KAMEZAWA Hiroyuki   tracepoint: add t...
92
  #include <trace/events/oom.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
93
  #include "internal.h"
faf60af17   Cyrill Gorcunov   procfs: Move /pro...
94
  #include "fd.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95

0f2fe20f5   Eric W. Biederman   [PATCH] proc: Pro...
96
97
98
99
100
101
102
103
104
  /* NOTE:
   *	Implementing inode permission operations in /proc is almost
   *	certainly an error.  Permission checks need to happen during
   *	each system call not at open time.  The reason is that most of
   *	what we wish to check for permissions in /proc varies at runtime.
   *
   *	The classic example of a problem is opening file descriptors
   *	in /proc for a task before it execs a suid executable.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
105
  struct pid_entry {
cedbccab8   Alexey Dobriyan   proc: more "const...
106
  	const char *name;
c5141e6d6   Eric Dumazet   procfs: reorder s...
107
  	int len;
d161a13f9   Al Viro   switch procfs to ...
108
  	umode_t mode;
c5ef1c42c   Arjan van de Ven   [PATCH] mark stru...
109
  	const struct inode_operations *iop;
00977a59b   Arjan van de Ven   [PATCH] mark stru...
110
  	const struct file_operations *fop;
20cdc894c   Eric W. Biederman   [PATCH] proc: mod...
111
  	union proc_op op;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
112
  };
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
113
  #define NOD(NAME, MODE, IOP, FOP, OP) {			\
20cdc894c   Eric W. Biederman   [PATCH] proc: mod...
114
  	.name = (NAME),					\
c5141e6d6   Eric Dumazet   procfs: reorder s...
115
  	.len  = sizeof(NAME) - 1,			\
20cdc894c   Eric W. Biederman   [PATCH] proc: mod...
116
117
118
119
120
  	.mode = MODE,					\
  	.iop  = IOP,					\
  	.fop  = FOP,					\
  	.op   = OP,					\
  }
631f9c186   Alexey Dobriyan   proc: remove '##'...
121
122
123
  #define DIR(NAME, MODE, iops, fops)	\
  	NOD(NAME, (S_IFDIR|(MODE)), &iops, &fops, {} )
  #define LNK(NAME, get_link)					\
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
124
  	NOD(NAME, (S_IFLNK|S_IRWXUGO),				\
20cdc894c   Eric W. Biederman   [PATCH] proc: mod...
125
  		&proc_pid_link_inode_operations, NULL,		\
631f9c186   Alexey Dobriyan   proc: remove '##'...
126
127
128
  		{ .proc_get_link = get_link } )
  #define REG(NAME, MODE, fops)				\
  	NOD(NAME, (S_IFREG|(MODE)), NULL, &fops, {})
631f9c186   Alexey Dobriyan   proc: remove '##'...
129
  #define ONE(NAME, MODE, show)				\
be614086a   Eric W. Biederman   proc: implement p...
130
131
  	NOD(NAME, (S_IFREG|(MODE)), 			\
  		NULL, &proc_single_file_operations,	\
631f9c186   Alexey Dobriyan   proc: remove '##'...
132
  		{ .proc_show = show } )
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
133

aed541759   Vegard Nossum   proc: calculate t...
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
  /*
   * Count the number of hardlinks for the pid_entry table, excluding the .
   * and .. links.
   */
  static unsigned int pid_entry_count_dirs(const struct pid_entry *entries,
  	unsigned int n)
  {
  	unsigned int i;
  	unsigned int count;
  
  	count = 0;
  	for (i = 0; i < n; ++i) {
  		if (S_ISDIR(entries[i].mode))
  			++count;
  	}
  
  	return count;
  }
f7ad3c6be   Miklos Szeredi   vfs: add helpers ...
152
  static int get_task_root(struct task_struct *task, struct path *root)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
153
  {
7c2c7d993   Hugh Dickins   fix setuid someti...
154
  	int result = -ENOENT;
0494f6ec5   Miklos Szeredi   [PATCH] use get_f...
155
  	task_lock(task);
f7ad3c6be   Miklos Szeredi   vfs: add helpers ...
156
157
  	if (task->fs) {
  		get_fs_root(task->fs, root);
7c2c7d993   Hugh Dickins   fix setuid someti...
158
159
  		result = 0;
  	}
0494f6ec5   Miklos Szeredi   [PATCH] use get_f...
160
  	task_unlock(task);
7c2c7d993   Hugh Dickins   fix setuid someti...
161
  	return result;
0494f6ec5   Miklos Szeredi   [PATCH] use get_f...
162
  }
7773fbc54   Cyrill Gorcunov   procfs: make proc...
163
  static int proc_cwd_link(struct dentry *dentry, struct path *path)
0494f6ec5   Miklos Szeredi   [PATCH] use get_f...
164
  {
2b0143b5c   David Howells   VFS: normal files...
165
  	struct task_struct *task = get_proc_task(d_inode(dentry));
0494f6ec5   Miklos Szeredi   [PATCH] use get_f...
166
  	int result = -ENOENT;
99f895518   Eric W. Biederman   [PATCH] proc: don...
167
168
  
  	if (task) {
f7ad3c6be   Miklos Szeredi   vfs: add helpers ...
169
170
171
172
173
174
  		task_lock(task);
  		if (task->fs) {
  			get_fs_pwd(task->fs, path);
  			result = 0;
  		}
  		task_unlock(task);
99f895518   Eric W. Biederman   [PATCH] proc: don...
175
176
  		put_task_struct(task);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
177
178
  	return result;
  }
7773fbc54   Cyrill Gorcunov   procfs: make proc...
179
  static int proc_root_link(struct dentry *dentry, struct path *path)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
180
  {
2b0143b5c   David Howells   VFS: normal files...
181
  	struct task_struct *task = get_proc_task(d_inode(dentry));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
182
  	int result = -ENOENT;
99f895518   Eric W. Biederman   [PATCH] proc: don...
183
184
  
  	if (task) {
f7ad3c6be   Miklos Szeredi   vfs: add helpers ...
185
  		result = get_task_root(task, path);
99f895518   Eric W. Biederman   [PATCH] proc: don...
186
187
  		put_task_struct(task);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
188
189
  	return result;
  }
c2c0bb446   Alexey Dobriyan   proc: fix PAGE_SI...
190
191
  static ssize_t proc_pid_cmdline_read(struct file *file, char __user *buf,
  				     size_t _count, loff_t *pos)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192
  {
c2c0bb446   Alexey Dobriyan   proc: fix PAGE_SI...
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
  	struct task_struct *tsk;
  	struct mm_struct *mm;
  	char *page;
  	unsigned long count = _count;
  	unsigned long arg_start, arg_end, env_start, env_end;
  	unsigned long len1, len2, len;
  	unsigned long p;
  	char c;
  	ssize_t rv;
  
  	BUG_ON(*pos < 0);
  
  	tsk = get_proc_task(file_inode(file));
  	if (!tsk)
  		return -ESRCH;
  	mm = get_task_mm(tsk);
  	put_task_struct(tsk);
  	if (!mm)
  		return 0;
  	/* Check if process spawned far enough to have cmdline. */
  	if (!mm->env_end) {
  		rv = 0;
  		goto out_mmput;
  	}
  
  	page = (char *)__get_free_page(GFP_TEMPORARY);
  	if (!page) {
  		rv = -ENOMEM;
  		goto out_mmput;
  	}
  
  	down_read(&mm->mmap_sem);
  	arg_start = mm->arg_start;
  	arg_end = mm->arg_end;
  	env_start = mm->env_start;
  	env_end = mm->env_end;
  	up_read(&mm->mmap_sem);
  
  	BUG_ON(arg_start > arg_end);
  	BUG_ON(env_start > env_end);
  
  	len1 = arg_end - arg_start;
  	len2 = env_end - env_start;
3581d458c   Alexey Dobriyan   /proc/$PID/cmdlin...
236
237
238
239
240
  	/* Empty ARGV. */
  	if (len1 == 0) {
  		rv = 0;
  		goto out_free_page;
  	}
2ca66ff70   Alexey Dobriyan   proc: convert /pr...
241
  	/*
c2c0bb446   Alexey Dobriyan   proc: fix PAGE_SI...
242
243
  	 * Inherently racy -- command line shares address space
  	 * with code and data.
2ca66ff70   Alexey Dobriyan   proc: convert /pr...
244
  	 */
272ddc8b3   Linus Torvalds   proc: don't use F...
245
  	rv = access_remote_vm(mm, arg_end - 1, &c, 1, 0);
c2c0bb446   Alexey Dobriyan   proc: fix PAGE_SI...
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
  	if (rv <= 0)
  		goto out_free_page;
  
  	rv = 0;
  
  	if (c == '\0') {
  		/* Command line (set of strings) occupies whole ARGV. */
  		if (len1 <= *pos)
  			goto out_free_page;
  
  		p = arg_start + *pos;
  		len = len1 - *pos;
  		while (count > 0 && len > 0) {
  			unsigned int _count;
  			int nr_read;
  
  			_count = min3(count, len, PAGE_SIZE);
272ddc8b3   Linus Torvalds   proc: don't use F...
263
  			nr_read = access_remote_vm(mm, p, page, _count, 0);
c2c0bb446   Alexey Dobriyan   proc: fix PAGE_SI...
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
  			if (nr_read < 0)
  				rv = nr_read;
  			if (nr_read <= 0)
  				goto out_free_page;
  
  			if (copy_to_user(buf, page, nr_read)) {
  				rv = -EFAULT;
  				goto out_free_page;
  			}
  
  			p	+= nr_read;
  			len	-= nr_read;
  			buf	+= nr_read;
  			count	-= nr_read;
  			rv	+= nr_read;
  		}
  	} else {
  		/*
  		 * Command line (1 string) occupies ARGV and maybe
  		 * extends into ENVP.
  		 */
  		if (len1 + len2 <= *pos)
  			goto skip_argv_envp;
  		if (len1 <= *pos)
  			goto skip_argv;
  
  		p = arg_start + *pos;
  		len = len1 - *pos;
  		while (count > 0 && len > 0) {
  			unsigned int _count, l;
  			int nr_read;
  			bool final;
  
  			_count = min3(count, len, PAGE_SIZE);
272ddc8b3   Linus Torvalds   proc: don't use F...
298
  			nr_read = access_remote_vm(mm, p, page, _count, 0);
c2c0bb446   Alexey Dobriyan   proc: fix PAGE_SI...
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
  			if (nr_read < 0)
  				rv = nr_read;
  			if (nr_read <= 0)
  				goto out_free_page;
  
  			/*
  			 * Command line can be shorter than whole ARGV
  			 * even if last "marker" byte says it is not.
  			 */
  			final = false;
  			l = strnlen(page, nr_read);
  			if (l < nr_read) {
  				nr_read = l;
  				final = true;
  			}
  
  			if (copy_to_user(buf, page, nr_read)) {
  				rv = -EFAULT;
  				goto out_free_page;
  			}
  
  			p	+= nr_read;
  			len	-= nr_read;
  			buf	+= nr_read;
  			count	-= nr_read;
  			rv	+= nr_read;
  
  			if (final)
  				goto out_free_page;
  		}
  skip_argv:
  		/*
  		 * Command line (1 string) occupies ARGV and
  		 * extends into ENVP.
  		 */
  		if (len1 <= *pos) {
  			p = env_start + *pos - len1;
  			len = len1 + len2 - *pos;
  		} else {
  			p = env_start;
  			len = len2;
  		}
  		while (count > 0 && len > 0) {
  			unsigned int _count, l;
  			int nr_read;
  			bool final;
  
  			_count = min3(count, len, PAGE_SIZE);
272ddc8b3   Linus Torvalds   proc: don't use F...
347
  			nr_read = access_remote_vm(mm, p, page, _count, 0);
c2c0bb446   Alexey Dobriyan   proc: fix PAGE_SI...
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
  			if (nr_read < 0)
  				rv = nr_read;
  			if (nr_read <= 0)
  				goto out_free_page;
  
  			/* Find EOS. */
  			final = false;
  			l = strnlen(page, nr_read);
  			if (l < nr_read) {
  				nr_read = l;
  				final = true;
  			}
  
  			if (copy_to_user(buf, page, nr_read)) {
  				rv = -EFAULT;
  				goto out_free_page;
  			}
  
  			p	+= nr_read;
  			len	-= nr_read;
  			buf	+= nr_read;
  			count	-= nr_read;
  			rv	+= nr_read;
  
  			if (final)
  				goto out_free_page;
  		}
  skip_argv_envp:
  		;
  	}
  
  out_free_page:
  	free_page((unsigned long)page);
  out_mmput:
  	mmput(mm);
  	if (rv > 0)
  		*pos += rv;
  	return rv;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
386
  }
c2c0bb446   Alexey Dobriyan   proc: fix PAGE_SI...
387
388
389
390
  static const struct file_operations proc_pid_cmdline_ops = {
  	.read	= proc_pid_cmdline_read,
  	.llseek	= generic_file_llseek,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
391
392
393
394
395
  #ifdef CONFIG_KALLSYMS
  /*
   * Provides a wchan file via kallsyms in a proper one-value-per-file format.
   * Returns the resolved symbol.  If that fails, simply return the address.
   */
edfcd6064   Alexey Dobriyan   proc: convert /pr...
396
397
  static int proc_pid_wchan(struct seq_file *m, struct pid_namespace *ns,
  			  struct pid *pid, struct task_struct *task)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
398
  {
ffb451227   Alexey Dobriyan   Simplify kallsyms...
399
  	unsigned long wchan;
9281acea6   Tejun Heo   kallsyms: make KS...
400
  	char symname[KSYM_NAME_LEN];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
401
402
  
  	wchan = get_wchan(task);
caaee6234   Jann Horn   ptrace: use fsuid...
403
404
  	if (wchan && ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)
  			&& !lookup_symbol_name(wchan, symname))
25ce31916   Joe Perches   proc: remove use ...
405
  		seq_printf(m, "%s", symname);
b2f73922d   Ingo Molnar   fs/proc, core/deb...
406
  	else
1e92a61c4   Robin Humble   Revert "proc/base...
407
  		seq_putc(m, '0');
25ce31916   Joe Perches   proc: remove use ...
408
409
  
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
410
411
  }
  #endif /* CONFIG_KALLSYMS */
a9712bc12   Al Viro   deal with races i...
412
413
414
415
416
  static int lock_trace(struct task_struct *task)
  {
  	int err = mutex_lock_killable(&task->signal->cred_guard_mutex);
  	if (err)
  		return err;
caaee6234   Jann Horn   ptrace: use fsuid...
417
  	if (!ptrace_may_access(task, PTRACE_MODE_ATTACH_FSCREDS)) {
a9712bc12   Al Viro   deal with races i...
418
419
420
421
422
423
424
425
426
427
  		mutex_unlock(&task->signal->cred_guard_mutex);
  		return -EPERM;
  	}
  	return 0;
  }
  
  static void unlock_trace(struct task_struct *task)
  {
  	mutex_unlock(&task->signal->cred_guard_mutex);
  }
2ec220e27   Ken Chen   proc: add /proc/*...
428
429
430
431
432
433
434
435
436
  #ifdef CONFIG_STACKTRACE
  
  #define MAX_STACK_TRACE_DEPTH	64
  
  static int proc_pid_stack(struct seq_file *m, struct pid_namespace *ns,
  			  struct pid *pid, struct task_struct *task)
  {
  	struct stack_trace trace;
  	unsigned long *entries;
a9712bc12   Al Viro   deal with races i...
437
  	int err;
2ec220e27   Ken Chen   proc: add /proc/*...
438
439
440
441
442
443
444
445
446
447
  	int i;
  
  	entries = kmalloc(MAX_STACK_TRACE_DEPTH * sizeof(*entries), GFP_KERNEL);
  	if (!entries)
  		return -ENOMEM;
  
  	trace.nr_entries	= 0;
  	trace.max_entries	= MAX_STACK_TRACE_DEPTH;
  	trace.entries		= entries;
  	trace.skip		= 0;
2ec220e27   Ken Chen   proc: add /proc/*...
448

a9712bc12   Al Viro   deal with races i...
449
450
451
452
453
  	err = lock_trace(task);
  	if (!err) {
  		save_stack_trace_tsk(task, &trace);
  
  		for (i = 0; i < trace.nr_entries; i++) {
8b927d734   Josh Poimboeuf   proc: Fix return ...
454
455
  			seq_printf(m, "[<%pK>] %pB
  ",
a9712bc12   Al Viro   deal with races i...
456
457
458
  				   (void *)entries[i], (void *)entries[i]);
  		}
  		unlock_trace(task);
2ec220e27   Ken Chen   proc: add /proc/*...
459
460
  	}
  	kfree(entries);
a9712bc12   Al Viro   deal with races i...
461
  	return err;
2ec220e27   Ken Chen   proc: add /proc/*...
462
463
  }
  #endif
5968ceced   Naveen N. Rao   sched/stat: Expos...
464
  #ifdef CONFIG_SCHED_INFO
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
465
466
467
  /*
   * Provides /proc/PID/schedstat
   */
f6e826ca3   Alexey Dobriyan   proc: convert /pr...
468
469
  static int proc_pid_schedstat(struct seq_file *m, struct pid_namespace *ns,
  			      struct pid *pid, struct task_struct *task)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
470
  {
5968ceced   Naveen N. Rao   sched/stat: Expos...
471
472
473
474
475
476
  	if (unlikely(!sched_info_on()))
  		seq_printf(m, "0 0 0
  ");
  	else
  		seq_printf(m, "%llu %llu %lu
  ",
25ce31916   Joe Perches   proc: remove use ...
477
478
479
480
481
  		   (unsigned long long)task->se.sum_exec_runtime,
  		   (unsigned long long)task->sched_info.run_delay,
  		   task->sched_info.pcount);
  
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
482
483
  }
  #endif
9745512ce   Arjan van de Ven   sched: latencytop...
484
485
486
487
  #ifdef CONFIG_LATENCYTOP
  static int lstats_show_proc(struct seq_file *m, void *v)
  {
  	int i;
13d77c37c   Hiroshi Shimamoto   latencytop: chang...
488
489
  	struct inode *inode = m->private;
  	struct task_struct *task = get_proc_task(inode);
9745512ce   Arjan van de Ven   sched: latencytop...
490

13d77c37c   Hiroshi Shimamoto   latencytop: chang...
491
492
493
494
  	if (!task)
  		return -ESRCH;
  	seq_puts(m, "Latency Top version : v0.1
  ");
9745512ce   Arjan van de Ven   sched: latencytop...
495
  	for (i = 0; i < 32; i++) {
34e49d4f6   Joe Perches   fs/proc/base.c, k...
496
497
  		struct latency_record *lr = &task->latency_record[i];
  		if (lr->backtrace[0]) {
9745512ce   Arjan van de Ven   sched: latencytop...
498
  			int q;
34e49d4f6   Joe Perches   fs/proc/base.c, k...
499
500
  			seq_printf(m, "%i %li %li",
  				   lr->count, lr->time, lr->max);
9745512ce   Arjan van de Ven   sched: latencytop...
501
  			for (q = 0; q < LT_BACKTRACEDEPTH; q++) {
34e49d4f6   Joe Perches   fs/proc/base.c, k...
502
503
  				unsigned long bt = lr->backtrace[q];
  				if (!bt)
9745512ce   Arjan van de Ven   sched: latencytop...
504
  					break;
34e49d4f6   Joe Perches   fs/proc/base.c, k...
505
  				if (bt == ULONG_MAX)
9745512ce   Arjan van de Ven   sched: latencytop...
506
  					break;
34e49d4f6   Joe Perches   fs/proc/base.c, k...
507
  				seq_printf(m, " %ps", (void *)bt);
9745512ce   Arjan van de Ven   sched: latencytop...
508
  			}
9d6de12f7   Alexey Dobriyan   proc: use seq_put...
509
510
  			seq_putc(m, '
  ');
9745512ce   Arjan van de Ven   sched: latencytop...
511
512
513
  		}
  
  	}
13d77c37c   Hiroshi Shimamoto   latencytop: chang...
514
  	put_task_struct(task);
9745512ce   Arjan van de Ven   sched: latencytop...
515
516
517
518
519
  	return 0;
  }
  
  static int lstats_open(struct inode *inode, struct file *file)
  {
13d77c37c   Hiroshi Shimamoto   latencytop: chang...
520
  	return single_open(file, lstats_show_proc, inode);
d6643d12c   Hiroshi Shimamoto   latencytop: fix m...
521
  }
9745512ce   Arjan van de Ven   sched: latencytop...
522
523
524
  static ssize_t lstats_write(struct file *file, const char __user *buf,
  			    size_t count, loff_t *offs)
  {
496ad9aa8   Al Viro   new helper: file_...
525
  	struct task_struct *task = get_proc_task(file_inode(file));
9745512ce   Arjan van de Ven   sched: latencytop...
526

13d77c37c   Hiroshi Shimamoto   latencytop: chang...
527
528
  	if (!task)
  		return -ESRCH;
9745512ce   Arjan van de Ven   sched: latencytop...
529
  	clear_all_latency_tracing(task);
13d77c37c   Hiroshi Shimamoto   latencytop: chang...
530
  	put_task_struct(task);
9745512ce   Arjan van de Ven   sched: latencytop...
531
532
533
534
535
536
537
538
539
  
  	return count;
  }
  
  static const struct file_operations proc_lstats_operations = {
  	.open		= lstats_open,
  	.read		= seq_read,
  	.write		= lstats_write,
  	.llseek		= seq_lseek,
13d77c37c   Hiroshi Shimamoto   latencytop: chang...
540
  	.release	= single_release,
9745512ce   Arjan van de Ven   sched: latencytop...
541
542
543
  };
  
  #endif
6ba51e375   Alexey Dobriyan   proc: convert /pr...
544
545
  static int proc_oom_score(struct seq_file *m, struct pid_namespace *ns,
  			  struct pid *pid, struct task_struct *task)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
546
  {
a7f638f99   David Rientjes   mm, oom: normaliz...
547
  	unsigned long totalpages = totalram_pages + total_swap_pages;
b95c35e76   Oleg Nesterov   oom: fix the unsa...
548
  	unsigned long points = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
549

ef419398b   Oleg Nesterov   proc_oom_score: r...
550
551
  	points = oom_badness(task, NULL, NULL, totalpages) *
  					1000 / totalpages;
25ce31916   Joe Perches   proc: remove use ...
552
553
554
555
  	seq_printf(m, "%lu
  ", points);
  
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
556
  }
d85f50d5e   Neil Horman   proc: export a pr...
557
  struct limit_names {
cedbccab8   Alexey Dobriyan   proc: more "const...
558
559
  	const char *name;
  	const char *unit;
d85f50d5e   Neil Horman   proc: export a pr...
560
561
562
  };
  
  static const struct limit_names lnames[RLIM_NLIMITS] = {
cff4edb59   Kees Cook   proc: fix reporte...
563
  	[RLIMIT_CPU] = {"Max cpu time", "seconds"},
d85f50d5e   Neil Horman   proc: export a pr...
564
565
566
567
568
569
570
571
572
573
574
575
576
577
  	[RLIMIT_FSIZE] = {"Max file size", "bytes"},
  	[RLIMIT_DATA] = {"Max data size", "bytes"},
  	[RLIMIT_STACK] = {"Max stack size", "bytes"},
  	[RLIMIT_CORE] = {"Max core file size", "bytes"},
  	[RLIMIT_RSS] = {"Max resident set", "bytes"},
  	[RLIMIT_NPROC] = {"Max processes", "processes"},
  	[RLIMIT_NOFILE] = {"Max open files", "files"},
  	[RLIMIT_MEMLOCK] = {"Max locked memory", "bytes"},
  	[RLIMIT_AS] = {"Max address space", "bytes"},
  	[RLIMIT_LOCKS] = {"Max file locks", "locks"},
  	[RLIMIT_SIGPENDING] = {"Max pending signals", "signals"},
  	[RLIMIT_MSGQUEUE] = {"Max msgqueue size", "bytes"},
  	[RLIMIT_NICE] = {"Max nice priority", NULL},
  	[RLIMIT_RTPRIO] = {"Max realtime priority", NULL},
8808117ca   Eugene Teo   proc: add RLIMIT_...
578
  	[RLIMIT_RTTIME] = {"Max realtime timeout", "us"},
d85f50d5e   Neil Horman   proc: export a pr...
579
580
581
  };
  
  /* Display limits for a process */
1c963eb13   Alexey Dobriyan   proc: convert /pr...
582
583
  static int proc_pid_limits(struct seq_file *m, struct pid_namespace *ns,
  			   struct pid *pid, struct task_struct *task)
d85f50d5e   Neil Horman   proc: export a pr...
584
585
  {
  	unsigned int i;
d85f50d5e   Neil Horman   proc: export a pr...
586
  	unsigned long flags;
d85f50d5e   Neil Horman   proc: export a pr...
587
588
  
  	struct rlimit rlim[RLIM_NLIMITS];
a6bebbc87   Lai Jiangshan   [PATCH] signal, p...
589
  	if (!lock_task_sighand(task, &flags))
d85f50d5e   Neil Horman   proc: export a pr...
590
  		return 0;
d85f50d5e   Neil Horman   proc: export a pr...
591
592
  	memcpy(rlim, task->signal->rlim, sizeof(struct rlimit) * RLIM_NLIMITS);
  	unlock_task_sighand(task, &flags);
d85f50d5e   Neil Horman   proc: export a pr...
593
594
595
596
  
  	/*
  	 * print the file header
  	 */
1c963eb13   Alexey Dobriyan   proc: convert /pr...
597
598
         seq_printf(m, "%-25s %-20s %-20s %-10s
  ",
25ce31916   Joe Perches   proc: remove use ...
599
  		  "Limit", "Soft Limit", "Hard Limit", "Units");
d85f50d5e   Neil Horman   proc: export a pr...
600
601
602
  
  	for (i = 0; i < RLIM_NLIMITS; i++) {
  		if (rlim[i].rlim_cur == RLIM_INFINITY)
1c963eb13   Alexey Dobriyan   proc: convert /pr...
603
  			seq_printf(m, "%-25s %-20s ",
25ce31916   Joe Perches   proc: remove use ...
604
  				   lnames[i].name, "unlimited");
d85f50d5e   Neil Horman   proc: export a pr...
605
  		else
1c963eb13   Alexey Dobriyan   proc: convert /pr...
606
  			seq_printf(m, "%-25s %-20lu ",
25ce31916   Joe Perches   proc: remove use ...
607
  				   lnames[i].name, rlim[i].rlim_cur);
d85f50d5e   Neil Horman   proc: export a pr...
608
609
  
  		if (rlim[i].rlim_max == RLIM_INFINITY)
1c963eb13   Alexey Dobriyan   proc: convert /pr...
610
  			seq_printf(m, "%-20s ", "unlimited");
d85f50d5e   Neil Horman   proc: export a pr...
611
  		else
1c963eb13   Alexey Dobriyan   proc: convert /pr...
612
  			seq_printf(m, "%-20lu ", rlim[i].rlim_max);
d85f50d5e   Neil Horman   proc: export a pr...
613
614
  
  		if (lnames[i].unit)
1c963eb13   Alexey Dobriyan   proc: convert /pr...
615
616
  			seq_printf(m, "%-10s
  ", lnames[i].unit);
d85f50d5e   Neil Horman   proc: export a pr...
617
  		else
1c963eb13   Alexey Dobriyan   proc: convert /pr...
618
619
  			seq_putc(m, '
  ');
d85f50d5e   Neil Horman   proc: export a pr...
620
  	}
1c963eb13   Alexey Dobriyan   proc: convert /pr...
621
  	return 0;
d85f50d5e   Neil Horman   proc: export a pr...
622
  }
ebcb67341   Roland McGrath   /proc/PID/syscall
623
  #ifdef CONFIG_HAVE_ARCH_TRACEHOOK
09d93bd62   Alexey Dobriyan   proc: convert /pr...
624
625
  static int proc_pid_syscall(struct seq_file *m, struct pid_namespace *ns,
  			    struct pid *pid, struct task_struct *task)
ebcb67341   Roland McGrath   /proc/PID/syscall
626
627
628
  {
  	long nr;
  	unsigned long args[6], sp, pc;
25ce31916   Joe Perches   proc: remove use ...
629
630
631
  	int res;
  
  	res = lock_trace(task);
a9712bc12   Al Viro   deal with races i...
632
633
  	if (res)
  		return res;
ebcb67341   Roland McGrath   /proc/PID/syscall
634
635
  
  	if (task_current_syscall(task, &nr, args, 6, &sp, &pc))
09d93bd62   Alexey Dobriyan   proc: convert /pr...
636
637
  		seq_puts(m, "running
  ");
a9712bc12   Al Viro   deal with races i...
638
  	else if (nr < 0)
09d93bd62   Alexey Dobriyan   proc: convert /pr...
639
640
  		seq_printf(m, "%ld 0x%lx 0x%lx
  ", nr, sp, pc);
a9712bc12   Al Viro   deal with races i...
641
  	else
09d93bd62   Alexey Dobriyan   proc: convert /pr...
642
  		seq_printf(m,
ebcb67341   Roland McGrath   /proc/PID/syscall
643
644
645
646
647
  		       "%ld 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx
  ",
  		       nr,
  		       args[0], args[1], args[2], args[3], args[4], args[5],
  		       sp, pc);
a9712bc12   Al Viro   deal with races i...
648
  	unlock_trace(task);
25ce31916   Joe Perches   proc: remove use ...
649
650
  
  	return 0;
ebcb67341   Roland McGrath   /proc/PID/syscall
651
652
  }
  #endif /* CONFIG_HAVE_ARCH_TRACEHOOK */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
653
654
655
656
657
  /************************************************************************/
  /*                       Here the fs part begins                        */
  /************************************************************************/
  
  /* permission checks */
778c11447   Eric W. Biederman   [PATCH] proc: Use...
658
  static int proc_fd_access_allowed(struct inode *inode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
659
  {
778c11447   Eric W. Biederman   [PATCH] proc: Use...
660
661
  	struct task_struct *task;
  	int allowed = 0;
df26c40e5   Eric W. Biederman   [PATCH] proc: Cle...
662
663
664
  	/* Allow access to a task's file descriptors if it is us or we
  	 * may use ptrace attach to the process and find out that
  	 * information.
778c11447   Eric W. Biederman   [PATCH] proc: Use...
665
666
  	 */
  	task = get_proc_task(inode);
df26c40e5   Eric W. Biederman   [PATCH] proc: Cle...
667
  	if (task) {
caaee6234   Jann Horn   ptrace: use fsuid...
668
  		allowed = ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS);
778c11447   Eric W. Biederman   [PATCH] proc: Use...
669
  		put_task_struct(task);
df26c40e5   Eric W. Biederman   [PATCH] proc: Cle...
670
  	}
778c11447   Eric W. Biederman   [PATCH] proc: Use...
671
  	return allowed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
672
  }
6b4e306aa   Eric W. Biederman   ns: proc files fo...
673
  int proc_setattr(struct dentry *dentry, struct iattr *attr)
6d76fa58b   Linus Torvalds   Don't allow chmod...
674
675
  {
  	int error;
2b0143b5c   David Howells   VFS: normal files...
676
  	struct inode *inode = d_inode(dentry);
6d76fa58b   Linus Torvalds   Don't allow chmod...
677
678
679
  
  	if (attr->ia_valid & ATTR_MODE)
  		return -EPERM;
31051c85b   Jan Kara   fs: Give dentry t...
680
  	error = setattr_prepare(dentry, attr);
1025774ce   Christoph Hellwig   remove inode_setattr
681
682
  	if (error)
  		return error;
1025774ce   Christoph Hellwig   remove inode_setattr
683
684
685
  	setattr_copy(inode, attr);
  	mark_inode_dirty(inode);
  	return 0;
6d76fa58b   Linus Torvalds   Don't allow chmod...
686
  }
0499680a4   Vasiliy Kulikov   procfs: add hidep...
687
688
689
690
691
692
693
694
695
696
697
698
  /*
   * May current process learn task's sched/cmdline info (for hide_pid_min=1)
   * or euid/egid (for hide_pid_min=2)?
   */
  static bool has_pid_permissions(struct pid_namespace *pid,
  				 struct task_struct *task,
  				 int hide_pid_min)
  {
  	if (pid->hide_pid < hide_pid_min)
  		return true;
  	if (in_group_p(pid->pid_gid))
  		return true;
caaee6234   Jann Horn   ptrace: use fsuid...
699
  	return ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS);
0499680a4   Vasiliy Kulikov   procfs: add hidep...
700
701
702
703
704
705
706
707
708
709
  }
  
  
  static int proc_pid_permission(struct inode *inode, int mask)
  {
  	struct pid_namespace *pid = inode->i_sb->s_fs_info;
  	struct task_struct *task;
  	bool has_perms;
  
  	task = get_proc_task(inode);
a2ef990ab   Xiaotian Feng   proc: fix null po...
710
711
  	if (!task)
  		return -ESRCH;
0499680a4   Vasiliy Kulikov   procfs: add hidep...
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
  	has_perms = has_pid_permissions(pid, task, 1);
  	put_task_struct(task);
  
  	if (!has_perms) {
  		if (pid->hide_pid == 2) {
  			/*
  			 * Let's make getdents(), stat(), and open()
  			 * consistent with each other.  If a process
  			 * may not stat() a file, it shouldn't be seen
  			 * in procfs at all.
  			 */
  			return -ENOENT;
  		}
  
  		return -EPERM;
  	}
  	return generic_permission(inode, mask);
  }
c5ef1c42c   Arjan van de Ven   [PATCH] mark stru...
730
  static const struct inode_operations proc_def_inode_operations = {
6d76fa58b   Linus Torvalds   Don't allow chmod...
731
732
  	.setattr	= proc_setattr,
  };
be614086a   Eric W. Biederman   proc: implement p...
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
  static int proc_single_show(struct seq_file *m, void *v)
  {
  	struct inode *inode = m->private;
  	struct pid_namespace *ns;
  	struct pid *pid;
  	struct task_struct *task;
  	int ret;
  
  	ns = inode->i_sb->s_fs_info;
  	pid = proc_pid(inode);
  	task = get_pid_task(pid, PIDTYPE_PID);
  	if (!task)
  		return -ESRCH;
  
  	ret = PROC_I(inode)->op.proc_show(m, ns, pid, task);
  
  	put_task_struct(task);
  	return ret;
  }
  
  static int proc_single_open(struct inode *inode, struct file *filp)
  {
c6a340584   Jovi Zhang   proc: use single_...
755
  	return single_open(filp, proc_single_show, inode);
be614086a   Eric W. Biederman   proc: implement p...
756
757
758
759
760
761
762
763
  }
  
  static const struct file_operations proc_single_file_operations = {
  	.open		= proc_single_open,
  	.read		= seq_read,
  	.llseek		= seq_lseek,
  	.release	= single_release,
  };
5381e169e   Oleg Nesterov   proc: introduce p...
764
765
  
  struct mm_struct *proc_mem_open(struct inode *inode, unsigned int mode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
766
  {
5381e169e   Oleg Nesterov   proc: introduce p...
767
768
  	struct task_struct *task = get_proc_task(inode);
  	struct mm_struct *mm = ERR_PTR(-ESRCH);
e268337df   Linus Torvalds   proc: clean up an...
769

5381e169e   Oleg Nesterov   proc: introduce p...
770
  	if (task) {
caaee6234   Jann Horn   ptrace: use fsuid...
771
  		mm = mm_access(task, mode | PTRACE_MODE_FSCREDS);
5381e169e   Oleg Nesterov   proc: introduce p...
772
  		put_task_struct(task);
e268337df   Linus Torvalds   proc: clean up an...
773

5381e169e   Oleg Nesterov   proc: introduce p...
774
775
776
777
778
779
780
781
782
783
784
785
786
787
  		if (!IS_ERR_OR_NULL(mm)) {
  			/* ensure this mm_struct can't be freed */
  			atomic_inc(&mm->mm_count);
  			/* but do not pin its memory */
  			mmput(mm);
  		}
  	}
  
  	return mm;
  }
  
  static int __mem_open(struct inode *inode, struct file *file, unsigned int mode)
  {
  	struct mm_struct *mm = proc_mem_open(inode, mode);
e268337df   Linus Torvalds   proc: clean up an...
788
789
790
  
  	if (IS_ERR(mm))
  		return PTR_ERR(mm);
e268337df   Linus Torvalds   proc: clean up an...
791
  	file->private_data = mm;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
792
793
  	return 0;
  }
b409e578d   Cong Wang   proc: clean up /p...
794
795
  static int mem_open(struct inode *inode, struct file *file)
  {
bc452b4b6   Djalal Harouni   proc: do not allo...
796
797
798
799
800
801
  	int ret = __mem_open(inode, file, PTRACE_MODE_ATTACH);
  
  	/* OK to pass negative loff_t, we can catch out-of-range */
  	file->f_mode |= FMODE_UNSIGNED_OFFSET;
  
  	return ret;
b409e578d   Cong Wang   proc: clean up /p...
802
  }
572d34b94   Oleg Nesterov   proc: unify mem_r...
803
804
  static ssize_t mem_rw(struct file *file, char __user *buf,
  			size_t count, loff_t *ppos, int write)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
805
  {
e268337df   Linus Torvalds   proc: clean up an...
806
  	struct mm_struct *mm = file->private_data;
572d34b94   Oleg Nesterov   proc: unify mem_r...
807
808
  	unsigned long addr = *ppos;
  	ssize_t copied;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
809
  	char *page;
272ddc8b3   Linus Torvalds   proc: don't use F...
810
  	unsigned int flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
811

e268337df   Linus Torvalds   proc: clean up an...
812
813
  	if (!mm)
  		return 0;
99f895518   Eric W. Biederman   [PATCH] proc: don...
814

30cd89039   KOSAKI Motohiro   proc: put check_m...
815
816
  	page = (char *)__get_free_page(GFP_TEMPORARY);
  	if (!page)
e268337df   Linus Torvalds   proc: clean up an...
817
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
818

f7ca54f48   Frederik Deweerdt   [PATCH] fix mem_w...
819
  	copied = 0;
6d08f2c71   Oleg Nesterov   proc: make sure m...
820
821
  	if (!atomic_inc_not_zero(&mm->mm_users))
  		goto free;
272ddc8b3   Linus Torvalds   proc: don't use F...
822
823
  	/* Maybe we should limit FOLL_FORCE to actual ptrace users? */
  	flags = FOLL_FORCE;
6347e8d5b   Lorenzo Stoakes   mm: replace acces...
824
825
  	if (write)
  		flags |= FOLL_WRITE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
826
  	while (count > 0) {
572d34b94   Oleg Nesterov   proc: unify mem_r...
827
  		int this_len = min_t(int, count, PAGE_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
828

572d34b94   Oleg Nesterov   proc: unify mem_r...
829
  		if (write && copy_from_user(page, buf, this_len)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
830
831
832
  			copied = -EFAULT;
  			break;
  		}
572d34b94   Oleg Nesterov   proc: unify mem_r...
833

6347e8d5b   Lorenzo Stoakes   mm: replace acces...
834
  		this_len = access_remote_vm(mm, addr, page, this_len, flags);
572d34b94   Oleg Nesterov   proc: unify mem_r...
835
  		if (!this_len) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
836
837
838
839
  			if (!copied)
  				copied = -EIO;
  			break;
  		}
572d34b94   Oleg Nesterov   proc: unify mem_r...
840
841
842
843
844
845
846
847
848
849
  
  		if (!write && copy_to_user(buf, page, this_len)) {
  			copied = -EFAULT;
  			break;
  		}
  
  		buf += this_len;
  		addr += this_len;
  		copied += this_len;
  		count -= this_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
850
  	}
572d34b94   Oleg Nesterov   proc: unify mem_r...
851
  	*ppos = addr;
30cd89039   KOSAKI Motohiro   proc: put check_m...
852

6d08f2c71   Oleg Nesterov   proc: make sure m...
853
854
  	mmput(mm);
  free:
30cd89039   KOSAKI Motohiro   proc: put check_m...
855
  	free_page((unsigned long) page);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
856
857
  	return copied;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
858

572d34b94   Oleg Nesterov   proc: unify mem_r...
859
860
861
862
863
864
865
866
867
868
869
  static ssize_t mem_read(struct file *file, char __user *buf,
  			size_t count, loff_t *ppos)
  {
  	return mem_rw(file, buf, count, ppos, 0);
  }
  
  static ssize_t mem_write(struct file *file, const char __user *buf,
  			 size_t count, loff_t *ppos)
  {
  	return mem_rw(file, (char __user*)buf, count, ppos, 1);
  }
85863e475   Matt Mackall   maps4: add /proc/...
870
  loff_t mem_lseek(struct file *file, loff_t offset, int orig)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
871
872
873
874
875
876
877
878
879
880
881
882
883
884
  {
  	switch (orig) {
  	case 0:
  		file->f_pos = offset;
  		break;
  	case 1:
  		file->f_pos += offset;
  		break;
  	default:
  		return -EINVAL;
  	}
  	force_successful_syscall_return();
  	return file->f_pos;
  }
e268337df   Linus Torvalds   proc: clean up an...
885
886
887
  static int mem_release(struct inode *inode, struct file *file)
  {
  	struct mm_struct *mm = file->private_data;
71879d3cb   Oleg Nesterov   proc: mem_release...
888
  	if (mm)
6d08f2c71   Oleg Nesterov   proc: make sure m...
889
  		mmdrop(mm);
e268337df   Linus Torvalds   proc: clean up an...
890
891
  	return 0;
  }
00977a59b   Arjan van de Ven   [PATCH] mark stru...
892
  static const struct file_operations proc_mem_operations = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
893
894
895
896
  	.llseek		= mem_lseek,
  	.read		= mem_read,
  	.write		= mem_write,
  	.open		= mem_open,
e268337df   Linus Torvalds   proc: clean up an...
897
  	.release	= mem_release,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
898
  };
b409e578d   Cong Wang   proc: clean up /p...
899
900
901
902
  static int environ_open(struct inode *inode, struct file *file)
  {
  	return __mem_open(inode, file, PTRACE_MODE_READ);
  }
315e28c8d   James Pearson   Don't truncate /p...
903
904
905
  static ssize_t environ_read(struct file *file, char __user *buf,
  			size_t count, loff_t *ppos)
  {
315e28c8d   James Pearson   Don't truncate /p...
906
907
  	char *page;
  	unsigned long src = *ppos;
b409e578d   Cong Wang   proc: clean up /p...
908
909
  	int ret = 0;
  	struct mm_struct *mm = file->private_data;
a3b609ef9   Mateusz Guzik   proc read mm's {a...
910
  	unsigned long env_start, env_end;
315e28c8d   James Pearson   Don't truncate /p...
911

8148a73c9   Mathias Krause   proc: prevent acc...
912
913
  	/* Ensure the process spawned far enough to have an environment. */
  	if (!mm || !mm->env_end)
b409e578d   Cong Wang   proc: clean up /p...
914
  		return 0;
315e28c8d   James Pearson   Don't truncate /p...
915

315e28c8d   James Pearson   Don't truncate /p...
916
917
  	page = (char *)__get_free_page(GFP_TEMPORARY);
  	if (!page)
b409e578d   Cong Wang   proc: clean up /p...
918
  		return -ENOMEM;
315e28c8d   James Pearson   Don't truncate /p...
919

d6f64b89d   Al Viro   close race in /pr...
920
  	ret = 0;
b409e578d   Cong Wang   proc: clean up /p...
921
922
  	if (!atomic_inc_not_zero(&mm->mm_users))
  		goto free;
a3b609ef9   Mateusz Guzik   proc read mm's {a...
923
924
925
926
927
  
  	down_read(&mm->mmap_sem);
  	env_start = mm->env_start;
  	env_end = mm->env_end;
  	up_read(&mm->mmap_sem);
315e28c8d   James Pearson   Don't truncate /p...
928
  	while (count > 0) {
e8905ec27   Djalal Harouni   proc: environ_rea...
929
930
  		size_t this_len, max_len;
  		int retval;
315e28c8d   James Pearson   Don't truncate /p...
931

a3b609ef9   Mateusz Guzik   proc read mm's {a...
932
  		if (src >= (env_end - env_start))
315e28c8d   James Pearson   Don't truncate /p...
933
  			break;
a3b609ef9   Mateusz Guzik   proc read mm's {a...
934
  		this_len = env_end - (env_start + src);
e8905ec27   Djalal Harouni   proc: environ_rea...
935
936
937
  
  		max_len = min_t(size_t, PAGE_SIZE, count);
  		this_len = min(max_len, this_len);
315e28c8d   James Pearson   Don't truncate /p...
938

272ddc8b3   Linus Torvalds   proc: don't use F...
939
  		retval = access_remote_vm(mm, (env_start + src), page, this_len, 0);
315e28c8d   James Pearson   Don't truncate /p...
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
  
  		if (retval <= 0) {
  			ret = retval;
  			break;
  		}
  
  		if (copy_to_user(buf, page, retval)) {
  			ret = -EFAULT;
  			break;
  		}
  
  		ret += retval;
  		src += retval;
  		buf += retval;
  		count -= retval;
  	}
  	*ppos = src;
315e28c8d   James Pearson   Don't truncate /p...
957
  	mmput(mm);
b409e578d   Cong Wang   proc: clean up /p...
958
959
  
  free:
315e28c8d   James Pearson   Don't truncate /p...
960
  	free_page((unsigned long) page);
315e28c8d   James Pearson   Don't truncate /p...
961
962
963
964
  	return ret;
  }
  
  static const struct file_operations proc_environ_operations = {
b409e578d   Cong Wang   proc: clean up /p...
965
  	.open		= environ_open,
315e28c8d   James Pearson   Don't truncate /p...
966
  	.read		= environ_read,
87df84241   Arnd Bergmann   procfs: Kill BKL ...
967
  	.llseek		= generic_file_llseek,
b409e578d   Cong Wang   proc: clean up /p...
968
  	.release	= mem_release,
315e28c8d   James Pearson   Don't truncate /p...
969
  };
c53171678   Al Viro   proc: switch auxv...
970
971
972
973
974
975
976
977
978
979
  static int auxv_open(struct inode *inode, struct file *file)
  {
  	return __mem_open(inode, file, PTRACE_MODE_READ_FSCREDS);
  }
  
  static ssize_t auxv_read(struct file *file, char __user *buf,
  			size_t count, loff_t *ppos)
  {
  	struct mm_struct *mm = file->private_data;
  	unsigned int nwords = 0;
06b2849d1   Leon Yu   proc: fix NULL de...
980
981
982
  
  	if (!mm)
  		return 0;
c53171678   Al Viro   proc: switch auxv...
983
984
985
986
987
988
989
990
991
992
993
994
995
  	do {
  		nwords += 2;
  	} while (mm->saved_auxv[nwords - 2] != 0); /* AT_NULL */
  	return simple_read_from_buffer(buf, count, ppos, mm->saved_auxv,
  				       nwords * sizeof(mm->saved_auxv[0]));
  }
  
  static const struct file_operations proc_auxv_operations = {
  	.open		= auxv_open,
  	.read		= auxv_read,
  	.llseek		= generic_file_llseek,
  	.release	= mem_release,
  };
fa0cbbf14   David Rientjes   mm, oom: reintrod...
996
997
998
  static ssize_t oom_adj_read(struct file *file, char __user *buf, size_t count,
  			    loff_t *ppos)
  {
496ad9aa8   Al Viro   new helper: file_...
999
  	struct task_struct *task = get_proc_task(file_inode(file));
fa0cbbf14   David Rientjes   mm, oom: reintrod...
1000
1001
1002
  	char buffer[PROC_NUMBUF];
  	int oom_adj = OOM_ADJUST_MIN;
  	size_t len;
fa0cbbf14   David Rientjes   mm, oom: reintrod...
1003
1004
1005
  
  	if (!task)
  		return -ESRCH;
f913da596   Michal Hocko   proc, oom: drop b...
1006
1007
1008
1009
1010
  	if (task->signal->oom_score_adj == OOM_SCORE_ADJ_MAX)
  		oom_adj = OOM_ADJUST_MAX;
  	else
  		oom_adj = (task->signal->oom_score_adj * -OOM_DISABLE) /
  			  OOM_SCORE_ADJ_MAX;
fa0cbbf14   David Rientjes   mm, oom: reintrod...
1011
1012
1013
1014
1015
  	put_task_struct(task);
  	len = snprintf(buffer, sizeof(buffer), "%d
  ", oom_adj);
  	return simple_read_from_buffer(buf, count, ppos, buffer, len);
  }
1d5f0acbc   Michal Hocko   proc, oom_adj: ex...
1016
1017
1018
  static int __set_oom_adj(struct file *file, int oom_adj, bool legacy)
  {
  	static DEFINE_MUTEX(oom_adj_mutex);
44a70adec   Michal Hocko   mm, oom_adj: make...
1019
  	struct mm_struct *mm = NULL;
1d5f0acbc   Michal Hocko   proc, oom_adj: ex...
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
  	struct task_struct *task;
  	int err = 0;
  
  	task = get_proc_task(file_inode(file));
  	if (!task)
  		return -ESRCH;
  
  	mutex_lock(&oom_adj_mutex);
  	if (legacy) {
  		if (oom_adj < task->signal->oom_score_adj &&
  				!capable(CAP_SYS_RESOURCE)) {
  			err = -EACCES;
  			goto err_unlock;
  		}
  		/*
  		 * /proc/pid/oom_adj is provided for legacy purposes, ask users to use
  		 * /proc/pid/oom_score_adj instead.
  		 */
  		pr_warn_once("%s (%d): /proc/%d/oom_adj is deprecated, please use /proc/%d/oom_score_adj instead.
  ",
  			  current->comm, task_pid_nr(current), task_pid_nr(task),
  			  task_pid_nr(task));
  	} else {
  		if ((short)oom_adj < task->signal->oom_score_adj_min &&
  				!capable(CAP_SYS_RESOURCE)) {
  			err = -EACCES;
  			goto err_unlock;
  		}
  	}
44a70adec   Michal Hocko   mm, oom_adj: make...
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
  	/*
  	 * Make sure we will check other processes sharing the mm if this is
  	 * not vfrok which wants its own oom_score_adj.
  	 * pin the mm so it doesn't go away and get reused after task_unlock
  	 */
  	if (!task->vfork_done) {
  		struct task_struct *p = find_lock_task_mm(task);
  
  		if (p) {
  			if (atomic_read(&p->mm->mm_users) > 1) {
  				mm = p->mm;
  				atomic_inc(&mm->mm_count);
  			}
  			task_unlock(p);
  		}
  	}
1d5f0acbc   Michal Hocko   proc, oom_adj: ex...
1065
1066
1067
1068
  	task->signal->oom_score_adj = oom_adj;
  	if (!legacy && has_capability_noaudit(current, CAP_SYS_RESOURCE))
  		task->signal->oom_score_adj_min = (short)oom_adj;
  	trace_oom_score_adj_update(task);
44a70adec   Michal Hocko   mm, oom_adj: make...
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
  
  	if (mm) {
  		struct task_struct *p;
  
  		rcu_read_lock();
  		for_each_process(p) {
  			if (same_thread_group(task, p))
  				continue;
  
  			/* do not touch kernel threads or the global init */
  			if (p->flags & PF_KTHREAD || is_global_init(p))
  				continue;
  
  			task_lock(p);
  			if (!p->vfork_done && process_shares_mm(p, mm)) {
  				pr_info("updating oom_score_adj for %d (%s) from %d to %d because it shares mm with %d (%s). Report if this is unexpected.
  ",
  						task_pid_nr(p), p->comm,
  						p->signal->oom_score_adj, oom_adj,
  						task_pid_nr(task), task->comm);
  				p->signal->oom_score_adj = oom_adj;
  				if (!legacy && has_capability_noaudit(current, CAP_SYS_RESOURCE))
  					p->signal->oom_score_adj_min = (short)oom_adj;
  			}
  			task_unlock(p);
  		}
  		rcu_read_unlock();
  		mmdrop(mm);
  	}
1d5f0acbc   Michal Hocko   proc, oom_adj: ex...
1098
1099
1100
1101
1102
  err_unlock:
  	mutex_unlock(&oom_adj_mutex);
  	put_task_struct(task);
  	return err;
  }
f913da596   Michal Hocko   proc, oom: drop b...
1103

b72bdfa73   David Rientjes   mm, oom: add comm...
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
  /*
   * /proc/pid/oom_adj exists solely for backwards compatibility with previous
   * kernels.  The effective policy is defined by oom_score_adj, which has a
   * different scale: oom_adj grew exponentially and oom_score_adj grows linearly.
   * Values written to oom_adj are simply mapped linearly to oom_score_adj.
   * Processes that become oom disabled via oom_adj will still be oom disabled
   * with this implementation.
   *
   * oom_adj cannot be removed since existing userspace binaries use it.
   */
fa0cbbf14   David Rientjes   mm, oom: reintrod...
1114
1115
1116
  static ssize_t oom_adj_write(struct file *file, const char __user *buf,
  			     size_t count, loff_t *ppos)
  {
fa0cbbf14   David Rientjes   mm, oom: reintrod...
1117
1118
  	char buffer[PROC_NUMBUF];
  	int oom_adj;
fa0cbbf14   David Rientjes   mm, oom: reintrod...
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
  	int err;
  
  	memset(buffer, 0, sizeof(buffer));
  	if (count > sizeof(buffer) - 1)
  		count = sizeof(buffer) - 1;
  	if (copy_from_user(buffer, buf, count)) {
  		err = -EFAULT;
  		goto out;
  	}
  
  	err = kstrtoint(strstrip(buffer), 0, &oom_adj);
  	if (err)
  		goto out;
  	if ((oom_adj < OOM_ADJUST_MIN || oom_adj > OOM_ADJUST_MAX) &&
  	     oom_adj != OOM_DISABLE) {
  		err = -EINVAL;
  		goto out;
  	}
fa0cbbf14   David Rientjes   mm, oom: reintrod...
1137
1138
1139
1140
1141
1142
1143
1144
  	/*
  	 * Scale /proc/pid/oom_score_adj appropriately ensuring that a maximum
  	 * value is always attainable.
  	 */
  	if (oom_adj == OOM_ADJUST_MAX)
  		oom_adj = OOM_SCORE_ADJ_MAX;
  	else
  		oom_adj = (oom_adj * OOM_SCORE_ADJ_MAX) / -OOM_DISABLE;
1d5f0acbc   Michal Hocko   proc, oom_adj: ex...
1145
  	err = __set_oom_adj(file, oom_adj, true);
fa0cbbf14   David Rientjes   mm, oom: reintrod...
1146
1147
1148
1149
1150
1151
1152
1153
1154
  out:
  	return err < 0 ? err : count;
  }
  
  static const struct file_operations proc_oom_adj_operations = {
  	.read		= oom_adj_read,
  	.write		= oom_adj_write,
  	.llseek		= generic_file_llseek,
  };
a63d83f42   David Rientjes   oom: badness heur...
1155
1156
1157
  static ssize_t oom_score_adj_read(struct file *file, char __user *buf,
  					size_t count, loff_t *ppos)
  {
496ad9aa8   Al Viro   new helper: file_...
1158
  	struct task_struct *task = get_proc_task(file_inode(file));
a63d83f42   David Rientjes   oom: badness heur...
1159
  	char buffer[PROC_NUMBUF];
a9c58b907   David Rientjes   mm, oom: change t...
1160
  	short oom_score_adj = OOM_SCORE_ADJ_MIN;
a63d83f42   David Rientjes   oom: badness heur...
1161
1162
1163
1164
  	size_t len;
  
  	if (!task)
  		return -ESRCH;
f913da596   Michal Hocko   proc, oom: drop b...
1165
  	oom_score_adj = task->signal->oom_score_adj;
a63d83f42   David Rientjes   oom: badness heur...
1166
  	put_task_struct(task);
a9c58b907   David Rientjes   mm, oom: change t...
1167
1168
  	len = snprintf(buffer, sizeof(buffer), "%hd
  ", oom_score_adj);
a63d83f42   David Rientjes   oom: badness heur...
1169
1170
1171
1172
1173
1174
  	return simple_read_from_buffer(buf, count, ppos, buffer, len);
  }
  
  static ssize_t oom_score_adj_write(struct file *file, const char __user *buf,
  					size_t count, loff_t *ppos)
  {
a63d83f42   David Rientjes   oom: badness heur...
1175
  	char buffer[PROC_NUMBUF];
0a8cb8e34   Alexey Dobriyan   fs/proc: convert ...
1176
  	int oom_score_adj;
a63d83f42   David Rientjes   oom: badness heur...
1177
1178
1179
1180
1181
  	int err;
  
  	memset(buffer, 0, sizeof(buffer));
  	if (count > sizeof(buffer) - 1)
  		count = sizeof(buffer) - 1;
723548bff   David Rientjes   oom: rewrite erro...
1182
1183
1184
1185
  	if (copy_from_user(buffer, buf, count)) {
  		err = -EFAULT;
  		goto out;
  	}
a63d83f42   David Rientjes   oom: badness heur...
1186

0a8cb8e34   Alexey Dobriyan   fs/proc: convert ...
1187
  	err = kstrtoint(strstrip(buffer), 0, &oom_score_adj);
a63d83f42   David Rientjes   oom: badness heur...
1188
  	if (err)
723548bff   David Rientjes   oom: rewrite erro...
1189
  		goto out;
a63d83f42   David Rientjes   oom: badness heur...
1190
  	if (oom_score_adj < OOM_SCORE_ADJ_MIN ||
723548bff   David Rientjes   oom: rewrite erro...
1191
1192
1193
1194
  			oom_score_adj > OOM_SCORE_ADJ_MAX) {
  		err = -EINVAL;
  		goto out;
  	}
a63d83f42   David Rientjes   oom: badness heur...
1195

1d5f0acbc   Michal Hocko   proc, oom_adj: ex...
1196
  	err = __set_oom_adj(file, oom_score_adj, false);
723548bff   David Rientjes   oom: rewrite erro...
1197
1198
  out:
  	return err < 0 ? err : count;
a63d83f42   David Rientjes   oom: badness heur...
1199
1200
1201
1202
1203
  }
  
  static const struct file_operations proc_oom_score_adj_operations = {
  	.read		= oom_score_adj_read,
  	.write		= oom_score_adj_write,
6038f373a   Arnd Bergmann   llseek: automatic...
1204
  	.llseek		= default_llseek,
a63d83f42   David Rientjes   oom: badness heur...
1205
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1206
1207
1208
1209
1210
  #ifdef CONFIG_AUDITSYSCALL
  #define TMPBUFLEN 21
  static ssize_t proc_loginuid_read(struct file * file, char __user * buf,
  				  size_t count, loff_t *ppos)
  {
496ad9aa8   Al Viro   new helper: file_...
1211
  	struct inode * inode = file_inode(file);
99f895518   Eric W. Biederman   [PATCH] proc: don...
1212
  	struct task_struct *task = get_proc_task(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1213
1214
  	ssize_t length;
  	char tmpbuf[TMPBUFLEN];
99f895518   Eric W. Biederman   [PATCH] proc: don...
1215
1216
  	if (!task)
  		return -ESRCH;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1217
  	length = scnprintf(tmpbuf, TMPBUFLEN, "%u",
e1760bd5f   Eric W. Biederman   userns: Convert t...
1218
1219
  			   from_kuid(file->f_cred->user_ns,
  				     audit_get_loginuid(task)));
99f895518   Eric W. Biederman   [PATCH] proc: don...
1220
  	put_task_struct(task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1221
1222
1223
1224
1225
1226
  	return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
  }
  
  static ssize_t proc_loginuid_write(struct file * file, const char __user * buf,
  				   size_t count, loff_t *ppos)
  {
496ad9aa8   Al Viro   new helper: file_...
1227
  	struct inode * inode = file_inode(file);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1228
  	uid_t loginuid;
e1760bd5f   Eric W. Biederman   userns: Convert t...
1229
  	kuid_t kloginuid;
774636e19   Alexey Dobriyan   proc: convert to ...
1230
  	int rv;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1231

7dc521579   Paul E. McKenney   vfs: Apply lockde...
1232
1233
1234
  	rcu_read_lock();
  	if (current != pid_task(proc_pid(inode), PIDTYPE_PID)) {
  		rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1235
  		return -EPERM;
7dc521579   Paul E. McKenney   vfs: Apply lockde...
1236
1237
  	}
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1238

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1239
1240
1241
1242
  	if (*ppos != 0) {
  		/* No partial writes. */
  		return -EINVAL;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1243

774636e19   Alexey Dobriyan   proc: convert to ...
1244
1245
1246
  	rv = kstrtou32_from_user(buf, count, 10, &loginuid);
  	if (rv < 0)
  		return rv;
81407c84a   Eric Paris   audit: allow unse...
1247
1248
1249
1250
1251
1252
  
  	/* is userspace tring to explicitly UNSET the loginuid? */
  	if (loginuid == AUDIT_UID_UNSET) {
  		kloginuid = INVALID_UID;
  	} else {
  		kloginuid = make_kuid(file->f_cred->user_ns, loginuid);
774636e19   Alexey Dobriyan   proc: convert to ...
1253
1254
  		if (!uid_valid(kloginuid))
  			return -EINVAL;
e1760bd5f   Eric W. Biederman   userns: Convert t...
1255
  	}
774636e19   Alexey Dobriyan   proc: convert to ...
1256
1257
1258
1259
  	rv = audit_set_loginuid(kloginuid);
  	if (rv < 0)
  		return rv;
  	return count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1260
  }
00977a59b   Arjan van de Ven   [PATCH] mark stru...
1261
  static const struct file_operations proc_loginuid_operations = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1262
1263
  	.read		= proc_loginuid_read,
  	.write		= proc_loginuid_write,
87df84241   Arnd Bergmann   procfs: Kill BKL ...
1264
  	.llseek		= generic_file_llseek,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1265
  };
1e0bd7550   Eric Paris   [PATCH] export se...
1266
1267
1268
1269
  
  static ssize_t proc_sessionid_read(struct file * file, char __user * buf,
  				  size_t count, loff_t *ppos)
  {
496ad9aa8   Al Viro   new helper: file_...
1270
  	struct inode * inode = file_inode(file);
1e0bd7550   Eric Paris   [PATCH] export se...
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
  	struct task_struct *task = get_proc_task(inode);
  	ssize_t length;
  	char tmpbuf[TMPBUFLEN];
  
  	if (!task)
  		return -ESRCH;
  	length = scnprintf(tmpbuf, TMPBUFLEN, "%u",
  				audit_get_sessionid(task));
  	put_task_struct(task);
  	return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
  }
  
  static const struct file_operations proc_sessionid_operations = {
  	.read		= proc_sessionid_read,
87df84241   Arnd Bergmann   procfs: Kill BKL ...
1285
  	.llseek		= generic_file_llseek,
1e0bd7550   Eric Paris   [PATCH] export se...
1286
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1287
  #endif
f4f154fd9   Akinobu Mita   [PATCH] fault inj...
1288
1289
1290
1291
  #ifdef CONFIG_FAULT_INJECTION
  static ssize_t proc_fault_inject_read(struct file * file, char __user * buf,
  				      size_t count, loff_t *ppos)
  {
496ad9aa8   Al Viro   new helper: file_...
1292
  	struct task_struct *task = get_proc_task(file_inode(file));
f4f154fd9   Akinobu Mita   [PATCH] fault inj...
1293
1294
1295
  	char buffer[PROC_NUMBUF];
  	size_t len;
  	int make_it_fail;
f4f154fd9   Akinobu Mita   [PATCH] fault inj...
1296
1297
1298
1299
1300
1301
1302
1303
  
  	if (!task)
  		return -ESRCH;
  	make_it_fail = task->make_it_fail;
  	put_task_struct(task);
  
  	len = snprintf(buffer, sizeof(buffer), "%i
  ", make_it_fail);
0c28f287a   Akinobu Mita   procfs: use simpl...
1304
1305
  
  	return simple_read_from_buffer(buf, count, ppos, buffer, len);
f4f154fd9   Akinobu Mita   [PATCH] fault inj...
1306
1307
1308
1309
1310
1311
  }
  
  static ssize_t proc_fault_inject_write(struct file * file,
  			const char __user * buf, size_t count, loff_t *ppos)
  {
  	struct task_struct *task;
774636e19   Alexey Dobriyan   proc: convert to ...
1312
  	char buffer[PROC_NUMBUF];
f4f154fd9   Akinobu Mita   [PATCH] fault inj...
1313
  	int make_it_fail;
774636e19   Alexey Dobriyan   proc: convert to ...
1314
  	int rv;
f4f154fd9   Akinobu Mita   [PATCH] fault inj...
1315
1316
1317
1318
1319
1320
1321
1322
  
  	if (!capable(CAP_SYS_RESOURCE))
  		return -EPERM;
  	memset(buffer, 0, sizeof(buffer));
  	if (count > sizeof(buffer) - 1)
  		count = sizeof(buffer) - 1;
  	if (copy_from_user(buffer, buf, count))
  		return -EFAULT;
774636e19   Alexey Dobriyan   proc: convert to ...
1323
1324
1325
  	rv = kstrtoint(strstrip(buffer), 0, &make_it_fail);
  	if (rv < 0)
  		return rv;
16caed319   Dave Jones   fault-injection: ...
1326
1327
  	if (make_it_fail < 0 || make_it_fail > 1)
  		return -EINVAL;
496ad9aa8   Al Viro   new helper: file_...
1328
  	task = get_proc_task(file_inode(file));
f4f154fd9   Akinobu Mita   [PATCH] fault inj...
1329
1330
1331
1332
  	if (!task)
  		return -ESRCH;
  	task->make_it_fail = make_it_fail;
  	put_task_struct(task);
cba8aafe1   Vincent Li   fs/proc/base.c: f...
1333
1334
  
  	return count;
f4f154fd9   Akinobu Mita   [PATCH] fault inj...
1335
  }
00977a59b   Arjan van de Ven   [PATCH] mark stru...
1336
  static const struct file_operations proc_fault_inject_operations = {
f4f154fd9   Akinobu Mita   [PATCH] fault inj...
1337
1338
  	.read		= proc_fault_inject_read,
  	.write		= proc_fault_inject_write,
87df84241   Arnd Bergmann   procfs: Kill BKL ...
1339
  	.llseek		= generic_file_llseek,
f4f154fd9   Akinobu Mita   [PATCH] fault inj...
1340
1341
  };
  #endif
9745512ce   Arjan van de Ven   sched: latencytop...
1342

43ae34cb4   Ingo Molnar   sched: scheduler ...
1343
1344
1345
1346
1347
1348
1349
1350
  #ifdef CONFIG_SCHED_DEBUG
  /*
   * Print out various scheduling related per-task fields:
   */
  static int sched_show(struct seq_file *m, void *v)
  {
  	struct inode *inode = m->private;
  	struct task_struct *p;
43ae34cb4   Ingo Molnar   sched: scheduler ...
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
  	p = get_proc_task(inode);
  	if (!p)
  		return -ESRCH;
  	proc_sched_show_task(p, m);
  
  	put_task_struct(p);
  
  	return 0;
  }
  
  static ssize_t
  sched_write(struct file *file, const char __user *buf,
  	    size_t count, loff_t *offset)
  {
496ad9aa8   Al Viro   new helper: file_...
1365
  	struct inode *inode = file_inode(file);
43ae34cb4   Ingo Molnar   sched: scheduler ...
1366
  	struct task_struct *p;
43ae34cb4   Ingo Molnar   sched: scheduler ...
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
  	p = get_proc_task(inode);
  	if (!p)
  		return -ESRCH;
  	proc_sched_set_task(p);
  
  	put_task_struct(p);
  
  	return count;
  }
  
  static int sched_open(struct inode *inode, struct file *filp)
  {
c6a340584   Jovi Zhang   proc: use single_...
1379
  	return single_open(filp, sched_show, inode);
43ae34cb4   Ingo Molnar   sched: scheduler ...
1380
1381
1382
1383
1384
1385
1386
  }
  
  static const struct file_operations proc_pid_sched_operations = {
  	.open		= sched_open,
  	.read		= seq_read,
  	.write		= sched_write,
  	.llseek		= seq_lseek,
5ea473a1d   Alexey Dobriyan   Fix leaks on /pro...
1387
  	.release	= single_release,
43ae34cb4   Ingo Molnar   sched: scheduler ...
1388
1389
1390
  };
  
  #endif
5091faa44   Mike Galbraith   sched: Add 'autog...
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
  #ifdef CONFIG_SCHED_AUTOGROUP
  /*
   * Print out autogroup related information:
   */
  static int sched_autogroup_show(struct seq_file *m, void *v)
  {
  	struct inode *inode = m->private;
  	struct task_struct *p;
  
  	p = get_proc_task(inode);
  	if (!p)
  		return -ESRCH;
  	proc_sched_autogroup_show_task(p, m);
  
  	put_task_struct(p);
  
  	return 0;
  }
  
  static ssize_t
  sched_autogroup_write(struct file *file, const char __user *buf,
  	    size_t count, loff_t *offset)
  {
496ad9aa8   Al Viro   new helper: file_...
1414
  	struct inode *inode = file_inode(file);
5091faa44   Mike Galbraith   sched: Add 'autog...
1415
1416
  	struct task_struct *p;
  	char buffer[PROC_NUMBUF];
0a8cb8e34   Alexey Dobriyan   fs/proc: convert ...
1417
  	int nice;
5091faa44   Mike Galbraith   sched: Add 'autog...
1418
1419
1420
1421
1422
1423
1424
  	int err;
  
  	memset(buffer, 0, sizeof(buffer));
  	if (count > sizeof(buffer) - 1)
  		count = sizeof(buffer) - 1;
  	if (copy_from_user(buffer, buf, count))
  		return -EFAULT;
0a8cb8e34   Alexey Dobriyan   fs/proc: convert ...
1425
1426
1427
  	err = kstrtoint(strstrip(buffer), 0, &nice);
  	if (err < 0)
  		return err;
5091faa44   Mike Galbraith   sched: Add 'autog...
1428
1429
1430
1431
  
  	p = get_proc_task(inode);
  	if (!p)
  		return -ESRCH;
2e5b5b3a1   Hiroshi Shimamoto   sched: Clean up p...
1432
  	err = proc_sched_autogroup_set_nice(p, nice);
5091faa44   Mike Galbraith   sched: Add 'autog...
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
  	if (err)
  		count = err;
  
  	put_task_struct(p);
  
  	return count;
  }
  
  static int sched_autogroup_open(struct inode *inode, struct file *filp)
  {
  	int ret;
  
  	ret = single_open(filp, sched_autogroup_show, NULL);
  	if (!ret) {
  		struct seq_file *m = filp->private_data;
  
  		m->private = inode;
  	}
  	return ret;
  }
  
  static const struct file_operations proc_pid_sched_autogroup_operations = {
  	.open		= sched_autogroup_open,
  	.read		= seq_read,
  	.write		= sched_autogroup_write,
  	.llseek		= seq_lseek,
  	.release	= single_release,
  };
  
  #endif /* CONFIG_SCHED_AUTOGROUP */
4614a696b   John Stultz   procfs: allow thr...
1463
1464
1465
  static ssize_t comm_write(struct file *file, const char __user *buf,
  				size_t count, loff_t *offset)
  {
496ad9aa8   Al Viro   new helper: file_...
1466
  	struct inode *inode = file_inode(file);
4614a696b   John Stultz   procfs: allow thr...
1467
1468
  	struct task_struct *p;
  	char buffer[TASK_COMM_LEN];
830e0fc96   David Rientjes   fs, proc: truncat...
1469
  	const size_t maxlen = sizeof(buffer) - 1;
4614a696b   John Stultz   procfs: allow thr...
1470
1471
  
  	memset(buffer, 0, sizeof(buffer));
830e0fc96   David Rientjes   fs, proc: truncat...
1472
  	if (copy_from_user(buffer, buf, count > maxlen ? maxlen : count))
4614a696b   John Stultz   procfs: allow thr...
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
  		return -EFAULT;
  
  	p = get_proc_task(inode);
  	if (!p)
  		return -ESRCH;
  
  	if (same_thread_group(current, p))
  		set_task_comm(p, buffer);
  	else
  		count = -EINVAL;
  
  	put_task_struct(p);
  
  	return count;
  }
  
  static int comm_show(struct seq_file *m, void *v)
  {
  	struct inode *inode = m->private;
  	struct task_struct *p;
  
  	p = get_proc_task(inode);
  	if (!p)
  		return -ESRCH;
  
  	task_lock(p);
  	seq_printf(m, "%s
  ", p->comm);
  	task_unlock(p);
  
  	put_task_struct(p);
  
  	return 0;
  }
  
  static int comm_open(struct inode *inode, struct file *filp)
  {
c6a340584   Jovi Zhang   proc: use single_...
1510
  	return single_open(filp, comm_show, inode);
4614a696b   John Stultz   procfs: allow thr...
1511
1512
1513
1514
1515
1516
1517
1518
1519
  }
  
  static const struct file_operations proc_pid_set_comm_operations = {
  	.open		= comm_open,
  	.read		= seq_read,
  	.write		= comm_write,
  	.llseek		= seq_lseek,
  	.release	= single_release,
  };
7773fbc54   Cyrill Gorcunov   procfs: make proc...
1520
  static int proc_exe_link(struct dentry *dentry, struct path *exe_path)
925d1c401   Matt Helsley   procfs task exe s...
1521
1522
  {
  	struct task_struct *task;
925d1c401   Matt Helsley   procfs task exe s...
1523
  	struct file *exe_file;
2b0143b5c   David Howells   VFS: normal files...
1524
  	task = get_proc_task(d_inode(dentry));
925d1c401   Matt Helsley   procfs task exe s...
1525
1526
  	if (!task)
  		return -ENOENT;
cd81a9170   Mateusz Guzik   mm: introduce get...
1527
  	exe_file = get_task_exe_file(task);
925d1c401   Matt Helsley   procfs task exe s...
1528
  	put_task_struct(task);
925d1c401   Matt Helsley   procfs task exe s...
1529
1530
1531
1532
1533
1534
1535
1536
  	if (exe_file) {
  		*exe_path = exe_file->f_path;
  		path_get(&exe_file->f_path);
  		fput(exe_file);
  		return 0;
  	} else
  		return -ENOENT;
  }
6b2553918   Al Viro   replace ->follow_...
1537
  static const char *proc_pid_get_link(struct dentry *dentry,
fceef393a   Al Viro   switch ->get_link...
1538
1539
  				     struct inode *inode,
  				     struct delayed_call *done)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1540
  {
408ef013c   Christoph Hellwig   fs: move path_put...
1541
  	struct path path;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1542
  	int error = -EACCES;
6b2553918   Al Viro   replace ->follow_...
1543
1544
  	if (!dentry)
  		return ERR_PTR(-ECHILD);
778c11447   Eric W. Biederman   [PATCH] proc: Use...
1545
1546
  	/* Are we allowed to snoop on the tasks file descriptors? */
  	if (!proc_fd_access_allowed(inode))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1547
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1548

408ef013c   Christoph Hellwig   fs: move path_put...
1549
1550
1551
  	error = PROC_I(inode)->op.proc_get_link(dentry, &path);
  	if (error)
  		goto out;
6e77137b3   Al Viro   don't pass nameid...
1552
  	nd_jump_link(&path);
408ef013c   Christoph Hellwig   fs: move path_put...
1553
  	return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1554
  out:
008b150a3   Al Viro   [PATCH] Fix up sy...
1555
  	return ERR_PTR(error);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1556
  }
3dcd25f37   Jan Blunck   d_path: Make proc...
1557
  static int do_proc_readlink(struct path *path, char __user *buffer, int buflen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1558
  {
e12ba74d8   Mel Gorman   Group short-lived...
1559
  	char *tmp = (char*)__get_free_page(GFP_TEMPORARY);
3dcd25f37   Jan Blunck   d_path: Make proc...
1560
  	char *pathname;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1561
1562
1563
1564
  	int len;
  
  	if (!tmp)
  		return -ENOMEM;
0c28f287a   Akinobu Mita   procfs: use simpl...
1565

7b2a69ba7   Eric W. Biederman   Revert "vfs: show...
1566
  	pathname = d_path(path, tmp, PAGE_SIZE);
3dcd25f37   Jan Blunck   d_path: Make proc...
1567
1568
  	len = PTR_ERR(pathname);
  	if (IS_ERR(pathname))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1569
  		goto out;
3dcd25f37   Jan Blunck   d_path: Make proc...
1570
  	len = tmp + PAGE_SIZE - 1 - pathname;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1571
1572
1573
  
  	if (len > buflen)
  		len = buflen;
3dcd25f37   Jan Blunck   d_path: Make proc...
1574
  	if (copy_to_user(buffer, pathname, len))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1575
1576
1577
1578
1579
1580
1581
1582
1583
  		len = -EFAULT;
   out:
  	free_page((unsigned long)tmp);
  	return len;
  }
  
  static int proc_pid_readlink(struct dentry * dentry, char __user * buffer, int buflen)
  {
  	int error = -EACCES;
2b0143b5c   David Howells   VFS: normal files...
1584
  	struct inode *inode = d_inode(dentry);
3dcd25f37   Jan Blunck   d_path: Make proc...
1585
  	struct path path;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1586

778c11447   Eric W. Biederman   [PATCH] proc: Use...
1587
1588
  	/* Are we allowed to snoop on the tasks file descriptors? */
  	if (!proc_fd_access_allowed(inode))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1589
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1590

7773fbc54   Cyrill Gorcunov   procfs: make proc...
1591
  	error = PROC_I(inode)->op.proc_get_link(dentry, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1592
1593
  	if (error)
  		goto out;
3dcd25f37   Jan Blunck   d_path: Make proc...
1594
1595
  	error = do_proc_readlink(&path, buffer, buflen);
  	path_put(&path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1596
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1597
1598
  	return error;
  }
faf60af17   Cyrill Gorcunov   procfs: Move /pro...
1599
  const struct inode_operations proc_pid_link_inode_operations = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1600
  	.readlink	= proc_pid_readlink,
6b2553918   Al Viro   replace ->follow_...
1601
  	.get_link	= proc_pid_get_link,
6d76fa58b   Linus Torvalds   Don't allow chmod...
1602
  	.setattr	= proc_setattr,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1603
  };
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1604
1605
  
  /* building an inode */
6b4e306aa   Eric W. Biederman   ns: proc files fo...
1606
  struct inode *proc_pid_make_inode(struct super_block * sb, struct task_struct *task)
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1607
1608
1609
  {
  	struct inode * inode;
  	struct proc_inode *ei;
c69e8d9c0   David Howells   CRED: Use RCU to ...
1610
  	const struct cred *cred;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1611

28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1612
  	/* We need a new inode */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1613

28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1614
1615
1616
1617
1618
1619
  	inode = new_inode(sb);
  	if (!inode)
  		goto out;
  
  	/* Common stuff */
  	ei = PROC_I(inode);
85fe4025c   Christoph Hellwig   fs: do not assign...
1620
  	inode->i_ino = get_next_ino();
078cd8279   Deepa Dinamani   fs: Replace CURRE...
1621
  	inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1622
1623
1624
1625
1626
  	inode->i_op = &proc_def_inode_operations;
  
  	/*
  	 * grab the reference to task.
  	 */
1a657f78d   Oleg Nesterov   [PATCH] introduce...
1627
  	ei->pid = get_task_pid(task, PIDTYPE_PID);
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1628
1629
  	if (!ei->pid)
  		goto out_unlock;
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1630
  	if (task_dumpable(task)) {
c69e8d9c0   David Howells   CRED: Use RCU to ...
1631
1632
1633
1634
1635
  		rcu_read_lock();
  		cred = __task_cred(task);
  		inode->i_uid = cred->euid;
  		inode->i_gid = cred->egid;
  		rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1636
  	}
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1637
  	security_task_to_inode(task, inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1638
  out:
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1639
1640
1641
1642
1643
  	return inode;
  
  out_unlock:
  	iput(inode);
  	return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1644
  }
6b4e306aa   Eric W. Biederman   ns: proc files fo...
1645
  int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1646
  {
2b0143b5c   David Howells   VFS: normal files...
1647
  	struct inode *inode = d_inode(dentry);
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1648
  	struct task_struct *task;
c69e8d9c0   David Howells   CRED: Use RCU to ...
1649
  	const struct cred *cred;
0499680a4   Vasiliy Kulikov   procfs: add hidep...
1650
  	struct pid_namespace *pid = dentry->d_sb->s_fs_info;
c69e8d9c0   David Howells   CRED: Use RCU to ...
1651

28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1652
  	generic_fillattr(inode, stat);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1653

28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1654
  	rcu_read_lock();
dcb0f2228   Eric W. Biederman   userns: Convert p...
1655
1656
  	stat->uid = GLOBAL_ROOT_UID;
  	stat->gid = GLOBAL_ROOT_GID;
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1657
1658
  	task = pid_task(proc_pid(inode), PIDTYPE_PID);
  	if (task) {
0499680a4   Vasiliy Kulikov   procfs: add hidep...
1659
1660
1661
1662
1663
1664
1665
1666
  		if (!has_pid_permissions(pid, task, 2)) {
  			rcu_read_unlock();
  			/*
  			 * This doesn't prevent learning whether PID exists,
  			 * it only makes getattr() consistent with readdir().
  			 */
  			return -ENOENT;
  		}
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1667
1668
  		if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) ||
  		    task_dumpable(task)) {
c69e8d9c0   David Howells   CRED: Use RCU to ...
1669
1670
1671
  			cred = __task_cred(task);
  			stat->uid = cred->euid;
  			stat->gid = cred->egid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1672
1673
  		}
  	}
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1674
  	rcu_read_unlock();
d6e711448   Alan Cox   [PATCH] setuid co...
1675
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1676
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1677
1678
1679
1680
1681
1682
1683
1684
1685
  /* dentry stuff */
  
  /*
   *	Exceptional case: normally we are not allowed to unhash a busy
   * directory. In this case, however, we can do it - no aliasing problems
   * due to the way we treat inodes.
   *
   * Rewrite the inode's ownerships here because the owning task may have
   * performed a setuid(), etc.
99f895518   Eric W. Biederman   [PATCH] proc: don...
1686
1687
1688
1689
1690
1691
1692
   *
   * Before the /proc/pid/status file was created the only way to read
   * the effective uid of a /process was to stat /proc/pid.  Reading
   * /proc/pid/status is slow enough that procps and other packages
   * kept stating /proc/pid.  To keep the rules in /proc simple I have
   * made this apply to all per process world readable and executable
   * directories.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1693
   */
0b728e191   Al Viro   stop passing name...
1694
  int pid_revalidate(struct dentry *dentry, unsigned int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1695
  {
34286d666   Nick Piggin   fs: rcu-walk awar...
1696
1697
  	struct inode *inode;
  	struct task_struct *task;
c69e8d9c0   David Howells   CRED: Use RCU to ...
1698
  	const struct cred *cred;
0b728e191   Al Viro   stop passing name...
1699
  	if (flags & LOOKUP_RCU)
34286d666   Nick Piggin   fs: rcu-walk awar...
1700
  		return -ECHILD;
2b0143b5c   David Howells   VFS: normal files...
1701
  	inode = d_inode(dentry);
34286d666   Nick Piggin   fs: rcu-walk awar...
1702
  	task = get_proc_task(inode);
99f895518   Eric W. Biederman   [PATCH] proc: don...
1703
1704
1705
  	if (task) {
  		if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) ||
  		    task_dumpable(task)) {
c69e8d9c0   David Howells   CRED: Use RCU to ...
1706
1707
1708
1709
1710
  			rcu_read_lock();
  			cred = __task_cred(task);
  			inode->i_uid = cred->euid;
  			inode->i_gid = cred->egid;
  			rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1711
  		} else {
dcb0f2228   Eric W. Biederman   userns: Convert p...
1712
1713
  			inode->i_uid = GLOBAL_ROOT_UID;
  			inode->i_gid = GLOBAL_ROOT_GID;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1714
  		}
9ee8ab9fb   Linus Torvalds   Relax /proc fix a...
1715
  		inode->i_mode &= ~(S_ISUID | S_ISGID);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1716
  		security_task_to_inode(task, inode);
99f895518   Eric W. Biederman   [PATCH] proc: don...
1717
  		put_task_struct(task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1718
1719
  		return 1;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1720
1721
  	return 0;
  }
d855a4b79   Oleg Nesterov   proc: don't (ab)u...
1722
1723
1724
1725
  static inline bool proc_inode_is_dead(struct inode *inode)
  {
  	return !proc_pid(inode)->tasks[PIDTYPE_PID].first;
  }
1dd704b61   David Howells   proc: Uninline pi...
1726
1727
1728
1729
1730
1731
  int pid_delete_dentry(const struct dentry *dentry)
  {
  	/* Is the task we represent dead?
  	 * If so, then don't put the dentry on the lru list,
  	 * kill it immediately.
  	 */
2b0143b5c   David Howells   VFS: normal files...
1732
  	return proc_inode_is_dead(d_inode(dentry));
1dd704b61   David Howells   proc: Uninline pi...
1733
  }
6b4e306aa   Eric W. Biederman   ns: proc files fo...
1734
  const struct dentry_operations pid_dentry_operations =
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
1735
1736
1737
1738
1739
1740
  {
  	.d_revalidate	= pid_revalidate,
  	.d_delete	= pid_delete_dentry,
  };
  
  /* Lookups */
1c0d04c9e   Eric W. Biederman   [PATCH] proc: com...
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
  /*
   * Fill a directory entry.
   *
   * If possible create the dcache entry and derive our inode number and
   * file type from dcache entry.
   *
   * Since all of the proc inode numbers are dynamically generated, the inode
   * numbers do not exist until the inode is cache.  This means creating the
   * the dcache entry in readdir is necessary to keep the inode numbers
   * reported by readdir in sync with the inode numbers reported
   * by stat.
   */
f0c3b5093   Al Viro   [readdir] convert...
1753
  bool proc_fill_cache(struct file *file, struct dir_context *ctx,
6b4e306aa   Eric W. Biederman   ns: proc files fo...
1754
  	const char *name, int len,
c5141e6d6   Eric Dumazet   procfs: reorder s...
1755
  	instantiate_t instantiate, struct task_struct *task, const void *ptr)
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
1756
  {
f0c3b5093   Al Viro   [readdir] convert...
1757
  	struct dentry *child, *dir = file->f_path.dentry;
1df98b8bb   Al Viro   proc_fill_cache()...
1758
  	struct qstr qname = QSTR_INIT(name, len);
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
1759
  	struct inode *inode;
1df98b8bb   Al Viro   proc_fill_cache()...
1760
1761
  	unsigned type;
  	ino_t ino;
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
1762

1df98b8bb   Al Viro   proc_fill_cache()...
1763
  	child = d_hash_and_lookup(dir, &qname);
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
1764
  	if (!child) {
3781764b5   Al Viro   proc_fill_cache()...
1765
1766
1767
  		DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
  		child = d_alloc_parallel(dir, &qname, &wq);
  		if (IS_ERR(child))
1df98b8bb   Al Viro   proc_fill_cache()...
1768
  			goto end_instantiate;
3781764b5   Al Viro   proc_fill_cache()...
1769
1770
1771
1772
1773
1774
1775
  		if (d_in_lookup(child)) {
  			int err = instantiate(d_inode(dir), child, task, ptr);
  			d_lookup_done(child);
  			if (err < 0) {
  				dput(child);
  				goto end_instantiate;
  			}
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
1776
1777
  		}
  	}
2b0143b5c   David Howells   VFS: normal files...
1778
  	inode = d_inode(child);
147ce6997   Al Viro   proc_fill_cache()...
1779
1780
  	ino = inode->i_ino;
  	type = inode->i_mode >> 12;
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
1781
  	dput(child);
f0c3b5093   Al Viro   [readdir] convert...
1782
  	return dir_emit(ctx, name, len, ino, type);
1df98b8bb   Al Viro   proc_fill_cache()...
1783
1784
1785
  
  end_instantiate:
  	return dir_emit(ctx, name, len, 1, DT_UNKNOWN);
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
1786
  }
640708a2c   Pavel Emelyanov   procfs: introduce...
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
  /*
   * dname_to_vma_addr - maps a dentry name into two unsigned longs
   * which represent vma start and end addresses.
   */
  static int dname_to_vma_addr(struct dentry *dentry,
  			     unsigned long *start, unsigned long *end)
  {
  	if (sscanf(dentry->d_name.name, "%lx-%lx", start, end) != 2)
  		return -EINVAL;
  
  	return 0;
  }
0b728e191   Al Viro   stop passing name...
1799
  static int map_files_d_revalidate(struct dentry *dentry, unsigned int flags)
640708a2c   Pavel Emelyanov   procfs: introduce...
1800
1801
1802
1803
1804
1805
1806
1807
  {
  	unsigned long vm_start, vm_end;
  	bool exact_vma_exists = false;
  	struct mm_struct *mm = NULL;
  	struct task_struct *task;
  	const struct cred *cred;
  	struct inode *inode;
  	int status = 0;
0b728e191   Al Viro   stop passing name...
1808
  	if (flags & LOOKUP_RCU)
640708a2c   Pavel Emelyanov   procfs: introduce...
1809
  		return -ECHILD;
2b0143b5c   David Howells   VFS: normal files...
1810
  	inode = d_inode(dentry);
640708a2c   Pavel Emelyanov   procfs: introduce...
1811
1812
1813
  	task = get_proc_task(inode);
  	if (!task)
  		goto out_notask;
caaee6234   Jann Horn   ptrace: use fsuid...
1814
  	mm = mm_access(task, PTRACE_MODE_READ_FSCREDS);
2344bec78   Cong Wang   proc: use mm_acce...
1815
  	if (IS_ERR_OR_NULL(mm))
640708a2c   Pavel Emelyanov   procfs: introduce...
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
  		goto out;
  
  	if (!dname_to_vma_addr(dentry, &vm_start, &vm_end)) {
  		down_read(&mm->mmap_sem);
  		exact_vma_exists = !!find_exact_vma(mm, vm_start, vm_end);
  		up_read(&mm->mmap_sem);
  	}
  
  	mmput(mm);
  
  	if (exact_vma_exists) {
  		if (task_dumpable(task)) {
  			rcu_read_lock();
  			cred = __task_cred(task);
  			inode->i_uid = cred->euid;
  			inode->i_gid = cred->egid;
  			rcu_read_unlock();
  		} else {
dcb0f2228   Eric W. Biederman   userns: Convert p...
1834
1835
  			inode->i_uid = GLOBAL_ROOT_UID;
  			inode->i_gid = GLOBAL_ROOT_GID;
640708a2c   Pavel Emelyanov   procfs: introduce...
1836
1837
1838
1839
1840
1841
1842
1843
1844
  		}
  		security_task_to_inode(task, inode);
  		status = 1;
  	}
  
  out:
  	put_task_struct(task);
  
  out_notask:
640708a2c   Pavel Emelyanov   procfs: introduce...
1845
1846
1847
1848
1849
1850
1851
  	return status;
  }
  
  static const struct dentry_operations tid_map_files_dentry_operations = {
  	.d_revalidate	= map_files_d_revalidate,
  	.d_delete	= pid_delete_dentry,
  };
6b2553918   Al Viro   replace ->follow_...
1852
  static int map_files_get_link(struct dentry *dentry, struct path *path)
640708a2c   Pavel Emelyanov   procfs: introduce...
1853
1854
1855
1856
1857
1858
1859
1860
  {
  	unsigned long vm_start, vm_end;
  	struct vm_area_struct *vma;
  	struct task_struct *task;
  	struct mm_struct *mm;
  	int rc;
  
  	rc = -ENOENT;
2b0143b5c   David Howells   VFS: normal files...
1861
  	task = get_proc_task(d_inode(dentry));
640708a2c   Pavel Emelyanov   procfs: introduce...
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
  	if (!task)
  		goto out;
  
  	mm = get_task_mm(task);
  	put_task_struct(task);
  	if (!mm)
  		goto out;
  
  	rc = dname_to_vma_addr(dentry, &vm_start, &vm_end);
  	if (rc)
  		goto out_mmput;
70335abb2   Artem Fetishev   fs/proc/base.c: f...
1873
  	rc = -ENOENT;
640708a2c   Pavel Emelyanov   procfs: introduce...
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
  	down_read(&mm->mmap_sem);
  	vma = find_exact_vma(mm, vm_start, vm_end);
  	if (vma && vma->vm_file) {
  		*path = vma->vm_file->f_path;
  		path_get(path);
  		rc = 0;
  	}
  	up_read(&mm->mmap_sem);
  
  out_mmput:
  	mmput(mm);
  out:
  	return rc;
  }
  
  struct map_files_info {
7b540d064   Al Viro   proc_map_files_re...
1890
  	fmode_t		mode;
640708a2c   Pavel Emelyanov   procfs: introduce...
1891
1892
1893
  	unsigned long	len;
  	unsigned char	name[4*sizeof(long)+2]; /* max: %lx-%lx\0 */
  };
bdb4d100a   Calvin Owens   procfs: always ex...
1894
1895
1896
1897
1898
1899
  /*
   * Only allow CAP_SYS_ADMIN to follow the links, due to concerns about how the
   * symlinks may be used to bypass permissions on ancestor directories in the
   * path to the file in question.
   */
  static const char *
6b2553918   Al Viro   replace ->follow_...
1900
  proc_map_files_get_link(struct dentry *dentry,
fceef393a   Al Viro   switch ->get_link...
1901
1902
  			struct inode *inode,
  		        struct delayed_call *done)
bdb4d100a   Calvin Owens   procfs: always ex...
1903
1904
1905
  {
  	if (!capable(CAP_SYS_ADMIN))
  		return ERR_PTR(-EPERM);
fceef393a   Al Viro   switch ->get_link...
1906
  	return proc_pid_get_link(dentry, inode, done);
bdb4d100a   Calvin Owens   procfs: always ex...
1907
1908
1909
  }
  
  /*
6b2553918   Al Viro   replace ->follow_...
1910
   * Identical to proc_pid_link_inode_operations except for get_link()
bdb4d100a   Calvin Owens   procfs: always ex...
1911
1912
1913
   */
  static const struct inode_operations proc_map_files_link_inode_operations = {
  	.readlink	= proc_pid_readlink,
6b2553918   Al Viro   replace ->follow_...
1914
  	.get_link	= proc_map_files_get_link,
bdb4d100a   Calvin Owens   procfs: always ex...
1915
1916
  	.setattr	= proc_setattr,
  };
c52a47ace   Al Viro   proc_fill_cache()...
1917
  static int
640708a2c   Pavel Emelyanov   procfs: introduce...
1918
1919
1920
  proc_map_files_instantiate(struct inode *dir, struct dentry *dentry,
  			   struct task_struct *task, const void *ptr)
  {
7b540d064   Al Viro   proc_map_files_re...
1921
  	fmode_t mode = (fmode_t)(unsigned long)ptr;
640708a2c   Pavel Emelyanov   procfs: introduce...
1922
1923
  	struct proc_inode *ei;
  	struct inode *inode;
640708a2c   Pavel Emelyanov   procfs: introduce...
1924
1925
  	inode = proc_pid_make_inode(dir->i_sb, task);
  	if (!inode)
c52a47ace   Al Viro   proc_fill_cache()...
1926
  		return -ENOENT;
640708a2c   Pavel Emelyanov   procfs: introduce...
1927
1928
  
  	ei = PROC_I(inode);
6b2553918   Al Viro   replace ->follow_...
1929
  	ei->op.proc_get_link = map_files_get_link;
640708a2c   Pavel Emelyanov   procfs: introduce...
1930

bdb4d100a   Calvin Owens   procfs: always ex...
1931
  	inode->i_op = &proc_map_files_link_inode_operations;
640708a2c   Pavel Emelyanov   procfs: introduce...
1932
1933
  	inode->i_size = 64;
  	inode->i_mode = S_IFLNK;
7b540d064   Al Viro   proc_map_files_re...
1934
  	if (mode & FMODE_READ)
640708a2c   Pavel Emelyanov   procfs: introduce...
1935
  		inode->i_mode |= S_IRUSR;
7b540d064   Al Viro   proc_map_files_re...
1936
  	if (mode & FMODE_WRITE)
640708a2c   Pavel Emelyanov   procfs: introduce...
1937
1938
1939
1940
  		inode->i_mode |= S_IWUSR;
  
  	d_set_d_op(dentry, &tid_map_files_dentry_operations);
  	d_add(dentry, inode);
c52a47ace   Al Viro   proc_fill_cache()...
1941
  	return 0;
640708a2c   Pavel Emelyanov   procfs: introduce...
1942
1943
1944
  }
  
  static struct dentry *proc_map_files_lookup(struct inode *dir,
00cd8dd3b   Al Viro   stop passing name...
1945
  		struct dentry *dentry, unsigned int flags)
640708a2c   Pavel Emelyanov   procfs: introduce...
1946
1947
1948
1949
  {
  	unsigned long vm_start, vm_end;
  	struct vm_area_struct *vma;
  	struct task_struct *task;
c52a47ace   Al Viro   proc_fill_cache()...
1950
  	int result;
640708a2c   Pavel Emelyanov   procfs: introduce...
1951
  	struct mm_struct *mm;
c52a47ace   Al Viro   proc_fill_cache()...
1952
  	result = -ENOENT;
640708a2c   Pavel Emelyanov   procfs: introduce...
1953
1954
1955
  	task = get_proc_task(dir);
  	if (!task)
  		goto out;
c52a47ace   Al Viro   proc_fill_cache()...
1956
  	result = -EACCES;
caaee6234   Jann Horn   ptrace: use fsuid...
1957
  	if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS))
640708a2c   Pavel Emelyanov   procfs: introduce...
1958
  		goto out_put_task;
c52a47ace   Al Viro   proc_fill_cache()...
1959
  	result = -ENOENT;
640708a2c   Pavel Emelyanov   procfs: introduce...
1960
  	if (dname_to_vma_addr(dentry, &vm_start, &vm_end))
eb94cd96e   Cyrill Gorcunov   fs, proc: fix ABB...
1961
  		goto out_put_task;
640708a2c   Pavel Emelyanov   procfs: introduce...
1962
1963
1964
  
  	mm = get_task_mm(task);
  	if (!mm)
eb94cd96e   Cyrill Gorcunov   fs, proc: fix ABB...
1965
  		goto out_put_task;
640708a2c   Pavel Emelyanov   procfs: introduce...
1966
1967
1968
1969
1970
  
  	down_read(&mm->mmap_sem);
  	vma = find_exact_vma(mm, vm_start, vm_end);
  	if (!vma)
  		goto out_no_vma;
05f564849   Stanislav Kinsbursky   proc: check vma->...
1971
1972
1973
  	if (vma->vm_file)
  		result = proc_map_files_instantiate(dir, dentry, task,
  				(void *)(unsigned long)vma->vm_file->f_mode);
640708a2c   Pavel Emelyanov   procfs: introduce...
1974
1975
1976
1977
  
  out_no_vma:
  	up_read(&mm->mmap_sem);
  	mmput(mm);
640708a2c   Pavel Emelyanov   procfs: introduce...
1978
1979
1980
  out_put_task:
  	put_task_struct(task);
  out:
c52a47ace   Al Viro   proc_fill_cache()...
1981
  	return ERR_PTR(result);
640708a2c   Pavel Emelyanov   procfs: introduce...
1982
1983
1984
1985
1986
1987
1988
1989
1990
  }
  
  static const struct inode_operations proc_map_files_inode_operations = {
  	.lookup		= proc_map_files_lookup,
  	.permission	= proc_fd_permission,
  	.setattr	= proc_setattr,
  };
  
  static int
f0c3b5093   Al Viro   [readdir] convert...
1991
  proc_map_files_readdir(struct file *file, struct dir_context *ctx)
640708a2c   Pavel Emelyanov   procfs: introduce...
1992
  {
640708a2c   Pavel Emelyanov   procfs: introduce...
1993
1994
1995
  	struct vm_area_struct *vma;
  	struct task_struct *task;
  	struct mm_struct *mm;
f0c3b5093   Al Viro   [readdir] convert...
1996
1997
1998
1999
  	unsigned long nr_files, pos, i;
  	struct flex_array *fa = NULL;
  	struct map_files_info info;
  	struct map_files_info *p;
640708a2c   Pavel Emelyanov   procfs: introduce...
2000
  	int ret;
640708a2c   Pavel Emelyanov   procfs: introduce...
2001
  	ret = -ENOENT;
f0c3b5093   Al Viro   [readdir] convert...
2002
  	task = get_proc_task(file_inode(file));
640708a2c   Pavel Emelyanov   procfs: introduce...
2003
2004
2005
2006
  	if (!task)
  		goto out;
  
  	ret = -EACCES;
caaee6234   Jann Horn   ptrace: use fsuid...
2007
  	if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS))
640708a2c   Pavel Emelyanov   procfs: introduce...
2008
2009
2010
  		goto out_put_task;
  
  	ret = 0;
f0c3b5093   Al Viro   [readdir] convert...
2011
2012
  	if (!dir_emit_dots(file, ctx))
  		goto out_put_task;
640708a2c   Pavel Emelyanov   procfs: introduce...
2013

f0c3b5093   Al Viro   [readdir] convert...
2014
2015
2016
2017
  	mm = get_task_mm(task);
  	if (!mm)
  		goto out_put_task;
  	down_read(&mm->mmap_sem);
640708a2c   Pavel Emelyanov   procfs: introduce...
2018

f0c3b5093   Al Viro   [readdir] convert...
2019
  	nr_files = 0;
640708a2c   Pavel Emelyanov   procfs: introduce...
2020

f0c3b5093   Al Viro   [readdir] convert...
2021
2022
2023
2024
2025
2026
2027
2028
2029
  	/*
  	 * We need two passes here:
  	 *
  	 *  1) Collect vmas of mapped files with mmap_sem taken
  	 *  2) Release mmap_sem and instantiate entries
  	 *
  	 * otherwise we get lockdep complained, since filldir()
  	 * routine might require mmap_sem taken in might_fault().
  	 */
640708a2c   Pavel Emelyanov   procfs: introduce...
2030

f0c3b5093   Al Viro   [readdir] convert...
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
  	for (vma = mm->mmap, pos = 2; vma; vma = vma->vm_next) {
  		if (vma->vm_file && ++pos > ctx->pos)
  			nr_files++;
  	}
  
  	if (nr_files) {
  		fa = flex_array_alloc(sizeof(info), nr_files,
  					GFP_KERNEL);
  		if (!fa || flex_array_prealloc(fa, 0, nr_files,
  						GFP_KERNEL)) {
  			ret = -ENOMEM;
  			if (fa)
  				flex_array_free(fa);
  			up_read(&mm->mmap_sem);
  			mmput(mm);
  			goto out_put_task;
640708a2c   Pavel Emelyanov   procfs: introduce...
2047
  		}
f0c3b5093   Al Viro   [readdir] convert...
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
  		for (i = 0, vma = mm->mmap, pos = 2; vma;
  				vma = vma->vm_next) {
  			if (!vma->vm_file)
  				continue;
  			if (++pos <= ctx->pos)
  				continue;
  
  			info.mode = vma->vm_file->f_mode;
  			info.len = snprintf(info.name,
  					sizeof(info.name), "%lx-%lx",
  					vma->vm_start, vma->vm_end);
  			if (flex_array_put(fa, i++, &info, GFP_KERNEL))
  				BUG();
640708a2c   Pavel Emelyanov   procfs: introduce...
2061
  		}
640708a2c   Pavel Emelyanov   procfs: introduce...
2062
  	}
f0c3b5093   Al Viro   [readdir] convert...
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
  	up_read(&mm->mmap_sem);
  
  	for (i = 0; i < nr_files; i++) {
  		p = flex_array_get(fa, i);
  		if (!proc_fill_cache(file, ctx,
  				      p->name, p->len,
  				      proc_map_files_instantiate,
  				      task,
  				      (void *)(unsigned long)p->mode))
  			break;
  		ctx->pos++;
640708a2c   Pavel Emelyanov   procfs: introduce...
2074
  	}
f0c3b5093   Al Viro   [readdir] convert...
2075
2076
2077
  	if (fa)
  		flex_array_free(fa);
  	mmput(mm);
640708a2c   Pavel Emelyanov   procfs: introduce...
2078

640708a2c   Pavel Emelyanov   procfs: introduce...
2079
2080
2081
2082
2083
2084
2085
2086
  out_put_task:
  	put_task_struct(task);
  out:
  	return ret;
  }
  
  static const struct file_operations proc_map_files_operations = {
  	.read		= generic_read_dir,
f50752eaa   Al Viro   switch all procfs...
2087
2088
  	.iterate_shared	= proc_map_files_readdir,
  	.llseek		= generic_file_llseek,
640708a2c   Pavel Emelyanov   procfs: introduce...
2089
  };
b5946beaa   Eric Engestrom   procfs: add condi...
2090
  #ifdef CONFIG_CHECKPOINT_RESTORE
48f6a7a51   Pavel Emelyanov   posix-timers: Int...
2091
2092
2093
2094
  struct timers_private {
  	struct pid *pid;
  	struct task_struct *task;
  	struct sighand_struct *sighand;
57b8015e0   Pavel Emelyanov   posix-timers: Sho...
2095
  	struct pid_namespace *ns;
48f6a7a51   Pavel Emelyanov   posix-timers: Int...
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
  	unsigned long flags;
  };
  
  static void *timers_start(struct seq_file *m, loff_t *pos)
  {
  	struct timers_private *tp = m->private;
  
  	tp->task = get_pid_task(tp->pid, PIDTYPE_PID);
  	if (!tp->task)
  		return ERR_PTR(-ESRCH);
  
  	tp->sighand = lock_task_sighand(tp->task, &tp->flags);
  	if (!tp->sighand)
  		return ERR_PTR(-ESRCH);
  
  	return seq_list_start(&tp->task->signal->posix_timers, *pos);
  }
  
  static void *timers_next(struct seq_file *m, void *v, loff_t *pos)
  {
  	struct timers_private *tp = m->private;
  	return seq_list_next(v, &tp->task->signal->posix_timers, pos);
  }
  
  static void timers_stop(struct seq_file *m, void *v)
  {
  	struct timers_private *tp = m->private;
  
  	if (tp->sighand) {
  		unlock_task_sighand(tp->task, &tp->flags);
  		tp->sighand = NULL;
  	}
  
  	if (tp->task) {
  		put_task_struct(tp->task);
  		tp->task = NULL;
  	}
  }
  
  static int show_timer(struct seq_file *m, void *v)
  {
  	struct k_itimer *timer;
57b8015e0   Pavel Emelyanov   posix-timers: Sho...
2138
2139
  	struct timers_private *tp = m->private;
  	int notify;
cedbccab8   Alexey Dobriyan   proc: more "const...
2140
  	static const char * const nstr[] = {
57b8015e0   Pavel Emelyanov   posix-timers: Sho...
2141
2142
2143
2144
  		[SIGEV_SIGNAL] = "signal",
  		[SIGEV_NONE] = "none",
  		[SIGEV_THREAD] = "thread",
  	};
48f6a7a51   Pavel Emelyanov   posix-timers: Int...
2145
2146
  
  	timer = list_entry((struct list_head *)v, struct k_itimer, list);
57b8015e0   Pavel Emelyanov   posix-timers: Sho...
2147
  	notify = timer->it_sigev_notify;
48f6a7a51   Pavel Emelyanov   posix-timers: Int...
2148
2149
  	seq_printf(m, "ID: %d
  ", timer->it_id);
25ce31916   Joe Perches   proc: remove use ...
2150
2151
2152
2153
  	seq_printf(m, "signal: %d/%p
  ",
  		   timer->sigq->info.si_signo,
  		   timer->sigq->info.si_value.sival_ptr);
57b8015e0   Pavel Emelyanov   posix-timers: Sho...
2154
2155
  	seq_printf(m, "notify: %s/%s.%d
  ",
25ce31916   Joe Perches   proc: remove use ...
2156
2157
2158
  		   nstr[notify & ~SIGEV_THREAD_ID],
  		   (notify & SIGEV_THREAD_ID) ? "tid" : "pid",
  		   pid_nr_ns(timer->it_pid, tp->ns));
15ef0298d   Pavel Tikhomirov   posix-timers: Sho...
2159
2160
  	seq_printf(m, "ClockID: %d
  ", timer->it_clock);
48f6a7a51   Pavel Emelyanov   posix-timers: Int...
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
  
  	return 0;
  }
  
  static const struct seq_operations proc_timers_seq_ops = {
  	.start	= timers_start,
  	.next	= timers_next,
  	.stop	= timers_stop,
  	.show	= show_timer,
  };
  
  static int proc_timers_open(struct inode *inode, struct file *file)
  {
  	struct timers_private *tp;
  
  	tp = __seq_open_private(file, &proc_timers_seq_ops,
  			sizeof(struct timers_private));
  	if (!tp)
  		return -ENOMEM;
  
  	tp->pid = proc_pid(inode);
57b8015e0   Pavel Emelyanov   posix-timers: Sho...
2182
  	tp->ns = inode->i_sb->s_fs_info;
48f6a7a51   Pavel Emelyanov   posix-timers: Int...
2183
2184
2185
2186
2187
2188
2189
2190
2191
  	return 0;
  }
  
  static const struct file_operations proc_timers_operations = {
  	.open		= proc_timers_open,
  	.read		= seq_read,
  	.llseek		= seq_lseek,
  	.release	= seq_release_private,
  };
b5946beaa   Eric Engestrom   procfs: add condi...
2192
  #endif
640708a2c   Pavel Emelyanov   procfs: introduce...
2193

5de23d435   John Stultz   proc: add /proc/<...
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
  static ssize_t timerslack_ns_write(struct file *file, const char __user *buf,
  					size_t count, loff_t *offset)
  {
  	struct inode *inode = file_inode(file);
  	struct task_struct *p;
  	u64 slack_ns;
  	int err;
  
  	err = kstrtoull_from_user(buf, count, 10, &slack_ns);
  	if (err < 0)
  		return err;
  
  	p = get_proc_task(inode);
  	if (!p)
  		return -ESRCH;
4b2bd5fec   John Stultz   proc: fix timersl...
2209
2210
2211
2212
2213
  	if (p != current) {
  		if (!capable(CAP_SYS_NICE)) {
  			count = -EPERM;
  			goto out;
  		}
5de23d435   John Stultz   proc: add /proc/<...
2214

4b2bd5fec   John Stultz   proc: fix timersl...
2215
2216
2217
2218
2219
  		err = security_task_setscheduler(p);
  		if (err) {
  			count = err;
  			goto out;
  		}
904763e1f   John Stultz   proc: add LSM hoo...
2220
  	}
7abbaf940   John Stultz   proc: relax /proc...
2221
2222
2223
2224
2225
2226
2227
2228
  	task_lock(p);
  	if (slack_ns == 0)
  		p->timer_slack_ns = p->default_timer_slack_ns;
  	else
  		p->timer_slack_ns = slack_ns;
  	task_unlock(p);
  
  out:
5de23d435   John Stultz   proc: add /proc/<...
2229
2230
2231
2232
2233
2234
2235
2236
2237
  	put_task_struct(p);
  
  	return count;
  }
  
  static int timerslack_ns_show(struct seq_file *m, void *v)
  {
  	struct inode *inode = m->private;
  	struct task_struct *p;
7abbaf940   John Stultz   proc: relax /proc...
2238
  	int err = 0;
5de23d435   John Stultz   proc: add /proc/<...
2239
2240
2241
2242
  
  	p = get_proc_task(inode);
  	if (!p)
  		return -ESRCH;
4b2bd5fec   John Stultz   proc: fix timersl...
2243
  	if (p != current) {
5de23d435   John Stultz   proc: add /proc/<...
2244

4b2bd5fec   John Stultz   proc: fix timersl...
2245
2246
2247
2248
2249
2250
2251
2252
  		if (!capable(CAP_SYS_NICE)) {
  			err = -EPERM;
  			goto out;
  		}
  		err = security_task_getscheduler(p);
  		if (err)
  			goto out;
  	}
904763e1f   John Stultz   proc: add LSM hoo...
2253

7abbaf940   John Stultz   proc: relax /proc...
2254
2255
2256
2257
2258
2259
  	task_lock(p);
  	seq_printf(m, "%llu
  ", p->timer_slack_ns);
  	task_unlock(p);
  
  out:
5de23d435   John Stultz   proc: add /proc/<...
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
  	put_task_struct(p);
  
  	return err;
  }
  
  static int timerslack_ns_open(struct inode *inode, struct file *filp)
  {
  	return single_open(filp, timerslack_ns_show, inode);
  }
  
  static const struct file_operations proc_pid_set_timerslack_ns_operations = {
  	.open		= timerslack_ns_open,
  	.read		= seq_read,
  	.write		= timerslack_ns_write,
  	.llseek		= seq_lseek,
  	.release	= single_release,
  };
c52a47ace   Al Viro   proc_fill_cache()...
2277
  static int proc_pident_instantiate(struct inode *dir,
c5141e6d6   Eric Dumazet   procfs: reorder s...
2278
  	struct dentry *dentry, struct task_struct *task, const void *ptr)
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
2279
  {
c5141e6d6   Eric Dumazet   procfs: reorder s...
2280
  	const struct pid_entry *p = ptr;
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
2281
2282
  	struct inode *inode;
  	struct proc_inode *ei;
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
2283

61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2284
  	inode = proc_pid_make_inode(dir->i_sb, task);
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
2285
2286
2287
2288
2289
2290
  	if (!inode)
  		goto out;
  
  	ei = PROC_I(inode);
  	inode->i_mode = p->mode;
  	if (S_ISDIR(inode->i_mode))
bfe868486   Miklos Szeredi   filesystems: add ...
2291
  		set_nlink(inode, 2);	/* Use getattr to fix if necessary */
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
2292
2293
2294
2295
2296
  	if (p->iop)
  		inode->i_op = p->iop;
  	if (p->fop)
  		inode->i_fop = p->fop;
  	ei->op = p->op;
fb045adb9   Nick Piggin   fs: dcache reduce...
2297
  	d_set_d_op(dentry, &pid_dentry_operations);
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
2298
2299
  	d_add(dentry, inode);
  	/* Close the race of the process dying before we return the dentry */
0b728e191   Al Viro   stop passing name...
2300
  	if (pid_revalidate(dentry, 0))
c52a47ace   Al Viro   proc_fill_cache()...
2301
  		return 0;
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
2302
  out:
c52a47ace   Al Viro   proc_fill_cache()...
2303
  	return -ENOENT;
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
2304
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2305
2306
  static struct dentry *proc_pident_lookup(struct inode *dir, 
  					 struct dentry *dentry,
c5141e6d6   Eric Dumazet   procfs: reorder s...
2307
  					 const struct pid_entry *ents,
7bcd6b0ef   Eric W. Biederman   [PATCH] proc: rem...
2308
  					 unsigned int nents)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2309
  {
c52a47ace   Al Viro   proc_fill_cache()...
2310
  	int error;
99f895518   Eric W. Biederman   [PATCH] proc: don...
2311
  	struct task_struct *task = get_proc_task(dir);
c5141e6d6   Eric Dumazet   procfs: reorder s...
2312
  	const struct pid_entry *p, *last;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2313

c52a47ace   Al Viro   proc_fill_cache()...
2314
  	error = -ENOENT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2315

99f895518   Eric W. Biederman   [PATCH] proc: don...
2316
2317
  	if (!task)
  		goto out_no_task;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2318

20cdc894c   Eric W. Biederman   [PATCH] proc: mod...
2319
2320
2321
2322
  	/*
  	 * Yes, it does not scale. And it should not. Don't add
  	 * new entries into /proc/<tgid>/ without very good reasons.
  	 */
7bcd6b0ef   Eric W. Biederman   [PATCH] proc: rem...
2323
2324
  	last = &ents[nents - 1];
  	for (p = ents; p <= last; p++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2325
2326
2327
2328
2329
  		if (p->len != dentry->d_name.len)
  			continue;
  		if (!memcmp(dentry->d_name.name, p->name, p->len))
  			break;
  	}
7bcd6b0ef   Eric W. Biederman   [PATCH] proc: rem...
2330
  	if (p > last)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2331
  		goto out;
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
2332
  	error = proc_pident_instantiate(dir, dentry, task, p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2333
  out:
99f895518   Eric W. Biederman   [PATCH] proc: don...
2334
2335
  	put_task_struct(task);
  out_no_task:
c52a47ace   Al Viro   proc_fill_cache()...
2336
  	return ERR_PTR(error);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2337
  }
f0c3b5093   Al Viro   [readdir] convert...
2338
  static int proc_pident_readdir(struct file *file, struct dir_context *ctx,
c5141e6d6   Eric Dumazet   procfs: reorder s...
2339
  		const struct pid_entry *ents, unsigned int nents)
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2340
  {
f0c3b5093   Al Viro   [readdir] convert...
2341
2342
  	struct task_struct *task = get_proc_task(file_inode(file));
  	const struct pid_entry *p;
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2343

28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2344
  	if (!task)
f0c3b5093   Al Viro   [readdir] convert...
2345
  		return -ENOENT;
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2346

f0c3b5093   Al Viro   [readdir] convert...
2347
2348
2349
2350
2351
  	if (!dir_emit_dots(file, ctx))
  		goto out;
  
  	if (ctx->pos >= nents + 2)
  		goto out;
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2352

f0c3b5093   Al Viro   [readdir] convert...
2353
2354
2355
2356
2357
2358
  	for (p = ents + (ctx->pos - 2); p <= ents + nents - 1; p++) {
  		if (!proc_fill_cache(file, ctx, p->name, p->len,
  				proc_pident_instantiate, task, p))
  			break;
  		ctx->pos++;
  	}
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2359
  out:
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2360
  	put_task_struct(task);
f0c3b5093   Al Viro   [readdir] convert...
2361
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2362
  }
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2363
2364
2365
2366
  #ifdef CONFIG_SECURITY
  static ssize_t proc_pid_attr_read(struct file * file, char __user * buf,
  				  size_t count, loff_t *ppos)
  {
496ad9aa8   Al Viro   new helper: file_...
2367
  	struct inode * inode = file_inode(file);
04ff97086   Al Viro   [PATCH] sanitize ...
2368
  	char *p = NULL;
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2369
2370
  	ssize_t length;
  	struct task_struct *task = get_proc_task(inode);
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2371
  	if (!task)
04ff97086   Al Viro   [PATCH] sanitize ...
2372
  		return -ESRCH;
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2373
2374
  
  	length = security_getprocattr(task,
2fddfeefe   Josef "Jeff" Sipek   [PATCH] proc: cha...
2375
  				      (char*)file->f_path.dentry->d_name.name,
04ff97086   Al Viro   [PATCH] sanitize ...
2376
  				      &p);
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2377
  	put_task_struct(task);
04ff97086   Al Viro   [PATCH] sanitize ...
2378
2379
2380
  	if (length > 0)
  		length = simple_read_from_buffer(buf, count, ppos, p, length);
  	kfree(p);
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2381
  	return length;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2382
  }
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2383
2384
2385
  static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf,
  				   size_t count, loff_t *ppos)
  {
496ad9aa8   Al Viro   new helper: file_...
2386
  	struct inode * inode = file_inode(file);
bb646cdb1   Al Viro   proc_pid_attr_wri...
2387
  	void *page;
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
  	ssize_t length;
  	struct task_struct *task = get_proc_task(inode);
  
  	length = -ESRCH;
  	if (!task)
  		goto out_no_task;
  	if (count > PAGE_SIZE)
  		count = PAGE_SIZE;
  
  	/* No partial writes. */
  	length = -EINVAL;
  	if (*ppos != 0)
  		goto out;
bb646cdb1   Al Viro   proc_pid_attr_wri...
2401
2402
2403
  	page = memdup_user(buf, count);
  	if (IS_ERR(page)) {
  		length = PTR_ERR(page);
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2404
  		goto out;
bb646cdb1   Al Viro   proc_pid_attr_wri...
2405
  	}
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2406

107db7c7d   David Howells   CRED: Guard the s...
2407
  	/* Guard against adverse ptrace interaction */
9b1bf12d5   KOSAKI Motohiro   signals: move cre...
2408
  	length = mutex_lock_interruptible(&task->signal->cred_guard_mutex);
107db7c7d   David Howells   CRED: Guard the s...
2409
2410
  	if (length < 0)
  		goto out_free;
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2411
  	length = security_setprocattr(task,
2fddfeefe   Josef "Jeff" Sipek   [PATCH] proc: cha...
2412
  				      (char*)file->f_path.dentry->d_name.name,
bb646cdb1   Al Viro   proc_pid_attr_wri...
2413
  				      page, count);
9b1bf12d5   KOSAKI Motohiro   signals: move cre...
2414
  	mutex_unlock(&task->signal->cred_guard_mutex);
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2415
  out_free:
bb646cdb1   Al Viro   proc_pid_attr_wri...
2416
  	kfree(page);
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2417
2418
2419
2420
2421
  out:
  	put_task_struct(task);
  out_no_task:
  	return length;
  }
00977a59b   Arjan van de Ven   [PATCH] mark stru...
2422
  static const struct file_operations proc_pid_attr_operations = {
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2423
2424
  	.read		= proc_pid_attr_read,
  	.write		= proc_pid_attr_write,
87df84241   Arnd Bergmann   procfs: Kill BKL ...
2425
  	.llseek		= generic_file_llseek,
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2426
  };
c5141e6d6   Eric Dumazet   procfs: reorder s...
2427
  static const struct pid_entry attr_dir_stuff[] = {
631f9c186   Alexey Dobriyan   proc: remove '##'...
2428
2429
2430
2431
2432
2433
  	REG("current",    S_IRUGO|S_IWUGO, proc_pid_attr_operations),
  	REG("prev",       S_IRUGO,	   proc_pid_attr_operations),
  	REG("exec",       S_IRUGO|S_IWUGO, proc_pid_attr_operations),
  	REG("fscreate",   S_IRUGO|S_IWUGO, proc_pid_attr_operations),
  	REG("keycreate",  S_IRUGO|S_IWUGO, proc_pid_attr_operations),
  	REG("sockcreate", S_IRUGO|S_IWUGO, proc_pid_attr_operations),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2434
  };
f0c3b5093   Al Viro   [readdir] convert...
2435
  static int proc_attr_dir_readdir(struct file *file, struct dir_context *ctx)
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2436
  {
f0c3b5093   Al Viro   [readdir] convert...
2437
2438
  	return proc_pident_readdir(file, ctx, 
  				   attr_dir_stuff, ARRAY_SIZE(attr_dir_stuff));
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2439
  }
00977a59b   Arjan van de Ven   [PATCH] mark stru...
2440
  static const struct file_operations proc_attr_dir_operations = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2441
  	.read		= generic_read_dir,
f50752eaa   Al Viro   switch all procfs...
2442
2443
  	.iterate_shared	= proc_attr_dir_readdir,
  	.llseek		= generic_file_llseek,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2444
  };
72d9dcfc7   Eric W. Biederman   [PATCH] proc: Mer...
2445
  static struct dentry *proc_attr_dir_lookup(struct inode *dir,
00cd8dd3b   Al Viro   stop passing name...
2446
  				struct dentry *dentry, unsigned int flags)
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2447
  {
7bcd6b0ef   Eric W. Biederman   [PATCH] proc: rem...
2448
2449
  	return proc_pident_lookup(dir, dentry,
  				  attr_dir_stuff, ARRAY_SIZE(attr_dir_stuff));
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2450
  }
c5ef1c42c   Arjan van de Ven   [PATCH] mark stru...
2451
  static const struct inode_operations proc_attr_dir_inode_operations = {
72d9dcfc7   Eric W. Biederman   [PATCH] proc: Mer...
2452
  	.lookup		= proc_attr_dir_lookup,
99f895518   Eric W. Biederman   [PATCH] proc: don...
2453
  	.getattr	= pid_getattr,
6d76fa58b   Linus Torvalds   Don't allow chmod...
2454
  	.setattr	= proc_setattr,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2455
  };
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2456
  #endif
698ba7b5a   Christoph Hellwig   elf: kill USE_ELF...
2457
  #ifdef CONFIG_ELF_CORE
3cb4a0bb1   Kawai, Hidehiro   coredump masking:...
2458
2459
2460
  static ssize_t proc_coredump_filter_read(struct file *file, char __user *buf,
  					 size_t count, loff_t *ppos)
  {
496ad9aa8   Al Viro   new helper: file_...
2461
  	struct task_struct *task = get_proc_task(file_inode(file));
3cb4a0bb1   Kawai, Hidehiro   coredump masking:...
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
  	struct mm_struct *mm;
  	char buffer[PROC_NUMBUF];
  	size_t len;
  	int ret;
  
  	if (!task)
  		return -ESRCH;
  
  	ret = 0;
  	mm = get_task_mm(task);
  	if (mm) {
  		len = snprintf(buffer, sizeof(buffer), "%08lx
  ",
  			       ((mm->flags & MMF_DUMP_FILTER_MASK) >>
  				MMF_DUMP_FILTER_SHIFT));
  		mmput(mm);
  		ret = simple_read_from_buffer(buf, count, ppos, buffer, len);
  	}
  
  	put_task_struct(task);
  
  	return ret;
  }
  
  static ssize_t proc_coredump_filter_write(struct file *file,
  					  const char __user *buf,
  					  size_t count,
  					  loff_t *ppos)
  {
  	struct task_struct *task;
  	struct mm_struct *mm;
3cb4a0bb1   Kawai, Hidehiro   coredump masking:...
2493
2494
2495
2496
  	unsigned int val;
  	int ret;
  	int i;
  	unsigned long mask;
774636e19   Alexey Dobriyan   proc: convert to ...
2497
2498
2499
  	ret = kstrtouint_from_user(buf, count, 0, &val);
  	if (ret < 0)
  		return ret;
3cb4a0bb1   Kawai, Hidehiro   coredump masking:...
2500
2501
  
  	ret = -ESRCH;
496ad9aa8   Al Viro   new helper: file_...
2502
  	task = get_proc_task(file_inode(file));
3cb4a0bb1   Kawai, Hidehiro   coredump masking:...
2503
2504
  	if (!task)
  		goto out_no_task;
3cb4a0bb1   Kawai, Hidehiro   coredump masking:...
2505
2506
2507
  	mm = get_task_mm(task);
  	if (!mm)
  		goto out_no_mm;
41a0c249c   Colin Ian King   proc: fix -ESRCH ...
2508
  	ret = 0;
3cb4a0bb1   Kawai, Hidehiro   coredump masking:...
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
  
  	for (i = 0, mask = 1; i < MMF_DUMP_FILTER_BITS; i++, mask <<= 1) {
  		if (val & mask)
  			set_bit(i + MMF_DUMP_FILTER_SHIFT, &mm->flags);
  		else
  			clear_bit(i + MMF_DUMP_FILTER_SHIFT, &mm->flags);
  	}
  
  	mmput(mm);
   out_no_mm:
  	put_task_struct(task);
   out_no_task:
774636e19   Alexey Dobriyan   proc: convert to ...
2521
2522
2523
  	if (ret < 0)
  		return ret;
  	return count;
3cb4a0bb1   Kawai, Hidehiro   coredump masking:...
2524
2525
2526
2527
2528
  }
  
  static const struct file_operations proc_coredump_filter_operations = {
  	.read		= proc_coredump_filter_read,
  	.write		= proc_coredump_filter_write,
87df84241   Arnd Bergmann   procfs: Kill BKL ...
2529
  	.llseek		= generic_file_llseek,
3cb4a0bb1   Kawai, Hidehiro   coredump masking:...
2530
2531
  };
  #endif
aba76fdb8   Andrew Morton   [PATCH] io-accoun...
2532
  #ifdef CONFIG_TASK_IO_ACCOUNTING
19aadc98d   Alexey Dobriyan   proc: convert /pr...
2533
  static int do_io_accounting(struct task_struct *task, struct seq_file *m, int whole)
297c5d926   Andrea Righi   task IO accountin...
2534
  {
940389b8a   Andrea Righi   task IO accountin...
2535
  	struct task_io_accounting acct = task->ioac;
5995477ab   Andrea Righi   task IO accountin...
2536
  	unsigned long flags;
293eb1e77   Vasiliy Kulikov   proc: fix a race ...
2537
  	int result;
5995477ab   Andrea Righi   task IO accountin...
2538

293eb1e77   Vasiliy Kulikov   proc: fix a race ...
2539
2540
2541
  	result = mutex_lock_killable(&task->signal->cred_guard_mutex);
  	if (result)
  		return result;
caaee6234   Jann Horn   ptrace: use fsuid...
2542
  	if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) {
293eb1e77   Vasiliy Kulikov   proc: fix a race ...
2543
2544
2545
  		result = -EACCES;
  		goto out_unlock;
  	}
1d1221f37   Vasiliy Kulikov   proc: restrict ac...
2546

5995477ab   Andrea Righi   task IO accountin...
2547
2548
2549
2550
2551
2552
2553
2554
  	if (whole && lock_task_sighand(task, &flags)) {
  		struct task_struct *t = task;
  
  		task_io_accounting_add(&acct, &task->signal->ioac);
  		while_each_thread(task, t)
  			task_io_accounting_add(&acct, &t->ioac);
  
  		unlock_task_sighand(task, &flags);
297c5d926   Andrea Righi   task IO accountin...
2555
  	}
25ce31916   Joe Perches   proc: remove use ...
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
  	seq_printf(m,
  		   "rchar: %llu
  "
  		   "wchar: %llu
  "
  		   "syscr: %llu
  "
  		   "syscw: %llu
  "
  		   "read_bytes: %llu
  "
  		   "write_bytes: %llu
  "
  		   "cancelled_write_bytes: %llu
  ",
  		   (unsigned long long)acct.rchar,
  		   (unsigned long long)acct.wchar,
  		   (unsigned long long)acct.syscr,
  		   (unsigned long long)acct.syscw,
  		   (unsigned long long)acct.read_bytes,
  		   (unsigned long long)acct.write_bytes,
  		   (unsigned long long)acct.cancelled_write_bytes);
  	result = 0;
293eb1e77   Vasiliy Kulikov   proc: fix a race ...
2579
2580
2581
  out_unlock:
  	mutex_unlock(&task->signal->cred_guard_mutex);
  	return result;
297c5d926   Andrea Righi   task IO accountin...
2582
  }
19aadc98d   Alexey Dobriyan   proc: convert /pr...
2583
2584
  static int proc_tid_io_accounting(struct seq_file *m, struct pid_namespace *ns,
  				  struct pid *pid, struct task_struct *task)
297c5d926   Andrea Righi   task IO accountin...
2585
  {
19aadc98d   Alexey Dobriyan   proc: convert /pr...
2586
  	return do_io_accounting(task, m, 0);
aba76fdb8   Andrew Morton   [PATCH] io-accoun...
2587
  }
297c5d926   Andrea Righi   task IO accountin...
2588

19aadc98d   Alexey Dobriyan   proc: convert /pr...
2589
2590
  static int proc_tgid_io_accounting(struct seq_file *m, struct pid_namespace *ns,
  				   struct pid *pid, struct task_struct *task)
297c5d926   Andrea Righi   task IO accountin...
2591
  {
19aadc98d   Alexey Dobriyan   proc: convert /pr...
2592
  	return do_io_accounting(task, m, 1);
297c5d926   Andrea Righi   task IO accountin...
2593
2594
  }
  #endif /* CONFIG_TASK_IO_ACCOUNTING */
aba76fdb8   Andrew Morton   [PATCH] io-accoun...
2595

22d917d80   Eric W. Biederman   userns: Rework th...
2596
2597
  #ifdef CONFIG_USER_NS
  static int proc_id_map_open(struct inode *inode, struct file *file,
ccf94f1b4   Fabian Frederick   proc: constify se...
2598
  	const struct seq_operations *seq_ops)
22d917d80   Eric W. Biederman   userns: Rework th...
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
  {
  	struct user_namespace *ns = NULL;
  	struct task_struct *task;
  	struct seq_file *seq;
  	int ret = -EINVAL;
  
  	task = get_proc_task(inode);
  	if (task) {
  		rcu_read_lock();
  		ns = get_user_ns(task_cred_xxx(task, user_ns));
  		rcu_read_unlock();
  		put_task_struct(task);
  	}
  	if (!ns)
  		goto err;
  
  	ret = seq_open(file, seq_ops);
  	if (ret)
  		goto err_put_ns;
  
  	seq = file->private_data;
  	seq->private = ns;
  
  	return 0;
  err_put_ns:
  	put_user_ns(ns);
  err:
  	return ret;
  }
  
  static int proc_id_map_release(struct inode *inode, struct file *file)
  {
  	struct seq_file *seq = file->private_data;
  	struct user_namespace *ns = seq->private;
  	put_user_ns(ns);
  	return seq_release(inode, file);
  }
  
  static int proc_uid_map_open(struct inode *inode, struct file *file)
  {
  	return proc_id_map_open(inode, file, &proc_uid_seq_operations);
  }
  
  static int proc_gid_map_open(struct inode *inode, struct file *file)
  {
  	return proc_id_map_open(inode, file, &proc_gid_seq_operations);
  }
f76d207a6   Eric W. Biederman   userns: Add kproj...
2646
2647
2648
2649
  static int proc_projid_map_open(struct inode *inode, struct file *file)
  {
  	return proc_id_map_open(inode, file, &proc_projid_seq_operations);
  }
22d917d80   Eric W. Biederman   userns: Rework th...
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
  static const struct file_operations proc_uid_map_operations = {
  	.open		= proc_uid_map_open,
  	.write		= proc_uid_map_write,
  	.read		= seq_read,
  	.llseek		= seq_lseek,
  	.release	= proc_id_map_release,
  };
  
  static const struct file_operations proc_gid_map_operations = {
  	.open		= proc_gid_map_open,
  	.write		= proc_gid_map_write,
  	.read		= seq_read,
  	.llseek		= seq_lseek,
  	.release	= proc_id_map_release,
  };
f76d207a6   Eric W. Biederman   userns: Add kproj...
2665
2666
2667
2668
2669
2670
2671
2672
  
  static const struct file_operations proc_projid_map_operations = {
  	.open		= proc_projid_map_open,
  	.write		= proc_projid_map_write,
  	.read		= seq_read,
  	.llseek		= seq_lseek,
  	.release	= proc_id_map_release,
  };
9cc46516d   Eric W. Biederman   userns: Add a kno...
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
  
  static int proc_setgroups_open(struct inode *inode, struct file *file)
  {
  	struct user_namespace *ns = NULL;
  	struct task_struct *task;
  	int ret;
  
  	ret = -ESRCH;
  	task = get_proc_task(inode);
  	if (task) {
  		rcu_read_lock();
  		ns = get_user_ns(task_cred_xxx(task, user_ns));
  		rcu_read_unlock();
  		put_task_struct(task);
  	}
  	if (!ns)
  		goto err;
  
  	if (file->f_mode & FMODE_WRITE) {
  		ret = -EACCES;
  		if (!ns_capable(ns, CAP_SYS_ADMIN))
  			goto err_put_ns;
  	}
  
  	ret = single_open(file, &proc_setgroups_show, ns);
  	if (ret)
  		goto err_put_ns;
  
  	return 0;
  err_put_ns:
  	put_user_ns(ns);
  err:
  	return ret;
  }
  
  static int proc_setgroups_release(struct inode *inode, struct file *file)
  {
  	struct seq_file *seq = file->private_data;
  	struct user_namespace *ns = seq->private;
  	int ret = single_release(inode, file);
  	put_user_ns(ns);
  	return ret;
  }
  
  static const struct file_operations proc_setgroups_operations = {
  	.open		= proc_setgroups_open,
  	.write		= proc_setgroups_write,
  	.read		= seq_read,
  	.llseek		= seq_lseek,
  	.release	= proc_setgroups_release,
  };
22d917d80   Eric W. Biederman   userns: Rework th...
2724
  #endif /* CONFIG_USER_NS */
478307230   Kees Cook   [PATCH] proc: sho...
2725
2726
2727
  static int proc_pid_personality(struct seq_file *m, struct pid_namespace *ns,
  				struct pid *pid, struct task_struct *task)
  {
a9712bc12   Al Viro   deal with races i...
2728
2729
2730
2731
2732
2733
2734
  	int err = lock_trace(task);
  	if (!err) {
  		seq_printf(m, "%08x
  ", task->personality);
  		unlock_trace(task);
  	}
  	return err;
478307230   Kees Cook   [PATCH] proc: sho...
2735
  }
801199ce8   Eric W. Biederman   [PATCH] proc: Mak...
2736
  /*
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2737
2738
   * Thread groups
   */
00977a59b   Arjan van de Ven   [PATCH] mark stru...
2739
  static const struct file_operations proc_task_operations;
c5ef1c42c   Arjan van de Ven   [PATCH] mark stru...
2740
  static const struct inode_operations proc_task_inode_operations;
20cdc894c   Eric W. Biederman   [PATCH] proc: mod...
2741

c5141e6d6   Eric Dumazet   procfs: reorder s...
2742
  static const struct pid_entry tgid_base_stuff[] = {
631f9c186   Alexey Dobriyan   proc: remove '##'...
2743
2744
  	DIR("task",       S_IRUGO|S_IXUGO, proc_task_inode_operations, proc_task_operations),
  	DIR("fd",         S_IRUSR|S_IXUSR, proc_fd_inode_operations, proc_fd_operations),
640708a2c   Pavel Emelyanov   procfs: introduce...
2745
  	DIR("map_files",  S_IRUSR|S_IXUSR, proc_map_files_inode_operations, proc_map_files_operations),
631f9c186   Alexey Dobriyan   proc: remove '##'...
2746
  	DIR("fdinfo",     S_IRUSR|S_IXUSR, proc_fdinfo_inode_operations, proc_fdinfo_operations),
6b4e306aa   Eric W. Biederman   ns: proc files fo...
2747
  	DIR("ns",	  S_IRUSR|S_IXUGO, proc_ns_dir_inode_operations, proc_ns_dir_operations),
b2211a361   Andrew Morton   net: fix build wi...
2748
  #ifdef CONFIG_NET
631f9c186   Alexey Dobriyan   proc: remove '##'...
2749
  	DIR("net",        S_IRUGO|S_IXUGO, proc_net_inode_operations, proc_net_operations),
b2211a361   Andrew Morton   net: fix build wi...
2750
  #endif
631f9c186   Alexey Dobriyan   proc: remove '##'...
2751
  	REG("environ",    S_IRUSR, proc_environ_operations),
c53171678   Al Viro   proc: switch auxv...
2752
  	REG("auxv",       S_IRUSR, proc_auxv_operations),
631f9c186   Alexey Dobriyan   proc: remove '##'...
2753
  	ONE("status",     S_IRUGO, proc_pid_status),
35a35046e   Djalal Harouni   procfs: make /pro...
2754
  	ONE("personality", S_IRUSR, proc_pid_personality),
1c963eb13   Alexey Dobriyan   proc: convert /pr...
2755
  	ONE("limits",	  S_IRUGO, proc_pid_limits),
43ae34cb4   Ingo Molnar   sched: scheduler ...
2756
  #ifdef CONFIG_SCHED_DEBUG
631f9c186   Alexey Dobriyan   proc: remove '##'...
2757
  	REG("sched",      S_IRUGO|S_IWUSR, proc_pid_sched_operations),
43ae34cb4   Ingo Molnar   sched: scheduler ...
2758
  #endif
5091faa44   Mike Galbraith   sched: Add 'autog...
2759
2760
2761
  #ifdef CONFIG_SCHED_AUTOGROUP
  	REG("autogroup",  S_IRUGO|S_IWUSR, proc_pid_sched_autogroup_operations),
  #endif
4614a696b   John Stultz   procfs: allow thr...
2762
  	REG("comm",      S_IRUGO|S_IWUSR, proc_pid_set_comm_operations),
ebcb67341   Roland McGrath   /proc/PID/syscall
2763
  #ifdef CONFIG_HAVE_ARCH_TRACEHOOK
09d93bd62   Alexey Dobriyan   proc: convert /pr...
2764
  	ONE("syscall",    S_IRUSR, proc_pid_syscall),
ebcb67341   Roland McGrath   /proc/PID/syscall
2765
  #endif
c2c0bb446   Alexey Dobriyan   proc: fix PAGE_SI...
2766
  	REG("cmdline",    S_IRUGO, proc_pid_cmdline_ops),
631f9c186   Alexey Dobriyan   proc: remove '##'...
2767
2768
  	ONE("stat",       S_IRUGO, proc_tgid_stat),
  	ONE("statm",      S_IRUGO, proc_pid_statm),
b76437579   Siddhesh Poyarekar   procfs: mark thre...
2769
  	REG("maps",       S_IRUGO, proc_pid_maps_operations),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2770
  #ifdef CONFIG_NUMA
b76437579   Siddhesh Poyarekar   procfs: mark thre...
2771
  	REG("numa_maps",  S_IRUGO, proc_pid_numa_maps_operations),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2772
  #endif
631f9c186   Alexey Dobriyan   proc: remove '##'...
2773
2774
2775
2776
2777
2778
2779
  	REG("mem",        S_IRUSR|S_IWUSR, proc_mem_operations),
  	LNK("cwd",        proc_cwd_link),
  	LNK("root",       proc_root_link),
  	LNK("exe",        proc_exe_link),
  	REG("mounts",     S_IRUGO, proc_mounts_operations),
  	REG("mountinfo",  S_IRUGO, proc_mountinfo_operations),
  	REG("mountstats", S_IRUSR, proc_mountstats_operations),
1e8832811   Matt Mackall   maps4: make page ...
2780
  #ifdef CONFIG_PROC_PAGE_MONITOR
631f9c186   Alexey Dobriyan   proc: remove '##'...
2781
  	REG("clear_refs", S_IWUSR, proc_clear_refs_operations),
b76437579   Siddhesh Poyarekar   procfs: mark thre...
2782
  	REG("smaps",      S_IRUGO, proc_pid_smaps_operations),
32ed74a4b   Djalal Harouni   procfs: make /pro...
2783
  	REG("pagemap",    S_IRUSR, proc_pagemap_operations),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2784
2785
  #endif
  #ifdef CONFIG_SECURITY
631f9c186   Alexey Dobriyan   proc: remove '##'...
2786
  	DIR("attr",       S_IRUGO|S_IXUGO, proc_attr_dir_inode_operations, proc_attr_dir_operations),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2787
2788
  #endif
  #ifdef CONFIG_KALLSYMS
edfcd6064   Alexey Dobriyan   proc: convert /pr...
2789
  	ONE("wchan",      S_IRUGO, proc_pid_wchan),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2790
  #endif
2ec220e27   Ken Chen   proc: add /proc/*...
2791
  #ifdef CONFIG_STACKTRACE
35a35046e   Djalal Harouni   procfs: make /pro...
2792
  	ONE("stack",      S_IRUSR, proc_pid_stack),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2793
  #endif
5968ceced   Naveen N. Rao   sched/stat: Expos...
2794
  #ifdef CONFIG_SCHED_INFO
f6e826ca3   Alexey Dobriyan   proc: convert /pr...
2795
  	ONE("schedstat",  S_IRUGO, proc_pid_schedstat),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2796
  #endif
9745512ce   Arjan van de Ven   sched: latencytop...
2797
  #ifdef CONFIG_LATENCYTOP
631f9c186   Alexey Dobriyan   proc: remove '##'...
2798
  	REG("latency",  S_IRUGO, proc_lstats_operations),
9745512ce   Arjan van de Ven   sched: latencytop...
2799
  #endif
8793d854e   Paul Menage   Task Control Grou...
2800
  #ifdef CONFIG_PROC_PID_CPUSET
52de4779f   Zefan Li   cpuset: simplify ...
2801
  	ONE("cpuset",     S_IRUGO, proc_cpuset_show),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2802
  #endif
a424316ca   Paul Menage   Task Control Grou...
2803
  #ifdef CONFIG_CGROUPS
006f4ac49   Zefan Li   cgroup: simplify ...
2804
  	ONE("cgroup",  S_IRUGO, proc_cgroup_show),
a424316ca   Paul Menage   Task Control Grou...
2805
  #endif
6ba51e375   Alexey Dobriyan   proc: convert /pr...
2806
  	ONE("oom_score",  S_IRUGO, proc_oom_score),
fa0cbbf14   David Rientjes   mm, oom: reintrod...
2807
  	REG("oom_adj",    S_IRUGO|S_IWUSR, proc_oom_adj_operations),
a63d83f42   David Rientjes   oom: badness heur...
2808
  	REG("oom_score_adj", S_IRUGO|S_IWUSR, proc_oom_score_adj_operations),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2809
  #ifdef CONFIG_AUDITSYSCALL
631f9c186   Alexey Dobriyan   proc: remove '##'...
2810
2811
  	REG("loginuid",   S_IWUSR|S_IRUGO, proc_loginuid_operations),
  	REG("sessionid",  S_IRUGO, proc_sessionid_operations),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2812
  #endif
f4f154fd9   Akinobu Mita   [PATCH] fault inj...
2813
  #ifdef CONFIG_FAULT_INJECTION
631f9c186   Alexey Dobriyan   proc: remove '##'...
2814
  	REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
f4f154fd9   Akinobu Mita   [PATCH] fault inj...
2815
  #endif
698ba7b5a   Christoph Hellwig   elf: kill USE_ELF...
2816
  #ifdef CONFIG_ELF_CORE
631f9c186   Alexey Dobriyan   proc: remove '##'...
2817
  	REG("coredump_filter", S_IRUGO|S_IWUSR, proc_coredump_filter_operations),
3cb4a0bb1   Kawai, Hidehiro   coredump masking:...
2818
  #endif
aba76fdb8   Andrew Morton   [PATCH] io-accoun...
2819
  #ifdef CONFIG_TASK_IO_ACCOUNTING
19aadc98d   Alexey Dobriyan   proc: convert /pr...
2820
  	ONE("io",	S_IRUSR, proc_tgid_io_accounting),
aba76fdb8   Andrew Morton   [PATCH] io-accoun...
2821
  #endif
f133ecca9   Chris Metcalf   arch/tile: more /...
2822
  #ifdef CONFIG_HARDWALL
d962c1448   Alexey Dobriyan   proc: convert /pr...
2823
  	ONE("hardwall",   S_IRUGO, proc_pid_hardwall),
f133ecca9   Chris Metcalf   arch/tile: more /...
2824
  #endif
22d917d80   Eric W. Biederman   userns: Rework th...
2825
2826
2827
  #ifdef CONFIG_USER_NS
  	REG("uid_map",    S_IRUGO|S_IWUSR, proc_uid_map_operations),
  	REG("gid_map",    S_IRUGO|S_IWUSR, proc_gid_map_operations),
f76d207a6   Eric W. Biederman   userns: Add kproj...
2828
  	REG("projid_map", S_IRUGO|S_IWUSR, proc_projid_map_operations),
9cc46516d   Eric W. Biederman   userns: Add a kno...
2829
  	REG("setgroups",  S_IRUGO|S_IWUSR, proc_setgroups_operations),
22d917d80   Eric W. Biederman   userns: Rework th...
2830
  #endif
48f6a7a51   Pavel Emelyanov   posix-timers: Int...
2831
2832
2833
  #ifdef CONFIG_CHECKPOINT_RESTORE
  	REG("timers",	  S_IRUGO, proc_timers_operations),
  #endif
5de23d435   John Stultz   proc: add /proc/<...
2834
  	REG("timerslack_ns", S_IRUGO|S_IWUGO, proc_pid_set_timerslack_ns_operations),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2835
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2836

f0c3b5093   Al Viro   [readdir] convert...
2837
  static int proc_tgid_base_readdir(struct file *file, struct dir_context *ctx)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2838
  {
f0c3b5093   Al Viro   [readdir] convert...
2839
2840
  	return proc_pident_readdir(file, ctx,
  				   tgid_base_stuff, ARRAY_SIZE(tgid_base_stuff));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2841
  }
00977a59b   Arjan van de Ven   [PATCH] mark stru...
2842
  static const struct file_operations proc_tgid_base_operations = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2843
  	.read		= generic_read_dir,
f50752eaa   Al Viro   switch all procfs...
2844
2845
  	.iterate_shared	= proc_tgid_base_readdir,
  	.llseek		= generic_file_llseek,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2846
  };
00cd8dd3b   Al Viro   stop passing name...
2847
2848
  static struct dentry *proc_tgid_base_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
  {
7bcd6b0ef   Eric W. Biederman   [PATCH] proc: rem...
2849
2850
  	return proc_pident_lookup(dir, dentry,
  				  tgid_base_stuff, ARRAY_SIZE(tgid_base_stuff));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2851
  }
c5ef1c42c   Arjan van de Ven   [PATCH] mark stru...
2852
  static const struct inode_operations proc_tgid_base_inode_operations = {
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
2853
  	.lookup		= proc_tgid_base_lookup,
99f895518   Eric W. Biederman   [PATCH] proc: don...
2854
  	.getattr	= pid_getattr,
6d76fa58b   Linus Torvalds   Don't allow chmod...
2855
  	.setattr	= proc_setattr,
0499680a4   Vasiliy Kulikov   procfs: add hidep...
2856
  	.permission	= proc_pid_permission,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2857
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2858

60347f671   Pavel Emelyanov   pid namespaces: p...
2859
  static void proc_flush_task_mnt(struct vfsmount *mnt, pid_t pid, pid_t tgid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2860
  {
48e6484d4   Eric W. Biederman   [PATCH] proc: Rew...
2861
  	struct dentry *dentry, *leader, *dir;
8578cea75   Eric W. Biederman   [PATCH] proc: mak...
2862
  	char buf[PROC_NUMBUF];
48e6484d4   Eric W. Biederman   [PATCH] proc: Rew...
2863
2864
2865
  	struct qstr name;
  
  	name.name = buf;
60347f671   Pavel Emelyanov   pid namespaces: p...
2866
  	name.len = snprintf(buf, sizeof(buf), "%d", pid);
4f522a247   Al Viro   d_hash_and_lookup...
2867
  	/* no ->d_hash() rejects on procfs */
60347f671   Pavel Emelyanov   pid namespaces: p...
2868
  	dentry = d_hash_and_lookup(mnt->mnt_root, &name);
48e6484d4   Eric W. Biederman   [PATCH] proc: Rew...
2869
  	if (dentry) {
bbd519241   Eric W. Biederman   proc: Update proc...
2870
  		d_invalidate(dentry);
48e6484d4   Eric W. Biederman   [PATCH] proc: Rew...
2871
2872
  		dput(dentry);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2873

c35a7f18a   Oleg Nesterov   exit: proc: don't...
2874
2875
  	if (pid == tgid)
  		return;
48e6484d4   Eric W. Biederman   [PATCH] proc: Rew...
2876
  	name.name = buf;
60347f671   Pavel Emelyanov   pid namespaces: p...
2877
2878
  	name.len = snprintf(buf, sizeof(buf), "%d", tgid);
  	leader = d_hash_and_lookup(mnt->mnt_root, &name);
48e6484d4   Eric W. Biederman   [PATCH] proc: Rew...
2879
2880
  	if (!leader)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2881

48e6484d4   Eric W. Biederman   [PATCH] proc: Rew...
2882
2883
2884
2885
2886
2887
2888
  	name.name = "task";
  	name.len = strlen(name.name);
  	dir = d_hash_and_lookup(leader, &name);
  	if (!dir)
  		goto out_put_leader;
  
  	name.name = buf;
60347f671   Pavel Emelyanov   pid namespaces: p...
2889
  	name.len = snprintf(buf, sizeof(buf), "%d", pid);
48e6484d4   Eric W. Biederman   [PATCH] proc: Rew...
2890
2891
  	dentry = d_hash_and_lookup(dir, &name);
  	if (dentry) {
bbd519241   Eric W. Biederman   proc: Update proc...
2892
  		d_invalidate(dentry);
48e6484d4   Eric W. Biederman   [PATCH] proc: Rew...
2893
  		dput(dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2894
  	}
48e6484d4   Eric W. Biederman   [PATCH] proc: Rew...
2895
2896
2897
2898
2899
2900
  
  	dput(dir);
  out_put_leader:
  	dput(leader);
  out:
  	return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2901
  }
0895e91d6   Randy Dunlap   procfs: fix kerne...
2902
2903
2904
2905
2906
  /**
   * proc_flush_task -  Remove dcache entries for @task from the /proc dcache.
   * @task: task that should be flushed.
   *
   * When flushing dentries from proc, one needs to flush them from global
60347f671   Pavel Emelyanov   pid namespaces: p...
2907
   * proc (proc_mnt) and from all the namespaces' procs this task was seen
0895e91d6   Randy Dunlap   procfs: fix kerne...
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
   * in. This call is supposed to do all of this job.
   *
   * Looks in the dcache for
   * /proc/@pid
   * /proc/@tgid/task/@pid
   * if either directory is present flushes it and all of it'ts children
   * from the dcache.
   *
   * It is safe and reasonable to cache /proc entries for a task until
   * that task exits.  After that they just clog up the dcache with
   * useless entries, possibly causing useful dcache entries to be
   * flushed instead.  This routine is proved to flush those useless
   * dcache entries at process exit time.
   *
   * NOTE: This routine is just an optimization so it does not guarantee
   *       that no dcache entries will exist at process exit time it
   *       just makes it very unlikely that any will persist.
60347f671   Pavel Emelyanov   pid namespaces: p...
2925
2926
2927
2928
   */
  
  void proc_flush_task(struct task_struct *task)
  {
9fcc2d15b   Eric W. Biederman   proc: simplify an...
2929
  	int i;
9b4d1cbef   Oleg Nesterov   proc_flush_task: ...
2930
  	struct pid *pid, *tgid;
130f77ecb   Pavel Emelyanov   pid namespaces: m...
2931
  	struct upid *upid;
130f77ecb   Pavel Emelyanov   pid namespaces: m...
2932
  	pid = task_pid(task);
9b4d1cbef   Oleg Nesterov   proc_flush_task: ...
2933
  	tgid = task_tgid(task);
130f77ecb   Pavel Emelyanov   pid namespaces: m...
2934

9fcc2d15b   Eric W. Biederman   proc: simplify an...
2935
  	for (i = 0; i <= pid->level; i++) {
130f77ecb   Pavel Emelyanov   pid namespaces: m...
2936
2937
  		upid = &pid->numbers[i];
  		proc_flush_task_mnt(upid->ns->proc_mnt, upid->nr,
9b4d1cbef   Oleg Nesterov   proc_flush_task: ...
2938
  					tgid->numbers[i].nr);
130f77ecb   Pavel Emelyanov   pid namespaces: m...
2939
  	}
60347f671   Pavel Emelyanov   pid namespaces: p...
2940
  }
c52a47ace   Al Viro   proc_fill_cache()...
2941
2942
2943
  static int proc_pid_instantiate(struct inode *dir,
  				   struct dentry * dentry,
  				   struct task_struct *task, const void *ptr)
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
2944
  {
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
2945
  	struct inode *inode;
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
2946
  	inode = proc_pid_make_inode(dir->i_sb, task);
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
2947
2948
2949
2950
2951
2952
2953
  	if (!inode)
  		goto out;
  
  	inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
  	inode->i_op = &proc_tgid_base_inode_operations;
  	inode->i_fop = &proc_tgid_base_operations;
  	inode->i_flags|=S_IMMUTABLE;
aed541759   Vegard Nossum   proc: calculate t...
2954

bfe868486   Miklos Szeredi   filesystems: add ...
2955
2956
  	set_nlink(inode, 2 + pid_entry_count_dirs(tgid_base_stuff,
  						  ARRAY_SIZE(tgid_base_stuff)));
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
2957

fb045adb9   Nick Piggin   fs: dcache reduce...
2958
  	d_set_d_op(dentry, &pid_dentry_operations);
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
2959
2960
2961
  
  	d_add(dentry, inode);
  	/* Close the race of the process dying before we return the dentry */
0b728e191   Al Viro   stop passing name...
2962
  	if (pid_revalidate(dentry, 0))
c52a47ace   Al Viro   proc_fill_cache()...
2963
  		return 0;
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
2964
  out:
c52a47ace   Al Viro   proc_fill_cache()...
2965
  	return -ENOENT;
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
2966
  }
00cd8dd3b   Al Viro   stop passing name...
2967
  struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2968
  {
335eb5315   Alexey Dobriyan   proc: faster /pro...
2969
  	int result = -ENOENT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2970
  	struct task_struct *task;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2971
  	unsigned tgid;
b488893a3   Pavel Emelyanov   pid namespaces: c...
2972
  	struct pid_namespace *ns;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2973

dbcdb5044   Alexey Dobriyan   proc: add and rem...
2974
  	tgid = name_to_int(&dentry->d_name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2975
2976
  	if (tgid == ~0U)
  		goto out;
b488893a3   Pavel Emelyanov   pid namespaces: c...
2977
  	ns = dentry->d_sb->s_fs_info;
de7587343   Eric W. Biederman   [PATCH] proc: Rem...
2978
  	rcu_read_lock();
b488893a3   Pavel Emelyanov   pid namespaces: c...
2979
  	task = find_task_by_pid_ns(tgid, ns);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2980
2981
  	if (task)
  		get_task_struct(task);
de7587343   Eric W. Biederman   [PATCH] proc: Rem...
2982
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2983
2984
  	if (!task)
  		goto out;
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
2985
  	result = proc_pid_instantiate(dir, dentry, task, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2986
  	put_task_struct(task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2987
  out:
c52a47ace   Al Viro   proc_fill_cache()...
2988
  	return ERR_PTR(result);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2989
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2990
  /*
0804ef4b0   Eric W. Biederman   [PATCH] proc: rea...
2991
   * Find the first task with tgid >= tgid
0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
2992
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2993
   */
19fd4bb2a   Eric W. Biederman   proc: remove race...
2994
2995
  struct tgid_iter {
  	unsigned int tgid;
0804ef4b0   Eric W. Biederman   [PATCH] proc: rea...
2996
  	struct task_struct *task;
19fd4bb2a   Eric W. Biederman   proc: remove race...
2997
2998
2999
  };
  static struct tgid_iter next_tgid(struct pid_namespace *ns, struct tgid_iter iter)
  {
0804ef4b0   Eric W. Biederman   [PATCH] proc: rea...
3000
  	struct pid *pid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3001

19fd4bb2a   Eric W. Biederman   proc: remove race...
3002
3003
  	if (iter.task)
  		put_task_struct(iter.task);
454cc105e   Eric W. Biederman   [PATCH] proc: Rem...
3004
  	rcu_read_lock();
0804ef4b0   Eric W. Biederman   [PATCH] proc: rea...
3005
  retry:
19fd4bb2a   Eric W. Biederman   proc: remove race...
3006
3007
  	iter.task = NULL;
  	pid = find_ge_pid(iter.tgid, ns);
0804ef4b0   Eric W. Biederman   [PATCH] proc: rea...
3008
  	if (pid) {
19fd4bb2a   Eric W. Biederman   proc: remove race...
3009
3010
  		iter.tgid = pid_nr_ns(pid, ns);
  		iter.task = pid_task(pid, PIDTYPE_PID);
0804ef4b0   Eric W. Biederman   [PATCH] proc: rea...
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
  		/* What we to know is if the pid we have find is the
  		 * pid of a thread_group_leader.  Testing for task
  		 * being a thread_group_leader is the obvious thing
  		 * todo but there is a window when it fails, due to
  		 * the pid transfer logic in de_thread.
  		 *
  		 * So we perform the straight forward test of seeing
  		 * if the pid we have found is the pid of a thread
  		 * group leader, and don't worry if the task we have
  		 * found doesn't happen to be a thread group leader.
  		 * As we don't care in the case of readdir.
  		 */
19fd4bb2a   Eric W. Biederman   proc: remove race...
3023
3024
  		if (!iter.task || !has_group_leader_pid(iter.task)) {
  			iter.tgid += 1;
0804ef4b0   Eric W. Biederman   [PATCH] proc: rea...
3025
  			goto retry;
19fd4bb2a   Eric W. Biederman   proc: remove race...
3026
3027
  		}
  		get_task_struct(iter.task);
0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
3028
  	}
454cc105e   Eric W. Biederman   [PATCH] proc: Rem...
3029
  	rcu_read_unlock();
19fd4bb2a   Eric W. Biederman   proc: remove race...
3030
  	return iter;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3031
  }
0097875bd   Eric W. Biederman   proc: Implement /...
3032
  #define TGID_OFFSET (FIRST_PROCESS_ENTRY + 2)
0804ef4b0   Eric W. Biederman   [PATCH] proc: rea...
3033

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3034
  /* for the /proc/ directory itself, after non-process stuff has been done */
f0c3b5093   Al Viro   [readdir] convert...
3035
  int proc_pid_readdir(struct file *file, struct dir_context *ctx)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3036
  {
19fd4bb2a   Eric W. Biederman   proc: remove race...
3037
  	struct tgid_iter iter;
3aa3377fb   Al Viro   procfs: get rid o...
3038
  	struct pid_namespace *ns = file_inode(file)->i_sb->s_fs_info;
f0c3b5093   Al Viro   [readdir] convert...
3039
  	loff_t pos = ctx->pos;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3040

021ada7df   Al Viro   procfs: switch /p...
3041
  	if (pos >= PID_MAX_LIMIT + TGID_OFFSET)
f0c3b5093   Al Viro   [readdir] convert...
3042
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3043

0097875bd   Eric W. Biederman   proc: Implement /...
3044
  	if (pos == TGID_OFFSET - 2) {
2b0143b5c   David Howells   VFS: normal files...
3045
  		struct inode *inode = d_inode(ns->proc_self);
db9631648   Al Viro   proc_pid_readdir(...
3046
  		if (!dir_emit(ctx, "self", 4, inode->i_ino, DT_LNK))
f0c3b5093   Al Viro   [readdir] convert...
3047
  			return 0;
0097875bd   Eric W. Biederman   proc: Implement /...
3048
3049
3050
  		ctx->pos = pos = pos + 1;
  	}
  	if (pos == TGID_OFFSET - 1) {
2b0143b5c   David Howells   VFS: normal files...
3051
  		struct inode *inode = d_inode(ns->proc_thread_self);
0097875bd   Eric W. Biederman   proc: Implement /...
3052
3053
3054
  		if (!dir_emit(ctx, "thread-self", 11, inode->i_ino, DT_LNK))
  			return 0;
  		ctx->pos = pos = pos + 1;
021ada7df   Al Viro   procfs: switch /p...
3055
  	}
0097875bd   Eric W. Biederman   proc: Implement /...
3056
  	iter.tgid = pos - TGID_OFFSET;
19fd4bb2a   Eric W. Biederman   proc: remove race...
3057
  	iter.task = NULL;
19fd4bb2a   Eric W. Biederman   proc: remove race...
3058
3059
3060
  	for (iter = next_tgid(ns, iter);
  	     iter.task;
  	     iter.tgid += 1, iter = next_tgid(ns, iter)) {
f0c3b5093   Al Viro   [readdir] convert...
3061
3062
3063
3064
  		char name[PROC_NUMBUF];
  		int len;
  		if (!has_pid_permissions(ns, iter.task, 2))
  			continue;
0499680a4   Vasiliy Kulikov   procfs: add hidep...
3065

f0c3b5093   Al Viro   [readdir] convert...
3066
3067
3068
3069
  		len = snprintf(name, sizeof(name), "%d", iter.tgid);
  		ctx->pos = iter.tgid + TGID_OFFSET;
  		if (!proc_fill_cache(file, ctx, name, len,
  				     proc_pid_instantiate, iter.task, NULL)) {
19fd4bb2a   Eric W. Biederman   proc: remove race...
3070
  			put_task_struct(iter.task);
f0c3b5093   Al Viro   [readdir] convert...
3071
  			return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3072
  		}
0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
3073
  	}
f0c3b5093   Al Viro   [readdir] convert...
3074
  	ctx->pos = PID_MAX_LIMIT + TGID_OFFSET;
0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
3075
3076
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3077

0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
3078
  /*
1b3044e39   Janis Danisevskis   procfs: fix pthre...
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
   * proc_tid_comm_permission is a special permission function exclusively
   * used for the node /proc/<pid>/task/<tid>/comm.
   * It bypasses generic permission checks in the case where a task of the same
   * task group attempts to access the node.
   * The rationale behind this is that glibc and bionic access this node for
   * cross thread naming (pthread_set/getname_np(!self)). However, if
   * PR_SET_DUMPABLE gets set to 0 this node among others becomes uid=0 gid=0,
   * which locks out the cross thread naming implementation.
   * This function makes sure that the node is always accessible for members of
   * same thread group.
   */
  static int proc_tid_comm_permission(struct inode *inode, int mask)
  {
  	bool is_same_tgroup;
  	struct task_struct *task;
  
  	task = get_proc_task(inode);
  	if (!task)
  		return -ESRCH;
  	is_same_tgroup = same_thread_group(current, task);
  	put_task_struct(task);
  
  	if (likely(is_same_tgroup && !(mask & MAY_EXEC))) {
  		/* This file (/proc/<pid>/task/<tid>/comm) can always be
  		 * read or written by the members of the corresponding
  		 * thread group.
  		 */
  		return 0;
  	}
  
  	return generic_permission(inode, mask);
  }
  
  static const struct inode_operations proc_tid_comm_inode_operations = {
  		.permission = proc_tid_comm_permission,
  };
  
  /*
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
3117
3118
   * Tasks
   */
c5141e6d6   Eric Dumazet   procfs: reorder s...
3119
  static const struct pid_entry tid_base_stuff[] = {
631f9c186   Alexey Dobriyan   proc: remove '##'...
3120
  	DIR("fd",        S_IRUSR|S_IXUSR, proc_fd_inode_operations, proc_fd_operations),
3835541dd   Jerome Marchand   procfs: fix tid f...
3121
  	DIR("fdinfo",    S_IRUSR|S_IXUSR, proc_fdinfo_inode_operations, proc_fdinfo_operations),
6b4e306aa   Eric W. Biederman   ns: proc files fo...
3122
  	DIR("ns",	 S_IRUSR|S_IXUGO, proc_ns_dir_inode_operations, proc_ns_dir_operations),
6ba8ed79a   Eric W. Biederman   proc: Have net sh...
3123
3124
3125
  #ifdef CONFIG_NET
  	DIR("net",        S_IRUGO|S_IXUGO, proc_net_inode_operations, proc_net_operations),
  #endif
631f9c186   Alexey Dobriyan   proc: remove '##'...
3126
  	REG("environ",   S_IRUSR, proc_environ_operations),
c53171678   Al Viro   proc: switch auxv...
3127
  	REG("auxv",      S_IRUSR, proc_auxv_operations),
631f9c186   Alexey Dobriyan   proc: remove '##'...
3128
  	ONE("status",    S_IRUGO, proc_pid_status),
35a35046e   Djalal Harouni   procfs: make /pro...
3129
  	ONE("personality", S_IRUSR, proc_pid_personality),
1c963eb13   Alexey Dobriyan   proc: convert /pr...
3130
  	ONE("limits",	 S_IRUGO, proc_pid_limits),
43ae34cb4   Ingo Molnar   sched: scheduler ...
3131
  #ifdef CONFIG_SCHED_DEBUG
631f9c186   Alexey Dobriyan   proc: remove '##'...
3132
  	REG("sched",     S_IRUGO|S_IWUSR, proc_pid_sched_operations),
43ae34cb4   Ingo Molnar   sched: scheduler ...
3133
  #endif
1b3044e39   Janis Danisevskis   procfs: fix pthre...
3134
3135
3136
  	NOD("comm",      S_IFREG|S_IRUGO|S_IWUSR,
  			 &proc_tid_comm_inode_operations,
  			 &proc_pid_set_comm_operations, {}),
ebcb67341   Roland McGrath   /proc/PID/syscall
3137
  #ifdef CONFIG_HAVE_ARCH_TRACEHOOK
09d93bd62   Alexey Dobriyan   proc: convert /pr...
3138
  	ONE("syscall",   S_IRUSR, proc_pid_syscall),
ebcb67341   Roland McGrath   /proc/PID/syscall
3139
  #endif
c2c0bb446   Alexey Dobriyan   proc: fix PAGE_SI...
3140
  	REG("cmdline",   S_IRUGO, proc_pid_cmdline_ops),
631f9c186   Alexey Dobriyan   proc: remove '##'...
3141
3142
  	ONE("stat",      S_IRUGO, proc_tid_stat),
  	ONE("statm",     S_IRUGO, proc_pid_statm),
b76437579   Siddhesh Poyarekar   procfs: mark thre...
3143
  	REG("maps",      S_IRUGO, proc_tid_maps_operations),
2e13ba54a   Iago López Galeiras   fs, proc: introdu...
3144
  #ifdef CONFIG_PROC_CHILDREN
818411616   Cyrill Gorcunov   fs, proc: introdu...
3145
3146
  	REG("children",  S_IRUGO, proc_tid_children_operations),
  #endif
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
3147
  #ifdef CONFIG_NUMA
b76437579   Siddhesh Poyarekar   procfs: mark thre...
3148
  	REG("numa_maps", S_IRUGO, proc_tid_numa_maps_operations),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
3149
  #endif
631f9c186   Alexey Dobriyan   proc: remove '##'...
3150
3151
3152
3153
3154
3155
  	REG("mem",       S_IRUSR|S_IWUSR, proc_mem_operations),
  	LNK("cwd",       proc_cwd_link),
  	LNK("root",      proc_root_link),
  	LNK("exe",       proc_exe_link),
  	REG("mounts",    S_IRUGO, proc_mounts_operations),
  	REG("mountinfo",  S_IRUGO, proc_mountinfo_operations),
1e8832811   Matt Mackall   maps4: make page ...
3156
  #ifdef CONFIG_PROC_PAGE_MONITOR
631f9c186   Alexey Dobriyan   proc: remove '##'...
3157
  	REG("clear_refs", S_IWUSR, proc_clear_refs_operations),
b76437579   Siddhesh Poyarekar   procfs: mark thre...
3158
  	REG("smaps",     S_IRUGO, proc_tid_smaps_operations),
32ed74a4b   Djalal Harouni   procfs: make /pro...
3159
  	REG("pagemap",    S_IRUSR, proc_pagemap_operations),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
3160
3161
  #endif
  #ifdef CONFIG_SECURITY
631f9c186   Alexey Dobriyan   proc: remove '##'...
3162
  	DIR("attr",      S_IRUGO|S_IXUGO, proc_attr_dir_inode_operations, proc_attr_dir_operations),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
3163
3164
  #endif
  #ifdef CONFIG_KALLSYMS
edfcd6064   Alexey Dobriyan   proc: convert /pr...
3165
  	ONE("wchan",     S_IRUGO, proc_pid_wchan),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
3166
  #endif
2ec220e27   Ken Chen   proc: add /proc/*...
3167
  #ifdef CONFIG_STACKTRACE
35a35046e   Djalal Harouni   procfs: make /pro...
3168
  	ONE("stack",      S_IRUSR, proc_pid_stack),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
3169
  #endif
5968ceced   Naveen N. Rao   sched/stat: Expos...
3170
  #ifdef CONFIG_SCHED_INFO
f6e826ca3   Alexey Dobriyan   proc: convert /pr...
3171
  	ONE("schedstat", S_IRUGO, proc_pid_schedstat),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
3172
  #endif
9745512ce   Arjan van de Ven   sched: latencytop...
3173
  #ifdef CONFIG_LATENCYTOP
631f9c186   Alexey Dobriyan   proc: remove '##'...
3174
  	REG("latency",  S_IRUGO, proc_lstats_operations),
9745512ce   Arjan van de Ven   sched: latencytop...
3175
  #endif
8793d854e   Paul Menage   Task Control Grou...
3176
  #ifdef CONFIG_PROC_PID_CPUSET
52de4779f   Zefan Li   cpuset: simplify ...
3177
  	ONE("cpuset",    S_IRUGO, proc_cpuset_show),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
3178
  #endif
a424316ca   Paul Menage   Task Control Grou...
3179
  #ifdef CONFIG_CGROUPS
006f4ac49   Zefan Li   cgroup: simplify ...
3180
  	ONE("cgroup",  S_IRUGO, proc_cgroup_show),
a424316ca   Paul Menage   Task Control Grou...
3181
  #endif
6ba51e375   Alexey Dobriyan   proc: convert /pr...
3182
  	ONE("oom_score", S_IRUGO, proc_oom_score),
fa0cbbf14   David Rientjes   mm, oom: reintrod...
3183
  	REG("oom_adj",   S_IRUGO|S_IWUSR, proc_oom_adj_operations),
a63d83f42   David Rientjes   oom: badness heur...
3184
  	REG("oom_score_adj", S_IRUGO|S_IWUSR, proc_oom_score_adj_operations),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
3185
  #ifdef CONFIG_AUDITSYSCALL
631f9c186   Alexey Dobriyan   proc: remove '##'...
3186
  	REG("loginuid",  S_IWUSR|S_IRUGO, proc_loginuid_operations),
26ec3c646   Al Viro   make sessionid pe...
3187
  	REG("sessionid",  S_IRUGO, proc_sessionid_operations),
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
3188
  #endif
f4f154fd9   Akinobu Mita   [PATCH] fault inj...
3189
  #ifdef CONFIG_FAULT_INJECTION
631f9c186   Alexey Dobriyan   proc: remove '##'...
3190
  	REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
f4f154fd9   Akinobu Mita   [PATCH] fault inj...
3191
  #endif
297c5d926   Andrea Righi   task IO accountin...
3192
  #ifdef CONFIG_TASK_IO_ACCOUNTING
19aadc98d   Alexey Dobriyan   proc: convert /pr...
3193
  	ONE("io",	S_IRUSR, proc_tid_io_accounting),
297c5d926   Andrea Righi   task IO accountin...
3194
  #endif
f133ecca9   Chris Metcalf   arch/tile: more /...
3195
  #ifdef CONFIG_HARDWALL
d962c1448   Alexey Dobriyan   proc: convert /pr...
3196
  	ONE("hardwall",   S_IRUGO, proc_pid_hardwall),
f133ecca9   Chris Metcalf   arch/tile: more /...
3197
  #endif
22d917d80   Eric W. Biederman   userns: Rework th...
3198
3199
3200
  #ifdef CONFIG_USER_NS
  	REG("uid_map",    S_IRUGO|S_IWUSR, proc_uid_map_operations),
  	REG("gid_map",    S_IRUGO|S_IWUSR, proc_gid_map_operations),
f76d207a6   Eric W. Biederman   userns: Add kproj...
3201
  	REG("projid_map", S_IRUGO|S_IWUSR, proc_projid_map_operations),
9cc46516d   Eric W. Biederman   userns: Add a kno...
3202
  	REG("setgroups",  S_IRUGO|S_IWUSR, proc_setgroups_operations),
22d917d80   Eric W. Biederman   userns: Rework th...
3203
  #endif
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
3204
  };
f0c3b5093   Al Viro   [readdir] convert...
3205
  static int proc_tid_base_readdir(struct file *file, struct dir_context *ctx)
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
3206
  {
f0c3b5093   Al Viro   [readdir] convert...
3207
3208
  	return proc_pident_readdir(file, ctx,
  				   tid_base_stuff, ARRAY_SIZE(tid_base_stuff));
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
3209
  }
00cd8dd3b   Al Viro   stop passing name...
3210
3211
  static struct dentry *proc_tid_base_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
  {
7bcd6b0ef   Eric W. Biederman   [PATCH] proc: rem...
3212
3213
  	return proc_pident_lookup(dir, dentry,
  				  tid_base_stuff, ARRAY_SIZE(tid_base_stuff));
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
3214
  }
00977a59b   Arjan van de Ven   [PATCH] mark stru...
3215
  static const struct file_operations proc_tid_base_operations = {
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
3216
  	.read		= generic_read_dir,
f50752eaa   Al Viro   switch all procfs...
3217
3218
  	.iterate_shared	= proc_tid_base_readdir,
  	.llseek		= generic_file_llseek,
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
3219
  };
c5ef1c42c   Arjan van de Ven   [PATCH] mark stru...
3220
  static const struct inode_operations proc_tid_base_inode_operations = {
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
3221
3222
3223
3224
  	.lookup		= proc_tid_base_lookup,
  	.getattr	= pid_getattr,
  	.setattr	= proc_setattr,
  };
c52a47ace   Al Viro   proc_fill_cache()...
3225
  static int proc_task_instantiate(struct inode *dir,
c5141e6d6   Eric Dumazet   procfs: reorder s...
3226
  	struct dentry *dentry, struct task_struct *task, const void *ptr)
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
3227
  {
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
3228
  	struct inode *inode;
61a287840   Eric W. Biederman   [PATCH] proc: Rem...
3229
  	inode = proc_pid_make_inode(dir->i_sb, task);
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
3230
3231
3232
3233
3234
3235
3236
  
  	if (!inode)
  		goto out;
  	inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
  	inode->i_op = &proc_tid_base_inode_operations;
  	inode->i_fop = &proc_tid_base_operations;
  	inode->i_flags|=S_IMMUTABLE;
aed541759   Vegard Nossum   proc: calculate t...
3237

bfe868486   Miklos Szeredi   filesystems: add ...
3238
3239
  	set_nlink(inode, 2 + pid_entry_count_dirs(tid_base_stuff,
  						  ARRAY_SIZE(tid_base_stuff)));
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
3240

fb045adb9   Nick Piggin   fs: dcache reduce...
3241
  	d_set_d_op(dentry, &pid_dentry_operations);
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
3242
3243
3244
  
  	d_add(dentry, inode);
  	/* Close the race of the process dying before we return the dentry */
0b728e191   Al Viro   stop passing name...
3245
  	if (pid_revalidate(dentry, 0))
c52a47ace   Al Viro   proc_fill_cache()...
3246
  		return 0;
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
3247
  out:
c52a47ace   Al Viro   proc_fill_cache()...
3248
  	return -ENOENT;
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
3249
  }
00cd8dd3b   Al Viro   stop passing name...
3250
  static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags)
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
3251
  {
c52a47ace   Al Viro   proc_fill_cache()...
3252
  	int result = -ENOENT;
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
3253
3254
  	struct task_struct *task;
  	struct task_struct *leader = get_proc_task(dir);
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
3255
  	unsigned tid;
b488893a3   Pavel Emelyanov   pid namespaces: c...
3256
  	struct pid_namespace *ns;
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
3257
3258
3259
  
  	if (!leader)
  		goto out_no_task;
dbcdb5044   Alexey Dobriyan   proc: add and rem...
3260
  	tid = name_to_int(&dentry->d_name);
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
3261
3262
  	if (tid == ~0U)
  		goto out;
b488893a3   Pavel Emelyanov   pid namespaces: c...
3263
  	ns = dentry->d_sb->s_fs_info;
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
3264
  	rcu_read_lock();
b488893a3   Pavel Emelyanov   pid namespaces: c...
3265
  	task = find_task_by_pid_ns(tid, ns);
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
3266
3267
3268
3269
3270
  	if (task)
  		get_task_struct(task);
  	rcu_read_unlock();
  	if (!task)
  		goto out;
bac0abd61   Pavel Emelyanov   Isolate some expl...
3271
  	if (!same_thread_group(leader, task))
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
3272
  		goto out_drop_task;
444ceed8d   Eric W. Biederman   [PATCH] proc: Fac...
3273
  	result = proc_task_instantiate(dir, dentry, task, NULL);
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
3274
3275
3276
3277
3278
  out_drop_task:
  	put_task_struct(task);
  out:
  	put_task_struct(leader);
  out_no_task:
c52a47ace   Al Viro   proc_fill_cache()...
3279
  	return ERR_PTR(result);
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
3280
3281
3282
  }
  
  /*
0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
   * Find the first tid of a thread group to return to user space.
   *
   * Usually this is just the thread group leader, but if the users
   * buffer was too small or there was a seek into the middle of the
   * directory we have more work todo.
   *
   * In the case of a short read we start with find_task_by_pid.
   *
   * In the case of a seek we start with the leader and walk nr
   * threads past it.
   */
9f6e963f0   Oleg Nesterov   proc: fix ->f_pos...
3294
3295
  static struct task_struct *first_tid(struct pid *pid, int tid, loff_t f_pos,
  					struct pid_namespace *ns)
0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
3296
  {
d855a4b79   Oleg Nesterov   proc: don't (ab)u...
3297
  	struct task_struct *pos, *task;
9f6e963f0   Oleg Nesterov   proc: fix ->f_pos...
3298
3299
3300
3301
  	unsigned long nr = f_pos;
  
  	if (nr != f_pos)	/* 32bit overflow? */
  		return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3302

cc288738c   Eric W. Biederman   [PATCH] proc: Rem...
3303
  	rcu_read_lock();
d855a4b79   Oleg Nesterov   proc: don't (ab)u...
3304
3305
3306
3307
3308
  	task = pid_task(pid, PIDTYPE_PID);
  	if (!task)
  		goto fail;
  
  	/* Attempt to start with the tid of a thread */
9f6e963f0   Oleg Nesterov   proc: fix ->f_pos...
3309
  	if (tid && nr) {
b488893a3   Pavel Emelyanov   pid namespaces: c...
3310
  		pos = find_task_by_pid_ns(tid, ns);
d855a4b79   Oleg Nesterov   proc: don't (ab)u...
3311
  		if (pos && same_thread_group(pos, task))
a872ff0cb   Oleg Nesterov   [PATCH] simplify/...
3312
  			goto found;
0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
3313
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3314

0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
3315
  	/* If nr exceeds the number of threads there is nothing todo */
9f6e963f0   Oleg Nesterov   proc: fix ->f_pos...
3316
  	if (nr >= get_nr_threads(task))
c986c14a6   Oleg Nesterov   proc: change firs...
3317
  		goto fail;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3318

a872ff0cb   Oleg Nesterov   [PATCH] simplify/...
3319
3320
  	/* If we haven't found our starting place yet start
  	 * with the leader and walk nr threads forward.
0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
3321
  	 */
d855a4b79   Oleg Nesterov   proc: don't (ab)u...
3322
  	pos = task = task->group_leader;
c986c14a6   Oleg Nesterov   proc: change firs...
3323
  	do {
9f6e963f0   Oleg Nesterov   proc: fix ->f_pos...
3324
  		if (!nr--)
c986c14a6   Oleg Nesterov   proc: change firs...
3325
  			goto found;
d855a4b79   Oleg Nesterov   proc: don't (ab)u...
3326
  	} while_each_thread(task, pos);
c986c14a6   Oleg Nesterov   proc: change firs...
3327
3328
3329
  fail:
  	pos = NULL;
  	goto out;
a872ff0cb   Oleg Nesterov   [PATCH] simplify/...
3330
3331
3332
  found:
  	get_task_struct(pos);
  out:
cc288738c   Eric W. Biederman   [PATCH] proc: Rem...
3333
  	rcu_read_unlock();
0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
  	return pos;
  }
  
  /*
   * Find the next thread in the thread list.
   * Return NULL if there is an error or no next thread.
   *
   * The reference to the input task_struct is released.
   */
  static struct task_struct *next_tid(struct task_struct *start)
  {
c1df7fb88   Oleg Nesterov   [PATCH] cleanup n...
3345
  	struct task_struct *pos = NULL;
cc288738c   Eric W. Biederman   [PATCH] proc: Rem...
3346
  	rcu_read_lock();
c1df7fb88   Oleg Nesterov   [PATCH] cleanup n...
3347
  	if (pid_alive(start)) {
0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
3348
  		pos = next_thread(start);
c1df7fb88   Oleg Nesterov   [PATCH] cleanup n...
3349
3350
3351
3352
3353
  		if (thread_group_leader(pos))
  			pos = NULL;
  		else
  			get_task_struct(pos);
  	}
cc288738c   Eric W. Biederman   [PATCH] proc: Rem...
3354
  	rcu_read_unlock();
0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
3355
3356
  	put_task_struct(start);
  	return pos;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3357
3358
3359
  }
  
  /* for the /proc/TGID/task/ directories */
f0c3b5093   Al Viro   [readdir] convert...
3360
  static int proc_task_readdir(struct file *file, struct dir_context *ctx)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3361
  {
d855a4b79   Oleg Nesterov   proc: don't (ab)u...
3362
3363
  	struct inode *inode = file_inode(file);
  	struct task_struct *task;
b488893a3   Pavel Emelyanov   pid namespaces: c...
3364
  	struct pid_namespace *ns;
f0c3b5093   Al Viro   [readdir] convert...
3365
  	int tid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3366

d855a4b79   Oleg Nesterov   proc: don't (ab)u...
3367
  	if (proc_inode_is_dead(inode))
f0c3b5093   Al Viro   [readdir] convert...
3368
  		return -ENOENT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3369

f0c3b5093   Al Viro   [readdir] convert...
3370
  	if (!dir_emit_dots(file, ctx))
d855a4b79   Oleg Nesterov   proc: don't (ab)u...
3371
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3372

0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
3373
3374
3375
  	/* f_version caches the tgid value that the last readdir call couldn't
  	 * return. lseek aka telldir automagically resets f_version to 0.
  	 */
3aa3377fb   Al Viro   procfs: get rid o...
3376
  	ns = inode->i_sb->s_fs_info;
f0c3b5093   Al Viro   [readdir] convert...
3377
3378
  	tid = (int)file->f_version;
  	file->f_version = 0;
d855a4b79   Oleg Nesterov   proc: don't (ab)u...
3379
  	for (task = first_tid(proc_pid(inode), tid, ctx->pos - 2, ns);
0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
3380
  	     task;
f0c3b5093   Al Viro   [readdir] convert...
3381
3382
3383
  	     task = next_tid(task), ctx->pos++) {
  		char name[PROC_NUMBUF];
  		int len;
b488893a3   Pavel Emelyanov   pid namespaces: c...
3384
  		tid = task_pid_nr_ns(task, ns);
f0c3b5093   Al Viro   [readdir] convert...
3385
3386
3387
  		len = snprintf(name, sizeof(name), "%d", tid);
  		if (!proc_fill_cache(file, ctx, name, len,
  				proc_task_instantiate, task, NULL)) {
0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
3388
3389
  			/* returning this tgid failed, save it as the first
  			 * pid for the next readir call */
f0c3b5093   Al Viro   [readdir] convert...
3390
  			file->f_version = (u64)tid;
0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
3391
  			put_task_struct(task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3392
  			break;
0bc58a910   Eric W. Biederman   [PATCH] proc: ref...
3393
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3394
  	}
d855a4b79   Oleg Nesterov   proc: don't (ab)u...
3395

f0c3b5093   Al Viro   [readdir] convert...
3396
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3397
  }
6e66b52bf   Eric W. Biederman   [PATCH] proc: Fix...
3398
3399
3400
  
  static int proc_task_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
  {
2b0143b5c   David Howells   VFS: normal files...
3401
  	struct inode *inode = d_inode(dentry);
99f895518   Eric W. Biederman   [PATCH] proc: don...
3402
  	struct task_struct *p = get_proc_task(inode);
6e66b52bf   Eric W. Biederman   [PATCH] proc: Fix...
3403
  	generic_fillattr(inode, stat);
99f895518   Eric W. Biederman   [PATCH] proc: don...
3404
  	if (p) {
99f895518   Eric W. Biederman   [PATCH] proc: don...
3405
  		stat->nlink += get_nr_threads(p);
99f895518   Eric W. Biederman   [PATCH] proc: don...
3406
  		put_task_struct(p);
6e66b52bf   Eric W. Biederman   [PATCH] proc: Fix...
3407
3408
3409
3410
  	}
  
  	return 0;
  }
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
3411

c5ef1c42c   Arjan van de Ven   [PATCH] mark stru...
3412
  static const struct inode_operations proc_task_inode_operations = {
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
3413
3414
3415
  	.lookup		= proc_task_lookup,
  	.getattr	= proc_task_getattr,
  	.setattr	= proc_setattr,
0499680a4   Vasiliy Kulikov   procfs: add hidep...
3416
  	.permission	= proc_pid_permission,
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
3417
  };
00977a59b   Arjan van de Ven   [PATCH] mark stru...
3418
  static const struct file_operations proc_task_operations = {
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
3419
  	.read		= generic_read_dir,
f50752eaa   Al Viro   switch all procfs...
3420
3421
  	.iterate_shared	= proc_task_readdir,
  	.llseek		= generic_file_llseek,
28a6d6717   Eric W. Biederman   [PATCH] proc: reo...
3422
  };