The branch main has been updated by glebius:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=50c962d773705f60d32c29f8e4bb2743ab55733b

commit 50c962d773705f60d32c29f8e4bb2743ab55733b
Author:     Gleb Smirnoff <gleb...@freebsd.org>
AuthorDate: 2025-02-01 19:27:22 +0000
Commit:     Gleb Smirnoff <gleb...@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 */
 };

Reply via email to