From 2c29d44acf9b84d0d24f78d03fe313d3938181c6 Mon Sep 17 00:00:00 2001 From: Eugene Syromyatnikov Date: Fri, 28 Apr 2023 21:07:12 +0200 Subject: net: implement IP_LOCAL_PORT_RANGE socket option decoding Introduced by Linux kernel commit v6.3-rc1~162^2~206^2~1. * src/net.c (+print_port_range): New function. (print_getsockopt) : Call it. (print_setsockopt) : Ditto. * tests/.gitignore: Add ip_local_port_range, ip_local_port_range-Xabbrev, ip_local_port_range-Xraw, ip_local_port_range-Xverbose, ip_local_port_range-success, ip_local_port_range-success-Xabbrev, ip_local_port_range-success-Xraw, and ip_local_port_range-success-Xverbose. * tests/Makefile.am (check_PROGRAMS): Add ip_local_port_range-success, ip_local_port_range-success-Xabbrev, ip_local_port_range-success-Xraw, and ip_local_port_range-success-Xverbose. * tests/gen_tests.in (ip_local_port_range, ip_local_port_range-Xabbrev, ip_local_port_range-Xraw, ip_local_port_range-Xverbose, ip_local_port_range-success, ip_local_port_range-success-Xabbrev, ip_local_port_range-success-Xraw, ip_local_port_range-success-Xverbose): New tests. * tests/pure_executables.list: Add ip_local_port_range, ip_local_port_range-Xabbrev, ip_local_port_range-Xraw, and ip_local_port_range-Xverbose. * tests/ip_local_port_range.c: New file. * tests/ip_local_port_range-Xabbrev.c: Likewise. * tests/ip_local_port_range-Xraw.c: Likewise. * tests/ip_local_port_range-Xverbose.c: Likewise. * tests/ip_local_port_range-success-Xabbrev.c: Likewise. * tests/ip_local_port_range-success-Xraw.c: Likewise. * tests/ip_local_port_range-success-Xverbose.c: Likewise. * tests/ip_local_port_range-success.c: Likewise. * NEWS: Mention it. --- NEWS | 3 +- src/net.c | 38 ++++++ tests/.gitignore | 8 ++ tests/Makefile.am | 4 + tests/gen_tests.in | 8 ++ tests/ip_local_port_range-Xabbrev.c | 2 + tests/ip_local_port_range-Xraw.c | 2 + tests/ip_local_port_range-Xverbose.c | 2 + tests/ip_local_port_range-success-Xabbrev.c | 2 + tests/ip_local_port_range-success-Xraw.c | 2 + tests/ip_local_port_range-success-Xverbose.c | 2 + tests/ip_local_port_range-success.c | 2 + tests/ip_local_port_range.c | 185 +++++++++++++++++++++++++++ tests/pure_executables.list | 4 + 14 files changed, 263 insertions(+), 1 deletion(-) create mode 100644 tests/ip_local_port_range-Xabbrev.c create mode 100644 tests/ip_local_port_range-Xraw.c create mode 100644 tests/ip_local_port_range-Xverbose.c create mode 100644 tests/ip_local_port_range-success-Xabbrev.c create mode 100644 tests/ip_local_port_range-success-Xraw.c create mode 100644 tests/ip_local_port_range-success-Xverbose.c create mode 100644 tests/ip_local_port_range-success.c create mode 100644 tests/ip_local_port_range.c diff --git a/NEWS b/NEWS index 964b868e6..c7798adf0 100644 --- a/NEWS +++ b/NEWS @@ -8,10 +8,11 @@ Noteworthy changes in release ?.? (????-??-??) after capturing the specified number of syscalls. * Implemented decoding of PR_GET_MDWE and PR_SET_MDWE operations of prctl syscall. + * Implemented decoding of IP_LOCAL_PORT_RANGE socket option. * Implemented decoding of IFLA_BRPORT_MCAST_N_GROUPS, IFLA_BRPORT_MCAST_MAX_GROUPS, IFLA_GSO_IPV4_MAX_SIZE, IFLA_GRO_IPV4_MAX_SIZE, and TCA_EXT_WARN_MSG netlink attributes. - * Updated lists of F_SEAL_*, IFLA_*, IORING_*, IP_*, MFD_*, NFT_*, TCA_*, + * Updated lists of F_SEAL_*, IFLA_*, IORING_*, MFD_*, NFT_*, TCA_*, and V4L2_PIX_FMT_* constants. * Updated lists of ioctl commands from Linux 6.3. diff --git a/src/net.c b/src/net.c index 01f1c34f8..4c84928b8 100644 --- a/src/net.c +++ b/src/net.c @@ -733,6 +733,33 @@ print_txrehash(struct tcb *const tcp, const kernel_ulong_t addr, const int len) tprint_indirect_end(); } +static void +print_port_range(struct tcb *const tcp, const kernel_ulong_t addr, + const unsigned int len) +{ + unsigned int ports; + + if (len != sizeof(ports)) { + printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX); + return; + } + + if (umove_or_printaddr(tcp, addr, &ports)) + return; + + tprint_indirect_begin(); + PRINT_VAL_X(ports); + if (xlat_verbose(xlat_verbosity) != XLAT_STYLE_RAW) { + unsigned short lo = ports & 0xffff; + unsigned short hi = ports >> 16; + + if (ports && (!lo || !hi || lo <= hi)) + tprintf_comment("%.0hu..%.0hu", lo, hi); + } + tprint_indirect_end(); +} + + static void print_tpacket_stats(struct tcb *const tcp, const kernel_ulong_t addr, unsigned int len) @@ -910,6 +937,14 @@ print_getsockopt(struct tcb *const tcp, const unsigned int level, } break; + case SOL_IP: + switch (name) { + case IP_LOCAL_PORT_RANGE: + print_port_range(tcp, addr, rlen); + return; + } + break; + case SOL_PACKET: switch (name) { case PACKET_STATISTICS: @@ -1189,6 +1224,9 @@ print_setsockopt(struct tcb *const tcp, const unsigned int level, case MCAST_LEAVE_GROUP: print_group_req(tcp, addr, len); return; + case IP_LOCAL_PORT_RANGE: + print_port_range(tcp, addr, len); + return; } break; diff --git a/tests/.gitignore b/tests/.gitignore index a39408627..4c753e324 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -417,6 +417,14 @@ ioprio--pidns-translation ioprio-Xabbrev ioprio-Xraw ioprio-Xverbose +ip_local_port_range +ip_local_port_range-Xabbrev +ip_local_port_range-Xraw +ip_local_port_range-Xverbose +ip_local_port_range-success +ip_local_port_range-success-Xabbrev +ip_local_port_range-success-Xraw +ip_local_port_range-success-Xverbose ip_mreq ipc ipc_msg diff --git a/tests/Makefile.am b/tests/Makefile.am index 170876eed..f25c2a506 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -242,6 +242,10 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ ioctl_v4l2-success-v-Xraw \ ioctl_v4l2-success-v-Xverbose \ ioprio--pidns-translation \ + ip_local_port_range-success \ + ip_local_port_range-success-Xabbrev \ + ip_local_port_range-success-Xraw \ + ip_local_port_range-success-Xverbose \ is_linux_mips_n64 \ kcmp-y--pidns-translation \ kill--pidns-translation \ diff --git a/tests/gen_tests.in b/tests/gen_tests.in index db70ee1b4..1316ad6e8 100644 --- a/tests/gen_tests.in +++ b/tests/gen_tests.in @@ -435,6 +435,14 @@ ioprio--pidns-translation test_pidns -a18 -e trace=ioprio_get,ioprio_set ioprio-Xabbrev -a18 -e trace=ioprio_get,ioprio_set -Xabbrev ioprio-Xraw -a18 -e trace=ioprio_get,ioprio_set -Xraw ioprio-Xverbose -a18 -e trace=ioprio_get,ioprio_set -Xverbose +ip_local_port_range -e trace=getsockopt,setsockopt -a50 +ip_local_port_range-Xabbrev -e trace=getsockopt,setsockopt -Xabbrev -a50 +ip_local_port_range-Xraw -e trace=getsockopt,setsockopt -Xraw -a30 +ip_local_port_range-Xverbose -e trace=getsockopt,setsockopt -Xverbose -a69 +ip_local_port_range-success -einject=getsockopt,setsockopt:retval=42 -etrace=getsockopt,setsockopt -a50 +ip_local_port_range-success-Xabbrev -einject=getsockopt,setsockopt:retval=42 -etrace=getsockopt,setsockopt -Xabbrev -a50 +ip_local_port_range-success-Xraw -einject=getsockopt,setsockopt:retval=42 -etrace=getsockopt,setsockopt -Xraw -a30 +ip_local_port_range-success-Xverbose -einject=getsockopt,setsockopt:retval=42 -etrace=getsockopt,setsockopt -Xverbose -a69 ip_mreq -e trace=setsockopt ipc -a19 ipc_msg +ipc.sh -a26 diff --git a/tests/ip_local_port_range-Xabbrev.c b/tests/ip_local_port_range-Xabbrev.c new file mode 100644 index 000000000..c6e9fa1e6 --- /dev/null +++ b/tests/ip_local_port_range-Xabbrev.c @@ -0,0 +1,2 @@ +#define XLAT_ABBREV 1 +#include "ip_local_port_range.c" diff --git a/tests/ip_local_port_range-Xraw.c b/tests/ip_local_port_range-Xraw.c new file mode 100644 index 000000000..73faec1c8 --- /dev/null +++ b/tests/ip_local_port_range-Xraw.c @@ -0,0 +1,2 @@ +#define XLAT_RAW 1 +#include "ip_local_port_range.c" diff --git a/tests/ip_local_port_range-Xverbose.c b/tests/ip_local_port_range-Xverbose.c new file mode 100644 index 000000000..1487b5608 --- /dev/null +++ b/tests/ip_local_port_range-Xverbose.c @@ -0,0 +1,2 @@ +#define XLAT_VERBOSE 1 +#include "ip_local_port_range.c" diff --git a/tests/ip_local_port_range-success-Xabbrev.c b/tests/ip_local_port_range-success-Xabbrev.c new file mode 100644 index 000000000..da0e11849 --- /dev/null +++ b/tests/ip_local_port_range-success-Xabbrev.c @@ -0,0 +1,2 @@ +#define XLAT_ABBREV 1 +#include "ip_local_port_range-success.c" diff --git a/tests/ip_local_port_range-success-Xraw.c b/tests/ip_local_port_range-success-Xraw.c new file mode 100644 index 000000000..8c5be6f02 --- /dev/null +++ b/tests/ip_local_port_range-success-Xraw.c @@ -0,0 +1,2 @@ +#define XLAT_RAW 1 +#include "ip_local_port_range-success.c" diff --git a/tests/ip_local_port_range-success-Xverbose.c b/tests/ip_local_port_range-success-Xverbose.c new file mode 100644 index 000000000..e5e2d2412 --- /dev/null +++ b/tests/ip_local_port_range-success-Xverbose.c @@ -0,0 +1,2 @@ +#define XLAT_VERBOSE 1 +#include "ip_local_port_range-success.c" diff --git a/tests/ip_local_port_range-success.c b/tests/ip_local_port_range-success.c new file mode 100644 index 000000000..9e4c28ab2 --- /dev/null +++ b/tests/ip_local_port_range-success.c @@ -0,0 +1,2 @@ +#define INJSTR " (INJECTED)" +#include "ip_local_port_range.c" diff --git a/tests/ip_local_port_range.c b/tests/ip_local_port_range.c new file mode 100644 index 000000000..e4449d455 --- /dev/null +++ b/tests/ip_local_port_range.c @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2023 Eugene Syromyatnikov + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "tests.h" + +#include +#include +#include +#include +#include +#include + +#ifndef IP_LOCAL_PORT_RANGE +# define IP_LOCAL_PORT_RANGE 51 +#endif + +#ifndef INJSTR +# define INJSTR "" +#endif + +int +main(void) +{ + static const struct strval32 opts[] = { + { 0, NULL }, + { 1, "1.." }, + { 12345, "12345.." }, + { 0xbeef, "48879.." }, + { 0x10000, "..1" }, + { 12345 << 16, "..12345" }, + { 0x12341234U, "4660..4660" }, + { 0x87654321U, "17185..34661" }, + { 0xbadc0dedU, "3565..47836" }, + { 0xbeef0000U, "..48879" }, + { 0xbeef0001U, "1..48879" }, + { 0xbeefbeefU, "48879..48879" }, + { 0xbeeffaceU, NULL }, + }; + + TAIL_ALLOC_OBJECT_CONST_PTR(unsigned int, ports); + TAIL_ALLOC_OBJECT_CONST_ARR(unsigned int, big_ports, 2); + const char *errstr; + socklen_t len; + int rc; + + for (unsigned int i = 0; i < ARRAY_SIZE(opts); ++i) { + *ports = opts[i].val; + + /* optlen < 0, EINVAL */ + len = -1; + rc = setsockopt(0, SOL_IP, IP_LOCAL_PORT_RANGE, ports, len); + printf("setsockopt(0, " XLAT_FMT ", " XLAT_FMT ", %p, -1) = %s" + INJSTR "\n", + XLAT_ARGS(SOL_IP), XLAT_ARGS(IP_LOCAL_PORT_RANGE), + ports, sprintrc(rc)); + + rc = getsockopt(0, SOL_IP, IP_LOCAL_PORT_RANGE, ports, &len); + printf("getsockopt(0, " XLAT_FMT ", " XLAT_FMT ", %p, [-1]) = %s" + INJSTR "\n", + XLAT_ARGS(SOL_IP), XLAT_ARGS(IP_LOCAL_PORT_RANGE), + ports, sprintrc(rc)); + + + /* optlen = 0, EINVAL */ + len = 0; + rc = setsockopt(0, SOL_IP, IP_LOCAL_PORT_RANGE, ports, len); + printf("setsockopt(0, " XLAT_FMT ", " XLAT_FMT ", \"\", 0) = %s" + INJSTR "\n", + XLAT_ARGS(SOL_IP), XLAT_ARGS(IP_LOCAL_PORT_RANGE), + sprintrc(rc)); + + rc = getsockopt(0, SOL_IP, IP_LOCAL_PORT_RANGE, ports, &len); + printf("getsockopt(0, " XLAT_FMT ", " XLAT_FMT ", %p, [0]) = %s" + INJSTR "\n", + XLAT_ARGS(SOL_IP), XLAT_ARGS(IP_LOCAL_PORT_RANGE), + ports, sprintrc(rc)); + + + /* optlen < sizeof(int), EINVAL */ + len = sizeof(*ports) - 1; + rc = setsockopt(0, SOL_IP, IP_LOCAL_PORT_RANGE, ports, len); + errstr = sprintrc(rc); + printf("setsockopt(0, " XLAT_FMT ", " XLAT_FMT ", ", + XLAT_ARGS(SOL_IP), XLAT_ARGS(IP_LOCAL_PORT_RANGE)); + print_quoted_hex(ports, len); + printf(", 3) = %s" INJSTR "\n", errstr); + + rc = getsockopt(0, SOL_IP, IP_LOCAL_PORT_RANGE, ports, &len); + errstr = sprintrc(rc); + printf("getsockopt(0, " XLAT_FMT ", " XLAT_FMT ", ", + XLAT_ARGS(SOL_IP), XLAT_ARGS(IP_LOCAL_PORT_RANGE)); + if (INJSTR[0]) + print_quoted_hex(ports, len); + else + printf("%p", ports); + printf(", [3]) = %s" INJSTR "\n", errstr); + + + /* optval EFAULT */ + len = sizeof(*ports); + rc = setsockopt(0, SOL_IP, IP_LOCAL_PORT_RANGE, ports + 1, len); + printf("setsockopt(0, " XLAT_FMT ", " XLAT_FMT ", %p, 4) = %s" + INJSTR "\n", + XLAT_ARGS(SOL_IP), XLAT_ARGS(IP_LOCAL_PORT_RANGE), + ports + 1, sprintrc(rc)); + + rc = getsockopt(0, SOL_IP, IP_LOCAL_PORT_RANGE, ports + 1, &len); + printf("getsockopt(0, " XLAT_FMT ", " XLAT_FMT ", %p, [4]) = %s" + INJSTR "\n", + XLAT_ARGS(SOL_IP), XLAT_ARGS(IP_LOCAL_PORT_RANGE), + ports + 1, sprintrc(rc)); + + + /* classic */ + len = sizeof(*ports); + rc = setsockopt(0, SOL_IP, IP_LOCAL_PORT_RANGE, ports, len); + printf("setsockopt(0, " XLAT_FMT ", " XLAT_FMT ", [%#x%s%s%s]" + ", 4) = %s" INJSTR "\n", + XLAT_ARGS(SOL_IP), XLAT_ARGS(IP_LOCAL_PORT_RANGE), + *ports, + !XLAT_RAW && opts[i].str ? " /* " : "", + !XLAT_RAW && opts[i].str ? opts[i].str : "", + !XLAT_RAW && opts[i].str ? " */" : "", + sprintrc(rc)); + + rc = getsockopt(0, SOL_IP, IP_LOCAL_PORT_RANGE, ports, &len); + errstr = sprintrc(rc); + printf("getsockopt(0, " XLAT_FMT ", " XLAT_FMT ", ", + XLAT_ARGS(SOL_IP), XLAT_ARGS(IP_LOCAL_PORT_RANGE)); + if (INJSTR[0]) { + printf("[%#x%s%s%s]", + *ports, + !XLAT_RAW && opts[i].str ? " /* " : "", + !XLAT_RAW && opts[i].str ? opts[i].str : "", + !XLAT_RAW && opts[i].str ? " */" : ""); + } else { + printf("%p", ports); + } + printf(", [4]) = %s" INJSTR "\n", errstr); + + + /* optval > sizeof(int), EFAULT */ + len = sizeof(*ports) + 1; + rc = setsockopt(0, SOL_IP, IP_LOCAL_PORT_RANGE, ports, len); + printf("setsockopt(0, " XLAT_FMT ", " XLAT_FMT ", %p, 5) = %s" + INJSTR "\n", + XLAT_ARGS(SOL_IP), XLAT_ARGS(IP_LOCAL_PORT_RANGE), + ports, sprintrc(rc)); + + rc = getsockopt(0, SOL_IP, IP_LOCAL_PORT_RANGE, ports, &len); + printf("getsockopt(0, " XLAT_FMT ", " XLAT_FMT ", %p, [5]) = %s" + INJSTR "\n", + XLAT_ARGS(SOL_IP), XLAT_ARGS(IP_LOCAL_PORT_RANGE), + ports, sprintrc(rc)); + + + /* optlen > sizeof(int), EINVAL */ + len = sizeof(*ports) * 2; + big_ports[0] = opts[i].val; + big_ports[1] = opts[i].val; + rc = setsockopt(0, SOL_IP, IP_LOCAL_PORT_RANGE, big_ports, len); + errstr = sprintrc(rc); + printf("setsockopt(0, " XLAT_FMT ", " XLAT_FMT ", ", + XLAT_ARGS(SOL_IP), XLAT_ARGS(IP_LOCAL_PORT_RANGE)); + print_quoted_hex(big_ports, len); + printf(", 8) = %s" INJSTR "\n", errstr); + + rc = getsockopt(0, SOL_IP, IP_LOCAL_PORT_RANGE, big_ports, &len); + errstr = sprintrc(rc); + printf("getsockopt(0, " XLAT_FMT ", " XLAT_FMT ", ", + XLAT_ARGS(SOL_IP), XLAT_ARGS(IP_LOCAL_PORT_RANGE)); + if (INJSTR[0]) + print_quoted_hex(big_ports, len); + else + printf("%p", big_ports); + printf(", [8]) = %s" INJSTR "\n", errstr); + } + + puts("+++ exited with 0 +++"); + return 0; +} diff --git a/tests/pure_executables.list b/tests/pure_executables.list index 331c4e1c7..a1315f64e 100755 --- a/tests/pure_executables.list +++ b/tests/pure_executables.list @@ -270,6 +270,10 @@ ioprio ioprio-Xabbrev ioprio-Xraw ioprio-Xverbose +ip_local_port_range +ip_local_port_range-Xabbrev +ip_local_port_range-Xraw +ip_local_port_range-Xverbose ip_mreq ipc ipc_msg -- cgit v1.2.1