From d9dfb4d53461965d1fb99cb64b2f28666fe1f9e0 Mon Sep 17 00:00:00 2001 From: Alexander Bluhm Date: Thu, 19 Dec 2019 19:09:54 +0000 Subject: The previous fix for creating isakmpd(8) IKE pcap file, weakened the path sanitizer in the privsep parent. Bring back the checks in a way that works with new realpath(3). tested and OK hshoexer@ --- sbin/isakmpd/monitor.c | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/sbin/isakmpd/monitor.c b/sbin/isakmpd/monitor.c index 380818d36d6..30fb565dedc 100644 --- a/sbin/isakmpd/monitor.c +++ b/sbin/isakmpd/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.79 2019/12/10 15:51:21 bluhm Exp $ */ +/* $OpenBSD: monitor.c,v 1.80 2019/12/19 19:09:53 bluhm Exp $ */ /* * Copyright (c) 2003 Håkan Olsson. All rights reserved. @@ -71,7 +71,7 @@ static void m_priv_setsockopt(void); static void m_priv_req_readdir(void); static void m_priv_bind(void); static void m_priv_pfkey_open(void); -static int m_priv_local_sanitize_path(char *, size_t, int); +static int m_priv_local_sanitize_path(const char *, size_t, int); static int m_priv_check_sockopt(int, int); static int m_priv_check_bind(const struct sockaddr *, socklen_t); @@ -517,8 +517,9 @@ m_priv_getfd(void) must_read(&mode, sizeof mode); if ((ret = m_priv_local_sanitize_path(path, sizeof path, flags)) - != 0 && errno != ENOENT) { - log_print("m_priv_getfd: illegal path \"%s\"", path); + != 0) { + if (errno != ENOENT) + log_print("m_priv_getfd: illegal path \"%s\"", path); err = errno; v = -1; } else { @@ -683,9 +684,9 @@ must_write(const void *buf, size_t n) /* Check that path/mode is permitted. */ static int -m_priv_local_sanitize_path(char *path, size_t pmax, int flags) +m_priv_local_sanitize_path(const char *path, size_t pmax, int flags) { - char new_path[PATH_MAX], var_run[PATH_MAX]; + char new_path[PATH_MAX], var_run[PATH_MAX], *enddir; /* * We only permit paths starting with @@ -693,8 +694,29 @@ m_priv_local_sanitize_path(char *path, size_t pmax, int flags) * /var/run/ (rw) */ - if (realpath(path, new_path) == NULL || - realpath("/var/run", var_run) == NULL) + if (realpath(path, new_path) == NULL) { + if (errno != ENOENT) + return 1; + /* + * It is ok if the directory exists, + * but the file should be created. + */ + if (strlcpy(new_path, path, sizeof(new_path)) >= + sizeof(new_path)) + return 1; + enddir = strrchr(new_path, '/'); + if (enddir == NULL || enddir[1] == '\0') + return 1; + enddir[1] = '\0'; + if (realpath(new_path, new_path) == NULL) { + errno = ENOENT; + return 1; + } + enddir = strrchr(path, '/'); + strlcat(new_path, enddir, sizeof(new_path)); + } + + if (realpath("/var/run/", var_run) == NULL) return 1; strlcat(var_run, "/", sizeof(var_run)); -- cgit v1.2.3