aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/events/uprobes.c
diff options
context:
space:
mode:
authorOleg Nesterov <oleg@redhat.com>2014-05-05 10:38:18 -0400
committerOleg Nesterov <oleg@redhat.com>2014-05-14 07:57:24 -0400
commit29dedee0e693aa113164c820395ce51446a71ace (patch)
tree7dff2a1f28a6c2d300c14fbe3674f3756f4dea7a /kernel/events/uprobes.c
parent8e02ae573e6ae86930d08662790827a938203e70 (diff)
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>
Diffstat (limited to 'kernel/events/uprobes.c')
-rw-r--r--kernel/events/uprobes.c23
1 files changed, 11 insertions, 12 deletions
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 7716c40f2c50..a13251e8bfa4 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -279,18 +279,13 @@ static int verify_opcode(struct page *page, unsigned long vaddr, uprobe_opcode_t
279 * supported by that architecture then we need to modify is_trap_at_addr and 279 * supported by that architecture then we need to modify is_trap_at_addr and
280 * uprobe_write_opcode accordingly. This would never be a problem for archs 280 * uprobe_write_opcode accordingly. This would never be a problem for archs
281 * that have fixed length instructions. 281 * that have fixed length instructions.
282 */ 282 *
283
284/*
285 * uprobe_write_opcode - write the opcode at a given virtual address. 283 * uprobe_write_opcode - write the opcode at a given virtual address.
286 * @mm: the probed process address space. 284 * @mm: the probed process address space.
287 * @vaddr: the virtual address to store the opcode. 285 * @vaddr: the virtual address to store the opcode.
288 * @opcode: opcode to be written at @vaddr. 286 * @opcode: opcode to be written at @vaddr.
289 * 287 *
290 * Called with mm->mmap_sem held (for read and with a reference to 288 * Called with mm->mmap_sem held for write.
291 * mm).
292 *
293 * For mm @mm, write the opcode at @vaddr.
294 * Return 0 (success) or a negative errno. 289 * Return 0 (success) or a negative errno.
295 */ 290 */
296int uprobe_write_opcode(struct mm_struct *mm, unsigned long vaddr, 291int uprobe_write_opcode(struct mm_struct *mm, unsigned long vaddr,
@@ -310,21 +305,25 @@ retry:
310 if (ret <= 0) 305 if (ret <= 0)
311 goto put_old; 306 goto put_old;
312 307
308 ret = anon_vma_prepare(vma);
309 if (ret)
310 goto put_old;
311
313 ret = -ENOMEM; 312 ret = -ENOMEM;
314 new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, vaddr); 313 new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, vaddr);
315 if (!new_page) 314 if (!new_page)
316 goto put_old; 315 goto put_old;
317 316
318 __SetPageUptodate(new_page); 317 if (mem_cgroup_charge_anon(new_page, mm, GFP_KERNEL))
318 goto put_new;
319 319
320 __SetPageUptodate(new_page);
320 copy_highpage(new_page, old_page); 321 copy_highpage(new_page, old_page);
321 copy_to_page(new_page, vaddr, &opcode, UPROBE_SWBP_INSN_SIZE); 322 copy_to_page(new_page, vaddr, &opcode, UPROBE_SWBP_INSN_SIZE);
322 323
323 ret = anon_vma_prepare(vma);
324 if (ret)
325 goto put_new;
326
327 ret = __replace_page(vma, vaddr, old_page, new_page); 324 ret = __replace_page(vma, vaddr, old_page, new_page);
325 if (ret)
326 mem_cgroup_uncharge_page(new_page);
328 327
329put_new: 328put_new:
330 page_cache_release(new_page); 329 page_cache_release(new_page);