[PATCH] Implement decoding of setsockopt(TCP_AO_ADD_KEY)

наб nabijaczleweli at nabijaczleweli.xyz
Sun Mar 10 01:21:50 UTC 2024


Samples as run via tcp-ao-wrapper:
  setsockopt(3, SOL_TCP, TCP_AO_ADD_KEY, {addr={sa_family=AF_INET6, sin6_port=htons(0), sin6_flowinfo=htonl(0), inet_pton(AF_INET6, "::", &sin6_addr), sin6_scope_id=0}, prefix=0, alg_name="hmac(sha1)", ifindex=0, set_current=0, set_rnext=0, sndid=200, rcvid=100, maclen=12, keyflags=0, key="\x42\xe9\xd2\xd3\xd1\xec\x9f\x55\x56\x9c\xd7\x89\x1a\x90\x53\xba\x59\x6d\x5f\x0a"}, 288) = 0
  setsockopt(3, SOL_TCP, TCP_AO_ADD_KEY, {addr={sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("127.0.0.1")}, prefix=32, alg_name="cmac(aes)", ifindex=0, set_current=0, set_rnext=0, sndid=200, rcvid=100, maclen=12, keyflags=0, key="\x7a\x66\x25\xc9\x80\xdb\x68\x95\xf5\xaf\x84\x1b\xd6\x50\x29\xe1"}, 288) = -1 ENOPROTOOPT (Protocol not available)
---
This folds key/keylen into key="{hexdump of length keylen}";
should keylen be included explicitly?

set_current and set_rnext are bitfield bools,
hence explicit PRINTF (you can't sizeof(bitfield));
this feels kinda stinky as well.

 NEWS                          |   1 +
 src/net.c                     |  57 ++++++++++++++++++-
 src/xlat/tcp_ao_keyf_flags.in |   3 +
 tests/.gitignore              |   1 +
 tests/gen_tests.in            |   1 +
 tests/pure_executables.list   |   1 +
 tests/tcp_ao.c                | 101 ++++++++++++++++++++++++++++++++++
 7 files changed, 162 insertions(+), 3 deletions(-)
 create mode 100644 src/xlat/tcp_ao_keyf_flags.in
 create mode 100644 tests/tcp_ao.c

diff --git a/NEWS b/NEWS
index 8613cbc..d05e68d 100644
--- a/NEWS
+++ b/NEWS
@@ -10,6 +10,7 @@ Noteworthy changes in release ?.? (????-??-??)
   * Updated lists of BPF_*, KEXEC_*, KVM_*, PERF_*, SOL_*, STATX_*, UFFD_*,
     and V4L2_* constants.
   * Updated lists of ioctl commands from Linux 6.8.
+  * Implemented decoding of setsockopt(TCP_AO_ADD_KEY).
 
 Noteworthy changes in release 6.7 (2024-01-29)
 ==============================================
diff --git a/src/net.c b/src/net.c
index e8878c4..a9925af 100644
--- a/src/net.c
+++ b/src/net.c
@@ -16,9 +16,6 @@
 #include <sys/uio.h>
 #include <sys/un.h>
 #include <netinet/in.h>
-#ifdef HAVE_NETINET_TCP_H
-# include <netinet/tcp.h>
-#endif
 #ifdef HAVE_NETINET_UDP_H
 # include <netinet/udp.h>
 #endif
@@ -45,6 +42,7 @@
 #endif
 #include <linux/if_packet.h>
 #include <linux/icmp.h>
+#include <linux/tcp.h>
 #include <linux/vm_sockets.h>
 
 #include "xlat/socktypes.h"
@@ -879,6 +877,51 @@ print_icmp_filter(struct tcb *const tcp, const kernel_ulong_t addr, int len)
 	tprint_bitset_end();
 }
 
+#include "xlat/tcp_ao_keyf_flags.h"
+
+static void
+print_tcp_ao_add_key(struct tcb *const tcp, const kernel_ulong_t addr, int len)
+{
+	struct tcp_ao_add key = {};
+
+	if (len > (int) sizeof(key))
+		len = sizeof(key);
+	else if (len <= 0) {
+		printaddr(addr);
+		return;
+	}
+
+	if (umoven_or_printaddr(tcp, addr, len, &key))
+		return;
+
+	tprint_struct_begin();
+	PRINT_FIELD_SOCKADDR(key, addr, tcp);
+	tprint_struct_next();
+	PRINT_FIELD_U(key, prefix);
+	tprint_struct_next();
+	PRINT_FIELD_CSTRING(key, alg_name);
+	tprint_struct_next();
+	PRINT_FIELD_IFINDEX(key, ifindex);
+	tprint_struct_next();
+	tprints_field_name("set_current");
+	STRACE_PRINTF("%u", (unsigned) key.set_current);
+	tprint_struct_next();
+	tprints_field_name("set_rnext");
+	STRACE_PRINTF("%u", (unsigned) key.set_rnext);
+	tprint_struct_next();
+	PRINT_FIELD_U(key, sndid);
+	tprint_struct_next();
+	PRINT_FIELD_U(key, rcvid);
+	tprint_struct_next();
+	PRINT_FIELD_U(key, maclen);
+	tprint_struct_next();
+	PRINT_FIELD_FLAGS(key, keyflags, tcp_ao_keyf_flags, "TCP_AO_KEYF_???");
+	tprint_struct_next();
+	PRINT_FIELD_HEX_ARRAY_UPTO(key, key,
+		key.keylen > sizeof(key.key) ? sizeof(key.key) : key.keylen);
+	tprint_struct_end();
+}
+
 static void
 print_getsockopt(struct tcb *const tcp, const unsigned int level,
 		 const unsigned int name, const kernel_ulong_t addr,
@@ -1332,6 +1375,14 @@ print_setsockopt(struct tcb *const tcp, const unsigned int level,
 		else
 			printnum_int(tcp, addr, "%d");
 		return;
+
+	case SOL_TCP:
+		switch (name) {
+		case TCP_AO_ADD_KEY:
+			print_tcp_ao_add_key(tcp, addr, len);
+			return;
+		}
+		break;
 	}
 
 	/* default arg printing */
diff --git a/src/xlat/tcp_ao_keyf_flags.in b/src/xlat/tcp_ao_keyf_flags.in
new file mode 100644
index 0000000..caf6e2d
--- /dev/null
+++ b/src/xlat/tcp_ao_keyf_flags.in
@@ -0,0 +1,3 @@
+#unconditional
+TCP_AO_KEYF_IFINDEX
+TCP_AO_KEYF_EXCLUDE_OPT
diff --git a/tests/.gitignore b/tests/.gitignore
index 493714b..1aa7880 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -1109,6 +1109,7 @@ sysinfo
 syslog
 syslog-success
 tampering-notes
+tcp_ao
 tee
 tgkill
 tgkill--pidns-translation
diff --git a/tests/gen_tests.in b/tests/gen_tests.in
index 3499785..cdd25ec 100644
--- a/tests/gen_tests.in
+++ b/tests/gen_tests.in
@@ -1107,6 +1107,7 @@ sync_file_range2
 sysctl	-a16 --trace=_sysctl
 sysinfo	-a14
 syslog	-a35
+tcp_ao	-e trace=getsockopt,setsockopt
 tee
 tgkill	-a15 --signal='!cont'
 tgkill--pidns-translation       test_pidns -a15 --signal='!cont' -e trace=tgkill
diff --git a/tests/pure_executables.list b/tests/pure_executables.list
index b4af3cf..84cd766 100755
--- a/tests/pure_executables.list
+++ b/tests/pure_executables.list
@@ -794,6 +794,7 @@ sysctl
 sysinfo
 syslog
 tampering-notes
+tcp_ao
 tee
 tgkill
 time
diff --git a/tests/tcp_ao.c b/tests/tcp_ao.c
new file mode 100644
index 0000000..b23c3cf
--- /dev/null
+++ b/tests/tcp_ao.c
@@ -0,0 +1,101 @@
+/*
+ * Check decoding of SO_LINGER socket option.
+ *
+ * Copyright (c) 2017-2021 Dmitry V. Levin <ldv at strace.io>
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "tests.h"
+
+#include <linux/tcp.h>
+#include <netinet/in.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+static const char *errstr;
+
+static int
+add_key(int fd, struct tcp_ao_add *val)
+{
+	int rc = setsockopt(fd, IPPROTO_TCP, TCP_AO_ADD_KEY, val, sizeof(*val));
+	errstr = sprintrc(rc);
+	return rc;
+}
+
+int
+main(void)
+{
+	TAIL_ALLOC_OBJECT_CONST_PTR(struct tcp_ao_add, key);
+
+	int fd = socket(AF_INET, SOCK_STREAM, 0);
+	if (fd < 0)
+		perror_msg_and_skip("socket AF_TCP SOCK_STREAM");
+
+
+#define KEY1 "\x42\xe9\xd2\xd3\xd1\xec\x9f\x55\x56\x9c\xd7\x89\x1a\x90\x53\xba\x59\x6d\x5f\x0a"
+	*key = (struct tcp_ao_add){
+		.prefix = 0,
+		.alg_name = "hmac(sha1)",
+		.ifindex = 0,
+		.set_current = 0,
+		.set_rnext = 0,
+		.sndid = 200,
+		.rcvid = 100,
+		.maclen = 12,
+		.keyflags = 0,
+		.key = KEY1,
+		.keylen = sizeof(KEY1) - 1,
+	};
+	struct sockaddr_in6 addr6 =
+		{.sin6_family = AF_INET6, .sin6_addr = IN6ADDR_ANY_INIT};
+	memcpy(&key->addr, &addr6, sizeof(addr6));
+	add_key(fd, key);
+	printf("setsockopt(%d, SOL_TCP, TCP_AO_ADD_KEY, "
+	       "{addr={sa_family=AF_INET6, sin6_port=htons(0), "
+	       "sin6_flowinfo=htonl(0), inet_pton(AF_INET6, \"::\", "
+	       "&sin6_addr), sin6_scope_id=0}, prefix=0, "
+	       "alg_name=\"hmac(sha1)\", ifindex=0, set_current=0, "
+	       "set_rnext=0, sndid=200, rcvid=100, maclen=12, keyflags=0, "
+	       "key="
+	       "\"\\x42\\xe9\\xd2\\xd3\\xd1\\xec\\x9f\\x55\\x56\\x9c\\xd7\\x89"
+	       "\\x1a\\x90\\x53\\xba\\x59\\x6d\\x5f\\x0a\"}"
+	       ", %zu) = %s\n",
+	       fd, sizeof(*key), errstr);
+
+#define KEY2 "\x7a\x66\x25\xc9\x80\xdb\x68\x95\xf5\xaf\x84\x1b\xd6\x50\x29\xe1"
+	*key = (struct tcp_ao_add){
+		.prefix = 32,
+		.alg_name = "cmac(aes)",
+		.ifindex = 0,
+		.set_current = 0,
+		.set_rnext = 0,
+		.sndid = 200,
+		.rcvid = 100,
+		.maclen = 12,
+		.keyflags = TCP_AO_KEYF_IFINDEX|TCP_AO_KEYF_EXCLUDE_OPT,
+		.key = KEY2,
+		.keylen = sizeof(KEY2) - 1,
+	};
+	struct sockaddr_in addr =
+		{.sin_family = AF_INET, .sin_addr = {htonl(INADDR_LOOPBACK)}};
+	memcpy(&key->addr, &addr, sizeof(addr));
+	add_key(fd, key);
+	printf("setsockopt(%d, SOL_TCP, TCP_AO_ADD_KEY, "
+	       "{addr={sa_family=AF_INET, sin_port=htons(0), "
+	       "sin_addr=inet_addr(\"127.0.0.1\")}, prefix=32, "
+	       "alg_name=\"cmac(aes)\", ifindex=0, set_current=0, set_rnext=0, "
+	       "sndid=200, rcvid=100, maclen=12, "
+	       "keyflags=TCP_AO_KEYF_IFINDEX|TCP_AO_KEYF_EXCLUDE_OPT, key="
+	       "\"\\x7a\\x66\\x25\\xc9\\x80\\xdb\\x68\\x95\\xf5\\xaf\\x84\\x1b"
+	       "\\xd6\\x50\\x29\\xe1\"}"
+	       ", %zu) = %s\n",
+	       fd, sizeof(*key), errstr);
+
+	puts("+++ exited with 0 +++");
+	return 0;
+}
-- 
2.39.2
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.strace.io/pipermail/strace-devel/attachments/20240310/18efdcc0/attachment.bin>


More information about the Strace-devel mailing list