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 <csmall@enc.com.au>
This commit is contained in:
Laurent Bigonville 2016-01-03 18:11:51 +11:00 committed by Craig Small
parent 6fcb690099
commit 5da390422d
2 changed files with 37 additions and 37 deletions

1
NEWS
View File

@ -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
----------------

View File

@ -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"