summaryrefslogtreecommitdiff
path: root/libexec
diff options
context:
space:
mode:
authorkre <kre@NetBSD.org>2022-05-17 11:18:58 +0000
committerkre <kre@NetBSD.org>2022-05-17 11:18:58 +0000
commita94b15d05ff55533299f1b5a05d460b926ad98bc (patch)
tree407cbda6dbe535f3b9d1eb3f49482fcf5c826435 /libexec
parentf5563f850413b8a83b94591c5990315bdffada9d (diff)
fix local privilege escalation due to a race condition
NetBSD-SA2016-006 included an incomplete fix for CVE-2016-6253, a local privilege escalation vulnerability in mail.local(8). mail.local(8) attempts to open(2) a user's existing mailbox file to append to it. If that call fails, mail.local(8) will then issue a second open(2) call to create the file (O_CREAT). An attacker had the opportunity to create the file in question (as a symlink, or link to some other file) in between these two open(2) calls. Fix this by using O_EXCL in the 2nd open call, if the file exists when that one happens, something is going wrong, so just abort. Also, only attempt that 2nd open if the reason the first failed was that the file did not exist (this doesn't fix the issue, but it potentially saves some cycles). Thanks to Jan Schaumann for bringing this to our attention.
Diffstat (limited to 'libexec')
-rw-r--r--libexec/mail.local/mail.local.c11
1 files changed, 6 insertions, 5 deletions
diff --git a/libexec/mail.local/mail.local.c b/libexec/mail.local/mail.local.c
index a7f2e672fa9..12fb27dd452 100644
--- a/libexec/mail.local/mail.local.c
+++ b/libexec/mail.local/mail.local.c
@@ -1,4 +1,4 @@
-/* $NetBSD: mail.local.c,v 1.28 2016/07/21 12:29:37 shm Exp $ */
+/* $NetBSD: mail.local.c,v 1.29 2022/05/17 11:18:58 kre Exp $ */
/*-
* Copyright (c) 1990, 1993, 1994
@@ -36,7 +36,7 @@ __COPYRIGHT("@(#) Copyright (c) 1990, 1993, 1994\
#if 0
static char sccsid[] = "@(#)mail.local.c 8.22 (Berkeley) 6/21/95";
#else
-__RCSID("$NetBSD: mail.local.c,v 1.28 2016/07/21 12:29:37 shm Exp $");
+__RCSID("$NetBSD: mail.local.c,v 1.29 2022/05/17 11:18:58 kre Exp $");
#endif
#endif /* not lint */
@@ -217,11 +217,12 @@ deliver(int fd, char *name, int lockfile)
return(EX_OSERR);
}
- if ((mbfd = open(path, O_APPEND|O_WRONLY|O_EXLOCK,
+ if ((mbfd = open(path, O_APPEND|O_WRONLY|O_EXLOCK|O_NOFOLLOW,
S_IRUSR|S_IWUSR)) == -1) {
/* create file */
- if ((mbfd = open(path, O_APPEND|O_CREAT|O_WRONLY|O_EXLOCK,
- S_IRUSR|S_IWUSR)) == -1) {
+ if (errno != ENOENT ||
+ (mbfd = open(path, O_APPEND|O_CREAT|O_WRONLY|O_EXLOCK|O_EXCL,
+ S_IRUSR|S_IWUSR)) == -1) {
logwarn("%s: %s", path, strerror(errno));
rval = EX_OSERR;
goto bad;