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>
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>
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,
6873MODULE_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+
7181struct 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+
7590static 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
15641579static 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+
16651729static 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" );
0 commit comments