nano

nano with my custom patches
git clone git://bsandro.tech/nano
Log | Files | Refs | README | LICENSE

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:
Msrc/files.c | 12+++++++++---
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; }