Skip to content

Commit

Permalink
[PATCH] uml: fix host LDT lookup initialization locking, try 2
Browse files Browse the repository at this point in the history
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 <jdike@addtoit.com>
Cc: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
Jeff Dike authored and Linus Torvalds committed Mar 1, 2007
1 parent dae9f8e commit af72790
Showing 1 changed file with 24 additions and 12 deletions.
36 changes: 24 additions & 12 deletions arch/um/sys-i386/ldt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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;
}

Expand All @@ -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++){
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);
}

0 comments on commit af72790

Please sign in to comment.