aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um
diff options
context:
space:
mode:
authorJeff Dike <jdike@addtoit.com>2007-02-28 23:13:06 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-03-01 17:53:38 -0500
commitaf727902212343211627da14d17c85592feb0e18 (patch)
treef0b2b42a8ec582de6a6a52d2007a0d44eb32c36b /arch/um
parentdae9f8e63cbb532e8c4b9c54bda0bf511af9c01c (diff)
[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 <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>
Diffstat (limited to 'arch/um')
-rw-r--r--arch/um/sys-i386/ldt.c36
1 files changed, 24 insertions, 12 deletions
diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c
index 5db7737df0ff..4a8b4202ef9e 100644
--- a/arch/um/sys-i386/ldt.c
+++ b/arch/um/sys-i386/ldt.c
@@ -7,6 +7,7 @@
7#include "linux/slab.h" 7#include "linux/slab.h"
8#include "linux/types.h" 8#include "linux/types.h"
9#include "linux/errno.h" 9#include "linux/errno.h"
10#include "linux/spinlock.h"
10#include "asm/uaccess.h" 11#include "asm/uaccess.h"
11#include "asm/smp.h" 12#include "asm/smp.h"
12#include "asm/ldt.h" 13#include "asm/ldt.h"
@@ -386,23 +387,33 @@ static long do_modify_ldt_skas(int func, void __user *ptr,
386 return ret; 387 return ret;
387} 388}
388 389
389short dummy_list[9] = {0, -1}; 390static DEFINE_SPINLOCK(host_ldt_lock);
390short * host_ldt_entries = NULL; 391static short dummy_list[9] = {0, -1};
392static short * host_ldt_entries = NULL;
391 393
392void ldt_get_host_info(void) 394static void ldt_get_host_info(void)
393{ 395{
394 long ret; 396 long ret;
395 struct ldt_entry * ldt; 397 struct ldt_entry * ldt, *tmp;
396 int i, size, k, order; 398 int i, size, k, order;
397 399
400 spin_lock(&host_ldt_lock);
401
402 if(host_ldt_entries != NULL){
403 spin_unlock(&host_ldt_lock);
404 return;
405 }
398 host_ldt_entries = dummy_list+1; 406 host_ldt_entries = dummy_list+1;
399 407
408 spin_unlock(&host_ldt_lock);
409
400 for(i = LDT_PAGES_MAX-1, order=0; i; i>>=1, order++); 410 for(i = LDT_PAGES_MAX-1, order=0; i; i>>=1, order++);
401 411
402 ldt = (struct ldt_entry *) 412 ldt = (struct ldt_entry *)
403 __get_free_pages(GFP_KERNEL|__GFP_ZERO, order); 413 __get_free_pages(GFP_KERNEL|__GFP_ZERO, order);
404 if(ldt == NULL) { 414 if(ldt == NULL) {
405 printk("ldt_get_host_info: couldn't allocate buffer for host ldt\n"); 415 printk("ldt_get_host_info: couldn't allocate buffer for host "
416 "ldt\n");
406 return; 417 return;
407 } 418 }
408 419
@@ -426,11 +437,13 @@ void ldt_get_host_info(void)
426 host_ldt_entries = dummy_list; 437 host_ldt_entries = dummy_list;
427 else { 438 else {
428 size = (size + 1) * sizeof(dummy_list[0]); 439 size = (size + 1) * sizeof(dummy_list[0]);
429 host_ldt_entries = kmalloc(size, GFP_KERNEL); 440 tmp = kmalloc(size, GFP_KERNEL);
430 if(host_ldt_entries == NULL) { 441 if(tmp == NULL) {
431 printk("ldt_get_host_info: couldn't allocate host ldt list\n"); 442 printk("ldt_get_host_info: couldn't allocate host ldt "
443 "list\n");
432 goto out_free; 444 goto out_free;
433 } 445 }
446 host_ldt_entries = tmp;
434 } 447 }
435 448
436 for(i=0, k=0; i<ret/LDT_ENTRY_SIZE; i++){ 449 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,
480 * inherited from the host. All ldt-entries found 493 * inherited from the host. All ldt-entries found
481 * will be reset in the following loop 494 * will be reset in the following loop
482 */ 495 */
483 if(host_ldt_entries == NULL) 496 ldt_get_host_info();
484 ldt_get_host_info();
485 for(num_p=host_ldt_entries; *num_p != -1; num_p++){ 497 for(num_p=host_ldt_entries; *num_p != -1; num_p++){
486 desc.entry_number = *num_p; 498 desc.entry_number = *num_p;
487 err = write_ldt_entry(&new_mm->id, 1, &desc, 499 err = write_ldt_entry(&new_mm->id, 1, &desc,
@@ -560,6 +572,6 @@ void free_ldt(struct mmu_context_skas * mm)
560 572
561int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount) 573int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount)
562{ 574{
563 return(CHOOSE_MODE_PROC(do_modify_ldt_tt, do_modify_ldt_skas, func, 575 return CHOOSE_MODE_PROC(do_modify_ldt_tt, do_modify_ldt_skas, func,
564 ptr, bytecount)); 576 ptr, bytecount);
565} 577}