]> xenbits.xen.org Git - xenclient/kernel.git/commitdiff
Add a RESTRICT ioctl to /proc/xen/privcmd, which allows a privcommand restricted-evtchn-dev
authort_jeang <devnull@localhost>
Tue, 6 Jan 2009 12:06:04 +0000 (12:06 +0000)
committert_jeang <devnull@localhost>
Tue, 6 Jan 2009 12:06:04 +0000 (12:06 +0000)
file descriptor to be restricted to only work with one domain.

Certain difficult operations, like hypercalls, are prohibited completely
on restricted handles.

drivers/xen/privcmd/privcmd.c
include/xen/public/privcmd.h

index 845406e463ae4b15f70f81843f3c7630bfba7a15..5f65956714c972f301e035be73b724e0ecea0ff7 100644 (file)
 static struct proc_dir_entry *privcmd_intf;
 static struct proc_dir_entry *capabilities_intf;
 
+struct privcmd_filp_data {
+    domid_t restrict_domid;
+};
+
+#define UNRESTRICTED_DOMID ((domid_t)-1)
+
 #ifndef HAVE_ARCH_PRIVCMD_MMAP
 static int privcmd_enforce_singleshot_mapping(struct vm_area_struct *vma);
 #endif
@@ -42,11 +48,15 @@ static long privcmd_ioctl(struct file *file,
 {
        int ret = -ENOSYS;
        void __user *udata = (void __user *) data;
+        struct privcmd_filp_data *fdata = file->private_data;
 
        switch (cmd) {
        case IOCTL_PRIVCMD_HYPERCALL: {
                privcmd_hypercall_t hypercall;
   
+                if (fdata->restrict_domid != UNRESTRICTED_DOMID)
+                        return -EACCES;
+
                if (copy_from_user(&hypercall, udata, sizeof(hypercall)))
                        return -EFAULT;
 
@@ -110,6 +120,10 @@ static long privcmd_ioctl(struct file *file,
                if (copy_from_user(&mmapcmd, udata, sizeof(mmapcmd)))
                        return -EFAULT;
 
+                if (fdata->restrict_domid != UNRESTRICTED_DOMID &&
+                    fdata->restrict_domid != mmapcmd.dom)
+                        return -EACCES;
+
                p = mmapcmd.entry;
                for (i = 0; i < mmapcmd.num;) {
                        int nr = min(mmapcmd.num - i, MMAP_NR_PER_PAGE);
@@ -204,6 +218,10 @@ static long privcmd_ioctl(struct file *file,
                if (copy_from_user(&m, udata, sizeof(m)))
                        return -EFAULT;
 
+                if (fdata->restrict_domid != UNRESTRICTED_DOMID &&
+                    fdata->restrict_domid != m.dom)
+                        return -EACCES;
+
                nr_pages = m.num;
                if ((m.num <= 0) || (nr_pages > (LONG_MAX >> PAGE_SHIFT)))
                        return -EINVAL;
@@ -279,6 +297,20 @@ static long privcmd_ioctl(struct file *file,
        }
        break;
 
+        case IOCTL_PRIVCMD_RESTRICT_DOMID: {
+               privcmd_restrict_domid_t prd;
+
+                if (fdata->restrict_domid != UNRESTRICTED_DOMID)
+                        return -EACCES;
+                if (copy_from_user(&prd, udata, sizeof(prd)))
+                        return -EFAULT;
+                if (prd.domid >= DOMID_FIRST_RESERVED)
+                        return -EINVAL;
+                fdata->restrict_domid = prd.domid;
+                ret = 0;
+        }
+        break;
+
        default:
                ret = -EINVAL;
                break;
@@ -319,9 +351,29 @@ static int privcmd_enforce_singleshot_mapping(struct vm_area_struct *vma)
 }
 #endif
 
+static int privcmd_open(struct inode *ino, struct file *filp)
+{
+        struct privcmd_filp_data *fd;
+        fd = kmalloc(sizeof(*fd), GFP_KERNEL);
+        if (!fd)
+                return -ENOMEM;
+        fd->restrict_domid = UNRESTRICTED_DOMID;
+        filp->private_data = fd;
+        return 0;
+}
+
+static int privcmd_release(struct inode *ino, struct file *filp)
+{
+        struct privcmd_filp_data *fd = filp->private_data;
+        kfree(fd);
+        return 0;
+}
+
 static const struct file_operations privcmd_file_ops = {
        .unlocked_ioctl = privcmd_ioctl,
        .mmap = privcmd_mmap,
+        .open = privcmd_open,
+        .release = privcmd_release
 };
 
 static int capabilities_read(char *page, char **start, off_t off,
index d1162eebb0b19b2d8de91c324bf1d30919fca86c..1d1965690eaa58f3a39eee78392624037a465620 100644 (file)
@@ -64,6 +64,10 @@ typedef struct privcmd_mmapbatch {
        xen_pfn_t __user *arr; /* array of mfns - top nibble set on err */
 } privcmd_mmapbatch_t; 
 
+typedef struct privcmd_restrict_domid {
+       domid_t domid;
+} privcmd_restrict_domid_t;
+
 /*
  * @cmd: IOCTL_PRIVCMD_HYPERCALL
  * @arg: &privcmd_hypercall_t
@@ -75,5 +79,7 @@ typedef struct privcmd_mmapbatch {
        _IOC(_IOC_NONE, 'P', 2, sizeof(privcmd_mmap_t))
 #define IOCTL_PRIVCMD_MMAPBATCH                                        \
        _IOC(_IOC_NONE, 'P', 3, sizeof(privcmd_mmapbatch_t))
+#define IOCTL_PRIVCMD_RESTRICT_DOMID                           \
+       _IOC(_IOC_NONE, 'P', 4, sizeof(privcmd_restrict_domid_t))
 
 #endif /* __LINUX_PUBLIC_PRIVCMD_H__ */