Fix potential TOCTOU when creating time stamp directory and file.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: ISC
|
||||
*
|
||||
* Copyright (c) 2009-2021 Todd C. Miller <Todd.Miller@sudo.ws>
|
||||
* Copyright (c) 2009-2022 Todd C. Miller <Todd.Miller@sudo.ws>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@@ -76,16 +76,17 @@ is_dir(int dfd, const char *name, int namelen, bool quiet)
|
||||
}
|
||||
|
||||
/*
|
||||
* Create any parent directories needed by path (but not path itself).
|
||||
* Create any parent directories needed by path (but not path itself)
|
||||
* and return an open fd for the parent directory or -1 on error.
|
||||
*/
|
||||
bool
|
||||
sudo_mkdir_parents_v1(const char *path, uid_t uid, gid_t gid, mode_t mode, bool quiet)
|
||||
int
|
||||
sudo_open_parent_dir_v1(const char *path, uid_t uid, gid_t gid, mode_t mode,
|
||||
bool quiet)
|
||||
{
|
||||
const char *cp, *ep, *pathend;
|
||||
char name[PATH_MAX];
|
||||
bool ret = false;
|
||||
int parentfd;
|
||||
debug_decl(sudo_mkdir_parents, SUDO_DEBUG_UTIL);
|
||||
debug_decl(sudo_open_parent_dir, SUDO_DEBUG_UTIL);
|
||||
|
||||
/* Starting parent dir is either root or cwd. */
|
||||
cp = path;
|
||||
@@ -100,7 +101,7 @@ sudo_mkdir_parents_v1(const char *path, uid_t uid, gid_t gid, mode_t mode, bool
|
||||
if (parentfd == -1) {
|
||||
if (!quiet)
|
||||
sudo_warn(U_("unable to open %s"), *path == '/' ? "/" : ".");
|
||||
debug_return_bool(false);
|
||||
debug_return_int(-1);
|
||||
}
|
||||
|
||||
/* Iterate over path components, skipping the last one. */
|
||||
@@ -129,7 +130,7 @@ reopen:
|
||||
sudo_warn(U_("unable to open %.*s"),
|
||||
(int)(ep - path), path);
|
||||
}
|
||||
goto done;
|
||||
goto bad;
|
||||
}
|
||||
if (mkdirat(parentfd, name, mode) == 0) {
|
||||
dfd = openat(parentfd, name, O_RDONLY|O_NONBLOCK|O_NOFOLLOW, 0);
|
||||
@@ -138,12 +139,12 @@ reopen:
|
||||
sudo_warn(U_("unable to open %.*s"),
|
||||
(int)(ep - path), path);
|
||||
}
|
||||
goto done;
|
||||
goto bad;
|
||||
}
|
||||
/* Make sure the path we created is still a directory. */
|
||||
if (!is_dir(dfd, path, ep - path, quiet)) {
|
||||
close(dfd);
|
||||
goto done;
|
||||
goto bad;
|
||||
}
|
||||
if (uid != (uid_t)-1 && gid != (gid_t)-1) {
|
||||
if (fchown(dfd, uid, gid) != 0) {
|
||||
@@ -159,22 +160,39 @@ reopen:
|
||||
sudo_warn(U_("unable to mkdir %.*s"),
|
||||
(int)(ep - path), path);
|
||||
}
|
||||
goto done;
|
||||
goto bad;
|
||||
}
|
||||
} else {
|
||||
/* Already exists, make sure it is a directory. */
|
||||
if (!is_dir(dfd, path, ep - path, quiet)) {
|
||||
close(dfd);
|
||||
goto done;
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
close(parentfd);
|
||||
parentfd = dfd;
|
||||
}
|
||||
ret = true;
|
||||
|
||||
done:
|
||||
debug_return_int(parentfd);
|
||||
bad:
|
||||
if (parentfd != -1)
|
||||
close(parentfd);
|
||||
debug_return_bool(ret);
|
||||
debug_return_int(-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create any parent directories needed by path (but not path itself).
|
||||
*/
|
||||
bool
|
||||
sudo_mkdir_parents_v1(const char *path, uid_t uid, gid_t gid, mode_t mode,
|
||||
bool quiet)
|
||||
{
|
||||
int fd;
|
||||
debug_decl(sudo_mkdir_parents, SUDO_DEBUG_UTIL);
|
||||
|
||||
fd = sudo_open_parent_dir(path, uid, gid, mode, quiet);
|
||||
if (fd == -1)
|
||||
debug_return_bool(false);
|
||||
close(fd);
|
||||
debug_return_bool(true);
|
||||
}
|
||||
|
Reference in New Issue
Block a user