bitkeeper revision 1.460 (3f721160CQuzVfl_qVkHJLnLn6yY1A)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Wed, 24 Sep 2003 21:49:20 +0000 (21:49 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Wed, 24 Sep 2003 21:49:20 +0000 (21:49 +0000)
ldt.c:
  Xenolinux modify_ldt syscall now silently clamps the segment limit to a safe value. This is needed for brainded new linuxthreads versions which specify a 4GB segment limit.

xenolinux-2.4.22-sparse/arch/xeno/kernel/ldt.c

index ca89b694bdc83efd9b1e3b332bd0e22d8d1790d1..28ae39fd6023f12c4371ff8dd2d01e403f1065ff 100644 (file)
@@ -68,7 +68,7 @@ static int write_ldt(void * ptr, unsigned long bytecount, int oldmode)
 {
     struct mm_struct * mm = current->mm;
     __u32 entry_1, entry_2, *lp;
-    unsigned long phys_lp;
+    unsigned long phys_lp, max_limit;
     int error;
     struct modify_ldt_ldt_s ldt_info;
 
@@ -89,6 +89,13 @@ static int write_ldt(void * ptr, unsigned long bytecount, int oldmode)
             goto out;
     }
 
+    /*
+     * This makes our tests for overlap with Xen space easier. There's no good
+     * reason to have a user segment starting this high anyway.
+     */
+    if (ldt_info.base_addr >= PAGE_OFFSET)
+        goto out;
+
     down_write(&mm->mmap_sem);
     if (!mm->context.segments) {
         void * segments = vmalloc(LDT_ENTRIES*LDT_ENTRY_SIZE);
@@ -122,6 +129,13 @@ static int write_ldt(void * ptr, unsigned long bytecount, int oldmode)
         }
     }
 
+    max_limit = HYPERVISOR_VIRT_START - ldt_info.base_addr;
+    if ( ldt_info.limit_in_pages )
+        max_limit >>= PAGE_SHIFT;
+    max_limit--;
+    if ( (ldt_info.limit & 0xfffff) > (max_limit & 0xfffff) )
+        ldt_info.limit = max_limit;
+
     entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
         (ldt_info.limit & 0x0ffff);
     entry_2 = (ldt_info.base_addr & 0xff000000) |