[PATCH OLK-6.6 0/3] Xen privcmd driver: restrict to target domain at boot when not in dom0 to fix secure boot issue
Patch 1: Restrict the privcmd driver in unprivileged domU to only allow hypercalls targeting a specific domain obtained from Xenstore, preventing secure boot bypass. Patch 2: Unregister the xenstore notifier on module exit to clean up resources added by patch 1. Patch 3: Add an unrestricted boot parameter to optionally allow all hypercalls when secure boot is not active, guarded by a new lockdown reason. GuoHan Zhao (1): xen/privcmd: unregister xenstore notifier on module exit Juergen Gross (2): xen/privcmd: restrict usage in unprivileged domU xen/privcmd: add boot control for restricted usage in domU drivers/xen/privcmd.c | 78 +++++++++++++++++++++++++++++++++++++--- include/linux/security.h | 1 + security/security.c | 1 + 3 files changed, 75 insertions(+), 5 deletions(-) -- 2.22.0
From: Juergen Gross <jgross@suse.com> mainline inclusion from mainline-v7.0-rc6 commit 453b8fb68f3641fea970db88b7d9a153ed2a37e8 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/14027 CVE: CVE-2026-31788 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... -------------------------------- The Xen privcmd driver allows to issue arbitrary hypercalls from user space processes. This is normally no problem, as access is usually limited to root and the hypervisor will deny any hypercalls affecting other domains. In case the guest is booted using secure boot, however, the privcmd driver would be enabling a root user process to modify e.g. kernel memory contents, thus breaking the secure boot feature. The only known case where an unprivileged domU is really needing to use the privcmd driver is the case when it is acting as the device model for another guest. In this case all hypercalls issued via the privcmd driver will target that other guest. Fortunately the privcmd driver can already be locked down to allow only hypercalls targeting a specific domain, but this mode can be activated from user land only today. The target domain can be obtained from Xenstore, so when not running in dom0 restrict the privcmd driver to that target domain from the beginning, resolving the potential problem of breaking secure boot. This is XSA-482 Reported-by: Teddy Astie <teddy.astie@vates.tech> Fixes: 1c5de1939c20 ("xen: add privcmd driver") Signed-off-by: Juergen Gross <jgross@suse.com> Conflicts: drivers/xen/privcmd.c [commit bf4afc53b77ae not merged] Signed-off-by: Zhang Yuwei <zhangyuwei20@huawei.com> --- drivers/xen/privcmd.c | 62 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 57 insertions(+), 5 deletions(-) diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c index 61aaded483e1..3c97710fc094 100644 --- a/drivers/xen/privcmd.c +++ b/drivers/xen/privcmd.c @@ -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,8 @@ #include <linux/seq_file.h> #include <linux/miscdevice.h> #include <linux/moduleparam.h> - +#include <linux/notifier.h> +#include <linux/wait.h> #include <asm/xen/hypervisor.h> #include <asm/xen/hypercall.h> @@ -43,7 +45,7 @@ #include <xen/page.h> #include <xen/xen-ops.h> #include <xen/balloon.h> - +#include <xen/xenbus.h> #include "privcmd.h" MODULE_LICENSE("GPL"); @@ -65,6 +67,11 @@ 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, @@ -1156,13 +1163,16 @@ static long privcmd_ioctl(struct file *file, static int privcmd_open(struct inode *ino, struct file *file) { - struct privcmd_data *data = kzalloc(sizeof(*data), GFP_KERNEL); + struct privcmd_data *data; + if (wait_event_interruptible(restrict_wait_wq, !restrict_wait) < 0) + return -EINTR; + + data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; - /* DOMID_INVALID implies no restriction */ - data->domid = DOMID_INVALID; + data->domid = target_domain; file->private_data = data; return 0; @@ -1255,6 +1265,45 @@ 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) +{ + restrict_wait = true; + + register_xenstore_notifier(&xenstore_notifier); +} + static int __init privcmd_init(void) { int err; @@ -1262,6 +1311,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"); -- 2.22.0
From: GuoHan Zhao <zhaoguohan@kylinos.cn> mainline inclusion from mainline-v7.0-rc6 commit cd7e1fef5a1ca1c4fcd232211962ac2395601636 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/14027 CVE: CVE-2026-31788 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... -------------------------------- Commit 453b8fb68f36 ("xen/privcmd: restrict usage in unprivileged domU") added a xenstore notifier to defer setting the restriction target until Xenstore is ready. XEN_PRIVCMD can be built as a module, but privcmd_exit() leaves that notifier behind. Balance the notifier lifecycle by unregistering it on module exit. This is harmless even if xenstore was already ready at registration time and the notifier was never queued on the chain. Fixes: 453b8fb68f36 ("xen/privcmd: restrict usage in unprivileged domU") Signed-off-by: GuoHan Zhao <zhaoguohan@kylinos.cn> Reviewed-by: Juergen Gross <jgross@suse.com> Signed-off-by: Juergen Gross <jgross@suse.com> Message-ID: <20260325120246.252899-1-zhaoguohan@kylinos.cn> Conflicts: drivers/xen/privcmd.c [commit f0d7db7b33243 not merged] Signed-off-by: Zhang Yuwei <zhangyuwei20@huawei.com> --- drivers/xen/privcmd.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c index 3c97710fc094..29bb4ea7af9b 100644 --- a/drivers/xen/privcmd.c +++ b/drivers/xen/privcmd.c @@ -1343,6 +1343,9 @@ static int __init privcmd_init(void) static void __exit privcmd_exit(void) { + if (!xen_initial_domain()) + unregister_xenstore_notifier(&xenstore_notifier); + privcmd_irqfd_exit(); misc_deregister(&privcmd_dev); misc_deregister(&xen_privcmdbuf_dev); -- 2.22.0
From: Juergen Gross <jgross@suse.com> mainline inclusion from mainline-v7.0-rc6 commit 1613462be621ad5103ec338a7b0ca0746ec4e5f1 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/14027 CVE: CVE-2026-31788 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... -------------------------------- When running in an unprivileged domU under Xen, the privcmd driver is restricted to allow only hypercalls against a target domain, for which the current domU is acting as a device model. Add a boot parameter "unrestricted" to allow all hypercalls (the hypervisor will still refuse destructive hypercalls affecting other guests). Make this new parameter effective only in case the domU wasn't started using secure boot, as otherwise hypercalls targeting the domU itself might result in violating the secure boot functionality. This is achieved by adding another lockdown reason, which can be tested to not being set when applying the "unrestricted" option. This is part of XSA-482 Signed-off-by: Juergen Gross <jgross@suse.com> Conflicts: drivers/xen/privcmd.c [commit f0d7db7b33243 not merged] Signed-off-by: Zhang Yuwei <zhangyuwei20@huawei.com> --- drivers/xen/privcmd.c | 13 +++++++++++++ include/linux/security.h | 1 + security/security.c | 1 + 3 files changed, 15 insertions(+) diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c index 29bb4ea7af9b..74d6a2bd6d04 100644 --- a/drivers/xen/privcmd.c +++ b/drivers/xen/privcmd.c @@ -32,6 +32,7 @@ #include <linux/miscdevice.h> #include <linux/moduleparam.h> #include <linux/notifier.h> +#include <linux/security.h> #include <linux/wait.h> #include <asm/xen/hypervisor.h> #include <asm/xen/hypercall.h> @@ -63,6 +64,11 @@ 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; }; @@ -1299,6 +1305,13 @@ static struct notifier_block xenstore_notifier = { 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); diff --git a/include/linux/security.h b/include/linux/security.h index 4bd0f6fc553e..937840870d86 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -125,6 +125,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, diff --git a/security/security.c b/security/security.c index 839e12addac7..66edcbcd1a97 100644 --- a/security/security.c +++ b/security/security.c @@ -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", -- 2.22.0
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://atomgit.com/openeuler/kernel/merge_requests/21619 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/XUJ... FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://atomgit.com/openeuler/kernel/merge_requests/21619 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/XUJ...
participants (2)
-
patchwork bot -
Zhang Yuwei