mirror of
https://gitlab.com/chrony/chrony.git
synced 2025-12-04 09:05:06 -05:00
main: create new file when writing pidfile
When writing the pidfile, open the file with the O_CREAT|O_EXCL flags to avoid following a symlink and writing the PID to an unexpected file, when chronyd still has the root privileges. The Linux open(2) man page warns about O_EXCL not working as expected on NFS versions before 3 and Linux versions before 2.6. Saving pidfiles on a distributed filesystem like NFS is not generally expected, but if there is a reason to do that, these old kernel and NFS versions are not considered to be supported for saving files by chronyd. This is a minimal backport specific to this issue of the following commits: - commit2fc8edacb8("use PATH_MAX") - commitf4c6a00b2a("logging: call exit() in LOG_Message()") - commit7a4c396bba("util: add functions for common file operations") - commite18903a6b5("switch to new util file functions") Reported-by: Matthias Gerstner <mgerstner@suse.de>
This commit is contained in:
95
util.c
95
util.c
@@ -1179,6 +1179,101 @@ UTI_CheckDirPermissions(const char *path, mode_t perm, uid_t uid, gid_t gid)
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static int
|
||||
join_path(const char *basedir, const char *name, const char *suffix,
|
||||
char *buffer, size_t length, LOG_Severity severity)
|
||||
{
|
||||
const char *sep;
|
||||
|
||||
if (!basedir) {
|
||||
basedir = "";
|
||||
sep = "";
|
||||
} else {
|
||||
sep = "/";
|
||||
}
|
||||
|
||||
if (!suffix)
|
||||
suffix = "";
|
||||
|
||||
if (snprintf(buffer, length, "%s%s%s%s", basedir, sep, name, suffix) >= length) {
|
||||
LOG(severity, "File path %s%s%s%s too long", basedir, sep, name, suffix);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
FILE *
|
||||
UTI_OpenFile(const char *basedir, const char *name, const char *suffix,
|
||||
char mode, mode_t perm)
|
||||
{
|
||||
const char *file_mode;
|
||||
char path[PATH_MAX];
|
||||
LOG_Severity severity;
|
||||
int fd, flags;
|
||||
FILE *file;
|
||||
|
||||
severity = mode >= 'A' && mode <= 'Z' ? LOGS_FATAL : LOGS_ERR;
|
||||
|
||||
if (!join_path(basedir, name, suffix, path, sizeof (path), severity))
|
||||
return NULL;
|
||||
|
||||
switch (mode) {
|
||||
case 'r':
|
||||
case 'R':
|
||||
flags = O_RDONLY;
|
||||
file_mode = "r";
|
||||
if (severity != LOGS_FATAL)
|
||||
severity = LOGS_DEBUG;
|
||||
break;
|
||||
case 'w':
|
||||
case 'W':
|
||||
flags = O_WRONLY | O_CREAT | O_EXCL;
|
||||
file_mode = "w";
|
||||
break;
|
||||
case 'a':
|
||||
case 'A':
|
||||
flags = O_WRONLY | O_CREAT | O_APPEND;
|
||||
file_mode = "a";
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
try_again:
|
||||
fd = open(path, flags, perm);
|
||||
if (fd < 0) {
|
||||
if (errno == EEXIST) {
|
||||
if (unlink(path) < 0) {
|
||||
LOG(severity, "Could not remove %s : %s", path, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
DEBUG_LOG("Removed %s", path);
|
||||
goto try_again;
|
||||
}
|
||||
LOG(severity, "Could not open %s : %s", path, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UTI_FdSetCloexec(fd);
|
||||
|
||||
file = fdopen(fd, file_mode);
|
||||
if (!file) {
|
||||
LOG(severity, "Could not open %s : %s", path, strerror(errno));
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DEBUG_LOG("Opened %s fd=%d mode=%c", path, fd, mode);
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
UTI_DropRoot(uid_t uid, gid_t gid)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user