From 828540578cadb2e3e90e29754325cd3d8fab7033 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 | 69 +++++++++++++++++++++++++++-------------------------- 2 files changed, 36 insertions(+), 34 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 16e00c18..0d637d67 100644 --- a/ps/output.c +++ b/ps/output.c @@ -1212,64 +1212,68 @@ setREL1(LXCNAME) /****************** 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; -setREL1(ID_TGID) - snprintf(filename, sizeof filename, "/proc/%d/attr/current", rSv(ID_TGID, s_int, pp)); - 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; setREL1(ID_TGID) + +#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(rSv(ID_TGID, s_int, pp), &context)){ +#endif + if(ps_getpidcon && selinux_enabled && !ps_getpidcon(rSv(ID_TGID, s_int, pp), &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; + + snprintf(filename, sizeof filename, "/proc/%d/attr/current", rSv(ID_TGID, s_int, pp)); + + 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; @@ -1277,9 +1281,6 @@ setREL1(ID_TGID) return len; } -#endif - - ////////////////////////////// Test code ///////////////////////////////// // like "args"