git: 897240c7d666 - main - syslogd: Enter capability mode

From: Jake Freeland <jfree_at_FreeBSD.org>
Date: Wed, 27 Nov 2024 22:27:14 UTC
The branch main has been updated by jfree:

URL: https://cgit.FreeBSD.org/src/commit/?id=897240c7d666744137da6125feabf3c3a5522ada

commit 897240c7d666744137da6125feabf3c3a5522ada
Author:     Jake Freeland <jfree@FreeBSD.org>
AuthorDate: 2024-11-27 22:25:57 +0000
Commit:     Jake Freeland <jfree@FreeBSD.org>
CommitDate: 2024-11-27 22:25:57 +0000

    syslogd: Enter capability mode
    
    Create syslogd_cap_enter() function, which puts syslogd in capability
    mode and opens necessary libcasper channels for resource acquisition.
    The `syslogd.casper` and `system.net` services are used.
    
    Substitute capability-mode-unfriendly functions with their libcasper
    `cap_` equivalents.
    
    Reviewed by:    markj
    Differential Revision:  https://reviews.freebsd.org/D41467
---
 usr.sbin/syslogd/syslogd.c     | 67 ++++++++++++++++++++++++++++++++++++------
 usr.sbin/syslogd/syslogd_cap.h |  2 ++
 2 files changed, 60 insertions(+), 9 deletions(-)

diff --git a/usr.sbin/syslogd/syslogd.c b/usr.sbin/syslogd/syslogd.c
index 755552ecd21c..901a90ef3e35 100644
--- a/usr.sbin/syslogd/syslogd.c
+++ b/usr.sbin/syslogd/syslogd.c
@@ -271,6 +271,16 @@ static const int sigcatch[] = {
 	SIGCHLD,
 };
 
+/*
+ * Communication channels between syslogd and libcasper
+ * services. These channels are used to request external
+ * resources while in capability mode.
+ */
+#ifdef WITH_CASPER
+static cap_channel_t *cap_syslogd;
+static cap_channel_t *cap_net;
+#endif
+
 static int	nulldesc;	/* /dev/null descriptor */
 static bool	Debug;		/* debug flag */
 static bool	Foreground = false; /* Run in foreground, instead of daemonizing */
@@ -1826,7 +1836,8 @@ fprintlog_write(struct filed *f, struct iovlist *il, int flags)
 					break;
 				++i;
 			}
-			f->f_file = p_open(i, f->f_pname, &f->f_procdesc);
+			f->f_file = cap_p_open(cap_syslogd, i, f->f_pname,
+			    &f->f_procdesc);
 			if (f->f_file < 0) {
 				logerror(f->f_pname);
 				break;
@@ -1849,7 +1860,8 @@ fprintlog_write(struct filed *f, struct iovlist *il, int flags)
 		dprintf(" %s%s\n", _PATH_DEV, f->f_fname);
 		iovlist_append(il, "\r\n");
 		errno = 0;	/* ttymsg() only sometimes returns an errno */
-		if ((msgret = ttymsg(il->iov, il->iovcnt, f->f_fname, 10))) {
+		if ((msgret = cap_ttymsg(cap_syslogd, il->iov, il->iovcnt,
+		    f->f_fname, 10))) {
 			f->f_type = F_UNUSED;
 			logerror(msgret);
 		}
@@ -1859,7 +1871,7 @@ fprintlog_write(struct filed *f, struct iovlist *il, int flags)
 	case F_WALL:
 		dprintf("\n");
 		iovlist_append(il, "\r\n");
-		wallmsg(f, il->iov, il->iovcnt);
+		cap_wallmsg(cap_syslogd, f, il->iov, il->iovcnt);
 		break;
 	default:
 		break;
@@ -2142,7 +2154,7 @@ cvthname(struct sockaddr *f)
 	static char hname[NI_MAXHOST], ip[NI_MAXHOST];
 
 	dprintf("cvthname(%d) len = %d\n", f->sa_family, f->sa_len);
-	error = getnameinfo(f, f->sa_len, ip, sizeof(ip), NULL, 0,
+	error = cap_getnameinfo(cap_net, f, f->sa_len, ip, sizeof(ip), NULL, 0,
 		    NI_NUMERICHOST);
 	if (error) {
 		dprintf("Malformed from address %s\n", gai_strerror(error));
@@ -2153,7 +2165,7 @@ cvthname(struct sockaddr *f)
 	if (!resolve)
 		return (ip);
 
-	error = getnameinfo(f, f->sa_len, hname, sizeof(hname),
+	error = cap_getnameinfo(cap_net, f, f->sa_len, hname, sizeof(hname),
 		    NULL, 0, NI_NAMEREQD);
 	if (error) {
 		dprintf("Host name for your address (%s) unknown\n", ip);
@@ -2477,6 +2489,36 @@ closelogfiles(void)
 	}
 }
 
+static void
+syslogd_cap_enter(void)
+{
+#ifdef WITH_CASPER
+	cap_channel_t *cap_casper;
+	cap_net_limit_t *limit;
+
+	cap_casper = cap_init();
+	if (cap_casper == NULL)
+		err(1, "Failed to communicate with libcasper");
+	cap_syslogd = cap_service_open(cap_casper, "syslogd.casper");
+	if (cap_syslogd == NULL)
+		err(1, "Failed to open the syslogd.casper libcasper service");
+	cap_net = cap_service_open(cap_casper, "system.net");
+	if (cap_syslogd == NULL)
+		err(1, "Failed to open the system.net libcasper service");
+	cap_close(cap_casper);
+	limit = cap_net_limit_init(cap_net,
+	    CAPNET_ADDR2NAME | CAPNET_NAME2ADDR);
+	if (limit == NULL)
+		err(1, "Failed to create system.net limits");
+	if (cap_net_limit(limit) == -1)
+		err(1, "Failed to apply system.net limits");
+	caph_cache_tzdata();
+	caph_cache_catpages();
+	if (caph_enter_casper() == -1)
+		err(1, "Failed to enter capability mode");
+#endif
+}
+
 /*
  *  INIT -- Initialize syslogd from configuration table
  */
@@ -2532,9 +2574,16 @@ init(bool reload)
 	}
 #endif
 
+	if (!reload) {
+		struct tm tm;
+		/* Cache time files before entering capability mode. */
+		timegm(&tm);
+		syslogd_cap_enter();
+	}
+
 	Initialized = false;
 	closelogfiles();
-	fill_flist(readconfigfile(ConfFile));
+	fill_flist(cap_readconfigfile(cap_syslogd, ConfFile));
 	Initialized = true;
 
 	if (Debug) {
@@ -3364,14 +3413,14 @@ validate(struct sockaddr *sa, const char *hname)
 		.ai_socktype = SOCK_DGRAM,
 		.ai_flags = AI_PASSIVE | AI_NUMERICHOST
 	};
-	if (getaddrinfo(name, NULL, &hints, &res) == 0)
+	if (cap_getaddrinfo(cap_net, name, NULL, &hints, &res) == 0)
 		freeaddrinfo(res);
 	else if (strchr(name, '.') == NULL) {
 		strlcat(name, ".", sizeof(name));
 		strlcat(name, LocalDomain, sizeof(name));
 	}
-	if (getnameinfo(sa, sa->sa_len, ip, sizeof(ip), port, sizeof(port),
-			NI_NUMERICHOST | NI_NUMERICSERV) != 0)
+	if (cap_getnameinfo(cap_net, sa, sa->sa_len, ip, sizeof(ip), port,
+	    sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV) != 0)
 		return (false);	/* for safety, should not occur */
 	dprintf("validate: dgram from IP %s, port %s, name %s;\n",
 		ip, port, name);
diff --git a/usr.sbin/syslogd/syslogd_cap.h b/usr.sbin/syslogd/syslogd_cap.h
index 420676aa72f2..2e52c57bcdf8 100644
--- a/usr.sbin/syslogd/syslogd_cap.h
+++ b/usr.sbin/syslogd/syslogd_cap.h
@@ -45,6 +45,8 @@
 #include <capsicum_helpers.h>
 #include <libcasper_service.h>
 
+#include <casper/cap_net.h>
+
 #include "syslogd.h"
 
 /*