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
{
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;
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);
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;
}
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;
}
#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,
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
_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__ */