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