Skip to content

Commit 7c2c322

Browse files
committed
Open directories with the O_DIRECTORY flag.
We cannot use O_PATH on Linux in many cases because older kernels don't support fchdir() or fstat() on an fd opened with O_PATH.
1 parent 0ecdcb6 commit 7c2c322

File tree

21 files changed

+45
-34
lines changed

21 files changed

+45
-34
lines changed

include/sudo_compat.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,11 @@
144144
# endif
145145
#endif
146146

147+
/* Older systems lack O_DIRECTORY. */
148+
#ifndef O_DIRECTORY
149+
# define O_DIRECTORY 0
150+
#endif
151+
147152
/*
148153
* BSD defines these in <sys/param.h> but we don't include that anymore.
149154
*/

lib/iolog/iolog_loginfo.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ 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)) == -1) {
52+
if ((tmpfd = open(iolog_dir, O_RDONLY|O_DIRECTORY)) == -1) {
5353
sudo_warn("%s", iolog_dir);
5454
goto bad;
5555
}

lib/iolog/iolog_mkdirs.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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);
56+
dfd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY);
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);
60+
dfd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY);
6161
if (!iolog_swapids(true)) {
6262
ok = false;
6363
goto done;

lib/iolog/regress/fuzz/fuzz_iolog_timing.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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);
89+
dfd = open(logdir, O_RDONLY|O_DIRECTORY);
9090
if (dfd == -1)
9191
goto cleanup;
9292

lib/iolog/regress/iolog_filter/check_iolog_filter.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ main(int argc, char *argv[])
7272
ntests++;
7373

7474
/* I/O logs consist of multiple files in a directory. */
75-
dfd = open(logdir, O_RDONLY);
75+
dfd = open(logdir, O_RDONLY|O_DIRECTORY);
7676
if (dfd == -1) {
7777
sudo_warn("%s", logdir);
7878
errors++;

lib/util/fchmodat.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ sudo_fchmodat(int dfd, const char *path, mode_t mode, int flag)
4040
if (dfd == (int)AT_FDCWD)
4141
return chmod(path, mode);
4242

43-
/* Save cwd */
44-
if ((odfd = open(".", O_RDONLY)) == -1)
43+
/* Save cwd (cannot use O_PATH on older Linux kernels). */
44+
if ((odfd = open(".", O_RDONLY|O_DIRECTORY)) == -1)
4545
goto done;
4646

4747
if (fchdir(dfd) == -1)

lib/util/fchownat.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ sudo_fchownat(int dfd, const char *path, uid_t uid, gid_t gid, int flags)
3636
return chown(path, uid, gid);
3737
}
3838

39-
/* Save cwd */
40-
if ((odfd = open(".", O_RDONLY)) == -1)
39+
/* Save cwd (cannot use O_PATH on older Linux kernels). */
40+
if ((odfd = open(".", O_RDONLY|O_DIRECTORY)) == -1)
4141
return -1;
4242

4343
if (fchdir(dfd) == -1) {

lib/util/fstatat.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ sudo_fstatat(int dfd, const char * restrict path, struct stat * restrict sb, int
3838
return stat(path, sb);
3939
}
4040

41-
/* Save cwd */
42-
if ((odfd = open(".", O_RDONLY)) == -1)
41+
/* Save cwd (cannot use O_PATH on older Linux kernels). */
42+
if ((odfd = open(".", O_RDONLY|O_DIRECTORY)) == -1)
4343
goto done;
4444

4545
if (fchdir(dfd) == -1)

lib/util/mkdir_parents.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,9 @@ sudo_open_parent_dir_v1(const char *path, uid_t uid, gid_t gid, mode_t mode,
8989
do {
9090
cp++;
9191
} while (*cp == '/');
92-
parentfd = open("/", O_RDONLY|O_NONBLOCK);
92+
parentfd = open("/", O_RDONLY|O_NONBLOCK|O_DIRECTORY);
9393
} else {
94-
parentfd = open(".", O_RDONLY|O_NONBLOCK);
94+
parentfd = open(".", O_RDONLY|O_NONBLOCK|O_DIRECTORY);
9595
}
9696
if (parentfd == -1) {
9797
if (!quiet)
@@ -118,7 +118,7 @@ sudo_open_parent_dir_v1(const char *path, uid_t uid, gid_t gid, mode_t mode,
118118
memcpy(name, cp, len);
119119
name[len] = '\0';
120120
reopen:
121-
dfd = openat(parentfd, name, O_RDONLY|O_NONBLOCK, 0);
121+
dfd = openat(parentfd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY, 0);
122122
if (dfd == -1) {
123123
if (errno != ENOENT) {
124124
if (!quiet) {
@@ -128,7 +128,8 @@ sudo_open_parent_dir_v1(const char *path, uid_t uid, gid_t gid, mode_t mode,
128128
goto bad;
129129
}
130130
if (mkdirat(parentfd, name, mode) == 0) {
131-
dfd = openat(parentfd, name, O_RDONLY|O_NONBLOCK|O_NOFOLLOW, 0);
131+
dfd = openat(parentfd, name,
132+
O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_NOFOLLOW, 0);
132133
if (dfd == -1) {
133134
if (!quiet) {
134135
sudo_warn(U_("unable to open %.*s"),

lib/util/mkdirat.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ sudo_mkdirat(int dfd, const char *path, mode_t mode)
3333
if (dfd == (int)AT_FDCWD)
3434
return mkdir(path, mode);
3535

36-
/* Save cwd */
37-
if ((odfd = open(".", O_RDONLY)) == -1)
36+
/* Save cwd (cannot use O_PATH on older Linux kernels). */
37+
if ((odfd = open(".", O_RDONLY|O_DIRECTORY)) == -1)
3838
return -1;
3939

4040
if (fchdir(dfd) == -1) {

0 commit comments

Comments
 (0)