326 lines
12 KiB
Diff
326 lines
12 KiB
Diff
commit a01ee3c0b32d4c39aa83066ed61103343469527e
|
|
Author: Aristeu Rozanski <arozansk@redhat.com>
|
|
Date: Mon Apr 8 15:03:13 2013 -0400
|
|
|
|
procps: add support for linux namespaces
|
|
|
|
Each process in Linux has a /proc/<pid>/ns directory which contains
|
|
symbolic links to pipes that identify which namespaces that process
|
|
belongs to. This patch adds support for ps to display that information
|
|
optionally.
|
|
|
|
Signed-off-by: Aristeu Rozanski <arozansk@redhat.com>
|
|
|
|
---
|
|
proc/libprocps.sym | 2 +
|
|
proc/readproc.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
proc/readproc.h | 15 +++++++++++++
|
|
ps/output.c | 38 ++++++++++++++++++++++++++++++++++
|
|
ps/ps.1 | 24 +++++++++++++++++++++
|
|
5 files changed, 137 insertions(+)
|
|
|
|
--- procps-ng-3.3.8.orig/proc/libprocps.sym 2013-05-25 17:39:40.000000000 -0400
|
|
+++ procps-ng-3.3.8/proc/libprocps.sym 2013-09-17 16:09:45.496846630 -0400
|
|
@@ -11,6 +11,8 @@ global:
|
|
escaped_copy;
|
|
free_slabinfo;
|
|
freeproc;
|
|
+ get_ns_id;
|
|
+ get_ns_name;
|
|
get_pid_digits;
|
|
get_slabinfo;
|
|
getbtime;
|
|
--- procps-ng-3.3.8.orig/proc/readproc.c 2013-05-25 17:39:40.000000000 -0400
|
|
+++ procps-ng-3.3.8/proc/readproc.c 2013-09-17 16:09:45.498846654 -0400
|
|
@@ -457,6 +457,51 @@ static void oomadj2proc(const char* S, p
|
|
#endif
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
+static ino_t _ns2proc(unsigned pid, const char *ns)
|
|
+{
|
|
+ struct stat s;
|
|
+ char filename[40];
|
|
+
|
|
+ snprintf(filename, sizeof(filename), "/proc/%i/ns/%s", pid, ns);
|
|
+
|
|
+ if (stat(filename, &s) == -1)
|
|
+ return 0;
|
|
+
|
|
+ return s.st_ino;
|
|
+}
|
|
+
|
|
+static const char *ns_names[] = {
|
|
+ [IPCNS] = "ipc",
|
|
+ [MNTNS] = "mnt",
|
|
+ [NETNS] = "net",
|
|
+ [PIDNS] = "pid",
|
|
+ [USERNS] = "user",
|
|
+ [UTSNS] = "uts",
|
|
+};
|
|
+
|
|
+const char *get_ns_name(int id) {
|
|
+ if (id >= NUM_NS)
|
|
+ return NULL;
|
|
+ return ns_names[id];
|
|
+}
|
|
+
|
|
+int get_ns_id(const char *name) {
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < NUM_NS; i++)
|
|
+ if (!strcmp(ns_names[i], name))
|
|
+ return i;
|
|
+ return -1;
|
|
+}
|
|
+
|
|
+static void ns2proc(proc_t *restrict P) {
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < NUM_NS; i++)
|
|
+ P->ns[i] = _ns2proc(P->tgid, ns_names[i]);
|
|
+}
|
|
+///////////////////////////////////////////////////////////////////////
|
|
+
|
|
|
|
// Reads /proc/*/stat files, being careful not to trip over processes with
|
|
// names like ":-) 1 2 3 4 5 6".
|
|
@@ -757,6 +802,7 @@ static struct utlbuf_s ub = { NULL,
|
|
static struct stat sb; // stat() buffer
|
|
char *restrict const path = PT->path;
|
|
unsigned flags = PT->flags;
|
|
+ int i;
|
|
|
|
if (unlikely(stat(path, &sb) == -1)) /* no such dirent (anymore) */
|
|
goto next_proc;
|
|
@@ -844,6 +890,12 @@ p->wchan = (KLONG)~0ull;
|
|
}
|
|
#endif
|
|
|
|
+ if (unlikely(flags & PROC_FILLNS)) // read /proc/#/ns/*
|
|
+ ns2proc(p);
|
|
+ else
|
|
+ for (i = 0; i < NUM_NS; i++)
|
|
+ p->ns[i] = 0;
|
|
+
|
|
return p;
|
|
next_proc:
|
|
return NULL;
|
|
@@ -862,6 +914,7 @@ static proc_t* simple_readtask(PROCTAB *
|
|
static struct utlbuf_s ub = { NULL, 0 }; // buf for stat,statm,status
|
|
static struct stat sb; // stat() buffer
|
|
unsigned flags = PT->flags;
|
|
+ int i;
|
|
|
|
if (unlikely(stat(path, &sb) == -1)) /* no such dirent (anymore) */
|
|
goto next_task;
|
|
@@ -974,6 +1027,11 @@ status2proc(ub.buf, t, 0);
|
|
oomadj2proc(ub.buf, t);
|
|
}
|
|
#endif
|
|
+ if (unlikely(flags & PROC_FILLNS))
|
|
+ ns2proc(t);
|
|
+ else
|
|
+ for (i = 0; i < NUM_NS; i++)
|
|
+ t->ns[i] = 0;
|
|
|
|
return t;
|
|
next_task:
|
|
--- procps-ng-3.3.8.orig/proc/readproc.h 2013-05-25 17:39:40.000000000 -0400
|
|
+++ procps-ng-3.3.8/proc/readproc.h 2013-09-17 16:09:45.499846666 -0400
|
|
@@ -31,6 +31,18 @@ EXTERN_C_BEGIN
|
|
// neither tgid nor tid seemed correct. (in other words, FIXME)
|
|
#define XXXID tid
|
|
|
|
+#define NUM_NS 6
|
|
+enum ns_type {
|
|
+ IPCNS = 0,
|
|
+ MNTNS,
|
|
+ NETNS,
|
|
+ PIDNS,
|
|
+ USERNS,
|
|
+ UTSNS
|
|
+};
|
|
+extern const char *get_ns_name(int id);
|
|
+extern int get_ns_id(const char *name);
|
|
+
|
|
// Basic data structure which holds all information we can get about a process.
|
|
// (unless otherwise specified, fields are read from /proc/#/stat)
|
|
//
|
|
@@ -157,6 +169,8 @@ nlwp, // stat,status number of thr
|
|
oom_score, // oom_score (badness for OOM killer)
|
|
oom_adj; // oom_adj (adjustment to OOM score)
|
|
#endif
|
|
+ ino_t
|
|
+ ns[NUM_NS]; // ns/* inode number of /proc/<pid>/ns/*
|
|
} proc_t;
|
|
|
|
// PROCTAB: data structure holding the persistent information readproc needs
|
|
@@ -266,6 +280,7 @@ #define PROC_FILLARG 0x0100 // a
|
|
#define PROC_FILLCGROUP 0x0200 // alloc and fill in `cgroup`
|
|
#define PROC_FILLSUPGRP 0x0400 // resolve supplementary group id -> group name
|
|
#define PROC_FILLOOM 0x0800 // fill in proc_t oom_score and oom_adj
|
|
+#define PROC_FILLNS 0x8000 // fill in proc_t namespace information
|
|
|
|
#define PROC_LOOSE_TASKS 0x2000 // treat threads as if they were processes
|
|
|
|
--- procps-ng-3.3.8.orig/ps/output.c 2013-09-17 16:08:53.000000000 -0400
|
|
+++ procps-ng-3.3.8/ps/output.c 2013-09-17 16:10:41.087532129 -0400
|
|
@@ -139,6 +139,13 @@ static int sr_ ## NAME (const proc_t* P,
|
|
return 0; \
|
|
}
|
|
|
|
+#define CMP_NS(NAME, ID) \
|
|
+static int sr_ ## NAME (const proc_t* P, const proc_t* Q) { \
|
|
+ if (P->ns[ID] < Q->ns[ID]) return -1; \
|
|
+ if (P->ns[ID] > Q->ns[ID]) return 1; \
|
|
+ return 0; \
|
|
+}
|
|
+
|
|
CMP_INT(rtprio)
|
|
CMP_SMALL(sched)
|
|
CMP_INT(cutime)
|
|
@@ -216,6 +223,13 @@ CMP_SMALL(state)
|
|
CMP_COOKED_TIME(time)
|
|
CMP_COOKED_TIME(etime)
|
|
|
|
+CMP_NS(ipcns, IPCNS);
|
|
+CMP_NS(mntns, MNTNS);
|
|
+CMP_NS(netns, NETNS);
|
|
+CMP_NS(pidns, PIDNS);
|
|
+CMP_NS(userns, USERNS);
|
|
+CMP_NS(utsns, UTSNS);
|
|
+
|
|
/* approximation to: kB of address space that could end up in swap */
|
|
static int sr_swapable(const proc_t* P, const proc_t* Q) {
|
|
unsigned long p_swapable = P->vm_data + P->vm_stack;
|
|
@@ -1279,6 +1293,23 @@ outbuf[1] = '\0';
|
|
}
|
|
|
|
#endif
|
|
+
|
|
+/************************ Linux namespaces ******************************/
|
|
+
|
|
+#define _pr_ns(NAME, ID)\
|
|
+static int pr_##NAME(char *restrict const outbuf, const proc_t *restrict const pp) {\
|
|
+ if (pp->ns[ID])\
|
|
+ return snprintf(outbuf, COLWID, "%li", pp->ns[ID]);\
|
|
+ else\
|
|
+ return snprintf(outbuf, COLWID, "-");\
|
|
+}
|
|
+_pr_ns(ipcns, IPCNS);
|
|
+_pr_ns(mntns, MNTNS);
|
|
+_pr_ns(netns, NETNS);
|
|
+_pr_ns(pidns, PIDNS);
|
|
+_pr_ns(userns, USERNS);
|
|
+_pr_ns(utsns, UTSNS);
|
|
+
|
|
/****************** FLASK & seLinux security stuff **********************/
|
|
// move the bulk of this to libproc sometime
|
|
|
|
@@ -1439,6 +1470,7 @@ static const char *const vals[] = {"tt
|
|
#define USR PROC_FILLUSR /* uid_t -> user names */
|
|
#define GRP PROC_FILLGRP /* gid_t -> group names */
|
|
#define WCH PROC_FILLWCHAN /* do WCHAN lookup */
|
|
+#define NS PROC_FILLNS /* read namespace information */
|
|
|
|
#define SGRP PROC_FILLSTATUS | PROC_FILLSUPGRP /* supgid -> supgrp (names) */
|
|
#define CGRP PROC_FILLCGROUP | PROC_EDITCGRPCVT /* read cgroup */
|
|
@@ -1527,6 +1559,7 @@ {"ignored", "IGNORED", pr_sigignore,sr
|
|
{"inblk", "INBLK", pr_nop, sr_nop, 5, 0, BSD, AN|RIGHT}, /*inblock*/
|
|
{"inblock", "INBLK", pr_nop, sr_nop, 5, 0, DEC, AN|RIGHT}, /*inblk*/
|
|
{"intpri", "PRI", pr_opri, sr_priority, 3, 0, HPU, TO|RIGHT},
|
|
+{"ipcns", "IPCNS", pr_ipcns, sr_ipcns, 10, NS, LNX, ET|RIGHT},
|
|
{"jid", "JID", pr_nop, sr_nop, 1, 0, SGI, PO|RIGHT},
|
|
{"jobc", "JOBC", pr_nop, sr_nop, 4, 0, XXX, AN|RIGHT},
|
|
{"ktrace", "KTRACE", pr_nop, sr_nop, 8, 0, BSD, AN|RIGHT},
|
|
@@ -1559,9 +1592,11 @@ {"maj_flt", "MAJFL", pr_majflt, sr
|
|
{"majflt", "MAJFLT", pr_majflt, sr_maj_flt, 6, 0, XXX, AN|RIGHT},
|
|
{"min_flt", "MINFL", pr_minflt, sr_min_flt, 6, 0, LNX, AN|RIGHT},
|
|
{"minflt", "MINFLT", pr_minflt, sr_min_flt, 6, 0, XXX, AN|RIGHT},
|
|
+{"mntns", "MNTNS", pr_mntns, sr_mntns, 10, NS, LNX, ET|RIGHT},
|
|
{"msgrcv", "MSGRCV", pr_nop, sr_nop, 6, 0, XXX, AN|RIGHT},
|
|
{"msgsnd", "MSGSND", pr_nop, sr_nop, 6, 0, XXX, AN|RIGHT},
|
|
{"mwchan", "MWCHAN", pr_nop, sr_nop, 6, WCH, BSD, TO|WCHAN}, /* mutex (FreeBSD) */
|
|
+{"netns", "NETNS", pr_netns, sr_netns, 10, NS, LNX, ET|RIGHT},
|
|
{"ni", "NI", pr_nice, sr_nice, 3, 0, BSD, TO|RIGHT}, /*nice*/
|
|
{"nice", "NI", pr_nice, sr_nice, 3, 0, U98, TO|RIGHT}, /*ni*/
|
|
{"nivcsw", "IVCSW", pr_nop, sr_nop, 5, 0, XXX, AN|RIGHT},
|
|
@@ -1586,6 +1621,7 @@ {"pending", "PENDING", pr_sig, sr
|
|
{"pgid", "PGID", pr_pgid, sr_pgrp, 5, 0, U98, PO|PIDMAX|RIGHT},
|
|
{"pgrp", "PGRP", pr_pgid, sr_pgrp, 5, 0, LNX, PO|PIDMAX|RIGHT},
|
|
{"pid", "PID", pr_procs, sr_procs, 5, 0, U98, PO|PIDMAX|RIGHT},
|
|
+{"pidns", "PIDNS", pr_pidns, sr_pidns, 10, NS, LNX, ET|RIGHT},
|
|
{"pmem", "%MEM", pr_pmem, sr_rss, 4, 0, XXX, PO|RIGHT}, /*%mem*/
|
|
{"poip", "-", pr_nop, sr_nop, 1, 0, BSD, AN|RIGHT},
|
|
{"policy", "POL", pr_class, sr_sched, 3, 0, DEC, TO|LEFT},
|
|
@@ -1693,6 +1729,7 @@ {"unit", "UNIT", pr_sd_unit, sr
|
|
{"upr", "UPR", pr_nop, sr_nop, 3, 0, BSD, TO|RIGHT}, /*usrpri*/
|
|
{"uprocp", "UPROCP", pr_nop, sr_nop, 8, 0, BSD, AN|RIGHT},
|
|
{"user", "USER", pr_euser, sr_euser, 8, USR, U98, ET|USER}, /* BSD n forces this to UID */
|
|
+{"userns", "USERNS", pr_userns, sr_userns, 10, NS, LNX, ET|RIGHT},
|
|
{"usertime", "USER", pr_nop, sr_nop, 4, 0, DEC, ET|RIGHT},
|
|
{"usrpri", "UPR", pr_nop, sr_nop, 3, 0, DEC, TO|RIGHT}, /*upr*/
|
|
{"util", "C", pr_c, sr_pcpu, 2, 0, SGI, ET|RIGHT}, // not sure about "C"
|
|
@@ -1700,6 +1737,7 @@ {"utime", "UTIME", pr_nop, sr
|
|
#ifdef WITH_SYSTEMD
|
|
{"uunit", "UUNIT", pr_sd_uunit, sr_nop, 31, 0, LNX, ET|LEFT},
|
|
#endif
|
|
+{"utsns", "UTSNS", pr_utsns, sr_utsns, 10, NS, LNX, ET|RIGHT},
|
|
{"vm_data", "DATA", pr_nop, sr_vm_data, 5, 0, LNx, PO|RIGHT},
|
|
{"vm_exe", "EXE", pr_nop, sr_vm_exe, 5, 0, LNx, PO|RIGHT},
|
|
{"vm_lib", "LIB", pr_nop, sr_vm_lib, 5, 0, LNx, PO|RIGHT},
|
|
--- procps-ng-3.3.8.orig/ps/ps.1 2013-05-25 17:39:40.000000000 -0400
|
|
+++ procps-ng-3.3.8/ps/ps.1 2013-09-17 16:11:12.942925254 -0400
|
|
@@ -1299,6 +1299,10 @@ format is displayed. (alias
|
|
.BR sig_ignore , \ sigignore ).
|
|
T}
|
|
|
|
+ipcns IPCNS T{
|
|
+Unique inode number describing the namespace the process belongs to. See namespaces(7).
|
|
+T}
|
|
+
|
|
label LABEL T{
|
|
security label, most commonly used for SELinux context data. This is for
|
|
the
|
|
@@ -1335,6 +1339,14 @@ min_flt MINFLT T{
|
|
The number of minor page faults that have occurred with this process.
|
|
T}
|
|
|
|
+mntns MNTNS T{
|
|
+Unique inode number describing the namespace the process belongs to. See namespaces(7).
|
|
+T}
|
|
+
|
|
+netns NETNS T{
|
|
+Unique inode number describing the namespace the process belongs to. See namespaces(7).
|
|
+T}
|
|
+
|
|
ni NI T{
|
|
nice value. This ranges from 19 (nicest) to \-20 (not nice to others),
|
|
see
|
|
@@ -1403,6 +1415,10 @@ a number representing the process ID (al
|
|
.BR tgid ).
|
|
T}
|
|
|
|
+pidns PIDNS T{
|
|
+Unique inode number describing the namespace the process belongs to. See namespaces(7).
|
|
+T}
|
|
+
|
|
pmem %MEM T{
|
|
see
|
|
.BR %mem .
|
|
@@ -1739,6 +1755,14 @@ uunit UUNIT T{
|
|
displays systemd user unit which a process belongs to.
|
|
T}
|
|
|
|
+userns USERNS T{
|
|
+Unique inode number describing the namespace the process belongs to. See namespaces(7).
|
|
+T}
|
|
+
|
|
+utsns UTSNS T{
|
|
+Unique inode number describing the namespace the process belongs to. See namespaces(7).
|
|
+T}
|
|
+
|
|
vsize VSZ T{
|
|
see
|
|
.BR vsz .
|