Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH net v3 13/14] rxrpc: Fix CHALLENGE packet overqueuing and simplify RESPONSE generation
From: Simon Horman @ 2026-07-20 14:54 UTC (permalink / raw)
  To: dhowells
  Cc: Simon Horman, netdev, marc.dionne, kuba, davem, edumazet, pabeni,
	linux-afs, linux-kernel, stable
In-Reply-To: <20260713081022.2186481-14-dhowells@redhat.com>

This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
https://sashiko.dev/#/patchset/20260713081022.2186481-8-dhowells@redhat.com?part=13
---
--- Patch [13]: [PATCH net v3 13/14] rxrpc: Fix CHALLENGE packet overqueuing and simplify RESPONSE generation ---
commit ebc5bb53c96c167e2d7c2726bed42c09fd3a97d1
Author: David Howells <dhowells@redhat.com>

rxrpc: Fix CHALLENGE packet overqueuing and simplify RESPONSE generation

This commit removes the out-of-band queueing mechanism for rxrpc challenge
packets, moving instead to a preemptively supplied application data key.
The event processor now parses the challenge and generates the response
directly using this key.

Link: https://sashiko.dev/#/patchset/20260624163819.3017002-1-dhowells%40redhat.com

> --- a/net/rxrpc/recvmsg.c
> +++ b/net/rxrpc/recvmsg.c
> @@ -405,7 +405,7 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
>  
>  	trace_rxrpc_recvmsg(0, rxrpc_recvmsg_enter, 0);
>  
> -	if (flags & (MSG_OOB | MSG_TRUNC))
> +	if (flags & MSG_TRUNC)
>  		return -EOPNOTSUPP;

[Severity: Medium]
Does removing MSG_OOB from this check cause out-of-band requests to silently
fall through and return in-band data?

By not returning -EOPNOTSUPP for MSG_OOB, the socket might violate standard
semantics by returning regular data when the caller explicitly requested
out-of-band data.

> --- a/net/rxrpc/rxgk.c
> +++ b/net/rxrpc/rxgk.c
> @@ -936,7 +937,7 @@ static int rxgk_construct_response(struct rxrpc_connection *conn,
>  	if (IS_ERR(gk))
>  		return PTR_ERR(gk);
>  
> -	auth_len = 20 + (4 + appdata->len) + 12 + (1 + 4) * 4;
> +	auth_len = 20 + (4 + appdata->datalen) + 12 + (1 + 4) * 4;

[Severity: Critical]
Is auth_len calculated incorrectly here by missing the padding for
appdata->datalen?

It looks like this unpadded length is used to calculate authx_len, which
determines the size of the skb and the scatterlist allocation.

Later, rxgk_construct_authenticator() uses rxgk_pad_out() to correctly
round up the written bytes:

ret = rxgk_pad_out(response, appdata->datalen, offset);

Since the written padded size is larger than the unpadded alloc_len
passed to rxgk_encrypt_authenticator(), will this cause the crypto layer
to write past the end of the scatterlist and corrupt memory?

[ ... ]

> @@ -1011,24 +1012,36 @@ static int rxgk_construct_response(struct rxrpc_connection *conn,
>   * Respond to a challenge packet.
>   */
>  static int rxgk_respond_to_challenge(struct rxrpc_connection *conn,
> -				     struct sk_buff *challenge,
> -				     struct krb5_buffer *appdata)
> +				     struct sk_buff *challenge)
>  {
> -	_enter("{%d,%x}", conn->debug_id, key_serial(conn->key));
> +	struct user_key_payload dummy = {}, *appdata = &dummy;
> +	int ret;
> +
> +	_enter("{%d,%u,%x,%x}",
> +	       conn->debug_id, conn->service_id,
> +	       key_serial(conn->key), key_serial(conn->bundle->app_data));
>  
>  	if (key_validate(conn->key) < 0)
>  		return rxrpc_abort_conn(conn, NULL, RXGK_EXPIRED, -EPROTO,
>  					rxgk_abort_chall_key_expired);
>  
> -	return rxgk_construct_response(conn, challenge, appdata);
> -}
> +	if (conn->bundle->app_data) {
> +		rcu_read_lock();
> +		appdata = (struct user_key_payload *)
> +			user_key_payload_rcu(conn->bundle->app_data);
> +		if (appdata && !refcount_inc_not_zero(&appdata->ref))
> +			appdata = NULL;
> +		rcu_read_unlock();

[Severity: Critical]
Is it safe to blindly cast the payload of conn->bundle->app_data to
a struct user_key_payload here?

If a non-user key like a keyring or logon key was somehow attached to
the call, this cast will interpret the alien key payload as a
user_key_payload. For example, if rxrpc_sendmsg_cmsg() in
net/rxrpc/sendmsg.c has an inverted type check that inadvertently accepts
non-user keys:

if (key_ref_to_ptr(key)->type == &key_type_user) {
    key_ref_put(key);
    return -EINVAL;
}

Calling refcount_inc_not_zero() on a mismatched type could corrupt memory
by incrementing whatever happens to be at that offset. Furthermore, reading
the data length from this corrupted structure could leak arbitrary kernel
memory into the network via the response packet.

^ permalink raw reply

* Re: [PATCH net v3 12/14] rxrpc: Pass appdata key to rxrpc_call and thence to rxrpc_bundle
From: Simon Horman @ 2026-07-20 14:54 UTC (permalink / raw)
  To: dhowells
  Cc: Simon Horman, netdev, marc.dionne, kuba, davem, edumazet, pabeni,
	linux-afs, linux-kernel, stable
In-Reply-To: <20260713081022.2186481-13-dhowells@redhat.com>

This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
https://sashiko.dev/#/patchset/20260713081022.2186481-8-dhowells@redhat.com?part=12
---
--- Patch [12]: [PATCH net v3 12/14] rxrpc: Pass appdata key to rxrpc_call and thence to rxrpc_bundle ---
commit 6a78aabb95a0cb45b9da0216dba46c2925209a22
Author: David Howells <dhowells@redhat.com>

rxrpc: Pass appdata key to rxrpc_call and thence to rxrpc_bundle

Currently, when a CHALLENGE packet comes in, it's queued in an OOB queue on
the AF_RXRPC socket that generated one of the calls on that connection for
the application (which might be in userspace) to service. The application
then picks up the CHALLENGE and requests a RESPONSE packet be generated,
allowing the app to include app-specific data in it if appropriate.

Link: https://sashiko.dev/#/patchset/20260624163819.3017002-1-dhowells%40redhat.com

> diff --git a/net/rxrpc/conn_client.c b/net/rxrpc/conn_client.c
> index 48519f0de1853..5cbfa7b223e01 100644
> --- a/net/rxrpc/conn_client.c
> +++ b/net/rxrpc/conn_client.c
> @@ -81,6 +81,7 @@ static struct rxrpc_bundle *rxrpc_alloc_bundle(struct rxrpc_call *call,
>  		bundle->local		= call->local;
>  		bundle->peer		= rxrpc_get_peer(call->peer, rxrpc_peer_get_bundle);
>  		bundle->key		= key_get(call->key);
> +		bundle->app_data	= key_get(call->app_data);

[Severity: Medium]
Will this bundle lookup logic reuse stale app_data keys for new calls?

When rxrpc_look_up_bundle() compares connection parameters, it does not seem
to check bundle->app_data.

If a new call provides a different app_data key but otherwise identical
parameters, won't it match an existing bundle and inherit the previous call's
stale app_data instead of establishing a new connection bundle for the new
data?

>  		bundle->security	= call->security;
>  		bundle->exclusive	= test_bit(RXRPC_CALL_EXCLUSIVE, &call->flags);
>  		bundle->upgrade		= test_bit(RXRPC_CALL_UPGRADE, &call->flags);

[ ... ]

> diff --git a/net/rxrpc/sendmsg.c b/net/rxrpc/sendmsg.c
> index 71343998b87d1..cdf35440317d6 100644
> --- a/net/rxrpc/sendmsg.c
> +++ b/net/rxrpc/sendmsg.c
> @@ -614,6 +617,22 @@ static int rxrpc_sendmsg_cmsg(struct msghdr *msg, struct rxrpc_send_params *p)
>  				return -ERANGE;
>  			break;
>  
> +		case RXRPC_RESPONSE_APPDATA:
> +			if (len != sizeof(key_serial_t))
> +				return -EINVAL;
> +			if (p->call.app_data)
> +				return -EINVAL;
> +			key_id = *(key_serial_t *)CMSG_DATA(cmsg);
> +			key = lookup_user_key(key_id, 0, KEY_NEED_SEARCH);
> +			if (IS_ERR(key))
> +				return PTR_ERR(key);
> +			if (key_ref_to_ptr(key)->type == &key_type_user) {
> +				key_ref_put(key);
> +				return -EINVAL;
> +			}

[Severity: High]
Does this inverted check reject valid user keys and cause a regression with
memory parsing?

The user API expects a user key here for the RESPONSE app data. However,
if a local user sends an RXRPC_RESPONSE_APPDATA control message via sendmsg
and provides a valid user key, this check rejects it with -EINVAL.

Conversely, it accepts any non-user key.

When the subsystem later attempts to parse this key's payload, won't it assume
the memory layout of a user key payload, leading to out-of-bounds reads or
memory corruption?

> +			p->call.app_data = key_ref_to_ptr(key);
> +			break;
> +
>  		default:
>  			return -EINVAL;
>  		}

^ permalink raw reply

* Re: [PATCH net v3 11/14] afs: Create a server appdata key
From: Simon Horman @ 2026-07-20 14:53 UTC (permalink / raw)
  To: dhowells
  Cc: Simon Horman, netdev, marc.dionne, kuba, davem, edumazet, pabeni,
	linux-afs, linux-kernel, stable
In-Reply-To: <20260713081022.2186481-12-dhowells@redhat.com>

This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
https://sashiko.dev/#/patchset/20260713081022.2186481-8-dhowells@redhat.com?part=11
---
--- Patch [11]: [PATCH net v3 11/14] afs: Create a server appdata key ---
commit dc88fd6982b57fe321cbc39b2f060f5b1d06bb8e
Author: David Howells <dhowells@redhat.com>

afs: Create a server appdata key

This commit creates an appdata key for each fileserver the AFS filesystem
talks to with RxGK. It attaches the key to the afs_server record to be
used for generating application data in response to CHALLENGE packets.

Link: https://sashiko.dev/#/patchset/20260624163819.3017002-1-dhowells%40redhat.com

> diff --git a/fs/afs/cm_security.c b/fs/afs/cm_security.c
> index 103168c70dd4d..36907a04efd0b 100644
> --- a/fs/afs/cm_security.c
> +++ b/fs/afs/cm_security.c
[ ... ]
> @@ -23,6 +25,236 @@ static int afs_create_yfs_cm_token(struct sk_buff *challenge,
> +	/* struct RXGK_Token {
> +	 *	rxgk_key		K0;
> +	 *	RXGK_Level		level;
> +	 *	rxgkTime		starttime;
> +	 *	afs_int32		lifetime;
> +	 *	afs_int32		bytelife;
> +	 *	rxgkTime		expirationtime;
> +	 *	struct RXGK_AuthName	identities<>;
> +	 * };
> +	 */
> +	toksize = keysize + 8 + 4 + 4 + 8 + xdr_len_object(authsize);

[Severity: High]
Does this toksize calculation omit the 4 bytes required for the level field? 

It looks like the sizes added up correspond to starttime (8), lifetime (4),
bytelife (4), and expirationtime (8).

If the level field is omitted, toksize will be 4 bytes too small.

[ ... ]
> +	*xdr++ = htonl(RXRPC_SECURITY_ENCRYPT);	/* token.level */
> +	*xdr++ = htonl(0);			/* token.starttime */
> +	*xdr++ = htonl(0);			/* " */
> +	*xdr++ = htonl(0);			/* token.lifetime */
> +	*xdr++ = htonl(0);			/* token.bytelife */
> +	*xdr++ = htonl(0);			/* token.expirationtime */
> +	*xdr++ = htonl(0);			/* " */
[ ... ]
> +	xdr = encbase + xdr_round_up(encsize);
> +
> +	if ((unsigned long)xdr - (unsigned long)appdata != adatasize)
> +		pr_err("Appdata size incorrect %lx != %zx\n",
> +		       (unsigned long)xdr - (unsigned long)appdata, adatasize);

[Severity: High]
Can this manual advance of the xdr pointer hide the token size mismatch?

Because xdr is advanced based on the miscalculated encsize rather than the
actual number of fields written, it appears this will bypass the adatasize
sanity check on the next line.

[ ... ]
> +	ret = crypto_krb5_encrypt(token_krb5, aead, &sg, 1, encsize, offset, toksize, false);

[Severity: High]
Since toksize is smaller than the actual plaintext being constructed, will
this corrupt the token?

When crypto_krb5_encrypt() executes, it seems it will only process the
truncated toksize bytes of plaintext. This would leave the trailing 4 bytes
of the serialized XDR unencrypted and overwritten by the appended Kerberos
checksum. 

The fileserver would then reject the appdata token when XDR parsing fails.

^ permalink raw reply

* Re: [PATCH net v3 07/14] afs: Simplify call refcounting
From: Simon Horman @ 2026-07-20 14:52 UTC (permalink / raw)
  To: dhowells
  Cc: Simon Horman, netdev, marc.dionne, kuba, davem, edumazet, pabeni,
	linux-afs, linux-kernel, stable
In-Reply-To: <20260713081022.2186481-8-dhowells@redhat.com>

This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
https://sashiko.dev/#/patchset/20260713081022.2186481-8-dhowells@redhat.com?part=7
---
--- Patch [7]: [PATCH net v3 07/14] afs: Simplify call refcounting ---
commit 467b175328043584d311b0ca542f46ebdef122fe
Author: David Howells <dhowells@redhat.com>

afs: Simplify call refcounting

This commit simplifies afs_call refcounting by removing the ref held by queued
async work items and dropping the retaining ref upon async call completion
instead. It also dispatches cache manager server RPC handlers directly from
afs_deliver_to_call() and changes call->work to a function pointer.

> diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c
> index 06c711c75f556..a404b6f0cc7c2 100644
> --- a/fs/afs/rxrpc.c
> +++ b/fs/afs/rxrpc.c
[ ... ]
> @@ -479,8 +445,7 @@ void afs_make_call(struct afs_call *call, gfp_t gfp)
>  	if (call->rxcall)
>  		rxrpc_kernel_shutdown_call(call->net->socket, call->rxcall);
>  	if (call->async) {
> -		if (cancel_work_sync(&call->async_work))
> -			afs_put_call(call);
> +		cancel_work_sync(&call->async_work);
>  		afs_set_call_complete(call, ret, 0);
>  	}

[Severity: Medium]
Can this leak the struct afs_call object?

When rxrpc_kernel_begin_call() fails, the code jumps to error_kill_call and
cancels the async work here. Since afs_set_call_complete() no longer drops
call->drop_ref, and the async work function is cancelled (so it never runs to
drop the retaining ref), it seems the retaining ref acquired via afs_get_call()
earlier in afs_make_call() is never released on this error path.

[ ... ]
> @@ -704,19 +671,16 @@ static void afs_wake_up_async_call(struct sock *sk, struct rxrpc_call *rxcall,
>  				   unsigned long call_user_ID)
>  {
>  	struct afs_call *call = (struct afs_call *)call_user_ID;
> -	int r;
>  
>  	trace_afs_notify_call(rxcall, call);
>  	call->need_attention = true;
>  
> -	if (__refcount_inc_not_zero(&call->ref, &r)) {
> -		trace_afs_call(call->debug_id, afs_call_trace_wake, r + 1,
> -			       atomic_read(&call->net->nr_outstanding_calls),
> -			       __builtin_return_address(0));
> +	trace_afs_call(call->debug_id, afs_call_trace_wake,
> +		       refcount_read(&call->ref),
> +		       atomic_read(&call->net->nr_outstanding_calls),
> +		       __builtin_return_address(0));
>  
> -		if (!queue_work(afs_async_calls, &call->async_work))
> -			afs_deferred_put_call(call);
> -	}
> +	queue_work(afs_async_calls, &call->async_work);
>  }

[Severity: Critical]
Can this result in a use-after-free and workqueue corruption if an RxRPC
notification arrives right as the call completes?

afs_process_async_call() drops the final retaining reference and synchronously
frees the afs_call object when call->state == AFS_CALL_COMPLETE. If
afs_wake_up_async_call() is executed concurrently by the RxRPC thread before
rxrpc_kernel_shutdown_call() unhooks the callback, it will now blindly modify
call->need_attention and call queue_work() on a freed &call->async_work without
first acquiring a reference.

> diff --git a/fs/afs/file.c b/fs/afs/file.c
> index 0467742bfeee3..35d68f7f498df 100644
> --- a/fs/afs/file.c
> +++ b/fs/afs/file.c
[ ... ]
> @@ -316,15 +316,17 @@ void afs_fetch_data_async_rx(struct work_struct *work)
>  	struct afs_call *call = container_of(work, struct afs_call, async_work);
>  
>  	afs_read_receive(call);
> -	afs_put_call(call);
> +
> +	if (call->state == AFS_CALL_COMPLETE) {
> +		cancel_work(&call->async_work);
> +		afs_put_call(call);
> +	}
>  }
>  
>  void afs_fetch_data_immediate_cancel(struct afs_call *call)
>  {
>  	if (call->async) {
> -		afs_get_call(call, afs_call_trace_wake);
> -		if (!queue_work(afs_async_calls, &call->async_work))
> -			afs_deferred_put_call(call);
> +		queue_work(afs_async_calls, &call->async_work);
>  		flush_work(&call->async_work);
>  	}
>  }

[Severity: High]
This is a pre-existing issue, but does flushing the async work here cause a
NULL pointer dereference?

If afs_make_call() fails early (e.g. rxrpc_kernel_begin_call() fails),
call->rxcall is NULL. The error path calls call->type->immediate_cancel(call),
which resolves to afs_fetch_data_immediate_cancel(). This queues and
synchronously flushes the work.

afs_read_receive() is then executed while call->state is still less than
AFS_CALL_COMPLETE. This calls rxrpc_kernel_check_life() and passes it
call->rxcall:

fs/afs/file.c:afs_read_receive() {
	...
	if (state < AFS_CALL_COMPLETE) {
		netfs_read_subreq_progress(op->fetch.subreq);
		if (rxrpc_kernel_check_life(call->net->socket, call->rxcall))
			return;
	...
}

Because call->rxcall is NULL, wouldn't rxrpc_kernel_check_life()
unconditionally dereference it when calling rxrpc_call_is_complete(), causing
an immediate kernel panic?

^ permalink raw reply

* Re: [PATCH net v3 04/14] rxrpc: Fix packet encryption error handling
From: Simon Horman @ 2026-07-20 14:52 UTC (permalink / raw)
  To: dhowells
  Cc: Simon Horman, netdev, marc.dionne, kuba, davem, edumazet, pabeni,
	linux-afs, linux-kernel, stable
In-Reply-To: <20260713081022.2186481-5-dhowells@redhat.com>

This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
https://sashiko.dev/#/patchset/20260713081022.2186481-8-dhowells@redhat.com?part=4
---
--- Patch [4]: [PATCH net v3 04/14] rxrpc: Fix packet encryption error handling ---
commit 01fc73762a5a2162d360f4b9e10f752440ebbd67
Author: David Howells <dhowells@redhat.com>

rxrpc: Fix packet encryption error handling

This commit modifies the error handling in rxrpc_send_data() when
secure_packet() fails. It treats -ENOMEM as a retryable error and marks
other errors as terminal by setting the RXRPC_CALL_TX_ERROR flag to abort
the call.

Closes: https://sashiko.dev/#/patchset/20260702144919.172295-1-dhowells%40redhat.com

> diff --git a/net/rxrpc/sendmsg.c b/net/rxrpc/sendmsg.c
> --- a/net/rxrpc/sendmsg.c
> +++ b/net/rxrpc/sendmsg.c
[ ... ]
> @@ -440,12 +446,21 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
>  		/* add the packet to the send queue if it's now full */
>  		if (!txb->space ||
>  		    (msg_data_left(msg) == 0 && !more)) {
> -			if (msg_data_left(msg) == 0 && !more)
> -				txb->flags |= RXRPC_LAST_PACKET;
> -
> +			/* Do any required crypto.  If this fails, it could
> +			 * have corrupted the txbuf content with a partial
> +			 * encrypt.  Assume that ENOMEM is retryable, but
> +			 * everything else is terminal.
> +			 */
>  			ret = call->security->secure_packet(call, txb);
> -			if (ret < 0)
> +			if (ret < 0) {
> +				if (ret == -ENOMEM)
> +					goto maybe_error;

[Severity: High]
If secure_packet() fails with -ENOMEM, does this jump to maybe_error bypass
rxrpc_queue_packet() but still return a successful write length?

Looking at rxrpc_send_data(), the user data has already been copied into txb
and 'copied' has been incremented. The maybe_error path handles this:

maybe_error:
	if (copied) {
		...
		goto success;
	}

Because copied > 0, it jumps to success and returns the number of bytes
copied, including the data in the unqueued txb.

Could this mislead userspace into thinking the data was sent when it was
actually dropped, leaving the unencrypted packet permanently stuck in
call->tx_pending and leading to an application hang?

> +				set_bit(RXRPC_CALL_TX_ERROR, &call->flags);
>  				goto out;
> +			}
> +
> +			if (msg_data_left(msg) == 0 && !more)
> +				txb->flags |= RXRPC_LAST_PACKET;
>  			rxrpc_queue_packet(rx, call, txb, notify_end_tx);
>  			txb = NULL;
>  		}

^ permalink raw reply

* Re: [PATCH net] e1000e: Fix out-of-bounds MMIO access by validating BAR0 size
From: Andrew Lunn @ 2026-07-20 14:46 UTC (permalink / raw)
  To: Breno Leitao
  Cc: Pu Lehui, Tony Nguyen, Przemek Kitszel, Andrew Lunn,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	netdev, linux-kernel
In-Reply-To: <al4Z4_tFbyQM-ogu@gmail.com>

On Mon, Jul 20, 2026 at 05:53:37AM -0700, Breno Leitao wrote:
> On Mon, Jul 20, 2026 at 07:56:20PM +0800, Pu Lehui wrote:
> > 
> > On 2026/7/20 17:47, Breno Leitao wrote:
> > > On Wed, Jul 15, 2026 at 03:58:50AM +0000, Pu Lehui wrote:
> > > > +/* Minimum MMIO (BAR0) len, the largest offset is lower than 64K */
> > > 
> > > Why "the largest" in this case?
> > 
> > Hi Breno,
> > 
> > Thanks for pointing that out. I meant the maximum register offset accessed
> > by the driver.
> > 
> > IIUC, common e1000e NIC usually have a 128K BAR0. But since I'm not 100%
> > sure if older NIC might be smaller, I picked 64K as a safe lower limit
> > because it covers the largest register offset used in the driver's codebase.
> > If my assumption here is off, I'd really appreciate any corrections!
> > 
> > And for this comment, how about the follow?
> > /* Minimum MMIO (BAR0) length to safely cover the maximum register offset
> > accessed by the driver */
> 
> Thanks, Would something like this be a bit better?
> 
>      /* 
>       * Smallest BAR0 that covers every register the driver accesses
>       */

I would actually reference the highest register. It then becomes
exactly clear where this number comes from. Better still, use the
register #define in the test, along with this comment.

	 Andrew

^ permalink raw reply

* Re: [PATCH net 2/7] selftests: openvswitch: add config file
From: Aaron Conole @ 2026-07-20 14:43 UTC (permalink / raw)
  To: Matthieu Baerts
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Shuah Khan, netdev, linux-kselftest, linux-kernel,
	Eelco Chaudron, Ilya Maximets, dev
In-Reply-To: <a2032420-b4d4-4eba-9eb4-65eeeea2b63b@kernel.org>

Matthieu Baerts <matttbe@kernel.org> writes:

> Hi Aaron,
>
> Thank you for the review!
>
> On 16/07/2026 22:00, Aaron Conole wrote:
>> Aaron Conole <aconole@redhat.com> writes:
>>> "Matthieu Baerts (NGI0)" <matttbe@kernel.org> writes:
>>>
>>>> The kselftests doc mentions that a config file should be present "if a
>>>> test needs specific kernel config options enabled". This selftest
>>>> requires some kernel config, but no config file was provided.
>>>>
>>>> We could say that a sub-target could use the parent's config file, but
>>>> the kselftests doc doesn't mention anything about that. Plus the
>>>> net/openvswitch target is the only net target without a config file.
>>>
>>> We've been operating on that assumption from the openvswitch side, but
>>> it's true that isn't explicitly documented anywhere, and I guess it
>>> isn't officially supported in the kselftest framework.  I guess we'll
>>> need to keep updating this config as we add tests for things like SCTP,
>>> and others, and maybe that's a good thing like we can add a comment
>>> describing which tests take which configs.
>>>
>>> The downside is for most of the OVS testing we use the NIPA scripts
>>> and those 'inherit' the parent config, so it would be a change on our
>>> side from the development standpoint (but probably something we should
>>> have been doing from the beginning).
>>>
>>> That said, would it be worth also exploring the 'cascading
>>> configuration' support?  It seems like a useful feature, but maybe it
>>> should be a separate discussion.  I ask because of how OVS interacts
>>> with the networking stack as an 'alternative bridge' so-to-speak, I do
>>> worry about having to duplicate lots of configurations between the two
>>> as we expand the test coverage on OVS side.
>
> It is not clear to me what you are using on your side, but I guess it
> should be doable to modify some scripts to merge this new config file
> and the net one in your case.

This doesn't seem to break the NIPA case (at least I can see the
'contest test' output is not SKIP, but PASS for the openvswitch.sh).
I'm not sure about the suggestion to change the script in
tools/testing/selftests/net/openvswitch/openvswitch.sh to do a config
merge.  It isn't out-of-tree or anything, and seems like that would
create confusing git state (and not desirable from my end) - the
upstream test would leave a modified, tracked file.  Was that your
suggestion?  Or do you mean NIPA itself (but I think it already just
uses the top-level config).

The config change itself looks fine to me.

>>>> Here is a new config file, which is a trimmed version of the net one,
>>>> with hopefully the minimal required kconfig on top of 'make defconfig'.
>>>
>>> Should this also remove the OVS configs from the upper level since there
>>> shouldn't be OVS tests executing there (ie: CONFIG_OPENVSWITCH*)?
>> 
>> Actually, forget this part.  The P-MTU tests in pmtu.sh use ovs to
>> create a datapath through OVS.  So these configurations need to stay at
>> the top level as well.
>
> Indeed. I don't know these tests well, but maybe this P-MTU selftest
> should move to the net/openvswitch target?

Well, it is testing path MTU across multiple topologies, so it isn't
really an openvswitch specific test.  Just one that happens to use
openvswitch in one of the test cases.

> Cheers,
> Matt


^ permalink raw reply

* Re: [PATCH 7/8] net: mv643xx: use platform_device_set_fwnode()
From: Andrew Lunn @ 2026-07-20 14:43 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy (CS GROUP), Andi Shyti, Joerg Roedel (AMD),
	Will Deacon, Robin Murphy, Andy Shevchenko, Doug Berger,
	Florian Fainelli, Broadcom internal kernel review list,
	Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Ulf Hansson, Frank Li, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, Lee Jones,
	Sebastian Hesselbarth, Srinivas Kandagatla, brgl, driver-core,
	linuxppc-dev, linux-kernel, linux-i2c, iommu, netdev, linux-pm,
	imx, linux-arm-kernel, mfd, linux-arm-msm, linux-sound
In-Reply-To: <20260720-pdev-set-fwnode-instead-of-of-node-v1-7-2dee93f42c54@oss.qualcomm.com>

On Mon, Jul 20, 2026 at 11:24:54AM +0200, Bartosz Golaszewski wrote:
> Prefer the higher-level platform_device_set_fwnode() over the
> OF-specific platform_device_set_of_node() for dynamically allocated
> platform devices.
> 
> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
> ---
>  drivers/net/ethernet/marvell/mv643xx_eth.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
> index 9caa1e47c174c9d7a161b7f2e2ee12a829b813d4..2f2d6cce8d852b9ec3ab42678a04a7915d1f00cc 100644
> --- a/drivers/net/ethernet/marvell/mv643xx_eth.c
> +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
> @@ -2780,7 +2780,7 @@ static int mv643xx_eth_shared_of_add_port(struct platform_device *pdev,
>  		goto put_err;
>  	}
>  	ppdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
> -	platform_device_set_of_node(ppdev, pnp);
> +	platform_device_set_fwnode(ppdev, of_fwnode_handle(pnp));

This is definitely an OF only driver. There are no other calls to
fwnode functions in this driver, so this is the wrong thing to do.

Sorry, NACK.

       Andrew

^ permalink raw reply

* [PATCH net 6/6] ovpn: use monotonic clock for peer keepalive timeouts
From: Antonio Quartulli @ 2026-07-20 14:41 UTC (permalink / raw)
  To: netdev
  Cc: Sabrina Dubroca, Jakub Kicinski, Paolo Abeni, David S. Miller,
	Eric Dumazet, Andrew Lunn, Ralf Lici, Marco Baffo,
	Antonio Quartulli
In-Reply-To: <20260720144131.3657121-1-antonio@openvpn.net>

From: Marco Baffo <marco@mandelbit.com>

Replace ktime_get_real_seconds() with the monotonic
ktime_get_boottime_seconds() to ensure the keepalive mechanism is robust
against system clock modifications.

Right now, the driver uses ktime_get_real_seconds() to track peer
timeouts, relying on the system wall-clock.

An administrative time adjustment or an NTP sync that steps the clock
forward can cause `now' to instantly exceed `last_recv + timeout'.

When this occurs, the driver artificially expires healthy peers.
Depending on the OpenVPN user-space configuration, this triggers a
premature tunnel restart (if --keepalive or --ping-restart is used) or
a complete disconnection of the client (if --ping-exit is used).

Fixes: 3ecfd9349f40 ("ovpn: implement keepalive mechanism")
Signed-off-by: Marco Baffo <marco@mandelbit.com>
Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
---
 drivers/net/ovpn/io.c   | 4 ++--
 drivers/net/ovpn/peer.c | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ovpn/io.c b/drivers/net/ovpn/io.c
index a6b777a9c2d9..9a66d693039a 100644
--- a/drivers/net/ovpn/io.c
+++ b/drivers/net/ovpn/io.c
@@ -142,7 +142,7 @@ void ovpn_decrypt_post(void *data, int ret)
 	}
 
 	/* keep track of last received authenticated packet for keepalive */
-	WRITE_ONCE(peer->last_recv, ktime_get_real_seconds());
+	WRITE_ONCE(peer->last_recv, ktime_get_boottime_seconds());
 
 	rcu_read_lock();
 	sock = rcu_dereference(peer->sock);
@@ -294,7 +294,7 @@ void ovpn_encrypt_post(void *data, int ret)
 
 	ovpn_peer_stats_increment_tx(&peer->link_stats, orig_len);
 	/* keep track of last sent packet for keepalive */
-	WRITE_ONCE(peer->last_sent, ktime_get_real_seconds());
+	WRITE_ONCE(peer->last_sent, ktime_get_boottime_seconds());
 	/* skb passed down the stack - don't free it */
 	skb = NULL;
 err_unlock:
diff --git a/drivers/net/ovpn/peer.c b/drivers/net/ovpn/peer.c
index 8fdbb5050690..a21d02ac715e 100644
--- a/drivers/net/ovpn/peer.c
+++ b/drivers/net/ovpn/peer.c
@@ -45,7 +45,7 @@ static void unlock_ovpn(struct ovpn_priv *ovpn,
  */
 void ovpn_peer_keepalive_set(struct ovpn_peer *peer, u32 interval, u32 timeout)
 {
-	time64_t now = ktime_get_real_seconds();
+	time64_t now = ktime_get_boottime_seconds();
 
 	netdev_dbg(peer->ovpn->dev,
 		   "scheduling keepalive for peer %u: interval=%u timeout=%u\n",
@@ -1359,7 +1359,7 @@ void ovpn_peer_keepalive_work(struct work_struct *work)
 {
 	struct ovpn_priv *ovpn = container_of(work, struct ovpn_priv,
 					      keepalive_work.work);
-	time64_t next_run = 0, now = ktime_get_real_seconds();
+	time64_t next_run = 0, now = ktime_get_boottime_seconds();
 	LLIST_HEAD(release_list);
 
 	spin_lock_bh(&ovpn->lock);
-- 
2.54.0


^ permalink raw reply related

* [PATCH net 5/6] ovpn: fix use after free in unlock_ovpn()
From: Antonio Quartulli @ 2026-07-20 14:41 UTC (permalink / raw)
  To: netdev
  Cc: Sabrina Dubroca, Jakub Kicinski, Paolo Abeni, David S. Miller,
	Eric Dumazet, Andrew Lunn, Ralf Lici, Marco Baffo,
	Antonio Quartulli
In-Reply-To: <20260720144131.3657121-1-antonio@openvpn.net>

From: Marco Baffo <marco@mandelbit.com>

unlock_ovpn() iterates over the release_list using llist_for_each_entry()
and drops the peer reference inside the loop body via ovpn_peer_put().

If this drops the last reference, the peer is eventually freed. However,
llist_for_each_entry() reads peer->release_entry.next in the loop advance
expression, which runs after the body. By that time the peer may have
already been freed, resulting in a use after free when advancing to the
next list entry.

Fix this by using llist_for_each_entry_safe(), which caches the next
pointer before executing the loop body.

Fixes: 80747caef33d ("ovpn: introduce the ovpn_peer object")
Signed-off-by: Marco Baffo <marco@mandelbit.com>
Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
---
 drivers/net/ovpn/peer.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ovpn/peer.c b/drivers/net/ovpn/peer.c
index 2b6096d8b1cc..8fdbb5050690 100644
--- a/drivers/net/ovpn/peer.c
+++ b/drivers/net/ovpn/peer.c
@@ -26,11 +26,12 @@ static void unlock_ovpn(struct ovpn_priv *ovpn,
 			 struct llist_head *release_list)
 	__releases(&ovpn->lock)
 {
-	struct ovpn_peer *peer;
+	struct ovpn_peer *peer, *next;
 
 	spin_unlock_bh(&ovpn->lock);
 
-	llist_for_each_entry(peer, release_list->first, release_entry) {
+	llist_for_each_entry_safe(peer, next, release_list->first,
+				  release_entry) {
 		ovpn_socket_release(peer);
 		ovpn_peer_put(peer);
 	}
-- 
2.54.0


^ permalink raw reply related

* [PATCH net 4/6] selftests/net: ovpn: fix getaddrinfo memory leak in ovpn_parse_remote()
From: Antonio Quartulli @ 2026-07-20 14:41 UTC (permalink / raw)
  To: netdev
  Cc: Sabrina Dubroca, Jakub Kicinski, Paolo Abeni, David S. Miller,
	Eric Dumazet, Andrew Lunn, Ralf Lici, longlong yan,
	Antonio Quartulli
In-Reply-To: <20260720144131.3657121-1-antonio@openvpn.net>

From: longlong yan <yanlonglong@kylinos.cn>

The ovpn_parse_remote() function has two memory management issues:

1. When both 'host' and 'vpnip' are non-NULL, the first getaddrinfo()
   allocation is leaked because 'result' is overwritten by the second
   getaddrinfo() call without freeing the first allocation.

2. When both 'host' and 'vpnip' are NULL, 'result' is an uninitialized
   stack variable passed to freeaddrinfo(), which is undefined behavior.

Fix by initializing 'result' to NULL and calling freeaddrinfo() after
the first getaddrinfo() result is consumed.

Fixes: 959bc330a439 ("testing/selftests: add test tool and scripts for ovpn module")
Signed-off-by: longlong yan <yanlonglong@kylinos.cn>
Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
---
 tools/testing/selftests/net/ovpn/ovpn-cli.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/net/ovpn/ovpn-cli.c b/tools/testing/selftests/net/ovpn/ovpn-cli.c
index d40953375c86..f4effa7580c0 100644
--- a/tools/testing/selftests/net/ovpn/ovpn-cli.c
+++ b/tools/testing/selftests/net/ovpn/ovpn-cli.c
@@ -1785,7 +1785,7 @@ static int ovpn_parse_remote(struct ovpn_ctx *ovpn, const char *host,
 			     const char *service, const char *vpnip)
 {
 	int ret;
-	struct addrinfo *result;
+	struct addrinfo *result = NULL;
 	struct addrinfo hints = {
 		.ai_family = ovpn->sa_family,
 		.ai_socktype = SOCK_DGRAM,
@@ -1809,6 +1809,8 @@ static int ovpn_parse_remote(struct ovpn_ctx *ovpn, const char *host,
 		}
 
 		memcpy(&ovpn->remote, result->ai_addr, result->ai_addrlen);
+		freeaddrinfo(result);
+		result = NULL;
 	}
 
 	if (vpnip) {
-- 
2.54.0


^ permalink raw reply related

* [PATCH net 3/6] ovpn: hold peer before scheduling keepalive work
From: Antonio Quartulli @ 2026-07-20 14:41 UTC (permalink / raw)
  To: netdev
  Cc: Sabrina Dubroca, Jakub Kicinski, Paolo Abeni, David S. Miller,
	Eric Dumazet, Andrew Lunn, Ralf Lici, Shuvam Pandey, stable,
	Antonio Quartulli
In-Reply-To: <20260720144131.3657121-1-antonio@openvpn.net>

From: Shuvam Pandey <shuvampandey1@gmail.com>

ovpn_peer_keepalive_send() passes its peer reference to
ovpn_xmit_special(), which ultimately drops it. The keepalive scheduler
currently queues the work first and takes the reference only after
schedule_work() reports that the work was queued.

Once schedule_work() queues the item, another CPU may run the worker
before the caller gets to ovpn_peer_hold(). In that case the worker can
consume a reference that was not acquired for it, corrupting the peer
lifetime accounting.

Take the peer reference before queueing the work and drop it again when
the work was already pending.

Fixes: 3ecfd9349f40 ("ovpn: implement keepalive mechanism")
Cc: stable@vger.kernel.org
Signed-off-by: Shuvam Pandey <shuvampandey1@gmail.com>
Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
---
 drivers/net/ovpn/peer.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ovpn/peer.c b/drivers/net/ovpn/peer.c
index 1844d97154ce..2b6096d8b1cc 100644
--- a/drivers/net/ovpn/peer.c
+++ b/drivers/net/ovpn/peer.c
@@ -1284,8 +1284,10 @@ static time64_t ovpn_peer_keepalive_work_single(struct ovpn_peer *peer,
 		netdev_dbg(peer->ovpn->dev,
 			   "sending keepalive to peer %u\n",
 			   peer->id);
-		if (schedule_work(&peer->keepalive_work))
-			ovpn_peer_hold(peer);
+		if (WARN_ON(!ovpn_peer_hold(peer)))
+			return 0;
+		if (!schedule_work(&peer->keepalive_work))
+			ovpn_peer_put(peer);
 	}
 
 	if (next_run1 < next_run2)
-- 
2.54.0


^ permalink raw reply related

* [PATCH net 2/6] ovpn: fix peer refcount leak in TCP error paths
From: Antonio Quartulli @ 2026-07-20 14:41 UTC (permalink / raw)
  To: netdev
  Cc: Sabrina Dubroca, Jakub Kicinski, Paolo Abeni, David S. Miller,
	Eric Dumazet, Andrew Lunn, Ralf Lici, Pavitra Jha, stable,
	Antonio Quartulli
In-Reply-To: <20260720144131.3657121-1-antonio@openvpn.net>

From: Pavitra Jha <jhapavitra98@gmail.com>

When either the TCP RX or TX error path calls ovpn_peer_hold() followed
by schedule_work(&peer->tcp.defer_del_work), and the work item is already
pending from the other path, schedule_work() returns false and the work
runs only once. Since ovpn_tcp_peer_del_work() calls ovpn_peer_put()
exactly once, the extra reference taken by the losing path is never
dropped, leaking the peer object.

The race window:

  CPU0 (strparser/RX error):       CPU1 (tcp_tx_work/TX error):
  ovpn_peer_hold()   <- refcnt+1   ovpn_peer_hold()   <- refcnt+2
  schedule_work()    <- queued      schedule_work()    <- NO-OP
                                    (work already pending)
  ovpn_tcp_peer_del_work runs:
    ovpn_peer_del()
    ovpn_peer_put()  <- refcnt+1
                                   <- peer never freed

Fix by checking the return value of schedule_work() in both paths and
calling ovpn_peer_put() to drop the extra reference if the work was
already pending. ovpn_peer_hold() is kept unconditional in the TX path
as it cannot fail at that point.

Fixes: a6a5e87b3ee4 ("ovpn: avoid sleep in atomic context in TCP RX error path")
Cc: stable@vger.kernel.org
Signed-off-by: Pavitra Jha <jhapavitra98@gmail.com>
Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
---
 drivers/net/ovpn/tcp.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ovpn/tcp.c b/drivers/net/ovpn/tcp.c
index 433bd07a4f1b..0af14055c39a 100644
--- a/drivers/net/ovpn/tcp.c
+++ b/drivers/net/ovpn/tcp.c
@@ -151,7 +151,8 @@ static void ovpn_tcp_rcv(struct strparser *strp, struct sk_buff *skb)
 	/* take reference for deferred peer deletion. should never fail */
 	if (WARN_ON(!ovpn_peer_hold(peer)))
 		goto err_nopeer;
-	schedule_work(&peer->tcp.defer_del_work);
+	if (!schedule_work(&peer->tcp.defer_del_work))
+		ovpn_peer_put(peer);
 	ovpn_dev_dstats_rx_dropped(peer->ovpn->dev);
 err_nopeer:
 	kfree_skb(skb);
@@ -283,7 +284,8 @@ static void ovpn_tcp_send_sock(struct ovpn_peer *peer, struct sock *sk)
 			 * stream therefore we abort the connection
 			 */
 			ovpn_peer_hold(peer);
-			schedule_work(&peer->tcp.defer_del_work);
+			if (!schedule_work(&peer->tcp.defer_del_work))
+				ovpn_peer_put(peer);
 
 			/* we bail out immediately and keep tx_in_progress set
 			 * to true. This way we prevent more TX attempts
-- 
2.54.0


^ permalink raw reply related

* [PATCH net 1/6] ovpn: avoid putting unrelated P2P peer on socket release
From: Antonio Quartulli @ 2026-07-20 14:41 UTC (permalink / raw)
  To: netdev
  Cc: Sabrina Dubroca, Jakub Kicinski, Paolo Abeni, David S. Miller,
	Eric Dumazet, Andrew Lunn, Ralf Lici, Qing Ming, Simon Horman,
	Antonio Quartulli
In-Reply-To: <20260720144131.3657121-1-antonio@openvpn.net>

From: Qing Ming <a0yami@mailbox.org>

ovpn_peer_release_p2p() is called when an OVPN UDP socket is being
destroyed. It checks the currently published P2P peer and releases it only
if that peer still uses the socket being destroyed.

A peer replacement can publish a new peer before the old UDP socket is
destroyed. When the old socket destruction path runs afterwards,
ovpn_peer_release_p2p() observes the new peer through ovpn->peer. Since the
new peer uses a different socket, the function takes the socket mismatch
branch.

That branch still calls ovpn_peer_put(peer). At this point, however, peer
is the currently published replacement peer, not the peer associated with
the socket being destroyed. Dropping its reference can free it while
ovpn->peer still points to it, leading to later use-after-free accesses
from the peer and socket cleanup paths.

KASAN reports this as a slab-use-after-free on the kmalloc-1k ovpn_peer
object. In the reproducer, the object is allocated from ovpn_peer_new() via
ovpn_nl_peer_new_doit(), and freed through ovpn_peer_release_rcu() from RCU
callback processing. Observed access sites include ovpn_peer_remove(),
ovpn_socket_release(), ovpn_nl_peer_del_notify(), and unlock_ovpn().

Fix this by returning from the socket mismatch branch without putting the
peer.

Fixes: f6226ae7a0cd ("ovpn: introduce the ovpn_socket object")
Signed-off-by: Qing Ming <a0yami@mailbox.org>
Reviewed-by: Simon Horman <horms@kernel.org>
Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
---
 drivers/net/ovpn/peer.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/net/ovpn/peer.c b/drivers/net/ovpn/peer.c
index a09d61296425..1844d97154ce 100644
--- a/drivers/net/ovpn/peer.c
+++ b/drivers/net/ovpn/peer.c
@@ -1167,7 +1167,6 @@ static void ovpn_peer_release_p2p(struct ovpn_priv *ovpn, struct sock *sk,
 		ovpn_sock = rcu_access_pointer(peer->sock);
 		if (!ovpn_sock || ovpn_sock->sk != sk) {
 			spin_unlock_bh(&ovpn->lock);
-			ovpn_peer_put(peer);
 			return;
 		}
 	}
-- 
2.54.0


^ permalink raw reply related

* [PATCH net 0/6] pull request: fixes for ovpn 2026-07-20
From: Antonio Quartulli @ 2026-07-20 14:41 UTC (permalink / raw)
  To: netdev
  Cc: Sabrina Dubroca, Jakub Kicinski, Paolo Abeni, David S. Miller,
	Eric Dumazet, Andrew Lunn, Ralf Lici, Antonio Quartulli

Hi all!

This is a resend of the series of small fixes I sent on 2026-06-08,
now rebased on top of the latest net/main.

Changes compared to the previous submission are the addition of the
committer Signed-off-by tags that were missing on two patches (as
flagged by the SoB checker) and the amending of the commit message
about the new clock function being used for keepalive tracking.
No code was changed.

There are larger fixes in our queue which we are still working on,
therefore please ignore any "previous issue" Sashiko may report.

Please pull or let me know of any issue!

Thanks a lot,
	Antonio


The following changes since commit e13caf1c26587434f0b768193100440939c0fb91:

  Merge tag 'net-7.2-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net (2026-07-17 10:25:13 -0700)

are available in the Git repository at:

  https://github.com/OpenVPN/ovpn-net-next.git ovpn-net-20260720

for you to fetch changes up to f7e6287ccd3abeed9e638b581dc3fdf742106ba3:

  ovpn: use monotonic clock for peer keepalive timeouts (2026-07-20 16:29:31 +0200)

----------------------------------------------------------------
Included fixes:
* ensure keepalive timestamps are computed using monotonic source
* avoid UAF in unlock_ovpn() when iterating over release_list
* fix memleak in selftest tool
* ensure reference to peer is acquired before scheduling worker
  (which may drop the not-yet-taken ref)
* fix refcount leak in case of concurrent TX and RX TCP error
* fix potential refcount unbalance in case of sock release in
  P2P mode

----------------------------------------------------------------
Marco Baffo (2):
      ovpn: fix use after free in unlock_ovpn()
      ovpn: use monotonic clock for peer keepalive timeouts

Pavitra Jha (1):
      ovpn: fix peer refcount leak in TCP error paths

Qing Ming (1):
      ovpn: avoid putting unrelated P2P peer on socket release

Shuvam Pandey (1):
      ovpn: hold peer before scheduling keepalive work

longlong yan (1):
      selftests/net: ovpn: fix getaddrinfo memory leak in ovpn_parse_remote()

 drivers/net/ovpn/io.c                       |  4 ++--
 drivers/net/ovpn/peer.c                     | 16 +++++++++-------
 drivers/net/ovpn/tcp.c                      |  6 ++++--
 tools/testing/selftests/net/ovpn/ovpn-cli.c |  4 +++-
 4 files changed, 18 insertions(+), 12 deletions(-)

^ permalink raw reply

* [PATCH net-next v2] net: Replace %pK output with 0
From: Sebastian Andrzej Siewior @ 2026-07-20 14:40 UTC (permalink / raw)
  To: linux-atm-general, linux-can, linux-sctp, netdev
  Cc: David S. Miller, Eric Dumazet, Herbert Xu, Jakub Kicinski,
	Kuniyuki Iwashima, Marc Kleine-Budde, Marcelo Ricardo Leitner,
	Neal Cardwell, Oliver Hartkopp, Paolo Abeni, Remi Denis-Courmont,
	Simon Horman, Steffen Klassert, Willem de Bruijn, Xin Long,
	Petr Mladek, Thomas Weißschuh, Kees Cook

Commit 71338aa7d050c ("net: convert %p usage to %pK") which is from
2011 and changed the %p annotation for pointer to %pK. Back then the
default behaviour for %p was to print the pointer. The %pK modifier was
introduced to able to control the behaviour of specific pointer values
without changing the behaviour of %p for everyone. It was dedicated to
avoid leaking pointers via /proc.

There was also the idea to remove the check from formatting the string
and move to the open callback with some helpers but this did not happen.

Things changed over time. The default behaviour for %p is now to print a
hash pointer which does not leak the address but allows to correlate if
two pointers are equal.
The policy on %p is to not introduce new ones. This is somehow in
between since it already exists. The pointer are usually socket pointers
and I don't see any value in exposing them. Therefore I am following the
recommendation of removing them. Since their usage in /proc/ can be
considered ABI I replace the pointer with a 0.

Replace the %pK annotation with 0 value. Correct the spacing for the
cases where pointer is at the beginning. Use %ps in CAN where the read
callback is used.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---

v1…v2: https://lore.kernel.org/all/20260706073824.xixrLxoD@linutronix.de
 - This follows Kees' feedback regarding the general policy and "is it
   really needed?". Since I don't think that this is of general usage I
   replaced them all with 0 and corrected the spacing at the beginning.

 - can_print_rcvlist() is now using a %ps to print the name of the
   function. Everything is a sock pointer (or some other data structure)
   and is now 0.

 net/atm/proc.c           |  7 +++----
 net/can/bcm.c            |  4 +---
 net/can/proc.c           | 12 ++++--------
 net/ipv4/ping.c          |  5 ++---
 net/ipv4/raw.c           |  4 ++--
 net/ipv4/tcp_ipv4.c      | 13 ++++++-------
 net/ipv4/udp.c           |  5 ++---
 net/ipv6/datagram.c      |  5 ++---
 net/ipv6/tcp_ipv6.c      | 12 ++++++------
 net/key/af_key.c         |  5 ++---
 net/netlink/af_netlink.c |  5 ++---
 net/packet/af_packet.c   |  6 ++----
 net/phonet/socket.c      |  5 ++---
 net/sctp/proc.c          |  6 +++---
 net/unix/af_unix.c       |  5 ++---
 15 files changed, 41 insertions(+), 58 deletions(-)

diff --git a/net/atm/proc.c b/net/atm/proc.c
index 8f20b49b9c02a..4db7036ba8e72 100644
--- a/net/atm/proc.c
+++ b/net/atm/proc.c
@@ -159,7 +159,7 @@ static void vcc_info(struct seq_file *seq, struct atm_vcc *vcc)
 {
 	struct sock *sk = sk_atm(vcc);
 
-	seq_printf(seq, "%pK ", vcc);
+	seq_printf(seq, "      0 ");
 	if (!vcc->dev)
 		seq_printf(seq, "Unassigned    ");
 	else
@@ -228,9 +228,8 @@ static const struct seq_operations pvc_seq_ops = {
 static int vcc_seq_show(struct seq_file *seq, void *v)
 {
 	if (v == SEQ_START_TOKEN) {
-		seq_printf(seq, sizeof(void *) == 4 ? "%-8s%s" : "%-16s%s",
-			"Address ", "Itf VPI VCI   Fam Flags Reply "
-			"Send buffer     Recv buffer      [refcnt]\n");
+		seq_printf(seq, "Address Itf VPI VCI   Fam Flags Reply "
+			   "Send buffer     Recv buffer     [refcnt]\n");
 	} else {
 		struct vcc_state *state = seq->private;
 		struct atm_vcc *vcc = atm_sk(state->sk);
diff --git a/net/can/bcm.c b/net/can/bcm.c
index 3d637a1e0ac1a..c262d9530f553 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -220,9 +220,7 @@ static int bcm_proc_show(struct seq_file *m, void *v)
 	struct bcm_sock *bo = bcm_sk(sk);
 	struct bcm_op *op;
 
-	seq_printf(m, ">>> socket %pK", sk->sk_socket);
-	seq_printf(m, " / sk %pK", sk);
-	seq_printf(m, " / bo %pK", bo);
+	seq_printf(m, ">>> socket 0 / sk 0 / bo 0");
 	seq_printf(m, " / dropped %lu", bo->dropped_usr_msgs);
 	seq_printf(m, " / bound %s", bcm_proc_getifname(net, ifname, bo->ifindex));
 	seq_printf(m, " <<<\n");
diff --git a/net/can/proc.c b/net/can/proc.c
index de4d05ae34597..cc3050f4c8e75 100644
--- a/net/can/proc.c
+++ b/net/can/proc.c
@@ -192,12 +192,11 @@ static void can_print_rcvlist(struct seq_file *m, struct hlist_head *rx_list,
 
 	hlist_for_each_entry_rcu(r, rx_list, list) {
 		char *fmt = (r->can_id & CAN_EFF_FLAG)?
-			"   %-5s  %08x  %08x  %pK  %pK  %8ld  %s\n" :
-			"   %-5s     %03x    %08x  %pK  %pK  %8ld  %s\n";
+			"   %-5s  %08x  %08x  %ps %8u %8ld  %s\n" :
+			"   %-5s     %03x    %08x  %-20ps %8u %8ld  %s\n";
 
 		seq_printf(m, fmt, DNAME(dev), r->can_id, r->mask,
-			   r->func, r->data, atomic_long_read(&r->matches),
-			   r->ident);
+			   r->func, 0, atomic_long_read(&r->matches), r->ident);
 	}
 }
 
@@ -207,10 +206,7 @@ static void can_print_recv_banner(struct seq_file *m)
 	 *                  can1.  00000000  00000000  00000000
 	 *                 .......          0  tp20
 	 */
-	if (IS_ENABLED(CONFIG_64BIT))
-		seq_puts(m, "  device   can_id   can_mask      function          userdata       matches  ident\n");
-	else
-		seq_puts(m, "  device   can_id   can_mask  function  userdata   matches  ident\n");
+	seq_puts(m, "  device   can_id   can_mask  function             userdata  matches  ident\n");
 }
 
 static int can_stats_proc_show(struct seq_file *m, void *v)
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
index d36f1e273fde4..223a0108b74cc 100644
--- a/net/ipv4/ping.c
+++ b/net/ipv4/ping.c
@@ -1095,15 +1095,14 @@ static void ping_v4_format_sock(struct sock *sp, struct seq_file *f,
 	__u16 srcp = ntohs(inet->inet_sport);
 
 	seq_printf(f, "%5d: %08X:%04X %08X:%04X"
-		" %02X %08X:%08X %02X:%08lX %08X %5u %8d %llu %d %pK %u",
+		" %02X %08X:%08X %02X:%08lX %08X %5u %8d %llu %d 0 %u",
 		bucket, src, srcp, dest, destp, sp->sk_state,
 		sk_wmem_alloc_get(sp),
 		sk_rmem_alloc_get(sp),
 		0, 0L, 0,
 		from_kuid_munged(seq_user_ns(f), sk_uid(sp)),
 		0, sock_i_ino(sp),
-		refcount_read(&sp->sk_refcnt), sp,
-		sk_drops_read(sp));
+		refcount_read(&sp->sk_refcnt), sk_drops_read(sp));
 }
 
 static int ping_v4_seq_show(struct seq_file *seq, void *v)
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 2aebaf8297e04..0a3e561f670bd 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -1045,14 +1045,14 @@ static void raw_sock_seq_show(struct seq_file *seq, struct sock *sp, int i)
 	      srcp  = inet->inet_num;
 
 	seq_printf(seq, "%4d: %08X:%04X %08X:%04X"
-		" %02X %08X:%08X %02X:%08lX %08X %5u %8d %llu %d %pK %u\n",
+		" %02X %08X:%08X %02X:%08lX %08X %5u %8d %llu %d 0 %u\n",
 		i, src, srcp, dest, destp, sp->sk_state,
 		sk_wmem_alloc_get(sp),
 		sk_rmem_alloc_get(sp),
 		0, 0L, 0,
 		from_kuid_munged(seq_user_ns(seq), sk_uid(sp)),
 		0, sock_i_ino(sp),
-		refcount_read(&sp->sk_refcnt), sp, sk_drops_read(sp));
+		refcount_read(&sp->sk_refcnt), sk_drops_read(sp));
 }
 
 static int raw_seq_show(struct seq_file *seq, void *v)
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 4a46da375043b..3a0ce1743642a 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -2745,7 +2745,7 @@ static void get_openreq4(const struct request_sock *req,
 	long delta = req->rsk_timer.expires - jiffies;
 
 	seq_printf(f, "%4d: %08X:%04X %08X:%04X"
-		" %02X %08X:%08X %02X:%08lX %08X %5u %8d %u %d %pK",
+		" %02X %08X:%08X %02X:%08lX %08X %5u %8d %u %d 0",
 		i,
 		ireq->ir_loc_addr,
 		ireq->ir_num,
@@ -2760,8 +2760,7 @@ static void get_openreq4(const struct request_sock *req,
 				 sk_uid(req->rsk_listener)),
 		0,  /* non standard timer */
 		0, /* open_requests have no inode */
-		0,
-		req);
+		0);
 }
 
 static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i)
@@ -2808,7 +2807,7 @@ static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i)
 				      READ_ONCE(tp->copied_seq), 0);
 
 	seq_printf(f, "%4d: %08X:%04X %08X:%04X %02X %08X:%08X %02X:%08lX "
-			"%08X %5u %8d %llu %d %pK %lu %lu %u %u %d",
+			"%08X %5u %8d %llu %d 0 %lu %lu %u %u %d",
 		i, src, srcp, dest, destp, state,
 		READ_ONCE(tp->write_seq) - tp->snd_una,
 		rx_queue,
@@ -2818,7 +2817,7 @@ static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i)
 		from_kuid_munged(seq_user_ns(f), sk_uid(sk)),
 		READ_ONCE(icsk->icsk_probes_out),
 		sock_i_ino(sk),
-		refcount_read(&sk->sk_refcnt), sk,
+		refcount_read(&sk->sk_refcnt),
 		jiffies_to_clock_t(icsk->icsk_rto),
 		jiffies_to_clock_t(icsk->icsk_ack.ato),
 		(icsk->icsk_ack.quick << 1) | inet_csk_in_pingpong_mode(sk),
@@ -2841,10 +2840,10 @@ static void get_timewait4_sock(const struct inet_timewait_sock *tw,
 	srcp  = ntohs(tw->tw_sport);
 
 	seq_printf(f, "%4d: %08X:%04X %08X:%04X"
-		" %02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %pK",
+		" %02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d 0",
 		i, src, srcp, dest, destp, READ_ONCE(tw->tw_substate), 0, 0,
 		3, jiffies_delta_to_clock_t(delta), 0, 0, 0, 0,
-		refcount_read(&tw->tw_refcnt), tw);
+		refcount_read(&tw->tw_refcnt));
 }
 
 #define TMPSZ 150
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 59248a59358ca..b35e448e48c59 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -3280,15 +3280,14 @@ static void udp4_format_sock(struct sock *sp, struct seq_file *f,
 	__u16 srcp	  = ntohs(inet->inet_sport);
 
 	seq_printf(f, "%5d: %08X:%04X %08X:%04X"
-		" %02X %08X:%08X %02X:%08lX %08X %5u %8d %llu %d %pK %u",
+		" %02X %08X:%08X %02X:%08lX %08X %5u %8d %llu %d 0 %u",
 		bucket, src, srcp, dest, destp, sp->sk_state,
 		sk_wmem_alloc_get(sp),
 		udp_rqueue_get(sp),
 		0, 0L, 0,
 		from_kuid_munged(seq_user_ns(f), sk_uid(sp)),
 		0, sock_i_ino(sp),
-		refcount_read(&sp->sk_refcnt), sp,
-		sk_drops_read(sp));
+		refcount_read(&sp->sk_refcnt), sk_drops_read(sp));
 }
 
 static int udp4_seq_show(struct seq_file *seq, void *v)
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 38d7b48452817..191c9733ff9fa 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -1102,7 +1102,7 @@ void __ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp,
 	src   = &sp->sk_v6_rcv_saddr;
 	seq_printf(seq,
 		   "%5d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
-		   "%02X %08X:%08X %02X:%08lX %08X %5u %8d %llu %d %pK %u\n",
+		   "%02X %08X:%08X %02X:%08lX %08X %5u %8d %llu %d 0 %u\n",
 		   bucket,
 		   src->s6_addr32[0], src->s6_addr32[1],
 		   src->s6_addr32[2], src->s6_addr32[3], srcp,
@@ -1115,6 +1115,5 @@ void __ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp,
 		   from_kuid_munged(seq_user_ns(seq), sk_uid(sp)),
 		   0,
 		   sock_i_ino(sp),
-		   refcount_read(&sp->sk_refcnt), sp,
-		   sk_drops_read(sp));
+		   refcount_read(&sp->sk_refcnt), sk_drops_read(sp));
 }
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 522ba45ce9b75..bc45e647c4956 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -2101,7 +2101,7 @@ static void get_openreq6(struct seq_file *seq,
 
 	seq_printf(seq,
 		   "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
-		   "%02X %08X:%08X %02X:%08lX %08X %5u %8d %d %d %pK\n",
+		   "%02X %08X:%08X %02X:%08lX %08X %5u %8d %d %d 0\n",
 		   i,
 		   src->s6_addr32[0], src->s6_addr32[1],
 		   src->s6_addr32[2], src->s6_addr32[3],
@@ -2118,7 +2118,7 @@ static void get_openreq6(struct seq_file *seq,
 				    sk_uid(req->rsk_listener)),
 		   0,  /* non standard timer */
 		   0, /* open_requests have no inode */
-		   0, req);
+		   0);
 }
 
 static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)
@@ -2169,7 +2169,7 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)
 
 	seq_printf(seq,
 		   "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
-		   "%02X %08X:%08X %02X:%08lX %08X %5u %8d %llu %d %pK %lu %lu %u %u %d\n",
+		   "%02X %08X:%08X %02X:%08lX %08X %5u %8d %llu %d 0 %lu %lu %u %u %d\n",
 		   i,
 		   src->s6_addr32[0], src->s6_addr32[1],
 		   src->s6_addr32[2], src->s6_addr32[3], srcp,
@@ -2184,7 +2184,7 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)
 		   from_kuid_munged(seq_user_ns(seq), sk_uid(sp)),
 		   READ_ONCE(icsk->icsk_probes_out),
 		   sock_i_ino(sp),
-		   refcount_read(&sp->sk_refcnt), sp,
+		   refcount_read(&sp->sk_refcnt),
 		   jiffies_to_clock_t(icsk->icsk_rto),
 		   jiffies_to_clock_t(icsk->icsk_ack.ato),
 		   (icsk->icsk_ack.quick << 1) | inet_csk_in_pingpong_mode(sp),
@@ -2209,7 +2209,7 @@ static void get_timewait6_sock(struct seq_file *seq,
 
 	seq_printf(seq,
 		   "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
-		   "%02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %pK\n",
+		   "%02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d\n",
 		   i,
 		   src->s6_addr32[0], src->s6_addr32[1],
 		   src->s6_addr32[2], src->s6_addr32[3], srcp,
@@ -2217,7 +2217,7 @@ static void get_timewait6_sock(struct seq_file *seq,
 		   dest->s6_addr32[2], dest->s6_addr32[3], destp,
 		   READ_ONCE(tw->tw_substate), 0, 0,
 		   3, jiffies_delta_to_clock_t(delta), 0, 0, 0, 0,
-		   refcount_read(&tw->tw_refcnt), tw);
+		   refcount_read(&tw->tw_refcnt));
 }
 
 static int tcp6_seq_show(struct seq_file *seq, void *v)
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 1d8965d7f4f3c..aa12e16edfdcb 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -3803,10 +3803,9 @@ static int pfkey_seq_show(struct seq_file *f, void *v)
 	struct sock *s = sk_entry(v);
 
 	if (v == SEQ_START_TOKEN)
-		seq_printf(f ,"sk       RefCnt Rmem   Wmem   User   Inode\n");
+		seq_printf(f ,"sk RefCnt Rmem   Wmem   User   Inode\n");
 	else
-		seq_printf(f, "%pK %-6d %-6u %-6u %-6u %-6llu\n",
-			       s,
+		seq_printf(f, "0  %-6d %-6u %-6u %-6u %-6llu\n",
 			       refcount_read(&s->sk_refcnt),
 			       sk_rmem_alloc_get(s),
 			       sk_wmem_alloc_get(s),
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 5202fe0b08671..d5172778f2a4a 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -2700,14 +2700,13 @@ static int netlink_native_seq_show(struct seq_file *seq, void *v)
 {
 	if (v == SEQ_START_TOKEN) {
 		seq_puts(seq,
-			 "sk               Eth Pid        Groups   "
+			 "sk Eth Pid        Groups   "
 			 "Rmem     Wmem     Dump  Locks    Drops    Inode\n");
 	} else {
 		struct sock *s = v;
 		struct netlink_sock *nlk = nlk_sk(s);
 
-		seq_printf(seq, "%pK %-3d %-10u %08x %-8d %-8d %-5d %-8d %-8u %-8llu\n",
-			   s,
+		seq_printf(seq, "0  %-3d %-10u %08x %-8d %-8d %-5d %-8d %-8u %-8llu\n",
 			   s->sk_protocol,
 			   nlk->portid,
 			   nlk->groups ? (u32)nlk->groups[0] : 0,
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 8e6f3a734ba0b..177c2810cff48 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -4719,15 +4719,13 @@ static int packet_seq_show(struct seq_file *seq, void *v)
 {
 	if (v == SEQ_START_TOKEN)
 		seq_printf(seq,
-			   "%*sRefCnt Type Proto  Iface R Rmem   User   Inode\n",
-			   IS_ENABLED(CONFIG_64BIT) ? -17 : -9, "sk");
+			   "sk RefCnt Type Proto  Iface R Rmem   User   Inode\n");
 	else {
 		struct sock *s = sk_entry(v);
 		const struct packet_sock *po = pkt_sk(s);
 
 		seq_printf(seq,
-			   "%pK %-6d %-4d %04x   %-5d %1d %-6u %-6u %-6llu\n",
-			   s,
+			   "0  %-6d %-4d %04x   %-5d %1d %-6u %-6u %-6llu\n",
 			   refcount_read(&s->sk_refcnt),
 			   s->sk_type,
 			   ntohs(READ_ONCE(po->num)),
diff --git a/net/phonet/socket.c b/net/phonet/socket.c
index 631a99cdbd006..ad12b746d4fca 100644
--- a/net/phonet/socket.c
+++ b/net/phonet/socket.c
@@ -586,14 +586,13 @@ static int pn_sock_seq_show(struct seq_file *seq, void *v)
 		struct pn_sock *pn = pn_sk(sk);
 
 		seq_printf(seq, "%2d %04X:%04X:%02X %02X %08X:%08X %5d %llu "
-			"%d %pK %u",
+			"%d 0 %u",
 			sk->sk_protocol, pn->sobject, pn->dobject,
 			pn->resource, sk->sk_state,
 			sk_wmem_alloc_get(sk), sk_rmem_alloc_get(sk),
 			from_kuid_munged(seq_user_ns(seq), sk_uid(sk)),
 			sock_i_ino(sk),
-			refcount_read(&sk->sk_refcnt), sk,
-			sk_drops_read(sk));
+			refcount_read(&sk->sk_refcnt), sk_drops_read(sk));
 	}
 	seq_pad(seq, '\n');
 	return 0;
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index 43433d7e2acd7..7ea123b90aa59 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -174,7 +174,7 @@ static int sctp_eps_seq_show(struct seq_file *seq, void *v)
 		sk = ep->base.sk;
 		if (!net_eq(sock_net(sk), seq_file_net(seq)))
 			continue;
-		seq_printf(seq, "%8pK %8pK %-3d %-3d %-4d %-5d %5u %5llu ", ep, sk,
+		seq_printf(seq, "%8d %8d %-3d %-3d %-4d %-5d %5u %5llu ", 0, 0,
 			   sctp_sk(sk)->type, sk->sk_state, hash,
 			   ep->base.bind_addr.port,
 			   from_kuid_munged(seq_user_ns(seq), sk_uid(sk)),
@@ -260,9 +260,9 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
 	sk = epb->sk;
 
 	seq_printf(seq,
-		   "%8pK %8pK %-3d %-3d %-2d %-4d "
+		   "%8d %8d %-3d %-3d %-2d %-4d "
 		   "%4d %8d %8d %7u %5llu %-5d %5d ",
-		   assoc, sk, sctp_sk(sk)->type, sk->sk_state,
+		   0, 0, sctp_sk(sk)->type, sk->sk_state,
 		   assoc->state, 0,
 		   assoc->assoc_id,
 		   assoc->sndbuf_used,
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index f7a9d55eee8a1..ee3eb5eeee7e8 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -3547,15 +3547,14 @@ static int unix_seq_show(struct seq_file *seq, void *v)
 {
 
 	if (v == SEQ_START_TOKEN)
-		seq_puts(seq, "Num       RefCount Protocol Flags    Type St "
+		seq_puts(seq, "Num RefCount Protocol Flags    Type St "
 			 "Inode Path\n");
 	else {
 		struct sock *s = v;
 		struct unix_sock *u = unix_sk(s);
 		unix_state_lock(s);
 
-		seq_printf(seq, "%pK: %08X %08X %08X %04X %02X %5llu",
-			s,
+		seq_printf(seq, "0:  %08X %08X %08X %04X %02X %5llu",
 			refcount_read(&s->sk_refcnt),
 			0,
 			s->sk_state == TCP_LISTEN ? __SO_ACCEPTCON : 0,
-- 
2.53.0


^ permalink raw reply related

* Re: [PATCH net v2] net: stmmac: dwmac4: mask interrupts when stopping DMA in suspend
From: Maxime Chevallier @ 2026-07-20 14:40 UTC (permalink / raw)
  To: Luis Lang, netdev
  Cc: Andrew Lunn, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Maxime Coquelin, Alexandre Torgue,
	Russell King (Oracle), Oleksij Rempel, Ovidiu Panait,
	Rohan G Thomas, moderated list:ARM/STM32 ARCHITECTURE,
	moderated list:ARM/STM32 ARCHITECTURE, open list
In-Reply-To: <20260720111534.163416-1-luis.la@mail.de>

Hi Luis,

On 7/20/26 13:15, Luis Lang wrote:
> Since commit 1b9707e6f1a9 ("net: stmmac: enable RPS and RBU
> interrupts"), suspending causes an interrupt storm from the RPS
> interrupt.
> Fix this by adding a deinit_chan() op to stmmac_dma_ops, which
> masks all default dma channel interrupts. This is called from
> stmmac_stop_all_dma(), so interrupts don't trigger while suspending.
> 
> Fixes: 1b9707e6f1a9 ("net: stmmac: enable RPS and RBU interrupts")
> Suggested-by: Andrew Lunn <andrew@lunn.ch>
> Suggested-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
> Signed-off-by: Luis Lang <luis.la@mail.de>

I wasn't able to reproduce the original issue on dwmac4, however
I could test that suspend/resume as well as WoL still works on a
dwmac4 device with this patch applied.

Thanks for the patch !

Tested-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>

Maxime

> ---
>  .../net/ethernet/stmicro/stmmac/dwmac4_dma.c  | 24 +++++++++++++++++++
>  drivers/net/ethernet/stmicro/stmmac/hwif.h    |  4 ++++
>  .../net/ethernet/stmicro/stmmac/stmmac_main.c |  4 ++++
>  3 files changed, 32 insertions(+)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> index 829a23bdad01..23ffe1adcd0d 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> @@ -106,6 +106,17 @@ static void dwmac4_dma_init_channel(struct stmmac_priv *priv,
>  	       ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
>  }
>  
> +static void dwmac4_dma_deinit_channel(struct stmmac_priv *priv,
> +				      void __iomem *ioaddr, u32 chan)
> +{
> +	const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
> +	u32 value;
> +
> +	value = readl(ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
> +	value &= ~DMA_CHAN_INTR_DEFAULT_MASK;
> +	writel(value, ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
> +}
> +
>  static void dwmac410_dma_init_channel(struct stmmac_priv *priv,
>  				      void __iomem *ioaddr,
>  				      struct stmmac_dma_cfg *dma_cfg, u32 chan)
> @@ -125,6 +136,17 @@ static void dwmac410_dma_init_channel(struct stmmac_priv *priv,
>  	       ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
>  }
>  
> +static void dwmac410_dma_deinit_channel(struct stmmac_priv *priv,
> +					void __iomem *ioaddr, u32 chan)
> +{
> +	const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
> +	u32 value;
> +
> +	value = readl(ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
> +	value &= ~DMA_CHAN_INTR_DEFAULT_MASK_4_10;
> +	writel(value, ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
> +}
> +
>  static void dwmac4_dma_init(void __iomem *ioaddr,
>  			    struct stmmac_dma_cfg *dma_cfg)
>  {
> @@ -548,6 +570,7 @@ const struct stmmac_dma_ops dwmac4_dma_ops = {
>  	.reset = dwmac4_dma_reset,
>  	.init = dwmac4_dma_init,
>  	.init_chan = dwmac4_dma_init_channel,
> +	.deinit_chan = dwmac4_dma_deinit_channel,
>  	.init_rx_chan = dwmac4_dma_init_rx_chan,
>  	.init_tx_chan = dwmac4_dma_init_tx_chan,
>  	.axi = dwmac4_dma_axi,
> @@ -577,6 +600,7 @@ const struct stmmac_dma_ops dwmac410_dma_ops = {
>  	.reset = dwmac4_dma_reset,
>  	.init = dwmac4_dma_init,
>  	.init_chan = dwmac410_dma_init_channel,
> +	.deinit_chan = dwmac410_dma_deinit_channel,
>  	.init_rx_chan = dwmac4_dma_init_rx_chan,
>  	.init_tx_chan = dwmac4_dma_init_tx_chan,
>  	.axi = dwmac4_dma_axi,
> diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
> index e6317b94fff7..04dafec021b4 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
> +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
> @@ -170,6 +170,8 @@ struct stmmac_dma_ops {
>  	void (*init)(void __iomem *ioaddr, struct stmmac_dma_cfg *dma_cfg);
>  	void (*init_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
>  			  struct stmmac_dma_cfg *dma_cfg, u32 chan);
> +	void (*deinit_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
> +			    u32 chan);
>  	void (*init_rx_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
>  			     struct stmmac_dma_cfg *dma_cfg,
>  			     dma_addr_t phy, u32 chan);
> @@ -235,6 +237,8 @@ struct stmmac_dma_ops {
>  	stmmac_do_void_callback(__priv, dma, init, __args)
>  #define stmmac_init_chan(__priv, __args...) \
>  	stmmac_do_void_callback(__priv, dma, init_chan, __priv, __args)
> +#define stmmac_deinit_chan(__priv, __args...) \
> +	stmmac_do_void_callback(__priv, dma, deinit_chan, __priv, __args)
>  #define stmmac_init_rx_chan(__priv, __args...) \
>  	stmmac_do_void_callback(__priv, dma, init_rx_chan, __priv, __args)
>  #define stmmac_init_tx_chan(__priv, __args...) \
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index 2a0d7eff88d3..af29a50ddb89 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -2560,6 +2560,7 @@ static void stmmac_stop_all_dma(struct stmmac_priv *priv)
>  {
>  	u8 rx_channels_count = priv->plat->rx_queues_to_use;
>  	u8 tx_channels_count = priv->plat->tx_queues_to_use;
> +	u8 dma_csr_ch = max(rx_channels_count, tx_channels_count);
>  	u8 chan;
>  
>  	for (chan = 0; chan < rx_channels_count; chan++)
> @@ -2567,6 +2568,9 @@ static void stmmac_stop_all_dma(struct stmmac_priv *priv)
>  
>  	for (chan = 0; chan < tx_channels_count; chan++)
>  		stmmac_stop_tx_dma(priv, chan);
> +
> +	for (chan = 0; chan < dma_csr_ch; chan++)
> +		stmmac_deinit_chan(priv, priv->ioaddr, chan);
>  }
>  
>  /**


^ permalink raw reply

* Re: [PATCH 1/3] usb: chipidea: Use %pe to print error pointers
From: Frank Li @ 2026-07-20 14:39 UTC (permalink / raw)
  To: Subasri S
  Cc: Peter Chen, Greg Kroah-Hartman, Frank Li, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, Duncan Sands,
	Chas Williams, Minas Harutyunyan, Hans de Goede, Heikki Krogerus,
	Badhri Jagan Sridharan, linux-usb, imx, linux-arm-kernel,
	linux-kernel, linux-atm-general, netdev
In-Reply-To: <20260719-usb-ptr_err_patchset-v1-1-85f7f2e4fefb@gmail.com>

On Sun, Jul 19, 2026 at 06:25:46PM +0530, Subasri S wrote:
>
> Use the %pe format specifier instead of %ld with PTR_ERR() for printing
> error pointers in imx_get_clks(), ci_hdrc_imx_probe(), and
> ci_get_platdata(). This prints symbolic error names (e.g. -ENOMEM)
> instead of errno numbers (e.g. -12), making error logs more readable.
>
> This patch fixes coccinelle reported warnings:

Avoid use words "This patch", just

Fix coccinelle reported warnings:

> ./chipidea/ci_hdrc_imx.c:452:5-12: WARNING: Consider using %pe to print PTR_ERR()
> ./chipidea/ci_hdrc_imx.c:468:5-12: WARNING: Consider using %pe to print PTR_ERR()
> ./chipidea/ci_hdrc_imx.c:222:4-11: WARNING: Consider using %pe to print PTR_ERR()
> ./chipidea/ci_hdrc_imx.c:222:24-31: WARNING: Consider using %pe to print PTR_ERR()

keep one is enough

> ./chipidea/core.c:684:4-11: WARNING: Consider using %pe to print PTR_ERR()
>
> Compile-tested only.
>
> Signed-off-by: Subasri S <subasris1210@gmail.com>
> ---
>  drivers/usb/chipidea/ci_hdrc_imx.c | 12 ++++++------
>  drivers/usb/chipidea/core.c        |  4 ++--
>  2 files changed, 8 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c
> index 56d2ba824a0b..7bfe37ed68ae 100644
> --- a/drivers/usb/chipidea/ci_hdrc_imx.c
> +++ b/drivers/usb/chipidea/ci_hdrc_imx.c
> @@ -218,8 +218,8 @@ static int imx_get_clks(struct device *dev)
>                 if (IS_ERR(data->clk)) {
>                         ret = PTR_ERR(data->clk);
>                         dev_err(dev,
> -                               "Failed to get clks, err=%ld,%ld\n",
> -                               PTR_ERR(data->clk), PTR_ERR(data->clk_ipg));
> +                               "Failed to get clks, err=%pe,%pe\n",
> +                               data->clk, data->clk_ipg);
>                         return ret;
>                 }
>                 /* Get wakeup clock. Not all of the platforms need to
> @@ -448,8 +448,8 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
>                 pinctrl_hsic_idle = pinctrl_lookup_state(data->pinctrl, "idle");
>                 if (IS_ERR(pinctrl_hsic_idle)) {
>                         dev_err(dev,
> -                               "pinctrl_hsic_idle lookup failed, err=%ld\n",
> -                                       PTR_ERR(pinctrl_hsic_idle));
> +                               "pinctrl_hsic_idle lookup failed, err=%pe\n",
> +                                       pinctrl_hsic_idle);
>                         ret = PTR_ERR(pinctrl_hsic_idle);
>                         goto err_put;
>                 }
> @@ -464,8 +464,8 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
>                                                                 "active");
>                 if (IS_ERR(data->pinctrl_hsic_active)) {
>                         dev_err(dev,
> -                               "pinctrl_hsic_active lookup failed, err=%ld\n",
> -                                       PTR_ERR(data->pinctrl_hsic_active));
> +                               "pinctrl_hsic_active lookup failed, err=%pe\n",
> +                                       data->pinctrl_hsic_active);
>                         ret = PTR_ERR(data->pinctrl_hsic_active);
>                         goto err_put;
>                 }
> diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
> index 07563be0013f..09db8a4eace2 100644
> --- a/drivers/usb/chipidea/core.c
> +++ b/drivers/usb/chipidea/core.c
> @@ -680,8 +680,8 @@ static int ci_get_platdata(struct device *dev,
>                         /* no vbus regulator is needed */
>                         platdata->reg_vbus = NULL;
>                 } else if (IS_ERR(platdata->reg_vbus)) {
> -                       dev_err(dev, "Getting regulator error: %ld\n",
> -                               PTR_ERR(platdata->reg_vbus));
> +                       dev_err(dev, "Getting regulator error: %pe\n",
> +                               platdata->reg_vbus);
>                         return PTR_ERR(platdata->reg_vbus);
>                 }
>                 /* Get TPL support */
>
> --
> 2.43.0
>
>

^ permalink raw reply

* Re: [PATCH 4/8] net: bcmgenet: use platform_device_set_fwnode()
From: Andrew Lunn @ 2026-07-20 14:38 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy (CS GROUP), Andi Shyti, Joerg Roedel (AMD),
	Will Deacon, Robin Murphy, Andy Shevchenko, Doug Berger,
	Florian Fainelli, Broadcom internal kernel review list,
	Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Ulf Hansson, Frank Li, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, Lee Jones,
	Sebastian Hesselbarth, Srinivas Kandagatla, brgl, driver-core,
	linuxppc-dev, linux-kernel, linux-i2c, iommu, netdev, linux-pm,
	imx, linux-arm-kernel, mfd, linux-arm-msm, linux-sound
In-Reply-To: <20260720-pdev-set-fwnode-instead-of-of-node-v1-4-2dee93f42c54@oss.qualcomm.com>

On Mon, Jul 20, 2026 at 11:24:51AM +0200, Bartosz Golaszewski wrote:
> Prefer the higher-level platform_device_set_fwnode() over the
> OF-specific platform_device_set_of_node() for dynamically allocated
> platform devices.

Why?

This driver is OF only. It does not support ACPI, and probably never
will. In general, networking and ACPI don't go together, ACPI is not
sufficiently advanced.

What is you use case here?

	Andrew

^ permalink raw reply

* [PATCH v3 net] idpf: disable PTM on probe failure and on remove
From: Myeonghun Pak @ 2026-07-20 14:35 UTC (permalink / raw)
  To: Tony Nguyen, Przemek Kitszel, intel-wired-lan
  Cc: Milena Olech, Emil Tantilov, Mina Almasry, Andrew Lunn,
	David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	netdev, linux-kernel, Myeonghun Pak, Ijae Kim

idpf_probe() enables PCIe Precision Time Measurement with
pci_enable_ptm(), which takes a reference on the device and on every
PTM-capable device up the path to the PTM Root.

Neither the probe error path nor idpf_remove() drops that reference, so
the PTM enable counts of this device and of its upstream path stay
elevated with no bound driver, and the device's PTM control bits remain
set.  pcim_enable_device() only arranges for pci_disable_device() and
does not undo the PTM enable.

Add the matching pci_disable_ptm() to the common probe unwind and to
idpf_remove().  pci_enable_ptm() failure is not fatal here, so guard both
calls with pcie_ptm_enabled(): pci_disable_ptm() decrements
dev->ptm_enable_cnt unconditionally and then recurses upstream, so
calling it after a failed enable would drive this device's count negative
and wrongly decrement parents shared with other endpoints.

This issue was identified during our ongoing static-analysis research
while reviewing kernel code.

Fixes: 8d5e12c5921c ("idpf: add initial PTP support")
Co-developed-by: Ijae Kim <ae878000@gmail.com>
Signed-off-by: Ijae Kim <ae878000@gmail.com>
Signed-off-by: Myeonghun Pak <mhun512@gmail.com>
---
Changes in v3:
- Rebased; aa8671af0c38 ("PCI/PTM: Drop pci_enable_ptm() granularity
  parameter") changed the call signature, so v2 no longer applied.
- Guard both pci_disable_ptm() calls with pcie_ptm_enabled(), as
  pci_disable_ptm() is refcounted and recurses upstream since
  e1092d5e15e6 ("PCI/PTM: Do not enable PTM automatically for Root and
  Switch Upstream Ports").  Raised by Tony Nguyen.
- Dropped the v2 claim that pci_disable_ptm() is a no-op when PTM was not
  enabled; that is no longer true.

Changes in v2:
- Disable PTM in the probe error path, as requested by Emil Tantilov.

 drivers/net/ethernet/intel/idpf/idpf_main.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/intel/idpf/idpf_main.c b/drivers/net/ethernet/intel/idpf/idpf_main.c
index ab3c409..97bafeb 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_main.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_main.c
@@ -159,6 +159,8 @@ destroy_wqs:
 	mutex_destroy(&adapter->queue_lock);
 	mutex_destroy(&adapter->vc_buf_lock);
 
+	if (pcie_ptm_enabled(pdev))
+		pci_disable_ptm(pdev);
 	pci_set_drvdata(pdev, NULL);
 	kfree(adapter);
 }
@@ -266,7 +268,7 @@ static int idpf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	if (err) {
 		pci_err(pdev, "DMA configuration failed: %pe\n", ERR_PTR(err));
 
-		goto err_free;
+		goto err_disable_ptm;
 	}
 
 	pci_set_master(pdev);
@@ -279,7 +281,7 @@ static int idpf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	if (!adapter->init_wq) {
 		dev_err(dev, "Failed to allocate init workqueue\n");
 		err = -ENOMEM;
-		goto err_free;
+		goto err_disable_ptm;
 	}
 
 	adapter->serv_wq = alloc_workqueue("%s-%s-service",
@@ -366,6 +368,9 @@ err_mbx_wq_alloc:
 	destroy_workqueue(adapter->serv_wq);
 err_serv_wq_alloc:
 	destroy_workqueue(adapter->init_wq);
+err_disable_ptm:
+	if (pcie_ptm_enabled(pdev))
+		pci_disable_ptm(pdev);
 err_free:
 	kfree(adapter);
 	return err;
-- 
2.47.1


^ permalink raw reply related

* Re: [PATCH 5/8] pmdomain: imx: use platform_device_set_fwnode()
From: Frank Li @ 2026-07-20 14:34 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy (CS GROUP), Andi Shyti, Joerg Roedel (AMD),
	Will Deacon, Robin Murphy, Andy Shevchenko, Doug Berger,
	Florian Fainelli, Broadcom internal kernel review list,
	Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Ulf Hansson, Frank Li, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, Lee Jones,
	Sebastian Hesselbarth, Srinivas Kandagatla, brgl, driver-core,
	linuxppc-dev, linux-kernel, linux-i2c, iommu, netdev, linux-pm,
	imx, linux-arm-kernel, mfd, linux-arm-msm, linux-sound
In-Reply-To: <20260720-pdev-set-fwnode-instead-of-of-node-v1-5-2dee93f42c54@oss.qualcomm.com>

On Mon, Jul 20, 2026 at 11:24:52AM +0200, Bartosz Golaszewski wrote:
> Prefer the higher-level platform_device_set_fwnode() over the
> OF-specific platform_device_set_of_node() for dynamically allocated
> platform devices.
>
> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
> ---
>  drivers/pmdomain/imx/gpc.c | 2 +-

Reviewed-by: Frank Li <Frank.Li@nxp.com>

>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/pmdomain/imx/gpc.c b/drivers/pmdomain/imx/gpc.c
> index abca5f449a226fbae4213926e1395c413160c950..c147eaf048ba2b79a744ec87029420981581e48e 100644
> --- a/drivers/pmdomain/imx/gpc.c
> +++ b/drivers/pmdomain/imx/gpc.c
> @@ -487,7 +487,7 @@ static int imx_gpc_probe(struct platform_device *pdev)
>  			domain->ipg_rate_mhz = ipg_rate_mhz;
>
>  			pd_pdev->dev.parent = &pdev->dev;
> -			platform_device_set_of_node(pd_pdev, np);
> +			platform_device_set_fwnode(pd_pdev, of_fwnode_handle(np));
>
>  			ret = platform_device_add(pd_pdev);
>  			if (ret) {
>
> --
> 2.47.3
>
>

^ permalink raw reply

* Re: [PATCH 3/8] iommu/fsl: use platform_device_set_fwnode()
From: Robin Murphy @ 2026-07-20 14:34 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: driver-core, linuxppc-dev, linux-kernel, linux-i2c, iommu, netdev,
	linux-pm, imx, linux-arm-kernel, mfd, linux-arm-msm, linux-sound,
	Bartosz Golaszewski, Greg Kroah-Hartman, Rafael J. Wysocki,
	Danilo Krummrich, Madhavan Srinivasan, Michael Ellerman,
	Nicholas Piggin, Christophe Leroy (CS GROUP), Andi Shyti,
	Joerg Roedel (AMD), Will Deacon, Andy Shevchenko, Doug Berger,
	Florian Fainelli, Broadcom internal kernel review list,
	Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Ulf Hansson, Frank Li, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, Lee Jones,
	Sebastian Hesselbarth, Srinivas Kandagatla
In-Reply-To: <CAMRc=MefqCMgVv-o5hWoRwS2iXPQNs5nH2qHiz55+ew162LfSA@mail.gmail.com>

On 20/07/2026 2:39 pm, Bartosz Golaszewski wrote:
> On Mon, 20 Jul 2026 14:58:27 +0200, Robin Murphy <robin.murphy@arm.com> said:
>> On 20/07/2026 10:24 am, Bartosz Golaszewski wrote:
>>> Prefer the higher-level platform_device_set_fwnode() over the
>>> OF-specific platform_device_set_of_node() for dynamically allocated
>>> platform devices.
>>
>> This is very much non-portable code specific to OF-only platforms, but
>> if the intention is to remove platform_device_set_of_node() again
>> already, then FWIW,
>>
> 
> Providing platform_device_set_of_node() and using it was done to make the
> transision to expanding reference counting to all firmware nodes possible.
> I don't think we'll remove it just yet as it doesn't make sense to convert
> the code under drivers/of/ to using the fwnode variant.

OK, but in that case why convert these users either? If the OF helper 
does continue to exist then I'd imagine the static checker brigade will 
eventually end up sending patches to "simplify" these open-coded 
equivalents back to using it. And frankly, if drivers do know for sure 
they're exclusively dealing with of_nodes, rather than doing something 
conditional under an is_of_node() check, then I see little justification 
for them *not* using the dedicated helper.

If the complaint is that there are no *public* users to justify 
exporting platform_device_set_fwnode(), then as I say AFAICS that's much 
more neatly addressed with the static inline approach, such that we 
still get to unify the public APIs, actively eliminate something from 
the symbol table and save a bit of source and object code, but without 
any need to churn the truly OF-based callers at all.

Thanks,
Robin.

> 
>> Acked-by: Robin Murphy <robin.murphy@arm.com>
>>
>> (Although I'm slightly puzzled by the cover letter - AFAICS in -next,
>> platform_device_set_of_node() is itself very much a user of
>> platform_device_set_fwnode(), however in terms of symbol exports,
>> perhaps the former could now just be a static inline wrapper?)
>>
> 
> Sure that can be done independently later.
> 
> Bart


^ permalink raw reply

* Re: [PATCH 3/8] iommu/fsl: use platform_device_set_fwnode()
From: Frank Li @ 2026-07-20 14:34 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy (CS GROUP), Andi Shyti, Joerg Roedel (AMD),
	Will Deacon, Robin Murphy, Andy Shevchenko, Doug Berger,
	Florian Fainelli, Broadcom internal kernel review list,
	Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Ulf Hansson, Frank Li, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, Lee Jones,
	Sebastian Hesselbarth, Srinivas Kandagatla, brgl, driver-core,
	linuxppc-dev, linux-kernel, linux-i2c, iommu, netdev, linux-pm,
	imx, linux-arm-kernel, mfd, linux-arm-msm, linux-sound
In-Reply-To: <20260720-pdev-set-fwnode-instead-of-of-node-v1-3-2dee93f42c54@oss.qualcomm.com>

On Mon, Jul 20, 2026 at 11:24:50AM +0200, Bartosz Golaszewski wrote:
> Prefer the higher-level platform_device_set_fwnode() over the
> OF-specific platform_device_set_of_node() for dynamically allocated
> platform devices.
>
> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
> ---

Reviewed-by: Frank Li <Frank.Li@nxp.com>

>  drivers/iommu/fsl_pamu.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/iommu/fsl_pamu.c b/drivers/iommu/fsl_pamu.c
> index c83bbc3faad56d6ee1c89b0a7f74028af02c81e9..268a1f752fbceab4fd24013aeea5df1b6982fbb1 100644
> --- a/drivers/iommu/fsl_pamu.c
> +++ b/drivers/iommu/fsl_pamu.c
> @@ -975,7 +975,7 @@ static __init int fsl_pamu_init(void)
>  		goto error_device_alloc;
>  	}
>
> -	platform_device_set_of_node(pdev, np);
> +	platform_device_set_fwnode(pdev, of_fwnode_handle(np));
>
>  	ret = pamu_domain_init();
>  	if (ret)
>
> --
> 2.47.3
>
>

^ permalink raw reply

* Re: [PATCH net v3] phonet: check register_netdevice_notifier() error in phonet_device_init()
From: Andrew Lunn @ 2026-07-20 14:29 UTC (permalink / raw)
  To: Minhong He
  Cc: courmisch, davem, edumazet, kuba, pabeni, horms,
	remi.denis-courmont, netdev, linux-kernel
In-Reply-To: <20260720070031.108248-1-heminhong@kylinos.cn>

On Mon, Jul 20, 2026 at 03:00:31PM +0800, Minhong He wrote:
> phonet_device_init() registers a netdevice notifier before calling
> phonet_netlink_register(), but does not check whether notifier
> registration succeeded. On failure, netlink setup still proceeds and
> init may return success without the notifier in place.
> 
> Also, the existing phonet_netlink_register() failure path called
> phonet_device_exit(), which runs rtnl_unregister_all() even though
> rtnl_register_many() already unwound any partial registration. Calling
> the full exit helper on a partial init is not correct.
> 
> Check each registration error and unwind only the steps that have
> succeeded so far.
> 
> Signed-off-by: Minhong He <heminhong@kylinos.cn>
> ---
> v3:
> - Use goto-based unwind; do not call phonet_device_exit() on
>   phonet_netlink_register() failure (avoids rtnl_unregister_all()
>   after rtnl_register_many() already unwound).
> - Drop Fixes tag (theoretical init failure path; not suitable for
>   stable autosel).
> v2: https://lore.kernel.org/netdev/20260716101504.158387-1-heminhong@kylinos.cn/
> - On notifier registration failure, unwind only proc/pernet.
> v1: https://lore.kernel.org/netdev/20260713075212.431455-1-heminhong@kylinos.cn/
> 
>  net/phonet/pn_dev.c | 20 +++++++++++++++++---
>  1 file changed, 17 insertions(+), 3 deletions(-)
> 
> diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c
> index ad44831d6745..f41322a12fb7 100644
> --- a/net/phonet/pn_dev.c
> +++ b/net/phonet/pn_dev.c
> @@ -350,16 +350,30 @@ static struct pernet_operations phonet_net_ops = {
>  /* Initialize Phonet devices list */
>  int __init phonet_device_init(void)
>  {
> -	int err = register_pernet_subsys(&phonet_net_ops);
> +	int err;
> +
> +	err = register_pernet_subsys(&phonet_net_ops);
>  	if (err)
>  		return err;
>  
>  	proc_create_net("pnresource", 0, init_net.proc_net, &pn_res_seq_ops,
>  			sizeof(struct seq_net_private));
> -	register_netdevice_notifier(&phonet_device_notifier);
> +
> +	err = register_netdevice_notifier(&phonet_device_notifier);
> +	if (err)
> +		goto err_pernet;
> +
>  	err = phonet_netlink_register();
>  	if (err)
> -		phonet_device_exit();
> +		goto err_notifier;
> +
> +	return 0;
> +
> +err_notifier:
> +	unregister_netdevice_notifier(&phonet_device_notifier);
> +err_pernet:
> +	unregister_pernet_subsys(&phonet_net_ops);
> +	remove_proc_entry("pnresource", init_net.proc_net);

It is good practice to undo in the opposite order to which it was
done. Sometimes there are dependencies, and things will break if you
tear them down in the wrong order.

It is also unusual to see two undo steps without a goto label between
them. Can proc_create_net() fail? Should the return value be tested
and cleanup done if it fails?

    Andrew

---
pw-bot: cr

^ permalink raw reply

* [PATCH net-next v2 6/6] SUNRPC: Remove sock_recvmsg path from svcsock TCP receives
From: Chuck Lever @ 2026-07-20 14:28 UTC (permalink / raw)
  To: Jakub Kicinski, Paolo Abeni, Simon Horman, John Fastabend,
	Sabrina Dubroca, Shuah Khan, Jeff Layton, NeilBrown,
	Olga Kornievskaia, Dai Ngo, Tom Talpey, Chuck Lever
  Cc: netdev, kernel-tls-handshake, linux-kselftest, linux-nfs
In-Reply-To: <20260720-tcp-read-sock-v2-0-29545d034f3c@kernel.org>

From: Chuck Lever <chuck.lever@oracle.com>

The svcsock TCP receive path maintains two code paths: one
using read_sock/read_sock_rectype and a legacy path using
sock_recvmsg. Plain TCP sockets already provide read_sock
(tcp_read_sock) in their proto_ops, so a single
read_sock-based receive path handles all cases relevant to
NFSD, using read_sock_rectype under kTLS and read_sock
otherwise.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 net/sunrpc/svcsock.c | 329 ++++-----------------------------------------------
 1 file changed, 26 insertions(+), 303 deletions(-)

diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index e40931d11491..9b9e0da9e73c 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -8,15 +8,6 @@
  * evenly when servicing a single client. May need to modify the
  * svc_xprt_enqueue procedure...
  *
- * TCP support is largely untested and may be a little slow. The problem
- * is that we currently do two separate recvfrom's, one for the 4-byte
- * record length, and the second for the actual record. This could possibly
- * be improved by always reading a minimum size of around 100 bytes and
- * tucking any superfluous bytes away in a temporary store. Still, that
- * leaves write requests out in the rain. An alternative may be to peek at
- * the first skb in the queue, and if it matches the next TCP sequence
- * number, to extract the record marker. Yuck.
- *
  * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
  */
 
@@ -238,138 +229,6 @@ static int svc_one_sock_name(struct svc_sock *svsk, char *buf, int remaining)
 	return len;
 }
 
-static int
-svc_tcp_sock_process_cmsg(struct socket *sock, struct msghdr *msg,
-			  struct cmsghdr *cmsg, int ret)
-{
-	u8 content_type = tls_get_record_type(sock->sk, cmsg);
-	u8 level, description;
-
-	switch (content_type) {
-	case 0:
-		break;
-	case TLS_RECORD_TYPE_DATA:
-		/* TLS sets EOR at the end of each application data
-		 * record, even though there might be more frames
-		 * waiting to be decrypted.
-		 */
-		msg->msg_flags &= ~MSG_EOR;
-		break;
-	case TLS_RECORD_TYPE_ALERT:
-		tls_alert_recv(sock->sk, msg, &level, &description);
-		ret = (level == TLS_ALERT_LEVEL_FATAL) ?
-			-ENOTCONN : -EAGAIN;
-		break;
-	default:
-		/* discard this record type */
-		ret = -EAGAIN;
-	}
-	return ret;
-}
-
-static int
-svc_tcp_sock_recv_cmsg(struct socket *sock, unsigned int *msg_flags)
-{
-	union {
-		struct cmsghdr	cmsg;
-		u8		buf[CMSG_SPACE(sizeof(u8))];
-	} u;
-	u8 alert[2];
-	struct kvec alert_kvec = {
-		.iov_base = alert,
-		.iov_len = sizeof(alert),
-	};
-	struct msghdr msg = {
-		.msg_flags = *msg_flags,
-		.msg_control = &u,
-		.msg_controllen = sizeof(u),
-	};
-	int ret;
-
-	iov_iter_kvec(&msg.msg_iter, ITER_DEST, &alert_kvec, 1,
-		      alert_kvec.iov_len);
-	ret = sock_recvmsg(sock, &msg, MSG_DONTWAIT);
-	if (ret > 0 &&
-	    tls_get_record_type(sock->sk, &u.cmsg) == TLS_RECORD_TYPE_ALERT) {
-		iov_iter_revert(&msg.msg_iter, ret);
-		ret = svc_tcp_sock_process_cmsg(sock, &msg, &u.cmsg, -EAGAIN);
-	}
-	return ret;
-}
-
-static int
-svc_tcp_sock_recvmsg(struct svc_sock *svsk, struct msghdr *msg)
-{
-	int ret;
-	struct socket *sock = svsk->sk_sock;
-
-	ret = sock_recvmsg(sock, msg, MSG_DONTWAIT);
-	if (msg->msg_flags & MSG_CTRUNC) {
-		msg->msg_flags &= ~(MSG_CTRUNC | MSG_EOR);
-		if (ret == 0 || ret == -EIO)
-			ret = svc_tcp_sock_recv_cmsg(sock, &msg->msg_flags);
-	}
-	return ret;
-}
-
-#if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE
-static void svc_flush_bvec(const struct bio_vec *bvec, size_t size, size_t seek)
-{
-	struct bvec_iter bi = {
-		.bi_size	= size + seek,
-	};
-	struct bio_vec bv;
-
-	bvec_iter_advance(bvec, &bi, seek & PAGE_MASK);
-	for_each_bvec(bv, bvec, bi, bi)
-		flush_dcache_page(bv.bv_page);
-}
-#else
-static inline void svc_flush_bvec(const struct bio_vec *bvec, size_t size,
-				  size_t seek)
-{
-}
-#endif
-
-/*
- * Read from @rqstp's transport socket. The incoming message fills whole
- * pages in @rqstp's rq_pages array until the last page of the message
- * has been received into a partial page.
- */
-static ssize_t svc_tcp_read_msg(struct svc_rqst *rqstp, size_t buflen,
-				size_t seek)
-{
-	struct svc_sock *svsk =
-		container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt);
-	struct bio_vec *bvec = rqstp->rq_bvec;
-	struct msghdr msg = { NULL };
-	unsigned int i;
-	ssize_t len;
-	size_t t;
-
-	clear_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
-
-	for (i = 0, t = 0; t < buflen; i++, t += PAGE_SIZE)
-		bvec_set_page(&bvec[i], rqstp->rq_pages[i], PAGE_SIZE, 0);
-
-	iov_iter_bvec(&msg.msg_iter, ITER_DEST, bvec, i, buflen);
-	if (seek) {
-		iov_iter_advance(&msg.msg_iter, seek);
-		buflen -= seek;
-	}
-	len = svc_tcp_sock_recvmsg(svsk, &msg);
-	if (len > 0)
-		svc_flush_bvec(bvec, len, seek);
-
-	/* If we read a full record, then assume there may be more
-	 * data to read (stream based sockets only!)
-	 */
-	if (len == buflen)
-		set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
-
-	return len;
-}
-
 /*
  * Set socket snd and rcv buffer lengths
  */
@@ -1048,50 +907,6 @@ static void svc_tcp_clear_pages(struct svc_sock *svsk)
 	svsk->sk_datalen = 0;
 }
 
-/*
- * Receive fragment record header into sk_marker.
- */
-static ssize_t svc_tcp_read_marker(struct svc_sock *svsk,
-				   struct svc_rqst *rqstp)
-{
-	ssize_t want, len;
-
-	/* If we haven't gotten the record length yet,
-	 * get the next four bytes.
-	 */
-	if (svsk->sk_tcplen < sizeof(rpc_fraghdr)) {
-		struct msghdr	msg = { NULL };
-		struct kvec	iov;
-
-		want = sizeof(rpc_fraghdr) - svsk->sk_tcplen;
-		iov.iov_base = ((char *)&svsk->sk_marker) + svsk->sk_tcplen;
-		iov.iov_len  = want;
-		iov_iter_kvec(&msg.msg_iter, ITER_DEST, &iov, 1, want);
-		len = svc_tcp_sock_recvmsg(svsk, &msg);
-		if (len < 0)
-			return len;
-		svsk->sk_tcplen += len;
-		if (len < want) {
-			/* call again to read the remaining bytes */
-			goto err_short;
-		}
-		trace_svcsock_marker(&svsk->sk_xprt, svsk->sk_marker);
-		if (svc_sock_reclen(svsk) + svsk->sk_datalen >
-		    svsk->sk_xprt.xpt_server->sv_max_mesg)
-			goto err_too_large;
-	}
-	return svc_sock_reclen(svsk);
-
-err_too_large:
-	net_notice_ratelimited("svc: %s oversized RPC fragment (%u octets) from %pISpc\n",
-			       svsk->sk_xprt.xpt_server->sv_name,
-			       svc_sock_reclen(svsk),
-			       (struct sockaddr *)&svsk->sk_xprt.xpt_remote);
-	svc_xprt_deferred_close(&svsk->sk_xprt);
-err_short:
-	return -EAGAIN;
-}
-
 static int receive_cb_reply(struct svc_sock *svsk, struct svc_rqst *rqstp)
 {
 	struct rpc_xprt *bc_xprt = svsk->sk_xprt.xpt_bc_xprt;
@@ -1135,10 +950,10 @@ static void svc_tcp_fragment_received(struct svc_sock *svsk)
 }
 
 /*
- * read_sock_rectype data actor: receives decrypted application data
- * from the TLS layer, parsing the RPC record stream (fragment
- * headers and message bodies) and assembling complete RPC messages
- * into rqstp->rq_pages.
+ * read_sock data actor: receives application data from the
+ * transport socket, parsing the RPC record stream (fragment
+ * headers and message bodies) and assembling complete RPC
+ * messages into rqstp->rq_pages.
  */
 static int svc_tcp_recv_actor(read_descriptor_t *desc,
 			      struct sk_buff *skb,
@@ -1266,7 +1081,21 @@ static int svc_tcp_rectype_actor(read_descriptor_t *desc,
 	return 0;
 }
 
-static int svc_tcp_recvfrom_readsock(struct svc_rqst *rqstp)
+/**
+ * svc_tcp_recvfrom - Receive data from a TCP socket
+ * @rqstp: request structure into which to receive an RPC Call
+ *
+ * Called in a loop when XPT_DATA has been set.
+ *
+ * Returns:
+ *   On success, the number of bytes in a received RPC Call, or
+ *   %0 if a complete RPC Call message was not ready to return
+ *
+ * The zero return case handles partial receives and callback Replies.
+ * The state of a partial receive is preserved in the svc_sock for
+ * the next call to svc_tcp_recvfrom.
+ */
+static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
 {
 	struct svc_sock	*svsk =
 		container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt);
@@ -1286,9 +1115,13 @@ static int svc_tcp_recvfrom_readsock(struct svc_rqst *rqstp)
 
 	desc.count = serv->sv_max_mesg;
 	lock_sock(sk);
-	len = svsk->sk_sock->ops->read_sock_rectype(sk, &desc,
-						    svc_tcp_recv_actor,
-						    svc_tcp_rectype_actor);
+	if (svsk->sk_sock->ops->read_sock_rectype)
+		len = svsk->sk_sock->ops->read_sock_rectype(sk, &desc,
+							    svc_tcp_recv_actor,
+							    svc_tcp_rectype_actor);
+	else
+		len = svsk->sk_sock->ops->read_sock(sk, &desc,
+						     svc_tcp_recv_actor);
 	release_sock(sk);
 
 	if (desc.error < 0) {
@@ -1375,116 +1208,6 @@ static int svc_tcp_recvfrom_readsock(struct svc_rqst *rqstp)
 	return 0;
 }
 
-/**
- * svc_tcp_recvfrom - Receive data from a TCP socket
- * @rqstp: request structure into which to receive an RPC Call
- *
- * Called in a loop when XPT_DATA has been set.
- *
- * Read the 4-byte stream record marker, then use the record length
- * in that marker to set up exactly the resources needed to receive
- * the next RPC message into @rqstp.
- *
- * Returns:
- *   On success, the number of bytes in a received RPC Call, or
- *   %0 if a complete RPC Call message was not ready to return
- *
- * The zero return case handles partial receives and callback Replies.
- * The state of a partial receive is preserved in the svc_sock for
- * the next call to svc_tcp_recvfrom.
- */
-static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
-{
-	struct svc_sock	*svsk =
-		container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt);
-	struct svc_serv	*serv = svsk->sk_xprt.xpt_server;
-	size_t want, base;
-	ssize_t len;
-	__be32 *p;
-	__be32 calldir;
-
-	if (svsk->sk_sock->ops->read_sock_rectype)
-		return svc_tcp_recvfrom_readsock(rqstp);
-
-	clear_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
-	len = svc_tcp_read_marker(svsk, rqstp);
-	if (len < 0)
-		goto error;
-
-	base = svc_tcp_restore_pages(svsk, rqstp);
-	want = len - (svsk->sk_tcplen - sizeof(rpc_fraghdr));
-	len = svc_tcp_read_msg(rqstp, base + want, base);
-	if (len >= 0) {
-		trace_svcsock_tcp_recv(&svsk->sk_xprt, len);
-		svsk->sk_tcplen += len;
-		svsk->sk_datalen += len;
-	}
-	if (len != want || !svc_sock_final_rec(svsk))
-		goto err_incomplete;
-	if (svsk->sk_datalen < 8)
-		goto err_nuts;
-
-	rqstp->rq_arg.len = svsk->sk_datalen;
-	rqstp->rq_arg.page_base = 0;
-	if (rqstp->rq_arg.len <= rqstp->rq_arg.head[0].iov_len) {
-		rqstp->rq_arg.head[0].iov_len = rqstp->rq_arg.len;
-		rqstp->rq_arg.page_len = 0;
-	} else
-		rqstp->rq_arg.page_len = rqstp->rq_arg.len - rqstp->rq_arg.head[0].iov_len;
-
-	rqstp->rq_xprt_ctxt   = NULL;
-	rqstp->rq_prot	      = IPPROTO_TCP;
-	if (test_bit(XPT_LOCAL, &svsk->sk_xprt.xpt_flags))
-		set_bit(RQ_LOCAL, &rqstp->rq_flags);
-	else
-		clear_bit(RQ_LOCAL, &rqstp->rq_flags);
-
-	p = (__be32 *)rqstp->rq_arg.head[0].iov_base;
-	calldir = p[1];
-	if (calldir)
-		len = receive_cb_reply(svsk, rqstp);
-
-	/* Reset TCP read info */
-	svsk->sk_datalen = 0;
-	svc_tcp_fragment_received(svsk);
-
-	if (len < 0)
-		goto error;
-
-	svc_xprt_copy_addrs(rqstp, &svsk->sk_xprt);
-	if (serv->sv_stats)
-		serv->sv_stats->nettcpcnt++;
-
-	svc_sock_secure_port(rqstp);
-	svc_xprt_received(rqstp->rq_xprt);
-	return rqstp->rq_arg.len;
-
-err_incomplete:
-	svc_tcp_save_pages(svsk, rqstp);
-	if (len < 0 && len != -EAGAIN)
-		goto err_delete;
-	if (len == want)
-		svc_tcp_fragment_received(svsk);
-	else
-		trace_svcsock_tcp_recv_short(&svsk->sk_xprt,
-				svc_sock_reclen(svsk),
-				svsk->sk_tcplen - sizeof(rpc_fraghdr));
-	goto err_noclose;
-error:
-	if (len != -EAGAIN)
-		goto err_delete;
-	trace_svcsock_tcp_recv_eagain(&svsk->sk_xprt, 0);
-	goto err_noclose;
-err_nuts:
-	svsk->sk_datalen = 0;
-err_delete:
-	trace_svcsock_tcp_recv_err(&svsk->sk_xprt, len);
-	svc_xprt_deferred_close(&svsk->sk_xprt);
-err_noclose:
-	svc_xprt_received(rqstp->rq_xprt);
-	return 0;	/* record not complete */
-}
-
 /*
  * MSG_SPLICE_PAGES is used exclusively to reduce the number of
  * copy operations in this path. Therefore the caller must ensure

-- 
2.54.0


^ permalink raw reply related


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