git: 50c962d77370 - main - krpc/clnt_nl: filter RPC replies on vnet
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 01 Feb 2025 19:33:55 UTC
The branch main has been updated by glebius:
URL: https://cgit.FreeBSD.org/src/commit/?id=50c962d773705f60d32c29f8e4bb2743ab55733b
commit 50c962d773705f60d32c29f8e4bb2743ab55733b
Author: Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2025-02-01 19:27:22 +0000
Commit: Gleb Smirnoff <glebius@FreeBSD.org>
CommitDate: 2025-02-01 19:27:22 +0000
krpc/clnt_nl: filter RPC replies on vnet
RPC calls are filtered by the Netlink system itself, but the RPC replies
are not. With legitimate use the chance of a xid collision is zero, since
global clients use global atomically updated 32-bit counter for that.
However, a malicious jail may blindly inject replies guessing the xid,
where guessing is trivial. Protect against that checking the vnet, too.
---
sys/rpc/clnt_nl.c | 13 ++++++++++++-
sys/rpc/krpc.h | 5 ++++-
2 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/sys/rpc/clnt_nl.c b/sys/rpc/clnt_nl.c
index 8f841e4240d7..177566232cb5 100644
--- a/sys/rpc/clnt_nl.c
+++ b/sys/rpc/clnt_nl.c
@@ -269,10 +269,15 @@ clnt_nl_call(CLIENT *cl, struct rpc_callextra *ext, rpcproc_t proc,
u_int retries = 0;
bool rv __diagused;
+ CURVNET_ASSERT_SET();
+
cr = malloc(sizeof(struct ct_request), M_RPC, M_WAITOK);
*cr = (struct ct_request){
.cr_xid = atomic_fetchadd_32(&nl->nl_xid, 1),
.cr_error = ETIMEDOUT,
+#ifdef VIMAGE
+ .cr_vnet = curvnet,
+#endif
};
if (ext) {
@@ -394,6 +399,8 @@ clnt_nl_reply(struct nlmsghdr *hdr, struct nl_pstate *npt)
struct mchain mc;
int error;
+ CURVNET_ASSERT_SET();
+
if ((error = nl_parse_nlmsg(hdr, &rpcnl_parser, npt, &attrs)) != 0)
return (error);
if (attrs.data == NULL)
@@ -415,7 +422,11 @@ clnt_nl_reply(struct nlmsghdr *hdr, struct nl_pstate *npt)
rw_runlock(&rpcnl_global_lock);
TAILQ_FOREACH(cr, &nl->nl_pending, cr_link)
- if (cr->cr_xid == hdr->nlmsg_seq)
+ if (cr->cr_xid == hdr->nlmsg_seq
+#ifdef VIMAGE
+ && cr->cr_vnet == curvnet
+#endif
+ )
break;
if (cr == NULL) {
mtx_unlock(&nl->nl_lock);
diff --git a/sys/rpc/krpc.h b/sys/rpc/krpc.h
index 06aa14eeb91f..f77e2d2d7428 100644
--- a/sys/rpc/krpc.h
+++ b/sys/rpc/krpc.h
@@ -49,8 +49,11 @@ struct mbuf *_rpc_copym_into_ext_pgs(struct mbuf *, int);
*/
struct ct_request {
TAILQ_ENTRY(ct_request) cr_link;
- uint32_t cr_xid; /* XID of request */
struct mbuf *cr_mrep; /* reply received by upcall */
+#ifdef VIMAGE
+ struct vnet *cr_vnet;
+#endif
+ uint32_t cr_xid; /* XID of request */
int cr_error; /* any error from upcall */
char cr_verf[MAX_AUTH_BYTES]; /* reply verf */
};