Use O_CLOEXEC as much as possible when opening files

When calling open(), use O_CLOEXEC as much as possible to ensure the
file descriptor is closed when and if a process using libalpm forks.

For most of these cases, and especially in utility functions, the file
descriptor is opened and closed in the same function, so we don't have
too much to worry about. However, for things like the log file and
database lock file, we should ensure descriptors aren't left hanging
around for children to touch.

This patch is inspired by the problem in FS#36161, where an open file
descriptor to the current working directory prevents chroot() from
working on FreeBSD. We don't need this file descriptor in the child
process, so open it (and now several others) with O_CLOEXEC.

Signed-off-by: Dan McGee <dan@archlinux.org>
Signed-off-by: Allan McRae <allan@archlinux.org>
This commit is contained in:
Dan McGee 2014-01-02 12:37:12 -06:00 committed by Allan McRae
parent 8bec8a3f6a
commit 086bbc5b62
4 changed files with 18 additions and 11 deletions

View file

@ -556,7 +556,7 @@ static int commit_single_pkg(alpm_handle_t *handle, alpm_pkg_t *newpkg,
} }
/* save the cwd so we can restore it later */ /* save the cwd so we can restore it later */
OPEN(cwdfd, ".", O_RDONLY); OPEN(cwdfd, ".", O_RDONLY | O_CLOEXEC);
if(cwdfd < 0) { if(cwdfd < 0) {
_alpm_log(handle, ALPM_LOG_ERROR, _("could not get current working directory\n")); _alpm_log(handle, ALPM_LOG_ERROR, _("could not get current working directory\n"));
} }

View file

@ -110,7 +110,7 @@ int _alpm_handle_lock(alpm_handle_t *handle)
FREE(dir); FREE(dir);
do { do {
handle->lockfd = open(handle->lockfile, O_WRONLY | O_CREAT | O_EXCL, 0000); handle->lockfd = open(handle->lockfile, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, 0000);
} while(handle->lockfd == -1 && errno == EINTR); } while(handle->lockfd == -1 && errno == EINTR);
return (handle->lockfd >= 0 ? 0 : -1); return (handle->lockfd >= 0 ? 0 : -1);

View file

@ -49,9 +49,16 @@ int SYMEXPORT alpm_logaction(alpm_handle_t *handle, const char *prefix,
/* check if the logstream is open already, opening it if needed */ /* check if the logstream is open already, opening it if needed */
if(handle->logstream == NULL) { if(handle->logstream == NULL) {
handle->logstream = fopen(handle->logfile, "a"); int fd;
do {
fd = open(handle->logfile, O_WRONLY | O_APPEND | O_CREAT | O_CLOEXEC,
0000);
} while(fd == -1 && errno == EINTR);
if(fd >= 0) {
handle->logstream = fdopen(fd, "a");
}
/* if we couldn't open it, we have an issue */ /* if we couldn't open it, we have an issue */
if(handle->logstream == NULL) { if(fd < 0 || handle->logstream == NULL) {
if(errno == EACCES) { if(errno == EACCES) {
handle->pm_errno = ALPM_ERR_BADPERMS; handle->pm_errno = ALPM_ERR_BADPERMS;
} else if(errno == ENOENT) { } else if(errno == ENOENT) {

View file

@ -153,9 +153,9 @@ int _alpm_copyfile(const char *src, const char *dest)
MALLOC(buf, (size_t)ALPM_BUFFER_SIZE, return 1); MALLOC(buf, (size_t)ALPM_BUFFER_SIZE, return 1);
OPEN(in, src, O_RDONLY); OPEN(in, src, O_RDONLY | O_CLOEXEC);
do { do {
out = open(dest, O_WRONLY | O_CREAT, 0000); out = open(dest, O_WRONLY | O_CREAT | O_BINARY | O_CLOEXEC, 0000);
} while(out == -1 && errno == EINTR); } while(out == -1 && errno == EINTR);
if(in < 0 || out < 0) { if(in < 0 || out < 0) {
goto cleanup; goto cleanup;
@ -244,7 +244,7 @@ int _alpm_open_archive(alpm_handle_t *handle, const char *path,
archive_read_support_format_all(*archive); archive_read_support_format_all(*archive);
_alpm_log(handle, ALPM_LOG_DEBUG, "opening archive %s\n", path); _alpm_log(handle, ALPM_LOG_DEBUG, "opening archive %s\n", path);
OPEN(fd, path, O_RDONLY); OPEN(fd, path, O_RDONLY | O_CLOEXEC);
if(fd < 0) { if(fd < 0) {
_alpm_log(handle, ALPM_LOG_ERROR, _alpm_log(handle, ALPM_LOG_ERROR,
_("could not open file %s: %s\n"), path, strerror(errno)); _("could not open file %s: %s\n"), path, strerror(errno));
@ -326,7 +326,7 @@ int _alpm_unpack(alpm_handle_t *handle, const char *path, const char *prefix,
oldmask = umask(0022); oldmask = umask(0022);
/* save the cwd so we can restore it later */ /* save the cwd so we can restore it later */
OPEN(cwdfd, ".", O_RDONLY); OPEN(cwdfd, ".", O_RDONLY | O_CLOEXEC);
if(cwdfd < 0) { if(cwdfd < 0) {
_alpm_log(handle, ALPM_LOG_ERROR, _("could not get current working directory\n")); _alpm_log(handle, ALPM_LOG_ERROR, _("could not get current working directory\n"));
} }
@ -502,7 +502,7 @@ int _alpm_run_chroot(alpm_handle_t *handle, const char *cmd, char *const argv[])
int retval = 0; int retval = 0;
/* save the cwd so we can restore it later */ /* save the cwd so we can restore it later */
OPEN(cwdfd, ".", O_RDONLY); OPEN(cwdfd, ".", O_RDONLY | O_CLOEXEC);
if(cwdfd < 0) { if(cwdfd < 0) {
_alpm_log(handle, ALPM_LOG_ERROR, _("could not get current working directory\n")); _alpm_log(handle, ALPM_LOG_ERROR, _("could not get current working directory\n"));
} }
@ -778,7 +778,7 @@ static int md5_file(const char *path, unsigned char output[16])
MALLOC(buf, (size_t)ALPM_BUFFER_SIZE, return 1); MALLOC(buf, (size_t)ALPM_BUFFER_SIZE, return 1);
OPEN(fd, path, O_RDONLY); OPEN(fd, path, O_RDONLY | O_CLOEXEC);
if(fd < 0) { if(fd < 0) {
free(buf); free(buf);
return 1; return 1;
@ -820,7 +820,7 @@ static int sha2_file(const char *path, unsigned char output[32], int is224)
MALLOC(buf, (size_t)ALPM_BUFFER_SIZE, return 1); MALLOC(buf, (size_t)ALPM_BUFFER_SIZE, return 1);
OPEN(fd, path, O_RDONLY); OPEN(fd, path, O_RDONLY | O_CLOEXEC);
if(fd < 0) { if(fd < 0) {
free(buf); free(buf);
return 1; return 1;