xen: XSA-482 security patches for v7.0

-----BEGIN PGP SIGNATURE-----
 
 iJEEABYKADkWIQRTLbB6QfY48x44uB6AXGG7T9hjvgUCab0z0RsUgAAAAAAEAA5t
 YW51MiwyLjUrMS4xMiwyLDIACgkQgFxhu0/YY76sUQD+OJZtGt6EIA5mO1fMZqRb
 gVXfyDHIIMvdFPkCXSXZqTABAJlJfefjm6b17kW6yNNcs3OUmp4IFqMPv1kJVwY+
 XpIB
 =oMtv
 -----END PGP SIGNATURE-----

Merge tag 'xsa482-7.0-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip

Pull xen fixes from Juergen Gross:
 "Restrict the xen privcmd driver in unprivileged domU to only allow
  hypercalls to target domain when using secure boot"

* tag 'xsa482-7.0-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip:
  xen/privcmd: add boot control for restricted usage in domU
  xen/privcmd: restrict usage in unprivileged domU
This commit is contained in:
Linus Torvalds 2026-03-23 21:30:14 -07:00
commit a0124352d5
3 changed files with 72 additions and 3 deletions

View File

@ -12,6 +12,7 @@
#include <linux/eventfd.h>
#include <linux/file.h>
#include <linux/kernel.h>
#include <linux/kstrtox.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/poll.h>
@ -30,7 +31,10 @@
#include <linux/seq_file.h>
#include <linux/miscdevice.h>
#include <linux/moduleparam.h>
#include <linux/notifier.h>
#include <linux/security.h>
#include <linux/virtio_mmio.h>
#include <linux/wait.h>
#include <asm/xen/hypervisor.h>
#include <asm/xen/hypercall.h>
@ -46,6 +50,7 @@
#include <xen/page.h>
#include <xen/xen-ops.h>
#include <xen/balloon.h>
#include <xen/xenbus.h>
#ifdef CONFIG_XEN_ACPI
#include <xen/acpi.h>
#endif
@ -68,10 +73,20 @@ module_param_named(dm_op_buf_max_size, privcmd_dm_op_buf_max_size, uint,
MODULE_PARM_DESC(dm_op_buf_max_size,
"Maximum size of a dm_op hypercall buffer");
static bool unrestricted;
module_param(unrestricted, bool, 0);
MODULE_PARM_DESC(unrestricted,
"Don't restrict hypercalls to target domain if running in a domU");
struct privcmd_data {
domid_t domid;
};
/* DOMID_INVALID implies no restriction */
static domid_t target_domain = DOMID_INVALID;
static bool restrict_wait;
static DECLARE_WAIT_QUEUE_HEAD(restrict_wait_wq);
static int privcmd_vma_range_is_mapped(
struct vm_area_struct *vma,
unsigned long addr,
@ -1563,13 +1578,16 @@ static long privcmd_ioctl(struct file *file,
static int privcmd_open(struct inode *ino, struct file *file)
{
struct privcmd_data *data = kzalloc_obj(*data);
struct privcmd_data *data;
if (wait_event_interruptible(restrict_wait_wq, !restrict_wait) < 0)
return -EINTR;
data = kzalloc_obj(*data);
if (!data)
return -ENOMEM;
/* DOMID_INVALID implies no restriction */
data->domid = DOMID_INVALID;
data->domid = target_domain;
file->private_data = data;
return 0;
@ -1662,6 +1680,52 @@ static struct miscdevice privcmd_dev = {
.fops = &xen_privcmd_fops,
};
static int init_restrict(struct notifier_block *notifier,
unsigned long event,
void *data)
{
char *target;
unsigned int domid;
/* Default to an guaranteed unused domain-id. */
target_domain = DOMID_IDLE;
target = xenbus_read(XBT_NIL, "target", "", NULL);
if (IS_ERR(target) || kstrtouint(target, 10, &domid)) {
pr_err("No target domain found, blocking all hypercalls\n");
goto out;
}
target_domain = domid;
out:
if (!IS_ERR(target))
kfree(target);
restrict_wait = false;
wake_up_all(&restrict_wait_wq);
return NOTIFY_DONE;
}
static struct notifier_block xenstore_notifier = {
.notifier_call = init_restrict,
};
static void __init restrict_driver(void)
{
if (unrestricted) {
if (security_locked_down(LOCKDOWN_XEN_USER_ACTIONS))
pr_warn("Kernel is locked down, parameter \"unrestricted\" ignored\n");
else
return;
}
restrict_wait = true;
register_xenstore_notifier(&xenstore_notifier);
}
static int __init privcmd_init(void)
{
int err;
@ -1669,6 +1733,9 @@ static int __init privcmd_init(void)
if (!xen_domain())
return -ENODEV;
if (!xen_initial_domain())
restrict_driver();
err = misc_register(&privcmd_dev);
if (err != 0) {
pr_err("Could not register Xen privcmd device\n");

View File

@ -145,6 +145,7 @@ enum lockdown_reason {
LOCKDOWN_BPF_WRITE_USER,
LOCKDOWN_DBG_WRITE_KERNEL,
LOCKDOWN_RTAS_ERROR_INJECTION,
LOCKDOWN_XEN_USER_ACTIONS,
LOCKDOWN_INTEGRITY_MAX,
LOCKDOWN_KCORE,
LOCKDOWN_KPROBES,

View File

@ -61,6 +61,7 @@ const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX + 1] = {
[LOCKDOWN_BPF_WRITE_USER] = "use of bpf to write user RAM",
[LOCKDOWN_DBG_WRITE_KERNEL] = "use of kgdb/kdb to write kernel RAM",
[LOCKDOWN_RTAS_ERROR_INJECTION] = "RTAS error injection",
[LOCKDOWN_XEN_USER_ACTIONS] = "Xen guest user action",
[LOCKDOWN_INTEGRITY_MAX] = "integrity",
[LOCKDOWN_KCORE] = "/proc/kcore access",
[LOCKDOWN_KPROBES] = "use of kprobes",