Merge tag 'stable/for-linus-3.8-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 18 Jan 2013 20:02:52 +0000 (12:02 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 18 Jan 2013 20:02:52 +0000 (12:02 -0800)
Pull Xen fixes from Konrad Rzeszutek Wilk:
 - CVE-2013-0190/XSA-40 (or stack corruption for 32-bit PV kernels)
 - Fix racy vma access spotted by Al Viro
 - Fix mmap batch ioctl potentially resulting in large O(n) page allcations.
 - Fix vcpu online/offline BUG:scheduling while atomic..
 - Fix unbound buffer scanning for more than 32 vCPUs.
 - Fix grant table being incorrectly initialized
 - Fix incorrect check in pciback
 - Allow privcmd in backend domains.

Fix up whitespace conflict due to ugly merge resolution in Xen tree in
arch/arm/xen/enlighten.c

* tag 'stable/for-linus-3.8-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen:
  xen: Fix stack corruption in xen_failsafe_callback for 32bit PVOPS guests.
  Revert "xen/smp: Fix CPU online/offline bug triggering a BUG: scheduling while atomic."
  xen/gntdev: remove erronous use of copy_to_user
  xen/gntdev: correctly unmap unlinked maps in mmu notifier
  xen/gntdev: fix unsafe vma access
  xen/privcmd: Fix mmap batch ioctl.
  Xen: properly bound buffer access when parsing cpu/*/availability
  xen/grant-table: correctly initialize grant table version 1
  x86/xen : Fix the wrong check in pciback
  xen/privcmd: Relax access control in privcmd_ioctl_mmap

1  2 
arch/x86/kernel/entry_32.S
drivers/xen/grant-table.c

index ff84d5469d772fd8ae8f5e0599e8072333eeb0c1,cf8639b4dcf3a731859fe4c1c9c3befff6004944..6ed91d9980e240b73fa824f7db00d8065d145316
@@@ -739,11 -739,30 +739,11 @@@ ENTRY(ptregs_##name) ; 
  ENDPROC(ptregs_##name)
  
  PTREGSCALL1(iopl)
 -PTREGSCALL0(fork)
 -PTREGSCALL0(vfork)
 -PTREGSCALL2(sigaltstack)
  PTREGSCALL0(sigreturn)
  PTREGSCALL0(rt_sigreturn)
  PTREGSCALL2(vm86)
  PTREGSCALL1(vm86old)
  
 -/* Clone is an oddball.  The 4th arg is in %edi */
 -ENTRY(ptregs_clone)
 -      CFI_STARTPROC
 -      leal 4(%esp),%eax
 -      pushl_cfi %eax
 -      pushl_cfi PT_EDI(%eax)
 -      movl PT_EDX(%eax),%ecx
 -      movl PT_ECX(%eax),%edx
 -      movl PT_EBX(%eax),%eax
 -      call sys_clone
 -      addl $8,%esp
 -      CFI_ADJUST_CFA_OFFSET -8
 -      ret
 -      CFI_ENDPROC
 -ENDPROC(ptregs_clone)
 -
  .macro FIXUP_ESPFIX_STACK
  /*
   * Switch back for ESPFIX stack to the normal zerobased stack
@@@ -1065,7 -1084,6 +1065,6 @@@ ENTRY(xen_failsafe_callback
        lea 16(%esp),%esp
        CFI_ADJUST_CFA_OFFSET -16
        jz 5f
-       addl $16,%esp
        jmp iret_exc
  5:    pushl_cfi $-1 /* orig_ax = -1 => not a system call */
        SAVE_ALL
index 7038de53652b3cd8999ac7d642fd84441c79dcd5,95ce9d02cecaabfb3246252941adcacdd01d015e..157c0ccda3efdce0e8a3c4b9ab0937ade1d932ec
  /* External tools reserve first few grant table entries. */
  #define NR_RESERVED_ENTRIES 8
  #define GNTTAB_LIST_END 0xffffffff
- #define GREFS_PER_GRANT_FRAME \
- (grant_table_version == 1 ?                      \
- (PAGE_SIZE / sizeof(struct grant_entry_v1)) :   \
- (PAGE_SIZE / sizeof(union grant_entry_v2)))
  
  static grant_ref_t **gnttab_list;
  static unsigned int nr_grant_frames;
@@@ -154,6 -150,7 +150,7 @@@ static struct gnttab_ops *gnttab_interf
  static grant_status_t *grstatus;
  
  static int grant_table_version;
+ static int grefs_per_grant_frame;
  
  static struct gnttab_free_callback *gnttab_free_callback_list;
  
@@@ -767,12 -764,14 +764,14 @@@ static int grow_gnttab_list(unsigned in
        unsigned int new_nr_grant_frames, extra_entries, i;
        unsigned int nr_glist_frames, new_nr_glist_frames;
  
+       BUG_ON(grefs_per_grant_frame == 0);
        new_nr_grant_frames = nr_grant_frames + more_frames;
-       extra_entries       = more_frames * GREFS_PER_GRANT_FRAME;
+       extra_entries       = more_frames * grefs_per_grant_frame;
  
-       nr_glist_frames = (nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP;
+       nr_glist_frames = (nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP;
        new_nr_glist_frames =
-               (new_nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP;
+               (new_nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP;
        for (i = nr_glist_frames; i < new_nr_glist_frames; i++) {
                gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_ATOMIC);
                if (!gnttab_list[i])
        }
  
  
-       for (i = GREFS_PER_GRANT_FRAME * nr_grant_frames;
-            i < GREFS_PER_GRANT_FRAME * new_nr_grant_frames - 1; i++)
+       for (i = grefs_per_grant_frame * nr_grant_frames;
+            i < grefs_per_grant_frame * new_nr_grant_frames - 1; i++)
                gnttab_entry(i) = i + 1;
  
        gnttab_entry(i) = gnttab_free_head;
-       gnttab_free_head = GREFS_PER_GRANT_FRAME * nr_grant_frames;
+       gnttab_free_head = grefs_per_grant_frame * nr_grant_frames;
        gnttab_free_count += extra_entries;
  
        nr_grant_frames = new_nr_grant_frames;
@@@ -957,7 -956,8 +956,8 @@@ EXPORT_SYMBOL_GPL(gnttab_unmap_refs)
  
  static unsigned nr_status_frames(unsigned nr_grant_frames)
  {
-       return (nr_grant_frames * GREFS_PER_GRANT_FRAME + SPP - 1) / SPP;
+       BUG_ON(grefs_per_grant_frame == 0);
+       return (nr_grant_frames * grefs_per_grant_frame + SPP - 1) / SPP;
  }
  
  static int gnttab_map_frames_v1(xen_pfn_t *frames, unsigned int nr_gframes)
@@@ -1115,6 -1115,7 +1115,7 @@@ static void gnttab_request_version(void
        rc = HYPERVISOR_grant_table_op(GNTTABOP_set_version, &gsv, 1);
        if (rc == 0 && gsv.version == 2) {
                grant_table_version = 2;
+               grefs_per_grant_frame = PAGE_SIZE / sizeof(union grant_entry_v2);
                gnttab_interface = &gnttab_v2_ops;
        } else if (grant_table_version == 2) {
                /*
                panic("we need grant tables version 2, but only version 1 is available");
        } else {
                grant_table_version = 1;
+               grefs_per_grant_frame = PAGE_SIZE / sizeof(struct grant_entry_v1);
                gnttab_interface = &gnttab_v1_ops;
        }
        printk(KERN_INFO "Grant tables using version %d layout.\n",
                grant_table_version);
  }
  
int gnttab_resume(void)
static int gnttab_setup(void)
  {
        unsigned int max_nr_gframes;
  
-       gnttab_request_version();
        max_nr_gframes = gnttab_max_grant_frames();
        if (max_nr_gframes < nr_grant_frames)
                return -ENOSYS;
        return 0;
  }
  
+ int gnttab_resume(void)
+ {
+       gnttab_request_version();
+       return gnttab_setup();
+ }
  int gnttab_suspend(void)
  {
        gnttab_interface->unmap_frames();
@@@ -1171,9 -1178,10 +1178,10 @@@ static int gnttab_expand(unsigned int r
        int rc;
        unsigned int cur, extra;
  
+       BUG_ON(grefs_per_grant_frame == 0);
        cur = nr_grant_frames;
-       extra = ((req_entries + (GREFS_PER_GRANT_FRAME-1)) /
-                GREFS_PER_GRANT_FRAME);
+       extra = ((req_entries + (grefs_per_grant_frame-1)) /
+                grefs_per_grant_frame);
        if (cur + extra > gnttab_max_grant_frames())
                return -ENOSPC;
  
@@@ -1191,21 -1199,23 +1199,23 @@@ int gnttab_init(void
        unsigned int nr_init_grefs;
        int ret;
  
+       gnttab_request_version();
        nr_grant_frames = 1;
        boot_max_nr_grant_frames = __max_nr_grant_frames();
  
        /* Determine the maximum number of frames required for the
         * grant reference free list on the current hypervisor.
         */
+       BUG_ON(grefs_per_grant_frame == 0);
        max_nr_glist_frames = (boot_max_nr_grant_frames *
-                              GREFS_PER_GRANT_FRAME / RPP);
+                              grefs_per_grant_frame / RPP);
  
        gnttab_list = kmalloc(max_nr_glist_frames * sizeof(grant_ref_t *),
                              GFP_KERNEL);
        if (gnttab_list == NULL)
                return -ENOMEM;
  
-       nr_glist_frames = (nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP;
+       nr_glist_frames = (nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP;
        for (i = 0; i < nr_glist_frames; i++) {
                gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_KERNEL);
                if (gnttab_list[i] == NULL) {
                }
        }
  
-       if (gnttab_resume() < 0) {
+       if (gnttab_setup() < 0) {
                ret = -ENODEV;
                goto ini_nomem;
        }
  
-       nr_init_grefs = nr_grant_frames * GREFS_PER_GRANT_FRAME;
+       nr_init_grefs = nr_grant_frames * grefs_per_grant_frame;
  
        for (i = NR_RESERVED_ENTRIES; i < nr_init_grefs - 1; i++)
                gnttab_entry(i) = i + 1;
  }
  EXPORT_SYMBOL_GPL(gnttab_init);
  
 -static int __devinit __gnttab_init(void)
 +static int __gnttab_init(void)
  {
        /* Delay grant-table initialization in the PV on HVM case */
        if (xen_hvm_domain())