From e40cb27ee4fb7b794e605cd881185cb33ce6cbd7 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Mon, 20 Jul 2026 16:44:12 +0100 Subject: [PATCH] sysctl/XSM: drop .readconsole() hook Integrate the checking with xsm_sysctl(), now that it has the full op struct passed. As a positive side effect, permissions are then checked at the same early point with and without Flask. This is part of CVE-2026-62426 / XSA-499. Signed-off-by: Jan Beulich Reviewed-by: Andrew Cooper Acked-By: Daniel P. Smith (cherry picked from commit 4b249cba4b25ad1b5c86bf3b2ff9cc685b47fa67) --- xen/common/sysctl.c | 4 ---- xen/include/xsm/dummy.h | 6 ------ xen/include/xsm/xsm.h | 6 ------ xen/xsm/dummy.c | 1 - xen/xsm/flask/hooks.c | 18 ++++++------------ 5 files changed, 6 insertions(+), 29 deletions(-) diff --git a/xen/common/sysctl.c b/xen/common/sysctl.c index 5844c52056..011def5bb2 100644 --- a/xen/common/sysctl.c +++ b/xen/common/sysctl.c @@ -59,10 +59,6 @@ long do_sysctl(XEN_GUEST_HANDLE_PARAM(xen_sysctl_t) u_sysctl) switch ( op->cmd ) { case XEN_SYSCTL_readconsole: - ret = xsm_readconsole(XSM_HOOK, op->u.readconsole.clear); - if ( ret ) - break; - ret = read_console_ring(&op->u.readconsole); break; diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h index 54b50e9a46..aacef701a9 100644 --- a/xen/include/xsm/dummy.h +++ b/xen/include/xsm/dummy.h @@ -179,12 +179,6 @@ static XSM_INLINE int cf_check xsm_sysctl( return xsm_default_action(action, current->domain, NULL); } -static XSM_INLINE int cf_check xsm_readconsole(XSM_DEFAULT_ARG uint32_t clear) -{ - XSM_ASSERT_ACTION(XSM_HOOK); - return xsm_default_action(action, current->domain, NULL); -} - static XSM_INLINE int cf_check xsm_alloc_security_domain(struct domain *d) { return 0; diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h index 25469378ae..87e277aa38 100644 --- a/xen/include/xsm/xsm.h +++ b/xen/include/xsm/xsm.h @@ -60,7 +60,6 @@ struct xsm_ops { int (*set_target)(struct domain *d, struct domain *e); int (*domctl)(struct domain *d, struct xen_domctl *op); int (*sysctl)(const struct xen_sysctl *op); - int (*readconsole)(uint32_t clear); int (*evtchn_unbound)(struct domain *d, struct evtchn *chn, domid_t id2); int (*evtchn_interdomain)(struct domain *d1, struct evtchn *chn1, @@ -238,11 +237,6 @@ static inline int xsm_sysctl(xsm_default_t def, const struct xen_sysctl *op) return alternative_call(xsm_ops.sysctl, op); } -static inline int xsm_readconsole(xsm_default_t def, uint32_t clear) -{ - return alternative_call(xsm_ops.readconsole, clear); -} - static inline int xsm_evtchn_unbound( xsm_default_t def, struct domain *d1, struct evtchn *chn, domid_t id2) { diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c index 99c68e403a..97c06ee522 100644 --- a/xen/xsm/dummy.c +++ b/xen/xsm/dummy.c @@ -21,7 +21,6 @@ static const struct xsm_ops __initconst_cf_clobber dummy_ops = { .set_target = xsm_set_target, .domctl = xsm_domctl, .sysctl = xsm_sysctl, - .readconsole = xsm_readconsole, .evtchn_unbound = xsm_evtchn_unbound, .evtchn_interdomain = xsm_evtchn_interdomain, diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index b21f379a84..654b8afbea 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -897,13 +897,18 @@ static int cf_check flask_sysctl(const struct xen_sysctl *op) switch ( op->cmd ) { /* These have individual XSM hooks */ - case XEN_SYSCTL_readconsole: case XEN_SYSCTL_page_offline_op: #ifdef CONFIG_X86 case XEN_SYSCTL_cpu_hotplug: #endif return 0; + case XEN_SYSCTL_readconsole: + return domain_has_xen(current->domain, + XEN__READCONSOLE | + (op->u.readconsole.clear ? XEN__CLEARCONSOLE + : 0)); + case XEN_SYSCTL_tbuf_op: return domain_has_xen(current->domain, XEN__TBUFCONTROL); @@ -974,16 +979,6 @@ static int cf_check flask_sysctl(const struct xen_sysctl *op) } } -static int cf_check flask_readconsole(uint32_t clear) -{ - uint32_t perms = XEN__READCONSOLE; - - if ( clear ) - perms |= XEN__CLEARCONSOLE; - - return domain_has_xen(current->domain, perms); -} - static inline uint32_t resource_to_perm(uint8_t access) { if ( access ) @@ -1909,7 +1904,6 @@ static const struct xsm_ops __initconst_cf_clobber flask_ops = { .set_target = flask_set_target, .domctl = flask_domctl, .sysctl = flask_sysctl, - .readconsole = flask_readconsole, .evtchn_unbound = flask_evtchn_unbound, .evtchn_interdomain = flask_evtchn_interdomain,