Skip to content

Commit a012435

Browse files
committed
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
2 parents c369299 + 1613462 commit a012435

3 files changed

Lines changed: 72 additions & 3 deletions

File tree

drivers/xen/privcmd.c

Lines changed: 70 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <linux/eventfd.h>
1313
#include <linux/file.h>
1414
#include <linux/kernel.h>
15+
#include <linux/kstrtox.h>
1516
#include <linux/module.h>
1617
#include <linux/mutex.h>
1718
#include <linux/poll.h>
@@ -30,7 +31,10 @@
3031
#include <linux/seq_file.h>
3132
#include <linux/miscdevice.h>
3233
#include <linux/moduleparam.h>
34+
#include <linux/notifier.h>
35+
#include <linux/security.h>
3336
#include <linux/virtio_mmio.h>
37+
#include <linux/wait.h>
3438

3539
#include <asm/xen/hypervisor.h>
3640
#include <asm/xen/hypercall.h>
@@ -46,6 +50,7 @@
4650
#include <xen/page.h>
4751
#include <xen/xen-ops.h>
4852
#include <xen/balloon.h>
53+
#include <xen/xenbus.h>
4954
#ifdef CONFIG_XEN_ACPI
5055
#include <xen/acpi.h>
5156
#endif
@@ -68,10 +73,20 @@ module_param_named(dm_op_buf_max_size, privcmd_dm_op_buf_max_size, uint,
6873
MODULE_PARM_DESC(dm_op_buf_max_size,
6974
"Maximum size of a dm_op hypercall buffer");
7075

76+
static bool unrestricted;
77+
module_param(unrestricted, bool, 0);
78+
MODULE_PARM_DESC(unrestricted,
79+
"Don't restrict hypercalls to target domain if running in a domU");
80+
7181
struct privcmd_data {
7282
domid_t domid;
7383
};
7484

85+
/* DOMID_INVALID implies no restriction */
86+
static domid_t target_domain = DOMID_INVALID;
87+
static bool restrict_wait;
88+
static DECLARE_WAIT_QUEUE_HEAD(restrict_wait_wq);
89+
7590
static int privcmd_vma_range_is_mapped(
7691
struct vm_area_struct *vma,
7792
unsigned long addr,
@@ -1563,13 +1578,16 @@ static long privcmd_ioctl(struct file *file,
15631578

15641579
static int privcmd_open(struct inode *ino, struct file *file)
15651580
{
1566-
struct privcmd_data *data = kzalloc_obj(*data);
1581+
struct privcmd_data *data;
1582+
1583+
if (wait_event_interruptible(restrict_wait_wq, !restrict_wait) < 0)
1584+
return -EINTR;
15671585

1586+
data = kzalloc_obj(*data);
15681587
if (!data)
15691588
return -ENOMEM;
15701589

1571-
/* DOMID_INVALID implies no restriction */
1572-
data->domid = DOMID_INVALID;
1590+
data->domid = target_domain;
15731591

15741592
file->private_data = data;
15751593
return 0;
@@ -1662,13 +1680,62 @@ static struct miscdevice privcmd_dev = {
16621680
.fops = &xen_privcmd_fops,
16631681
};
16641682

1683+
static int init_restrict(struct notifier_block *notifier,
1684+
unsigned long event,
1685+
void *data)
1686+
{
1687+
char *target;
1688+
unsigned int domid;
1689+
1690+
/* Default to an guaranteed unused domain-id. */
1691+
target_domain = DOMID_IDLE;
1692+
1693+
target = xenbus_read(XBT_NIL, "target", "", NULL);
1694+
if (IS_ERR(target) || kstrtouint(target, 10, &domid)) {
1695+
pr_err("No target domain found, blocking all hypercalls\n");
1696+
goto out;
1697+
}
1698+
1699+
target_domain = domid;
1700+
1701+
out:
1702+
if (!IS_ERR(target))
1703+
kfree(target);
1704+
1705+
restrict_wait = false;
1706+
wake_up_all(&restrict_wait_wq);
1707+
1708+
return NOTIFY_DONE;
1709+
}
1710+
1711+
static struct notifier_block xenstore_notifier = {
1712+
.notifier_call = init_restrict,
1713+
};
1714+
1715+
static void __init restrict_driver(void)
1716+
{
1717+
if (unrestricted) {
1718+
if (security_locked_down(LOCKDOWN_XEN_USER_ACTIONS))
1719+
pr_warn("Kernel is locked down, parameter \"unrestricted\" ignored\n");
1720+
else
1721+
return;
1722+
}
1723+
1724+
restrict_wait = true;
1725+
1726+
register_xenstore_notifier(&xenstore_notifier);
1727+
}
1728+
16651729
static int __init privcmd_init(void)
16661730
{
16671731
int err;
16681732

16691733
if (!xen_domain())
16701734
return -ENODEV;
16711735

1736+
if (!xen_initial_domain())
1737+
restrict_driver();
1738+
16721739
err = misc_register(&privcmd_dev);
16731740
if (err != 0) {
16741741
pr_err("Could not register Xen privcmd device\n");

include/linux/security.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ enum lockdown_reason {
145145
LOCKDOWN_BPF_WRITE_USER,
146146
LOCKDOWN_DBG_WRITE_KERNEL,
147147
LOCKDOWN_RTAS_ERROR_INJECTION,
148+
LOCKDOWN_XEN_USER_ACTIONS,
148149
LOCKDOWN_INTEGRITY_MAX,
149150
LOCKDOWN_KCORE,
150151
LOCKDOWN_KPROBES,

security/security.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX + 1] = {
6161
[LOCKDOWN_BPF_WRITE_USER] = "use of bpf to write user RAM",
6262
[LOCKDOWN_DBG_WRITE_KERNEL] = "use of kgdb/kdb to write kernel RAM",
6363
[LOCKDOWN_RTAS_ERROR_INJECTION] = "RTAS error injection",
64+
[LOCKDOWN_XEN_USER_ACTIONS] = "Xen guest user action",
6465
[LOCKDOWN_INTEGRITY_MAX] = "integrity",
6566
[LOCKDOWN_KCORE] = "/proc/kcore access",
6667
[LOCKDOWN_KPROBES] = "use of kprobes",

0 commit comments

Comments
 (0)