From 7697ed3a778551bcb32d210403bb3245c24b0bc6 Mon Sep 17 00:00:00 2001 From: Jaromir Capik Date: Oct 08 2013 15:01:18 +0000 Subject: - Introduce namespaces support (#1016242) --- diff --git a/pgrep-introduce_support_for_namespaces.patch b/pgrep-introduce_support_for_namespaces.patch new file mode 100644 index 0000000..2b725d0 --- /dev/null +++ b/pgrep-introduce_support_for_namespaces.patch @@ -0,0 +1,265 @@ +commit de7b3b9222ab4e2f75db88f0f75b555ab306140b +Author: Aristeu Rozanski +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 + +--- + 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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 match by real IDs\n" + " -x, --exact match exactly with the command name\n" + " -F, --pidfile 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 match the processes that belong to the same\n" ++ " namespace as \n" ++ " --nslist 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; diff --git a/procps-add_support_for_linux_namespaces.patch b/procps-add_support_for_linux_namespaces.patch new file mode 100644 index 0000000..db5de99 --- /dev/null +++ b/procps-add_support_for_linux_namespaces.patch @@ -0,0 +1,325 @@ +commit a01ee3c0b32d4c39aa83066ed61103343469527e +Author: Aristeu Rozanski +Date: Mon Apr 8 15:03:13 2013 -0400 + + procps: add support for linux namespaces + + Each process in Linux has a /proc//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 + +--- + 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//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 . diff --git a/procps-fix_the_fatal_make_dist_error_for_nsutils.patch b/procps-fix_the_fatal_make_dist_error_for_nsutils.patch new file mode 100644 index 0000000..26e4362 --- /dev/null +++ b/procps-fix_the_fatal_make_dist_error_for_nsutils.patch @@ -0,0 +1,28 @@ +commit e2242cb943c620599913db3a68ccba06fa07ac36 +Author: Jim Warner +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 + +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 diff --git a/procps-ng.spec b/procps-ng.spec index a00a6f1..133305b 100644 --- a/procps-ng.spec +++ b/procps-ng.spec @@ -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 - 3.3.8-15 +- Introduce namespaces support (#1016242) + * Tue Sep 17 2013 Jaromir Capik - 3.3.8-14 - top: Fixing missing newline when running in the batch mode (#1008674) diff --git a/skill-support_namespaces.patch b/skill-support_namespaces.patch new file mode 100644 index 0000000..28b59a2 --- /dev/null +++ b/skill-support_namespaces.patch @@ -0,0 +1,228 @@ +commit 91d225f3b8fcfa514f1ef20239af7b0ada64c01c +Author: Aristeu Rozanski +Date: Tue Apr 16 12:07:10 2013 -0400 + + skill: support namespaces + + In the same fashion of pgrep, introduce two new options: + --ns + - nslist + which allows processes to be filtered by namespace. + + Signed-off-by: Aristeu Rozanski + +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 expression is a terminal\n" + " -u, --user expression is a username\n"), out); + fputs(USAGE_SEPARATOR, out); ++ fputs(_("Alternatively, expression can be:\n" ++ " --ns match the processes that belong to the same\n" ++ " namespace as \n" ++ " --nslist 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)