commit 10800ee410286c3f19ffa7fd563fe0cf08e3a68a
parent b4299f4f4e38e17e348f26b496d1a9c5b534e89f
Author: Benno Schulenberg <bensberg@telfort.nl>
Date: Wed, 20 May 2020 16:17:30 +0200
locking: prevent a symlink attack by not opening an existing lock file
If in between the unlink() in delete_lockfile() and the fopen() in
write_lockfile() some other process creates a symlink in the place
of the lock file, then the fopen() could unexpectedly overwite a
root-owned file (when the user is root).
This basically reverts the previous commit, b4299f4f, but makes the
code a bit conciser.
Diffstat:
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/src/files.c b/src/files.c
@@ -129,6 +129,7 @@ bool write_lockfile(const char *lockfilename, const char *filename, bool modifie
struct passwd *mypwuid = getpwuid(myuid);
char myhostname[32];
struct stat fileinfo;
+ int fd;
FILE *filestream;
char *lockdata;
size_t wroteamt;
@@ -150,12 +151,17 @@ bool write_lockfile(const char *lockfilename, const char *filename, bool modifie
if (!delete_lockfile(lockfilename))
return FALSE;
- /* Create lock file (or truncate existing one) and open it for writing. */
- filestream = fopen(lockfilename, "wb");
+ /* Create the lockfile -- do not accept an existing one. */
+ fd = open(lockfilename, O_WRONLY|O_CREAT|O_EXCL, RW_FOR_ALL);
+
+ if (fd > 0)
+ filestream = fdopen(fd, "wb");
- if (filestream == NULL) {
+ if (fd < 0 || filestream == NULL) {
statusline(MILD, _("Error writing lock file %s: %s"),
lockfilename, strerror(errno));
+ if (fd > 0)
+ close(fd);
return FALSE;
}