Netdev List
 help / color / mirror / Atom feed
* [PATCH net-next v2 0/7] net: convert rawv6, ieee802154, phonet and tls getsockopt to sockopt_t
@ 2026-07-20 16:17 Breno Leitao
  2026-07-20 16:17 ` [PATCH net-next v2 1/7] ipv6: raw: drop unused level argument from do_rawv6_getsockopt Breno Leitao
                   ` (7 more replies)
  0 siblings, 8 replies; 13+ messages in thread
From: Breno Leitao @ 2026-07-20 16:17 UTC (permalink / raw)
  To: sdf, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Alexander Aring, Stefan Schmidt, Miquel Raynal,
	Remi Denis-Courmont, Rémi Denis-Courmont, John Fastabend,
	Sabrina Dubroca, Shuah Khan
  Cc: netdev, linux-kernel, linux-wpan, linux-kselftest, Breno Leitao,
	kernel-team, Rémi Denis-Courmont

Now that sockopt_init_user() was already merged, builds a user-backed
sockopt_t from the __user pair. A getsockopt leaf can then take
a sockopt_t behind a thin __user wrapper: the wrapper builds it, calls
the leaf, and writes the length back to optlen. The leaf copies with
copy_to_iter() instead of copy_to_user().

Convert four more leaves the way udp and raw already were: ipv6 raw
(do_rawv6_getsockopt), ieee802154 dgram, phonet pep, and tls
(do_tls_getsockopt and its per-option helpers). 

Converting phonet surfaced a pre-existing bug: pep_getsockopt() clamps the
length it reports but writes a full int with put_user(), overrunning an
optval buffer shorter than sizeof(int). It is fixed in its own patch, with
a Fixes: tag, before the phonet conversion, so it can be backported alone.

The last patch adds getsockopt_iter selftest fixtures for rawv6,
ieee802154, phonet and tls, checking the returned length and errno across
exact, oversized and short buffers, an unknown optname and a bad level.

For full motivation about these changes, please check the initial thread
at link
https://lore.kernel.org/all/20260401-getsockopt-v2-0-611df6771aff@debian.org/#t

Signed-off-by: Breno Leitao <leitao@debian.org>
---
Changes in v2:
- Replace min_t() by umin() (David)
- Link to v1: https://patch.msgid.link/20260716-getsockopt_phase4-v1-0-4f45cb12dce7@debian.org

---
Breno Leitao (7):
      ipv6: raw: drop unused level argument from do_rawv6_getsockopt
      ipv6: raw: convert do_rawv6_getsockopt to sockopt_t
      ieee802154: convert dgram getsockopt to sockopt_t
      phonet: pep: do not write beyond optlen in getsockopt
      phonet: pep: convert getsockopt to sockopt_t
      tls: convert getsockopt to sockopt_t
      selftests: net: getsockopt_iter: cover rawv6, ieee802154, phonet and tls

 net/ieee802154/socket.c                       |  38 ++-
 net/ipv6/raw.c                                |  27 +-
 net/phonet/pep.c                              |  36 ++-
 net/tls/tls_main.c                            |  80 +++--
 tools/testing/selftests/net/getsockopt_iter.c | 424 ++++++++++++++++++++++++++
 5 files changed, 533 insertions(+), 72 deletions(-)
---
base-commit: f6f3b36c15ed44de1fbb44e645e4fae8c4a4453e
change-id: 20260715-getsockopt_phase4-180209cfc60a

Best regards,
--  
Breno Leitao <leitao@debian.org>


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH net-next v2 1/7] ipv6: raw: drop unused level argument from do_rawv6_getsockopt
  2026-07-20 16:17 [PATCH net-next v2 0/7] net: convert rawv6, ieee802154, phonet and tls getsockopt to sockopt_t Breno Leitao
@ 2026-07-20 16:17 ` Breno Leitao
  2026-07-20 16:17 ` [PATCH net-next v2 2/7] ipv6: raw: convert do_rawv6_getsockopt to sockopt_t Breno Leitao
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 13+ messages in thread
From: Breno Leitao @ 2026-07-20 16:17 UTC (permalink / raw)
  To: sdf, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Alexander Aring, Stefan Schmidt, Miquel Raynal,
	Remi Denis-Courmont, Rémi Denis-Courmont, John Fastabend,
	Sabrina Dubroca, Shuah Khan
  Cc: netdev, linux-kernel, linux-wpan, linux-kselftest, Breno Leitao,
	kernel-team

do_rawv6_getsockopt() takes a level argument but never uses it; the
level dispatch is handled by the caller, rawv6_getsockopt(). Drop it,
matching ipv4's do_raw_getsockopt().

No functional change.

Signed-off-by: Breno Leitao <leitao@debian.org>
---
 net/ipv6/raw.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 3cc58698cbbd3..99eec36796fb9 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -1051,8 +1051,8 @@ static int rawv6_setsockopt(struct sock *sk, int level, int optname,
 	return do_rawv6_setsockopt(sk, level, optname, optval, optlen);
 }
 
-static int do_rawv6_getsockopt(struct sock *sk, int level, int optname,
-			    char __user *optval, int __user *optlen)
+static int do_rawv6_getsockopt(struct sock *sk, int optname,
+			       char __user *optval, int __user *optlen)
 {
 	struct raw6_sock *rp = raw6_sk(sk);
 	int val, len;
@@ -1109,7 +1109,7 @@ static int rawv6_getsockopt(struct sock *sk, int level, int optname,
 		return ipv6_getsockopt(sk, level, optname, optval, optlen);
 	}
 
-	return do_rawv6_getsockopt(sk, level, optname, optval, optlen);
+	return do_rawv6_getsockopt(sk, optname, optval, optlen);
 }
 
 static int rawv6_ioctl(struct sock *sk, int cmd, int *karg)

-- 
2.53.0-Meta


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH net-next v2 2/7] ipv6: raw: convert do_rawv6_getsockopt to sockopt_t
  2026-07-20 16:17 [PATCH net-next v2 0/7] net: convert rawv6, ieee802154, phonet and tls getsockopt to sockopt_t Breno Leitao
  2026-07-20 16:17 ` [PATCH net-next v2 1/7] ipv6: raw: drop unused level argument from do_rawv6_getsockopt Breno Leitao
@ 2026-07-20 16:17 ` Breno Leitao
  2026-07-20 16:17 ` [PATCH net-next v2 3/7] ieee802154: convert dgram getsockopt " Breno Leitao
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 13+ messages in thread
From: Breno Leitao @ 2026-07-20 16:17 UTC (permalink / raw)
  To: sdf, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Alexander Aring, Stefan Schmidt, Miquel Raynal,
	Remi Denis-Courmont, Rémi Denis-Courmont, John Fastabend,
	Sabrina Dubroca, Shuah Khan
  Cc: netdev, linux-kernel, linux-wpan, linux-kselftest, Breno Leitao,
	kernel-team

Convert do_rawv6_getsockopt to the new sockopt_t model, mirroring what
we have in ipv4. The overall goal is to move these callbacks gradually
from __user points to use sockopt_t, and this part touches
do_rawv6_getsockopt.

No functional change.

Signed-off-by: Breno Leitao <leitao@debian.org>
---
 net/ipv6/raw.c | 27 +++++++++++++++++++--------
 1 file changed, 19 insertions(+), 8 deletions(-)

diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 99eec36796fb9..1f15942d14163 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -1051,14 +1051,12 @@ static int rawv6_setsockopt(struct sock *sk, int level, int optname,
 	return do_rawv6_setsockopt(sk, level, optname, optval, optlen);
 }
 
-static int do_rawv6_getsockopt(struct sock *sk, int optname,
-			       char __user *optval, int __user *optlen)
+static int do_rawv6_getsockopt(struct sock *sk, int optname, sockopt_t *opt)
 {
 	struct raw6_sock *rp = raw6_sk(sk);
 	int val, len;
 
-	if (get_user(len, optlen))
-		return -EFAULT;
+	len = opt->optlen;
 
 	switch (optname) {
 	case IPV6_HDRINCL:
@@ -1082,9 +1080,8 @@ static int do_rawv6_getsockopt(struct sock *sk, int optname,
 
 	len = min_t(unsigned int, sizeof(int), len);
 
-	if (put_user(len, optlen))
-		return -EFAULT;
-	if (copy_to_user(optval, &val, len))
+	opt->optlen = len;
+	if (copy_to_iter(&val, len, &opt->iter_out) != len)
 		return -EFAULT;
 	return 0;
 }
@@ -1092,6 +1089,9 @@ static int do_rawv6_getsockopt(struct sock *sk, int optname,
 static int rawv6_getsockopt(struct sock *sk, int level, int optname,
 			  char __user *optval, int __user *optlen)
 {
+	sockopt_t opt;
+	int err;
+
 	switch (level) {
 	case SOL_RAW:
 		break;
@@ -1109,7 +1109,18 @@ static int rawv6_getsockopt(struct sock *sk, int level, int optname,
 		return ipv6_getsockopt(sk, level, optname, optval, optlen);
 	}
 
-	return do_rawv6_getsockopt(sk, optname, optval, optlen);
+	err = sockopt_init_user(&opt, optval, optlen);
+	if (err)
+		return err;
+
+	err = do_rawv6_getsockopt(sk, optname, &opt);
+	if (err)
+		return err;
+
+	if (put_user(opt.optlen, optlen))
+		return -EFAULT;
+
+	return 0;
 }
 
 static int rawv6_ioctl(struct sock *sk, int cmd, int *karg)

-- 
2.53.0-Meta


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH net-next v2 3/7] ieee802154: convert dgram getsockopt to sockopt_t
  2026-07-20 16:17 [PATCH net-next v2 0/7] net: convert rawv6, ieee802154, phonet and tls getsockopt to sockopt_t Breno Leitao
  2026-07-20 16:17 ` [PATCH net-next v2 1/7] ipv6: raw: drop unused level argument from do_rawv6_getsockopt Breno Leitao
  2026-07-20 16:17 ` [PATCH net-next v2 2/7] ipv6: raw: convert do_rawv6_getsockopt to sockopt_t Breno Leitao
@ 2026-07-20 16:17 ` Breno Leitao
  2026-07-22 13:40   ` Joe Damato
  2026-07-20 16:17 ` [PATCH net-next v2 4/7] phonet: pep: do not write beyond optlen in getsockopt Breno Leitao
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 13+ messages in thread
From: Breno Leitao @ 2026-07-20 16:17 UTC (permalink / raw)
  To: sdf, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Alexander Aring, Stefan Schmidt, Miquel Raynal,
	Remi Denis-Courmont, Rémi Denis-Courmont, John Fastabend,
	Sabrina Dubroca, Shuah Khan
  Cc: netdev, linux-kernel, linux-wpan, linux-kselftest, Breno Leitao,
	kernel-team

Continue converting the proto-layer getsockopt callbacks to the sockopt_t
interface, splitting dgram_getsockopt() into a do_dgram_getsockopt() helper
that takes a sockopt_t.

No functional change.

Signed-off-by: Breno Leitao <leitao@debian.org>
---
 net/ieee802154/socket.c | 38 ++++++++++++++++++++++++++------------
 1 file changed, 26 insertions(+), 12 deletions(-)

diff --git a/net/ieee802154/socket.c b/net/ieee802154/socket.c
index 85dce296d7513..763f63e48afe4 100644
--- a/net/ieee802154/socket.c
+++ b/net/ieee802154/socket.c
@@ -831,20 +831,12 @@ static int ieee802154_dgram_deliver(struct net_device *dev, struct sk_buff *skb)
 	return ret;
 }
 
-static int dgram_getsockopt(struct sock *sk, int level, int optname,
-			    char __user *optval, int __user *optlen)
+static int do_dgram_getsockopt(struct sock *sk, int optname, sockopt_t *opt)
 {
 	struct dgram_sock *ro = dgram_sk(sk);
-
 	int val, len;
 
-	if (level != SOL_IEEE802154)
-		return -EOPNOTSUPP;
-
-	if (get_user(len, optlen))
-		return -EFAULT;
-
-	len = min_t(unsigned int, len, sizeof(int));
+	len = min_t(unsigned int, opt->optlen, sizeof(int));
 
 	switch (optname) {
 	case WPAN_WANTACK:
@@ -871,10 +863,32 @@ static int dgram_getsockopt(struct sock *sk, int level, int optname,
 		return -ENOPROTOOPT;
 	}
 
-	if (put_user(len, optlen))
+	opt->optlen = len;
+	if (copy_to_iter(&val, len, &opt->iter_out) != len)
 		return -EFAULT;
-	if (copy_to_user(optval, &val, len))
+	return 0;
+}
+
+static int dgram_getsockopt(struct sock *sk, int level, int optname,
+			    char __user *optval, int __user *optlen)
+{
+	sockopt_t opt;
+	int err;
+
+	if (level != SOL_IEEE802154)
+		return -EOPNOTSUPP;
+
+	err = sockopt_init_user(&opt, optval, optlen);
+	if (err)
+		return err;
+
+	err = do_dgram_getsockopt(sk, optname, &opt);
+	if (err)
+		return err;
+
+	if (put_user(opt.optlen, optlen))
 		return -EFAULT;
+
 	return 0;
 }
 

-- 
2.53.0-Meta


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH net-next v2 4/7] phonet: pep: do not write beyond optlen in getsockopt
  2026-07-20 16:17 [PATCH net-next v2 0/7] net: convert rawv6, ieee802154, phonet and tls getsockopt to sockopt_t Breno Leitao
                   ` (2 preceding siblings ...)
  2026-07-20 16:17 ` [PATCH net-next v2 3/7] ieee802154: convert dgram getsockopt " Breno Leitao
@ 2026-07-20 16:17 ` Breno Leitao
  2026-07-20 16:17 ` [PATCH net-next v2 5/7] phonet: pep: convert getsockopt to sockopt_t Breno Leitao
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 13+ messages in thread
From: Breno Leitao @ 2026-07-20 16:17 UTC (permalink / raw)
  To: sdf, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Alexander Aring, Stefan Schmidt, Miquel Raynal,
	Remi Denis-Courmont, Rémi Denis-Courmont, John Fastabend,
	Sabrina Dubroca, Shuah Khan
  Cc: netdev, linux-kernel, linux-wpan, linux-kselftest, Breno Leitao,
	kernel-team, Rémi Denis-Courmont

pep_getsockopt() clamps the reported length to the caller's buffer with
min_t(), but then stores the value with put_user(val, (int __user *)
optval), which always writes sizeof(int) bytes. A getsockopt() call with
an optlen smaller than sizeof(int) thus reports the clamped length yet
writes a full int, one to three bytes past the user buffer.

Write the value with copy_to_user() bounded by len, so at most optlen
bytes are copied, matching the length reported back to userspace.

Fixes: 02a47617cdce ("Phonet: implement GPRS virtual interface over PEP socket")
Signed-off-by: Breno Leitao <leitao@debian.org>
Acked-by: Rémi Denis-Courmont <remi@remlab.net>
---
 net/phonet/pep.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/phonet/pep.c b/net/phonet/pep.c
index 7069271393933..60d1a5375725b 100644
--- a/net/phonet/pep.c
+++ b/net/phonet/pep.c
@@ -1115,7 +1115,7 @@ static int pep_getsockopt(struct sock *sk, int level, int optname,
 	len = min_t(unsigned int, sizeof(int), len);
 	if (put_user(len, optlen))
 		return -EFAULT;
-	if (put_user(val, (int __user *) optval))
+	if (copy_to_user(optval, &val, len))
 		return -EFAULT;
 	return 0;
 }

-- 
2.53.0-Meta


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH net-next v2 5/7] phonet: pep: convert getsockopt to sockopt_t
  2026-07-20 16:17 [PATCH net-next v2 0/7] net: convert rawv6, ieee802154, phonet and tls getsockopt to sockopt_t Breno Leitao
                   ` (3 preceding siblings ...)
  2026-07-20 16:17 ` [PATCH net-next v2 4/7] phonet: pep: do not write beyond optlen in getsockopt Breno Leitao
@ 2026-07-20 16:17 ` Breno Leitao
  2026-07-20 16:17 ` [PATCH net-next v2 6/7] tls: " Breno Leitao
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 13+ messages in thread
From: Breno Leitao @ 2026-07-20 16:17 UTC (permalink / raw)
  To: sdf, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Alexander Aring, Stefan Schmidt, Miquel Raynal,
	Remi Denis-Courmont, Rémi Denis-Courmont, John Fastabend,
	Sabrina Dubroca, Shuah Khan
  Cc: netdev, linux-kernel, linux-wpan, linux-kselftest, Breno Leitao,
	kernel-team, Rémi Denis-Courmont

Continue converting the proto-layer getsockopt callbacks to the
sockopt_t interface, splitting pep_getsockopt() into a
do_pep_getsockopt() helper that takes a sockopt_t.

The thin pep_getsockopt() wrapper keeps its __user signature for now:
it builds a user-backed sockopt_t with sockopt_init_user(), calls the
helper, and writes the returned length back to optlen. The helper uses
copy_to_iter() instead of copy_to_user(). No functional change.

Signed-off-by: Breno Leitao <leitao@debian.org>
Acked-by: Rémi Denis-Courmont <remi@remlab.net>
---
 net/phonet/pep.c | 36 ++++++++++++++++++++++++++----------
 1 file changed, 26 insertions(+), 10 deletions(-)

diff --git a/net/phonet/pep.c b/net/phonet/pep.c
index 60d1a5375725b..7ef4a9a240ef8 100644
--- a/net/phonet/pep.c
+++ b/net/phonet/pep.c
@@ -1078,17 +1078,11 @@ static int pep_setsockopt(struct sock *sk, int level, int optname,
 	return err;
 }
 
-static int pep_getsockopt(struct sock *sk, int level, int optname,
-				char __user *optval, int __user *optlen)
+static int do_pep_getsockopt(struct sock *sk, int optname, sockopt_t *opt)
 {
 	struct pep_sock *pn = pep_sk(sk);
 	int len, val;
 
-	if (level != SOL_PNPIPE)
-		return -ENOPROTOOPT;
-	if (get_user(len, optlen))
-		return -EFAULT;
-
 	switch (optname) {
 	case PNPIPE_ENCAP:
 		val = pn->ifindex ? PNPIPE_ENCAP_IP : PNPIPE_ENCAP_NONE;
@@ -1112,11 +1106,33 @@ static int pep_getsockopt(struct sock *sk, int level, int optname,
 		return -ENOPROTOOPT;
 	}
 
-	len = min_t(unsigned int, sizeof(int), len);
-	if (put_user(len, optlen))
+	len = umin(sizeof(int), opt->optlen);
+	opt->optlen = len;
+	if (copy_to_iter(&val, len, &opt->iter_out) != len)
 		return -EFAULT;
-	if (copy_to_user(optval, &val, len))
+	return 0;
+}
+
+static int pep_getsockopt(struct sock *sk, int level, int optname,
+			  char __user *optval, int __user *optlen)
+{
+	sockopt_t opt;
+	int err;
+
+	if (level != SOL_PNPIPE)
+		return -ENOPROTOOPT;
+
+	err = sockopt_init_user(&opt, optval, optlen);
+	if (err)
+		return err;
+
+	err = do_pep_getsockopt(sk, optname, &opt);
+	if (err)
+		return err;
+
+	if (put_user(opt.optlen, optlen))
 		return -EFAULT;
+
 	return 0;
 }
 

-- 
2.53.0-Meta


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH net-next v2 6/7] tls: convert getsockopt to sockopt_t
  2026-07-20 16:17 [PATCH net-next v2 0/7] net: convert rawv6, ieee802154, phonet and tls getsockopt to sockopt_t Breno Leitao
                   ` (4 preceding siblings ...)
  2026-07-20 16:17 ` [PATCH net-next v2 5/7] phonet: pep: convert getsockopt to sockopt_t Breno Leitao
@ 2026-07-20 16:17 ` Breno Leitao
  2026-07-23  9:51   ` Sabrina Dubroca
  2026-07-20 16:17 ` [PATCH net-next v2 7/7] selftests: net: getsockopt_iter: cover rawv6, ieee802154, phonet and tls Breno Leitao
  2026-07-22 13:42 ` [PATCH net-next v2 0/7] net: convert rawv6, ieee802154, phonet and tls getsockopt to sockopt_t Joe Damato
  7 siblings, 1 reply; 13+ messages in thread
From: Breno Leitao @ 2026-07-20 16:17 UTC (permalink / raw)
  To: sdf, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Alexander Aring, Stefan Schmidt, Miquel Raynal,
	Remi Denis-Courmont, Rémi Denis-Courmont, John Fastabend,
	Sabrina Dubroca, Shuah Khan
  Cc: netdev, linux-kernel, linux-wpan, linux-kselftest, Breno Leitao,
	kernel-team

Continue converting the proto-layer getsockopt callbacks to the sockopt_t
interface, converting do_tls_getsockopt() and its per-option helpers to
take a sockopt_t.

The thin tls_getsockopt() wrapper keeps its __user signature for now: it
builds a user-backed sockopt_t with sockopt_init_user(), calls the helper,
and writes the returned length back to optlen. The helpers use
copy_to_iter() instead of copy_to_user(); the NULL optval check in the
TLS_TX/TLS_RX path is preserved by testing the iterator user buffer.

No functional change.

Signed-off-by: Breno Leitao <leitao@debian.org>
---
 net/tls/tls_main.c | 80 ++++++++++++++++++++++++++----------------------------
 1 file changed, 38 insertions(+), 42 deletions(-)

diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c
index 8c588cdab733d..fbb274287aa5f 100644
--- a/net/tls/tls_main.c
+++ b/net/tls/tls_main.c
@@ -424,20 +424,16 @@ static __poll_t tls_sk_poll(struct file *file, struct socket *sock,
 	return mask;
 }
 
-static int do_tls_getsockopt_conf(struct sock *sk, char __user *optval,
-				  int __user *optlen, int tx)
+static int do_tls_getsockopt_conf(struct sock *sk, sockopt_t *opt, int tx)
 {
 	int rc = 0;
 	const struct tls_cipher_desc *cipher_desc;
 	struct tls_context *ctx = tls_get_ctx(sk);
 	struct tls_crypto_info *crypto_info;
 	struct cipher_context *cctx;
-	int len;
+	int len = opt->optlen;
 
-	if (get_user(len, optlen))
-		return -EFAULT;
-
-	if (!optval || (len < sizeof(*crypto_info))) {
+	if (!opt->iter_out.ubuf || len < sizeof(*crypto_info)) {
 		rc = -EINVAL;
 		goto out;
 	}
@@ -462,7 +458,8 @@ static int do_tls_getsockopt_conf(struct sock *sk, char __user *optval,
 	}
 
 	if (len == sizeof(*crypto_info)) {
-		if (copy_to_user(optval, crypto_info, sizeof(*crypto_info)))
+		if (copy_to_iter(crypto_info, sizeof(*crypto_info),
+				 &opt->iter_out) != sizeof(*crypto_info))
 			rc = -EFAULT;
 		goto out;
 	}
@@ -478,44 +475,38 @@ static int do_tls_getsockopt_conf(struct sock *sk, char __user *optval,
 	memcpy(crypto_info_rec_seq(crypto_info, cipher_desc),
 	       cctx->rec_seq, cipher_desc->rec_seq);
 
-	if (copy_to_user(optval, crypto_info, cipher_desc->crypto_info))
+	if (copy_to_iter(crypto_info, cipher_desc->crypto_info,
+			 &opt->iter_out) != cipher_desc->crypto_info)
 		rc = -EFAULT;
 
 out:
 	return rc;
 }
 
-static int do_tls_getsockopt_tx_zc(struct sock *sk, char __user *optval,
-				   int __user *optlen)
+static int do_tls_getsockopt_tx_zc(struct sock *sk, sockopt_t *opt)
 {
 	struct tls_context *ctx = tls_get_ctx(sk);
 	unsigned int value;
-	int len;
-
-	if (get_user(len, optlen))
-		return -EFAULT;
+	int len = opt->optlen;
 
 	if (len != sizeof(value))
 		return -EINVAL;
 
 	value = ctx->zerocopy_sendfile;
-	if (copy_to_user(optval, &value, sizeof(value)))
+	if (copy_to_iter(&value, sizeof(value), &opt->iter_out) != sizeof(value))
 		return -EFAULT;
 
 	return 0;
 }
 
-static int do_tls_getsockopt_no_pad(struct sock *sk, char __user *optval,
-				    int __user *optlen)
+static int do_tls_getsockopt_no_pad(struct sock *sk, sockopt_t *opt)
 {
 	struct tls_context *ctx = tls_get_ctx(sk);
-	int value, len;
+	int value, len = opt->optlen;
 
 	if (ctx->prot_info.version != TLS_1_3_VERSION)
 		return -EINVAL;
 
-	if (get_user(len, optlen))
-		return -EFAULT;
 	if (len < sizeof(value))
 		return -EINVAL;
 
@@ -525,38 +516,31 @@ static int do_tls_getsockopt_no_pad(struct sock *sk, char __user *optval,
 	if (value < 0)
 		return value;
 
-	if (put_user(sizeof(value), optlen))
-		return -EFAULT;
-	if (copy_to_user(optval, &value, sizeof(value)))
+	opt->optlen = sizeof(value);
+	if (copy_to_iter(&value, sizeof(value), &opt->iter_out) != sizeof(value))
 		return -EFAULT;
 
 	return 0;
 }
 
-static int do_tls_getsockopt_tx_payload_len(struct sock *sk, char __user *optval,
-					    int __user *optlen)
+static int do_tls_getsockopt_tx_payload_len(struct sock *sk, sockopt_t *opt)
 {
 	struct tls_context *ctx = tls_get_ctx(sk);
 	u16 payload_len = ctx->tx_max_payload_len;
-	int len;
-
-	if (get_user(len, optlen))
-		return -EFAULT;
+	int len = opt->optlen;
 
 	if (len < sizeof(payload_len))
 		return -EINVAL;
 
-	if (put_user(sizeof(payload_len), optlen))
-		return -EFAULT;
-
-	if (copy_to_user(optval, &payload_len, sizeof(payload_len)))
+	opt->optlen = sizeof(payload_len);
+	if (copy_to_iter(&payload_len, sizeof(payload_len),
+			 &opt->iter_out) != sizeof(payload_len))
 		return -EFAULT;
 
 	return 0;
 }
 
-static int do_tls_getsockopt(struct sock *sk, int optname,
-			     char __user *optval, int __user *optlen)
+static int do_tls_getsockopt(struct sock *sk, int optname, sockopt_t *opt)
 {
 	int rc = 0;
 
@@ -565,17 +549,16 @@ static int do_tls_getsockopt(struct sock *sk, int optname,
 	switch (optname) {
 	case TLS_TX:
 	case TLS_RX:
-		rc = do_tls_getsockopt_conf(sk, optval, optlen,
-					    optname == TLS_TX);
+		rc = do_tls_getsockopt_conf(sk, opt, optname == TLS_TX);
 		break;
 	case TLS_TX_ZEROCOPY_RO:
-		rc = do_tls_getsockopt_tx_zc(sk, optval, optlen);
+		rc = do_tls_getsockopt_tx_zc(sk, opt);
 		break;
 	case TLS_RX_EXPECT_NO_PAD:
-		rc = do_tls_getsockopt_no_pad(sk, optval, optlen);
+		rc = do_tls_getsockopt_no_pad(sk, opt);
 		break;
 	case TLS_TX_MAX_PAYLOAD_LEN:
-		rc = do_tls_getsockopt_tx_payload_len(sk, optval, optlen);
+		rc = do_tls_getsockopt_tx_payload_len(sk, opt);
 		break;
 	default:
 		rc = -ENOPROTOOPT;
@@ -591,12 +574,25 @@ static int tls_getsockopt(struct sock *sk, int level, int optname,
 			  char __user *optval, int __user *optlen)
 {
 	struct tls_context *ctx = tls_get_ctx(sk);
+	sockopt_t opt;
+	int err;
 
 	if (level != SOL_TLS)
 		return ctx->sk_proto->getsockopt(sk, level,
 						 optname, optval, optlen);
 
-	return do_tls_getsockopt(sk, optname, optval, optlen);
+	err = sockopt_init_user(&opt, optval, optlen);
+	if (err)
+		return err;
+
+	err = do_tls_getsockopt(sk, optname, &opt);
+	if (err)
+		return err;
+
+	if (put_user(opt.optlen, optlen))
+		return -EFAULT;
+
+	return 0;
 }
 
 static int validate_crypto_info(const struct tls_crypto_info *crypto_info,

-- 
2.53.0-Meta


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH net-next v2 7/7] selftests: net: getsockopt_iter: cover rawv6, ieee802154, phonet and tls
  2026-07-20 16:17 [PATCH net-next v2 0/7] net: convert rawv6, ieee802154, phonet and tls getsockopt to sockopt_t Breno Leitao
                   ` (5 preceding siblings ...)
  2026-07-20 16:17 ` [PATCH net-next v2 6/7] tls: " Breno Leitao
@ 2026-07-20 16:17 ` Breno Leitao
  2026-07-23 10:29   ` Sabrina Dubroca
  2026-07-22 13:42 ` [PATCH net-next v2 0/7] net: convert rawv6, ieee802154, phonet and tls getsockopt to sockopt_t Joe Damato
  7 siblings, 1 reply; 13+ messages in thread
From: Breno Leitao @ 2026-07-20 16:17 UTC (permalink / raw)
  To: sdf, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Alexander Aring, Stefan Schmidt, Miquel Raynal,
	Remi Denis-Courmont, Rémi Denis-Courmont, John Fastabend,
	Sabrina Dubroca, Shuah Khan
  Cc: netdev, linux-kernel, linux-wpan, linux-kselftest, Breno Leitao,
	kernel-team, Rémi Denis-Courmont

Add fixtures for the newly converted getsockopt leaves:

  - rawv6:      IPV6_HDRINCL / IPV6_CHECKSUM int paths + a SOL_RAW
                unknown-optname case that reaches do_rawv6_getsockopt().
  - ieee802154: WPAN_WANTACK dgram int path + non-SOL_IEEE802154 level
                rejection.
  - phonet:     PNPIPE_ENCAP pep int path + non-SOL_PNPIPE level
                rejection.
  - tls:        TLS_TX_ZEROCOPY_RO, the TLS_TX crypto_info round-trip at
                the base and full cipher sizes, the NULL-optval and short
                buffer EINVAL paths, and an unknown optname. It skips when
                the kernel lacks TLS or AES-GCM.

Each fixture pins the returned-length / errno semantics across exact,
oversized and short buffers, an unknown optname and a bogus level. The
semantics are unchanged by the sockopt_t conversion, so the tests pass
both before and after the leaf conversions.

Signed-off-by: Breno Leitao <leitao@debian.org>
Acked-by: Rémi Denis-Courmont <remi@remlab.net>
---
 tools/testing/selftests/net/getsockopt_iter.c | 424 ++++++++++++++++++++++++++
 1 file changed, 424 insertions(+)

diff --git a/tools/testing/selftests/net/getsockopt_iter.c b/tools/testing/selftests/net/getsockopt_iter.c
index fe5a5268bc34e..974065a23fa82 100644
--- a/tools/testing/selftests/net/getsockopt_iter.c
+++ b/tools/testing/selftests/net/getsockopt_iter.c
@@ -28,7 +28,10 @@
 #include <linux/vm_sockets.h>
 #include <linux/icmp.h>
 #include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
 #include <sys/socket.h>
+#include <linux/tls.h>
 #include "kselftest_harness.h"
 
 #ifndef AF_VSOCK
@@ -40,6 +43,45 @@
 #ifndef ICMP_FILTER
 #define ICMP_FILTER 1
 #endif
+#ifndef IPV6_HDRINCL
+#define IPV6_HDRINCL 36
+#endif
+#ifndef IPV6_CHECKSUM
+#define IPV6_CHECKSUM 7
+#endif
+#ifndef AF_IEEE802154
+#define AF_IEEE802154 36
+#endif
+#ifndef SOL_IEEE802154
+#define SOL_IEEE802154 0
+#endif
+#ifndef WPAN_WANTACK
+#define WPAN_WANTACK 0
+#endif
+#ifndef AF_PHONET
+#define AF_PHONET 35
+#endif
+#ifndef SOL_PNPIPE
+#define SOL_PNPIPE 275
+#endif
+#ifndef PN_PROTO_PIPE
+#define PN_PROTO_PIPE 2
+#endif
+#ifndef PNPIPE_ENCAP
+#define PNPIPE_ENCAP 1
+#endif
+#ifndef PNPIPE_ENCAP_NONE
+#define PNPIPE_ENCAP_NONE 0
+#endif
+#ifndef PNPIPE_ENCAP_IP
+#define PNPIPE_ENCAP_IP 1
+#endif
+#ifndef SOL_TLS
+#define SOL_TLS 282
+#endif
+#ifndef TCP_ULP
+#define TCP_ULP 31
+#endif
 
 /* ---------- netlink ---------- */
 
@@ -394,4 +436,386 @@ TEST_F(raw, bad_optname)
 	ASSERT_EQ(sizeof(val), optlen);
 }
 
+/* ---------- raw (ipv6) ---------- */
+
+FIXTURE(rawv6)
+{
+	int fd;
+};
+
+FIXTURE_SETUP(rawv6)
+{
+	self->fd = socket(AF_INET6, SOCK_RAW, IPPROTO_UDP);
+	if (self->fd < 0)
+		SKIP(return, "SOCK_RAW/IPv6 socket: %s", strerror(errno));
+}
+
+FIXTURE_TEARDOWN(rawv6)
+{
+	if (self->fd >= 0)
+		close(self->fd);
+}
+
+TEST_F(rawv6, hdrincl_exact)
+{
+	socklen_t optlen;
+	int val = -1;
+
+	optlen = sizeof(val);
+
+	ASSERT_EQ(0, getsockopt(self->fd, IPPROTO_IPV6, IPV6_HDRINCL,
+				&val, &optlen));
+	ASSERT_EQ(sizeof(int), optlen);
+	ASSERT_TRUE(val == 0 || val == 1);
+}
+
+TEST_F(rawv6, hdrincl_oversize_clamped)
+{
+	char buf[16] = {};
+	socklen_t optlen = sizeof(buf);
+
+	ASSERT_EQ(0, getsockopt(self->fd, IPPROTO_IPV6, IPV6_HDRINCL,
+				buf, &optlen));
+	ASSERT_EQ(sizeof(int), optlen);
+}
+
+/* Raw int options clamp the reported length down to the user buffer
+ * instead of returning EINVAL on a short buffer.
+ */
+TEST_F(rawv6, hdrincl_undersize_clamped)
+{
+	socklen_t optlen = 2;
+	int val = 0;
+
+	ASSERT_EQ(0, getsockopt(self->fd, IPPROTO_IPV6, IPV6_HDRINCL,
+				&val, &optlen));
+	ASSERT_EQ(2, optlen);
+}
+
+TEST_F(rawv6, checksum_default)
+{
+	socklen_t optlen;
+	int val = 0;
+
+	optlen = sizeof(val);
+
+	/* A non-ICMPv6 raw socket has the checksum disabled, reported as -1. */
+	ASSERT_EQ(0, getsockopt(self->fd, IPPROTO_IPV6, IPV6_CHECKSUM,
+				&val, &optlen));
+	ASSERT_EQ(sizeof(int), optlen);
+	ASSERT_EQ(-1, val);
+}
+
+TEST_F(rawv6, bad_optname)
+{
+	socklen_t optlen;
+	int val;
+
+	optlen = sizeof(val);
+
+	/* SOL_RAW reaches do_rawv6_getsockopt() directly. */
+	ASSERT_EQ(-1, getsockopt(self->fd, SOL_RAW, 0x7fff, &val, &optlen));
+	ASSERT_EQ(ENOPROTOOPT, errno);
+	ASSERT_EQ(sizeof(val), optlen);
+}
+
+/* ---------- ieee802154 (dgram) ---------- */
+
+FIXTURE(ieee802154)
+{
+	int fd;
+};
+
+FIXTURE_SETUP(ieee802154)
+{
+	self->fd = socket(AF_IEEE802154, SOCK_DGRAM, 0);
+	if (self->fd < 0)
+		SKIP(return, "AF_IEEE802154 dgram socket: %s", strerror(errno));
+}
+
+FIXTURE_TEARDOWN(ieee802154)
+{
+	if (self->fd >= 0)
+		close(self->fd);
+}
+
+TEST_F(ieee802154, wantack_exact)
+{
+	socklen_t optlen;
+	int val = -1;
+
+	optlen = sizeof(val);
+
+	ASSERT_EQ(0, getsockopt(self->fd, SOL_IEEE802154, WPAN_WANTACK,
+				&val, &optlen));
+	ASSERT_EQ(sizeof(int), optlen);
+	ASSERT_TRUE(val == 0 || val == 1);
+}
+
+TEST_F(ieee802154, wantack_oversize_clamped)
+{
+	char buf[16] = {};
+	socklen_t optlen = sizeof(buf);
+
+	ASSERT_EQ(0, getsockopt(self->fd, SOL_IEEE802154, WPAN_WANTACK,
+				buf, &optlen));
+	ASSERT_EQ(sizeof(int), optlen);
+}
+
+TEST_F(ieee802154, wantack_undersize_clamped)
+{
+	socklen_t optlen = 2;
+	int val = 0;
+
+	ASSERT_EQ(0, getsockopt(self->fd, SOL_IEEE802154, WPAN_WANTACK,
+				&val, &optlen));
+	ASSERT_EQ(2, optlen);
+}
+
+TEST_F(ieee802154, bad_optname)
+{
+	socklen_t optlen;
+	int val;
+
+	optlen = sizeof(val);
+
+	ASSERT_EQ(-1, getsockopt(self->fd, SOL_IEEE802154, 0x7fff,
+				 &val, &optlen));
+	ASSERT_EQ(ENOPROTOOPT, errno);
+	ASSERT_EQ(sizeof(val), optlen);
+}
+
+/* dgram_getsockopt() rejects any level other than SOL_IEEE802154. */
+TEST_F(ieee802154, bad_level)
+{
+	socklen_t optlen;
+	int val;
+
+	optlen = sizeof(val);
+
+	ASSERT_EQ(-1, getsockopt(self->fd, SOL_RAW, WPAN_WANTACK,
+				 &val, &optlen));
+	ASSERT_EQ(EOPNOTSUPP, errno);
+	ASSERT_EQ(sizeof(val), optlen);
+}
+
+/* ---------- phonet (pep) ---------- */
+
+FIXTURE(phonet)
+{
+	int fd;
+};
+
+FIXTURE_SETUP(phonet)
+{
+	self->fd = socket(AF_PHONET, SOCK_SEQPACKET, PN_PROTO_PIPE);
+	if (self->fd < 0)
+		SKIP(return, "AF_PHONET pipe socket: %s", strerror(errno));
+}
+
+FIXTURE_TEARDOWN(phonet)
+{
+	if (self->fd >= 0)
+		close(self->fd);
+}
+
+TEST_F(phonet, encap_exact)
+{
+	socklen_t optlen;
+	int val = -1;
+
+	optlen = sizeof(val);
+
+	ASSERT_EQ(0, getsockopt(self->fd, SOL_PNPIPE, PNPIPE_ENCAP,
+				&val, &optlen));
+	ASSERT_EQ(sizeof(int), optlen);
+	ASSERT_TRUE(val == PNPIPE_ENCAP_NONE || val == PNPIPE_ENCAP_IP);
+}
+
+TEST_F(phonet, encap_oversize_clamped)
+{
+	char buf[16] = {};
+	socklen_t optlen = sizeof(buf);
+
+	ASSERT_EQ(0, getsockopt(self->fd, SOL_PNPIPE, PNPIPE_ENCAP,
+				buf, &optlen));
+	ASSERT_EQ(sizeof(int), optlen);
+}
+
+/* pep clamps the reported length down to the user buffer. Use an
+ * int-sized backing buffer with a short optlen so the baseline kernel,
+ * which writes a full int via put_user(), does not scribble past it.
+ */
+TEST_F(phonet, encap_undersize_clamped)
+{
+	socklen_t optlen = 2;
+	int val = 0;
+
+	ASSERT_EQ(0, getsockopt(self->fd, SOL_PNPIPE, PNPIPE_ENCAP,
+				&val, &optlen));
+	ASSERT_EQ(2, optlen);
+}
+
+TEST_F(phonet, bad_optname)
+{
+	socklen_t optlen;
+	int val;
+
+	optlen = sizeof(val);
+
+	ASSERT_EQ(-1, getsockopt(self->fd, SOL_PNPIPE, 0x7fff, &val, &optlen));
+	ASSERT_EQ(ENOPROTOOPT, errno);
+	ASSERT_EQ(sizeof(val), optlen);
+}
+
+/* pep_getsockopt() rejects any level other than SOL_PNPIPE. */
+TEST_F(phonet, bad_level)
+{
+	socklen_t optlen;
+	int val;
+
+	optlen = sizeof(val);
+
+	ASSERT_EQ(-1, getsockopt(self->fd, SOL_RAW, PNPIPE_ENCAP, &val, &optlen));
+	ASSERT_EQ(ENOPROTOOPT, errno);
+	ASSERT_EQ(sizeof(val), optlen);
+}
+
+/* ---------- tls ---------- */
+
+FIXTURE(tls)
+{
+	int fd;
+	int sfd;
+};
+
+FIXTURE_SETUP(tls)
+{
+	struct sockaddr_in a = {
+		.sin_family = AF_INET,
+		.sin_addr.s_addr = htonl(INADDR_LOOPBACK),
+	};
+	socklen_t alen = sizeof(a);
+	int lfd;
+
+	self->fd = -1;
+	self->sfd = -1;
+
+	lfd = socket(AF_INET, SOCK_STREAM, 0);
+	if (lfd < 0)
+		SKIP(return, "TCP socket: %s", strerror(errno));
+	if (bind(lfd, (struct sockaddr *)&a, sizeof(a)) || listen(lfd, 1) ||
+	    getsockname(lfd, (struct sockaddr *)&a, &alen)) {
+		close(lfd);
+		SKIP(return, "listener setup: %s", strerror(errno));
+	}
+	self->fd = socket(AF_INET, SOCK_STREAM, 0);
+	if (connect(self->fd, (struct sockaddr *)&a, sizeof(a))) {
+		close(lfd);
+		SKIP(return, "connect: %s", strerror(errno));
+	}
+	self->sfd = accept(lfd, NULL, NULL);
+	close(lfd);
+	if (setsockopt(self->fd, IPPROTO_TCP, TCP_ULP, "tls", sizeof("tls")))
+		SKIP(return, "TCP_ULP=tls: %s (built without TLS?)",
+		     strerror(errno));
+}
+
+FIXTURE_TEARDOWN(tls)
+{
+	if (self->fd >= 0)
+		close(self->fd);
+	if (self->sfd >= 0)
+		close(self->sfd);
+}
+
+/* do_tls_getsockopt_tx_zc(): fixed-size int, exact length required. */
+TEST_F(tls, tx_zerocopy_exact)
+{
+	socklen_t optlen = sizeof(int);
+	int val = -1;
+
+	ASSERT_EQ(0, getsockopt(self->fd, SOL_TLS, TLS_TX_ZEROCOPY_RO,
+				&val, &optlen));
+	ASSERT_EQ(sizeof(int), optlen);
+	ASSERT_TRUE(val == 0 || val == 1);
+}
+
+TEST_F(tls, tx_zerocopy_wrong_len)
+{
+	socklen_t optlen = 2;
+	int val;
+
+	ASSERT_EQ(-1, getsockopt(self->fd, SOL_TLS, TLS_TX_ZEROCOPY_RO,
+				 &val, &optlen));
+	ASSERT_EQ(EINVAL, errno);
+}
+
+/* do_tls_getsockopt_conf(): NULL optval still yields EINVAL -- the
+ * converted code tests opt->iter_out.ubuf in place of optval.
+ */
+TEST_F(tls, conf_null_optval)
+{
+	socklen_t optlen = 64;
+
+	ASSERT_EQ(-1, getsockopt(self->fd, SOL_TLS, TLS_TX, NULL, &optlen));
+	ASSERT_EQ(EINVAL, errno);
+}
+
+TEST_F(tls, conf_short)
+{
+	socklen_t optlen = 2;
+	char buf[2];
+
+	ASSERT_EQ(-1, getsockopt(self->fd, SOL_TLS, TLS_TX, buf, &optlen));
+	ASSERT_EQ(EINVAL, errno);
+}
+
+/* TLS_TX before crypto is set reports not-ready. */
+TEST_F(tls, conf_not_ready)
+{
+	struct tls_crypto_info info;
+	socklen_t optlen = sizeof(info);
+
+	ASSERT_EQ(-1, getsockopt(self->fd, SOL_TLS, TLS_TX, &info, &optlen));
+	ASSERT_EQ(EBUSY, errno);
+}
+
+/* Set TX crypto, then read it back at the base and full sizes, exercising
+ * both copy_to_iter() branches. SKIP if AES-GCM is unavailable.
+ */
+TEST_F(tls, conf_crypto_roundtrip)
+{
+	struct tls12_crypto_info_aes_gcm_128 tx = {
+		.info.version = TLS_1_2_VERSION,
+		.info.cipher_type = TLS_CIPHER_AES_GCM_128,
+	};
+	struct tls12_crypto_info_aes_gcm_128 full;
+	struct tls_crypto_info base;
+	socklen_t optlen;
+
+	if (setsockopt(self->fd, SOL_TLS, TLS_TX, &tx, sizeof(tx)))
+		SKIP(return, "set TLS_TX aes_gcm_128: %s", strerror(errno));
+
+	optlen = sizeof(base);
+	ASSERT_EQ(0, getsockopt(self->fd, SOL_TLS, TLS_TX, &base, &optlen));
+	ASSERT_EQ(sizeof(base), optlen);
+	ASSERT_EQ(TLS_1_2_VERSION, base.version);
+	ASSERT_EQ(TLS_CIPHER_AES_GCM_128, base.cipher_type);
+
+	optlen = sizeof(full);
+	ASSERT_EQ(0, getsockopt(self->fd, SOL_TLS, TLS_TX, &full, &optlen));
+	ASSERT_EQ(sizeof(full), optlen);
+	ASSERT_EQ(TLS_CIPHER_AES_GCM_128, full.info.cipher_type);
+}
+
+TEST_F(tls, bad_optname)
+{
+	socklen_t optlen = sizeof(int);
+	int val;
+
+	ASSERT_EQ(-1, getsockopt(self->fd, SOL_TLS, 0x7fff, &val, &optlen));
+	ASSERT_EQ(ENOPROTOOPT, errno);
+}
+
 TEST_HARNESS_MAIN

-- 
2.53.0-Meta


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH net-next v2 3/7] ieee802154: convert dgram getsockopt to sockopt_t
  2026-07-20 16:17 ` [PATCH net-next v2 3/7] ieee802154: convert dgram getsockopt " Breno Leitao
@ 2026-07-22 13:40   ` Joe Damato
  0 siblings, 0 replies; 13+ messages in thread
From: Joe Damato @ 2026-07-22 13:40 UTC (permalink / raw)
  To: Breno Leitao
  Cc: sdf, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Alexander Aring, Stefan Schmidt, Miquel Raynal,
	Remi Denis-Courmont, Rémi Denis-Courmont, John Fastabend,
	Sabrina Dubroca, Shuah Khan, netdev, linux-kernel, linux-wpan,
	linux-kselftest, kernel-team

On Mon, Jul 20, 2026 at 09:17:44AM -0700, Breno Leitao wrote:
> Continue converting the proto-layer getsockopt callbacks to the sockopt_t
> interface, splitting dgram_getsockopt() into a do_dgram_getsockopt() helper
> that takes a sockopt_t.
> 
> No functional change.
> 
> Signed-off-by: Breno Leitao <leitao@debian.org>
> ---
>  net/ieee802154/socket.c | 38 ++++++++++++++++++++++++++------------
>  1 file changed, 26 insertions(+), 12 deletions(-)
> 
> diff --git a/net/ieee802154/socket.c b/net/ieee802154/socket.c
> index 85dce296d7513..763f63e48afe4 100644
> --- a/net/ieee802154/socket.c
> +++ b/net/ieee802154/socket.c
> @@ -831,20 +831,12 @@ static int ieee802154_dgram_deliver(struct net_device *dev, struct sk_buff *skb)
>  	return ret;
>  }
>  
> -static int dgram_getsockopt(struct sock *sk, int level, int optname,
> -			    char __user *optval, int __user *optlen)
> +static int do_dgram_getsockopt(struct sock *sk, int optname, sockopt_t *opt)
>  {
>  	struct dgram_sock *ro = dgram_sk(sk);
> -
>  	int val, len;
>  
> -	if (level != SOL_IEEE802154)
> -		return -EOPNOTSUPP;
> -
> -	if (get_user(len, optlen))
> -		return -EFAULT;
> -
> -	len = min_t(unsigned int, len, sizeof(int));
> +	len = min_t(unsigned int, opt->optlen, sizeof(int));

Does the same min() feedback David gave on the last revision apply here as
well?

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH net-next v2 0/7] net: convert rawv6, ieee802154, phonet and tls getsockopt to sockopt_t
  2026-07-20 16:17 [PATCH net-next v2 0/7] net: convert rawv6, ieee802154, phonet and tls getsockopt to sockopt_t Breno Leitao
                   ` (6 preceding siblings ...)
  2026-07-20 16:17 ` [PATCH net-next v2 7/7] selftests: net: getsockopt_iter: cover rawv6, ieee802154, phonet and tls Breno Leitao
@ 2026-07-22 13:42 ` Joe Damato
  2026-07-23 14:05   ` Breno Leitao
  7 siblings, 1 reply; 13+ messages in thread
From: Joe Damato @ 2026-07-22 13:42 UTC (permalink / raw)
  To: Breno Leitao
  Cc: sdf, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Alexander Aring, Stefan Schmidt, Miquel Raynal,
	Remi Denis-Courmont, Rémi Denis-Courmont, John Fastabend,
	Sabrina Dubroca, Shuah Khan, netdev, linux-kernel, linux-wpan,
	linux-kselftest, kernel-team, Rémi Denis-Courmont

On Mon, Jul 20, 2026 at 09:17:41AM -0700, Breno Leitao wrote:
> Now that sockopt_init_user() was already merged, builds a user-backed
> sockopt_t from the __user pair. A getsockopt leaf can then take
> a sockopt_t behind a thin __user wrapper: the wrapper builds it, calls
> the leaf, and writes the length back to optlen. The leaf copies with
> copy_to_iter() instead of copy_to_user().
> 
> Convert four more leaves the way udp and raw already were: ipv6 raw
> (do_rawv6_getsockopt), ieee802154 dgram, phonet pep, and tls
> (do_tls_getsockopt and its per-option helpers). 
> 
> Converting phonet surfaced a pre-existing bug: pep_getsockopt() clamps the
> length it reports but writes a full int with put_user(), overrunning an
> optval buffer shorter than sizeof(int). It is fixed in its own patch, with
> a Fixes: tag, before the phonet conversion, so it can be backported alone.
> 
> The last patch adds getsockopt_iter selftest fixtures for rawv6,
> ieee802154, phonet and tls, checking the returned length and errno across
> exact, oversized and short buffers, an unknown optname and a bad level.
> 
> For full motivation about these changes, please check the initial thread
> at link
> https://lore.kernel.org/all/20260401-getsockopt-v2-0-611df6771aff@debian.org/#t
> 
> Signed-off-by: Breno Leitao <leitao@debian.org>
> ---
> Changes in v2:
> - Replace min_t() by umin() (David)
> - Link to v1: https://patch.msgid.link/20260716-getsockopt_phase4-v1-0-4f45cb12dce7@debian.org

Other than the nit I mentioned about min vs min_t on the one patch, it looks
good overall to me, so for the series:

Reviewed-by: Joe Damato <joe@dama.to>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH net-next v2 6/7] tls: convert getsockopt to sockopt_t
  2026-07-20 16:17 ` [PATCH net-next v2 6/7] tls: " Breno Leitao
@ 2026-07-23  9:51   ` Sabrina Dubroca
  0 siblings, 0 replies; 13+ messages in thread
From: Sabrina Dubroca @ 2026-07-23  9:51 UTC (permalink / raw)
  To: Breno Leitao
  Cc: sdf, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Alexander Aring, Stefan Schmidt, Miquel Raynal,
	Remi Denis-Courmont, Rémi Denis-Courmont, John Fastabend,
	Shuah Khan, netdev, linux-kernel, linux-wpan, linux-kselftest,
	kernel-team

2026-07-20, 09:17:47 -0700, Breno Leitao wrote:
> Continue converting the proto-layer getsockopt callbacks to the sockopt_t
> interface, converting do_tls_getsockopt() and its per-option helpers to
> take a sockopt_t.
> 
> The thin tls_getsockopt() wrapper keeps its __user signature for now: it
> builds a user-backed sockopt_t with sockopt_init_user(), calls the helper,
> and writes the returned length back to optlen. The helpers use
> copy_to_iter() instead of copy_to_user(); the NULL optval check in the
> TLS_TX/TLS_RX path is preserved by testing the iterator user buffer.
> 
> No functional change.
>
> Signed-off-by: Breno Leitao <leitao@debian.org>

Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>

Looks ok, just a few small comments:

> -static int do_tls_getsockopt_conf(struct sock *sk, char __user *optval,
> -				  int __user *optlen, int tx)
> +static int do_tls_getsockopt_conf(struct sock *sk, sockopt_t *opt, int tx)
>  {
>  	int rc = 0;
>  	const struct tls_cipher_desc *cipher_desc;
>  	struct tls_context *ctx = tls_get_ctx(sk);
>  	struct tls_crypto_info *crypto_info;
>  	struct cipher_context *cctx;
> -	int len;
> +	int len = opt->optlen;
>  
> -	if (get_user(len, optlen))
> -		return -EFAULT;
> -
> -	if (!optval || (len < sizeof(*crypto_info))) {
> +	if (!opt->iter_out.ubuf || len < sizeof(*crypto_info)) {

Not something about your patch but... I really wonder what this NULL
check was trying to accomplish. The other getsockopts in tls don't
have one, I don't think the rest of networkng does that either.


> @@ -591,12 +574,25 @@ static int tls_getsockopt(struct sock *sk, int level, int optname,
>  			  char __user *optval, int __user *optlen)
>  {
>  	struct tls_context *ctx = tls_get_ctx(sk);
> +	sockopt_t opt;
> +	int err;
>  
>  	if (level != SOL_TLS)
>  		return ctx->sk_proto->getsockopt(sk, level,
>  						 optname, optval, optlen);
>  
> -	return do_tls_getsockopt(sk, optname, optval, optlen);
> +	err = sockopt_init_user(&opt, optval, optlen);
> +	if (err)
> +		return err;
> +
> +	err = do_tls_getsockopt(sk, optname, &opt);
> +	if (err)
> +		return err;
> +
> +	if (put_user(opt.optlen, optlen))
> +		return -EFAULT;

One of the sashikos complains that we're now writing the length with
put_user in cases where we didn't before. I don't think we need to
care, but if someone complains, we could make this conditional on
optlen having been changed by the handler.

It also complains that optlen was getting updated on EFAULT and now
it's not. There's possibly some code out there that's crazy enough to
pass a bogus buffer to get the size it should have provided?

Also some complaints about "what if optlen is negative". I think we
can ignore all of that.

-- 
Sabrina

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH net-next v2 7/7] selftests: net: getsockopt_iter: cover rawv6, ieee802154, phonet and tls
  2026-07-20 16:17 ` [PATCH net-next v2 7/7] selftests: net: getsockopt_iter: cover rawv6, ieee802154, phonet and tls Breno Leitao
@ 2026-07-23 10:29   ` Sabrina Dubroca
  0 siblings, 0 replies; 13+ messages in thread
From: Sabrina Dubroca @ 2026-07-23 10:29 UTC (permalink / raw)
  To: Breno Leitao
  Cc: sdf, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Alexander Aring, Stefan Schmidt, Miquel Raynal,
	Remi Denis-Courmont, Rémi Denis-Courmont, John Fastabend,
	Shuah Khan, netdev, linux-kernel, linux-wpan, linux-kselftest,
	kernel-team, Rémi Denis-Courmont

2026-07-20, 09:17:48 -0700, Breno Leitao wrote:
> Add fixtures for the newly converted getsockopt leaves:
> 
>   - rawv6:      IPV6_HDRINCL / IPV6_CHECKSUM int paths + a SOL_RAW
>                 unknown-optname case that reaches do_rawv6_getsockopt().
>   - ieee802154: WPAN_WANTACK dgram int path + non-SOL_IEEE802154 level
>                 rejection.
>   - phonet:     PNPIPE_ENCAP pep int path + non-SOL_PNPIPE level
>                 rejection.
>   - tls:        TLS_TX_ZEROCOPY_RO, the TLS_TX crypto_info round-trip at
>                 the base and full cipher sizes, the NULL-optval and short
>                 buffer EINVAL paths, and an unknown optname. It skips when
>                 the kernel lacks TLS or AES-GCM.
> 
> Each fixture pins the returned-length / errno semantics across exact,
> oversized and short buffers, an unknown optname and a bogus level. The
> semantics are unchanged by the sockopt_t conversion, so the tests pass
> both before and after the leaf conversions.
> 
> Signed-off-by: Breno Leitao <leitao@debian.org>
> Acked-by: Rémi Denis-Courmont <remi@remlab.net>
> ---

> +/* ---------- tls ---------- */

The TLS tests themselves look good.
Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>

I guess there's a question here (for components that already have
their own tests, so I think just tls for this patch) about whether
getsockopt tests belong with the other component tests (net/tls.c) or
in this getsockopt_iter group.

-- 
Sabrina

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH net-next v2 0/7] net: convert rawv6, ieee802154, phonet and tls getsockopt to sockopt_t
  2026-07-22 13:42 ` [PATCH net-next v2 0/7] net: convert rawv6, ieee802154, phonet and tls getsockopt to sockopt_t Joe Damato
@ 2026-07-23 14:05   ` Breno Leitao
  0 siblings, 0 replies; 13+ messages in thread
From: Breno Leitao @ 2026-07-23 14:05 UTC (permalink / raw)
  To: Joe Damato, sdf, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Simon Horman, Alexander Aring, Stefan Schmidt,
	Miquel Raynal, Remi Denis-Courmont, Rémi Denis-Courmont,
	John Fastabend, Sabrina Dubroca, Shuah Khan, netdev, linux-kernel,
	linux-wpan, linux-kselftest, kernel-team,
	Rémi Denis-Courmont, david.laight.linux

On Wed, Jul 22, 2026 at 06:42:41AM -0700, Joe Damato wrote:
> On Mon, Jul 20, 2026 at 09:17:41AM -0700, Breno Leitao wrote:
> > Now that sockopt_init_user() was already merged, builds a user-backed
> > sockopt_t from the __user pair. A getsockopt leaf can then take
> > a sockopt_t behind a thin __user wrapper: the wrapper builds it, calls
> > the leaf, and writes the length back to optlen. The leaf copies with
> > copy_to_iter() instead of copy_to_user().
> > 
> > Convert four more leaves the way udp and raw already were: ipv6 raw
> > (do_rawv6_getsockopt), ieee802154 dgram, phonet pep, and tls
> > (do_tls_getsockopt and its per-option helpers). 
> > 
> > Converting phonet surfaced a pre-existing bug: pep_getsockopt() clamps the
> > length it reports but writes a full int with put_user(), overrunning an
> > optval buffer shorter than sizeof(int). It is fixed in its own patch, with
> > a Fixes: tag, before the phonet conversion, so it can be backported alone.
> > 
> > The last patch adds getsockopt_iter selftest fixtures for rawv6,
> > ieee802154, phonet and tls, checking the returned length and errno across
> > exact, oversized and short buffers, an unknown optname and a bad level.
> > 
> > For full motivation about these changes, please check the initial thread
> > at link
> > https://lore.kernel.org/all/20260401-getsockopt-v2-0-611df6771aff@debian.org/#t
> > 
> > Signed-off-by: Breno Leitao <leitao@debian.org>
> > ---
> > Changes in v2:
> > - Replace min_t() by umin() (David)
> > - Link to v1: https://patch.msgid.link/20260716-getsockopt_phase4-v1-0-4f45cb12dce7@debian.org
> 
> Other than the nit I mentioned about min vs min_t on the one patch, it looks
> good overall to me, so for the series:

Thanks for the review, In fact, I'm using umin() rather than plain min()
on purpose: opt->optlen is a signed int and sizeof(int) is size_t, so
min() trips the signedness check unless the compiler can prove optlen >=
0.

I don't think min() is correct here, it would be min_t() or umin(),
I would say.

--thanks
breno

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2026-07-23 14:05 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-20 16:17 [PATCH net-next v2 0/7] net: convert rawv6, ieee802154, phonet and tls getsockopt to sockopt_t Breno Leitao
2026-07-20 16:17 ` [PATCH net-next v2 1/7] ipv6: raw: drop unused level argument from do_rawv6_getsockopt Breno Leitao
2026-07-20 16:17 ` [PATCH net-next v2 2/7] ipv6: raw: convert do_rawv6_getsockopt to sockopt_t Breno Leitao
2026-07-20 16:17 ` [PATCH net-next v2 3/7] ieee802154: convert dgram getsockopt " Breno Leitao
2026-07-22 13:40   ` Joe Damato
2026-07-20 16:17 ` [PATCH net-next v2 4/7] phonet: pep: do not write beyond optlen in getsockopt Breno Leitao
2026-07-20 16:17 ` [PATCH net-next v2 5/7] phonet: pep: convert getsockopt to sockopt_t Breno Leitao
2026-07-20 16:17 ` [PATCH net-next v2 6/7] tls: " Breno Leitao
2026-07-23  9:51   ` Sabrina Dubroca
2026-07-20 16:17 ` [PATCH net-next v2 7/7] selftests: net: getsockopt_iter: cover rawv6, ieee802154, phonet and tls Breno Leitao
2026-07-23 10:29   ` Sabrina Dubroca
2026-07-22 13:42 ` [PATCH net-next v2 0/7] net: convert rawv6, ieee802154, phonet and tls getsockopt to sockopt_t Joe Damato
2026-07-23 14:05   ` Breno Leitao

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox