Commit 80090207 by Cedric Le Goater Committed by Daniel Lezcano

lxc: forbid open fds upon startup

This patch modifies the startup of a container to forbid opened fds, unless these are stdios. Signed-off-by: 's avatarCedric Le Goater <clg@fr.ibm.com>
parent 7d9fb3e9
......@@ -33,9 +33,7 @@
#define _GNU_SOURCE
#include <getopt.h>
#include <lxc/lxc.h>
#include <lxc/log.h>
#include <lxc/utils.h>
#include <lxc/error.h>
lxc_log_define(lxc_init, lxc);
......@@ -100,12 +98,6 @@ int main(int argc, char *argv[])
exit(err);
}
err = lxc_close_all_inherited_fd();
if (err) {
ERROR("unable to close inherited fds");
goto out;
}
err = 0;
for (;;) {
int status;
......
......@@ -163,9 +163,9 @@ int main(int argc, char *argv[])
return err;
}
lxc_close_inherited_fd(0);
lxc_close_inherited_fd(1);
lxc_close_inherited_fd(2);
close(0);
close(1);
close(2);
if (my_args.log_file) {
open(my_args.log_file, O_WRONLY | O_CLOEXEC);
......
......@@ -106,6 +106,64 @@ lxc_log_define(lxc_start, lxc);
LXC_TTY_HANDLER(SIGINT);
LXC_TTY_HANDLER(SIGQUIT);
static int match_fd(int fd)
{
return (fd == 0 || fd == 1 || fd == 2);
}
int lxc_check_inherited(void)
{
struct dirent dirent, *direntp;
int fd, fddir;
DIR *dir;
int ret = 0;
dir = opendir("/proc/self/fd");
if (!dir) {
WARN("failed to open directory: %m");
return -1;
}
fddir = dirfd(dir);
while (!readdir_r(dir, &dirent, &direntp)) {
char procpath[64];
char path[PATH_MAX];
if (!direntp)
break;
if (!strcmp(direntp->d_name, "."))
continue;
if (!strcmp(direntp->d_name, ".."))
continue;
fd = atoi(direntp->d_name);
if (fd == fddir || fd == lxc_log_fd)
continue;
if (match_fd(fd))
continue;
/*
* found inherited fd
*/
ret = -1;
snprintf(procpath, sizeof(procpath), "/proc/self/fd/%d", fd);
if (readlink(procpath, path, sizeof(path)) == -1)
ERROR("readlink(%s) failed : %m", procpath);
else
ERROR("inherited fd %d on %s", fd, path);
}
if (closedir(dir))
ERROR("failed to close directory");
return ret;
}
static int setup_sigchld_fd(sigset_t *oldmask)
{
sigset_t mask;
......@@ -432,6 +490,9 @@ int lxc_start(const char *name, char *const argv[], struct lxc_conf *conf)
int err = -1;
int status;
if (lxc_check_inherited())
return -1;
handler = lxc_init(name, conf);
if (!handler) {
ERROR("failed to initialize the container");
......@@ -444,12 +505,6 @@ int lxc_start(const char *name, char *const argv[], struct lxc_conf *conf)
goto out_fini;
}
err = lxc_close_all_inherited_fd();
if (err) {
ERROR("unable to close inherited fds");
goto out_abort;
}
err = lxc_poll(name, handler);
if (err) {
ERROR("mainloop exited with an error");
......
......@@ -45,6 +45,7 @@ extern int lxc_poll(const char *name, struct lxc_handler *handler);
extern void lxc_abort(const char *name, struct lxc_handler *handler);
extern void lxc_fini(const char *name, struct lxc_handler *handler);
extern int lxc_set_state(const char *, struct lxc_handler *, lxc_state_t);
extern int lxc_check_inherited(void);
#endif
......@@ -34,7 +34,6 @@
#include <dirent.h>
#include <fcntl.h>
#include "list.h"
#include "log.h"
lxc_log_define(lxc_utils, lxc);
......@@ -110,131 +109,6 @@ err:
goto out_mmap;
}
struct lxc_fd_entry {
int fd;
struct lxc_list list;
};
struct lxc_list lxc_fd_list;
static int fd_list_add(int fd)
{
struct lxc_fd_entry *entry;
entry = malloc(sizeof(struct lxc_fd_entry));
if (!entry) {
SYSERROR("malloc");
return -1;
}
entry->fd = fd;
entry->list.elem = entry;
lxc_list_add(&lxc_fd_list, &entry->list);
return 0;
}
static void fd_list_del(struct lxc_fd_entry *entry)
{
lxc_list_del(&entry->list);
free(entry);
}
static void __attribute__((constructor)) __lxc_fd_collect_inherited(void)
{
struct dirent dirent, *direntp;
int fd, fddir;
DIR *dir;
lxc_list_init(&lxc_fd_list);
dir = opendir("/proc/self/fd");
if (!dir) {
WARN("failed to open directory: %s", strerror(errno));
return;
}
fddir = dirfd(dir);
while (!readdir_r(dir, &dirent, &direntp)) {
if (!direntp)
break;
if (!strcmp(direntp->d_name, "."))
continue;
if (!strcmp(direntp->d_name, ".."))
continue;
fd = atoi(direntp->d_name);
if (fd == fddir)
continue;
if (fd_list_add(fd))
WARN("failed to add fd '%d' to the list", fd);
}
if (closedir(dir))
WARN("failed to close directory");
}
int lxc_close_inherited_fd(int fd)
{
struct lxc_fd_entry *entry;
struct lxc_list *iterator;
lxc_list_for_each(iterator, &lxc_fd_list) {
entry = iterator->elem;
if (entry->fd != fd)
continue;
fd_list_del(entry);
break;
}
DEBUG("closing fd '%d'", fd);
return close(fd);
}
int lxc_close_all_inherited_fd(void)
{
struct lxc_fd_entry *entry;
struct lxc_list *iterator;
again:
lxc_list_for_each(iterator, &lxc_fd_list) {
entry = iterator->elem;
/* do not close the stderr fd to keep open default
* error reporting path.
*/
if (entry->fd == 2 && isatty(entry->fd)) {
fd_list_del(entry);
continue;
}
DEBUG("closing fd '%d'", entry->fd);
if (close(entry->fd))
WARN("failed to close fd '%d': %s", entry->fd,
strerror(errno));
fd_list_del(entry);
goto again;
}
DEBUG("closed all inherited file descriptors");
return 0;
}
static int mount_fs(const char *source, const char *target, const char *type)
{
/* the umount may fail */
......
......@@ -51,7 +51,5 @@
#endif
extern int lxc_copy_file(const char *src, const char *dst);
extern int lxc_close_inherited_fd(int fd);
extern int lxc_close_all_inherited_fd(void);
extern int lxc_setup_fs(void);
extern int get_u16(ushort *val, const char *arg, int base);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment