diff mbox series

[net-next] net: ncsi: check for netlink-driven responses before requiring a handler

Message ID 20241028-ncsi-arb-opcode-v1-1-9d65080908b9@codeconstruct.com.au (mailing list archive)
State Changes Requested
Delegated to: Netdev Maintainers
Headers show
Series [net-next] net: ncsi: check for netlink-driven responses before requiring a handler | expand

Checks

Context Check Description
netdev/series_format success Single patches do not need cover letters
netdev/tree_selection success Clearly marked for net-next
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 5 this patch: 5
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers success CCed 6 of 6 maintainers
netdev/build_clang success Errors and warnings before: 3 this patch: 3
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 4 this patch: 4
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 82 lines checked
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0
netdev/contest success net-next-2024-10-31--09-00 (tests: 779)

Commit Message

Jeremy Kerr Oct. 28, 2024, 7:08 a.m. UTC
Currently, the NCSI response path will look up an opcode-specific
handler for all incoming response messages. However, we may be receiving
a response from a netlink-generated request, which may not have a
corresponding in-kernel handler for that request opcode. In that case,
we'll drop the response because we didn't find a opcode-specific
handler.

Perform the lookup for the pending request (and hence for
NETLINK_DRIVEN) before requiring an in-kernel handler, and defer the
requirement for a corresponding kernel request until we know it's a
kernel-driven command.

Signed-off-by: Jeremy Kerr <jk@codeconstruct.com.au>
---
 net/ncsi/ncsi-rsp.c | 61 ++++++++++++++++++++++++-----------------------------
 1 file changed, 27 insertions(+), 34 deletions(-)


---
base-commit: 03fc07a24735e0be8646563913abf5f5cb71ad19
change-id: 20241028-ncsi-arb-opcode-a346ddb88862

Best regards,

Comments

Simon Horman Nov. 2, 2024, 1:58 p.m. UTC | #1
On Mon, Oct 28, 2024 at 03:08:34PM +0800, Jeremy Kerr wrote:
> Currently, the NCSI response path will look up an opcode-specific
> handler for all incoming response messages. However, we may be receiving
> a response from a netlink-generated request, which may not have a
> corresponding in-kernel handler for that request opcode. In that case,
> we'll drop the response because we didn't find a opcode-specific
> handler.
> 
> Perform the lookup for the pending request (and hence for
> NETLINK_DRIVEN) before requiring an in-kernel handler, and defer the
> requirement for a corresponding kernel request until we know it's a
> kernel-driven command.
> 
> Signed-off-by: Jeremy Kerr <jk@codeconstruct.com.au>

Hi Jeremy,

Not strictly related to this patch, but I do wonder if the log messages
should be rate limited, which doesn't seem to be the case at this time.

Regardless, this looks good to me.

Reviewed-by: Simon Horman <horms@kernel.org>

...
Jakub Kicinski Nov. 3, 2024, 6:54 p.m. UTC | #2
On Mon, 28 Oct 2024 15:08:34 +0800 Jeremy Kerr wrote:
> Subject: [PATCH net-next] net: ncsi: check for netlink-driven responses before requiring a handler

> Currently, the NCSI response path will look up an opcode-specific
> handler for all incoming response messages. However, we may be receiving
> a response from a netlink-generated request, which may not have a
> corresponding in-kernel handler for that request opcode. In that case,
> we'll drop the response because we didn't find a opcode-specific
> handler.

This makes it sound like the code is written this way unintentionally,
which I doubt. A better description of the patch would be "allow
userspace to issue commands unknown to the kernel". And then it'd be
great to get some examples of commands you'd like to issue..

> Perform the lookup for the pending request (and hence for
> NETLINK_DRIVEN) before requiring an in-kernel handler, and defer the
> requirement for a corresponding kernel request until we know it's a
> kernel-driven command.

As for the code - delaying handling ret != 0 makes me worried that
someone will insert code in between and clobber it. Can you split
the handling so that all the ret != 0 (or EPERM for netlink)
are still handled in the if (ret) {} ?
Jeremy Kerr Nov. 4, 2024, 3:57 a.m. UTC | #3
Hi Jakub,

> > Currently, the NCSI response path will look up an opcode-specific
> > handler for all incoming response messages. However, we may be
> > receiving
> > a response from a netlink-generated request, which may not have a
> > corresponding in-kernel handler for that request opcode. In that
> > case,
> > we'll drop the response because we didn't find a opcode-specific
> > handler.
> 
> This makes it sound like the code is written this way
> unintentionally, which I doubt.

This seems like an oversight in the response path, failing on a missing
in-kernel handler even if we don't later use it. If we were
intentionally enforcing only known commands, then we'd also be checking
on the request side.

But yes, I can certainly word this in terms of what this change now
enables, and provide examples.

> > Perform the lookup for the pending request (and hence for
> > NETLINK_DRIVEN) before requiring an in-kernel handler, and defer
> > the
> > requirement for a corresponding kernel request until we know it's a
> > kernel-driven command.
> 
> As for the code - delaying handling ret != 0 makes me worried that
> someone will insert code in between and clobber it. Can you split
> the handling so that all the ret != 0 (or EPERM for netlink)
> are still handled in the if (ret) {} ?

Can do! The -EPERM case can probably be simplified a little too, as it
just indicates we didn't get a success response from the remote NCSI
device.

Will work on a v2 soon.

Cheers,


Jeremy
diff mbox series

Patch

diff --git a/net/ncsi/ncsi-rsp.c b/net/ncsi/ncsi-rsp.c
index e28be33bdf2c487c0fbfe3a1b4de6f52c8f923cc..882767c138895eba5bd7e413b7edb6480d5807bf 100644
--- a/net/ncsi/ncsi-rsp.c
+++ b/net/ncsi/ncsi-rsp.c
@@ -1205,12 +1205,6 @@  int ncsi_rcv_rsp(struct sk_buff *skb, struct net_device *dev,
 		}
 	}
 
-	if (!nrh) {
-		netdev_err(nd->dev, "Received unrecognized packet (0x%x)\n",
-			   hdr->type);
-		return -ENOENT;
-	}
-
 	/* Associate with the request */
 	spin_lock_irqsave(&ndp->lock, flags);
 	nr = &ndp->requests[hdr->id];
@@ -1228,43 +1222,42 @@  int ncsi_rcv_rsp(struct sk_buff *skb, struct net_device *dev,
 
 	/* Validate the packet */
 	spin_unlock_irqrestore(&ndp->lock, flags);
-	payload = nrh->payload;
+	payload = nrh ? nrh->payload : -1;
 	if (payload < 0)
 		payload = ntohs(hdr->length);
+
 	ret = ncsi_validate_rsp_pkt(nr, payload);
-	if (ret) {
+	if (ret)
 		netdev_warn(ndp->ndev.dev,
 			    "NCSI: 'bad' packet ignored for type 0x%x\n",
 			    hdr->type);
 
-		if (nr->flags == NCSI_REQ_FLAG_NETLINK_DRIVEN) {
-			if (ret == -EPERM)
-				goto out_netlink;
-			else
-				ncsi_send_netlink_err(ndp->ndev.dev,
-						      nr->snd_seq,
-						      nr->snd_portid,
-						      &nr->nlhdr,
-						      ret);
-		}
-		goto out;
-	}
-
-	/* Process the packet */
-	ret = nrh->handler(nr);
-	if (ret)
-		netdev_err(ndp->ndev.dev,
-			   "NCSI: Handler for packet type 0x%x returned %d\n",
-			   hdr->type, ret);
-
-out_netlink:
 	if (nr->flags == NCSI_REQ_FLAG_NETLINK_DRIVEN) {
-		ret = ncsi_rsp_handler_netlink(nr);
-		if (ret) {
-			netdev_err(ndp->ndev.dev,
-				   "NCSI: Netlink handler for packet type 0x%x returned %d\n",
-				   hdr->type, ret);
+		/* netlink driven: forward response to netlink socket */
+		if (!ret || ret == -EPERM)
+			ncsi_rsp_handler_netlink(nr);
+		else
+			ncsi_send_netlink_err(ndp->ndev.dev,
+					      nr->snd_seq,
+					      nr->snd_portid,
+					      &nr->nlhdr,
+					      ret);
+	} else if (nrh) {
+		/* not netlink driven: process the packet in the kernel. We
+		 * need to have a handler for this
+		 */
+		if (!ret) {
+			ret = nrh->handler(nr);
+			if (ret)
+				netdev_err(ndp->ndev.dev,
+					   "NCSI: Handler for packet type 0x%x returned %d\n",
+					   hdr->type, ret);
 		}
+
+	} else {
+		netdev_err(nd->dev, "Received unrecognized packet (0x%x)\n",
+			   hdr->type);
+		ret = -ENOENT;
 	}
 
 out: