From nobody Sun Nov 02 15:18:06 2025 X-Original-To: dev-commits-src-all@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 4czyyk3qWRz6Fw4k; Sun, 02 Nov 2025 15:18:06 +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 "R12" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4czyyk35mFz3vv7; Sun, 02 Nov 2025 15:18:06 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1762096686; 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=+4Xth/oqvUq2KDjhvNdaCD0vyP+BN6XTS/7HiqxojNo=; b=MONnTZhkB/ZxGFFM38rMjzfZNwimvO7KZvZ2x/LL7cxi8VP4MuwEUv82JHzlMtwEnnNaDM Tu+IuzndwP1kPn9XARv3Rz+hGRsjMyjfQSyh2xgfvrbCVP0gw7qXtWk7WrJ4S4YOmxp3Zd J4ATBLb7zeGpnvLDB23kb8Ws6PbdH+VMoU0YxYORDYnkIB1on7AmsSu2u3UZl5EqrxFnDB FFUcmxfQN3MZE4nthmGuArxiKSRVPiotsmUhKXLXQBTEXOaRMkl3nLn9H1B9DBo1+RWrUf FK6tn//WLWUEUePVasHwLs+R1IhDa8kIdBQruAoY/4bkbv4D6urpWny/wTe06w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1762096686; 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=+4Xth/oqvUq2KDjhvNdaCD0vyP+BN6XTS/7HiqxojNo=; b=KEf3gOyT40PcvuHReYuWUjAH0/xKNU3CHtksblH02yLdMksvfyG9fQEkDn4hRthpu9IG3Z IwW+R/dvyvn7TQ4QlQAghlE9hUr9ftBsSLu4qzrZw6EmqPJemhncXMIQxaz2oeg6ABpXxk i5WbdFht9FcppjotPw8cFPdNVuBUIUdUL99RwRbaXIEXj5BiT9J6orOgQXwi5PQM7J/Wkr jmEJdR+BlmSSd0SHYVQAc3xnIzW+foeYFf5H8vvWMbBX4MWLA+kMilpzoLfqcawR7h2N7P VBx1KZKQKoNBhb3JaAOC85txQgJ2M+IAXgVfNAHL9NVHXSInMKJCBjirgqcANg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1762096686; a=rsa-sha256; cv=none; b=GIIWLm8AafY7TjLMLxqxO1B/ihf6LHrBqG8rshDpxEs1VsY/ogrQZSbQawStTYotv5gR17 H8EMbHLMuOr1kbt5tOCj/qg1ED8vfqe1IYw39v8sY2dZHyQODUoWssfA8JyYSJE3WGVWIh o79YpOh1UZ2rVjh7ruXoE/F19sRBW5DwkcBR1XJSj4Sgq3LXeD2DiULYqAIy9sCDwdO4qI 2dDlapDz74dnCCWh4WJCJOSd3HyKYgy2Qqp91AqqR/Nrom9VcXezlKKfi5JcMqfSQZ2Z/M PyAxXPmDjUv6NxQ94k8T44FUnth/KJQiAyrRWglgu6p3Z6oTIh25oZKRZgRwxQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none 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 4czyyk2Nz7zWn4; Sun, 02 Nov 2025 15:18:06 +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 5A2FI6Ps056753; Sun, 2 Nov 2025 15:18:06 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 5A2FI6dG056750; Sun, 2 Nov 2025 15:18:06 GMT (envelope-from git) Date: Sun, 2 Nov 2025 15:18:06 GMT Message-Id: <202511021518.5A2FI6dG056750@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Juraj Lutter Subject: git: 2deeed061b14 - main - sockstat(1): Add "-F" parameter List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: otis X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 2deeed061b1473a4230211c6562a533b76ce846c Auto-Submitted: auto-generated The branch main has been updated by otis: URL: https://cgit.FreeBSD.org/src/commit/?id=2deeed061b1473a4230211c6562a533b76ce846c commit 2deeed061b1473a4230211c6562a533b76ce846c Author: Juraj Lutter AuthorDate: 2025-10-29 20:48:21 +0000 Commit: Juraj Lutter CommitDate: 2025-11-02 15:17:47 +0000 sockstat(1): Add "-F" parameter Add "-F" parameter that, when specified, instructs sockstat(1) to only display sockets for username/UID specified. For consistency with "-j", the last occurence of "-F" is used. Reviewed by: asomers Approved by: asomers Differential Revision: https://reviews.freebsd.org/D53458 --- usr.bin/sockstat/main.c | 170 +++++++++++++++++++++++++++++++++----------- usr.bin/sockstat/sockstat.1 | 7 +- 2 files changed, 136 insertions(+), 41 deletions(-) diff --git a/usr.bin/sockstat/main.c b/usr.bin/sockstat/main.c index 07663e54534d..1f174d827e1a 100644 --- a/usr.bin/sockstat/main.c +++ b/usr.bin/sockstat/main.c @@ -88,6 +88,7 @@ static bool opt_A; /* Show kernel address of pcb */ static bool opt_b; /* Show BBLog state */ static bool opt_C; /* Show congestion control */ static bool opt_c; /* Show connected sockets */ +static bool opt_F; /* Show sockets for selected user only */ static bool opt_f; /* Show FIB numbers */ static bool opt_I; /* Show spliced socket addresses */ static bool opt_i; /* Show inp_gencnt */ @@ -115,6 +116,12 @@ static size_t default_numprotos = nitems(default_protos); static int *protos; /* protocols to use */ static size_t numprotos; /* allocated size of protos[] */ +/* + * Show sockets for user username or UID specified + */ +static char *filter_user_optarg = NULL; /* saved optarg for username/UID resolving */ +static uid_t filter_user_uid; /* UID to show sockets for */ + struct addr { union { struct sockaddr_storage address; @@ -217,6 +224,18 @@ _enforce_ksize(size_t received_size, size_t expected_size, const char *struct_na } #define enforce_ksize(_sz, _struct) (_enforce_ksize(_sz, sizeof(_struct), #_struct)) +static inline bool +filtered_uid(uid_t i_uid) +{ + return ((i_uid) == filter_user_uid); +} + +static inline bool +need_nosocks(void) +{ + return !(opt_F || (opt_j >= 0)); +} + static int get_proto_type(const char *proto) { @@ -758,7 +777,8 @@ gather_inet(int proto) if (sock->socket != 0) RB_INSERT(socks_t, &socks, sock); else - SLIST_INSERT_HEAD(&nosocks, sock, socket_list); + if (need_nosocks()) + SLIST_INSERT_HEAD(&nosocks, sock, socket_list); } out: free(buf); @@ -862,6 +882,8 @@ getfiles(void) struct xfile *xfiles; size_t len, olen; + int filenum = 0; + olen = len = sizeof(*xfiles); if ((xfiles = malloc(len)) == NULL) xo_err(1, "malloc()"); @@ -880,14 +902,23 @@ getfiles(void) if ((files = malloc(nfiles * sizeof(struct file))) == NULL) xo_err(1, "malloc()"); + /* Fill files structure, optionally for specified user */ for (int i = 0; i < nfiles; i++) { - files[i].xf_data = xfiles[i].xf_data; - files[i].xf_pid = xfiles[i].xf_pid; - files[i].xf_uid = xfiles[i].xf_uid; - files[i].xf_fd = xfiles[i].xf_fd; - RB_INSERT(files_t, &ftree, &files[i]); + if (opt_F && !filtered_uid(xfiles[i].xf_uid)) + continue; + files[filenum].xf_data = xfiles[i].xf_data; + files[filenum].xf_pid = xfiles[i].xf_pid; + files[filenum].xf_uid = xfiles[i].xf_uid; + files[filenum].xf_fd = xfiles[i].xf_fd; + RB_INSERT(files_t, &ftree, &files[filenum]); + filenum++; } + /* Adjust global nfiles to match the number of files we + * actually filled into files[] array + */ + nfiles = filenum; + free(xfiles); } @@ -1584,6 +1615,24 @@ display_sock(struct sock *s, struct col_widths *cw, char *buf, size_t bufsize) static void display(void) { + static const char *__HDR_USER="USER", + *__HDR_COMMAND="COMMAND", + *__HDR_PID="PID", + *__HDR_FD="FD", + *__HDR_PROTO="PROTO", + *__HDR_LOCAL_ADDRESS="LOCAL ADDRESS", + *__HDR_FOREIGN_ADDRESS="FOREIGN ADDRESS", + *__HDR_PCB_KVA="PCB KVA", + *__HDR_FIB="FIB", + *__HDR_SPLICE_ADDRESS="SPLICE ADDRESS", + *__HDR_ID="ID", + *__HDR_ENCAPS="ENCAPS", + *__HDR_PATH_STATE="PATH STATE", + *__HDR_CONN_STATE="CONN STATE", + *__HDR_BBLOG_STATE="BBLOG STATE", + *__HDR_STACK="STACK", + *__HDR_CC="CC"; + struct passwd *pwd; struct file *xf; struct sock *s; @@ -1598,23 +1647,23 @@ display(void) if (!is_xo_style_encoding) { cw = (struct col_widths) { - .user = strlen("USER"), + .user = strlen(__HDR_USER), .command = 10, - .pid = strlen("PID"), - .fd = strlen("FD"), - .proto = strlen("PROTO"), - .local_addr = opt_w ? strlen("LOCAL ADDRESS") : 21, - .foreign_addr = opt_w ? strlen("FOREIGN ADDRESS") : 21, + .pid = strlen(__HDR_PID), + .fd = strlen(__HDR_FD), + .proto = strlen(__HDR_PROTO), + .local_addr = opt_w ? strlen(__HDR_LOCAL_ADDRESS) : 21, + .foreign_addr = opt_w ? strlen(__HDR_FOREIGN_ADDRESS) : 21, .pcb_kva = 18, - .fib = strlen("FIB"), - .splice_address = strlen("SPLICE ADDRESS"), - .inp_gencnt = strlen("ID"), - .encaps = strlen("ENCAPS"), - .path_state = strlen("PATH STATE"), - .conn_state = strlen("CONN STATE"), - .bblog_state = strlen("BBLOG STATE"), - .stack = strlen("STACK"), - .cc = strlen("CC"), + .fib = strlen(__HDR_FIB), + .splice_address = strlen(__HDR_SPLICE_ADDRESS), + .inp_gencnt = strlen(__HDR_ID), + .encaps = strlen(__HDR_ENCAPS), + .path_state = strlen(__HDR_PATH_STATE), + .conn_state = strlen(__HDR_CONN_STATE), + .bblog_state = strlen(__HDR_BBLOG_STATE), + .stack = strlen(__HDR_STACK), + .cc = strlen(__HDR_CC), }; calculate_column_widths(&cw); } else @@ -1625,34 +1674,34 @@ display(void) xo_open_list("socket"); if (!opt_q) { xo_emit("{T:/%-*s} {T:/%-*s} {T:/%*s} {T:/%*s} {T:/%-*s} " - "{T:/%-*s} {T:/%-*s}", cw.user, "USER", cw.command, - "COMMAND", cw.pid, "PID", cw.fd, "FD", cw.proto, - "PROTO", cw.local_addr, "LOCAL ADDRESS", - cw.foreign_addr, "FOREIGN ADDRESS"); + "{T:/%-*s} {T:/%-*s}", cw.user, __HDR_USER, cw.command, + __HDR_COMMAND, cw.pid, __HDR_PID, cw.fd, __HDR_FD, cw.proto, + __HDR_PROTO, cw.local_addr, __HDR_LOCAL_ADDRESS, + cw.foreign_addr, __HDR_FOREIGN_ADDRESS); if (opt_A) - xo_emit(" {T:/%-*s}", cw.pcb_kva, "PCB KVA"); + xo_emit(" {T:/%-*s}", cw.pcb_kva, __HDR_PCB_KVA); if (opt_f) /* RT_MAXFIBS is 65535. */ - xo_emit(" {T:/%*s}", cw.fib, "FIB"); + xo_emit(" {T:/%*s}", cw.fib, __HDR_FIB); if (opt_I) xo_emit(" {T:/%-*s}", cw.splice_address, - "SPLICE ADDRESS"); + __HDR_SPLICE_ADDRESS); if (opt_i) - xo_emit(" {T:/%*s}", cw.inp_gencnt, "ID"); + xo_emit(" {T:/%*s}", cw.inp_gencnt, __HDR_ID); if (opt_U) - xo_emit(" {T:/%*s}", cw.encaps, "ENCAPS"); + xo_emit(" {T:/%*s}", cw.encaps, __HDR_ENCAPS); if (opt_s) { if (show_path_state) xo_emit(" {T:/%-*s}", cw.path_state, - "PATH STATE"); - xo_emit(" {T:/%-*s}", cw.conn_state, "CONN STATE"); + __HDR_PATH_STATE); + xo_emit(" {T:/%-*s}", cw.conn_state, __HDR_CONN_STATE); } if (opt_b) - xo_emit(" {T:/%-*s}", cw.bblog_state, "BBLOG STATE"); + xo_emit(" {T:/%-*s}", cw.bblog_state, __HDR_BBLOG_STATE); if (opt_S) - xo_emit(" {T:/%-*s}", cw.stack, "STACK"); + xo_emit(" {T:/%-*s}", cw.stack, __HDR_STACK); if (opt_C) - xo_emit(" {T:/%-*s}", cw.cc, "CC"); + xo_emit(" {T:/%-*s}", cw.cc, __HDR_CC); xo_emit("\n"); } cap_setpassent(cappwd, 1); @@ -1684,7 +1733,7 @@ display(void) xo_close_instance("socket"); } } - if (opt_j >= 0) + if (!need_nosocks()) goto out; SLIST_FOREACH(s, &nosocks, socket_list) { if (!check_ports(s)) @@ -1775,11 +1824,44 @@ jail_getvnet(int jid) return (vnet); } +/* + * Parse username and/or UID + */ +static bool +parse_filter_user(void) +{ + struct passwd *pwd; + char *ep; + uid_t uid; + bool rv = false; + + uid = (uid_t)strtol(filter_user_optarg, &ep, 10); + + /* Open and/or rewind capsicumized password file */ + cap_setpassent(cappwd, 1); + + if (*ep == '\0') { + /* We have an UID specified, check if it's valid */ + if ((pwd = cap_getpwuid(cappwd, uid)) == NULL) + goto out; + filter_user_uid = uid; + } else { + /* Check if we have a valid username */ + if ((pwd = cap_getpwnam(cappwd, filter_user_optarg)) == NULL) + goto out; + filter_user_uid = pwd->pw_uid; + } + + rv = true; +out: + return (rv); +} + static void usage(void) { xo_error( -"usage: sockstat [--libxo ...] [-46AbCcfIiLlnqSsUuvw] [-j jid] [-p ports]\n" +"usage: sockstat [--libxo ...] [-46AbCcfIiLlnqSsUuvw] [-F uid/username] [-j jid] [-p ports]\n" " [-P protocols]\n"); exit(1); } @@ -1789,8 +1871,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" }; + const char *pwdcmds[] = { "setpassent", "getpwuid", "getpwnam" }; + const char *pwdfields[] = { "pw_name", "pw_uid" }; int protos_defined = -1; int o, i, err; @@ -1803,7 +1885,7 @@ main(int argc, char *argv[]) is_xo_style_encoding = true; } opt_j = -1; - while ((o = getopt(argc, argv, "46AbCcfIij:Llnp:P:qSsUuvw")) != -1) + while ((o = getopt(argc, argv, "46AbCcF:fIij:Llnp:P:qSsUuvw")) != -1) switch (o) { case '4': opt_4 = true; @@ -1823,6 +1905,11 @@ main(int argc, char *argv[]) case 'c': opt_c = true; break; + case 'F': + /* Save optarg for later use when we enter capabilities mode */ + filter_user_optarg = optarg; + opt_F = true; + break; case 'f': opt_f = true; break; @@ -1934,6 +2021,9 @@ main(int argc, char *argv[]) if (cap_pwd_limit_fields(cappwd, pwdfields, nitems(pwdfields)) < 0) xo_err(1, "Unable to apply pwd commands limits"); + if (opt_F && !parse_filter_user()) + xo_errx(1, "Invalid username or UID specified"); + if ((!opt_4 && !opt_6) && protos_defined != -1) opt_4 = opt_6 = true; if (!opt_4 && !opt_6 && !opt_u) diff --git a/usr.bin/sockstat/sockstat.1 b/usr.bin/sockstat/sockstat.1 index 1498fb1d88f7..b0fae81ee566 100644 --- a/usr.bin/sockstat/sockstat.1 +++ b/usr.bin/sockstat/sockstat.1 @@ -25,7 +25,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd October 14, 2025 +.Dd October 29, 2025 .Dt SOCKSTAT 1 .Os .Sh NAME @@ -35,6 +35,7 @@ .Nm .Op Fl -libxo .Op Fl 46AbCcfIiLlnqSsUuvw +.Op Fl F Ar user .Op Fl j Ar jail .Op Fl p Ar ports .Op Fl P Ar protocols @@ -73,6 +74,10 @@ Display the congestion control module, if applicable. This is currently only implemented for TCP. .It Fl c Show connected sockets. +.It Fl F Ar user +Show sockets for specified +.Ar user +(user name or UID) only. .It Fl f Show the FIB number of each socket. .It Fl I