From nobody Wed Nov 27 22:27:16 2024 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4XzDZs0kpcz5fsV4; Wed, 27 Nov 2024 22:27:17 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R10" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4XzDZr6jwRz4VBJ; Wed, 27 Nov 2024 22:27:16 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1732746436; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=iUGwZ5BZ4TfABGgoSSgLlEZbDPnJFLPZgkXIHIoKjiw=; b=OEz5R8ZAzRYh4/gP+I41F0sNovCis4rOQ1DRhOtu+HDKEKfRInqfX83105g4M5L5aTkT7t n1Ei+lihfIrny0122S+UvzB8JppE9RKEUo5PuWhl7q7AvyuKgTn3RAG6mTE3Yxw0ndhSb1 T2pRQa8QJZYEy4tu5HMRNCZUujL+qZFLk5k8Wf+FahLm6QcGMSiL41L0ug+jtVq625TYGe zroRf6Dc5G52f14SQHIsrnzM38BhUZEN45olaw8zwP21N9jkY1vy0cwMfj49d2C2gkevAr aSD69ktzc1Ksf4miW9p0iLOFjlJqIX+6N6z456cYBAtOCiy8k6hUKr/s8AvGTw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1732746436; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=iUGwZ5BZ4TfABGgoSSgLlEZbDPnJFLPZgkXIHIoKjiw=; b=MQYLaxqYFTfSnBi5eD1Dz/XHIdtKReAwbUgHRU4FbmmrX7qFBYnFgTjtu2tliMXHNM2wq6 /gcuI3HltrPS/EbR+/mM4MD4Ec3hLGViAlOzm27/woUwNHr3v+6RzUuDxTYKgKP+Yr0y6p J5PYT6MQevT49mhvK6QW4iDV4SpuC4YItGCqpL0+Vlcfp56cccyL88pMGlC1NkGZiDU2Fq qRgqCTY/88d2OKNKORXzEiQpjXDDwy7ieTpr7Az/iX3oHOeDGfzVTtJ8tdtUPpyZ+w6X++ LpGaZMZEHoUIbAUTEcpIkYpecjnha9rUJxA6myJiY5PvlJ2TBT0P6vaCH3404A== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1732746436; a=rsa-sha256; cv=none; b=YrCmQg8+4qtjgffwnyZiAjsc2jOn0l09CLb5OP0v1O/AJRINyQ2zzSkXcmsiDqaLL9By3O y0oCkVhGcP05jhXt3Q53y5vYNEijPrQn8s30F/+mPep8aEljMJxWb9d8lXaJlDVOlhsjq2 JpWwb0l/eoFLfu1dQ/6fxDIpyaT+R4BcAAU+g754UHAcWOHeY3lAy2f++/owUi/tjgATJ2 +Gqa6kdaal9dmuZVuYlNHWT9DSWalQAM3AK7ybRLOtml8bWm8QGCZi8Kr0XsMavYdo+gZW mSPliA01cQcwb+yi8jJZ54RUEWXCl2fhlnLcNwQn+pxkpEb8fFSUDOiRta4V2g== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4XzDZr6LDvz1Rl4; Wed, 27 Nov 2024 22:27:16 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 4ARMRG4J026845; Wed, 27 Nov 2024 22:27:16 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 4ARMRGh4026842; Wed, 27 Nov 2024 22:27:16 GMT (envelope-from git) Date: Wed, 27 Nov 2024 22:27:16 GMT Message-Id: <202411272227.4ARMRGh4026842@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Jake Freeland Subject: git: 4ecbee2760f7 - main - syslogd: Open forwarding socket descriptors List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: jfree X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 4ecbee2760f7c7bb0af8b28c202b12d5374e9f4c Auto-Submitted: auto-generated The branch main has been updated by jfree: URL: https://cgit.FreeBSD.org/src/commit/?id=4ecbee2760f7c7bb0af8b28c202b12d5374e9f4c commit 4ecbee2760f7c7bb0af8b28c202b12d5374e9f4c Author: Jake Freeland AuthorDate: 2024-11-27 22:26:04 +0000 Commit: Jake Freeland CommitDate: 2024-11-27 22:26:04 +0000 syslogd: Open forwarding socket descriptors Previously, when forwarding a message to a remote address, the target's addrinfo was saved at config-parse-time. When message-deliver-time came, the message's addrinfo was passed into sendmsg(2) and delivered by the first available inet socket. Passing an addrinfo into sendmsg(2) is prohibited in Capsicum capability mode, so sockets are now opened and connected to their remote peers at config-parse-time when executing outside of the capability sandbox. These connected socket descriptors are saved and passed into sendmsg(2), allowing forwarding to be performed inside of the capability sandbox. Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D47104 --- usr.sbin/syslogd/syslogd.c | 145 +++++++++++++++++++++++----------- usr.sbin/syslogd/syslogd.h | 3 +- usr.sbin/syslogd/syslogd_cap_config.c | 35 ++++---- 3 files changed, 115 insertions(+), 68 deletions(-) diff --git a/usr.sbin/syslogd/syslogd.c b/usr.sbin/syslogd/syslogd.c index 8cc0534e509d..0e063b72beb6 100644 --- a/usr.sbin/syslogd/syslogd.c +++ b/usr.sbin/syslogd/syslogd.c @@ -364,9 +364,12 @@ close_filed(struct filed *f) switch (f->f_type) { case F_FORW: - if (f->f_addr != NULL) { - freeaddrinfo(f->f_addr); - f->f_addr = NULL; + if (f->f_addr_fds != NULL) { + for (size_t i = 0; i < f->f_num_addr_fds; ++i) + close(f->f_addr_fds[i]); + free(f->f_addr_fds); + f->f_addr_fds = NULL; + f->f_num_addr_fds = 0; } /* FALLTHROUGH */ case F_FILE: @@ -1742,30 +1745,49 @@ iovlist_truncate(struct iovlist *il, size_t size) static void fprintlog_write(struct filed *f, struct iovlist *il, int flags) { - struct msghdr msghdr; - struct addrinfo *r; - struct socklist *sl; const char *msgret; - ssize_t lsent; switch (f->f_type) { - case F_FORW: - dprintf(" %s", f->f_hname); - switch (f->f_addr->ai_family) { + case F_FORW: { + ssize_t lsent; + + if (Debug) { + int domain, sockfd = f->f_addr_fds[0]; + socklen_t len = sizeof(domain); + + if (getsockopt(sockfd, SOL_SOCKET, SO_DOMAIN, + &domain, &len) < 0) + err(1, "getsockopt"); + + printf(" %s", f->f_hname); + switch (domain) { #ifdef INET - case AF_INET: - dprintf(":%d\n", - ntohs(satosin(f->f_addr->ai_addr)->sin_port)); - break; + case AF_INET: { + struct sockaddr_in sin; + + len = sizeof(sin); + if (getpeername(sockfd, + (struct sockaddr *)&sin, &len) < 0) + err(1, "getpeername"); + printf(":%d\n", ntohs(sin.sin_port)); + break; + } #endif #ifdef INET6 - case AF_INET6: - dprintf(":%d\n", - ntohs(satosin6(f->f_addr->ai_addr)->sin6_port)); - break; + case AF_INET6: { + struct sockaddr_in6 sin6; + + len = sizeof(sin6); + if (getpeername(sockfd, + (struct sockaddr *)&sin6, &len) < 0) + err(1, "getpeername"); + printf(":%d\n", ntohs(sin6.sin6_port)); + break; + } #endif - default: - dprintf("\n"); + default: + printf("\n"); + } } #if defined(INET) || defined(INET6) @@ -1773,24 +1795,13 @@ fprintlog_write(struct filed *f, struct iovlist *il, int flags) iovlist_truncate(il, MaxForwardLen); #endif - lsent = 0; - for (r = f->f_addr; r; r = r->ai_next) { - memset(&msghdr, 0, sizeof(msghdr)); - msghdr.msg_name = r->ai_addr; - msghdr.msg_namelen = r->ai_addrlen; - msghdr.msg_iov = il->iov; - msghdr.msg_iovlen = il->iovcnt; - STAILQ_FOREACH(sl, &shead, next) { - if (sl->sl_socket < 0) - continue; - if (sl->sl_sa == NULL || - sl->sl_family == AF_UNSPEC || - sl->sl_family == AF_LOCAL) - continue; - lsent = sendmsg(sl->sl_socket, &msghdr, 0); - if (lsent == (ssize_t)il->totalsize) - break; - } + for (size_t i = 0; i < f->f_num_addr_fds; ++i) { + struct msghdr msg = { + .msg_iov = il->iov, + .msg_iovlen = il->iovcnt, + }; + + lsent = sendmsg(f->f_addr_fds[i], &msg, 0); if (lsent == (ssize_t)il->totalsize && !send_to_all) break; } @@ -1822,6 +1833,7 @@ fprintlog_write(struct filed *f, struct iovlist *il, int flags) } } break; + } case F_FILE: dprintf(" %s\n", f->f_fname); @@ -2650,17 +2662,36 @@ init(bool reload) printf("%s%s", _PATH_DEV, f->f_fname); break; - case F_FORW: - switch (f->f_addr->ai_family) { + case F_FORW: { + int domain, sockfd = f->f_addr_fds[0]; + socklen_t len = sizeof(domain); + + if (getsockopt(sockfd, SOL_SOCKET, SO_DOMAIN, + &domain, &len) < 0) + err(1, "getsockopt"); + + switch (domain) { #ifdef INET - case AF_INET: - port = ntohs(satosin(f->f_addr->ai_addr)->sin_port); + case AF_INET: { + struct sockaddr_in sin; + + len = sizeof(sin); + if (getpeername(sockfd, (struct sockaddr *)&sin, &len) < 0) + err(1, "getpeername"); + port = ntohs(sin.sin_port); break; + } #endif #ifdef INET6 - case AF_INET6: - port = ntohs(satosin6(f->f_addr->ai_addr)->sin6_port); + case AF_INET6: { + struct sockaddr_in6 sin6; + + len = sizeof(sin6); + if (getpeername(sockfd, (struct sockaddr *)&sin6, &len) < 0) + err(1, "getpeername"); + port = ntohs(sin6.sin6_port); break; + } #endif default: port = 0; @@ -2671,6 +2702,7 @@ init(bool reload) printf("%s", f->f_hname); } break; + } case F_PIPE: printf("%s", f->f_pname); @@ -2948,7 +2980,7 @@ parse_selector(const char *p, struct filed *f) static void parse_action(const char *p, struct filed *f) { - struct addrinfo hints, *res; + struct addrinfo *ai, hints, *res; int error, i; const char *q; bool syncfile; @@ -3003,7 +3035,28 @@ parse_action(const char *p, struct filed *f) dprintf("%s\n", gai_strerror(error)); break; } - f->f_addr = res; + + for (ai = res; ai != NULL; ai = ai->ai_next) + ++f->f_num_addr_fds; + + f->f_addr_fds = calloc(f->f_num_addr_fds, + sizeof(*f->f_addr_fds)); + if (f->f_addr_fds == NULL) + err(1, "malloc failed"); + + for (ai = res, i = 0; ai != NULL; ai = ai->ai_next, ++i) { + int *sockp = &f->f_addr_fds[i]; + + *sockp = socket(ai->ai_family, ai->ai_socktype, 0); + if (*sockp < 0) + err(1, "socket"); + if (connect(*sockp, ai->ai_addr, ai->ai_addrlen) < 0) + err(1, "connect"); + /* Make it a write-only socket. */ + if (shutdown(*sockp, SHUT_RD) < 0) + err(1, "shutdown"); + } + f->f_type = F_FORW; break; diff --git a/usr.sbin/syslogd/syslogd.h b/usr.sbin/syslogd/syslogd.h index b6f83ceb6d8d..744465a9cc00 100644 --- a/usr.sbin/syslogd/syslogd.h +++ b/usr.sbin/syslogd/syslogd.h @@ -156,7 +156,8 @@ struct filed { char f_fname[MAXPATHLEN]; /* F_FILE, F_CONSOLE, F_TTY */ struct { char f_hname[MAXHOSTNAMELEN]; - struct addrinfo *f_addr; + int *f_addr_fds; + size_t f_num_addr_fds; }; /* F_FORW */ struct { char f_pname[MAXPATHLEN]; diff --git a/usr.sbin/syslogd/syslogd_cap_config.c b/usr.sbin/syslogd/syslogd_cap_config.c index 09d49b0a41b2..a952dbe325a0 100644 --- a/usr.sbin/syslogd/syslogd_cap_config.c +++ b/usr.sbin/syslogd/syslogd_cap_config.c @@ -137,18 +137,9 @@ filed_to_nvlist(const struct filed *filed) } else if (f_type == F_FILE || f_type == F_CONSOLE || f_type == F_TTY) { nvlist_add_string(nvl_filed, "f_fname", filed->f_fname); } else if (f_type == F_FORW) { - struct addrinfo *ai = filed->f_addr, *cur; - nvlist_t *nvl_addrinfo; - nvlist_add_string(nvl_filed, "f_hname", filed->f_hname); - if (filed->f_addr != NULL) { - for (cur = ai; cur != NULL; cur = cur->ai_next) { - nvl_addrinfo = addrinfo_pack(cur); - nvlist_append_nvlist_array(nvl_filed, - "f_addr", nvl_addrinfo); - nvlist_destroy(nvl_addrinfo); - } - } + nvlist_add_descriptor_array(nvl_filed, "f_addr_fds", + filed->f_addr_fds, filed->f_num_addr_fds); } else if (filed->f_type == F_PIPE) { nvlist_add_string(nvl_filed, "f_pname", filed->f_pname); if (filed->f_procdesc >= 0) { @@ -217,19 +208,21 @@ nvlist_to_filed(const nvlist_t *nvl_filed) (void)strlcpy(filed->f_fname, nvlist_get_string(nvl_filed, "f_fname"), sizeof(filed->f_fname)); } else if (f_type == F_FORW) { - const nvlist_t * const *f_addr; - struct addrinfo *ai, **next = NULL; + const int *f_addr_fds; (void)strlcpy(filed->f_hname, nvlist_get_string(nvl_filed, "f_hname"), sizeof(filed->f_hname)); - f_addr = nvlist_get_nvlist_array(nvl_filed, "f_addr", &sz); - for (i = 0; i < sz; ++i) { - ai = addrinfo_unpack(f_addr[i]); - if (next == NULL) - filed->f_addr = ai; - else - *next = ai; - next = &ai->ai_next; + + f_addr_fds = nvlist_get_descriptor_array(nvl_filed, + "f_addr_fds", &filed->f_num_addr_fds); + filed->f_addr_fds = calloc(filed->f_num_addr_fds, + sizeof(*f_addr_fds)); + if (filed->f_addr_fds == NULL) + err(1, "calloc"); + for (i = 0; i < filed->f_num_addr_fds; ++i) { + filed->f_addr_fds[i] = dup(f_addr_fds[i]); + if (filed->f_addr_fds[i] < 0) + err(1, "dup"); } } else if (filed->f_type == F_PIPE) { (void)strlcpy(filed->f_pname, nvlist_get_string(nvl_filed,