Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0
2 : : /*
3 : : * linux/fs/proc/array.c
4 : : *
5 : : * Copyright (C) 1992 by Linus Torvalds
6 : : * based on ideas by Darren Senn
7 : : *
8 : : * Fixes:
9 : : * Michael. K. Johnson: stat,statm extensions.
10 : : * <johnsonm@stolaf.edu>
11 : : *
12 : : * Pauline Middelink : Made cmdline,envline only break at '\0's, to
13 : : * make sure SET_PROCTITLE works. Also removed
14 : : * bad '!' which forced address recalculation for
15 : : * EVERY character on the current page.
16 : : * <middelin@polyware.iaf.nl>
17 : : *
18 : : * Danny ter Haar : added cpuinfo
19 : : * <dth@cistron.nl>
20 : : *
21 : : * Alessandro Rubini : profile extension.
22 : : * <rubini@ipvvis.unipv.it>
23 : : *
24 : : * Jeff Tranter : added BogoMips field to cpuinfo
25 : : * <Jeff_Tranter@Mitel.COM>
26 : : *
27 : : * Bruno Haible : remove 4K limit for the maps file
28 : : * <haible@ma2s2.mathematik.uni-karlsruhe.de>
29 : : *
30 : : * Yves Arrouye : remove removal of trailing spaces in get_array.
31 : : * <Yves.Arrouye@marin.fdn.fr>
32 : : *
33 : : * Jerome Forissier : added per-CPU time information to /proc/stat
34 : : * and /proc/<pid>/cpu extension
35 : : * <forissier@isia.cma.fr>
36 : : * - Incorporation and non-SMP safe operation
37 : : * of forissier patch in 2.1.78 by
38 : : * Hans Marcus <crowbar@concepts.nl>
39 : : *
40 : : * aeb@cwi.nl : /proc/partitions
41 : : *
42 : : *
43 : : * Alan Cox : security fixes.
44 : : * <alan@lxorguk.ukuu.org.uk>
45 : : *
46 : : * Al Viro : safe handling of mm_struct
47 : : *
48 : : * Gerhard Wichert : added BIGMEM support
49 : : * Siemens AG <Gerhard.Wichert@pdb.siemens.de>
50 : : *
51 : : * Al Viro & Jeff Garzik : moved most of the thing into base.c and
52 : : * : proc_misc.c. The rest may eventually go into
53 : : * : base.c too.
54 : : */
55 : :
56 : : #include <linux/types.h>
57 : : #include <linux/errno.h>
58 : : #include <linux/time.h>
59 : : #include <linux/kernel.h>
60 : : #include <linux/kernel_stat.h>
61 : : #include <linux/tty.h>
62 : : #include <linux/string.h>
63 : : #include <linux/mman.h>
64 : : #include <linux/sched/mm.h>
65 : : #include <linux/sched/numa_balancing.h>
66 : : #include <linux/sched/task_stack.h>
67 : : #include <linux/sched/task.h>
68 : : #include <linux/sched/cputime.h>
69 : : #include <linux/proc_fs.h>
70 : : #include <linux/ioport.h>
71 : : #include <linux/uaccess.h>
72 : : #include <linux/io.h>
73 : : #include <linux/mm.h>
74 : : #include <linux/hugetlb.h>
75 : : #include <linux/pagemap.h>
76 : : #include <linux/swap.h>
77 : : #include <linux/smp.h>
78 : : #include <linux/signal.h>
79 : : #include <linux/highmem.h>
80 : : #include <linux/file.h>
81 : : #include <linux/fdtable.h>
82 : : #include <linux/times.h>
83 : : #include <linux/cpuset.h>
84 : : #include <linux/rcupdate.h>
85 : : #include <linux/delayacct.h>
86 : : #include <linux/seq_file.h>
87 : : #include <linux/pid_namespace.h>
88 : : #include <linux/prctl.h>
89 : : #include <linux/ptrace.h>
90 : : #include <linux/tracehook.h>
91 : : #include <linux/string_helpers.h>
92 : : #include <linux/user_namespace.h>
93 : : #include <linux/fs_struct.h>
94 : :
95 : : #include <asm/pgtable.h>
96 : : #include <asm/processor.h>
97 : : #include "internal.h"
98 : :
99 : 89403 : void proc_task_name(struct seq_file *m, struct task_struct *p, bool escape)
100 : : {
101 : : char *buf;
102 : : size_t size;
103 : : char tcomm[64];
104 : : int ret;
105 : :
106 [ + + ]: 89403 : if (p->flags & PF_WQ_WORKER)
107 : 7778 : wq_worker_comm(tcomm, sizeof(tcomm), p);
108 : : else
109 : 81625 : __get_task_comm(tcomm, sizeof(tcomm), p);
110 : :
111 : 89446 : size = seq_get_buf(m, &buf);
112 [ + + ]: 89406 : if (escape) {
113 : 18709 : ret = string_escape_str(tcomm, buf, size,
114 : : ESCAPE_SPACE | ESCAPE_SPECIAL, "\n\\");
115 [ - + ]: 18709 : if (ret >= size)
116 : : ret = -1;
117 : : } else {
118 : 70697 : ret = strscpy(buf, tcomm, size);
119 : : }
120 : :
121 : 89452 : seq_commit(m, ret);
122 : 89451 : }
123 : :
124 : : /*
125 : : * The task state array is a strange "bitmap" of
126 : : * reasons to sleep. Thus "running" is zero, and
127 : : * you can test for combinations of others with
128 : : * simple bit tests.
129 : : */
130 : : static const char * const task_state_array[] = {
131 : :
132 : : /* states in TASK_REPORT: */
133 : : "R (running)", /* 0x00 */
134 : : "S (sleeping)", /* 0x01 */
135 : : "D (disk sleep)", /* 0x02 */
136 : : "T (stopped)", /* 0x04 */
137 : : "t (tracing stop)", /* 0x08 */
138 : : "X (dead)", /* 0x10 */
139 : : "Z (zombie)", /* 0x20 */
140 : : "P (parked)", /* 0x40 */
141 : :
142 : : /* states beyond TASK_REPORT: */
143 : : "I (idle)", /* 0x80 */
144 : : };
145 : :
146 : : static inline const char *get_task_state(struct task_struct *tsk)
147 : : {
148 : : BUILD_BUG_ON(1 + ilog2(TASK_REPORT_MAX) != ARRAY_SIZE(task_state_array));
149 : 54035 : return task_state_array[task_state_index(tsk)];
150 : : }
151 : :
152 : 18708 : static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
153 : : struct pid *pid, struct task_struct *p)
154 : : {
155 : : struct user_namespace *user_ns = seq_user_ns(m);
156 : : struct group_info *group_info;
157 : : int g, umask = -1;
158 : : struct task_struct *tracer;
159 : : const struct cred *cred;
160 : : pid_t ppid, tpid = 0, tgid, ngid;
161 : : unsigned int max_fds = 0;
162 : :
163 : : rcu_read_lock();
164 : : ppid = pid_alive(p) ?
165 [ + - ]: 37416 : task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0;
166 : :
167 : : tracer = ptrace_parent(p);
168 [ - + ]: 18709 : if (tracer)
169 : : tpid = task_pid_nr_ns(tracer, ns);
170 : :
171 : : tgid = task_tgid_nr_ns(p, ns);
172 : : ngid = task_numa_group_id(p);
173 : 18709 : cred = get_task_cred(p);
174 : :
175 : : task_lock(p);
176 [ + + ]: 18709 : if (p->fs)
177 : 18150 : umask = p->fs->umask;
178 [ + + ]: 18709 : if (p->files)
179 : 18149 : max_fds = files_fdtable(p->files)->max_fds;
180 : : task_unlock(p);
181 : : rcu_read_unlock();
182 : :
183 [ + + ]: 18709 : if (umask >= 0)
184 : 18150 : seq_printf(m, "Umask:\t%#04o\n", umask);
185 : 18709 : seq_puts(m, "State:\t");
186 : 18709 : seq_puts(m, get_task_state(p));
187 : :
188 : 18709 : seq_put_decimal_ull(m, "\nTgid:\t", tgid);
189 : 18709 : seq_put_decimal_ull(m, "\nNgid:\t", ngid);
190 : 18709 : seq_put_decimal_ull(m, "\nPid:\t", pid_nr_ns(pid, ns));
191 : 18709 : seq_put_decimal_ull(m, "\nPPid:\t", ppid);
192 : 18709 : seq_put_decimal_ull(m, "\nTracerPid:\t", tpid);
193 : 18709 : seq_put_decimal_ull(m, "\nUid:\t", from_kuid_munged(user_ns, cred->uid));
194 : 18709 : seq_put_decimal_ull(m, "\t", from_kuid_munged(user_ns, cred->euid));
195 : 18709 : seq_put_decimal_ull(m, "\t", from_kuid_munged(user_ns, cred->suid));
196 : 18709 : seq_put_decimal_ull(m, "\t", from_kuid_munged(user_ns, cred->fsuid));
197 : 18709 : seq_put_decimal_ull(m, "\nGid:\t", from_kgid_munged(user_ns, cred->gid));
198 : 18709 : seq_put_decimal_ull(m, "\t", from_kgid_munged(user_ns, cred->egid));
199 : 18709 : seq_put_decimal_ull(m, "\t", from_kgid_munged(user_ns, cred->sgid));
200 : 18709 : seq_put_decimal_ull(m, "\t", from_kgid_munged(user_ns, cred->fsgid));
201 : 18709 : seq_put_decimal_ull(m, "\nFDSize:\t", max_fds);
202 : :
203 : 18709 : seq_puts(m, "\nGroups:\t");
204 : 18708 : group_info = cred->group_info;
205 [ + + ]: 57427 : for (g = 0; g < group_info->ngroups; g++)
206 [ + + ]: 77438 : seq_put_decimal_ull(m, g ? " " : "",
207 : 38719 : from_kgid_munged(user_ns, group_info->gid[g]));
208 : 18708 : put_cred(cred);
209 : : /* Trailing space shouldn't have been added in the first place. */
210 : 18709 : seq_putc(m, ' ');
211 : :
212 : : #ifdef CONFIG_PID_NS
213 : 18709 : seq_puts(m, "\nNStgid:");
214 [ + + ]: 37416 : for (g = ns->level; g <= pid->level; g++)
215 : 37417 : seq_put_decimal_ull(m, "\t", task_tgid_nr_ns(p, pid->numbers[g].ns));
216 : 18708 : seq_puts(m, "\nNSpid:");
217 [ + + ]: 37417 : for (g = ns->level; g <= pid->level; g++)
218 : 37417 : seq_put_decimal_ull(m, "\t", task_pid_nr_ns(p, pid->numbers[g].ns));
219 : 18709 : seq_puts(m, "\nNSpgid:");
220 [ + + ]: 37414 : for (g = ns->level; g <= pid->level; g++)
221 : 37413 : seq_put_decimal_ull(m, "\t", task_pgrp_nr_ns(p, pid->numbers[g].ns));
222 : 18708 : seq_puts(m, "\nNSsid:");
223 [ + + ]: 37417 : for (g = ns->level; g <= pid->level; g++)
224 : 37416 : seq_put_decimal_ull(m, "\t", task_session_nr_ns(p, pid->numbers[g].ns));
225 : : #endif
226 : 18709 : seq_putc(m, '\n');
227 : 18708 : }
228 : :
229 : 93545 : void render_sigset_t(struct seq_file *m, const char *header,
230 : : sigset_t *set)
231 : : {
232 : : int i;
233 : :
234 : 93545 : seq_puts(m, header);
235 : :
236 : : i = _NSIG;
237 : : do {
238 : : int x = 0;
239 : :
240 : 1496675 : i -= 4;
241 [ + + ]: 1496675 : if (sigismember(set, i+1)) x |= 1;
242 [ + + ]: 1496675 : if (sigismember(set, i+2)) x |= 2;
243 [ + + ]: 1496675 : if (sigismember(set, i+3)) x |= 4;
244 [ + + ]: 1496675 : if (sigismember(set, i+4)) x |= 8;
245 : 1496675 : seq_putc(m, hex_asc[x]);
246 [ + + ]: 1496677 : } while (i >= 4);
247 : :
248 : 93544 : seq_putc(m, '\n');
249 : 93545 : }
250 : :
251 : 54034 : static void collect_sigign_sigcatch(struct task_struct *p, sigset_t *ign,
252 : : sigset_t *catch)
253 : : {
254 : : struct k_sigaction *k;
255 : : int i;
256 : :
257 : 54034 : k = p->sighand->action;
258 [ + + ]: 3509971 : for (i = 1; i <= _NSIG; ++i, ++k) {
259 [ + + ]: 3455937 : if (k->sa.sa_handler == SIG_IGN)
260 : : sigaddset(ign, i);
261 [ + + ]: 2565586 : else if (k->sa.sa_handler != SIG_DFL)
262 : : sigaddset(catch, i);
263 : : }
264 : 54034 : }
265 : :
266 : 18709 : static inline void task_sig(struct seq_file *m, struct task_struct *p)
267 : : {
268 : : unsigned long flags;
269 : : sigset_t pending, shpending, blocked, ignored, caught;
270 : : int num_threads = 0;
271 : : unsigned int qsize = 0;
272 : : unsigned long qlim = 0;
273 : :
274 : : sigemptyset(&pending);
275 : : sigemptyset(&shpending);
276 : : sigemptyset(&blocked);
277 : : sigemptyset(&ignored);
278 : : sigemptyset(&caught);
279 : :
280 [ + - ]: 18709 : if (lock_task_sighand(p, &flags)) {
281 : 18709 : pending = p->pending.signal;
282 : 18709 : shpending = p->signal->shared_pending.signal;
283 : 18709 : blocked = p->blocked;
284 : 18709 : collect_sigign_sigcatch(p, &ignored, &caught);
285 : : num_threads = get_nr_threads(p);
286 : : rcu_read_lock(); /* FIXME: is this correct? */
287 : 18709 : qsize = atomic_read(&__task_cred(p)->user->sigpending);
288 : : rcu_read_unlock();
289 : : qlim = task_rlimit(p, RLIMIT_SIGPENDING);
290 : : unlock_task_sighand(p, &flags);
291 : : }
292 : :
293 : 18709 : seq_put_decimal_ull(m, "Threads:\t", num_threads);
294 : 18709 : seq_put_decimal_ull(m, "\nSigQ:\t", qsize);
295 : 18709 : seq_put_decimal_ull(m, "/", qlim);
296 : :
297 : : /* render them all */
298 : 18709 : render_sigset_t(m, "\nSigPnd:\t", &pending);
299 : 18707 : render_sigset_t(m, "ShdPnd:\t", &shpending);
300 : 18709 : render_sigset_t(m, "SigBlk:\t", &blocked);
301 : 18709 : render_sigset_t(m, "SigIgn:\t", &ignored);
302 : 18708 : render_sigset_t(m, "SigCgt:\t", &caught);
303 : 18707 : }
304 : :
305 : 93543 : static void render_cap_t(struct seq_file *m, const char *header,
306 : : kernel_cap_t *a)
307 : : {
308 : : unsigned __capi;
309 : :
310 : 93543 : seq_puts(m, header);
311 [ + + ]: 280618 : CAP_FOR_EACH_U32(__capi) {
312 : 187076 : seq_put_hex_ll(m, NULL,
313 : 187076 : a->cap[CAP_LAST_U32 - __capi], 8);
314 : : }
315 : 93542 : seq_putc(m, '\n');
316 : 93545 : }
317 : :
318 : 18709 : static inline void task_cap(struct seq_file *m, struct task_struct *p)
319 : : {
320 : : const struct cred *cred;
321 : : kernel_cap_t cap_inheritable, cap_permitted, cap_effective,
322 : : cap_bset, cap_ambient;
323 : :
324 : : rcu_read_lock();
325 : 18709 : cred = __task_cred(p);
326 : 18709 : cap_inheritable = cred->cap_inheritable;
327 : 18709 : cap_permitted = cred->cap_permitted;
328 : 18709 : cap_effective = cred->cap_effective;
329 : 18709 : cap_bset = cred->cap_bset;
330 : 18709 : cap_ambient = cred->cap_ambient;
331 : : rcu_read_unlock();
332 : :
333 : 18704 : render_cap_t(m, "CapInh:\t", &cap_inheritable);
334 : 18705 : render_cap_t(m, "CapPrm:\t", &cap_permitted);
335 : 18709 : render_cap_t(m, "CapEff:\t", &cap_effective);
336 : 18709 : render_cap_t(m, "CapBnd:\t", &cap_bset);
337 : 18708 : render_cap_t(m, "CapAmb:\t", &cap_ambient);
338 : 18709 : }
339 : :
340 : 18706 : static inline void task_seccomp(struct seq_file *m, struct task_struct *p)
341 : : {
342 : 18706 : seq_put_decimal_ull(m, "NoNewPrivs:\t", task_no_new_privs(p));
343 : : #ifdef CONFIG_SECCOMP
344 : 18709 : seq_put_decimal_ull(m, "\nSeccomp:\t", p->seccomp.mode);
345 : : #endif
346 : 18709 : seq_puts(m, "\nSpeculation_Store_Bypass:\t");
347 [ + - - - : 18709 : switch (arch_prctl_spec_ctrl_get(p, PR_SPEC_STORE_BYPASS)) {
- - - ]
348 : : case -EINVAL:
349 : 18706 : seq_puts(m, "unknown");
350 : 18709 : break;
351 : : case PR_SPEC_NOT_AFFECTED:
352 : 0 : seq_puts(m, "not vulnerable");
353 : 0 : break;
354 : : case PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE:
355 : 0 : seq_puts(m, "thread force mitigated");
356 : 0 : break;
357 : : case PR_SPEC_PRCTL | PR_SPEC_DISABLE:
358 : 0 : seq_puts(m, "thread mitigated");
359 : 0 : break;
360 : : case PR_SPEC_PRCTL | PR_SPEC_ENABLE:
361 : 0 : seq_puts(m, "thread vulnerable");
362 : 0 : break;
363 : : case PR_SPEC_DISABLE:
364 : 0 : seq_puts(m, "globally mitigated");
365 : 0 : break;
366 : : default:
367 : 0 : seq_puts(m, "vulnerable");
368 : 0 : break;
369 : : }
370 : 18709 : seq_putc(m, '\n');
371 : 18707 : }
372 : :
373 : 18709 : static inline void task_context_switch_counts(struct seq_file *m,
374 : : struct task_struct *p)
375 : : {
376 : 18709 : seq_put_decimal_ull(m, "voluntary_ctxt_switches:\t", p->nvcsw);
377 : 18708 : seq_put_decimal_ull(m, "\nnonvoluntary_ctxt_switches:\t", p->nivcsw);
378 : 18707 : seq_putc(m, '\n');
379 : 18706 : }
380 : :
381 : 18707 : static void task_cpus_allowed(struct seq_file *m, struct task_struct *task)
382 : : {
383 : 37414 : seq_printf(m, "Cpus_allowed:\t%*pb\n",
384 : 18707 : cpumask_pr_args(task->cpus_ptr));
385 : 37418 : seq_printf(m, "Cpus_allowed_list:\t%*pbl\n",
386 : 18709 : cpumask_pr_args(task->cpus_ptr));
387 : 18705 : }
388 : :
389 : 18012 : static inline void task_core_dumping(struct seq_file *m, struct mm_struct *mm)
390 : : {
391 : 18012 : seq_put_decimal_ull(m, "CoreDumping:\t", !!mm->core_state);
392 : 18012 : seq_putc(m, '\n');
393 : 18011 : }
394 : :
395 : : static inline void task_thp_status(struct seq_file *m, struct mm_struct *mm)
396 : : {
397 : : bool thp_enabled = IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE);
398 : :
399 : : if (thp_enabled)
400 : : thp_enabled = !test_bit(MMF_DISABLE_THP, &mm->flags);
401 : 18013 : seq_printf(m, "THP_enabled:\t%d\n", thp_enabled);
402 : : }
403 : :
404 : 18709 : int proc_pid_status(struct seq_file *m, struct pid_namespace *ns,
405 : : struct pid *pid, struct task_struct *task)
406 : : {
407 : 18709 : struct mm_struct *mm = get_task_mm(task);
408 : :
409 : 18709 : seq_puts(m, "Name:\t");
410 : 18709 : proc_task_name(m, task, true);
411 : 18709 : seq_putc(m, '\n');
412 : :
413 : 18708 : task_state(m, ns, pid, task);
414 : :
415 [ + + ]: 18709 : if (mm) {
416 : 18014 : task_mem(m, mm);
417 : 18012 : task_core_dumping(m, mm);
418 : : task_thp_status(m, mm);
419 : 18014 : mmput(mm);
420 : : }
421 : 18709 : task_sig(m, task);
422 : 18707 : task_cap(m, task);
423 : 18706 : task_seccomp(m, task);
424 : 18703 : task_cpus_allowed(m, task);
425 : 18706 : cpuset_task_status_allowed(m, task);
426 : 18708 : task_context_switch_counts(m, task);
427 : 18709 : return 0;
428 : : }
429 : :
430 : 35326 : static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
431 : : struct pid *pid, struct task_struct *task, int whole)
432 : : {
433 : : unsigned long vsize, eip, esp, wchan = 0;
434 : : int priority, nice;
435 : : int tty_pgrp = -1, tty_nr = 0;
436 : : sigset_t sigign, sigcatch;
437 : : char state;
438 : : pid_t ppid = 0, pgid = -1, sid = -1;
439 : : int num_threads = 0;
440 : : int permitted;
441 : : struct mm_struct *mm;
442 : : unsigned long long start_time;
443 : : unsigned long cmin_flt = 0, cmaj_flt = 0;
444 : : unsigned long min_flt = 0, maj_flt = 0;
445 : : u64 cutime, cstime, utime, stime;
446 : : u64 cgtime, gtime;
447 : : unsigned long rsslim = 0;
448 : : unsigned long flags;
449 : :
450 : 35326 : state = *get_task_state(task);
451 : : vsize = eip = esp = 0;
452 : 35326 : permitted = ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS | PTRACE_MODE_NOAUDIT);
453 : 35328 : mm = get_task_mm(task);
454 [ + + ]: 35325 : if (mm) {
455 : 21958 : vsize = task_vsize(mm);
456 : : /*
457 : : * esp and eip are intentionally zeroed out. There is no
458 : : * non-racy way to read them without freezing the task.
459 : : * Programs that need reliable values can use ptrace(2).
460 : : *
461 : : * The only exception is if the task is core dumping because
462 : : * a program is not able to use ptrace(2) in that case. It is
463 : : * safe because the task has stopped executing permanently.
464 : : */
465 [ + - - + ]: 21946 : if (permitted && (task->flags & (PF_EXITING|PF_DUMPCORE))) {
466 [ # # ]: 0 : if (try_get_task_stack(task)) {
467 : 0 : eip = KSTK_EIP(task);
468 : 0 : esp = KSTK_ESP(task);
469 : : put_task_stack(task);
470 : : }
471 : : }
472 : : }
473 : :
474 : : sigemptyset(&sigign);
475 : : sigemptyset(&sigcatch);
476 : 35313 : cutime = cstime = utime = stime = 0;
477 : : cgtime = gtime = 0;
478 : :
479 [ + + ]: 35327 : if (lock_task_sighand(task, &flags)) {
480 : 35308 : struct signal_struct *sig = task->signal;
481 : :
482 [ + + ]: 35308 : if (sig->tty) {
483 : 414 : struct pid *pgrp = tty_get_pgrp(sig->tty);
484 : 414 : tty_pgrp = pid_nr_ns(pgrp, ns);
485 : 414 : put_pid(pgrp);
486 : 828 : tty_nr = new_encode_dev(tty_devnum(sig->tty));
487 : : }
488 : :
489 : : num_threads = get_nr_threads(task);
490 : 35308 : collect_sigign_sigcatch(task, &sigign, &sigcatch);
491 : :
492 : 35314 : cmin_flt = sig->cmin_flt;
493 : 35314 : cmaj_flt = sig->cmaj_flt;
494 : 35314 : cutime = sig->cutime;
495 : 35314 : cstime = sig->cstime;
496 : 35314 : cgtime = sig->cgtime;
497 : : rsslim = READ_ONCE(sig->rlim[RLIMIT_RSS].rlim_cur);
498 : :
499 : : /* add up live thread stats at the group level */
500 [ + - ]: 35314 : if (whole) {
501 : : struct task_struct *t = task;
502 : : do {
503 : 37812 : min_flt += t->min_flt;
504 : 37812 : maj_flt += t->maj_flt;
505 : 37812 : gtime += task_gtime(t);
506 [ + + ]: 37812 : } while_each_thread(task, t);
507 : :
508 : 35328 : min_flt += sig->min_flt;
509 : 35328 : maj_flt += sig->maj_flt;
510 : 35328 : thread_group_cputime_adjusted(task, &utime, &stime);
511 : 35328 : gtime += sig->gtime;
512 : : }
513 : :
514 : : sid = task_session_nr_ns(task, ns);
515 : 35298 : ppid = task_tgid_nr_ns(task->real_parent, ns);
516 : : pgid = task_pgrp_nr_ns(task, ns);
517 : :
518 : : unlock_task_sighand(task, &flags);
519 : : }
520 : :
521 [ + + + + ]: 35327 : if (permitted && (!whole || num_threads < 2))
522 : 34085 : wchan = get_wchan(task);
523 [ - + ]: 35328 : if (!whole) {
524 : 0 : min_flt = task->min_flt;
525 : 0 : maj_flt = task->maj_flt;
526 : 0 : task_cputime_adjusted(task, &utime, &stime);
527 : : gtime = task_gtime(task);
528 : : }
529 : :
530 : : /* scale priority and nice values from timeslices to -20..20 */
531 : : /* to make it look like a "normal" Unix priority/nice value */
532 : 35328 : priority = task_prio(task);
533 : : nice = task_nice(task);
534 : :
535 : : /* convert nsec -> ticks */
536 : 35306 : start_time = nsec_to_clock_t(task->real_start_time);
537 : :
538 : 35315 : seq_put_decimal_ull(m, "", pid_nr_ns(pid, ns));
539 : 35287 : seq_puts(m, " (");
540 : 35328 : proc_task_name(m, task, false);
541 : 35327 : seq_puts(m, ") ");
542 : 35327 : seq_putc(m, state);
543 : 35284 : seq_put_decimal_ll(m, " ", ppid);
544 : 35324 : seq_put_decimal_ll(m, " ", pgid);
545 : 35325 : seq_put_decimal_ll(m, " ", sid);
546 : 35323 : seq_put_decimal_ll(m, " ", tty_nr);
547 : 35328 : seq_put_decimal_ll(m, " ", tty_pgrp);
548 : 35327 : seq_put_decimal_ull(m, " ", task->flags);
549 : 35326 : seq_put_decimal_ull(m, " ", min_flt);
550 : 35325 : seq_put_decimal_ull(m, " ", cmin_flt);
551 : 35328 : seq_put_decimal_ull(m, " ", maj_flt);
552 : 35311 : seq_put_decimal_ull(m, " ", cmaj_flt);
553 : 35328 : seq_put_decimal_ull(m, " ", nsec_to_clock_t(utime));
554 : 35328 : seq_put_decimal_ull(m, " ", nsec_to_clock_t(stime));
555 : 35301 : seq_put_decimal_ll(m, " ", nsec_to_clock_t(cutime));
556 : 35325 : seq_put_decimal_ll(m, " ", nsec_to_clock_t(cstime));
557 : 35328 : seq_put_decimal_ll(m, " ", priority);
558 : 35328 : seq_put_decimal_ll(m, " ", nice);
559 : 35308 : seq_put_decimal_ll(m, " ", num_threads);
560 : 35328 : seq_put_decimal_ull(m, " ", 0);
561 : 35328 : seq_put_decimal_ull(m, " ", start_time);
562 : 35312 : seq_put_decimal_ull(m, " ", vsize);
563 [ + + ]: 57255 : seq_put_decimal_ull(m, " ", mm ? get_mm_rss(mm) : 0);
564 : 35328 : seq_put_decimal_ull(m, " ", rsslim);
565 [ + + + - ]: 35328 : seq_put_decimal_ull(m, " ", mm ? (permitted ? mm->start_code : 1) : 0);
566 [ + + + + ]: 35316 : seq_put_decimal_ull(m, " ", mm ? (permitted ? mm->end_code : 1) : 0);
567 [ + + ]: 35308 : seq_put_decimal_ull(m, " ", (permitted && mm) ? mm->start_stack : 0);
568 : 35327 : seq_put_decimal_ull(m, " ", esp);
569 : 35328 : seq_put_decimal_ull(m, " ", eip);
570 : : /* The signal information here is obsolete.
571 : : * It must be decimal for Linux 2.0 compatibility.
572 : : * Use /proc/#/status for real-time signals.
573 : : */
574 : 35308 : seq_put_decimal_ull(m, " ", task->pending.signal.sig[0] & 0x7fffffffUL);
575 : 35293 : seq_put_decimal_ull(m, " ", task->blocked.sig[0] & 0x7fffffffUL);
576 : 35301 : seq_put_decimal_ull(m, " ", sigign.sig[0] & 0x7fffffffUL);
577 : 35308 : seq_put_decimal_ull(m, " ", sigcatch.sig[0] & 0x7fffffffUL);
578 : :
579 : : /*
580 : : * We used to output the absolute kernel address, but that's an
581 : : * information leak - so instead we show a 0/1 flag here, to signal
582 : : * to user-space whether there's a wchan field in /proc/PID/wchan.
583 : : *
584 : : * This works with older implementations of procps as well.
585 : : */
586 [ + + ]: 35328 : if (wchan)
587 : 14583 : seq_puts(m, " 1");
588 : : else
589 : 20745 : seq_puts(m, " 0");
590 : :
591 : 35323 : seq_put_decimal_ull(m, " ", 0);
592 : 35328 : seq_put_decimal_ull(m, " ", 0);
593 : 35307 : seq_put_decimal_ll(m, " ", task->exit_signal);
594 : 35310 : seq_put_decimal_ll(m, " ", task_cpu(task));
595 : 35310 : seq_put_decimal_ull(m, " ", task->rt_priority);
596 : 35304 : seq_put_decimal_ull(m, " ", task->policy);
597 : 35319 : seq_put_decimal_ull(m, " ", delayacct_blkio_ticks(task));
598 : 35325 : seq_put_decimal_ull(m, " ", nsec_to_clock_t(gtime));
599 : 35328 : seq_put_decimal_ll(m, " ", nsec_to_clock_t(cgtime));
600 : :
601 [ + + ]: 35300 : if (mm && permitted) {
602 : 21933 : seq_put_decimal_ull(m, " ", mm->start_data);
603 : 21957 : seq_put_decimal_ull(m, " ", mm->end_data);
604 : 21960 : seq_put_decimal_ull(m, " ", mm->start_brk);
605 : 21960 : seq_put_decimal_ull(m, " ", mm->arg_start);
606 : 21960 : seq_put_decimal_ull(m, " ", mm->arg_end);
607 : 21961 : seq_put_decimal_ull(m, " ", mm->env_start);
608 : 21957 : seq_put_decimal_ull(m, " ", mm->env_end);
609 : : } else
610 : 13367 : seq_puts(m, " 0 0 0 0 0 0 0");
611 : :
612 [ + - ]: 35324 : if (permitted)
613 : 35324 : seq_put_decimal_ll(m, " ", task->exit_code);
614 : : else
615 : 0 : seq_puts(m, " 0");
616 : :
617 : 35327 : seq_putc(m, '\n');
618 [ + + ]: 35327 : if (mm)
619 : 21961 : mmput(mm);
620 : 35322 : return 0;
621 : : }
622 : :
623 : 0 : int proc_tid_stat(struct seq_file *m, struct pid_namespace *ns,
624 : : struct pid *pid, struct task_struct *task)
625 : : {
626 : 0 : return do_task_stat(m, ns, pid, task, 0);
627 : : }
628 : :
629 : 35328 : int proc_tgid_stat(struct seq_file *m, struct pid_namespace *ns,
630 : : struct pid *pid, struct task_struct *task)
631 : : {
632 : 35328 : return do_task_stat(m, ns, pid, task, 1);
633 : : }
634 : :
635 : 0 : int proc_pid_statm(struct seq_file *m, struct pid_namespace *ns,
636 : : struct pid *pid, struct task_struct *task)
637 : : {
638 : 0 : unsigned long size = 0, resident = 0, shared = 0, text = 0, data = 0;
639 : 0 : struct mm_struct *mm = get_task_mm(task);
640 : :
641 [ # # ]: 0 : if (mm) {
642 : 0 : size = task_statm(mm, &shared, &text, &data, &resident);
643 : 0 : mmput(mm);
644 : : }
645 : : /*
646 : : * For quick read, open code by putting numbers directly
647 : : * expected format is
648 : : * seq_printf(m, "%lu %lu %lu %lu 0 %lu 0\n",
649 : : * size, resident, shared, text, data);
650 : : */
651 : 0 : seq_put_decimal_ull(m, "", size);
652 : 0 : seq_put_decimal_ull(m, " ", resident);
653 : 0 : seq_put_decimal_ull(m, " ", shared);
654 : 0 : seq_put_decimal_ull(m, " ", text);
655 : 0 : seq_put_decimal_ull(m, " ", 0);
656 : 0 : seq_put_decimal_ull(m, " ", data);
657 : 0 : seq_put_decimal_ull(m, " ", 0);
658 : 0 : seq_putc(m, '\n');
659 : :
660 : 0 : return 0;
661 : : }
662 : :
663 : : #ifdef CONFIG_PROC_CHILDREN
664 : : static struct pid *
665 : : get_children_pid(struct inode *inode, struct pid *pid_prev, loff_t pos)
666 : : {
667 : : struct task_struct *start, *task;
668 : : struct pid *pid = NULL;
669 : :
670 : : read_lock(&tasklist_lock);
671 : :
672 : : start = pid_task(proc_pid(inode), PIDTYPE_PID);
673 : : if (!start)
674 : : goto out;
675 : :
676 : : /*
677 : : * Lets try to continue searching first, this gives
678 : : * us significant speedup on children-rich processes.
679 : : */
680 : : if (pid_prev) {
681 : : task = pid_task(pid_prev, PIDTYPE_PID);
682 : : if (task && task->real_parent == start &&
683 : : !(list_empty(&task->sibling))) {
684 : : if (list_is_last(&task->sibling, &start->children))
685 : : goto out;
686 : : task = list_first_entry(&task->sibling,
687 : : struct task_struct, sibling);
688 : : pid = get_pid(task_pid(task));
689 : : goto out;
690 : : }
691 : : }
692 : :
693 : : /*
694 : : * Slow search case.
695 : : *
696 : : * We might miss some children here if children
697 : : * are exited while we were not holding the lock,
698 : : * but it was never promised to be accurate that
699 : : * much.
700 : : *
701 : : * "Just suppose that the parent sleeps, but N children
702 : : * exit after we printed their tids. Now the slow paths
703 : : * skips N extra children, we miss N tasks." (c)
704 : : *
705 : : * So one need to stop or freeze the leader and all
706 : : * its children to get a precise result.
707 : : */
708 : : list_for_each_entry(task, &start->children, sibling) {
709 : : if (pos-- == 0) {
710 : : pid = get_pid(task_pid(task));
711 : : break;
712 : : }
713 : : }
714 : :
715 : : out:
716 : : read_unlock(&tasklist_lock);
717 : : return pid;
718 : : }
719 : :
720 : : static int children_seq_show(struct seq_file *seq, void *v)
721 : : {
722 : : struct inode *inode = file_inode(seq->file);
723 : :
724 : : seq_printf(seq, "%d ", pid_nr_ns(v, proc_pid_ns(inode)));
725 : : return 0;
726 : : }
727 : :
728 : : static void *children_seq_start(struct seq_file *seq, loff_t *pos)
729 : : {
730 : : return get_children_pid(file_inode(seq->file), NULL, *pos);
731 : : }
732 : :
733 : : static void *children_seq_next(struct seq_file *seq, void *v, loff_t *pos)
734 : : {
735 : : struct pid *pid;
736 : :
737 : : pid = get_children_pid(file_inode(seq->file), v, *pos + 1);
738 : : put_pid(v);
739 : :
740 : : ++*pos;
741 : : return pid;
742 : : }
743 : :
744 : : static void children_seq_stop(struct seq_file *seq, void *v)
745 : : {
746 : : put_pid(v);
747 : : }
748 : :
749 : : static const struct seq_operations children_seq_ops = {
750 : : .start = children_seq_start,
751 : : .next = children_seq_next,
752 : : .stop = children_seq_stop,
753 : : .show = children_seq_show,
754 : : };
755 : :
756 : : static int children_seq_open(struct inode *inode, struct file *file)
757 : : {
758 : : return seq_open(file, &children_seq_ops);
759 : : }
760 : :
761 : : const struct file_operations proc_tid_children_operations = {
762 : : .open = children_seq_open,
763 : : .read = seq_read,
764 : : .llseek = seq_lseek,
765 : : .release = seq_release,
766 : : };
767 : : #endif /* CONFIG_PROC_CHILDREN */
|