- Introduce namespaces support (#1016242)

This commit is contained in:
Jaromir Capik 2013-10-08 17:01:18 +02:00
parent 3fa51099ff
commit 7697ed3a77
5 changed files with 858 additions and 1 deletions

View File

@ -0,0 +1,265 @@
commit de7b3b9222ab4e2f75db88f0f75b555ab306140b
Author: Aristeu Rozanski <arozansk@redhat.com>
Date: Fri Apr 12 14:40:27 2013 -0400
pgrep: introduce support for namespaces
A PID should be specified with --ns:
$ pgrep --ns 12345
which will only match the processes which belong to to the same 6
namespaces. It is also possible to specify which namespaces to test:
$ pgrep --ns 12345 --nslist mnt,net,ipc
which will match processes that belong to the same mount, network and
IPC namespaces as PID 12345.
Signed-off-by: Aristeu Rozanski <arozansk@redhat.com>
---
Makefile.am | 4 +--
include/nsutils.h | 7 +++++
lib/nsutils.c | 32 +++++++++++++++++++++++++
pgrep.1 | 9 +++++++
pgrep.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
5 files changed, 117 insertions(+), 4 deletions(-)
--- procps-ng-3.3.8.orig/Makefile.am 2013-05-25 17:39:39.000000000 -0400
+++ procps-ng-3.3.8/Makefile.am 2013-09-17 16:57:03.515128029 -0400
@@ -89,8 +89,8 @@ else
endif
free_SOURCES = free.c $(top_srcdir)/lib/strutils.c $(top_srcdir)/lib/fileutils.c
-pgrep_SOURCES = pgrep.c $(top_srcdir)/lib/fileutils.c
-pkill_SOURCES = pgrep.c $(top_srcdir)/lib/fileutils.c
+pgrep_SOURCES = pgrep.c $(top_srcdir)/lib/fileutils.c $(top_srcdir)/lib/nsutils.c
+pkill_SOURCES = pgrep.c $(top_srcdir)/lib/fileutils.c $(top_srcdir)/lib/nsutils.c
pmap_SOURCES = pmap.c $(top_srcdir)/lib/fileutils.c
pwdx_SOURCES = pwdx.c $(top_srcdir)/lib/fileutils.c
sysctl_SOURCES = sysctl.c $(top_srcdir)/lib/fileutils.c
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ procps-ng-3.3.8/include/nsutils.h 2013-09-17 16:57:03.515128029 -0400
@@ -0,0 +1,7 @@
+#ifndef PROCPS_NG_NSUTILS
+#define PROCPS_NG_NSUTILS
+
+#include "proc/readproc.h"
+int ns_read(pid_t pid, proc_t *ns_task);
+
+#endif
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ procps-ng-3.3.8/lib/nsutils.c 2013-09-17 16:57:03.515128029 -0400
@@ -0,0 +1,32 @@
+#include <errno.h>
+#include <error.h>
+#include <stdio_ext.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "proc/readproc.h"
+#include "nsutils.h"
+
+/* we need to fill in only namespace information */
+int ns_read(pid_t pid, proc_t *ns_task)
+{
+ struct stat st;
+ char buff[50];
+ int i, rc = 0;
+
+ for (i = 0; i < NUM_NS; i++) {
+ snprintf(buff, sizeof(buff), "/proc/%i/ns/%s", pid,
+ get_ns_name(i));
+ if (stat(buff, &st)) {
+ if (errno != ENOENT)
+ rc = errno;
+ ns_task->ns[i] = 0;
+ continue;
+ }
+ ns_task->ns[i] = st.st_ino;
+ }
+ return rc;
+}
+
--- procps-ng-3.3.8.orig/pgrep.1 2013-05-25 17:39:40.000000000 -0400
+++ procps-ng-3.3.8/pgrep.1 2013-09-17 16:57:03.516128042 -0400
@@ -146,6 +146,15 @@ than
\fB\-L\fR, \fB\-\-logpidfile\fR
Fail if pidfile (see -F) not locked.
.TP
+\fB\-\-ns \fIpid\fP
+Match processes that belong to the same namespaces. Required to run as
+root to match processes from other users. See \-\-nslist for how to limit
+which namespaces to match.
+.TP
+\fB\-\-nslist \fIname\fP,...
+Match only the provided namespaces. Available namespaces:
+ipc, mnt, net, pid, user,uts.
+.TP
\fB\-V\fR, \fB\-\-version\fR
Display version information and exit.
.TP
--- procps-ng-3.3.8.orig/pgrep.c 2013-05-25 17:39:40.000000000 -0400
+++ procps-ng-3.3.8/pgrep.c 2013-09-17 16:58:18.439105071 -0400
@@ -46,6 +46,7 @@ #define CMDSTRSIZE 4096
#include "c.h"
#include "fileutils.h"
+#include "nsutils.h"
#include "nls.h"
#include "xalloc.h"
#include "proc/readproc.h"
@@ -76,6 +77,7 @@ static int opt_lock = 0;
static int opt_case = 0;
static int opt_echo = 0;
static int opt_threads = 0;
+static pid_t opt_ns_pid = 0;
static const char *opt_delim = "\n";
static struct el *opt_pgrp = NULL;
@@ -86,9 +88,13 @@ static struct el *opt_sid = NULL;
static struct el *opt_term = NULL;
static struct el *opt_euid = NULL;
static struct el *opt_ruid = NULL;
+static struct el *opt_nslist = NULL;
static char *opt_pattern = NULL;
static char *opt_pidfile = NULL;
+/* by default, all namespaces will be checked */
+static int ns_flags = 0x3f;
+
static int __attribute__ ((__noreturn__)) usage(int opt)
{
int err = (opt == '?');
@@ -121,7 +127,12 @@ if (i_am_pkill == 0) {
" -U, --uid <id,...> match by real IDs\n"
" -x, --exact match exactly with the command name\n"
" -F, --pidfile <file> read PIDs from file\n"
- " -L, --logpidfile fail if PID file is not locked\n"), fp);
+ " -L, --logpidfile fail if PID file is not locked\n"
+ " --ns <pid> match the processes that belong to the same\n"
+ " namespace as <pid>\n"
+ " --nslist <ns,...> list which namespaces will be considered for\n"
+ " the --ns option.\n"
+ " Available namespaces: ipc, mnt, net, pid, user, uts\n"), fp);
fputs(USAGE_SEPARATOR, fp);
fputs(USAGE_HELP, fp);
fputs(USAGE_VERSION, fp);
@@ -320,6 +331,20 @@ static int conv_str (const char *restric
}
+static int conv_ns (const char *restrict name, struct el *restrict e)
+{
+ int rc = conv_str(name, e);
+ int id;
+
+ ns_flags = 0;
+ id = get_ns_id(name);
+ if (id == -1)
+ return 0;
+ ns_flags |= (1 << id);
+
+ return rc;
+}
+
static int match_numlist (long value, const struct el *restrict list)
{
int found = 0;
@@ -350,6 +375,21 @@ for (i = list[0].num; i > 0; i--) {
return found;
}
+static int match_ns (const proc_t *task, const proc_t *ns_task)
+{
+ int found = 1;
+ int i;
+
+ for (i = 0; i < NUM_NS; i++) {
+ if (ns_flags & (1 << i)) {
+ if (task->ns[i] != ns_task->ns[i])
+ found = 0;
+ }
+ }
+
+ return found;
+}
+
static void output_numlist (const struct el *restrict list, int num)
{
int i;
@@ -386,6 +426,8 @@ int flags = 0;
flags |= PROC_FILLSTAT;
if (!(flags & PROC_FILLSTAT))
flags |= PROC_FILLSTATUS; /* FIXME: need one, and PROC_FILLANY broken */
+ if (opt_ns_pid)
+ flags |= PROC_FILLNS;
if (opt_euid && !opt_negate) {
int num = opt_euid[0].num;
int i = num;
@@ -442,6 +484,7 @@ int size = 0;
char cmdline[CMDSTRSIZE];
char cmdsearch[CMDSTRSIZE];
char cmdoutput[CMDSTRSIZE];
+ proc_t ns_task;
ptp = do_openproc();
preg = do_regcomp();
@@ -451,6 +494,11 @@ else saved_start_time = ~0ULL;
if (opt_newest) saved_pid = 0;
if (opt_oldest) saved_pid = INT_MAX;
+ if (opt_ns_pid && ns_read(opt_ns_pid, &ns_task)) {
+ fputs(_("Error reading reference namespace information\n"),
+ stderr);
+ exit (EXIT_FATAL);
+ }
memset(&task, 0, sizeof (task));
while(readproc(ptp, &task)) {
@@ -476,6 +524,8 @@ match = 0;
match = 0;
else if (opt_sid && ! match_numlist (task.session, opt_sid))
match = 0;
+ else if (opt_ns_pid && ! match_ns (&task, &ns_task))
+ match = 0;
else if (opt_term) {
if (task.tty == 0) {
match = 0;
@@ -622,7 +672,9 @@ static void parse_opts (int argc, char *
int criteria_count = 0;
enum {
- SIGNAL_OPTION = CHAR_MAX + 1
+ SIGNAL_OPTION = CHAR_MAX + 1,
+ NS_OPTION,
+ NSLIST_OPTION,
};
static const struct option longopts[] = {
{"signal", required_argument, NULL, SIGNAL_OPTION},
@@ -646,6 +698,8 @@ int criteria_count = 0;
{"pidfile", required_argument, NULL, 'F'},
{"logpidfile", no_argument, NULL, 'L'},
{"echo", no_argument, NULL, 'e'},
+ {"ns", required_argument, NULL, NS_OPTION},
+ {"nslist", required_argument, NULL, NSLIST_OPTION},
{"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, 'V'},
{NULL, 0, NULL, 0}
@@ -792,6 +846,17 @@ case 'l': /* Solaris: long output fo
break;
/* case 'z': / * Solaris: match by zone ID * /
* break; */
+ case NS_OPTION:
+ opt_ns_pid = atoi(optarg);
+ if (opt_ns_pid == 0)
+ usage (opt);
+ ++criteria_count;
+ break;
+ case NSLIST_OPTION:
+ opt_nslist = split_list (optarg, conv_ns);
+ if (opt_nslist == NULL)
+ usage (opt);
+ break;
case 'h':
usage (opt);
break;

View File

@ -0,0 +1,325 @@
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 .

View File

@ -0,0 +1,28 @@
commit e2242cb943c620599913db3a68ccba06fa07ac36
Author: Jim Warner <james.warner@comcast.net>
Date: Wed Sep 11 09:11:13 2013 -0500
build-sys: fix the fatal 'make dist' error for nsutils
While a 'make dist' appeared to work fine without this
patch, the nsutils.h file was missing from the include
subdirectory. Thus the tarball could not support make.
Reference(s):
http://gitorious.org/procps/procps/merge_requests/13
commit dd6f24dbed12e95235b3df49e550b5039e74e6d8
Signed-off-by: Jim Warner <james.warner@comcast.net>
diff --git a/include/Makefile.am b/include/Makefile.am
index c511513..fee45ca 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -2,6 +2,7 @@ dist_noinst_HEADERS = \
c.h \
fileutils.h \
nls.h \
+ nsutils.h \
rpmatch.h \
strutils.h \
xalloc.h

View File

@ -4,7 +4,7 @@
Summary: System and process monitoring utilities
Name: procps-ng
Version: 3.3.8
Release: 14%{?dist}
Release: 15%{?dist}
License: GPL+ and GPLv2 and GPLv2+ and GPLv3+ and LGPLv2+
Group: Applications/System
URL: https://sourceforge.net/projects/procps-ng/
@ -20,6 +20,10 @@ Patch5: procps-ng-3.3.8-RH-man-page-check.patch
Patch6: procps-ng-3.3.8-libselinux.patch
Patch7: procps-ng-3.3.8-free-shmem.patch
Patch8: 0002-top-restore-the-lost-final-newline-when-in-Batch-mod.patch
Patch9: procps-add_support_for_linux_namespaces.patch
Patch10: pgrep-introduce_support_for_namespaces.patch
Patch11: skill-support_namespaces.patch
Patch12: procps-fix_the_fatal_make_dist_error_for_nsutils.patch
Requires(post): /sbin/ldconfig
Requires(postun): /sbin/ldconfig
@ -87,6 +91,10 @@ System and process monitoring utilities development headers
%patch6 -p1
%patch7 -p1
%patch8 -p1
%patch9 -p1
%patch10 -p1
%patch11 -p1
%patch12 -p1
%build
# The following stuff is needed for git archives only
@ -153,6 +161,9 @@ mkdir -p %{buildroot}%{_sysconfdir}/sysctl.d
%{_includedir}/proc
%changelog
* Tue Sep 17 2013 Aristeu Rozanski <aris@redhat.com> - 3.3.8-15
- Introduce namespaces support (#1016242)
* Tue Sep 17 2013 Jaromir Capik <jcapik@redhat.com> - 3.3.8-14
- top: Fixing missing newline when running in the batch mode (#1008674)

View File

@ -0,0 +1,228 @@
commit 91d225f3b8fcfa514f1ef20239af7b0ada64c01c
Author: Aristeu Rozanski <arozansk@redhat.com>
Date: Tue Apr 16 12:07:10 2013 -0400
skill: support namespaces
In the same fashion of pgrep, introduce two new options:
--ns <pid>
- nslist <ns,...>
which allows processes to be filtered by namespace.
Signed-off-by: Aristeu Rozanski <arozansk@redhat.com>
diff --git a/Makefile.am b/Makefile.am
index 05128a4..3d66d60 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -55,7 +55,7 @@ EXTRA_DIST = \
if BUILD_KILL
bin_PROGRAMS = kill
dist_man_MANS += kill.1
-kill_SOURCES = skill.c $(top_srcdir)/lib/strutils.c $(top_srcdir)/lib/fileutils.c
+kill_SOURCES = skill.c $(top_srcdir)/lib/strutils.c $(top_srcdir)/lib/fileutils.c $(top_srcdir)/lib/nsutils.c
else
EXTRA_DIST += kill.1
endif
@@ -77,8 +77,8 @@ if BUILD_SKILL
usrbin_exec_PROGRAMS += \
skill \
snice
-skill_SOURCES = skill.c $(top_srcdir)/lib/strutils.c $(top_srcdir)/lib/fileutils.c
-snice_SOURCES = skill.c $(top_srcdir)/lib/strutils.c $(top_srcdir)/lib/fileutils.c
+skill_SOURCES = skill.c $(top_srcdir)/lib/strutils.c $(top_srcdir)/lib/fileutils.c $(top_srcdir)/lib/nsutils.c
+snice_SOURCES = skill.c $(top_srcdir)/lib/strutils.c $(top_srcdir)/lib/fileutils.c $(top_srcdir)/lib/nsutils.c
dist_man_MANS += \
skill.1 \
snice.1
diff --git a/skill.1 b/skill.1
index 9748a1d..8ef7683 100644
--- a/skill.1
+++ b/skill.1
@@ -77,6 +77,13 @@ The next expression is a process ID number.
.TP
\fB\-c\fR, \fB\-\-command\fR \fIcommand\fR
The next expression is a command name.
+.TP
+\fB\-\-ns \fIpid\fR
+Match the processes that belong to the same namespace as pid.
+.TP
+\fB\-\-nslist \fIns,...\fR
+list which namespaces will be considered for the --ns option.
+Available namespaces: ipc, mnt, net, pid, user, uts.
.PD
.SH SIGNALS
The behavior of signals is explained in
diff --git a/skill.c b/skill.c
index 03df229..d3fc978 100644
--- a/skill.c
+++ b/skill.c
@@ -36,6 +36,7 @@
#include "c.h"
#include "fileutils.h"
+#include "nsutils.h"
#include "strutils.h"
#include "nls.h"
#include "xalloc.h"
@@ -43,6 +44,7 @@
#include "proc/sig.h"
#include "proc/devname.h"
#include "proc/procps.h" /* char *user_from_uid(uid_t uid) */
+#include "proc/readproc.h"
#include "proc/version.h" /* procps_version */
#include "rpmatch.h"
@@ -56,11 +58,14 @@ struct run_time_conf_t {
int noaction;
int debugging;
};
-static int tty_count, uid_count, cmd_count, pid_count;
+static int tty_count, uid_count, cmd_count, pid_count, namespace_count;
static int *ttys;
static uid_t *uids;
static const char **cmds;
static int *pids;
+static char **namespaces;
+static int ns_pid;
+static proc_t ns_task;
#define ENLIST(thing,addme) do{ \
if(!thing##s) thing##s = xmalloc(sizeof(*thing##s)*saved_argc); \
@@ -85,6 +90,39 @@ static void display_kill_version(void)
fprintf(stdout, PROCPS_NG_VERSION);
}
+static int ns_flags = 0x3f;
+static int parse_namespaces(char *optarg)
+{
+ char *ptr = optarg, *tmp;
+ int len, id;
+
+ ns_flags = 0;
+ while (1) {
+ if (strchr(ptr, ',') == NULL) {
+ len = -1;
+ tmp = strdup(ptr);
+ } else {
+ len = strchr(ptr, ',') - ptr;
+ tmp = strndup(ptr, len);
+ }
+
+ id = get_ns_id(tmp);
+ if (id == -1) {
+ fprintf(stderr, "%s is not a valid namespace\n", tmp);
+ free(tmp);
+ return 1;
+ }
+ ns_flags |= (1 << id);
+ ENLIST(namespace, tmp);
+
+ if (len == -1)
+ break;
+
+ ptr+= len + 1;
+ }
+ return 0;
+}
+
/* kill or nice a process */
static void hurt_proc(int tty, int uid, int pid, const char *restrict const cmd,
struct run_time_conf_t *run_time)
@@ -131,6 +169,7 @@ static void check_proc(int pid, struct run_time_conf_t *run_time)
{
char buf[128];
struct stat statbuf;
+ proc_t task;
char *tmp;
int tty;
int fd;
@@ -183,6 +222,16 @@ static void check_proc(int pid, struct run_time_conf_t *run_time)
if (i == -1)
goto closure;
}
+ if (ns_pid) {
+ if (ns_read(pid, &task))
+ goto closure;
+ for (i = 0; i < NUM_NS; i++) {
+ if (ns_flags & (1 << i)) {
+ if (task.ns[i] != ns_task.ns[i])
+ goto closure;
+ }
+ }
+ }
/* This is where we kill/nice something. */
/* for debugging purposes?
fprintf(stderr, "PID %d, UID %d, TTY %d,%d, COMM %s\n",
@@ -317,6 +366,15 @@ static void __attribute__ ((__noreturn__)) skillsnice_usage(FILE * out)
" -t, --tty <tty> expression is a terminal\n"
" -u, --user <username> expression is a username\n"), out);
fputs(USAGE_SEPARATOR, out);
+ fputs(_("Alternatively, expression can be:\n"
+ " --ns <pid> match the processes that belong to the same\n"
+ " namespace as <pid>\n"
+ " --nslist <ns,...> list which namespaces will be considered for\n"
+ " the --ns option.\n"
+ " Available namespaces: ipc, mnt, net, pid, user, uts\n"), out);
+
+ fputs(USAGE_SEPARATOR, out);
+ fputs(USAGE_SEPARATOR, out);
fputs(USAGE_HELP, out);
fputs(USAGE_VERSION, out);
if (program == PROG_SKILL) {
@@ -488,6 +546,11 @@ static void skillsnice_parse(int argc,
int prino = DEFAULT_NICE;
int ch, i;
+ enum {
+ NS_OPTION = CHAR_MAX + 1,
+ NSLIST_OPTION,
+ };
+
static const struct option longopts[] = {
{"command", required_argument, NULL, 'c'},
{"debug", no_argument, NULL, 'd'},
@@ -499,6 +562,8 @@ static void skillsnice_parse(int argc,
{"table", no_argument, NULL, 'L'},
{"tty", required_argument, NULL, 't'},
{"user", required_argument, NULL, 'u'},
+ {"ns", required_argument, NULL, NS_OPTION},
+ {"nslist", required_argument, NULL, NSLIST_OPTION},
{"verbose", no_argument, NULL, 'v'},
{"warnings", no_argument, NULL, 'w'},
{"help", no_argument, NULL, 'h'},
@@ -572,6 +637,25 @@ static void skillsnice_parse(int argc,
}
}
break;
+ case NS_OPTION:
+ ns_pid = atoi(optarg);
+ if (ns_pid == 0) {
+ xwarnx(_("invalid pid number %i"), optarg);
+ kill_usage(stderr);
+ }
+ if (ns_read(ns_pid, &ns_task)) {
+ xwarnx(_("error reading reference namespace "
+ "information"));
+ kill_usage(stderr);
+ }
+
+ break;
+ case NSLIST_OPTION:
+ if (parse_namespaces(optarg)) {
+ xwarnx(_("invalid namespace list"));
+ kill_usage(stderr);
+ }
+ break;
case 'v':
run_time->verbose = 1;
break;
@@ -605,7 +689,7 @@ static void skillsnice_parse(int argc,
}
/* No more arguments to process. Must sanity check. */
- if (!tty_count && !uid_count && !cmd_count && !pid_count)
+ if (!tty_count && !uid_count && !cmd_count && !pid_count && !ns_pid)
xerrx(EXIT_FAILURE, _("no process selection criteria"));
if ((run_time->fast | run_time->interactive | run_time->
verbose | run_time->warnings | run_time->noaction) & ~1)