LCOV - code coverage report
Current view: top level - fs/proc - array.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 353 0.0 %
Date: 2023-04-06 08:38:28 Functions: 0 15 0.0 %

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

Generated by: LCOV version 1.14