mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-07-27 21:11:49 +00:00
init: don't kill(-1) if we aren't in a pid ns
...otherwise we'll kill everyone on the machine. Instead, let's explicitly try to kill our children. Let's do a best effort against fork bombs by disabling forking via the pids cgroup if it exists. This is best effort for a number of reasons: * the pids cgroup may not be available * the container may have bind mounted /dev/null over pids.max, so the write doesn't do anything Signed-off-by: Tycho Andersen <tycho@tycho.ws>
This commit is contained in:
parent
4be4832738
commit
d76e3e1a5b
@ -92,6 +92,86 @@ static struct arguments my_args = {
|
|||||||
.shortopts = short_options
|
.shortopts = short_options
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void prevent_forking(void)
|
||||||
|
{
|
||||||
|
FILE *f;
|
||||||
|
char name[PATH_MAX], path[PATH_MAX];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
f = fopen("/proc/self/cgroup", "r");
|
||||||
|
if (!f) {
|
||||||
|
SYSERROR("opening /proc/self/cgroup");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!feof(f)) {
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
if (2 != fscanf(f, "%*d:%[^:]:%s", name, path)) {
|
||||||
|
ERROR("didn't scan the right number of things");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(name, "pids"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ret = snprintf(name, sizeof(name), "/sys/fs/cgroup/pids/%s/pids.max", path);
|
||||||
|
if (ret < 0 || ret >= sizeof(path)) {
|
||||||
|
ERROR("failed snprintf");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd = open(name, O_WRONLY);
|
||||||
|
if (fd < 0) {
|
||||||
|
SYSERROR("open");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (write(fd, "1", 1) != 1)
|
||||||
|
SYSERROR("write");
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void kill_children(pid_t pid)
|
||||||
|
{
|
||||||
|
FILE *f;
|
||||||
|
char path[PATH_MAX];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = snprintf(path, sizeof(path), "/proc/%d/task/%d/children", pid, pid);
|
||||||
|
if (ret < 0 || ret >= sizeof(path)) {
|
||||||
|
ERROR("failed snprintf");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
f = fopen(path, "r");
|
||||||
|
if (!f) {
|
||||||
|
SYSERROR("couldn't open %s", path);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!feof(f)) {
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
|
if (fscanf(f, "%d ", &pid) != 1) {
|
||||||
|
ERROR("couldn't scan pid");
|
||||||
|
fclose(f);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
kill_children(pid);
|
||||||
|
kill(pid, SIGKILL);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int i, ret;
|
int i, ret;
|
||||||
@ -258,18 +338,28 @@ int main(int argc, char *argv[])
|
|||||||
case SIGTERM:
|
case SIGTERM:
|
||||||
if (!shutdown) {
|
if (!shutdown) {
|
||||||
shutdown = 1;
|
shutdown = 1;
|
||||||
ret = kill(-1, SIGTERM);
|
prevent_forking();
|
||||||
if (ret < 0)
|
if (getpid() != 1) {
|
||||||
DEBUG("%s - Failed to send SIGTERM to "
|
kill_children(getpid());
|
||||||
"all children", strerror(errno));
|
} else {
|
||||||
|
ret = kill(-1, SIGTERM);
|
||||||
|
if (ret < 0)
|
||||||
|
DEBUG("%s - Failed to send SIGTERM to "
|
||||||
|
"all children", strerror(errno));
|
||||||
|
}
|
||||||
alarm(1);
|
alarm(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SIGALRM:
|
case SIGALRM:
|
||||||
ret = kill(-1, SIGKILL);
|
prevent_forking();
|
||||||
if (ret < 0)
|
if (getpid() != 1) {
|
||||||
DEBUG("%s - Failed to send SIGKILL to all "
|
kill_children(getpid());
|
||||||
"children", strerror(errno));
|
} else {
|
||||||
|
ret = kill(-1, SIGTERM);
|
||||||
|
if (ret < 0)
|
||||||
|
DEBUG("%s - Failed to send SIGTERM to "
|
||||||
|
"all children", strerror(errno));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ret = kill(pid, was_interrupted);
|
ret = kill(pid, was_interrupted);
|
||||||
|
Loading…
Reference in New Issue
Block a user