Page MenuHomeFreeBSD

sockstat: Use libcasper to capsicumize
ClosedPublic

Authored by freqlabs on Oct 26 2020, 1:28 PM.

Details

Summary

Drop rights we do not need. This has to be done after jail_attach.

Diff Detail

Repository
rG FreeBSD src repository
Lint
Automatic diff as part of commit; lint not applicable.
Unit
Automatic diff as part of commit; unit tests not applicable.

Event Timeline

oshogbo added inline comments.
usr.bin/sockstat/sockstat.c
1418

copy paste error.

1424

-1 ? Shouldn't be CAPNET_ADDR2NAME ?

freqlabs changed the repository for this revision from rS FreeBSD src repository - subversion to rG FreeBSD src repository.

Incorporated feedback.

@oshogbo when this looks good to you I can commit it along with cap_netdb in D24832.

Yes. This looks go to me.

This revision is now accepted and ready to land.Jun 1 2021, 1:49 PM
This revision was automatically updated to reflect the committed changes.

sockstat is broken since this commit, preventing to run the tcptestsuite regression that is using it:

Assertion failed: (chan != NULL), function cap_xfer_nvlist, file /usr/src/lib/libcasper/libcasper/libcasper.c, line 304.
Abort trap (core dumped)
/usr/local/share/tcptestsuite/state-event-engine/rcv-rst-syn-rcvd/rcv-rst-syn-rcvd-via-listen-left-edge-insecure-ipv4.pkt:55: error executing `sockstat -4 -P tcp -s -p 8080 | grep -c SYN_RCVD | grep 1` command: non-zero status 1

Hello Oliver,

Thank you for reporting.
I'm just rebuilding the world, because I don't have a machine with this change applied anymore.

In meantime can you show me a backtrace?

Thanks,
Mariusz

Tested to display trace with gdb:

% gdb --args /usr/bin/sockstat -P tcp -p 8080
(...)
Reading symbols from /usr/bin/sockstat...
Reading symbols from /usr/lib/debug//usr/bin/sockstat.debug...
(gdb) run
Starting program: /usr/bin/sockstat -P tcp -p 8080
Assertion failed: (chan != NULL), function cap_xfer_nvlist, file /usr/src/lib/libcasper/libcasper/libcasper.c, line 304.

Program received signal SIGABRT, Aborted.
thr_kill () at thr_kill.S:4
4       RSYSCALL(thr_kill)

or with lldb:

% lldb -- /usr/bin/sockstat -P tcp -p 8080
(lldb) target create "/usr/bin/sockstat"
Current executable set to '/usr/bin/sockstat' (x86_64).
(lldb) settings set -- target.run-args  "-P" "tcp" "-p" "8080"
(lldb) run
Process 46042 launched: '/usr/bin/sockstat' (x86_64)
Assertion failed: (chan != NULL), function cap_xfer_nvlist, file /usr/src/lib/libcasper/libcasper/libcasper.c, line 304.
Program aborted due to an unhandled Error:
Error value was Success. (Note: Success values must still be checked prior to being destroyed).
PLEASE submit a bug report to https://bugs.freebsd.org/submit/ and include the crash backtrace.
#0 0x0000000003329a01 PrintStackTrace /usr/src/contrib/llvm-project/llvm/lib/Support/Unix/Signals.inc:565:13
#1 0x0000000003327eb5 RunSignalHandlers /usr/src/contrib/llvm-project/llvm/lib/Support/Signals.cpp:72:18
#2 0x0000000003329fc0 SignalHandler /usr/src/contrib/llvm-project/llvm/lib/Support/Unix/Signals.inc:0:3
#3 0x0000000803f29dc0 handle_signal /usr/src/lib/libthr/thread/thr_sig.c:0:3
Abort (core dumped)

Hello Oliver,

Thank you for the insides.
Can you verify if this patch fix the issue for you?

diff --git a/usr.bin/sockstat/Makefile b/usr.bin/sockstat/Makefile
index 6d0de7dc22d0..bf1cd0b9a443 100644
--- a/usr.bin/sockstat/Makefile
+++ b/usr.bin/sockstat/Makefile
@@ -10,6 +10,7 @@ LIBADD=               jail
 LIBADD+=       casper
 LIBADD+=       cap_net
 LIBADD+=       cap_netdb
+LIBADD+=       cap_pwd
 LIBADD+=       cap_sysctl
 CFLAGS+=       -DWITH_CASPER
 .endif
diff --git a/usr.bin/sockstat/sockstat.c b/usr.bin/sockstat/sockstat.c
index 7dc5e4904deb..5318a43f8585 100644
--- a/usr.bin/sockstat/sockstat.c
+++ b/usr.bin/sockstat/sockstat.c
@@ -71,6 +71,7 @@ __FBSDID("$FreeBSD$");
 #include <libcasper.h>
 #include <casper/cap_net.h>
 #include <casper/cap_netdb.h>
+#include <casper/cap_pwd.h>
 #include <casper/cap_sysctl.h>
 
 #define        sstosin(ss)     ((struct sockaddr_in *)(ss))
@@ -141,6 +142,7 @@ static int nxfiles;
 static cap_channel_t *capnet;
 static cap_channel_t *capnetdb;
 static cap_channel_t *capsysctl;
+static cap_channel_t *cappwd;
 
 static int
 xprintf(const char *fmt, ...)
@@ -163,7 +165,10 @@ get_proto_type(const char *proto)
 
        if (strlen(proto) == 0)
                return (0);
-       pent = cap_getprotobyname(capnetdb, proto);
+       if (capnetdb != NULL)
+               pent = cap_getprotobyname(capnetdb, proto);
+       else
+               pent = getprotobyname(proto);
        if (pent == NULL) {
                warn("cap_getprotobyname");
                return (-1);
@@ -1212,7 +1217,7 @@ display(void)
                        printf(" %-.*s", TCP_CA_NAME_MAX, "CC");
                printf("\n");
        }
-       setpassent(1);
+       cap_setpassent(cappwd, 1);
        for (xf = xfiles, n = 0; n < nxfiles; ++n, ++xf) {
                if (xf->xf_data == 0)
                        continue;
@@ -1226,7 +1231,8 @@ display(void)
                                continue;
                        s->shown = 1;
                        pos = 0;
-                       if (opt_n || (pwd = getpwuid(xf->xf_uid)) == NULL)
+                       if (opt_n ||
+                           (pwd = cap_getpwuid(cappwd, xf->xf_uid)) == NULL)
                                pos += xprintf("%lu ", (u_long)xf->xf_uid);
                        else
                                pos += xprintf("%s ", pwd->pw_name);
@@ -1323,6 +1329,8 @@ main(int argc, char *argv[])
 {
        cap_channel_t *capcas;
        cap_net_limit_t *limit;
+       const char *pwdcmds[] = { "setpassent", "getpwuid" };
+       const char *pwdfields[] = { "pw_name" };
        int protos_defined = -1;
        int o, i;
 
@@ -1421,12 +1429,19 @@ main(int argc, char *argv[])
        capsysctl = cap_service_open(capcas, "system.sysctl");
        if (capsysctl == NULL)
                err(1, "Unable to open system.sysctl service");
+       cappwd = cap_service_open(capcas, "system.pwd");
+       if (cappwd == NULL)
+               err(1, "Unable to open system.pwd service");
        cap_close(capcas);
        limit = cap_net_limit_init(capnet, CAPNET_ADDR2NAME);
        if (limit == NULL)
                err(1, "Unable to init cap_net limits");
        if (cap_net_limit(limit) < 0)
                err(1, "Unable to apply limits");
+       if (cap_pwd_limit_cmds(cappwd, pwdcmds, nitems(pwdcmds)) < 0)
+               err(1, "Unable to apply pwd commands limits");
+       if (cap_pwd_limit_fields(cappwd, pwdfields, nitems(pwdfields)) < 0)
+               err(1, "Unable to apply pwd commands limits");
 
        if ((!opt_4 && !opt_6) && protos_defined != -1)
                opt_4 = opt_6 = 1;

Thanks!
No more core dump once your patch applied.