librc: filter out container processes on OpenVZ host

Thanks to info and testing done by Daniel Robbins <drobbins@funtoo.org>,
there is now a fix for this. Below is his description of the steps
OpenRC needed to use.

1) See if /proc/<pid>/status exists
2) If it does, see if it has a "envID:" field
3) If it does, see if "envID:" is set to "0"
4) If so, then it's one of the host's processes and should be a
candidate for the list. Otherwise, it is one of the container's
processes and should be ignored.

This should fix the bug and allow start-stop-daemon to work properly on
OpenVZ hosts.

X-Gentoo-Bug: 376817
X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=376817
This commit is contained in:
William Hubbs 2014-06-20 16:01:47 -05:00
parent a817915632
commit 9eb9b28d3e

View File

@ -90,6 +90,11 @@ rc_find_pids(const char *exec, const char *const *argv, uid_t uid, pid_t pid)
{
DIR *procdir;
struct dirent *entry;
FILE *fp;
bool container_pid = false;
bool openvz_host = false;
char *line = NULL;
size_t len = 0;
pid_t p;
char buffer[PATH_MAX];
struct stat sb;
@ -117,6 +122,26 @@ rc_find_pids(const char *exec, const char *const *argv, uid_t uid, pid_t pid)
runscript_pid = 0;
}
/*
If /proc/self/status contains EnvID: 0, then we are an OpenVZ host,
and we will need to filter out processes that are inside containers
from our list of pids.
*/
if (exists("/proc/self/status")) {
fp = fopen("/proc/self/status", "r");
if (fp) {
while(! feof(fp)) {
rc_getline(&line, &len, fp);
if (strncmp(line, "envID:\t0", 8) == 0) {
openvz_host = true;
break;
}
}
fclose(fp);
}
}
while ((entry = readdir(procdir)) != NULL) {
if (sscanf(entry->d_name, "%d", &p) != 1)
continue;
@ -134,6 +159,25 @@ rc_find_pids(const char *exec, const char *const *argv, uid_t uid, pid_t pid)
if (argv &&
!pid_is_argv(p, (const char *const *)argv))
continue;
/* If this is an OpenVZ host, filter out container processes */
if (openvz_host) {
snprintf(buffer, sizeof(buffer), "/proc/%d/status", p);
if (exists(buffer)) {
fp = fopen(buffer, "r");
if (! fp)
continue;
while (! feof(fp)) {
rc_getline(&line, &len, fp);
if (strncmp(line, "envID:", 6) == 0) {
container_pid = ! (strncmp(line, "envID:\t0", 8) == 0);
break;
}
}
fclose(fp);
}
}
if (container_pid)
continue;
if (!pids) {
pids = xmalloc(sizeof(*pids));
LIST_INIT(pids);
@ -142,6 +186,8 @@ rc_find_pids(const char *exec, const char *const *argv, uid_t uid, pid_t pid)
pi->pid = p;
LIST_INSERT_HEAD(pids, pi, entries);
}
if (line != NULL)
free(line);
closedir(procdir);
return pids;
}