Mailing List Archive

[linux-2.6.18-xen] xen/privcmd: fix for proper operation in compat mode
# HG changeset patch
# User Keir Fraser <keir.fraser@citrix.com>
# Date 1262767089 0
# Node ID aa133dee7792aeb3d2a1aad90de7aa0d933e427e
# Parent 2b2d888e5a804c81dc5a1dcd0de4cf5e83106bf4
xen/privcmd: fix for proper operation in compat mode

- sizeof(struct privcmd_mmapbatch_32) was wrong
- MFN array must be translated for IOCTL_PRIVCMD_MMAPBATCH

Also, the error indicator of IOCTL_PRIVCMD_MMAPBATCH should be in the
top nibble (it is documented that way in include/xen/public/privcmd.h
and include/xen/compat_ioctl.h), but since that is an incompatible
change it is not being done here (instead, a new ioctl with proper
behavior will need to be added).

Signed-off-by: Jan Beulich <jbeulich@novell.com>
---
drivers/xen/privcmd/compat_privcmd.c | 36 +++++++++++++++++++++++++++++++++--
include/xen/compat_ioctl.h | 12 +++++++++++
2 files changed, 46 insertions(+), 2 deletions(-)

diff -r 2b2d888e5a80 -r aa133dee7792 drivers/xen/privcmd/compat_privcmd.c
--- a/drivers/xen/privcmd/compat_privcmd.c Wed Jan 06 08:15:35 2010 +0000
+++ b/drivers/xen/privcmd/compat_privcmd.c Wed Jan 06 08:38:09 2010 +0000
@@ -52,17 +52,49 @@ int privcmd_ioctl_32(int fd, unsigned in
struct privcmd_mmapbatch *p;
struct privcmd_mmapbatch_32 *p32;
struct privcmd_mmapbatch_32 n32;
+#ifdef xen_pfn32_t
+ xen_pfn_t *__user arr;
+ xen_pfn32_t *__user arr32;
+ unsigned int i;
+#endif

p32 = compat_ptr(arg);
p = compat_alloc_user_space(sizeof(*p));
if (copy_from_user(&n32, p32, sizeof(n32)) ||
put_user(n32.num, &p->num) ||
put_user(n32.dom, &p->dom) ||
- put_user(n32.addr, &p->addr) ||
- put_user(compat_ptr(n32.arr), &p->arr))
+ put_user(n32.addr, &p->addr))
return -EFAULT;
+#ifdef xen_pfn32_t
+ arr = compat_alloc_user_space(n32.num * sizeof(*arr)
+ + sizeof(*p));
+ arr32 = compat_ptr(n32.arr);
+ for (i = 0; i < n32.num; ++i) {
+ xen_pfn32_t mfn;
+
+ if (get_user(mfn, arr32 + i) || put_user(mfn, arr + i))
+ return -EFAULT;
+ }
+
+ if (put_user(arr, &p->arr))
+ return -EFAULT;
+#else
+ if (put_user(compat_ptr(n32.arr), &p->arr))
+ return -EFAULT;
+#endif

ret = sys_ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH, (unsigned long)p);
+
+#ifdef xen_pfn32_t
+ for (i = 0; !ret && i < n32.num; ++i) {
+ xen_pfn_t mfn;
+
+ if (get_user(mfn, arr + i) || put_user(mfn, arr32 + i))
+ ret = -EFAULT;
+ else if (mfn != (xen_pfn32_t)mfn)
+ ret = -ERANGE;
+ }
+#endif
}
break;
default:
diff -r 2b2d888e5a80 -r aa133dee7792 include/xen/compat_ioctl.h
--- a/include/xen/compat_ioctl.h Wed Jan 06 08:15:35 2010 +0000
+++ b/include/xen/compat_ioctl.h Wed Jan 06 08:38:09 2010 +0000
@@ -23,6 +23,11 @@
#define __LINUX_XEN_COMPAT_H__

#include <linux/compat.h>
+#include <linux/compiler.h>
+
+#if defined(CONFIG_X86) || defined(CONFIG_IA64)
+#define xen_pfn32_t __u32
+#endif

extern int privcmd_ioctl_32(int fd, unsigned int cmd, unsigned long arg);
struct privcmd_mmap_32 {
@@ -34,7 +39,14 @@ struct privcmd_mmapbatch_32 {
struct privcmd_mmapbatch_32 {
int num; /* number of pages to populate */
domid_t dom; /* target domain */
+#if defined(CONFIG_X86) || defined(CONFIG_IA64)
+ union { /* virtual address */
+ __u64 addr __packed;
+ __u32 va; /* ensures union is 4-byte aligned */
+ };
+#else
__u64 addr; /* virtual address */
+#endif
compat_uptr_t arr; /* array of mfns - top nibble set on err */
};
#define IOCTL_PRIVCMD_MMAP_32 \

_______________________________________________
Xen-changelog mailing list
Xen-changelog@lists.xensource.com
http://lists.xensource.com/xen-changelog