The branch main has been updated by emaste:

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

commit b73612a34259a478c53eab408362d7bf879fefa6
Author:     Jose Luis Duran <[email protected]>
AuthorDate: 2022-10-12 16:14:44 +0000
Commit:     Ed Maste <[email protected]>
CommitDate: 2023-11-02 18:52:40 +0000

    blacklistd: Handle fds that are pointing to routing sockets
    
    If the fd has access to make changes via the routing socket, grant full
    permission to make filter changes.
    
    Obtained from:  
https://github.com/zoulasc/blocklist/commit/1b9475b2c8e0be2b9adc4d88e521ed488ac3c43c
---
 contrib/blacklist/bin/conf.c | 113 ++++++++++++++++++++++++++++++++++++-------
 1 file changed, 95 insertions(+), 18 deletions(-)

diff --git a/contrib/blacklist/bin/conf.c b/contrib/blacklist/bin/conf.c
index 6eadf6b2ac8c..8f7e75a56be1 100644
--- a/contrib/blacklist/bin/conf.c
+++ b/contrib/blacklist/bin/conf.c
@@ -46,6 +46,7 @@ __RCSID("$NetBSD: conf.c,v 1.24 2016/04/04 15:52:56 christos 
Exp $");
 #include <ctype.h>
 #include <inttypes.h>
 #include <netdb.h>
+#include <unistd.h>
 #include <pwd.h>
 #include <syslog.h>
 #include <errno.h>
@@ -55,6 +56,7 @@ __RCSID("$NetBSD: conf.c,v 1.24 2016/04/04 15:52:56 christos 
Exp $");
 #include <arpa/inet.h>
 #include <netinet/in.h>
 #include <net/if.h>
+#include <net/route.h>
 #include <sys/socket.h>
 
 #include "bl.h"
@@ -1000,32 +1002,72 @@ confset_match(const struct confset *cs, struct conf *c,
        return i;
 }
 
-const struct conf *
-conf_find(int fd, uid_t uid, const struct sockaddr_storage *rss,
-    struct conf *cr)
+#ifdef AF_ROUTE
+static int
+conf_route_perm(int fd) {
+#if defined(RTM_IFANNOUNCE) && defined(SA_SIZE)
+       /*
+        * Send a routing message that is not supported to check for access
+        * We expect EOPNOTSUPP for having access, since we are sending a
+        * request the system does not understand and EACCES if we don't have
+        * access.
+        */
+       static struct sockaddr_in sin = {
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+               .sin_len = sizeof(sin),
+#endif
+               .sin_family = AF_INET,
+       };
+       char buf[4096];
+       struct rt_msghdr *rtm = (void *)buf;
+       char *cp = (char *)(rtm + 1);
+       size_t l;
+
+#define NEXTADDR(s) \
+       l = SA_SIZE(sizeof(*s)); memmove(cp, s, l); cp += l;
+       memset(buf, 0, sizeof(buf));
+       rtm->rtm_type = RTM_IFANNOUNCE;
+       rtm->rtm_flags = 0;
+       rtm->rtm_addrs = RTA_DST|RTA_GATEWAY;
+       rtm->rtm_version = RTM_VERSION;
+       rtm->rtm_seq = 666;
+       NEXTADDR(&sin);
+       NEXTADDR(&sin);
+       rtm->rtm_msglen = (u_short)((char *)cp - (char *)rtm);
+       if (write(fd, rtm, rtm->rtm_msglen) != -1) {
+               (*lfun)(LOG_ERR, "Writing to routing socket succeeded!");
+               return 0;
+       }
+       switch (errno) {
+       case EACCES:
+               return 0;
+       case EOPNOTSUPP:
+               return 1;
+       default:
+               (*lfun)(LOG_ERR,
+                   "Unexpected error writing to routing socket (%m)");
+               return 0;
+       }
+#else
+       return 0;
+#endif
+}
+#endif
+
+static int
+conf_handle_inet(int fd, const void *lss, struct conf *cr)
 {
-       int proto;
-       socklen_t slen;
-       struct sockaddr_storage lss;
-       size_t i;
        char buf[BUFSIZ];
+       int proto;
+       socklen_t slen = sizeof(proto);
 
-       memset(cr, 0, sizeof(*cr));
-       slen = sizeof(lss);
-       memset(&lss, 0, slen);
-       if (getsockname(fd, (void *)&lss, &slen) == -1) {
-               (*lfun)(LOG_ERR, "getsockname failed (%m)");
-               return NULL;
-       }
-
-       slen = sizeof(proto);
        if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &proto, &slen) == -1) {
                (*lfun)(LOG_ERR, "getsockopt failed (%m)");
-               return NULL;
+               return -1;
        }
 
        if (debug) {
-               sockaddr_snprintf(buf, sizeof(buf), "%a:%p", (void *)&lss);
+               sockaddr_snprintf(buf, sizeof(buf), "%a:%p", lss);
                (*lfun)(LOG_DEBUG, "listening socket: %s", buf);
        }
 
@@ -1038,16 +1080,51 @@ conf_find(int fd, uid_t uid, const struct 
sockaddr_storage *rss,
                break;
        default:
                (*lfun)(LOG_ERR, "unsupported protocol %d", proto);
+               return -1;
+       }
+       return 0;
+}
+
+const struct conf *
+conf_find(int fd, uid_t uid, const struct sockaddr_storage *rss,
+    struct conf *cr)
+{
+       socklen_t slen;
+       struct sockaddr_storage lss;
+       size_t i;
+       char buf[BUFSIZ];
+
+       memset(cr, 0, sizeof(*cr));
+       slen = sizeof(lss);
+       memset(&lss, 0, slen);
+       if (getsockname(fd, (void *)&lss, &slen) == -1) {
+               (*lfun)(LOG_ERR, "getsockname failed (%m)");
                return NULL;
        }
 
        switch (lss.ss_family) {
        case AF_INET:
                cr->c_port = ntohs(((struct sockaddr_in *)&lss)->sin_port);
+               if (conf_handle_inet(fd, &lss, cr) == -1)
+                       return NULL;
                break;
        case AF_INET6:
                cr->c_port = ntohs(((struct sockaddr_in6 *)&lss)->sin6_port);
+               if (conf_handle_inet(fd, &lss, cr) == -1)
+                       return NULL;
                break;
+#ifdef AF_ROUTE
+       case AF_ROUTE:
+               if (!conf_route_perm(fd)) {
+                       (*lfun)(LOG_ERR,
+                           "permission denied to routing socket (%m)");
+                       return NULL;
+               }
+               cr->c_proto = FSTAR;
+               cr->c_port = FSTAR;
+               memcpy(&lss, rss, sizeof(lss));
+               break;
+#endif
        default:
                (*lfun)(LOG_ERR, "unsupported family %d", lss.ss_family);
                return NULL;

Reply via email to