Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ed6f6a50 authored by Oleg Nesterov's avatar Oleg Nesterov
Browse files

uprobes: Kill set_orig_insn()->is_swbp_at_addr()



Unlike set_swbp(), set_orig_insn()->is_swbp_at_addr() makes sense,
although it can't prevent all confusions.

But the usage of is_swbp_at_addr() is equally confusing, and it adds
the extra get_user_pages() we can avoid.

This patch removes set_orig_insn()->is_swbp_at_addr() but changes
write_opcode() to do the necessary checks before replace_page().

Perhaps it also makes sense to ensure PAGE_MAPPING_ANON in unregister
case.

find_active_uprobe() becomes the only user of is_swbp_at_addr(),
we can change its semantics.

Signed-off-by: default avatarOleg Nesterov <oleg@redhat.com>
Acked-by: default avatarSrikar Dronamraju <srikar@linux.vnet.ibm.com>
parent cceb55aa
Loading
Loading
Loading
Loading
+23 −9
Original line number Original line Diff line number Diff line
@@ -190,6 +190,25 @@ static void copy_opcode(struct page *page, unsigned long vaddr, uprobe_opcode_t
	kunmap_atomic(kaddr);
	kunmap_atomic(kaddr);
}
}


static int verify_opcode(struct page *page, unsigned long vaddr, uprobe_opcode_t *new_opcode)
{
	uprobe_opcode_t old_opcode;
	bool is_swbp;

	copy_opcode(page, vaddr, &old_opcode);
	is_swbp = is_swbp_insn(&old_opcode);

	if (is_swbp_insn(new_opcode)) {
		if (is_swbp)		/* register: already installed? */
			return 0;
	} else {
		if (!is_swbp)		/* unregister: was it changed by us? */
			return -EINVAL;
	}

	return 1;
}

/*
/*
 * NOTE:
 * NOTE:
 * Expect the breakpoint instruction to be the smallest size instruction for
 * Expect the breakpoint instruction to be the smallest size instruction for
@@ -226,6 +245,10 @@ retry:
	if (ret <= 0)
	if (ret <= 0)
		return ret;
		return ret;


	ret = verify_opcode(old_page, vaddr, &opcode);
	if (ret <= 0)
		goto put_old;

	ret = -ENOMEM;
	ret = -ENOMEM;
	new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, vaddr);
	new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, vaddr);
	if (!new_page)
	if (!new_page)
@@ -311,15 +334,6 @@ int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned
int __weak
int __weak
set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr)
set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr)
{
{
	int result;

	result = is_swbp_at_addr(mm, vaddr);
	if (!result)
		return -EINVAL;

	if (result != 1)
		return result;

	return write_opcode(mm, vaddr, *(uprobe_opcode_t *)auprobe->insn);
	return write_opcode(mm, vaddr, *(uprobe_opcode_t *)auprobe->insn);
}
}