From 5da390422d2b58902731655ddd12439126a051da Mon Sep 17 00:00:00 2001 From: Laurent Bigonville Date: Sun, 3 Jan 2016 18:11:51 +1100 Subject: [PATCH] ps: use attr/current as fallback for context If SELINUX is enabled but the machine is using another MAC system (like apparmor), ps will fallback to just parsing "/proc/%d/attr/current", otherwise the label/context would not be properly displayed in that case. References: https://bugs.debian.org/786956 Signed-off-by: Craig Small --- NEWS | 1 + ps/output.c | 73 ++++++++++++++++++++++++++--------------------------- 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/NEWS b/NEWS index b30aedf3..e92355e7 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,7 @@ procps-ng-NEXT ---------------- * ps: sort by cgroup Debian #692279 * ps: display control group name with -o cgname + * ps: Fallback to attr/current for context Debian #786956 procps-ng-3.3.11 ---------------- diff --git a/ps/output.c b/ps/output.c index 4722fee5..6bf53394 100644 --- a/ps/output.c +++ b/ps/output.c @@ -1283,67 +1283,69 @@ static int pr_lxcname(char *restrict const outbuf, const proc_t *restrict const /****************** FLASK & seLinux security stuff **********************/ // move the bulk of this to libproc sometime -#if !ENABLE_LIBSELINUX - -static int pr_context(char *restrict const outbuf, const proc_t *restrict const pp){ - char filename[48]; - size_t len; - ssize_t num_read; - int fd; - -// wchan file is suitable for testing -//snprintf(filename, sizeof filename, "/proc/%d/wchan", pp->tgid); -snprintf(filename, sizeof filename, "/proc/%d/attr/current", pp->tgid); - - fd = open(filename, O_RDONLY, 0); - if(likely(fd==-1)) goto fail; - num_read = read(fd, outbuf, 666); - close(fd); - if(unlikely(num_read<=0)) goto fail; - outbuf[num_read] = '\0'; - - len = 0; - while(outbuf[len]>' ' && outbuf[len]<='~') len++; - outbuf[len] = '\0'; - if(len) return len; - -fail: - outbuf[0] = '-'; - outbuf[1] = '\0'; - return 1; -} - -#else - // This needs more study, considering: // 1. the static linking option (maybe disable this in that case) // 2. the -z and -Z option issue // 3. width of output static int pr_context(char *restrict const outbuf, const proc_t *restrict const pp){ + static void (*ps_freecon)(char*) = 0; static int (*ps_getpidcon)(pid_t pid, char **context) = 0; + static int (*ps_is_selinux_enabled)(void) = 0; static int tried_load = 0; + static int selinux_enabled = 0; size_t len; char *context; +#if ENABLE_LIBSELINUX if(!ps_getpidcon && !tried_load){ void *handle = dlopen("libselinux.so.1", RTLD_NOW); if(handle){ + ps_freecon = dlsym(handle, "freecon"); + if(dlerror()) + ps_freecon = 0; dlerror(); ps_getpidcon = dlsym(handle, "getpidcon"); if(dlerror()) ps_getpidcon = 0; + ps_is_selinux_enabled = dlsym(handle, "is_selinux_enabled"); + if(dlerror()) + ps_is_selinux_enabled = 0; + else + selinux_enabled = ps_is_selinux_enabled(); } tried_load++; } - if(ps_getpidcon && !ps_getpidcon(pp->tgid, &context)){ +#endif + if(ps_getpidcon && selinux_enabled && !ps_getpidcon(pp->tgid, &context)){ size_t max_len = OUTBUF_SIZE-1; len = strlen(context); if(len > max_len) len = max_len; memcpy(outbuf, context, len); if (outbuf[len-1] == '\n') --len; outbuf[len] = '\0'; - free(context); + ps_freecon(context); }else{ + char filename[48]; + ssize_t num_read; + int fd; + +// wchan file is suitable for testing +//snprintf(filename, sizeof filename, "/proc/%d/wchan", pp->tgid); + snprintf(filename, sizeof filename, "/proc/%d/attr/current", pp->tgid); + + if ((fd = open(filename, O_RDONLY, 0)) != -1) { + num_read = read(fd, outbuf, OUTBUF_SIZE-1); + close(fd); + if (num_read > 0) { + outbuf[num_read] = '\0'; + len = 0; + while(isprint(outbuf[len])) + len++; + outbuf[len] = '\0'; + if(len) + return len; + } + } outbuf[0] = '-'; outbuf[1] = '\0'; len = 1; @@ -1351,9 +1353,6 @@ static int pr_context(char *restrict const outbuf, const proc_t *restrict const return len; } -#endif - - ////////////////////////////// Test code ///////////////////////////////// // like "args"