Skip to content

Commit 6015f4e

Browse files
committed
auditd: Avoid blocking on open syscall
`open` might block on FIFO files or some character/block devices such as /dev/tty. Checking `stat` based on path introduces a TOCTOU issue. The "correct" way to check this is using `O_PATH` option with `open` to get a stable file descriptor, then use that for stats, only opening for actual read later.
1 parent f233955 commit 6015f4e

File tree

1 file changed

+17
-5
lines changed

1 file changed

+17
-5
lines changed

audisp/audispd-pconfig.c

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -143,9 +143,11 @@ int load_pconfig(plugin_conf_t *config, char *file)
143143

144144
clear_pconfig(config);
145145

146-
/* open the file */
147-
mode = O_RDONLY;
148-
rc = open(file, mode);
146+
/* only get a file descriptor, don't fully open.
147+
* This avoids blocking on block/char devices and FIFO files.
148+
* We do not pass O_NOFOLLOW, which allows for symlinked configs.
149+
*/
150+
rc = open(file, O_PATH);
149151
if (rc < 0) {
150152
if (errno != ENOENT) {
151153
audit_msg(LOG_ERR, "Error opening %s (%s)", file,
@@ -156,10 +158,9 @@ int load_pconfig(plugin_conf_t *config, char *file)
156158
"Config file %s doesn't exist, skipping", file);
157159
return 0;
158160
}
159-
fd = rc;
160161

161162
/* check the file's permissions: owned by root, not world writable,
162-
* not symlink.
163+
* pointing to regular file.
163164
*/
164165
if (fstat(fd, &st) < 0) {
165166
audit_msg(LOG_ERR, "Error fstat'ing config file (%s)",
@@ -179,13 +180,24 @@ int load_pconfig(plugin_conf_t *config, char *file)
179180
close(fd);
180181
return 1;
181182
}
183+
// this checks if the actual file is a regular file. The initial open might have followed a symlink, which is acceptable.
182184
if (!S_ISREG(st.st_mode)) {
183185
audit_msg(LOG_ERR, "Error - %s is not a regular file",
184186
file);
185187
close(fd);
186188
return 1;
187189
}
188190

191+
/* reopen the file for reading, now that it is determined to be safe */
192+
mode = O_RDONLY;
193+
rc = openat(fd, "", mode);
194+
if (rc < 0) {
195+
audit_msg(LOG_WARNING,
196+
"Error reopening file %s for reading", file);
197+
return 1;
198+
}
199+
fd = rc;
200+
189201
/* it's ok, read line by line */
190202
f = fdopen(fd, "rm");
191203
if (f == NULL) {

0 commit comments

Comments
 (0)