Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=af727902212343211627da14d17c85592feb0e18
Commit:     af727902212343211627da14d17c85592feb0e18
Parent:     dae9f8e63cbb532e8c4b9c54bda0bf511af9c01c
Author:     Jeff Dike <[EMAIL PROTECTED]>
AuthorDate: Wed Feb 28 20:13:06 2007 -0800
Committer:  Linus Torvalds <[EMAIL PROTECTED]>
CommitDate: Thu Mar 1 14:53:38 2007 -0800

    [PATCH] uml: fix host LDT lookup initialization locking, try 2
    
    Add some locking to host_ldt_entries to prevent racing when reading LDT
    information from the host.
    
    The locking is somewhat more careful than my previous attempt.  Now, only
    the check of host_ldt_entries is locked.  The lock is dropped immediately
    afterwards, and if the LDT needs initializing, that (and the memory
    allocations needed) proceed outside the lock.
    
    Also fixed some style violations.
    
    Signed-off-by: Jeff Dike <[EMAIL PROTECTED]>
    Cc: Paolo 'Blaisorblade' Giarrusso <[EMAIL PROTECTED]>
    Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
    Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
---
 arch/um/sys-i386/ldt.c |   36 ++++++++++++++++++++++++------------
 1 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c
index 5db7737..4a8b420 100644
--- a/arch/um/sys-i386/ldt.c
+++ b/arch/um/sys-i386/ldt.c
@@ -7,6 +7,7 @@
 #include "linux/slab.h"
 #include "linux/types.h"
 #include "linux/errno.h"
+#include "linux/spinlock.h"
 #include "asm/uaccess.h"
 #include "asm/smp.h"
 #include "asm/ldt.h"
@@ -386,23 +387,33 @@ static long do_modify_ldt_skas(int func, void __user *ptr,
        return ret;
 }
 
-short dummy_list[9] = {0, -1};
-short * host_ldt_entries = NULL;
+static DEFINE_SPINLOCK(host_ldt_lock);
+static short dummy_list[9] = {0, -1};
+static short * host_ldt_entries = NULL;
 
-void ldt_get_host_info(void)
+static void ldt_get_host_info(void)
 {
        long ret;
-       struct ldt_entry * ldt;
+       struct ldt_entry * ldt, *tmp;
        int i, size, k, order;
 
+       spin_lock(&host_ldt_lock);
+
+       if(host_ldt_entries != NULL){
+               spin_unlock(&host_ldt_lock);
+               return;
+       }
        host_ldt_entries = dummy_list+1;
 
+       spin_unlock(&host_ldt_lock);
+
        for(i = LDT_PAGES_MAX-1, order=0; i; i>>=1, order++);
 
        ldt = (struct ldt_entry *)
              __get_free_pages(GFP_KERNEL|__GFP_ZERO, order);
        if(ldt == NULL) {
-               printk("ldt_get_host_info: couldn't allocate buffer for host 
ldt\n");
+               printk("ldt_get_host_info: couldn't allocate buffer for host "
+                      "ldt\n");
                return;
        }
 
@@ -426,11 +437,13 @@ void ldt_get_host_info(void)
                host_ldt_entries = dummy_list;
        else {
                size = (size + 1) * sizeof(dummy_list[0]);
-               host_ldt_entries = kmalloc(size, GFP_KERNEL);
-               if(host_ldt_entries == NULL) {
-                       printk("ldt_get_host_info: couldn't allocate host ldt 
list\n");
+               tmp = kmalloc(size, GFP_KERNEL);
+               if(tmp == NULL) {
+                       printk("ldt_get_host_info: couldn't allocate host ldt "
+                              "list\n");
                        goto out_free;
                }
+               host_ldt_entries = tmp;
        }
 
        for(i=0, k=0; i<ret/LDT_ENTRY_SIZE; i++){
@@ -480,8 +493,7 @@ long init_new_ldt(struct mmu_context_skas * new_mm,
                         * inherited from the host. All ldt-entries found
                         * will be reset in the following loop
                         */
-                       if(host_ldt_entries == NULL)
-                               ldt_get_host_info();
+                       ldt_get_host_info();
                        for(num_p=host_ldt_entries; *num_p != -1; num_p++){
                                desc.entry_number = *num_p;
                                err = write_ldt_entry(&new_mm->id, 1, &desc,
@@ -560,6 +572,6 @@ void free_ldt(struct mmu_context_skas * mm)
 
 int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount)
 {
-       return(CHOOSE_MODE_PROC(do_modify_ldt_tt, do_modify_ldt_skas, func,
-                               ptr, bytecount));
+       return CHOOSE_MODE_PROC(do_modify_ldt_tt, do_modify_ldt_skas, func,
+                               ptr, bytecount);
 }
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to