Skip to content

Commit

Permalink
Add fopen_cloexec function to emulate 'e' mode
Browse files Browse the repository at this point in the history
Newer glibc versions (that we can't require) allow for an additional
letter 'e' in the fopen mode that will cause the file to be opened with
the O_CLOEXEC flag, so that it will be closed if the program exec()s
away. This is important because if liblxc is used in a multithreaded
program, another thread might want to run a program. This options
prevents the leakage of file descriptors from LXC. This patch adds an
emulation for that that uses the open(2) syscall and fdopen(3). At some
later point in time, it may be dropped against fopen(..., "...e").

This commit also converts all fopen() calls in utils.c (where the
function is added) to fopen_cloexec(). Subsequently, other calls to
fopen() and open() should also be adapted.

Signed-off-by: Christian Seiler <christian@iwakd.de>
Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
  • Loading branch information
chris-se authored and stgraber committed Sep 10, 2013
1 parent 6e16552 commit db27c8d
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 2 deletions.
50 changes: 48 additions & 2 deletions src/lxc/utils.c
Expand Up @@ -245,7 +245,7 @@ const char *lxc_global_config_value(const char *option_name)
if (values[i])
return values[i];

fin = fopen(LXC_GLOBAL_CONF, "r");
fin = fopen_cloexec(LXC_GLOBAL_CONF, "r");
if (fin) {
while (fgets(buf, 1024, fin)) {
if (buf[0] == '#')
Expand Down Expand Up @@ -391,7 +391,7 @@ int sha1sum_file(char *fnam, unsigned char *digest)

if (!fnam)
return -1;
if ((f = fopen(fnam, "r")) < 0) {
if ((f = fopen_cloexec(fnam, "r")) < 0) {
SYSERROR("Error opening template");
return -1;
}
Expand Down Expand Up @@ -477,3 +477,49 @@ const char** lxc_va_arg_list_to_argv_const(va_list ap, size_t skip)
{
return (const char**)lxc_va_arg_list_to_argv(ap, skip, 0);
}

FILE *fopen_cloexec(const char *path, const char *mode)
{
int open_mode = 0;
int step = 0;
int fd;
int saved_errno = 0;
FILE *ret;

if (!strncmp(mode, "r+", 2)) {
open_mode = O_RDWR;
step = 2;
} else if (!strncmp(mode, "r", 1)) {
open_mode = O_RDONLY;
step = 1;
} else if (!strncmp(mode, "w+", 2)) {
open_mode = O_RDWR | O_TRUNC | O_CREAT;
step = 2;
} else if (!strncmp(mode, "w", 1)) {
open_mode = O_WRONLY | O_TRUNC | O_CREAT;
step = 1;
} else if (!strncmp(mode, "a+", 2)) {
open_mode = O_RDWR | O_CREAT | O_APPEND;
step = 2;
} else if (!strncmp(mode, "a", 1)) {
open_mode = O_WRONLY | O_CREAT | O_APPEND;
step = 1;
}
for (; mode[step]; step++)
if (mode[step] == 'x')
open_mode |= O_EXCL;
open_mode |= O_CLOEXEC;

fd = (open_mode & O_CREAT) ?
open(path, open_mode, 0666) :
open(path, open_mode);
if (fd < 0)
return NULL;

ret = fdopen(fd, mode);
saved_errno = errno;
if (!ret)
close(fd);
errno = saved_errno;
return ret;
}
3 changes: 3 additions & 0 deletions src/lxc/utils.h
Expand Up @@ -148,6 +148,9 @@ static inline int signalfd(int fd, const sigset_t *mask, int flags)
}
#endif

/* open a file with O_CLOEXEC */
FILE *fopen_cloexec(const char *path, const char *mode);


/**
* BUILD_BUG_ON - break compile if a condition is true.
Expand Down

0 comments on commit db27c8d

Please sign in to comment.