linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
From: Pasha Tatashin <pasha.tatashin@soleen.com>
To: Oskar Gerlicz Kowalczuk <oskar@gerlicz.space>
Cc: Mike Rapoport <rppt@kernel.org>, Baoquan He <bhe@redhat.com>,
	 Pratyush Yadav <pratyush@kernel.org>,
	Andrew Morton <akpm@linux-foundation.org>,
	 linux-kernel@vger.kernel.org, kexec@lists.infradead.org,
	linux-mm@kvack.org
Subject: Re: [PATCH v3 2/5] kexec: abort liveupdate handover on kernel_kexec() unwind
Date: Sat, 21 Mar 2026 19:05:07 -0400	[thread overview]
Message-ID: <CA+CK2bCVge7xybLshgLLphHAdRSHMLD3egT1nEyESBUFi7kHCw@mail.gmail.com> (raw)
In-Reply-To: <20260321143642.166313-2-oskar@gerlicz.space>

On Sat, Mar 21, 2026 at 10:39 AM Oskar Gerlicz Kowalczuk
<oskar@gerlicz.space> wrote:
>
> liveupdate_reboot() can freeze outgoing session state before the kexec
> transition completes. v2 only unwound that state when kernel_kexec()
> returned a non-zero error, which misses the preserve_context path where
> machine_kexec() can return to the old kernel with error == 0.
>
> If that return path skips the abort, outgoing sessions remain stuck in
> the reboot state and later user space operations cannot make progress.
>
> Treat every return to the original kernel after a prepared liveupdate
> handover as an unwind point and call liveupdate_reboot_abort() there as
> well.
>
> Fixes: 8b32d3ced269 ("kexec: abort liveupdate handover on kernel_kexec() unwind")
> Signed-off-by: Oskar Gerlicz Kowalczuk <oskar@gerlicz.space>

AFAIK, preserve-context reboot is no longer used; in fact, it is
currently broken. I tried using it six years ago and hit an old
spinlock bug in the x86 code that prevented it, which means this path
touches dead code.

It was originally developed for machines lacking hardware support for
hibernation, and I can't imagine anyone using it today. (I know Amazon
is using it for a non intended reason and that is a very specific
scenario in a costumized kernel that internally fixes the upstream
bugs, and would not conlict with live update).

During live update, we cannot return to userspace after a successful
liveupdate_reboot(). We specifically place liveupdate_reboot() in the
kexec path as the last possible point of failure. Perhap, to guarantee
this behavior, we could  add !KEXEC_JUMP as a dependency to KHO and
LUO or crash the kernel.

Pasha

> ---
>  include/linux/liveupdate.h       |  5 +++++
>  kernel/kexec_core.c              |  6 +++++-
>  kernel/liveupdate/luo_core.c     | 11 ++++++++++-
>  kernel/liveupdate/luo_internal.h |  1 +
>  kernel/liveupdate/luo_session.c  | 23 +++++++++++++++++++++++
>  5 files changed, 44 insertions(+), 2 deletions(-)
>
> diff --git a/include/linux/liveupdate.h b/include/linux/liveupdate.h
> index dd11fdc76a5f..d93b043a0421 100644
> --- a/include/linux/liveupdate.h
> +++ b/include/linux/liveupdate.h
> @@ -226,6 +226,7 @@ bool liveupdate_enabled(void);
>
>  /* Called during kexec to tell LUO that entered into reboot */
>  int liveupdate_reboot(void);
> +void liveupdate_reboot_abort(void);
>
>  int liveupdate_register_file_handler(struct liveupdate_file_handler *fh);
>  int liveupdate_unregister_file_handler(struct liveupdate_file_handler *fh);
> @@ -250,6 +251,10 @@ static inline int liveupdate_reboot(void)
>         return 0;
>  }
>
> +static inline void liveupdate_reboot_abort(void)
> +{
> +}
> +
>  static inline int liveupdate_register_file_handler(struct liveupdate_file_handler *fh)
>  {
>         return -EOPNOTSUPP;
> diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c
> index 2fea396d29b9..95710a7d5e56 100644
> --- a/kernel/kexec_core.c
> +++ b/kernel/kexec_core.c
> @@ -1139,6 +1139,7 @@ bool kexec_load_permitted(int kexec_image_type)
>  int kernel_kexec(void)
>  {
>         int error = 0;
> +       bool liveupdate_prepared = false;
>
>         if (!kexec_trylock())
>                 return -EBUSY;
> @@ -1147,6 +1148,7 @@ int kernel_kexec(void)
>                 goto Unlock;
>         }
>
> +       liveupdate_prepared = true;
>         error = liveupdate_reboot();
>         if (error)
>                 goto Unlock;
> @@ -1230,7 +1232,9 @@ int kernel_kexec(void)
>         }
>  #endif
>
> - Unlock:
> +Unlock:
> +       if (liveupdate_prepared)
> +               liveupdate_reboot_abort();
>         kexec_unlock();
>         return error;
>  }
> diff --git a/kernel/liveupdate/luo_core.c b/kernel/liveupdate/luo_core.c
> index dda7bb57d421..95a0b81ce60d 100644
> --- a/kernel/liveupdate/luo_core.c
> +++ b/kernel/liveupdate/luo_core.c
> @@ -233,8 +233,9 @@ int liveupdate_reboot(void)
>         err = kho_finalize();
>         if (err) {
>                 pr_err("kho_finalize failed %d\n", err);
> +               liveupdate_reboot_abort();
>                 /*
> -                * kho_finalize() may return libfdt errors, to aboid passing to
> +                * kho_finalize() may return libfdt errors, to avoid passing to
>                  * userspace unknown errors, change this to EAGAIN.
>                  */
>                 err = -EAGAIN;
> @@ -243,6 +244,14 @@ int liveupdate_reboot(void)
>         return err;
>  }
>
> +void liveupdate_reboot_abort(void)
> +{
> +       if (!liveupdate_enabled())
> +               return;
> +
> +       luo_session_abort_reboot();
> +}
> +
>  /**
>   * liveupdate_enabled - Check if the live update feature is enabled.
>   *
> diff --git a/kernel/liveupdate/luo_internal.h b/kernel/liveupdate/luo_internal.h
> index 0cfc0269d746..8a6b1f6c9b4f 100644
> --- a/kernel/liveupdate/luo_internal.h
> +++ b/kernel/liveupdate/luo_internal.h
> @@ -88,6 +88,7 @@ int luo_session_retrieve(const char *name, struct file **filep);
>  int __init luo_session_setup_outgoing(void *fdt);
>  int __init luo_session_setup_incoming(void *fdt);
>  int luo_session_serialize(void);
> +void luo_session_abort_reboot(void);
>  int luo_session_deserialize(void);
>  bool luo_session_quiesce(void);
>  void luo_session_resume(void);
> diff --git a/kernel/liveupdate/luo_session.c b/kernel/liveupdate/luo_session.c
> index d97ec91e1118..200dd3b8229c 100644
> --- a/kernel/liveupdate/luo_session.c
> +++ b/kernel/liveupdate/luo_session.c
> @@ -788,6 +788,29 @@ int luo_session_serialize(void)
>         return err;
>  }
>
> +void luo_session_abort_reboot(void)
> +{
> +       struct luo_session_header *sh = &luo_session_global.outgoing;
> +       struct luo_session *session;
> +       int i = 0;
> +
> +       guard(rwsem_write)(&sh->rwsem);
> +       if (!READ_ONCE(sh->rebooting))
> +               return;
> +
> +       list_for_each_entry(session, &sh->list, list) {
> +               if (i >= sh->header_ser->count)
> +                       break;
> +
> +               luo_session_unfreeze_one(session, &sh->ser[i]);
> +               memset(&sh->ser[i], 0, sizeof(sh->ser[i]));
> +               i++;
> +       }
> +
> +       sh->header_ser->count = 0;
> +       luo_session_reboot_done(sh);
> +}
> +
>  /**
>   * luo_session_quiesce - Ensure no active sessions exist and lock session lists.
>   *
> --
> 2.53.0
>
>


  parent reply	other threads:[~2026-03-21 23:05 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-21 14:36 [PATCH v3 1/5] liveupdate: block outgoing session updates during reboot Oskar Gerlicz Kowalczuk
2026-03-21 14:36 ` [PATCH v3 2/5] kexec: abort liveupdate handover on kernel_kexec() unwind Oskar Gerlicz Kowalczuk
2026-03-21 14:36   ` [PATCH v3 3/5] liveupdate: fail session restore on file deserialization errors Oskar Gerlicz Kowalczuk
2026-03-21 14:36     ` [PATCH v3 4/5] liveupdate: validate handover metadata before using it Oskar Gerlicz Kowalczuk
2026-03-21 14:36       ` [PATCH v3 5/5] liveupdate: harden FLB lifetime and teardown paths Oskar Gerlicz Kowalczuk
2026-03-21 23:05   ` Pasha Tatashin [this message]
2026-03-23 14:12     ` [PATCH v3 2/5] kexec: abort liveupdate handover on kernel_kexec() unwind Pasha Tatashin
2026-03-21 17:45 ` [PATCH v3 1/5] liveupdate: block outgoing session updates during reboot Andrew Morton
2026-03-21 22:28 ` Pasha Tatashin
2026-03-23 19:00   ` Pasha Tatashin
2026-03-23 20:52     ` oskar
2026-03-23 22:23       ` Pasha Tatashin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CA+CK2bCVge7xybLshgLLphHAdRSHMLD3egT1nEyESBUFi7kHCw@mail.gmail.com \
    --to=pasha.tatashin@soleen.com \
    --cc=akpm@linux-foundation.org \
    --cc=bhe@redhat.com \
    --cc=kexec@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=oskar@gerlicz.space \
    --cc=pratyush@kernel.org \
    --cc=rppt@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox