forked from luck/tmp_suning_uos_patched
uprobes: Add mem_cgroup_charge_anon() into uprobe_write_opcode()
Hugh says: The one I noticed was that it forgets all about memcg (because it was copied from KSM, and there the replacement page has already been charged to a memcg). See how mm/memory.c do_anonymous_page() does a mem_cgroup_charge_anon(). Hopefully not a big problem, uprobes is a system-wide thing and only root can insert the probes. But I agree, should be fixed anyway. Add mem_cgroup_{un,}charge_anon() into uprobe_write_opcode(). To simplify the error handling (and avoid the new "uncharge" label) the patch also moves anon_vma_prepare() up before we alloc/charge the new page. While at it fix the comment about ->mmap_sem, it is held for write. Suggested-by: Hugh Dickins <hughd@google.com> Signed-off-by: Oleg Nesterov <oleg@redhat.com>
This commit is contained in:
parent
8e02ae573e
commit
29dedee0e6
|
@ -279,18 +279,13 @@ static int verify_opcode(struct page *page, unsigned long vaddr, uprobe_opcode_t
|
|||
* supported by that architecture then we need to modify is_trap_at_addr and
|
||||
* uprobe_write_opcode accordingly. This would never be a problem for archs
|
||||
* that have fixed length instructions.
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
* uprobe_write_opcode - write the opcode at a given virtual address.
|
||||
* @mm: the probed process address space.
|
||||
* @vaddr: the virtual address to store the opcode.
|
||||
* @opcode: opcode to be written at @vaddr.
|
||||
*
|
||||
* Called with mm->mmap_sem held (for read and with a reference to
|
||||
* mm).
|
||||
*
|
||||
* For mm @mm, write the opcode at @vaddr.
|
||||
* Called with mm->mmap_sem held for write.
|
||||
* Return 0 (success) or a negative errno.
|
||||
*/
|
||||
int uprobe_write_opcode(struct mm_struct *mm, unsigned long vaddr,
|
||||
|
@ -310,21 +305,25 @@ int uprobe_write_opcode(struct mm_struct *mm, unsigned long vaddr,
|
|||
if (ret <= 0)
|
||||
goto put_old;
|
||||
|
||||
ret = anon_vma_prepare(vma);
|
||||
if (ret)
|
||||
goto put_old;
|
||||
|
||||
ret = -ENOMEM;
|
||||
new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, vaddr);
|
||||
if (!new_page)
|
||||
goto put_old;
|
||||
|
||||
__SetPageUptodate(new_page);
|
||||
if (mem_cgroup_charge_anon(new_page, mm, GFP_KERNEL))
|
||||
goto put_new;
|
||||
|
||||
__SetPageUptodate(new_page);
|
||||
copy_highpage(new_page, old_page);
|
||||
copy_to_page(new_page, vaddr, &opcode, UPROBE_SWBP_INSN_SIZE);
|
||||
|
||||
ret = anon_vma_prepare(vma);
|
||||
if (ret)
|
||||
goto put_new;
|
||||
|
||||
ret = __replace_page(vma, vaddr, old_page, new_page);
|
||||
if (ret)
|
||||
mem_cgroup_uncharge_page(new_page);
|
||||
|
||||
put_new:
|
||||
page_cache_release(new_page);
|
||||
|
|
Loading…
Reference in New Issue
Block a user