From 3ba3399f943dff5d5fbe0c4b89752b0ec549ff74 Mon Sep 17 00:00:00 2001 From: Chris Webb Date: Tue, 28 Nov 2023 08:51:32 +0000 Subject: [PATCH] Set replacement file permissions before moving into place When doing :write -method replace, make sure we've set the correct mode, uid and gid on the replacement file before attempting to rename it on top of the original. This means that the original file is left in place with correct permissions if anything fails, rather than ending up with 0700 permissions from mkstemp(). --- src/file.cc | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/file.cc b/src/file.cc index a13e5c47..87112e24 100644 --- a/src/file.cc +++ b/src/file.cc @@ -369,6 +369,13 @@ void write_buffer_to_file(Buffer& buffer, StringView filename, ::fsync(fd); } + if (replace and geteuid() == 0 and ::chown(temp_filename, st.st_uid, st.st_gid) < 0) + throw runtime_error(format("unable to set replacement file ownership: {}", strerror(errno))); + if (replace and ::chmod(temp_filename, st.st_mode) < 0) + throw runtime_error(format("unable to set replacement file permissions: {}", strerror(errno))); + if (force and not replace and ::chmod(zfilename, st.st_mode) < 0) + throw runtime_error(format("unable to restore file permissions: {}", strerror(errno))); + if (replace and rename(temp_filename, zfilename) != 0) { if (force) @@ -376,11 +383,6 @@ void write_buffer_to_file(Buffer& buffer, StringView filename, throw runtime_error("replacing file failed"); } - if (replace and geteuid() == 0 and ::chown(zfilename, st.st_uid, st.st_gid) < 0) - throw runtime_error(format("unable to restore file ownership: {}", strerror(errno))); - if ((force or replace) and ::chmod(zfilename, st.st_mode) < 0) - throw runtime_error(format("unable to restore file permissions: {}", strerror(errno))); - if ((buffer.flags() & Buffer::Flags::File) and real_path(filename) == real_path(buffer.name())) buffer.notify_saved(get_fs_status(real_path(filename)));