Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 24 additions & 5 deletions audisp/audispd-pconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <unistd.h>
#include <stdlib.h>
#include <libgen.h>
#include <limits.h>
#include "audispd-pconfig.h"
#include "private.h"

Expand Down Expand Up @@ -134,7 +135,7 @@ void clear_pconfig(plugin_conf_t *config)
config->restart_cnt = 0;
}

int load_pconfig(plugin_conf_t *config, char *file)
int load_pconfig(plugin_conf_t *config, int dirfd, char *file)
{
int fd, rc, mode, lineno = 1;
struct stat st;
Expand All @@ -143,9 +144,10 @@ int load_pconfig(plugin_conf_t *config, char *file)

clear_pconfig(config);

/* open the file */
mode = O_RDONLY;
rc = open(file, mode);
/* O_PATH avoids blocking, as no read/seek is done.
* We do not pass O_NOFOLLOW, which allows for symlinked configs.
*/
rc = openat(dirfd, file, O_PATH);
if (rc < 0) {
if (errno != ENOENT) {
audit_msg(LOG_ERR, "Error opening %s (%s)", file,
Expand All @@ -159,7 +161,7 @@ int load_pconfig(plugin_conf_t *config, char *file)
fd = rc;

/* check the file's permissions: owned by root, not world writable,
* not symlink.
* pointing to regular file.
*/
if (fstat(fd, &st) < 0) {
audit_msg(LOG_ERR, "Error fstat'ing config file (%s)",
Expand All @@ -179,13 +181,30 @@ int load_pconfig(plugin_conf_t *config, char *file)
close(fd);
return 1;
}
// this checks if the actual file is a regular file. The initial open might have followed a symlink, which is acceptable.
if (!S_ISREG(st.st_mode)) {
audit_msg(LOG_ERR, "Error - %s is not a regular file",
file);
close(fd);
return 1;
}

// reopen with read perms
char fname[PATH_MAX];
snprintf(fname, PATH_MAX, "/proc/self/fd/%i", fd);
mode = O_RDONLY;
rc = open(fname, mode);

if (rc < 0) {
audit_msg(LOG_ERR, "Error - Failed to reopen %s for reading",
file);
close(fd);
return 1;
}

close(fd);
fd = rc;

/* it's ok, read line by line */
f = fdopen(fd, "rm");
if (f == NULL) {
Expand Down
2 changes: 1 addition & 1 deletion audisp/audispd-pconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ typedef struct plugin_conf
} plugin_conf_t;

void clear_pconfig(plugin_conf_t *config);
int load_pconfig(plugin_conf_t *config, char *file);
int load_pconfig(plugin_conf_t *config, int dirfd, char *file);
void free_pconfig(plugin_conf_t *config);

#endif
Expand Down
16 changes: 8 additions & 8 deletions audisp/audispd.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,16 +111,19 @@ static void load_plugin_conf(conf_llist *plugin)
/* read configs */
d = opendir(daemon_config.plugin_dir);
if (d) {
int dfd = dirfd(d);
if (dfd < 0) {
closedir(d);
return;
}

struct dirent *e;

while ((e = readdir(d))) {
plugin_conf_t config;
char fname[PATH_MAX];
const char *ext, *reason = NULL;

if (e->d_type != DT_REG)
reason = "not a regular file";
else if (e->d_name[0] == '.')
if (e->d_name[0] == '.')
reason = "hidden file";
else if (count_dots(e->d_name) > 1)
reason = "backup file";
Expand All @@ -132,11 +135,8 @@ static void load_plugin_conf(conf_llist *plugin)
continue;
}

snprintf(fname, sizeof(fname), "%s/%s",
daemon_config.plugin_dir, e->d_name);

clear_pconfig(&config);
if (load_pconfig(&config, fname) == 0) {
if (load_pconfig(&config, dfd, e->d_name) == 0) {
/* Push onto config list only if active */
if (config.active == A_YES)
plist_append(plugin, &config);
Expand Down