From 3bbfb541b258baec9eba674b5d8dc30007a61542 Mon Sep 17 00:00:00 2001
From: "Dmitry V. Levin" <ldv@strace.io>
Date: Wed, 21 Jun 2023 08:00:00 +0000
Subject: [PATCH] net: enhance getsockopt decoding

When getsockopt syscall fails the kernel sometimes updates the optlen
argument, for example, NETLINK_LIST_MEMBERSHIPS updates it even if
optval is not writable.

* src/net.c (SYS_FUNC(getsockopt)): Try to fetch and print optlen
argument on exiting syscall regardless of getsockopt exit status.

Upstream-Status: Backport
---
 src/net.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/src/net.c b/src/net.c
index f68ccb947..7244b5e57 100644
--- a/src/net.c
+++ b/src/net.c
@@ -1038,7 +1038,7 @@ SYS_FUNC(getsockopt)
 	} else {
 		ulen = get_tcb_priv_ulong(tcp);
 
-		if (syserror(tcp) || umove(tcp, tcp->u_arg[4], &rlen) < 0) {
+		if (umove(tcp, tcp->u_arg[4], &rlen) < 0) {
 			/* optval */
 			printaddr(tcp->u_arg[3]);
 			tprint_arg_next();
@@ -1047,6 +1047,19 @@ SYS_FUNC(getsockopt)
 			tprint_indirect_begin();
 			PRINT_VAL_D(ulen);
 			tprint_indirect_end();
+		} else if (syserror(tcp)) {
+			/* optval */
+			printaddr(tcp->u_arg[3]);
+			tprint_arg_next();
+
+			/* optlen */
+			tprint_indirect_begin();
+			if (ulen != rlen) {
+				PRINT_VAL_D(ulen);
+				tprint_value_changed();
+			}
+			PRINT_VAL_D(rlen);
+			tprint_indirect_end();
 		} else {
 			/* optval */
 			print_getsockopt(tcp, tcp->u_arg[1], tcp->u_arg[2],
