18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *  linux/fs/proc/array.c
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci *  Copyright (C) 1992  by Linus Torvalds
68c2ecf20Sopenharmony_ci *  based on ideas by Darren Senn
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * Fixes:
98c2ecf20Sopenharmony_ci * Michael. K. Johnson: stat,statm extensions.
108c2ecf20Sopenharmony_ci *                      <johnsonm@stolaf.edu>
118c2ecf20Sopenharmony_ci *
128c2ecf20Sopenharmony_ci * Pauline Middelink :  Made cmdline,envline only break at '\0's, to
138c2ecf20Sopenharmony_ci *                      make sure SET_PROCTITLE works. Also removed
148c2ecf20Sopenharmony_ci *                      bad '!' which forced address recalculation for
158c2ecf20Sopenharmony_ci *                      EVERY character on the current page.
168c2ecf20Sopenharmony_ci *                      <middelin@polyware.iaf.nl>
178c2ecf20Sopenharmony_ci *
188c2ecf20Sopenharmony_ci * Danny ter Haar    :	added cpuinfo
198c2ecf20Sopenharmony_ci *			<dth@cistron.nl>
208c2ecf20Sopenharmony_ci *
218c2ecf20Sopenharmony_ci * Alessandro Rubini :  profile extension.
228c2ecf20Sopenharmony_ci *                      <rubini@ipvvis.unipv.it>
238c2ecf20Sopenharmony_ci *
248c2ecf20Sopenharmony_ci * Jeff Tranter      :  added BogoMips field to cpuinfo
258c2ecf20Sopenharmony_ci *                      <Jeff_Tranter@Mitel.COM>
268c2ecf20Sopenharmony_ci *
278c2ecf20Sopenharmony_ci * Bruno Haible      :  remove 4K limit for the maps file
288c2ecf20Sopenharmony_ci *			<haible@ma2s2.mathematik.uni-karlsruhe.de>
298c2ecf20Sopenharmony_ci *
308c2ecf20Sopenharmony_ci * Yves Arrouye      :  remove removal of trailing spaces in get_array.
318c2ecf20Sopenharmony_ci *			<Yves.Arrouye@marin.fdn.fr>
328c2ecf20Sopenharmony_ci *
338c2ecf20Sopenharmony_ci * Jerome Forissier  :  added per-CPU time information to /proc/stat
348c2ecf20Sopenharmony_ci *                      and /proc/<pid>/cpu extension
358c2ecf20Sopenharmony_ci *                      <forissier@isia.cma.fr>
368c2ecf20Sopenharmony_ci *			- Incorporation and non-SMP safe operation
378c2ecf20Sopenharmony_ci *			of forissier patch in 2.1.78 by
388c2ecf20Sopenharmony_ci *			Hans Marcus <crowbar@concepts.nl>
398c2ecf20Sopenharmony_ci *
408c2ecf20Sopenharmony_ci * aeb@cwi.nl        :  /proc/partitions
418c2ecf20Sopenharmony_ci *
428c2ecf20Sopenharmony_ci *
438c2ecf20Sopenharmony_ci * Alan Cox	     :  security fixes.
448c2ecf20Sopenharmony_ci *			<alan@lxorguk.ukuu.org.uk>
458c2ecf20Sopenharmony_ci *
468c2ecf20Sopenharmony_ci * Al Viro           :  safe handling of mm_struct
478c2ecf20Sopenharmony_ci *
488c2ecf20Sopenharmony_ci * Gerhard Wichert   :  added BIGMEM support
498c2ecf20Sopenharmony_ci * Siemens AG           <Gerhard.Wichert@pdb.siemens.de>
508c2ecf20Sopenharmony_ci *
518c2ecf20Sopenharmony_ci * Al Viro & Jeff Garzik :  moved most of the thing into base.c and
528c2ecf20Sopenharmony_ci *			 :  proc_misc.c. The rest may eventually go into
538c2ecf20Sopenharmony_ci *			 :  base.c too.
548c2ecf20Sopenharmony_ci */
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci#include <linux/types.h>
578c2ecf20Sopenharmony_ci#include <linux/errno.h>
588c2ecf20Sopenharmony_ci#include <linux/time.h>
598c2ecf20Sopenharmony_ci#include <linux/kernel.h>
608c2ecf20Sopenharmony_ci#include <linux/kernel_stat.h>
618c2ecf20Sopenharmony_ci#include <linux/tty.h>
628c2ecf20Sopenharmony_ci#include <linux/string.h>
638c2ecf20Sopenharmony_ci#include <linux/mman.h>
648c2ecf20Sopenharmony_ci#include <linux/sched/mm.h>
658c2ecf20Sopenharmony_ci#include <linux/sched/numa_balancing.h>
668c2ecf20Sopenharmony_ci#include <linux/sched/task_stack.h>
678c2ecf20Sopenharmony_ci#include <linux/sched/task.h>
688c2ecf20Sopenharmony_ci#include <linux/sched/cputime.h>
698c2ecf20Sopenharmony_ci#include <linux/proc_fs.h>
708c2ecf20Sopenharmony_ci#include <linux/ioport.h>
718c2ecf20Sopenharmony_ci#include <linux/uaccess.h>
728c2ecf20Sopenharmony_ci#include <linux/io.h>
738c2ecf20Sopenharmony_ci#include <linux/mm.h>
748c2ecf20Sopenharmony_ci#include <linux/hugetlb.h>
758c2ecf20Sopenharmony_ci#include <linux/pagemap.h>
768c2ecf20Sopenharmony_ci#include <linux/swap.h>
778c2ecf20Sopenharmony_ci#include <linux/smp.h>
788c2ecf20Sopenharmony_ci#include <linux/signal.h>
798c2ecf20Sopenharmony_ci#include <linux/highmem.h>
808c2ecf20Sopenharmony_ci#include <linux/file.h>
818c2ecf20Sopenharmony_ci#include <linux/fdtable.h>
828c2ecf20Sopenharmony_ci#include <linux/times.h>
838c2ecf20Sopenharmony_ci#include <linux/cpuset.h>
848c2ecf20Sopenharmony_ci#include <linux/rcupdate.h>
858c2ecf20Sopenharmony_ci#include <linux/delayacct.h>
868c2ecf20Sopenharmony_ci#include <linux/seq_file.h>
878c2ecf20Sopenharmony_ci#include <linux/pid_namespace.h>
888c2ecf20Sopenharmony_ci#include <linux/prctl.h>
898c2ecf20Sopenharmony_ci#include <linux/ptrace.h>
908c2ecf20Sopenharmony_ci#include <linux/tracehook.h>
918c2ecf20Sopenharmony_ci#include <linux/string_helpers.h>
928c2ecf20Sopenharmony_ci#include <linux/user_namespace.h>
938c2ecf20Sopenharmony_ci#include <linux/fs_struct.h>
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci#include <asm/processor.h>
968c2ecf20Sopenharmony_ci#include "internal.h"
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_civoid proc_task_name(struct seq_file *m, struct task_struct *p, bool escape)
998c2ecf20Sopenharmony_ci{
1008c2ecf20Sopenharmony_ci	char *buf;
1018c2ecf20Sopenharmony_ci	size_t size;
1028c2ecf20Sopenharmony_ci	char tcomm[64];
1038c2ecf20Sopenharmony_ci	int ret;
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci	if (p->flags & PF_WQ_WORKER)
1068c2ecf20Sopenharmony_ci		wq_worker_comm(tcomm, sizeof(tcomm), p);
1078c2ecf20Sopenharmony_ci	else
1088c2ecf20Sopenharmony_ci		__get_task_comm(tcomm, sizeof(tcomm), p);
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci	size = seq_get_buf(m, &buf);
1118c2ecf20Sopenharmony_ci	if (escape) {
1128c2ecf20Sopenharmony_ci		ret = string_escape_str(tcomm, buf, size,
1138c2ecf20Sopenharmony_ci					ESCAPE_SPACE | ESCAPE_SPECIAL, "\n\\");
1148c2ecf20Sopenharmony_ci		if (ret >= size)
1158c2ecf20Sopenharmony_ci			ret = -1;
1168c2ecf20Sopenharmony_ci	} else {
1178c2ecf20Sopenharmony_ci		ret = strscpy(buf, tcomm, size);
1188c2ecf20Sopenharmony_ci	}
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	seq_commit(m, ret);
1218c2ecf20Sopenharmony_ci}
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci/*
1248c2ecf20Sopenharmony_ci * The task state array is a strange "bitmap" of
1258c2ecf20Sopenharmony_ci * reasons to sleep. Thus "running" is zero, and
1268c2ecf20Sopenharmony_ci * you can test for combinations of others with
1278c2ecf20Sopenharmony_ci * simple bit tests.
1288c2ecf20Sopenharmony_ci */
1298c2ecf20Sopenharmony_cistatic const char * const task_state_array[] = {
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	/* states in TASK_REPORT: */
1328c2ecf20Sopenharmony_ci	"R (running)",		/* 0x00 */
1338c2ecf20Sopenharmony_ci	"S (sleeping)",		/* 0x01 */
1348c2ecf20Sopenharmony_ci	"D (disk sleep)",	/* 0x02 */
1358c2ecf20Sopenharmony_ci	"T (stopped)",		/* 0x04 */
1368c2ecf20Sopenharmony_ci	"t (tracing stop)",	/* 0x08 */
1378c2ecf20Sopenharmony_ci	"X (dead)",		/* 0x10 */
1388c2ecf20Sopenharmony_ci	"Z (zombie)",		/* 0x20 */
1398c2ecf20Sopenharmony_ci	"P (parked)",		/* 0x40 */
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci	/* states beyond TASK_REPORT: */
1428c2ecf20Sopenharmony_ci	"I (idle)",		/* 0x80 */
1438c2ecf20Sopenharmony_ci};
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_cistatic inline const char *get_task_state(struct task_struct *tsk)
1468c2ecf20Sopenharmony_ci{
1478c2ecf20Sopenharmony_ci	BUILD_BUG_ON(1 + ilog2(TASK_REPORT_MAX) != ARRAY_SIZE(task_state_array));
1488c2ecf20Sopenharmony_ci	return task_state_array[task_state_index(tsk)];
1498c2ecf20Sopenharmony_ci}
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_cistatic inline void task_state(struct seq_file *m, struct pid_namespace *ns,
1528c2ecf20Sopenharmony_ci				struct pid *pid, struct task_struct *p)
1538c2ecf20Sopenharmony_ci{
1548c2ecf20Sopenharmony_ci	struct user_namespace *user_ns = seq_user_ns(m);
1558c2ecf20Sopenharmony_ci	struct group_info *group_info;
1568c2ecf20Sopenharmony_ci	int g, umask = -1;
1578c2ecf20Sopenharmony_ci	struct task_struct *tracer;
1588c2ecf20Sopenharmony_ci	const struct cred *cred;
1598c2ecf20Sopenharmony_ci	pid_t ppid, tpid = 0, tgid, ngid;
1608c2ecf20Sopenharmony_ci	unsigned int max_fds = 0;
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci	rcu_read_lock();
1638c2ecf20Sopenharmony_ci	ppid = pid_alive(p) ?
1648c2ecf20Sopenharmony_ci		task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0;
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci	tracer = ptrace_parent(p);
1678c2ecf20Sopenharmony_ci	if (tracer)
1688c2ecf20Sopenharmony_ci		tpid = task_pid_nr_ns(tracer, ns);
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci	tgid = task_tgid_nr_ns(p, ns);
1718c2ecf20Sopenharmony_ci	ngid = task_numa_group_id(p);
1728c2ecf20Sopenharmony_ci	cred = get_task_cred(p);
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	task_lock(p);
1758c2ecf20Sopenharmony_ci	if (p->fs)
1768c2ecf20Sopenharmony_ci		umask = p->fs->umask;
1778c2ecf20Sopenharmony_ci	if (p->files)
1788c2ecf20Sopenharmony_ci		max_fds = files_fdtable(p->files)->max_fds;
1798c2ecf20Sopenharmony_ci	task_unlock(p);
1808c2ecf20Sopenharmony_ci	rcu_read_unlock();
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci	if (umask >= 0)
1838c2ecf20Sopenharmony_ci		seq_printf(m, "Umask:\t%#04o\n", umask);
1848c2ecf20Sopenharmony_ci	seq_puts(m, "State:\t");
1858c2ecf20Sopenharmony_ci	seq_puts(m, get_task_state(p));
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, "\nTgid:\t", tgid);
1888c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, "\nNgid:\t", ngid);
1898c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, "\nPid:\t", pid_nr_ns(pid, ns));
1908c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, "\nPPid:\t", ppid);
1918c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, "\nTracerPid:\t", tpid);
1928c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, "\nUid:\t", from_kuid_munged(user_ns, cred->uid));
1938c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, "\t", from_kuid_munged(user_ns, cred->euid));
1948c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, "\t", from_kuid_munged(user_ns, cred->suid));
1958c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, "\t", from_kuid_munged(user_ns, cred->fsuid));
1968c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, "\nGid:\t", from_kgid_munged(user_ns, cred->gid));
1978c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, "\t", from_kgid_munged(user_ns, cred->egid));
1988c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, "\t", from_kgid_munged(user_ns, cred->sgid));
1998c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, "\t", from_kgid_munged(user_ns, cred->fsgid));
2008c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, "\nFDSize:\t", max_fds);
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci	seq_puts(m, "\nGroups:\t");
2038c2ecf20Sopenharmony_ci	group_info = cred->group_info;
2048c2ecf20Sopenharmony_ci	for (g = 0; g < group_info->ngroups; g++)
2058c2ecf20Sopenharmony_ci		seq_put_decimal_ull(m, g ? " " : "",
2068c2ecf20Sopenharmony_ci				from_kgid_munged(user_ns, group_info->gid[g]));
2078c2ecf20Sopenharmony_ci	put_cred(cred);
2088c2ecf20Sopenharmony_ci	/* Trailing space shouldn't have been added in the first place. */
2098c2ecf20Sopenharmony_ci	seq_putc(m, ' ');
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci#ifdef CONFIG_PID_NS
2128c2ecf20Sopenharmony_ci	seq_puts(m, "\nNStgid:");
2138c2ecf20Sopenharmony_ci	for (g = ns->level; g <= pid->level; g++)
2148c2ecf20Sopenharmony_ci		seq_put_decimal_ull(m, "\t", task_tgid_nr_ns(p, pid->numbers[g].ns));
2158c2ecf20Sopenharmony_ci	seq_puts(m, "\nNSpid:");
2168c2ecf20Sopenharmony_ci	for (g = ns->level; g <= pid->level; g++)
2178c2ecf20Sopenharmony_ci		seq_put_decimal_ull(m, "\t", task_pid_nr_ns(p, pid->numbers[g].ns));
2188c2ecf20Sopenharmony_ci	seq_puts(m, "\nNSpgid:");
2198c2ecf20Sopenharmony_ci	for (g = ns->level; g <= pid->level; g++)
2208c2ecf20Sopenharmony_ci		seq_put_decimal_ull(m, "\t", task_pgrp_nr_ns(p, pid->numbers[g].ns));
2218c2ecf20Sopenharmony_ci	seq_puts(m, "\nNSsid:");
2228c2ecf20Sopenharmony_ci	for (g = ns->level; g <= pid->level; g++)
2238c2ecf20Sopenharmony_ci		seq_put_decimal_ull(m, "\t", task_session_nr_ns(p, pid->numbers[g].ns));
2248c2ecf20Sopenharmony_ci#endif
2258c2ecf20Sopenharmony_ci	seq_putc(m, '\n');
2268c2ecf20Sopenharmony_ci}
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_civoid render_sigset_t(struct seq_file *m, const char *header,
2298c2ecf20Sopenharmony_ci				sigset_t *set)
2308c2ecf20Sopenharmony_ci{
2318c2ecf20Sopenharmony_ci	int i;
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci	seq_puts(m, header);
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci	i = _NSIG;
2368c2ecf20Sopenharmony_ci	do {
2378c2ecf20Sopenharmony_ci		int x = 0;
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci		i -= 4;
2408c2ecf20Sopenharmony_ci		if (sigismember(set, i+1)) x |= 1;
2418c2ecf20Sopenharmony_ci		if (sigismember(set, i+2)) x |= 2;
2428c2ecf20Sopenharmony_ci		if (sigismember(set, i+3)) x |= 4;
2438c2ecf20Sopenharmony_ci		if (sigismember(set, i+4)) x |= 8;
2448c2ecf20Sopenharmony_ci		seq_putc(m, hex_asc[x]);
2458c2ecf20Sopenharmony_ci	} while (i >= 4);
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	seq_putc(m, '\n');
2488c2ecf20Sopenharmony_ci}
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_cistatic void collect_sigign_sigcatch(struct task_struct *p, sigset_t *sigign,
2518c2ecf20Sopenharmony_ci				    sigset_t *sigcatch)
2528c2ecf20Sopenharmony_ci{
2538c2ecf20Sopenharmony_ci	struct k_sigaction *k;
2548c2ecf20Sopenharmony_ci	int i;
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci	k = p->sighand->action;
2578c2ecf20Sopenharmony_ci	for (i = 1; i <= _NSIG; ++i, ++k) {
2588c2ecf20Sopenharmony_ci		if (k->sa.sa_handler == SIG_IGN)
2598c2ecf20Sopenharmony_ci			sigaddset(sigign, i);
2608c2ecf20Sopenharmony_ci		else if (k->sa.sa_handler != SIG_DFL)
2618c2ecf20Sopenharmony_ci			sigaddset(sigcatch, i);
2628c2ecf20Sopenharmony_ci	}
2638c2ecf20Sopenharmony_ci}
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_cistatic inline void task_sig(struct seq_file *m, struct task_struct *p)
2668c2ecf20Sopenharmony_ci{
2678c2ecf20Sopenharmony_ci	unsigned long flags;
2688c2ecf20Sopenharmony_ci	sigset_t pending, shpending, blocked, ignored, caught;
2698c2ecf20Sopenharmony_ci	int num_threads = 0;
2708c2ecf20Sopenharmony_ci	unsigned int qsize = 0;
2718c2ecf20Sopenharmony_ci	unsigned long qlim = 0;
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci	sigemptyset(&pending);
2748c2ecf20Sopenharmony_ci	sigemptyset(&shpending);
2758c2ecf20Sopenharmony_ci	sigemptyset(&blocked);
2768c2ecf20Sopenharmony_ci	sigemptyset(&ignored);
2778c2ecf20Sopenharmony_ci	sigemptyset(&caught);
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci	if (lock_task_sighand(p, &flags)) {
2808c2ecf20Sopenharmony_ci		pending = p->pending.signal;
2818c2ecf20Sopenharmony_ci		shpending = p->signal->shared_pending.signal;
2828c2ecf20Sopenharmony_ci		blocked = p->blocked;
2838c2ecf20Sopenharmony_ci		collect_sigign_sigcatch(p, &ignored, &caught);
2848c2ecf20Sopenharmony_ci		num_threads = get_nr_threads(p);
2858c2ecf20Sopenharmony_ci		rcu_read_lock();  /* FIXME: is this correct? */
2868c2ecf20Sopenharmony_ci		qsize = atomic_read(&__task_cred(p)->user->sigpending);
2878c2ecf20Sopenharmony_ci		rcu_read_unlock();
2888c2ecf20Sopenharmony_ci		qlim = task_rlimit(p, RLIMIT_SIGPENDING);
2898c2ecf20Sopenharmony_ci		unlock_task_sighand(p, &flags);
2908c2ecf20Sopenharmony_ci	}
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, "Threads:\t", num_threads);
2938c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, "\nSigQ:\t", qsize);
2948c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, "/", qlim);
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ci	/* render them all */
2978c2ecf20Sopenharmony_ci	render_sigset_t(m, "\nSigPnd:\t", &pending);
2988c2ecf20Sopenharmony_ci	render_sigset_t(m, "ShdPnd:\t", &shpending);
2998c2ecf20Sopenharmony_ci	render_sigset_t(m, "SigBlk:\t", &blocked);
3008c2ecf20Sopenharmony_ci	render_sigset_t(m, "SigIgn:\t", &ignored);
3018c2ecf20Sopenharmony_ci	render_sigset_t(m, "SigCgt:\t", &caught);
3028c2ecf20Sopenharmony_ci}
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_cistatic void render_cap_t(struct seq_file *m, const char *header,
3058c2ecf20Sopenharmony_ci			kernel_cap_t *a)
3068c2ecf20Sopenharmony_ci{
3078c2ecf20Sopenharmony_ci	unsigned __capi;
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_ci	seq_puts(m, header);
3108c2ecf20Sopenharmony_ci	CAP_FOR_EACH_U32(__capi) {
3118c2ecf20Sopenharmony_ci		seq_put_hex_ll(m, NULL,
3128c2ecf20Sopenharmony_ci			   a->cap[CAP_LAST_U32 - __capi], 8);
3138c2ecf20Sopenharmony_ci	}
3148c2ecf20Sopenharmony_ci	seq_putc(m, '\n');
3158c2ecf20Sopenharmony_ci}
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_cistatic inline void task_cap(struct seq_file *m, struct task_struct *p)
3188c2ecf20Sopenharmony_ci{
3198c2ecf20Sopenharmony_ci	const struct cred *cred;
3208c2ecf20Sopenharmony_ci	kernel_cap_t cap_inheritable, cap_permitted, cap_effective,
3218c2ecf20Sopenharmony_ci			cap_bset, cap_ambient;
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_ci	rcu_read_lock();
3248c2ecf20Sopenharmony_ci	cred = __task_cred(p);
3258c2ecf20Sopenharmony_ci	cap_inheritable	= cred->cap_inheritable;
3268c2ecf20Sopenharmony_ci	cap_permitted	= cred->cap_permitted;
3278c2ecf20Sopenharmony_ci	cap_effective	= cred->cap_effective;
3288c2ecf20Sopenharmony_ci	cap_bset	= cred->cap_bset;
3298c2ecf20Sopenharmony_ci	cap_ambient	= cred->cap_ambient;
3308c2ecf20Sopenharmony_ci	rcu_read_unlock();
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci	render_cap_t(m, "CapInh:\t", &cap_inheritable);
3338c2ecf20Sopenharmony_ci	render_cap_t(m, "CapPrm:\t", &cap_permitted);
3348c2ecf20Sopenharmony_ci	render_cap_t(m, "CapEff:\t", &cap_effective);
3358c2ecf20Sopenharmony_ci	render_cap_t(m, "CapBnd:\t", &cap_bset);
3368c2ecf20Sopenharmony_ci	render_cap_t(m, "CapAmb:\t", &cap_ambient);
3378c2ecf20Sopenharmony_ci}
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_cistatic inline void task_seccomp(struct seq_file *m, struct task_struct *p)
3408c2ecf20Sopenharmony_ci{
3418c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, "NoNewPrivs:\t", task_no_new_privs(p));
3428c2ecf20Sopenharmony_ci#ifdef CONFIG_SECCOMP
3438c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, "\nSeccomp:\t", p->seccomp.mode);
3448c2ecf20Sopenharmony_ci#ifdef CONFIG_SECCOMP_FILTER
3458c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, "\nSeccomp_filters:\t",
3468c2ecf20Sopenharmony_ci			    atomic_read(&p->seccomp.filter_count));
3478c2ecf20Sopenharmony_ci#endif
3488c2ecf20Sopenharmony_ci#endif
3498c2ecf20Sopenharmony_ci	seq_puts(m, "\nSpeculation_Store_Bypass:\t");
3508c2ecf20Sopenharmony_ci	switch (arch_prctl_spec_ctrl_get(p, PR_SPEC_STORE_BYPASS)) {
3518c2ecf20Sopenharmony_ci	case -EINVAL:
3528c2ecf20Sopenharmony_ci		seq_puts(m, "unknown");
3538c2ecf20Sopenharmony_ci		break;
3548c2ecf20Sopenharmony_ci	case PR_SPEC_NOT_AFFECTED:
3558c2ecf20Sopenharmony_ci		seq_puts(m, "not vulnerable");
3568c2ecf20Sopenharmony_ci		break;
3578c2ecf20Sopenharmony_ci	case PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE:
3588c2ecf20Sopenharmony_ci		seq_puts(m, "thread force mitigated");
3598c2ecf20Sopenharmony_ci		break;
3608c2ecf20Sopenharmony_ci	case PR_SPEC_PRCTL | PR_SPEC_DISABLE:
3618c2ecf20Sopenharmony_ci		seq_puts(m, "thread mitigated");
3628c2ecf20Sopenharmony_ci		break;
3638c2ecf20Sopenharmony_ci	case PR_SPEC_PRCTL | PR_SPEC_ENABLE:
3648c2ecf20Sopenharmony_ci		seq_puts(m, "thread vulnerable");
3658c2ecf20Sopenharmony_ci		break;
3668c2ecf20Sopenharmony_ci	case PR_SPEC_DISABLE:
3678c2ecf20Sopenharmony_ci		seq_puts(m, "globally mitigated");
3688c2ecf20Sopenharmony_ci		break;
3698c2ecf20Sopenharmony_ci	default:
3708c2ecf20Sopenharmony_ci		seq_puts(m, "vulnerable");
3718c2ecf20Sopenharmony_ci		break;
3728c2ecf20Sopenharmony_ci	}
3738c2ecf20Sopenharmony_ci	seq_putc(m, '\n');
3748c2ecf20Sopenharmony_ci}
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_cistatic inline void task_context_switch_counts(struct seq_file *m,
3778c2ecf20Sopenharmony_ci						struct task_struct *p)
3788c2ecf20Sopenharmony_ci{
3798c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, "voluntary_ctxt_switches:\t", p->nvcsw);
3808c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, "\nnonvoluntary_ctxt_switches:\t", p->nivcsw);
3818c2ecf20Sopenharmony_ci	seq_putc(m, '\n');
3828c2ecf20Sopenharmony_ci}
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_cistatic void task_cpus_allowed(struct seq_file *m, struct task_struct *task)
3858c2ecf20Sopenharmony_ci{
3868c2ecf20Sopenharmony_ci	seq_printf(m, "Cpus_allowed:\t%*pb\n",
3878c2ecf20Sopenharmony_ci		   cpumask_pr_args(task->cpus_ptr));
3888c2ecf20Sopenharmony_ci	seq_printf(m, "Cpus_allowed_list:\t%*pbl\n",
3898c2ecf20Sopenharmony_ci		   cpumask_pr_args(task->cpus_ptr));
3908c2ecf20Sopenharmony_ci}
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_cistatic inline void task_core_dumping(struct seq_file *m, struct mm_struct *mm)
3938c2ecf20Sopenharmony_ci{
3948c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, "CoreDumping:\t", !!mm->core_state);
3958c2ecf20Sopenharmony_ci	seq_putc(m, '\n');
3968c2ecf20Sopenharmony_ci}
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_cistatic inline void task_thp_status(struct seq_file *m, struct mm_struct *mm)
3998c2ecf20Sopenharmony_ci{
4008c2ecf20Sopenharmony_ci	bool thp_enabled = IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE);
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci	if (thp_enabled)
4038c2ecf20Sopenharmony_ci		thp_enabled = !test_bit(MMF_DISABLE_THP, &mm->flags);
4048c2ecf20Sopenharmony_ci	seq_printf(m, "THP_enabled:\t%d\n", thp_enabled);
4058c2ecf20Sopenharmony_ci}
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ciint proc_pid_status(struct seq_file *m, struct pid_namespace *ns,
4088c2ecf20Sopenharmony_ci			struct pid *pid, struct task_struct *task)
4098c2ecf20Sopenharmony_ci{
4108c2ecf20Sopenharmony_ci	struct mm_struct *mm = get_task_mm(task);
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_ci	seq_puts(m, "Name:\t");
4138c2ecf20Sopenharmony_ci	proc_task_name(m, task, true);
4148c2ecf20Sopenharmony_ci	seq_putc(m, '\n');
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci	task_state(m, ns, pid, task);
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_ci	if (mm) {
4198c2ecf20Sopenharmony_ci		task_mem(m, mm);
4208c2ecf20Sopenharmony_ci		task_core_dumping(m, mm);
4218c2ecf20Sopenharmony_ci		task_thp_status(m, mm);
4228c2ecf20Sopenharmony_ci		mmput(mm);
4238c2ecf20Sopenharmony_ci	}
4248c2ecf20Sopenharmony_ci	task_sig(m, task);
4258c2ecf20Sopenharmony_ci	task_cap(m, task);
4268c2ecf20Sopenharmony_ci	task_seccomp(m, task);
4278c2ecf20Sopenharmony_ci	task_cpus_allowed(m, task);
4288c2ecf20Sopenharmony_ci	cpuset_task_status_allowed(m, task);
4298c2ecf20Sopenharmony_ci	task_context_switch_counts(m, task);
4308c2ecf20Sopenharmony_ci	return 0;
4318c2ecf20Sopenharmony_ci}
4328c2ecf20Sopenharmony_ci
4338c2ecf20Sopenharmony_cistatic int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
4348c2ecf20Sopenharmony_ci			struct pid *pid, struct task_struct *task, int whole)
4358c2ecf20Sopenharmony_ci{
4368c2ecf20Sopenharmony_ci	unsigned long vsize, eip, esp, wchan = 0;
4378c2ecf20Sopenharmony_ci	int priority, nice;
4388c2ecf20Sopenharmony_ci	int tty_pgrp = -1, tty_nr = 0;
4398c2ecf20Sopenharmony_ci	sigset_t sigign, sigcatch;
4408c2ecf20Sopenharmony_ci	char state;
4418c2ecf20Sopenharmony_ci	pid_t ppid = 0, pgid = -1, sid = -1;
4428c2ecf20Sopenharmony_ci	int num_threads = 0;
4438c2ecf20Sopenharmony_ci	int permitted;
4448c2ecf20Sopenharmony_ci	struct mm_struct *mm;
4458c2ecf20Sopenharmony_ci	unsigned long long start_time;
4468c2ecf20Sopenharmony_ci	unsigned long cmin_flt, cmaj_flt, min_flt, maj_flt;
4478c2ecf20Sopenharmony_ci	u64 cutime, cstime, cgtime, utime, stime, gtime;
4488c2ecf20Sopenharmony_ci	unsigned long rsslim = 0;
4498c2ecf20Sopenharmony_ci	unsigned long flags;
4508c2ecf20Sopenharmony_ci	int exit_code = task->exit_code;
4518c2ecf20Sopenharmony_ci	struct signal_struct *sig = task->signal;
4528c2ecf20Sopenharmony_ci	unsigned int seq = 1;
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci	state = *get_task_state(task);
4558c2ecf20Sopenharmony_ci	vsize = eip = esp = 0;
4568c2ecf20Sopenharmony_ci	permitted = ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS | PTRACE_MODE_NOAUDIT);
4578c2ecf20Sopenharmony_ci	mm = get_task_mm(task);
4588c2ecf20Sopenharmony_ci	if (mm) {
4598c2ecf20Sopenharmony_ci		vsize = task_vsize(mm);
4608c2ecf20Sopenharmony_ci		/*
4618c2ecf20Sopenharmony_ci		 * esp and eip are intentionally zeroed out.  There is no
4628c2ecf20Sopenharmony_ci		 * non-racy way to read them without freezing the task.
4638c2ecf20Sopenharmony_ci		 * Programs that need reliable values can use ptrace(2).
4648c2ecf20Sopenharmony_ci		 *
4658c2ecf20Sopenharmony_ci		 * The only exception is if the task is core dumping because
4668c2ecf20Sopenharmony_ci		 * a program is not able to use ptrace(2) in that case. It is
4678c2ecf20Sopenharmony_ci		 * safe because the task has stopped executing permanently.
4688c2ecf20Sopenharmony_ci		 */
4698c2ecf20Sopenharmony_ci		if (permitted && (task->flags & (PF_EXITING|PF_DUMPCORE))) {
4708c2ecf20Sopenharmony_ci			if (try_get_task_stack(task)) {
4718c2ecf20Sopenharmony_ci				eip = KSTK_EIP(task);
4728c2ecf20Sopenharmony_ci				esp = KSTK_ESP(task);
4738c2ecf20Sopenharmony_ci				put_task_stack(task);
4748c2ecf20Sopenharmony_ci			}
4758c2ecf20Sopenharmony_ci		}
4768c2ecf20Sopenharmony_ci	}
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_ci	sigemptyset(&sigign);
4798c2ecf20Sopenharmony_ci	sigemptyset(&sigcatch);
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_ci	if (lock_task_sighand(task, &flags)) {
4828c2ecf20Sopenharmony_ci		if (sig->tty) {
4838c2ecf20Sopenharmony_ci			struct pid *pgrp = tty_get_pgrp(sig->tty);
4848c2ecf20Sopenharmony_ci			tty_pgrp = pid_nr_ns(pgrp, ns);
4858c2ecf20Sopenharmony_ci			put_pid(pgrp);
4868c2ecf20Sopenharmony_ci			tty_nr = new_encode_dev(tty_devnum(sig->tty));
4878c2ecf20Sopenharmony_ci		}
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_ci		num_threads = get_nr_threads(task);
4908c2ecf20Sopenharmony_ci		collect_sigign_sigcatch(task, &sigign, &sigcatch);
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_ci		rsslim = READ_ONCE(sig->rlim[RLIMIT_RSS].rlim_cur);
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_ci		if (whole) {
4958c2ecf20Sopenharmony_ci			if (sig->flags & (SIGNAL_GROUP_EXIT | SIGNAL_STOP_STOPPED))
4968c2ecf20Sopenharmony_ci				exit_code = sig->group_exit_code;
4978c2ecf20Sopenharmony_ci		}
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_ci		sid = task_session_nr_ns(task, ns);
5008c2ecf20Sopenharmony_ci		ppid = task_tgid_nr_ns(task->real_parent, ns);
5018c2ecf20Sopenharmony_ci		pgid = task_pgrp_nr_ns(task, ns);
5028c2ecf20Sopenharmony_ci
5038c2ecf20Sopenharmony_ci		unlock_task_sighand(task, &flags);
5048c2ecf20Sopenharmony_ci	}
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ci	if (permitted && (!whole || num_threads < 2))
5078c2ecf20Sopenharmony_ci		wchan = get_wchan(task);
5088c2ecf20Sopenharmony_ci
5098c2ecf20Sopenharmony_ci	do {
5108c2ecf20Sopenharmony_ci		seq++; /* 2 on the 1st/lockless path, otherwise odd */
5118c2ecf20Sopenharmony_ci		flags = read_seqbegin_or_lock_irqsave(&sig->stats_lock, &seq);
5128c2ecf20Sopenharmony_ci
5138c2ecf20Sopenharmony_ci		cmin_flt = sig->cmin_flt;
5148c2ecf20Sopenharmony_ci		cmaj_flt = sig->cmaj_flt;
5158c2ecf20Sopenharmony_ci		cutime = sig->cutime;
5168c2ecf20Sopenharmony_ci		cstime = sig->cstime;
5178c2ecf20Sopenharmony_ci		cgtime = sig->cgtime;
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_ci		if (whole) {
5208c2ecf20Sopenharmony_ci			struct task_struct *t;
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_ci			min_flt = sig->min_flt;
5238c2ecf20Sopenharmony_ci			maj_flt = sig->maj_flt;
5248c2ecf20Sopenharmony_ci			gtime = sig->gtime;
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_ci			rcu_read_lock();
5278c2ecf20Sopenharmony_ci			__for_each_thread(sig, t) {
5288c2ecf20Sopenharmony_ci				min_flt += t->min_flt;
5298c2ecf20Sopenharmony_ci				maj_flt += t->maj_flt;
5308c2ecf20Sopenharmony_ci				gtime += task_gtime(t);
5318c2ecf20Sopenharmony_ci			}
5328c2ecf20Sopenharmony_ci			rcu_read_unlock();
5338c2ecf20Sopenharmony_ci		}
5348c2ecf20Sopenharmony_ci	} while (need_seqretry(&sig->stats_lock, seq));
5358c2ecf20Sopenharmony_ci	done_seqretry_irqrestore(&sig->stats_lock, seq, flags);
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_ci	if (whole) {
5388c2ecf20Sopenharmony_ci		thread_group_cputime_adjusted(task, &utime, &stime);
5398c2ecf20Sopenharmony_ci	} else {
5408c2ecf20Sopenharmony_ci		task_cputime_adjusted(task, &utime, &stime);
5418c2ecf20Sopenharmony_ci		min_flt = task->min_flt;
5428c2ecf20Sopenharmony_ci		maj_flt = task->maj_flt;
5438c2ecf20Sopenharmony_ci		gtime = task_gtime(task);
5448c2ecf20Sopenharmony_ci	}
5458c2ecf20Sopenharmony_ci
5468c2ecf20Sopenharmony_ci	/* scale priority and nice values from timeslices to -20..20 */
5478c2ecf20Sopenharmony_ci	/* to make it look like a "normal" Unix priority/nice value  */
5488c2ecf20Sopenharmony_ci	priority = task_prio(task);
5498c2ecf20Sopenharmony_ci	nice = task_nice(task);
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_ci	/* convert nsec -> ticks */
5528c2ecf20Sopenharmony_ci	start_time = nsec_to_clock_t(task->start_boottime);
5538c2ecf20Sopenharmony_ci
5548c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, "", pid_nr_ns(pid, ns));
5558c2ecf20Sopenharmony_ci	seq_puts(m, " (");
5568c2ecf20Sopenharmony_ci	proc_task_name(m, task, false);
5578c2ecf20Sopenharmony_ci	seq_puts(m, ") ");
5588c2ecf20Sopenharmony_ci	seq_putc(m, state);
5598c2ecf20Sopenharmony_ci	seq_put_decimal_ll(m, " ", ppid);
5608c2ecf20Sopenharmony_ci	seq_put_decimal_ll(m, " ", pgid);
5618c2ecf20Sopenharmony_ci	seq_put_decimal_ll(m, " ", sid);
5628c2ecf20Sopenharmony_ci	seq_put_decimal_ll(m, " ", tty_nr);
5638c2ecf20Sopenharmony_ci	seq_put_decimal_ll(m, " ", tty_pgrp);
5648c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, " ", task->flags);
5658c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, " ", min_flt);
5668c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, " ", cmin_flt);
5678c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, " ", maj_flt);
5688c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, " ", cmaj_flt);
5698c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, " ", nsec_to_clock_t(utime));
5708c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, " ", nsec_to_clock_t(stime));
5718c2ecf20Sopenharmony_ci	seq_put_decimal_ll(m, " ", nsec_to_clock_t(cutime));
5728c2ecf20Sopenharmony_ci	seq_put_decimal_ll(m, " ", nsec_to_clock_t(cstime));
5738c2ecf20Sopenharmony_ci	seq_put_decimal_ll(m, " ", priority);
5748c2ecf20Sopenharmony_ci	seq_put_decimal_ll(m, " ", nice);
5758c2ecf20Sopenharmony_ci	seq_put_decimal_ll(m, " ", num_threads);
5768c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, " ", 0);
5778c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, " ", start_time);
5788c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, " ", vsize);
5798c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, " ", mm ? get_mm_rss(mm) : 0);
5808c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, " ", rsslim);
5818c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, " ", mm ? (permitted ? mm->start_code : 1) : 0);
5828c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, " ", mm ? (permitted ? mm->end_code : 1) : 0);
5838c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, " ", (permitted && mm) ? mm->start_stack : 0);
5848c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, " ", esp);
5858c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, " ", eip);
5868c2ecf20Sopenharmony_ci	/* The signal information here is obsolete.
5878c2ecf20Sopenharmony_ci	 * It must be decimal for Linux 2.0 compatibility.
5888c2ecf20Sopenharmony_ci	 * Use /proc/#/status for real-time signals.
5898c2ecf20Sopenharmony_ci	 */
5908c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, " ", task->pending.signal.sig[0] & 0x7fffffffUL);
5918c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, " ", task->blocked.sig[0] & 0x7fffffffUL);
5928c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, " ", sigign.sig[0] & 0x7fffffffUL);
5938c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, " ", sigcatch.sig[0] & 0x7fffffffUL);
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci	/*
5968c2ecf20Sopenharmony_ci	 * We used to output the absolute kernel address, but that's an
5978c2ecf20Sopenharmony_ci	 * information leak - so instead we show a 0/1 flag here, to signal
5988c2ecf20Sopenharmony_ci	 * to user-space whether there's a wchan field in /proc/PID/wchan.
5998c2ecf20Sopenharmony_ci	 *
6008c2ecf20Sopenharmony_ci	 * This works with older implementations of procps as well.
6018c2ecf20Sopenharmony_ci	 */
6028c2ecf20Sopenharmony_ci	if (wchan)
6038c2ecf20Sopenharmony_ci		seq_puts(m, " 1");
6048c2ecf20Sopenharmony_ci	else
6058c2ecf20Sopenharmony_ci		seq_puts(m, " 0");
6068c2ecf20Sopenharmony_ci
6078c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, " ", 0);
6088c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, " ", 0);
6098c2ecf20Sopenharmony_ci	seq_put_decimal_ll(m, " ", task->exit_signal);
6108c2ecf20Sopenharmony_ci	seq_put_decimal_ll(m, " ", task_cpu(task));
6118c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, " ", task->rt_priority);
6128c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, " ", task->policy);
6138c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, " ", delayacct_blkio_ticks(task));
6148c2ecf20Sopenharmony_ci	seq_put_decimal_ull(m, " ", nsec_to_clock_t(gtime));
6158c2ecf20Sopenharmony_ci	seq_put_decimal_ll(m, " ", nsec_to_clock_t(cgtime));
6168c2ecf20Sopenharmony_ci
6178c2ecf20Sopenharmony_ci	if (mm && permitted) {
6188c2ecf20Sopenharmony_ci		seq_put_decimal_ull(m, " ", mm->start_data);
6198c2ecf20Sopenharmony_ci		seq_put_decimal_ull(m, " ", mm->end_data);
6208c2ecf20Sopenharmony_ci		seq_put_decimal_ull(m, " ", mm->start_brk);
6218c2ecf20Sopenharmony_ci		seq_put_decimal_ull(m, " ", mm->arg_start);
6228c2ecf20Sopenharmony_ci		seq_put_decimal_ull(m, " ", mm->arg_end);
6238c2ecf20Sopenharmony_ci		seq_put_decimal_ull(m, " ", mm->env_start);
6248c2ecf20Sopenharmony_ci		seq_put_decimal_ull(m, " ", mm->env_end);
6258c2ecf20Sopenharmony_ci	} else
6268c2ecf20Sopenharmony_ci		seq_puts(m, " 0 0 0 0 0 0 0");
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_ci	if (permitted)
6298c2ecf20Sopenharmony_ci		seq_put_decimal_ll(m, " ", exit_code);
6308c2ecf20Sopenharmony_ci	else
6318c2ecf20Sopenharmony_ci		seq_puts(m, " 0");
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_ci	seq_putc(m, '\n');
6348c2ecf20Sopenharmony_ci	if (mm)
6358c2ecf20Sopenharmony_ci		mmput(mm);
6368c2ecf20Sopenharmony_ci	return 0;
6378c2ecf20Sopenharmony_ci}
6388c2ecf20Sopenharmony_ci
6398c2ecf20Sopenharmony_ciint proc_tid_stat(struct seq_file *m, struct pid_namespace *ns,
6408c2ecf20Sopenharmony_ci			struct pid *pid, struct task_struct *task)
6418c2ecf20Sopenharmony_ci{
6428c2ecf20Sopenharmony_ci	return do_task_stat(m, ns, pid, task, 0);
6438c2ecf20Sopenharmony_ci}
6448c2ecf20Sopenharmony_ci
6458c2ecf20Sopenharmony_ciint proc_tgid_stat(struct seq_file *m, struct pid_namespace *ns,
6468c2ecf20Sopenharmony_ci			struct pid *pid, struct task_struct *task)
6478c2ecf20Sopenharmony_ci{
6488c2ecf20Sopenharmony_ci	return do_task_stat(m, ns, pid, task, 1);
6498c2ecf20Sopenharmony_ci}
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_ciint proc_pid_statm(struct seq_file *m, struct pid_namespace *ns,
6528c2ecf20Sopenharmony_ci			struct pid *pid, struct task_struct *task)
6538c2ecf20Sopenharmony_ci{
6548c2ecf20Sopenharmony_ci	struct mm_struct *mm = get_task_mm(task);
6558c2ecf20Sopenharmony_ci
6568c2ecf20Sopenharmony_ci	if (mm) {
6578c2ecf20Sopenharmony_ci		unsigned long size;
6588c2ecf20Sopenharmony_ci		unsigned long resident = 0;
6598c2ecf20Sopenharmony_ci		unsigned long shared = 0;
6608c2ecf20Sopenharmony_ci		unsigned long text = 0;
6618c2ecf20Sopenharmony_ci		unsigned long data = 0;
6628c2ecf20Sopenharmony_ci
6638c2ecf20Sopenharmony_ci		size = task_statm(mm, &shared, &text, &data, &resident);
6648c2ecf20Sopenharmony_ci		mmput(mm);
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_ci		/*
6678c2ecf20Sopenharmony_ci		 * For quick read, open code by putting numbers directly
6688c2ecf20Sopenharmony_ci		 * expected format is
6698c2ecf20Sopenharmony_ci		 * seq_printf(m, "%lu %lu %lu %lu 0 %lu 0\n",
6708c2ecf20Sopenharmony_ci		 *               size, resident, shared, text, data);
6718c2ecf20Sopenharmony_ci		 */
6728c2ecf20Sopenharmony_ci		seq_put_decimal_ull(m, "", size);
6738c2ecf20Sopenharmony_ci		seq_put_decimal_ull(m, " ", resident);
6748c2ecf20Sopenharmony_ci		seq_put_decimal_ull(m, " ", shared);
6758c2ecf20Sopenharmony_ci		seq_put_decimal_ull(m, " ", text);
6768c2ecf20Sopenharmony_ci		seq_put_decimal_ull(m, " ", 0);
6778c2ecf20Sopenharmony_ci		seq_put_decimal_ull(m, " ", data);
6788c2ecf20Sopenharmony_ci		seq_put_decimal_ull(m, " ", 0);
6798c2ecf20Sopenharmony_ci		seq_putc(m, '\n');
6808c2ecf20Sopenharmony_ci	} else {
6818c2ecf20Sopenharmony_ci		seq_write(m, "0 0 0 0 0 0 0\n", 14);
6828c2ecf20Sopenharmony_ci	}
6838c2ecf20Sopenharmony_ci	return 0;
6848c2ecf20Sopenharmony_ci}
6858c2ecf20Sopenharmony_ci
6868c2ecf20Sopenharmony_ci#ifdef CONFIG_PROC_CHILDREN
6878c2ecf20Sopenharmony_cistatic struct pid *
6888c2ecf20Sopenharmony_ciget_children_pid(struct inode *inode, struct pid *pid_prev, loff_t pos)
6898c2ecf20Sopenharmony_ci{
6908c2ecf20Sopenharmony_ci	struct task_struct *start, *task;
6918c2ecf20Sopenharmony_ci	struct pid *pid = NULL;
6928c2ecf20Sopenharmony_ci
6938c2ecf20Sopenharmony_ci	read_lock(&tasklist_lock);
6948c2ecf20Sopenharmony_ci
6958c2ecf20Sopenharmony_ci	start = pid_task(proc_pid(inode), PIDTYPE_PID);
6968c2ecf20Sopenharmony_ci	if (!start)
6978c2ecf20Sopenharmony_ci		goto out;
6988c2ecf20Sopenharmony_ci
6998c2ecf20Sopenharmony_ci	/*
7008c2ecf20Sopenharmony_ci	 * Lets try to continue searching first, this gives
7018c2ecf20Sopenharmony_ci	 * us significant speedup on children-rich processes.
7028c2ecf20Sopenharmony_ci	 */
7038c2ecf20Sopenharmony_ci	if (pid_prev) {
7048c2ecf20Sopenharmony_ci		task = pid_task(pid_prev, PIDTYPE_PID);
7058c2ecf20Sopenharmony_ci		if (task && task->real_parent == start &&
7068c2ecf20Sopenharmony_ci		    !(list_empty(&task->sibling))) {
7078c2ecf20Sopenharmony_ci			if (list_is_last(&task->sibling, &start->children))
7088c2ecf20Sopenharmony_ci				goto out;
7098c2ecf20Sopenharmony_ci			task = list_first_entry(&task->sibling,
7108c2ecf20Sopenharmony_ci						struct task_struct, sibling);
7118c2ecf20Sopenharmony_ci			pid = get_pid(task_pid(task));
7128c2ecf20Sopenharmony_ci			goto out;
7138c2ecf20Sopenharmony_ci		}
7148c2ecf20Sopenharmony_ci	}
7158c2ecf20Sopenharmony_ci
7168c2ecf20Sopenharmony_ci	/*
7178c2ecf20Sopenharmony_ci	 * Slow search case.
7188c2ecf20Sopenharmony_ci	 *
7198c2ecf20Sopenharmony_ci	 * We might miss some children here if children
7208c2ecf20Sopenharmony_ci	 * are exited while we were not holding the lock,
7218c2ecf20Sopenharmony_ci	 * but it was never promised to be accurate that
7228c2ecf20Sopenharmony_ci	 * much.
7238c2ecf20Sopenharmony_ci	 *
7248c2ecf20Sopenharmony_ci	 * "Just suppose that the parent sleeps, but N children
7258c2ecf20Sopenharmony_ci	 *  exit after we printed their tids. Now the slow paths
7268c2ecf20Sopenharmony_ci	 *  skips N extra children, we miss N tasks." (c)
7278c2ecf20Sopenharmony_ci	 *
7288c2ecf20Sopenharmony_ci	 * So one need to stop or freeze the leader and all
7298c2ecf20Sopenharmony_ci	 * its children to get a precise result.
7308c2ecf20Sopenharmony_ci	 */
7318c2ecf20Sopenharmony_ci	list_for_each_entry(task, &start->children, sibling) {
7328c2ecf20Sopenharmony_ci		if (pos-- == 0) {
7338c2ecf20Sopenharmony_ci			pid = get_pid(task_pid(task));
7348c2ecf20Sopenharmony_ci			break;
7358c2ecf20Sopenharmony_ci		}
7368c2ecf20Sopenharmony_ci	}
7378c2ecf20Sopenharmony_ci
7388c2ecf20Sopenharmony_ciout:
7398c2ecf20Sopenharmony_ci	read_unlock(&tasklist_lock);
7408c2ecf20Sopenharmony_ci	return pid;
7418c2ecf20Sopenharmony_ci}
7428c2ecf20Sopenharmony_ci
7438c2ecf20Sopenharmony_cistatic int children_seq_show(struct seq_file *seq, void *v)
7448c2ecf20Sopenharmony_ci{
7458c2ecf20Sopenharmony_ci	struct inode *inode = file_inode(seq->file);
7468c2ecf20Sopenharmony_ci
7478c2ecf20Sopenharmony_ci	seq_printf(seq, "%d ", pid_nr_ns(v, proc_pid_ns(inode->i_sb)));
7488c2ecf20Sopenharmony_ci	return 0;
7498c2ecf20Sopenharmony_ci}
7508c2ecf20Sopenharmony_ci
7518c2ecf20Sopenharmony_cistatic void *children_seq_start(struct seq_file *seq, loff_t *pos)
7528c2ecf20Sopenharmony_ci{
7538c2ecf20Sopenharmony_ci	return get_children_pid(file_inode(seq->file), NULL, *pos);
7548c2ecf20Sopenharmony_ci}
7558c2ecf20Sopenharmony_ci
7568c2ecf20Sopenharmony_cistatic void *children_seq_next(struct seq_file *seq, void *v, loff_t *pos)
7578c2ecf20Sopenharmony_ci{
7588c2ecf20Sopenharmony_ci	struct pid *pid;
7598c2ecf20Sopenharmony_ci
7608c2ecf20Sopenharmony_ci	pid = get_children_pid(file_inode(seq->file), v, *pos + 1);
7618c2ecf20Sopenharmony_ci	put_pid(v);
7628c2ecf20Sopenharmony_ci
7638c2ecf20Sopenharmony_ci	++*pos;
7648c2ecf20Sopenharmony_ci	return pid;
7658c2ecf20Sopenharmony_ci}
7668c2ecf20Sopenharmony_ci
7678c2ecf20Sopenharmony_cistatic void children_seq_stop(struct seq_file *seq, void *v)
7688c2ecf20Sopenharmony_ci{
7698c2ecf20Sopenharmony_ci	put_pid(v);
7708c2ecf20Sopenharmony_ci}
7718c2ecf20Sopenharmony_ci
7728c2ecf20Sopenharmony_cistatic const struct seq_operations children_seq_ops = {
7738c2ecf20Sopenharmony_ci	.start	= children_seq_start,
7748c2ecf20Sopenharmony_ci	.next	= children_seq_next,
7758c2ecf20Sopenharmony_ci	.stop	= children_seq_stop,
7768c2ecf20Sopenharmony_ci	.show	= children_seq_show,
7778c2ecf20Sopenharmony_ci};
7788c2ecf20Sopenharmony_ci
7798c2ecf20Sopenharmony_cistatic int children_seq_open(struct inode *inode, struct file *file)
7808c2ecf20Sopenharmony_ci{
7818c2ecf20Sopenharmony_ci	return seq_open(file, &children_seq_ops);
7828c2ecf20Sopenharmony_ci}
7838c2ecf20Sopenharmony_ci
7848c2ecf20Sopenharmony_ciconst struct file_operations proc_tid_children_operations = {
7858c2ecf20Sopenharmony_ci	.open    = children_seq_open,
7868c2ecf20Sopenharmony_ci	.read    = seq_read,
7878c2ecf20Sopenharmony_ci	.llseek  = seq_lseek,
7888c2ecf20Sopenharmony_ci	.release = seq_release,
7898c2ecf20Sopenharmony_ci};
7908c2ecf20Sopenharmony_ci#endif /* CONFIG_PROC_CHILDREN */
791