diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-23 23:51:42 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-23 23:51:42 -0400 |
commit | b81a618dcd3ea99de292dbe624f41ca68f464376 (patch) | |
tree | c5fbe44f944da9d7dc0c224116be77094d379c8a /arch/x86 | |
parent | 2f284c846331fa44be1300a3c2c3e85800268a00 (diff) | |
parent | a9712bc12c40c172e393f85a9b2ba8db4bf59509 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6:
deal with races in /proc/*/{syscall,stack,personality}
proc: enable writing to /proc/pid/mem
proc: make check_mem_permission() return an mm_struct on success
proc: hold cred_guard_mutex in check_mem_permission()
proc: disable mem_write after exec
mm: implement access_remote_vm
mm: factor out main logic of access_process_vm
mm: use mm_struct to resolve gate vma's in __get_user_pages
mm: arch: rename in_gate_area_no_task to in_gate_area_no_mm
mm: arch: make in_gate_area take an mm_struct instead of a task_struct
mm: arch: make get_gate_vma take an mm_struct instead of a task_struct
x86: mark associated mm when running a task in 32 bit compatibility mode
x86: add context tag to mark mm when running a task in 32-bit compatibility mode
auxv: require the target to be tracable (or yourself)
close race in /proc/*/environ
report errors in /proc/*/*map* sanely
pagemap: close races with suid execve
make sessionid permissions in /proc/*/task/* match those in /proc/*
fix leaks in path_lookupat()
Fix up trivial conflicts in fs/proc/base.c
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/ia32/ia32_aout.c | 1 | ||||
-rw-r--r-- | arch/x86/include/asm/mmu.h | 6 | ||||
-rw-r--r-- | arch/x86/kernel/process_64.c | 8 | ||||
-rw-r--r-- | arch/x86/mm/init_64.c | 16 | ||||
-rw-r--r-- | arch/x86/vdso/vdso32-setup.c | 15 |
5 files changed, 31 insertions, 15 deletions
diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c index 2d93bdbc9ac0..fd843877e841 100644 --- a/arch/x86/ia32/ia32_aout.c +++ b/arch/x86/ia32/ia32_aout.c | |||
@@ -298,6 +298,7 @@ static int load_aout_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
298 | /* OK, This is the point of no return */ | 298 | /* OK, This is the point of no return */ |
299 | set_personality(PER_LINUX); | 299 | set_personality(PER_LINUX); |
300 | set_thread_flag(TIF_IA32); | 300 | set_thread_flag(TIF_IA32); |
301 | current->mm->context.ia32_compat = 1; | ||
301 | 302 | ||
302 | setup_new_exec(bprm); | 303 | setup_new_exec(bprm); |
303 | 304 | ||
diff --git a/arch/x86/include/asm/mmu.h b/arch/x86/include/asm/mmu.h index 80a1dee5bea5..aeff3e89b222 100644 --- a/arch/x86/include/asm/mmu.h +++ b/arch/x86/include/asm/mmu.h | |||
@@ -13,6 +13,12 @@ typedef struct { | |||
13 | int size; | 13 | int size; |
14 | struct mutex lock; | 14 | struct mutex lock; |
15 | void *vdso; | 15 | void *vdso; |
16 | |||
17 | #ifdef CONFIG_X86_64 | ||
18 | /* True if mm supports a task running in 32 bit compatibility mode. */ | ||
19 | unsigned short ia32_compat; | ||
20 | #endif | ||
21 | |||
16 | } mm_context_t; | 22 | } mm_context_t; |
17 | 23 | ||
18 | #ifdef CONFIG_SMP | 24 | #ifdef CONFIG_SMP |
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index bd387e8f73b4..6c9dd922ac0d 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c | |||
@@ -501,6 +501,10 @@ void set_personality_64bit(void) | |||
501 | /* Make sure to be in 64bit mode */ | 501 | /* Make sure to be in 64bit mode */ |
502 | clear_thread_flag(TIF_IA32); | 502 | clear_thread_flag(TIF_IA32); |
503 | 503 | ||
504 | /* Ensure the corresponding mm is not marked. */ | ||
505 | if (current->mm) | ||
506 | current->mm->context.ia32_compat = 0; | ||
507 | |||
504 | /* TBD: overwrites user setup. Should have two bits. | 508 | /* TBD: overwrites user setup. Should have two bits. |
505 | But 64bit processes have always behaved this way, | 509 | But 64bit processes have always behaved this way, |
506 | so it's not too bad. The main problem is just that | 510 | so it's not too bad. The main problem is just that |
@@ -516,6 +520,10 @@ void set_personality_ia32(void) | |||
516 | set_thread_flag(TIF_IA32); | 520 | set_thread_flag(TIF_IA32); |
517 | current->personality |= force_personality32; | 521 | current->personality |= force_personality32; |
518 | 522 | ||
523 | /* Mark the associated mm as containing 32-bit tasks. */ | ||
524 | if (current->mm) | ||
525 | current->mm->context.ia32_compat = 1; | ||
526 | |||
519 | /* Prepare the first "return" to user space */ | 527 | /* Prepare the first "return" to user space */ |
520 | current_thread_info()->status |= TS_COMPAT; | 528 | current_thread_info()->status |= TS_COMPAT; |
521 | } | 529 | } |
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 2362b646178e..794233587287 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c | |||
@@ -862,18 +862,18 @@ static struct vm_area_struct gate_vma = { | |||
862 | .vm_flags = VM_READ | VM_EXEC | 862 | .vm_flags = VM_READ | VM_EXEC |
863 | }; | 863 | }; |
864 | 864 | ||
865 | struct vm_area_struct *get_gate_vma(struct task_struct *tsk) | 865 | struct vm_area_struct *get_gate_vma(struct mm_struct *mm) |
866 | { | 866 | { |
867 | #ifdef CONFIG_IA32_EMULATION | 867 | #ifdef CONFIG_IA32_EMULATION |
868 | if (test_tsk_thread_flag(tsk, TIF_IA32)) | 868 | if (!mm || mm->context.ia32_compat) |
869 | return NULL; | 869 | return NULL; |
870 | #endif | 870 | #endif |
871 | return &gate_vma; | 871 | return &gate_vma; |
872 | } | 872 | } |
873 | 873 | ||
874 | int in_gate_area(struct task_struct *task, unsigned long addr) | 874 | int in_gate_area(struct mm_struct *mm, unsigned long addr) |
875 | { | 875 | { |
876 | struct vm_area_struct *vma = get_gate_vma(task); | 876 | struct vm_area_struct *vma = get_gate_vma(mm); |
877 | 877 | ||
878 | if (!vma) | 878 | if (!vma) |
879 | return 0; | 879 | return 0; |
@@ -882,11 +882,11 @@ int in_gate_area(struct task_struct *task, unsigned long addr) | |||
882 | } | 882 | } |
883 | 883 | ||
884 | /* | 884 | /* |
885 | * Use this when you have no reliable task/vma, typically from interrupt | 885 | * Use this when you have no reliable mm, typically from interrupt |
886 | * context. It is less reliable than using the task's vma and may give | 886 | * context. It is less reliable than using a task's mm and may give |
887 | * false positives: | 887 | * false positives. |
888 | */ | 888 | */ |
889 | int in_gate_area_no_task(unsigned long addr) | 889 | int in_gate_area_no_mm(unsigned long addr) |
890 | { | 890 | { |
891 | return (addr >= VSYSCALL_START) && (addr < VSYSCALL_END); | 891 | return (addr >= VSYSCALL_START) && (addr < VSYSCALL_END); |
892 | } | 892 | } |
diff --git a/arch/x86/vdso/vdso32-setup.c b/arch/x86/vdso/vdso32-setup.c index 36df991985b2..468d591dde31 100644 --- a/arch/x86/vdso/vdso32-setup.c +++ b/arch/x86/vdso/vdso32-setup.c | |||
@@ -417,24 +417,25 @@ const char *arch_vma_name(struct vm_area_struct *vma) | |||
417 | return NULL; | 417 | return NULL; |
418 | } | 418 | } |
419 | 419 | ||
420 | struct vm_area_struct *get_gate_vma(struct task_struct *tsk) | 420 | struct vm_area_struct *get_gate_vma(struct mm_struct *mm) |
421 | { | 421 | { |
422 | struct mm_struct *mm = tsk->mm; | 422 | /* |
423 | 423 | * Check to see if the corresponding task was created in compat vdso | |
424 | /* Check to see if this task was created in compat vdso mode */ | 424 | * mode. |
425 | */ | ||
425 | if (mm && mm->context.vdso == (void *)VDSO_HIGH_BASE) | 426 | if (mm && mm->context.vdso == (void *)VDSO_HIGH_BASE) |
426 | return &gate_vma; | 427 | return &gate_vma; |
427 | return NULL; | 428 | return NULL; |
428 | } | 429 | } |
429 | 430 | ||
430 | int in_gate_area(struct task_struct *task, unsigned long addr) | 431 | int in_gate_area(struct mm_struct *mm, unsigned long addr) |
431 | { | 432 | { |
432 | const struct vm_area_struct *vma = get_gate_vma(task); | 433 | const struct vm_area_struct *vma = get_gate_vma(mm); |
433 | 434 | ||
434 | return vma && addr >= vma->vm_start && addr < vma->vm_end; | 435 | return vma && addr >= vma->vm_start && addr < vma->vm_end; |
435 | } | 436 | } |
436 | 437 | ||
437 | int in_gate_area_no_task(unsigned long addr) | 438 | int in_gate_area_no_mm(unsigned long addr) |
438 | { | 439 | { |
439 | return 0; | 440 | return 0; |
440 | } | 441 | } |