On Tue, Nov 13, 2018 at 05:07:20AM -0800, Nadav Amit wrote:
> v4->v5:
> - Fix Xen breakage [Damian Tometzki]
> - BUG_ON() when poking_mm initialization fails [PeterZ]
> - Better comments on "x86/mm: temporary mm struct"
> - Cleaner removal of the custom poker

I'll re-iterate my position: it is impossible for the text not to match,
and if it somehow does not match, something went sideways in an
unrecoverably fashion.

text_poke() must not fail, ever. If it does, our text is inconsistent
and we must abort/panic/bug.

The only way I will accept anything else is if someone can come up with
a sensible scenario of text_poke() failing and recovering from it.
AFAICT there is no possible way to gracefully recover.

Consider a jump label with multiple patch sites; we patch the first,
then fail. In order to restore to a sane state, we must undo the
patching of the first, but undoing text_poke() fails again. Then
what?

Allowing text_poke() to fail only creates an unfixable mess. Esp. since
there is no sane scenario under which is can fail.

---


--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -695,7 +695,7 @@ void __init_or_module text_poke_early(vo
 __ro_after_init struct mm_struct *poking_mm;
 __ro_after_init unsigned long poking_addr;
 
-static int __text_poke(void *addr, const void *opcode, size_t len)
+static void __text_poke(void *addr, const void *opcode, size_t len)
 {
        bool cross_page_boundary = offset_in_page(addr) + len > PAGE_SIZE;
        temporary_mm_state_t prev;
@@ -731,13 +731,10 @@ static int __text_poke(void *addr, const
         * The lock is not really needed, but this allows to avoid open-coding.
         */
        ptep = get_locked_pte(poking_mm, poking_addr, &ptl);
-
        /*
-        * If we failed to allocate a PTE, fail. This should *never* happen,
-        * since we preallocate the PTE.
+        * This must not fail; preallocated in poking_init().
         */
-       if (WARN_ON_ONCE(!ptep))
-               goto out;
+       VM_BUG_ON(!ptep)
 
        pte = mk_pte(pages[0], PAGE_KERNEL);
        set_pte_at(poking_mm, poking_addr, ptep, pte);
@@ -795,12 +792,14 @@ static int __text_poke(void *addr, const
        unuse_temporary_mm(prev);
 
        pte_unmap_unlock(ptep, ptl);
-out:
-       if (memcmp(addr, opcode, len))
-               r = -EFAULT;
+
+       /*
+        * If the text doesn't match what we just wrote; something is
+        * fundamentally screwy, there's nothing we can really do about that.
+        */
+       BUG_ON(memcmp(addr, opcode, len));
 
        local_irq_restore(flags);
-       return r;
 }
 
 /**
@@ -814,21 +813,10 @@ static int __text_poke(void *addr, const
  * in a way that permits an atomic write. It also makes sure we fit on a single
  * page.
  */
-int text_poke(void *addr, const void *opcode, size_t len)
+void text_poke(void *addr, const void *opcode, size_t len)
 {
-       int r;
-
        lockdep_assert_held(&text_mutex);
-
-       r = __text_poke(addr, opcode, len);
-
-       /*
-        * TODO: change the callers to consider the return value and remove this
-        *       historical assertion.
-        */
-       BUG_ON(r);
-
-       return r;
+       __text_poke(addr, opcode, len);
 }
 
 /**
@@ -847,7 +835,7 @@ int text_poke(void *addr, const void *op
  */
 int text_poke_kgdb(void *addr, const void *opcode, size_t len)
 {
-       return __text_poke(addr, opcode, len);
+       __text_poke(addr, opcode, len);
 }
 
 static void do_sync_core(void *info)
--- a/arch/x86/kernel/kgdb.c
+++ b/arch/x86/kernel/kgdb.c
@@ -767,10 +767,8 @@ int kgdb_arch_set_breakpoint(struct kgdb
         */
        if (mutex_is_locked(&text_mutex))
                return -EBUSY;
-       err = text_poke_kgdb((void *)bpt->bpt_addr, arch_kgdb_ops.gdb_bpt_instr,
+       text_poke_kgdb((void *)bpt->bpt_addr, arch_kgdb_ops.gdb_bpt_instr,
                             BREAK_INSTR_SIZE);
-       if (err)
-               return err;
        bpt->type = BP_POKE_BREAKPOINT;
 
        return err;
@@ -788,11 +786,8 @@ int kgdb_arch_remove_breakpoint(struct k
         */
        if (mutex_is_locked(&text_mutex))
                goto knl_write;
-       err = text_poke_kgdb((void *)bpt->bpt_addr, bpt->saved_instr,
-                            BREAK_INSTR_SIZE);
-       if (err)
-               goto knl_write;
-       return err;
+       text_poke_kgdb((void *)bpt->bpt_addr, bpt->saved_instr, 
BREAK_INSTR_SIZE);
+       return 0;
 
 knl_write:
        return probe_kernel_write((char *)bpt->bpt_addr,

Reply via email to