File bsc1179191_CVE-2020-28935_19f8f4d9.patch of Package unbound.22509
commit 19f8f4d9f99a44906ab9dcc46d44da299fde3506
Author: W.C.A. Wijngaards <wouter@nlnetlabs.nl>
Date: Mon Nov 23 13:48:04 2020 +0100
Further fix for CVE-2020-28935, so the chown is omitted when the pidfile
fails due to a symlink.
commit ad387832979b6ce4c93f64fe706301cd7d034e87
Author: W.C.A. Wijngaards <wouter@nlnetlabs.nl>
Date: Mon Nov 23 13:42:11 2020 +0100
- Fix for #303 CVE-2020-28935 : Fix that symlink does not interfere
with chown of pidfile.
---
daemon/unbound.c | 52 +++++++++++++++++++++++++++++++++++-----------------
1 file changed, 35 insertions(+), 17 deletions(-)
--- daemon/unbound.c
+++ daemon/unbound.c 2022-01-19 08:17:55.765153598 +0000
@@ -323,22 +323,39 @@ readpid (const char* file)
/** write pid to file.
* @param pidfile: file name of pid file.
* @param pid: pid to write to file.
+ * @return false on failure
*/
-static void
+static int
writepid (const char* pidfile, pid_t pid)
{
- FILE* f;
-
- if ((f = fopen(pidfile, "w")) == NULL ) {
+ int fd;
+ char pidbuf[32];
+ size_t count = 0;
+ snprintf(pidbuf, sizeof(pidbuf), "%lu\n", (unsigned long)pid);
+
+ if((fd = open(pidfile, O_WRONLY | O_CREAT | O_TRUNC
+#ifdef O_NOFOLLOW
+ | O_NOFOLLOW
+#endif
+ , 0644)) == -1) {
log_err("cannot open pidfile %s: %s",
pidfile, strerror(errno));
- return;
+ return 0;
}
- if(fprintf(f, "%lu\n", (unsigned long)pid) < 0) {
- log_err("cannot write to pidfile %s: %s",
- pidfile, strerror(errno));
+ while(count < strlen(pidbuf)) {
+ ssize_t r = write(fd, pidbuf+count, strlen(pidbuf)-count);
+ if(r == -1) {
+ if(errno == EAGAIN || errno == EINTR)
+ continue;
+ log_err("cannot write to pidfile %s: %s",
+ pidfile, strerror(errno));
+ close(fd);
+ return 0;
+ }
+ count += r;
}
- fclose(f);
+ close(fd);
+ return 1;
}
/**
@@ -473,16 +490,17 @@ perform_setup(struct daemon* daemon, str
/* write new pidfile (while still root, so can be outside chroot) */
#ifdef HAVE_KILL
if(cfg->pidfile && cfg->pidfile[0] && need_pidfile) {
- writepid(daemon->pidfile, getpid());
- if(cfg->username && cfg->username[0] && cfg_uid != (uid_t)-1 &&
- pidinchroot) {
+ if(writepid(daemon->pidfile, getpid())) {
+ if(cfg->username && cfg->username[0] && cfg_uid != (uid_t)-1 &&
+ pidinchroot) {
# ifdef HAVE_CHOWN
- if(chown(daemon->pidfile, cfg_uid, cfg_gid) == -1) {
- verbose(VERB_QUERY, "cannot chown %u.%u %s: %s",
- (unsigned)cfg_uid, (unsigned)cfg_gid,
- daemon->pidfile, strerror(errno));
- }
+ if(chown(daemon->pidfile, cfg_uid, cfg_gid) == -1) {
+ verbose(VERB_QUERY, "cannot chown %u.%u %s: %s",
+ (unsigned)cfg_uid, (unsigned)cfg_gid,
+ daemon->pidfile, strerror(errno));
+ }
# endif /* HAVE_CHOWN */
+ }
}
}
#else