1
2
3
4
5
6
7
8
9
10
11
12
13
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
48
49
50
51
52
53
54
55
56#include <linux/types.h>
57#include <linux/errno.h>
58#include <linux/time.h>
59#include <linux/time_namespace.h>
60#include <linux/kernel.h>
61#include <linux/kernel_stat.h>
62#include <linux/tty.h>
63#include <linux/string.h>
64#include <linux/mman.h>
65#include <linux/sched/mm.h>
66#include <linux/sched/numa_balancing.h>
67#include <linux/sched/task_stack.h>
68#include <linux/sched/task.h>
69#include <linux/sched/cputime.h>
70#include <linux/proc_fs.h>
71#include <linux/ioport.h>
72#include <linux/uaccess.h>
73#include <linux/io.h>
74#include <linux/mm.h>
75#include <linux/hugetlb.h>
76#include <linux/pagemap.h>
77#include <linux/swap.h>
78#include <linux/smp.h>
79#include <linux/signal.h>
80#include <linux/highmem.h>
81#include <linux/file.h>
82#include <linux/fdtable.h>
83#include <linux/times.h>
84#include <linux/cpuset.h>
85#include <linux/rcupdate.h>
86#include <linux/delayacct.h>
87#include <linux/seq_file.h>
88#include <linux/pid_namespace.h>
89#include <linux/prctl.h>
90#include <linux/ptrace.h>
91#include <linux/tracehook.h>
92#include <linux/string_helpers.h>
93#include <linux/user_namespace.h>
94#include <linux/fs_struct.h>
95
96#include <asm/processor.h>
97#include "internal.h"
98
99void 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 if (p->flags & PF_WQ_WORKER)
107 wq_worker_comm(tcomm, sizeof(tcomm), p);
108 else
109 __get_task_comm(tcomm, sizeof(tcomm), p);
110
111 size = seq_get_buf(m, &buf);
112 if (escape) {
113 ret = string_escape_str(tcomm, buf, size,
114 ESCAPE_SPACE | ESCAPE_SPECIAL, "\n\\");
115 if (ret >= size)
116 ret = -1;
117 } else {
118 ret = strscpy(buf, tcomm, size);
119 }
120
121 seq_commit(m, ret);
122}
123
124
125
126
127
128
129
130static const char * const task_state_array[] = {
131
132
133 "R (running)",
134 "S (sleeping)",
135 "D (disk sleep)",
136 "T (stopped)",
137 "t (tracing stop)",
138 "X (dead)",
139 "Z (zombie)",
140 "P (parked)",
141
142
143 "I (idle)",
144};
145
146static 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 return task_state_array[task_state_index(tsk)];
150}
151
152static 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 task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0;
166
167 tracer = ptrace_parent(p);
168 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 cred = get_task_cred(p);
174
175 task_lock(p);
176 if (p->fs)
177 umask = p->fs->umask;
178 if (p->files)
179 max_fds = files_fdtable(p->files)->max_fds;
180 task_unlock(p);
181 rcu_read_unlock();
182
183 if (umask >= 0)
184 seq_printf(m, "Umask:\t%#04o\n", umask);
185 seq_puts(m, "State:\t");
186 seq_puts(m, get_task_state(p));
187
188 seq_put_decimal_ull(m, "\nTgid:\t", tgid);
189 seq_put_decimal_ull(m, "\nNgid:\t", ngid);
190 seq_put_decimal_ull(m, "\nPid:\t", pid_nr_ns(pid, ns));
191 seq_put_decimal_ull(m, "\nPPid:\t", ppid);
192 seq_put_decimal_ull(m, "\nTracerPid:\t", tpid);
193 seq_put_decimal_ull(m, "\nUid:\t", from_kuid_munged(user_ns, cred->uid));
194 seq_put_decimal_ull(m, "\t", from_kuid_munged(user_ns, cred->euid));
195 seq_put_decimal_ull(m, "\t", from_kuid_munged(user_ns, cred->suid));
196 seq_put_decimal_ull(m, "\t", from_kuid_munged(user_ns, cred->fsuid));
197 seq_put_decimal_ull(m, "\nGid:\t", from_kgid_munged(user_ns, cred->gid));
198 seq_put_decimal_ull(m, "\t", from_kgid_munged(user_ns, cred->egid));
199 seq_put_decimal_ull(m, "\t", from_kgid_munged(user_ns, cred->sgid));
200 seq_put_decimal_ull(m, "\t", from_kgid_munged(user_ns, cred->fsgid));
201 seq_put_decimal_ull(m, "\nFDSize:\t", max_fds);
202
203 seq_puts(m, "\nGroups:\t");
204 group_info = cred->group_info;
205 for (g = 0; g < group_info->ngroups; g++)
206 seq_put_decimal_ull(m, g ? " " : "",
207 from_kgid_munged(user_ns, group_info->gid[g]));
208 put_cred(cred);
209
210 seq_putc(m, ' ');
211
212#ifdef CONFIG_PID_NS
213 seq_puts(m, "\nNStgid:");
214 for (g = ns->level; g <= pid->level; g++)
215 seq_put_decimal_ull(m, "\t", task_tgid_nr_ns(p, pid->numbers[g].ns));
216 seq_puts(m, "\nNSpid:");
217 for (g = ns->level; g <= pid->level; g++)
218 seq_put_decimal_ull(m, "\t", task_pid_nr_ns(p, pid->numbers[g].ns));
219 seq_puts(m, "\nNSpgid:");
220 for (g = ns->level; g <= pid->level; g++)
221 seq_put_decimal_ull(m, "\t", task_pgrp_nr_ns(p, pid->numbers[g].ns));
222 seq_puts(m, "\nNSsid:");
223 for (g = ns->level; g <= pid->level; g++)
224 seq_put_decimal_ull(m, "\t", task_session_nr_ns(p, pid->numbers[g].ns));
225#endif
226 seq_putc(m, '\n');
227}
228
229void render_sigset_t(struct seq_file *m, const char *header,
230 sigset_t *set)
231{
232 int i;
233
234 seq_puts(m, header);
235
236 i = _NSIG;
237 do {
238 int x = 0;
239
240 i -= 4;
241 if (sigismember(set, i+1)) x |= 1;
242 if (sigismember(set, i+2)) x |= 2;
243 if (sigismember(set, i+3)) x |= 4;
244 if (sigismember(set, i+4)) x |= 8;
245 seq_putc(m, hex_asc[x]);
246 } while (i >= 4);
247
248 seq_putc(m, '\n');
249}
250
251static void collect_sigign_sigcatch(struct task_struct *p, sigset_t *sigign,
252 sigset_t *sigcatch)
253{
254 struct k_sigaction *k;
255 int i;
256
257 k = p->sighand->action;
258 for (i = 1; i <= _NSIG; ++i, ++k) {
259 if (k->sa.sa_handler == SIG_IGN)
260 sigaddset(sigign, i);
261 else if (k->sa.sa_handler != SIG_DFL)
262 sigaddset(sigcatch, i);
263 }
264}
265
266static 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 if (lock_task_sighand(p, &flags)) {
281 pending = p->pending.signal;
282 shpending = p->signal->shared_pending.signal;
283 blocked = p->blocked;
284 collect_sigign_sigcatch(p, &ignored, &caught);
285 num_threads = get_nr_threads(p);
286 rcu_read_lock();
287 qsize = get_ucounts_value(task_ucounts(p), UCOUNT_RLIMIT_SIGPENDING);
288 rcu_read_unlock();
289 qlim = task_rlimit(p, RLIMIT_SIGPENDING);
290 unlock_task_sighand(p, &flags);
291 }
292
293 seq_put_decimal_ull(m, "Threads:\t", num_threads);
294 seq_put_decimal_ull(m, "\nSigQ:\t", qsize);
295 seq_put_decimal_ull(m, "/", qlim);
296
297
298 render_sigset_t(m, "\nSigPnd:\t", &pending);
299 render_sigset_t(m, "ShdPnd:\t", &shpending);
300 render_sigset_t(m, "SigBlk:\t", &blocked);
301 render_sigset_t(m, "SigIgn:\t", &ignored);
302 render_sigset_t(m, "SigCgt:\t", &caught);
303}
304
305static void render_cap_t(struct seq_file *m, const char *header,
306 kernel_cap_t *a)
307{
308 unsigned __capi;
309
310 seq_puts(m, header);
311 CAP_FOR_EACH_U32(__capi) {
312 seq_put_hex_ll(m, NULL,
313 a->cap[CAP_LAST_U32 - __capi], 8);
314 }
315 seq_putc(m, '\n');
316}
317
318static 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 cred = __task_cred(p);
326 cap_inheritable = cred->cap_inheritable;
327 cap_permitted = cred->cap_permitted;
328 cap_effective = cred->cap_effective;
329 cap_bset = cred->cap_bset;
330 cap_ambient = cred->cap_ambient;
331 rcu_read_unlock();
332
333 render_cap_t(m, "CapInh:\t", &cap_inheritable);
334 render_cap_t(m, "CapPrm:\t", &cap_permitted);
335 render_cap_t(m, "CapEff:\t", &cap_effective);
336 render_cap_t(m, "CapBnd:\t", &cap_bset);
337 render_cap_t(m, "CapAmb:\t", &cap_ambient);
338}
339
340static inline void task_seccomp(struct seq_file *m, struct task_struct *p)
341{
342 seq_put_decimal_ull(m, "NoNewPrivs:\t", task_no_new_privs(p));
343#ifdef CONFIG_SECCOMP
344 seq_put_decimal_ull(m, "\nSeccomp:\t", p->seccomp.mode);
345#ifdef CONFIG_SECCOMP_FILTER
346 seq_put_decimal_ull(m, "\nSeccomp_filters:\t",
347 atomic_read(&p->seccomp.filter_count));
348#endif
349#endif
350 seq_puts(m, "\nSpeculation_Store_Bypass:\t");
351 switch (arch_prctl_spec_ctrl_get(p, PR_SPEC_STORE_BYPASS)) {
352 case -EINVAL:
353 seq_puts(m, "unknown");
354 break;
355 case PR_SPEC_NOT_AFFECTED:
356 seq_puts(m, "not vulnerable");
357 break;
358 case PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE:
359 seq_puts(m, "thread force mitigated");
360 break;
361 case PR_SPEC_PRCTL | PR_SPEC_DISABLE:
362 seq_puts(m, "thread mitigated");
363 break;
364 case PR_SPEC_PRCTL | PR_SPEC_ENABLE:
365 seq_puts(m, "thread vulnerable");
366 break;
367 case PR_SPEC_DISABLE:
368 seq_puts(m, "globally mitigated");
369 break;
370 default:
371 seq_puts(m, "vulnerable");
372 break;
373 }
374
375 seq_puts(m, "\nSpeculationIndirectBranch:\t");
376 switch (arch_prctl_spec_ctrl_get(p, PR_SPEC_INDIRECT_BRANCH)) {
377 case -EINVAL:
378 seq_puts(m, "unsupported");
379 break;
380 case PR_SPEC_NOT_AFFECTED:
381 seq_puts(m, "not affected");
382 break;
383 case PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE:
384 seq_puts(m, "conditional force disabled");
385 break;
386 case PR_SPEC_PRCTL | PR_SPEC_DISABLE:
387 seq_puts(m, "conditional disabled");
388 break;
389 case PR_SPEC_PRCTL | PR_SPEC_ENABLE:
390 seq_puts(m, "conditional enabled");
391 break;
392 case PR_SPEC_ENABLE:
393 seq_puts(m, "always enabled");
394 break;
395 case PR_SPEC_DISABLE:
396 seq_puts(m, "always disabled");
397 break;
398 default:
399 seq_puts(m, "unknown");
400 break;
401 }
402 seq_putc(m, '\n');
403}
404
405static inline void task_context_switch_counts(struct seq_file *m,
406 struct task_struct *p)
407{
408 seq_put_decimal_ull(m, "voluntary_ctxt_switches:\t", p->nvcsw);
409 seq_put_decimal_ull(m, "\nnonvoluntary_ctxt_switches:\t", p->nivcsw);
410 seq_putc(m, '\n');
411}
412
413static void task_cpus_allowed(struct seq_file *m, struct task_struct *task)
414{
415 seq_printf(m, "Cpus_allowed:\t%*pb\n",
416 cpumask_pr_args(&task->cpus_mask));
417 seq_printf(m, "Cpus_allowed_list:\t%*pbl\n",
418 cpumask_pr_args(&task->cpus_mask));
419}
420
421static inline void task_core_dumping(struct seq_file *m, struct mm_struct *mm)
422{
423 seq_put_decimal_ull(m, "CoreDumping:\t", !!mm->core_state);
424 seq_putc(m, '\n');
425}
426
427static inline void task_thp_status(struct seq_file *m, struct mm_struct *mm)
428{
429 bool thp_enabled = IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE);
430
431 if (thp_enabled)
432 thp_enabled = !test_bit(MMF_DISABLE_THP, &mm->flags);
433 seq_printf(m, "THP_enabled:\t%d\n", thp_enabled);
434}
435
436int proc_pid_status(struct seq_file *m, struct pid_namespace *ns,
437 struct pid *pid, struct task_struct *task)
438{
439 struct mm_struct *mm = get_task_mm(task);
440
441 seq_puts(m, "Name:\t");
442 proc_task_name(m, task, true);
443 seq_putc(m, '\n');
444
445 task_state(m, ns, pid, task);
446
447 if (mm) {
448 task_mem(m, mm);
449 task_core_dumping(m, mm);
450 task_thp_status(m, mm);
451 mmput(mm);
452 }
453 task_sig(m, task);
454 task_cap(m, task);
455 task_seccomp(m, task);
456 task_cpus_allowed(m, task);
457 cpuset_task_status_allowed(m, task);
458 task_context_switch_counts(m, task);
459 return 0;
460}
461
462static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
463 struct pid *pid, struct task_struct *task, int whole)
464{
465 unsigned long vsize, eip, esp, wchan = 0;
466 int priority, nice;
467 int tty_pgrp = -1, tty_nr = 0;
468 sigset_t sigign, sigcatch;
469 char state;
470 pid_t ppid = 0, pgid = -1, sid = -1;
471 int num_threads = 0;
472 int permitted;
473 struct mm_struct *mm;
474 unsigned long long start_time;
475 unsigned long cmin_flt = 0, cmaj_flt = 0;
476 unsigned long min_flt = 0, maj_flt = 0;
477 u64 cutime, cstime, utime, stime;
478 u64 cgtime, gtime;
479 unsigned long rsslim = 0;
480 unsigned long flags;
481
482 state = *get_task_state(task);
483 vsize = eip = esp = 0;
484 permitted = ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS | PTRACE_MODE_NOAUDIT);
485 mm = get_task_mm(task);
486 if (mm) {
487 vsize = task_vsize(mm);
488
489
490
491
492
493
494
495
496
497 if (permitted && (task->flags & (PF_EXITING|PF_DUMPCORE))) {
498 if (try_get_task_stack(task)) {
499 eip = KSTK_EIP(task);
500 esp = KSTK_ESP(task);
501 put_task_stack(task);
502 }
503 }
504 }
505
506 sigemptyset(&sigign);
507 sigemptyset(&sigcatch);
508 cutime = cstime = utime = stime = 0;
509 cgtime = gtime = 0;
510
511 if (lock_task_sighand(task, &flags)) {
512 struct signal_struct *sig = task->signal;
513
514 if (sig->tty) {
515 struct pid *pgrp = tty_get_pgrp(sig->tty);
516 tty_pgrp = pid_nr_ns(pgrp, ns);
517 put_pid(pgrp);
518 tty_nr = new_encode_dev(tty_devnum(sig->tty));
519 }
520
521 num_threads = get_nr_threads(task);
522 collect_sigign_sigcatch(task, &sigign, &sigcatch);
523
524 cmin_flt = sig->cmin_flt;
525 cmaj_flt = sig->cmaj_flt;
526 cutime = sig->cutime;
527 cstime = sig->cstime;
528 cgtime = sig->cgtime;
529 rsslim = READ_ONCE(sig->rlim[RLIMIT_RSS].rlim_cur);
530
531
532 if (whole) {
533 struct task_struct *t = task;
534 do {
535 min_flt += t->min_flt;
536 maj_flt += t->maj_flt;
537 gtime += task_gtime(t);
538 } while_each_thread(task, t);
539
540 min_flt += sig->min_flt;
541 maj_flt += sig->maj_flt;
542 thread_group_cputime_adjusted(task, &utime, &stime);
543 gtime += sig->gtime;
544 }
545
546 sid = task_session_nr_ns(task, ns);
547 ppid = task_tgid_nr_ns(task->real_parent, ns);
548 pgid = task_pgrp_nr_ns(task, ns);
549
550 unlock_task_sighand(task, &flags);
551 }
552
553 if (permitted && (!whole || num_threads < 2))
554 wchan = get_wchan(task);
555 if (!whole) {
556 min_flt = task->min_flt;
557 maj_flt = task->maj_flt;
558 task_cputime_adjusted(task, &utime, &stime);
559 gtime = task_gtime(task);
560 }
561
562
563
564 priority = task_prio(task);
565 nice = task_nice(task);
566
567
568 start_time =
569 nsec_to_clock_t(timens_add_boottime_ns(task->start_boottime));
570
571 seq_put_decimal_ull(m, "", pid_nr_ns(pid, ns));
572 seq_puts(m, " (");
573 proc_task_name(m, task, false);
574 seq_puts(m, ") ");
575 seq_putc(m, state);
576 seq_put_decimal_ll(m, " ", ppid);
577 seq_put_decimal_ll(m, " ", pgid);
578 seq_put_decimal_ll(m, " ", sid);
579 seq_put_decimal_ll(m, " ", tty_nr);
580 seq_put_decimal_ll(m, " ", tty_pgrp);
581 seq_put_decimal_ull(m, " ", task->flags);
582 seq_put_decimal_ull(m, " ", min_flt);
583 seq_put_decimal_ull(m, " ", cmin_flt);
584 seq_put_decimal_ull(m, " ", maj_flt);
585 seq_put_decimal_ull(m, " ", cmaj_flt);
586 seq_put_decimal_ull(m, " ", nsec_to_clock_t(utime));
587 seq_put_decimal_ull(m, " ", nsec_to_clock_t(stime));
588 seq_put_decimal_ll(m, " ", nsec_to_clock_t(cutime));
589 seq_put_decimal_ll(m, " ", nsec_to_clock_t(cstime));
590 seq_put_decimal_ll(m, " ", priority);
591 seq_put_decimal_ll(m, " ", nice);
592 seq_put_decimal_ll(m, " ", num_threads);
593 seq_put_decimal_ull(m, " ", 0);
594 seq_put_decimal_ull(m, " ", start_time);
595 seq_put_decimal_ull(m, " ", vsize);
596 seq_put_decimal_ull(m, " ", mm ? get_mm_rss(mm) : 0);
597 seq_put_decimal_ull(m, " ", rsslim);
598 seq_put_decimal_ull(m, " ", mm ? (permitted ? mm->start_code : 1) : 0);
599 seq_put_decimal_ull(m, " ", mm ? (permitted ? mm->end_code : 1) : 0);
600 seq_put_decimal_ull(m, " ", (permitted && mm) ? mm->start_stack : 0);
601 seq_put_decimal_ull(m, " ", esp);
602 seq_put_decimal_ull(m, " ", eip);
603
604
605
606
607 seq_put_decimal_ull(m, " ", task->pending.signal.sig[0] & 0x7fffffffUL);
608 seq_put_decimal_ull(m, " ", task->blocked.sig[0] & 0x7fffffffUL);
609 seq_put_decimal_ull(m, " ", sigign.sig[0] & 0x7fffffffUL);
610 seq_put_decimal_ull(m, " ", sigcatch.sig[0] & 0x7fffffffUL);
611
612
613
614
615
616
617
618
619 if (wchan)
620 seq_puts(m, " 1");
621 else
622 seq_puts(m, " 0");
623
624 seq_put_decimal_ull(m, " ", 0);
625 seq_put_decimal_ull(m, " ", 0);
626 seq_put_decimal_ll(m, " ", task->exit_signal);
627 seq_put_decimal_ll(m, " ", task_cpu(task));
628 seq_put_decimal_ull(m, " ", task->rt_priority);
629 seq_put_decimal_ull(m, " ", task->policy);
630 seq_put_decimal_ull(m, " ", delayacct_blkio_ticks(task));
631 seq_put_decimal_ull(m, " ", nsec_to_clock_t(gtime));
632 seq_put_decimal_ll(m, " ", nsec_to_clock_t(cgtime));
633
634 if (mm && permitted) {
635 seq_put_decimal_ull(m, " ", mm->start_data);
636 seq_put_decimal_ull(m, " ", mm->end_data);
637 seq_put_decimal_ull(m, " ", mm->start_brk);
638 seq_put_decimal_ull(m, " ", mm->arg_start);
639 seq_put_decimal_ull(m, " ", mm->arg_end);
640 seq_put_decimal_ull(m, " ", mm->env_start);
641 seq_put_decimal_ull(m, " ", mm->env_end);
642 } else
643 seq_puts(m, " 0 0 0 0 0 0 0");
644
645 if (permitted)
646 seq_put_decimal_ll(m, " ", task->exit_code);
647 else
648 seq_puts(m, " 0");
649
650 seq_putc(m, '\n');
651 if (mm)
652 mmput(mm);
653 return 0;
654}
655
656int proc_tid_stat(struct seq_file *m, struct pid_namespace *ns,
657 struct pid *pid, struct task_struct *task)
658{
659 return do_task_stat(m, ns, pid, task, 0);
660}
661
662int proc_tgid_stat(struct seq_file *m, struct pid_namespace *ns,
663 struct pid *pid, struct task_struct *task)
664{
665 return do_task_stat(m, ns, pid, task, 1);
666}
667
668int proc_pid_statm(struct seq_file *m, struct pid_namespace *ns,
669 struct pid *pid, struct task_struct *task)
670{
671 struct mm_struct *mm = get_task_mm(task);
672
673 if (mm) {
674 unsigned long size;
675 unsigned long resident = 0;
676 unsigned long shared = 0;
677 unsigned long text = 0;
678 unsigned long data = 0;
679
680 size = task_statm(mm, &shared, &text, &data, &resident);
681 mmput(mm);
682
683
684
685
686
687
688
689 seq_put_decimal_ull(m, "", size);
690 seq_put_decimal_ull(m, " ", resident);
691 seq_put_decimal_ull(m, " ", shared);
692 seq_put_decimal_ull(m, " ", text);
693 seq_put_decimal_ull(m, " ", 0);
694 seq_put_decimal_ull(m, " ", data);
695 seq_put_decimal_ull(m, " ", 0);
696 seq_putc(m, '\n');
697 } else {
698 seq_write(m, "0 0 0 0 0 0 0\n", 14);
699 }
700 return 0;
701}
702
703#ifdef CONFIG_PROC_CHILDREN
704static struct pid *
705get_children_pid(struct inode *inode, struct pid *pid_prev, loff_t pos)
706{
707 struct task_struct *start, *task;
708 struct pid *pid = NULL;
709
710 read_lock(&tasklist_lock);
711
712 start = pid_task(proc_pid(inode), PIDTYPE_PID);
713 if (!start)
714 goto out;
715
716
717
718
719
720 if (pid_prev) {
721 task = pid_task(pid_prev, PIDTYPE_PID);
722 if (task && task->real_parent == start &&
723 !(list_empty(&task->sibling))) {
724 if (list_is_last(&task->sibling, &start->children))
725 goto out;
726 task = list_first_entry(&task->sibling,
727 struct task_struct, sibling);
728 pid = get_pid(task_pid(task));
729 goto out;
730 }
731 }
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748 list_for_each_entry(task, &start->children, sibling) {
749 if (pos-- == 0) {
750 pid = get_pid(task_pid(task));
751 break;
752 }
753 }
754
755out:
756 read_unlock(&tasklist_lock);
757 return pid;
758}
759
760static int children_seq_show(struct seq_file *seq, void *v)
761{
762 struct inode *inode = file_inode(seq->file);
763
764 seq_printf(seq, "%d ", pid_nr_ns(v, proc_pid_ns(inode->i_sb)));
765 return 0;
766}
767
768static void *children_seq_start(struct seq_file *seq, loff_t *pos)
769{
770 return get_children_pid(file_inode(seq->file), NULL, *pos);
771}
772
773static void *children_seq_next(struct seq_file *seq, void *v, loff_t *pos)
774{
775 struct pid *pid;
776
777 pid = get_children_pid(file_inode(seq->file), v, *pos + 1);
778 put_pid(v);
779
780 ++*pos;
781 return pid;
782}
783
784static void children_seq_stop(struct seq_file *seq, void *v)
785{
786 put_pid(v);
787}
788
789static const struct seq_operations children_seq_ops = {
790 .start = children_seq_start,
791 .next = children_seq_next,
792 .stop = children_seq_stop,
793 .show = children_seq_show,
794};
795
796static int children_seq_open(struct inode *inode, struct file *file)
797{
798 return seq_open(file, &children_seq_ops);
799}
800
801const struct file_operations proc_tid_children_operations = {
802 .open = children_seq_open,
803 .read = seq_read,
804 .llseek = seq_lseek,
805 .release = seq_release,
806};
807#endif
808