Skip to content

Commit ce13289

Browse files
committed
Use O_NOFOLLOW in places where we don't expect a symlink.
This means things like the I/O log files and when we are creating new files.
1 parent a930899 commit ce13289

18 files changed

Lines changed: 62 additions & 56 deletions

lib/iolog/iolog_loginfo.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* SPDX-License-Identifier: ISC
33
*
4-
* Copyright (c) 2009-2020 Todd C. Miller <Todd.Miller@sudo.ws>
4+
* Copyright (c) 2009-2023, 2025-2026 Todd C. Miller <Todd.Miller@sudo.ws>
55
*
66
* Permission to use, copy, modify, and distribute this software for any
77
* purpose with or without fee is hereby granted, provided that the above
@@ -49,14 +49,14 @@ iolog_parse_loginfo(int dfd, const char *iolog_dir)
4949
debug_decl(iolog_parse_loginfo, SUDO_DEBUG_UTIL);
5050

5151
if (dfd == -1) {
52-
if ((tmpfd = open(iolog_dir, O_RDONLY|O_DIRECTORY)) == -1) {
52+
if ((tmpfd = open(iolog_dir, O_RDONLY|O_DIRECTORY|O_NOFOLLOW)) == -1) {
5353
sudo_warn("%s", iolog_dir);
5454
goto bad;
5555
}
5656
dfd = tmpfd;
5757
}
58-
if ((fd = openat(dfd, "log.json", O_RDONLY, 0)) == -1) {
59-
fd = openat(dfd, "log", O_RDONLY, 0);
58+
if ((fd = openat(dfd, "log.json", O_RDONLY|O_NOFOLLOW, 0)) == -1) {
59+
fd = openat(dfd, "log", O_RDONLY|O_NOFOLLOW, 0);
6060
legacy = true;
6161
}
6262
if (tmpfd != -1)
@@ -103,7 +103,7 @@ iolog_write_info_file_legacy(int dfd, struct eventlog *evlog)
103103
int error, fd;
104104
debug_decl(iolog_info_write_log, SUDO_DEBUG_UTIL);
105105

106-
fd = iolog_openat(dfd, "log", O_CREAT|O_TRUNC|O_WRONLY);
106+
fd = iolog_openat(dfd, "log", O_CREAT|O_TRUNC|O_WRONLY|O_NOFOLLOW);
107107
if (fd == -1 || (fp = fdopen(fd, "w")) == NULL) {
108108
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
109109
"unable to %sopen %s/log", fd == -1 ? "" : "fd", evlog->iolog_path);
@@ -178,7 +178,7 @@ iolog_write_info_file_json(int dfd, struct eventlog *evlog)
178178
if (!eventlog_store_json(&jsonc, evlog))
179179
goto done;
180180

181-
fd = iolog_openat(dfd, "log.json", O_CREAT|O_TRUNC|O_WRONLY);
181+
fd = iolog_openat(dfd, "log.json", O_CREAT|O_TRUNC|O_WRONLY|O_NOFOLLOW);
182182
if (fd == -1 || (fp = fdopen(fd, "w")) == NULL) {
183183
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
184184
"unable to %sopen %s/log.json", fd == -1 ? "" : "fd",

lib/iolog/iolog_mkdirs.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* SPDX-License-Identifier: ISC
33
*
4-
* Copyright (c) 2009-2022 Todd C. Miller <Todd.Miller@sudo.ws>
4+
* Copyright (c) 2009-2023, 2025-2026 Todd C. Miller <Todd.Miller@sudo.ws>
55
*
66
* Permission to use, copy, modify, and distribute this software for any
77
* purpose with or without fee is hereby granted, provided that the above
@@ -53,11 +53,11 @@ iolog_mkdirs(const char *path)
5353
int dfd;
5454
debug_decl(iolog_mkdirs, SUDO_DEBUG_UTIL);
5555

56-
dfd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY);
56+
dfd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_NOFOLLOW);
5757
if (dfd == -1 && errno == EACCES) {
5858
/* Try again as the I/O log owner (for NFS). */
5959
if (iolog_swapids(false)) {
60-
dfd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY);
60+
dfd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_NOFOLLOW);
6161
if (!iolog_swapids(true)) {
6262
ok = false;
6363
goto done;

lib/iolog/iolog_nextid.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* SPDX-License-Identifier: ISC
33
*
4-
* Copyright (c) 2009-2021 Todd C. Miller <Todd.Miller@sudo.ws>
4+
* Copyright (c) 2009-2021, 2026 Todd C. Miller <Todd.Miller@sudo.ws>
55
*
66
* Permission to use, copy, modify, and distribute this software for any
77
* purpose with or without fee is hereby granted, provided that the above
@@ -82,7 +82,7 @@ iolog_nextid(const char *iolog_dir, char sessid[7])
8282
"%s: %s/seq", __func__, iolog_dir);
8383
goto done;
8484
}
85-
fd = iolog_openat(AT_FDCWD, pathbuf, O_RDWR|O_CREAT);
85+
fd = iolog_openat(AT_FDCWD, pathbuf, O_RDWR|O_CREAT|O_NOFOLLOW);
8686
if (fd == -1) {
8787
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
8888
"%s: unable to open %s", __func__, pathbuf);

lib/iolog/iolog_open.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* SPDX-License-Identifier: ISC
33
*
4-
* Copyright (c) 2009-2021 Todd C. Miller <Todd.Miller@sudo.ws>
4+
* Copyright (c) 2009-2021, 2025-2026 Todd C. Miller <Todd.Miller@sudo.ws>
55
*
66
* Permission to use, copy, modify, and distribute this software for any
77
* purpose with or without fee is hereby granted, provided that the above
@@ -80,7 +80,7 @@ iolog_open(struct iolog_file *iol, int dfd, int iofd, const char *mode)
8080
iol->compressed = false;
8181
iol->locked = false;
8282
if (iol->enabled) {
83-
int fd = iolog_openat(dfd, file, flags);
83+
int fd = iolog_openat(dfd, file, flags|O_NOFOLLOW);
8484
if (lockit && fd != -1) {
8585
if (sudo_lock_file(fd, SUDO_TLOCK)) {
8686
iol->locked = true;

lib/iolog/regress/fuzz/fuzz_iolog_timing.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2021 Todd C. Miller <Todd.Miller@sudo.ws>
2+
* Copyright (c) 2021, 2025-2026 Todd C. Miller <Todd.Miller@sudo.ws>
33
*
44
* Permission to use, copy, modify, and distribute this software for any
55
* purpose with or without fee is hereby granted, provided that the above
@@ -86,7 +86,7 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
8686
return 0;
8787

8888
/* Create a timing file from the supplied data. */
89-
dfd = open(logdir, O_RDONLY|O_DIRECTORY);
89+
dfd = open(logdir, O_RDONLY|O_DIRECTORY|O_NOFOLLOW);
9090
if (dfd == -1)
9191
goto cleanup;
9292

lib/util/sudo_debug.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* SPDX-License-Identifier: ISC
33
*
4-
* Copyright (c) 2011-2023 Todd C. Miller <Todd.Miller@sudo.ws>
4+
* Copyright (c) 2011-2023, 2026 Todd C. Miller <Todd.Miller@sudo.ws>
55
*
66
* Permission to use, copy, modify, and distribute this software for any
77
* purpose with or without fee is hereby granted, provided that the above
@@ -164,12 +164,13 @@ sudo_debug_new_output(struct sudo_debug_instance *instance,
164164
output->settings[j] = -1;
165165

166166
/* Open debug file. */
167-
output->fd = open(output->filename, O_WRONLY|O_APPEND, S_IRUSR|S_IWUSR);
167+
output->fd = open(output->filename, O_WRONLY|O_APPEND|O_NOFOLLOW,
168+
S_IRUSR|S_IWUSR);
168169
if (output->fd == -1) {
169170
/* Create debug file as needed and set group ownership. */
170171
if (errno == ENOENT) {
171-
output->fd = open(output->filename, O_WRONLY|O_APPEND|O_CREAT,
172-
S_IRUSR|S_IWUSR);
172+
output->fd = open(output->filename,
173+
O_WRONLY|O_APPEND|O_CREAT|O_NOFOLLOW, S_IRUSR|S_IWUSR);
173174
}
174175
if (output->fd == -1) {
175176
sudo_warn_nodebug("%s", output->filename);

logsrvd/iolog_writer.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* SPDX-License-Identifier: ISC
33
*
4-
* Copyright (c) 2019-2022 Todd C. Miller <Todd.Miller@sudo.ws>
4+
* Copyright (c) 2019-2023, 2025-2026 Todd C. Miller <Todd.Miller@sudo.ws>
55
*
66
* Permission to use, copy, modify, and distribute this software for any
77
* purpose with or without fee is hereby granted, provided that the above
@@ -637,8 +637,8 @@ create_iolog_path(struct connection_closure *closure)
637637
evlog->iolog_file = evlog->iolog_path + strlen(expanded_dir) + 1;
638638

639639
/* We use iolog_dir_fd in calls to openat(2) */
640-
closure->iolog_dir_fd =
641-
iolog_openat(AT_FDCWD, evlog->iolog_path, O_RDONLY|O_DIRECTORY);
640+
closure->iolog_dir_fd = iolog_openat(AT_FDCWD, evlog->iolog_path,
641+
O_RDONLY|O_DIRECTORY|O_NOFOLLOW);
642642
if (closure->iolog_dir_fd == -1) {
643643
sudo_warn("%s", evlog->iolog_path);
644644
goto bad;
@@ -721,7 +721,7 @@ iolog_store_uuid(int dfd, struct connection_closure *closure)
721721
}
722722

723723
/* Write UUID in string form to the I/O log directory. */
724-
fd = iolog_openat(dfd, "uuid", O_CREAT|O_TRUNC|O_WRONLY);
724+
fd = iolog_openat(dfd, "uuid", O_CREAT|O_TRUNC|O_WRONLY|O_NOFOLLOW);
725725
if (fd == -1) {
726726
sudo_warn(U_("unable to open %s/%s"), closure->evlog->iolog_path,
727727
"uuid");
@@ -894,7 +894,7 @@ iolog_rewrite(const struct timespec *target, struct connection_closure *closure)
894894
sudo_warn(U_("unable to mkdir %s"), tmpdir);
895895
goto done;
896896
}
897-
tmpdir_fd = iolog_openat(AT_FDCWD, tmpdir, O_RDONLY|O_DIRECTORY);
897+
tmpdir_fd = iolog_openat(AT_FDCWD, tmpdir, O_RDONLY|O_DIRECTORY|O_NOFOLLOW);
898898
if (tmpdir_fd == -1) {
899899
sudo_warn(U_("unable to open %s"), tmpdir);
900900
goto done;

logsrvd/logsrvd_conf.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* SPDX-License-Identifier: ISC
33
*
4-
* Copyright (c) 2019-2025 Todd C. Miller <Todd.Miller@sudo.ws>
4+
* Copyright (c) 2019-2026 Todd C. Miller <Todd.Miller@sudo.ws>
55
*
66
* Permission to use, copy, modify, and distribute this software for any
77
* purpose with or without fee is hereby granted, provided that the above
@@ -1315,9 +1315,9 @@ logsrvd_open_eventlog(struct logsrvd_config *config)
13151315

13161316
/* Cannot append to a JSON file that is a single object. */
13171317
if (config->eventlog.log_format == EVLOG_JSON_PRETTY) {
1318-
flags = O_RDWR|O_CREAT;
1318+
flags = O_RDWR|O_CREAT|O_NOFOLLOW;
13191319
} else {
1320-
flags = O_WRONLY|O_APPEND|O_CREAT;
1320+
flags = O_WRONLY|O_APPEND|O_CREAT|O_NOFOLLOW;
13211321
}
13221322
debug_return_ptr(logsrvd_open_log_file(config->logfile.path, flags));
13231323
}
@@ -1836,7 +1836,8 @@ logsrvd_conf_apply(struct logsrvd_config *config)
18361836
break;
18371837
case SERVER_LOG_FILE:
18381838
config->server.log_stream =
1839-
logsrvd_open_log_file(config->server.log_file, O_WRONLY|O_APPEND|O_CREAT);
1839+
logsrvd_open_log_file(config->server.log_file,
1840+
O_WRONLY|O_APPEND|O_CREAT|O_NOFOLLOW);
18401841
if (config->server.log_stream == NULL)
18411842
debug_return_bool(false);
18421843
sudo_warn_set_conversation(logsrvd_conv_logfile);

logsrvd/logsrvd_journal.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* SPDX-License-Identifier: ISC
33
*
4-
* Copyright (c) 2021-2022 Todd C. Miller <Todd.Miller@sudo.ws>
4+
* Copyright (c) 2021-2026 Todd C. Miller <Todd.Miller@sudo.ws>
55
*
66
* Permission to use, copy, modify, and distribute this software for any
77
* purpose with or without fee is hereby granted, provided that the above
@@ -128,7 +128,8 @@ journal_mkuuid(const char *parent_dir, char *pathbuf, size_t pathsize)
128128
goto done;
129129
}
130130
}
131-
fd = openat(dfd, uuid_str, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR);
131+
fd = openat(dfd, uuid_str, O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW,
132+
S_IRUSR|S_IWUSR);
132133
} while (fd == -1 && errno == EEXIST);
133134
if (fd == -1) {
134135
sudo_warn(U_("%s: %s"), "openat", pathbuf);
@@ -496,7 +497,7 @@ journal_restart(const RestartMessage *msg, const uint8_t *buf, size_t buflen,
496497
closure->errstr = _("unable to open journal file");
497498
debug_return_bool(false);
498499
}
499-
if ((fd = open(journal_path, O_RDWR)) == -1) {
500+
if ((fd = open(journal_path, O_RDWR|O_NOFOLLOW)) == -1) {
500501
sudo_warn(U_("unable to open %s"), journal_path);
501502
closure->errstr = _("unable to open journal file");
502503
debug_return_bool(false);

logsrvd/logsrvd_local.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* SPDX-License-Identifier: ISC
33
*
4-
* Copyright (c) 2019-2025 Todd C. Miller <Todd.Miller@sudo.ws>
4+
* Copyright (c) 2019-2026 Todd C. Miller <Todd.Miller@sudo.ws>
55
*
66
* Permission to use, copy, modify, and distribute this software for any
77
* purpose with or without fee is hereby granted, provided that the above
@@ -298,7 +298,7 @@ store_exit_info_json(int dfd, const struct eventlog *evlog)
298298
if (!sudo_json_init(&jsonc, 4, false, false, false))
299299
goto done;
300300

301-
fd = iolog_openat(dfd, "log.json", O_RDWR);
301+
fd = iolog_openat(dfd, "log.json", O_RDWR|O_NOFOLLOW);
302302
if (fd == -1) {
303303
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
304304
"unable to open to %s/log.json", evlog->iolog_path);
@@ -489,7 +489,7 @@ verify_iolog_uuid(int dfd, const unsigned char uuid[restrict static 16])
489489
debug_decl(verify_iolog_uuid, SUDO_DEBUG_UTIL);
490490

491491
/* Read in the I/O log uuid (string form), which must be 36-bytes. */
492-
fd = openat(dfd, "uuid", O_RDONLY);
492+
fd = openat(dfd, "uuid", O_RDONLY|O_NOFOLLOW);
493493
if (fd == -1)
494494
goto done;
495495
if (fstat(fd, &sb) == -1 || sb.st_size != 36)
@@ -545,7 +545,7 @@ store_restart_local(const RestartMessage *msg, const uint8_t *buf, size_t len,
545545

546546
/* We use iolog_dir_fd in calls to openat(2) */
547547
closure->iolog_dir_fd = iolog_openat(AT_FDCWD,
548-
closure->evlog->iolog_path, O_RDONLY|O_DIRECTORY);
548+
closure->evlog->iolog_path, O_RDONLY|O_DIRECTORY|O_NOFOLLOW);
549549
if (closure->iolog_dir_fd == -1) {
550550
sudo_warn("%s", closure->evlog->iolog_path);
551551
goto bad;

0 commit comments

Comments
 (0)