aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/kernel/perfmon.c
diff options
context:
space:
mode:
authorNick Piggin <npiggin@suse.de>2007-03-06 05:34:25 -0500
committerTony Luck <tony.luck@intel.com>2007-03-06 17:49:52 -0500
commit41d5e5d73ecef4ef56b7b4cde962929a712689b4 (patch)
tree51cb9289609c639d86a768ff92340291a4d1b452 /arch/ia64/kernel/perfmon.c
parent50157b09b33c2ec3637d3b317b06a7235c57c7f2 (diff)
[IA64] permon use-after-free fix
Perfmon associates vmalloc()ed memory with a file descriptor, and installs a vma mapping that memory. Unfortunately, the vm_file field is not filled in, so processes with mappings to that memory do not prevent the file from being closed and the memory freed. This results in use-after-free bugs and multiple freeing of pages, etc. I saw this bug on an Altix on SLES9. Haven't reproduced upstream but it looks like the same issue is there. Signed-off-by: Nick Piggin <npiggin@suse.de> Cc: Stephane Eranian <eranian@hpl.hp.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'arch/ia64/kernel/perfmon.c')
-rw-r--r--arch/ia64/kernel/perfmon.c11
1 files changed, 7 insertions, 4 deletions
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index 9ddf896a137a..abc7ad035886 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -2299,7 +2299,7 @@ pfm_remap_buffer(struct vm_area_struct *vma, unsigned long buf, unsigned long ad
2299 * allocate a sampling buffer and remaps it into the user address space of the task 2299 * allocate a sampling buffer and remaps it into the user address space of the task
2300 */ 2300 */
2301static int 2301static int
2302pfm_smpl_buffer_alloc(struct task_struct *task, pfm_context_t *ctx, unsigned long rsize, void **user_vaddr) 2302pfm_smpl_buffer_alloc(struct task_struct *task, struct file *filp, pfm_context_t *ctx, unsigned long rsize, void **user_vaddr)
2303{ 2303{
2304 struct mm_struct *mm = task->mm; 2304 struct mm_struct *mm = task->mm;
2305 struct vm_area_struct *vma = NULL; 2305 struct vm_area_struct *vma = NULL;
@@ -2349,6 +2349,7 @@ pfm_smpl_buffer_alloc(struct task_struct *task, pfm_context_t *ctx, unsigned lon
2349 * partially initialize the vma for the sampling buffer 2349 * partially initialize the vma for the sampling buffer
2350 */ 2350 */
2351 vma->vm_mm = mm; 2351 vma->vm_mm = mm;
2352 vma->vm_file = filp;
2352 vma->vm_flags = VM_READ| VM_MAYREAD |VM_RESERVED; 2353 vma->vm_flags = VM_READ| VM_MAYREAD |VM_RESERVED;
2353 vma->vm_page_prot = PAGE_READONLY; /* XXX may need to change */ 2354 vma->vm_page_prot = PAGE_READONLY; /* XXX may need to change */
2354 2355
@@ -2387,6 +2388,8 @@ pfm_smpl_buffer_alloc(struct task_struct *task, pfm_context_t *ctx, unsigned lon
2387 goto error; 2388 goto error;
2388 } 2389 }
2389 2390
2391 get_file(filp);
2392
2390 /* 2393 /*
2391 * now insert the vma in the vm list for the process, must be 2394 * now insert the vma in the vm list for the process, must be
2392 * done with mmap lock held 2395 * done with mmap lock held
@@ -2464,7 +2467,7 @@ pfarg_is_sane(struct task_struct *task, pfarg_context_t *pfx)
2464} 2467}
2465 2468
2466static int 2469static int
2467pfm_setup_buffer_fmt(struct task_struct *task, pfm_context_t *ctx, unsigned int ctx_flags, 2470pfm_setup_buffer_fmt(struct task_struct *task, struct file *filp, pfm_context_t *ctx, unsigned int ctx_flags,
2468 unsigned int cpu, pfarg_context_t *arg) 2471 unsigned int cpu, pfarg_context_t *arg)
2469{ 2472{
2470 pfm_buffer_fmt_t *fmt = NULL; 2473 pfm_buffer_fmt_t *fmt = NULL;
@@ -2505,7 +2508,7 @@ pfm_setup_buffer_fmt(struct task_struct *task, pfm_context_t *ctx, unsigned int
2505 /* 2508 /*
2506 * buffer is always remapped into the caller's address space 2509 * buffer is always remapped into the caller's address space
2507 */ 2510 */
2508 ret = pfm_smpl_buffer_alloc(current, ctx, size, &uaddr); 2511 ret = pfm_smpl_buffer_alloc(current, filp, ctx, size, &uaddr);
2509 if (ret) goto error; 2512 if (ret) goto error;
2510 2513
2511 /* keep track of user address of buffer */ 2514 /* keep track of user address of buffer */
@@ -2716,7 +2719,7 @@ pfm_context_create(pfm_context_t *ctx, void *arg, int count, struct pt_regs *reg
2716 * does the user want to sample? 2719 * does the user want to sample?
2717 */ 2720 */
2718 if (pfm_uuid_cmp(req->ctx_smpl_buf_id, pfm_null_uuid)) { 2721 if (pfm_uuid_cmp(req->ctx_smpl_buf_id, pfm_null_uuid)) {
2719 ret = pfm_setup_buffer_fmt(current, ctx, ctx_flags, 0, req); 2722 ret = pfm_setup_buffer_fmt(current, filp, ctx, ctx_flags, 0, req);
2720 if (ret) goto buffer_error; 2723 if (ret) goto buffer_error;
2721 } 2724 }
2722 2725