Skip to content

Commit

Permalink
libsemanage: set O_CLOEXEC flag for file descriptors
Browse files Browse the repository at this point in the history
Close internal managed file descriptors in case of an concurrent execve.

Also avoid leaking file descriptors in get_shell_list().

Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
  • Loading branch information
cgzones authored and bachradsusi committed Nov 27, 2024
1 parent 0bafe76 commit f1eb41d
Show file tree
Hide file tree
Showing 9 changed files with 35 additions and 33 deletions.
4 changes: 2 additions & 2 deletions libsemanage/src/compressed_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ static int bzip(semanage_handle_t *sh, const char *filename, void *data,
size_t len;
FILE *f;

if ((f = fopen(filename, "wb")) == NULL) {
if ((f = fopen(filename, "wbe")) == NULL) {
return -1;
}

Expand Down Expand Up @@ -177,7 +177,7 @@ int map_compressed_file(semanage_handle_t *sh, const char *path,
int ret = 0, fd = -1;
FILE *file = NULL;

fd = open(path, O_RDONLY);
fd = open(path, O_RDONLY | O_CLOEXEC);
if (fd == -1) {
ERR(sh, "Unable to open %s\n", path);
return -1;
Expand Down
2 changes: 1 addition & 1 deletion libsemanage/src/conf-parse.y
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,7 @@ semanage_conf_t *semanage_conf_parse(const char *config_filename)
if (semanage_conf_init(current_conf) == -1) {
goto cleanup;
}
if ((semanage_in = fopen(config_filename, "r")) == NULL) {
if ((semanage_in = fopen(config_filename, "re")) == NULL) {
/* configuration file does not exist or could not be
* read. THIS IS NOT AN ERROR. just rely on the
* defaults. */
Expand Down
2 changes: 1 addition & 1 deletion libsemanage/src/database_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ static int dbase_file_flush(semanage_handle_t * handle, dbase_file_t * dbase)
fname = dbase->path[handle->is_in_transaction];

mask = umask(0077);
str = fopen(fname, "w");
str = fopen(fname, "we");
umask(mask);
if (!str) {
ERR(handle, "could not open %s for writing: %s",
Expand Down
2 changes: 1 addition & 1 deletion libsemanage/src/database_policydb.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ static int dbase_policydb_cache(semanage_handle_t * handle,

/* Try opening file
* ENOENT is not fatal - we just create an empty policydb */
fp = fopen(fname, "rb");
fp = fopen(fname, "rbe");
if (fp == NULL && errno != ENOENT) {
ERR(handle, "could not open %s for reading: %s",
fname, strerror(errno));
Expand Down
20 changes: 10 additions & 10 deletions libsemanage/src/direct_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,7 @@ static int write_file(semanage_handle_t * sh,
int out;

if ((out =
open(filename, O_WRONLY | O_CREAT | O_TRUNC,
open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC,
S_IRUSR | S_IWUSR)) == -1) {
ERR(sh, "Could not open %s for writing.", filename);
return -1;
Expand Down Expand Up @@ -644,17 +644,17 @@ static int semanage_pipe_data(semanage_handle_t *sh, const char *path, const cha
*/
sigaction(SIGPIPE, &new_signal, &old_signal);

retval = pipe(input_fd);
retval = pipe2(input_fd, O_CLOEXEC);
if (retval == -1) {
ERR(sh, "Unable to create pipe for input pipe: %s\n", strerror(errno));
goto cleanup;
}
retval = pipe(output_fd);
retval = pipe2(output_fd, O_CLOEXEC);
if (retval == -1) {
ERR(sh, "Unable to create pipe for output pipe: %s\n", strerror(errno));
goto cleanup;
}
retval = pipe(err_fd);
retval = pipe2(err_fd, O_CLOEXEC);
if (retval == -1) {
ERR(sh, "Unable to create pipe for error pipe: %s\n", strerror(errno));
goto cleanup;
Expand Down Expand Up @@ -826,7 +826,7 @@ static int semanage_direct_write_langext(semanage_handle_t *sh,
goto cleanup;
}

fp = fopen(fn, "w");
fp = fopen(fn, "we");
if (fp == NULL) {
ERR(sh, "Unable to open %s module ext file.", modinfo->name);
ret = -1;
Expand Down Expand Up @@ -1077,7 +1077,7 @@ static int semanage_compare_checksum(semanage_handle_t *sh, const char *referenc
int fd, retval;
char *data;

fd = open(path, O_RDONLY);
fd = open(path, O_RDONLY | O_CLOEXEC);
if (fd == -1) {
if (errno != ENOENT) {
ERR(sh, "Unable to open %s: %s\n", path, strerror(errno));
Expand Down Expand Up @@ -1218,7 +1218,7 @@ static int semanage_direct_commit(semanage_handle_t * sh)
}
if (sepol_get_disable_dontaudit(sh->sepolh) == 1) {
FILE *touch;
touch = fopen(path, "w");
touch = fopen(path, "we");
if (touch != NULL) {
if (fclose(touch) != 0) {
ERR(sh, "Error attempting to create disable_dontaudit flag.");
Expand Down Expand Up @@ -1250,7 +1250,7 @@ static int semanage_direct_commit(semanage_handle_t * sh)

if (sepol_get_preserve_tunables(sh->sepolh) == 1) {
FILE *touch;
touch = fopen(path, "w");
touch = fopen(path, "we");
if (touch != NULL) {
if (fclose(touch) != 0) {
ERR(sh, "Error attempting to create preserve_tunable flag.");
Expand Down Expand Up @@ -2109,7 +2109,7 @@ static int semanage_direct_set_enabled(semanage_handle_t *sh,
switch (enabled) {
case 0: /* disable the module */
mask = umask(0077);
fp = fopen(fn, "w");
fp = fopen(fn, "we");
umask(mask);

if (fp == NULL) {
Expand Down Expand Up @@ -2296,7 +2296,7 @@ static int semanage_direct_get_module_info(semanage_handle_t *sh,
goto cleanup;
}

fp = fopen(fn, "r");
fp = fopen(fn, "re");

if (fp == NULL) {
ERR(sh,
Expand Down
8 changes: 5 additions & 3 deletions libsemanage/src/genhomedircon.c
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ static semanage_list_t *get_shell_list(void)
size_t buff_len = 0;
ssize_t len;

shells = fopen(PATH_SHELLS_FILE, "r");
shells = fopen(PATH_SHELLS_FILE, "re");
if (!shells)
return default_shell_list();
while ((len = getline(&temp, &buff_len, shells)) > 0) {
Expand All @@ -227,11 +227,13 @@ static semanage_list_t *get_shell_list(void)
if (semanage_list_push(&list, temp)) {
free(temp);
semanage_list_destroy(&list);
fclose(shells);
return default_shell_list();
}
}
}
free(temp);
fclose(shells);

return list;
}
Expand Down Expand Up @@ -503,7 +505,7 @@ static semanage_list_t *make_template(genhomedircon_settings_t * s,
FILE *template_file = NULL;
semanage_list_t *template_data = NULL;

template_file = fopen(s->homedir_template_path, "r");
template_file = fopen(s->homedir_template_path, "re");
if (!template_file)
return NULL;
template_data = semanage_slurp_file_filter(template_file, pred);
Expand Down Expand Up @@ -1413,7 +1415,7 @@ int semanage_genhomedircon(semanage_handle_t * sh,
s.h_semanage = sh;
s.policydb = policydb;

if (!(out = fopen(s.fcfilepath, "w"))) {
if (!(out = fopen(s.fcfilepath, "we"))) {
/* couldn't open output file */
ERR(sh, "Could not open the file_context file for writing");
retval = STATUS_ERR;
Expand Down
2 changes: 1 addition & 1 deletion libsemanage/src/parse_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ void parse_release(parse_info_t * info)
int parse_open(semanage_handle_t * handle, parse_info_t * info)
{

info->file_stream = fopen(info->filename, "r");
info->file_stream = fopen(info->filename, "re");
if (!info->file_stream && (errno != ENOENT)) {
ERR(handle, "could not open file %s: %s",
info->filename, strerror(errno));
Expand Down
26 changes: 13 additions & 13 deletions libsemanage/src/semanage_store.c
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,7 @@ int semanage_create_store(semanage_handle_t * sh, int create)
if (stat(path, &sb) == -1) {
if (errno == ENOENT && create) {
mask = umask(0077);
if ((fd = creat(path, S_IRUSR | S_IWUSR)) == -1) {
if ((fd = open(path, O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC, S_IRUSR | S_IWUSR)) == -1) {
umask(mask);
ERR(sh, "Could not create lock file at %s.",
path);
Expand Down Expand Up @@ -682,15 +682,15 @@ int semanage_copy_file(semanage_handle_t *sh, const char *src, const char *dst,
if (n < 0 || n >= PATH_MAX)
return -1;

if ((in = open(src, O_RDONLY)) == -1) {
if ((in = open(src, O_RDONLY | O_CLOEXEC)) == -1) {
return -1;
}

if (!mode)
mode = S_IRUSR | S_IWUSR;

mask = umask(0);
if ((out = open(tmp, O_WRONLY | O_CREAT | O_TRUNC, mode)) == -1) {
if ((out = open(tmp, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, mode)) == -1) {
umask(mask);
errsv = errno;
close(in);
Expand Down Expand Up @@ -1489,22 +1489,22 @@ int semanage_split_fc(semanage_handle_t * sh)
char buf[PATH_MAX] = { 0 };

/* I use fopen here instead of open so that I can use fgets which only reads a single line */
file_con = fopen(semanage_path(SEMANAGE_TMP, SEMANAGE_FC_TMPL), "r");
file_con = fopen(semanage_path(SEMANAGE_TMP, SEMANAGE_FC_TMPL), "re");
if (!file_con) {
ERR(sh, "Could not open %s for reading.",
semanage_path(SEMANAGE_TMP, SEMANAGE_FC_TMPL));
goto cleanup;
}

fc = open(semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC),
O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, S_IRUSR | S_IWUSR);
if (fc < 0) {
ERR(sh, "Could not open %s for writing.",
semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC));
goto cleanup;
}
hd = open(semanage_path(SEMANAGE_TMP, SEMANAGE_HOMEDIR_TMPL),
O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, S_IRUSR | S_IWUSR);
if (hd < 0) {
ERR(sh, "Could not open %s for writing.",
semanage_path(SEMANAGE_TMP, SEMANAGE_HOMEDIR_TMPL));
Expand Down Expand Up @@ -1719,7 +1719,7 @@ static int semanage_commit_sandbox(semanage_handle_t * sh)
memset(write_buf, 0, sizeof(write_buf));
snprintf(write_buf, sizeof(write_buf), "%d", commit_number);
if ((fd =
open(commit_filename, O_WRONLY | O_CREAT | O_TRUNC,
open(commit_filename, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC,
S_IRUSR | S_IWUSR)) == -1) {
ERR(sh, "Could not open commit number file %s for writing.",
commit_filename);
Expand All @@ -1735,7 +1735,7 @@ static int semanage_commit_sandbox(semanage_handle_t * sh)
close(fd);

/* sync changes in sandbox to filesystem */
fd = open(sandbox, O_DIRECTORY);
fd = open(sandbox, O_DIRECTORY | O_CLOEXEC);
if (fd == -1) {
ERR(sh, "Error while opening %s for syncfs(): %d", sandbox, errno);
return -1;
Expand Down Expand Up @@ -1869,7 +1869,7 @@ static int semanage_get_lock(semanage_handle_t * sh,
int got_lock = 0;

if ((fd =
open(lock_file, O_RDWR | O_CREAT | O_TRUNC,
open(lock_file, O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC,
S_IRUSR | S_IWUSR)) == -1) {
ERR(sh, "Could not open direct %s at %s.", lock_name,
lock_file);
Expand Down Expand Up @@ -2013,7 +2013,7 @@ int semanage_direct_get_serial(semanage_handle_t * sh)
semanage_path(SEMANAGE_ACTIVE, SEMANAGE_COMMIT_NUM_FILE);
}

if ((fd = open(commit_filename, O_RDONLY)) == -1) {
if ((fd = open(commit_filename, O_RDONLY | O_CLOEXEC)) == -1) {
if (errno == ENOENT) {
/* the commit number file does not exist yet,
* so assume that the number is 0 */
Expand Down Expand Up @@ -2093,7 +2093,7 @@ int semanage_read_policydb(semanage_handle_t * sh, sepol_policydb_t * in,
semanage_path(SEMANAGE_ACTIVE, file)) == NULL) {
goto cleanup;
}
if ((infile = fopen(kernel_filename, "r")) == NULL) {
if ((infile = fopen(kernel_filename, "re")) == NULL) {
ERR(sh, "Could not open kernel policy %s for reading.",
kernel_filename);
goto cleanup;
Expand Down Expand Up @@ -2136,7 +2136,7 @@ int semanage_write_policydb(semanage_handle_t * sh, sepol_policydb_t * out,
semanage_path(SEMANAGE_TMP, file)) == NULL) {
goto cleanup;
}
if ((outfile = fopen(kernel_filename, "wb")) == NULL) {
if ((outfile = fopen(kernel_filename, "wbe")) == NULL) {
ERR(sh, "Could not open kernel policy %s for writing.",
kernel_filename);
goto cleanup;
Expand Down Expand Up @@ -3003,7 +3003,7 @@ void semanage_setfiles(semanage_handle_t * sh, const char *path){

/* Make sure "path" is owned by root */
if ((geteuid() != 0 || getegid() != 0) &&
((fd = open(path, O_RDONLY)) != -1)){
((fd = open(path, O_RDONLY | O_CLOEXEC)) != -1)){
/* Skip files with the SUID or SGID bit set -- abuse protection */
if ((fstat(fd, &sb) != -1) &&
!(S_ISREG(sb.st_mode) &&
Expand Down
2 changes: 1 addition & 1 deletion libsemanage/src/utilities.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ char *semanage_findval(const char *file, const char *var, const char *delim)
assert(file);
assert(var);

if ((fd = fopen(file, "r")) == NULL)
if ((fd = fopen(file, "re")) == NULL)
return NULL;

while (getline(&buff, &buff_len, fd) > 0) {
Expand Down

0 comments on commit f1eb41d

Please sign in to comment.