Thread (4 messages) flat view 4 messages, 2 authors, 2018-05-23

Re: [PATCH v8] powerpc/mm: Only read faulting instruction when necessary in do_page_fault()

From: Nicholas Piggin <npiggin@gmail.com>
Date: 2018-05-23 08:05:52
Also in: lkml

On Wed, 23 May 2018 09:31:33 +0200
Christophe LEROY [off-list ref] wrote:
Le 23/05/2018 =C3=A0 09:17, Nicholas Piggin a =C3=A9crit=C2=A0:
quoted
On Wed, 23 May 2018 09:01:19 +0200 (CEST)
Christophe Leroy [off-list ref] wrote:
 =20
quoted
quoted
@@ -264,8 +266,30 @@ static bool bad_stack_expansion(struct pt_regs *r=
egs, unsigned long address,
quoted
quoted
  		 * between the last mapped region and the stack will
  		 * expand the stack rather than segfaulting.
  		 */
-		if (address + 2048 < uregs->gpr[1] && !store_update_sp)
-			return true;
+		if (address + 2048 >=3D uregs->gpr[1])
+			return false;
+		if (is_retry)
+			return false;
+
+		if ((flags & FAULT_FLAG_WRITE) && (flags & FAULT_FLAG_USER) &&
+		    access_ok(VERIFY_READ, nip, sizeof(inst))) {
+			int res;
+
+			pagefault_disable();
+			res =3D __get_user_inatomic(inst, nip);
+			pagefault_enable();
+			if (res) {
+				up_read(&mm->mmap_sem);
+				res =3D __get_user(inst, nip);
+				if (!res && store_updates_sp(inst))
+					return -1;
+				return true;
+			}
+			if (store_updates_sp(inst))
+				return false;
+		}
+		up_read(&mm->mmap_sem); =20
=20
Starting to look pretty good... I think probably I prefer the mmap_sem
drop going into the caller so we don't don't drop in the child function=
. =20
=20
Yes I can do that. I though it was ok as the drop is already done in=20
children functions like bad_area(), bad_access(), ...
That's true, all exit functions though. I think it may end up being a
bit nicer with the up_read in the caller, but see what you think.
quoted
I thought the retry logic was a little bit complex too, what do you
think of using fault_in_pages_readable and just doing a full retry to
avoid some of this complexity? =20
=20
Yes lets try that way, allthough fault_in_pages_readable() is nothing=20
else than a get_user().
Should we take any precaution to avoid retrying forever or is it just=20
not worth it ?
generic_perform_write() the core of the data copying for write(2)
syscall does this retry, so I think it's okay... Although I think I
wrote that so maybe that's a circular justification.

I think if we end up thrashing on this type of loop for a long time,
the system will already be basically dead.

quoted
quoted
  	/* The stack is being expanded, check if it's valid */
-	if (unlikely(bad_stack_expansion(regs, address, vma, store_update_sp=
)))
quoted
quoted
-		return bad_area(regs, address);
+	is_bad =3D bad_stack_expansion(regs, address, vma, flags, is_retry);
+	if (unlikely(is_bad =3D=3D -1)) {
+		is_retry =3D true;
+		goto retry;
+	}
+	if (unlikely(is_bad))
+		return bad_area_nosemaphore(regs, address); =20
=20
Suggest making the return so that you can do a single unlikely test for
the retry or bad case, and then distinguish the retry in there. Code
generation should be better. =20
=20
Ok. I'll try and come with v9 during this morning.
Thanks,
Nick
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help