mirror of https://github.com/torvalds/linux.git
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:
commit
a0124352d5
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
Loading…
Reference in New Issue