All of lore.kernel.org
 help / color / mirror / Atom feed
* uprobes: minor fixes + name the xol vma
@ 2015-07-09 21:44 Oleg Nesterov
  2015-07-09 21:44 ` [PATCH 1/3] uprobes: fix the usage of install_special_mapping() Oleg Nesterov
                   ` (3 more replies)
  0 siblings, 4 replies; 13+ messages in thread
From: Oleg Nesterov @ 2015-07-09 21:44 UTC (permalink / raw)
  To: Ingo Molnar, Srikar Dronamraju
  Cc: Andy Lutomirski, Kirill A. Shutemov, linux-kernel

Hello,

The bugs are theoretical, but still should be fixed imo. And it
would be nice to name the special vma installed by uprobes. As a
side effect this vma will be core-dump'ed, I think this is good.

This doesn't depend on the pending longjmp fixes.

Oleg.

 kernel/events/uprobes.c |   43 +++++++++++++++++++++++++++----------------
 1 files changed, 27 insertions(+), 16 deletions(-)


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 1/3] uprobes: fix the usage of install_special_mapping()
  2015-07-09 21:44 uprobes: minor fixes + name the xol vma Oleg Nesterov
@ 2015-07-09 21:44 ` Oleg Nesterov
  2015-07-09 21:49   ` Andy Lutomirski
  2015-07-09 21:44 ` [PATCH 2/3] uprobes: use vm_special_mapping to name the xol vma Oleg Nesterov
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 13+ messages in thread
From: Oleg Nesterov @ 2015-07-09 21:44 UTC (permalink / raw)
  To: Ingo Molnar, Srikar Dronamraju
  Cc: Andy Lutomirski, Kirill A. Shutemov, linux-kernel

install_special_mapping(pages) expects that "pages" is the zero-
terminated array while xol_add_vma() passes &area->page, this means
that special_mapping_fault() can wrongly use the next member in
xol_area (vaddr) as "struct page *".

Fortunately, this area is not expandable so pgoff != 0 isn't possible
(modulo bugs in special_mapping_vmops), but still this does not look
good.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
 kernel/events/uprobes.c |   16 ++++++++--------
 1 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 0f370ef..bd35bee 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -99,7 +99,7 @@ struct xol_area {
 	wait_queue_head_t 	wq;		/* if all slots are busy */
 	atomic_t 		slot_count;	/* number of in-use slots */
 	unsigned long 		*bitmap;	/* 0 = free slot */
-	struct page 		*page;
+	struct page 		*pages[2];
 
 	/*
 	 * We keep the vma's vm_start rather than a pointer to the vma
@@ -1142,7 +1142,7 @@ static int xol_add_vma(struct mm_struct *mm, struct xol_area *area)
 	}
 
 	ret = install_special_mapping(mm, area->vaddr, PAGE_SIZE,
-				VM_EXEC|VM_MAYEXEC|VM_DONTCOPY|VM_IO, &area->page);
+				VM_EXEC|VM_MAYEXEC|VM_DONTCOPY|VM_IO, area->pages);
 	if (ret)
 		goto fail;
 
@@ -1168,8 +1168,8 @@ static struct xol_area *__create_xol_area(unsigned long vaddr)
 	if (!area->bitmap)
 		goto free_area;
 
-	area->page = alloc_page(GFP_HIGHUSER);
-	if (!area->page)
+	area->pages[0] = alloc_page(GFP_HIGHUSER);
+	if (!area->pages[0])
 		goto free_bitmap;
 
 	area->vaddr = vaddr;
@@ -1177,12 +1177,12 @@ static struct xol_area *__create_xol_area(unsigned long vaddr)
 	/* Reserve the 1st slot for get_trampoline_vaddr() */
 	set_bit(0, area->bitmap);
 	atomic_set(&area->slot_count, 1);
-	copy_to_page(area->page, 0, &insn, UPROBE_SWBP_INSN_SIZE);
+	copy_to_page(area->pages[0], 0, &insn, UPROBE_SWBP_INSN_SIZE);
 
 	if (!xol_add_vma(mm, area))
 		return area;
 
-	__free_page(area->page);
+	__free_page(area->pages[0]);
  free_bitmap:
 	kfree(area->bitmap);
  free_area:
@@ -1220,7 +1220,7 @@ void uprobe_clear_state(struct mm_struct *mm)
 	if (!area)
 		return;
 
-	put_page(area->page);
+	put_page(area->pages[0]);
 	kfree(area->bitmap);
 	kfree(area);
 }
@@ -1289,7 +1289,7 @@ static unsigned long xol_get_insn_slot(struct uprobe *uprobe)
 	if (unlikely(!xol_vaddr))
 		return 0;
 
-	arch_uprobe_copy_ixol(area->page, xol_vaddr,
+	arch_uprobe_copy_ixol(area->pages[0], xol_vaddr,
 			      &uprobe->arch.ixol, sizeof(uprobe->arch.ixol));
 
 	return xol_vaddr;
-- 
1.5.5.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 2/3] uprobes: use vm_special_mapping to name the xol vma
  2015-07-09 21:44 uprobes: minor fixes + name the xol vma Oleg Nesterov
  2015-07-09 21:44 ` [PATCH 1/3] uprobes: fix the usage of install_special_mapping() Oleg Nesterov
@ 2015-07-09 21:44 ` Oleg Nesterov
  2015-07-09 21:50   ` Andy Lutomirski
  2015-07-09 21:44 ` [PATCH 3/3] uprobes: fix the waitqueue_active() check in xol_free_insn_slot() Oleg Nesterov
  2015-07-09 22:25 ` [PATCH v2 0/3] uprobes: minor fixes + name the xol vma Oleg Nesterov
  3 siblings, 1 reply; 13+ messages in thread
From: Oleg Nesterov @ 2015-07-09 21:44 UTC (permalink / raw)
  To: Ingo Molnar, Srikar Dronamraju
  Cc: Andy Lutomirski, Kirill A. Shutemov, linux-kernel

Change xol_add_vma() to use _install_special_mapping(), this way
we can name the vma installed by uprobes. Currently it looks like
private anonymous mapping, this is confusing and complicates the
debugging. With this change /proc/$pid/maps reports "[uprobes]".

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
 kernel/events/uprobes.c |   30 ++++++++++++++++++++----------
 1 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index bd35bee..6a9c5e0 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -96,17 +96,18 @@ struct uprobe {
  * allocated.
  */
 struct xol_area {
-	wait_queue_head_t 	wq;		/* if all slots are busy */
-	atomic_t 		slot_count;	/* number of in-use slots */
-	unsigned long 		*bitmap;	/* 0 = free slot */
-	struct page 		*pages[2];
+	wait_queue_head_t 		wq;		/* if all slots are busy */
+	atomic_t 			slot_count;	/* number of in-use slots */
+	unsigned long 			*bitmap;	/* 0 = free slot */
 
+	struct vm_special_mapping	xol_mapping;
+	struct page 			*pages[2];
 	/*
 	 * We keep the vma's vm_start rather than a pointer to the vma
 	 * itself.  The probed process or a naughty kernel module could make
 	 * the vma go away, and we must handle that reasonably gracefully.
 	 */
-	unsigned long 		vaddr;		/* Page(s) of instruction slots */
+	unsigned long 			vaddr;		/* Page(s) of instruction slots */
 };
 
 /*
@@ -1125,11 +1126,14 @@ void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned lon
 /* Slot allocation for XOL */
 static int xol_add_vma(struct mm_struct *mm, struct xol_area *area)
 {
-	int ret = -EALREADY;
+	struct vm_area_struct *vma;
+	int ret;
 
 	down_write(&mm->mmap_sem);
-	if (mm->uprobes_state.xol_area)
+	if (mm->uprobes_state.xol_area) {
+		ret = -EALREADY;
 		goto fail;
+	}
 
 	if (!area->vaddr) {
 		/* Try to map as high as possible, this is only a hint. */
@@ -1141,11 +1145,15 @@ static int xol_add_vma(struct mm_struct *mm, struct xol_area *area)
 		}
 	}
 
-	ret = install_special_mapping(mm, area->vaddr, PAGE_SIZE,
-				VM_EXEC|VM_MAYEXEC|VM_DONTCOPY|VM_IO, area->pages);
-	if (ret)
+	vma = _install_special_mapping(mm, area->vaddr, PAGE_SIZE,
+				VM_EXEC|VM_MAYEXEC|VM_DONTCOPY|VM_IO,
+				&area->xol_mapping);
+	if (IS_ERR(vma)) {
+		ret = PTR_ERR(vma);
 		goto fail;
+	}
 
+	ret = 0;
 	smp_wmb();	/* pairs with get_xol_area() */
 	mm->uprobes_state.xol_area = area;
  fail:
@@ -1168,6 +1176,8 @@ static struct xol_area *__create_xol_area(unsigned long vaddr)
 	if (!area->bitmap)
 		goto free_area;
 
+	area->xol_mapping.name = "[uprobes]";
+	area->xol_mapping.pages = area->pages;
 	area->pages[0] = alloc_page(GFP_HIGHUSER);
 	if (!area->pages[0])
 		goto free_bitmap;
-- 
1.5.5.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 3/3] uprobes: fix the waitqueue_active() check in xol_free_insn_slot()
  2015-07-09 21:44 uprobes: minor fixes + name the xol vma Oleg Nesterov
  2015-07-09 21:44 ` [PATCH 1/3] uprobes: fix the usage of install_special_mapping() Oleg Nesterov
  2015-07-09 21:44 ` [PATCH 2/3] uprobes: use vm_special_mapping to name the xol vma Oleg Nesterov
@ 2015-07-09 21:44 ` Oleg Nesterov
  2015-07-09 22:25 ` [PATCH v2 0/3] uprobes: minor fixes + name the xol vma Oleg Nesterov
  3 siblings, 0 replies; 13+ messages in thread
From: Oleg Nesterov @ 2015-07-09 21:44 UTC (permalink / raw)
  To: Ingo Molnar, Srikar Dronamraju
  Cc: Andy Lutomirski, Kirill A. Shutemov, linux-kernel

The xol_free_insn_slot()->waitqueue_active() check is buggy. We need
mb() after we set the conditon for wait_event(), or xol_take_insn_slot()
can miss the wakeup.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
 kernel/events/uprobes.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 6a9c5e0..9a4f9df 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -1336,6 +1336,7 @@ static void xol_free_insn_slot(struct task_struct *tsk)
 
 		clear_bit(slot_nr, area->bitmap);
 		atomic_dec(&area->slot_count);
+		smp_mb__after_atomic(); /* pairs with prepare_to_wait() */
 		if (waitqueue_active(&area->wq))
 			wake_up(&area->wq);
 
-- 
1.5.5.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/3] uprobes: fix the usage of install_special_mapping()
  2015-07-09 21:44 ` [PATCH 1/3] uprobes: fix the usage of install_special_mapping() Oleg Nesterov
@ 2015-07-09 21:49   ` Andy Lutomirski
  2015-07-09 22:02     ` Oleg Nesterov
  0 siblings, 1 reply; 13+ messages in thread
From: Andy Lutomirski @ 2015-07-09 21:49 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: Ingo Molnar, Srikar Dronamraju, Kirill A. Shutemov,
	linux-kernel@vger.kernel.org

On Thu, Jul 9, 2015 at 2:44 PM, Oleg Nesterov <oleg@redhat.com> wrote:
> install_special_mapping(pages) expects that "pages" is the zero-
> terminated array while xol_add_vma() passes &area->page, this means
> that special_mapping_fault() can wrongly use the next member in
> xol_area (vaddr) as "struct page *".
>
> Fortunately, this area is not expandable so pgoff != 0 isn't possible
> (modulo bugs in special_mapping_vmops), but still this does not look
> good.
>

I fell for that awhile back, too, causing a bizarre HPET bug.

What zeroes pages[1]?

--Andy

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 2/3] uprobes: use vm_special_mapping to name the xol vma
  2015-07-09 21:44 ` [PATCH 2/3] uprobes: use vm_special_mapping to name the xol vma Oleg Nesterov
@ 2015-07-09 21:50   ` Andy Lutomirski
  2015-07-09 22:03     ` Oleg Nesterov
  0 siblings, 1 reply; 13+ messages in thread
From: Andy Lutomirski @ 2015-07-09 21:50 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: Ingo Molnar, Srikar Dronamraju, Kirill A. Shutemov,
	linux-kernel@vger.kernel.org

On Thu, Jul 9, 2015 at 2:44 PM, Oleg Nesterov <oleg@redhat.com> wrote:
> Change xol_add_vma() to use _install_special_mapping(), this way
> we can name the vma installed by uprobes. Currently it looks like
> private anonymous mapping, this is confusing and complicates the
> debugging. With this change /proc/$pid/maps reports "[uprobes]".

I think this will cause core dumps to include it as a side effect.  Is
that okay?

--Andy

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/3] uprobes: fix the usage of install_special_mapping()
  2015-07-09 21:49   ` Andy Lutomirski
@ 2015-07-09 22:02     ` Oleg Nesterov
  2015-07-09 22:12       ` Andy Lutomirski
  0 siblings, 1 reply; 13+ messages in thread
From: Oleg Nesterov @ 2015-07-09 22:02 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Ingo Molnar, Srikar Dronamraju, Kirill A. Shutemov,
	linux-kernel@vger.kernel.org

On 07/09, Andy Lutomirski wrote:
>
> On Thu, Jul 9, 2015 at 2:44 PM, Oleg Nesterov <oleg@redhat.com> wrote:
> > install_special_mapping(pages) expects that "pages" is the zero-
> > terminated array while xol_add_vma() passes &area->page, this means
> > that special_mapping_fault() can wrongly use the next member in
> > xol_area (vaddr) as "struct page *".
> >
> > Fortunately, this area is not expandable so pgoff != 0 isn't possible
> > (modulo bugs in special_mapping_vmops), but still this does not look
> > good.
> >
>
> I fell for that awhile back, too, causing a bizarre HPET bug.

I guess you mean no_pages[] = {NULL} in map_vdso() ?

uprobes differs, I think pgoff != 0 is not actually possible (assuming
we fix special_mapping_fault). But this doesn't matter, this is wrong
anyway.

> What zeroes pages[1]?

Heh ;) Thanks. I'll send v2.

Oleg.


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 2/3] uprobes: use vm_special_mapping to name the xol vma
  2015-07-09 21:50   ` Andy Lutomirski
@ 2015-07-09 22:03     ` Oleg Nesterov
  0 siblings, 0 replies; 13+ messages in thread
From: Oleg Nesterov @ 2015-07-09 22:03 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Ingo Molnar, Srikar Dronamraju, Kirill A. Shutemov,
	linux-kernel@vger.kernel.org

On 07/09, Andy Lutomirski wrote:
>
> On Thu, Jul 9, 2015 at 2:44 PM, Oleg Nesterov <oleg@redhat.com> wrote:
> > Change xol_add_vma() to use _install_special_mapping(), this way
> > we can name the vma installed by uprobes. Currently it looks like
> > private anonymous mapping, this is confusing and complicates the
> > debugging. With this change /proc/$pid/maps reports "[uprobes]".
>
> I think this will cause core dumps to include it as a side effect.  Is
> that okay?

Yes, I even mentioned this in 0/3... I'll move thhis note into the
changelog in v2.

Thanks!

Oleg.


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/3] uprobes: fix the usage of install_special_mapping()
  2015-07-09 22:02     ` Oleg Nesterov
@ 2015-07-09 22:12       ` Andy Lutomirski
  0 siblings, 0 replies; 13+ messages in thread
From: Andy Lutomirski @ 2015-07-09 22:12 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: Ingo Molnar, Srikar Dronamraju, Kirill A. Shutemov,
	linux-kernel@vger.kernel.org

On Thu, Jul 9, 2015 at 3:02 PM, Oleg Nesterov <oleg@redhat.com> wrote:
> On 07/09, Andy Lutomirski wrote:
>>
>> On Thu, Jul 9, 2015 at 2:44 PM, Oleg Nesterov <oleg@redhat.com> wrote:
>> > install_special_mapping(pages) expects that "pages" is the zero-
>> > terminated array while xol_add_vma() passes &area->page, this means
>> > that special_mapping_fault() can wrongly use the next member in
>> > xol_area (vaddr) as "struct page *".
>> >
>> > Fortunately, this area is not expandable so pgoff != 0 isn't possible
>> > (modulo bugs in special_mapping_vmops), but still this does not look
>> > good.
>> >
>>
>> I fell for that awhile back, too, causing a bizarre HPET bug.
>
> I guess you mean no_pages[] = {NULL} in map_vdso() ?

Yes.

--Andy

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v2 0/3] uprobes: minor fixes + name the xol vma
  2015-07-09 21:44 uprobes: minor fixes + name the xol vma Oleg Nesterov
                   ` (2 preceding siblings ...)
  2015-07-09 21:44 ` [PATCH 3/3] uprobes: fix the waitqueue_active() check in xol_free_insn_slot() Oleg Nesterov
@ 2015-07-09 22:25 ` Oleg Nesterov
  2015-07-09 22:25   ` [PATCH v2 1/3] uprobes: fix the usage of install_special_mapping() Oleg Nesterov
                     ` (2 more replies)
  3 siblings, 3 replies; 13+ messages in thread
From: Oleg Nesterov @ 2015-07-09 22:25 UTC (permalink / raw)
  To: Ingo Molnar, Srikar Dronamraju
  Cc: Andy Lutomirski, Kirill A. Shutemov, linux-kernel

On 07/09, Oleg Nesterov wrote:
>
> Hello,
>
> The bugs are theoretical, but still should be fixed imo. And it
> would be nice to name the special vma installed by uprobes. As a
> side effect this vma will be core-dump'ed, I think this is good.
>
> This doesn't depend on the pending longjmp fixes.

v2:

	1/3 - initialize pages[1] (thanks Andy!)

	2/3 - update the changelog

Oleg.

 kernel/events/uprobes.c |   44 ++++++++++++++++++++++++++++----------------
 1 files changed, 28 insertions(+), 16 deletions(-)


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v2 1/3] uprobes: fix the usage of install_special_mapping()
  2015-07-09 22:25 ` [PATCH v2 0/3] uprobes: minor fixes + name the xol vma Oleg Nesterov
@ 2015-07-09 22:25   ` Oleg Nesterov
  2015-07-09 22:25   ` [PATCH v2 2/3] uprobes: use vm_special_mapping to name the xol vma Oleg Nesterov
  2015-07-09 22:25   ` [PATCH v2 3/3] uprobes: fix the waitqueue_active() check in xol_free_insn_slot() Oleg Nesterov
  2 siblings, 0 replies; 13+ messages in thread
From: Oleg Nesterov @ 2015-07-09 22:25 UTC (permalink / raw)
  To: Ingo Molnar, Srikar Dronamraju
  Cc: Andy Lutomirski, Kirill A. Shutemov, linux-kernel

install_special_mapping(pages) expects that "pages" is the zero-
terminated array while xol_add_vma() passes &area->page, this means
that special_mapping_fault() can wrongly use the next member in
xol_area (vaddr) as "struct page *".

Fortunately, this area is not expandable so pgoff != 0 isn't possible
(modulo bugs in special_mapping_vmops), but still this does not look
good.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
 kernel/events/uprobes.c |   17 +++++++++--------
 1 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 0f370ef..4b8ac5f 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -99,7 +99,7 @@ struct xol_area {
 	wait_queue_head_t 	wq;		/* if all slots are busy */
 	atomic_t 		slot_count;	/* number of in-use slots */
 	unsigned long 		*bitmap;	/* 0 = free slot */
-	struct page 		*page;
+	struct page 		*pages[2];
 
 	/*
 	 * We keep the vma's vm_start rather than a pointer to the vma
@@ -1142,7 +1142,7 @@ static int xol_add_vma(struct mm_struct *mm, struct xol_area *area)
 	}
 
 	ret = install_special_mapping(mm, area->vaddr, PAGE_SIZE,
-				VM_EXEC|VM_MAYEXEC|VM_DONTCOPY|VM_IO, &area->page);
+				VM_EXEC|VM_MAYEXEC|VM_DONTCOPY|VM_IO, area->pages);
 	if (ret)
 		goto fail;
 
@@ -1168,21 +1168,22 @@ static struct xol_area *__create_xol_area(unsigned long vaddr)
 	if (!area->bitmap)
 		goto free_area;
 
-	area->page = alloc_page(GFP_HIGHUSER);
-	if (!area->page)
+	area->pages[0] = alloc_page(GFP_HIGHUSER);
+	if (!area->pages[0])
 		goto free_bitmap;
+	area->pages[1] = NULL;
 
 	area->vaddr = vaddr;
 	init_waitqueue_head(&area->wq);
 	/* Reserve the 1st slot for get_trampoline_vaddr() */
 	set_bit(0, area->bitmap);
 	atomic_set(&area->slot_count, 1);
-	copy_to_page(area->page, 0, &insn, UPROBE_SWBP_INSN_SIZE);
+	copy_to_page(area->pages[0], 0, &insn, UPROBE_SWBP_INSN_SIZE);
 
 	if (!xol_add_vma(mm, area))
 		return area;
 
-	__free_page(area->page);
+	__free_page(area->pages[0]);
  free_bitmap:
 	kfree(area->bitmap);
  free_area:
@@ -1220,7 +1221,7 @@ void uprobe_clear_state(struct mm_struct *mm)
 	if (!area)
 		return;
 
-	put_page(area->page);
+	put_page(area->pages[0]);
 	kfree(area->bitmap);
 	kfree(area);
 }
@@ -1289,7 +1290,7 @@ static unsigned long xol_get_insn_slot(struct uprobe *uprobe)
 	if (unlikely(!xol_vaddr))
 		return 0;
 
-	arch_uprobe_copy_ixol(area->page, xol_vaddr,
+	arch_uprobe_copy_ixol(area->pages[0], xol_vaddr,
 			      &uprobe->arch.ixol, sizeof(uprobe->arch.ixol));
 
 	return xol_vaddr;
-- 
1.5.5.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 2/3] uprobes: use vm_special_mapping to name the xol vma
  2015-07-09 22:25 ` [PATCH v2 0/3] uprobes: minor fixes + name the xol vma Oleg Nesterov
  2015-07-09 22:25   ` [PATCH v2 1/3] uprobes: fix the usage of install_special_mapping() Oleg Nesterov
@ 2015-07-09 22:25   ` Oleg Nesterov
  2015-07-09 22:25   ` [PATCH v2 3/3] uprobes: fix the waitqueue_active() check in xol_free_insn_slot() Oleg Nesterov
  2 siblings, 0 replies; 13+ messages in thread
From: Oleg Nesterov @ 2015-07-09 22:25 UTC (permalink / raw)
  To: Ingo Molnar, Srikar Dronamraju
  Cc: Andy Lutomirski, Kirill A. Shutemov, linux-kernel

Change xol_add_vma() to use _install_special_mapping(), this way
we can name the vma installed by uprobes. Currently it looks like
private anonymous mapping, this is confusing and complicates the
debugging. With this change /proc/$pid/maps reports "[uprobes]".

As a side effect this will cause core dumps to include xol vma and
I think this is good; this can help to debug the problem if the app
crashed because it was probed.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
 kernel/events/uprobes.c |   30 ++++++++++++++++++++----------
 1 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 4b8ac5f..2d5b7bd 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -96,17 +96,18 @@ struct uprobe {
  * allocated.
  */
 struct xol_area {
-	wait_queue_head_t 	wq;		/* if all slots are busy */
-	atomic_t 		slot_count;	/* number of in-use slots */
-	unsigned long 		*bitmap;	/* 0 = free slot */
-	struct page 		*pages[2];
+	wait_queue_head_t 		wq;		/* if all slots are busy */
+	atomic_t 			slot_count;	/* number of in-use slots */
+	unsigned long 			*bitmap;	/* 0 = free slot */
 
+	struct vm_special_mapping	xol_mapping;
+	struct page 			*pages[2];
 	/*
 	 * We keep the vma's vm_start rather than a pointer to the vma
 	 * itself.  The probed process or a naughty kernel module could make
 	 * the vma go away, and we must handle that reasonably gracefully.
 	 */
-	unsigned long 		vaddr;		/* Page(s) of instruction slots */
+	unsigned long 			vaddr;		/* Page(s) of instruction slots */
 };
 
 /*
@@ -1125,11 +1126,14 @@ void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned lon
 /* Slot allocation for XOL */
 static int xol_add_vma(struct mm_struct *mm, struct xol_area *area)
 {
-	int ret = -EALREADY;
+	struct vm_area_struct *vma;
+	int ret;
 
 	down_write(&mm->mmap_sem);
-	if (mm->uprobes_state.xol_area)
+	if (mm->uprobes_state.xol_area) {
+		ret = -EALREADY;
 		goto fail;
+	}
 
 	if (!area->vaddr) {
 		/* Try to map as high as possible, this is only a hint. */
@@ -1141,11 +1145,15 @@ static int xol_add_vma(struct mm_struct *mm, struct xol_area *area)
 		}
 	}
 
-	ret = install_special_mapping(mm, area->vaddr, PAGE_SIZE,
-				VM_EXEC|VM_MAYEXEC|VM_DONTCOPY|VM_IO, area->pages);
-	if (ret)
+	vma = _install_special_mapping(mm, area->vaddr, PAGE_SIZE,
+				VM_EXEC|VM_MAYEXEC|VM_DONTCOPY|VM_IO,
+				&area->xol_mapping);
+	if (IS_ERR(vma)) {
+		ret = PTR_ERR(vma);
 		goto fail;
+	}
 
+	ret = 0;
 	smp_wmb();	/* pairs with get_xol_area() */
 	mm->uprobes_state.xol_area = area;
  fail:
@@ -1168,6 +1176,8 @@ static struct xol_area *__create_xol_area(unsigned long vaddr)
 	if (!area->bitmap)
 		goto free_area;
 
+	area->xol_mapping.name = "[uprobes]";
+	area->xol_mapping.pages = area->pages;
 	area->pages[0] = alloc_page(GFP_HIGHUSER);
 	if (!area->pages[0])
 		goto free_bitmap;
-- 
1.5.5.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 3/3] uprobes: fix the waitqueue_active() check in xol_free_insn_slot()
  2015-07-09 22:25 ` [PATCH v2 0/3] uprobes: minor fixes + name the xol vma Oleg Nesterov
  2015-07-09 22:25   ` [PATCH v2 1/3] uprobes: fix the usage of install_special_mapping() Oleg Nesterov
  2015-07-09 22:25   ` [PATCH v2 2/3] uprobes: use vm_special_mapping to name the xol vma Oleg Nesterov
@ 2015-07-09 22:25   ` Oleg Nesterov
  2 siblings, 0 replies; 13+ messages in thread
From: Oleg Nesterov @ 2015-07-09 22:25 UTC (permalink / raw)
  To: Ingo Molnar, Srikar Dronamraju
  Cc: Andy Lutomirski, Kirill A. Shutemov, linux-kernel

The xol_free_insn_slot()->waitqueue_active() check is buggy. We need
mb() after we set the conditon for wait_event(), or xol_take_insn_slot()
can miss the wakeup.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
 kernel/events/uprobes.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 2d5b7bd..4e5e979 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -1337,6 +1337,7 @@ static void xol_free_insn_slot(struct task_struct *tsk)
 
 		clear_bit(slot_nr, area->bitmap);
 		atomic_dec(&area->slot_count);
+		smp_mb__after_atomic(); /* pairs with prepare_to_wait() */
 		if (waitqueue_active(&area->wq))
 			wake_up(&area->wq);
 
-- 
1.5.5.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2015-07-09 22:27 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-07-09 21:44 uprobes: minor fixes + name the xol vma Oleg Nesterov
2015-07-09 21:44 ` [PATCH 1/3] uprobes: fix the usage of install_special_mapping() Oleg Nesterov
2015-07-09 21:49   ` Andy Lutomirski
2015-07-09 22:02     ` Oleg Nesterov
2015-07-09 22:12       ` Andy Lutomirski
2015-07-09 21:44 ` [PATCH 2/3] uprobes: use vm_special_mapping to name the xol vma Oleg Nesterov
2015-07-09 21:50   ` Andy Lutomirski
2015-07-09 22:03     ` Oleg Nesterov
2015-07-09 21:44 ` [PATCH 3/3] uprobes: fix the waitqueue_active() check in xol_free_insn_slot() Oleg Nesterov
2015-07-09 22:25 ` [PATCH v2 0/3] uprobes: minor fixes + name the xol vma Oleg Nesterov
2015-07-09 22:25   ` [PATCH v2 1/3] uprobes: fix the usage of install_special_mapping() Oleg Nesterov
2015-07-09 22:25   ` [PATCH v2 2/3] uprobes: use vm_special_mapping to name the xol vma Oleg Nesterov
2015-07-09 22:25   ` [PATCH v2 3/3] uprobes: fix the waitqueue_active() check in xol_free_insn_slot() Oleg Nesterov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.