fs/pstore/ftrace.c | 33 +++++++++++++++++++++++++++++++-- fs/pstore/inode.c | 6 ++++-- fs/pstore/internal.h | 2 ++ 3 files changed, 37 insertions(+), 4 deletions(-)
The pstore ftrace frontend works by purely collecting the
instruction address, saving it on the persistent area through
the backend and when the log is read, on next boot for example,
the address is then resolved by using the regular printk symbol
lookup (%pS for example).
Problem: if we are running a relocatable kernel with KASLR enabled,
this is a recipe for failure in the symbol resolution on next boots,
since the addresses are offset'ed by the KASLR address. So, naturally
the way to go is factor the KASLR address out of instruction address
collection, and adding the fresh offset when resolving the symbol
on future boots.
Problem #2: modules also have varying addresses that float based
on module base address and potentially the module ordering in
memory, meaning factoring KASLR offset for them is useless.
So, let's hereby only take KASLR offset into account for core
kernel addresses, leaving module ones as is.
And we have yet a 3rd complexity: not necessarily the check range
for core kernel addresses holds true on future boots, since the
module base address will vary. With that, the choice was to mark
the addresses as being core vs module based on its MSB. And with
that...
...we have the 4th challenge here: for some "simple" architectures,
the CPU number is saved bit-encoded on the instruction pointer, to
allow bigger timestamps - this is set through the PSTORE_CPU_IN_IP
define for such architectures. Hence, the approach here is to skip
such architectures (at least in a first moment).
TL;DR: let's factor KASLR offsets on pstore/ftrace for core kernel
addresses, leaving module addresses out and also leaving the
architectures that define PSTORE_CPU_IN_IP.
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
Hi folks, first of all thanks in advance for reviews and comments!
I was testing a pstore/ftrace patch the other day and noticed
the lack of the KASLR support. But to my surprise, it was not
as easy to fix up as I expected heh
Main reason is the obvious thing with modules: the way to
go, I think, is to somehow save the module name (or some other
id?) and the instruction offset inside such module, to then
resolve that in next boot, when printing. But that would require
more intrusive changes in the way pstore/ftrace saves the IP
(which is quite simple now), leading to some potentially
meaningful perf overhead.
Hence, I've decided to just mess with core kernel addresses
so far, lemme know WDYT - should I somehow pursue fixing
modules addr resolution as well? Or doesn't worth the changes?
Any ideas on how to approach that? I noticed that currently,
modules' symbols are sometimes resolved fine, sometimes they're
bogus but point to the module at least (not some other random
code), but eventually they are just nonsense addresses.
Regarding the choice of using the MSB to store if an addr is core
kernel or module, well this was also a choice taking into account
simplicity and performance, lemme know please if it's no good and
any suggestions on how to better do it, I can easily re-implement!
Thanks again,
Guilherme
fs/pstore/ftrace.c | 33 +++++++++++++++++++++++++++++++--
fs/pstore/inode.c | 6 ++++--
fs/pstore/internal.h | 2 ++
3 files changed, 37 insertions(+), 4 deletions(-)
diff --git a/fs/pstore/ftrace.c b/fs/pstore/ftrace.c
index 13db123beac1..58f8204b23af 100644
--- a/fs/pstore/ftrace.c
+++ b/fs/pstore/ftrace.c
@@ -18,10 +18,35 @@
#include <linux/cache.h>
#include <linux/slab.h>
#include <asm/barrier.h>
+#include <asm/setup.h>
#include "internal.h"
/* This doesn't need to be atomic: speed is chosen over correctness here. */
static u64 pstore_ftrace_stamp;
+unsigned long kaslr_off;
+
+static inline unsigned long adjust_ip(unsigned long ip)
+{
+#ifndef PSTORE_CPU_IN_IP
+ if (core_kernel_text(ip))
+ return ip - kaslr_off;
+
+ __clear_bit(BITS_PER_LONG - 1, &ip);
+#endif
+ return ip;
+}
+
+inline unsigned long decode_ip(unsigned long ip)
+{
+#ifndef PSTORE_CPU_IN_IP
+ if (test_bit(BITS_PER_LONG - 1, &ip))
+ return ip + kaslr_off;
+
+ __set_bit(BITS_PER_LONG - 1, &ip);
+
+#endif
+ return ip;
+}
static void notrace pstore_ftrace_call(unsigned long ip,
unsigned long parent_ip,
@@ -47,8 +72,8 @@ static void notrace pstore_ftrace_call(unsigned long ip,
local_irq_save(flags);
- rec.ip = ip;
- rec.parent_ip = parent_ip;
+ rec.ip = adjust_ip(ip);
+ rec.parent_ip = adjust_ip(parent_ip);
pstore_ftrace_write_timestamp(&rec, pstore_ftrace_stamp++);
pstore_ftrace_encode_cpu(&rec, raw_smp_processor_id());
psinfo->write(&record);
@@ -132,6 +157,10 @@ void pstore_register_ftrace(void)
if (!psinfo->write)
return;
+#ifdef CONFIG_RANDOMIZE_BASE
+ kaslr_off = kaslr_offset();
+#endif
+
pstore_ftrace_dir = debugfs_create_dir("pstore", NULL);
pstore_set_ftrace_enabled(record_ftrace);
diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c
index 83fa0bb3435a..62e678f3527d 100644
--- a/fs/pstore/inode.c
+++ b/fs/pstore/inode.c
@@ -105,17 +105,19 @@ static int pstore_ftrace_seq_show(struct seq_file *s, void *v)
struct pstore_private *ps = s->private;
struct pstore_ftrace_seq_data *data = v;
struct pstore_ftrace_record *rec;
+ unsigned long ip, parent_ip;
if (!data)
return 0;
rec = (struct pstore_ftrace_record *)(ps->record->buf + data->off);
+ ip = decode_ip(rec->ip);
+ parent_ip = decode_ip(rec->parent_ip);
seq_printf(s, "CPU:%d ts:%llu %08lx %08lx %ps <- %pS\n",
pstore_ftrace_decode_cpu(rec),
pstore_ftrace_read_timestamp(rec),
- rec->ip, rec->parent_ip, (void *)rec->ip,
- (void *)rec->parent_ip);
+ ip, parent_ip, (void *)ip, (void *)parent_ip);
return 0;
}
diff --git a/fs/pstore/internal.h b/fs/pstore/internal.h
index a0fc51196910..079284120db9 100644
--- a/fs/pstore/internal.h
+++ b/fs/pstore/internal.h
@@ -9,6 +9,7 @@
extern unsigned int kmsg_bytes;
#ifdef CONFIG_PSTORE_FTRACE
+extern unsigned long decode_ip(unsigned long ip);
extern void pstore_register_ftrace(void);
extern void pstore_unregister_ftrace(void);
ssize_t pstore_ftrace_combine_log(char **dest_log, size_t *dest_log_size,
@@ -16,6 +17,7 @@ ssize_t pstore_ftrace_combine_log(char **dest_log, size_t *dest_log_size,
#else
static inline void pstore_register_ftrace(void) {}
static inline void pstore_unregister_ftrace(void) {}
+static inline unsigned long decode_ip(unsigned long ip) { return ip; }
static inline ssize_t
pstore_ftrace_combine_log(char **dest_log, size_t *dest_log_size,
const char *src_log, size_t src_log_size)
--
2.50.1
Hi Guilherme, kernel test robot noticed the following build errors: [auto build test ERROR on kees/for-next/pstore] [also build test ERROR on kees/for-next/kspp linus/master v7.0-rc6 next-20260403] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Guilherme-G-Piccoli/pstore-ftrace-Factor-KASLR-offset-in-the-core-kernel-instruction-addresses/20260315-152241 base: https://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/pstore patch link: https://lore.kernel.org/r/20260313201010.1622406-3-gpiccoli%40igalia.com patch subject: [PATCH] pstore/ftrace: Factor KASLR offset in the core kernel instruction addresses config: parisc-allmodconfig (https://download.01.org/0day-ci/archive/20260405/202604051301.skV8JLnH-lkp@intel.com/config) compiler: hppa-linux-gcc (GCC) 15.2.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260405/202604051301.skV8JLnH-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202604051301.skV8JLnH-lkp@intel.com/ All errors (new ones prefixed by >>, old ones prefixed by <<): >> ERROR: modpost: "core_kernel_text" [fs/pstore/pstore.ko] undefined! -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
On Fri, Mar 13, 2026 at 05:00:22PM -0300, Guilherme G. Piccoli wrote:
> The pstore ftrace frontend works by purely collecting the
> instruction address, saving it on the persistent area through
> the backend and when the log is read, on next boot for example,
> the address is then resolved by using the regular printk symbol
> lookup (%pS for example).
>
> Problem: if we are running a relocatable kernel with KASLR enabled,
> this is a recipe for failure in the symbol resolution on next boots,
> since the addresses are offset'ed by the KASLR address. So, naturally
> the way to go is factor the KASLR address out of instruction address
> collection, and adding the fresh offset when resolving the symbol
> on future boots.
>
> Problem #2: modules also have varying addresses that float based
> on module base address and potentially the module ordering in
> memory, meaning factoring KASLR offset for them is useless.
> So, let's hereby only take KASLR offset into account for core
> kernel addresses, leaving module ones as is.
>
> And we have yet a 3rd complexity: not necessarily the check range
> for core kernel addresses holds true on future boots, since the
> module base address will vary. With that, the choice was to mark
> the addresses as being core vs module based on its MSB. And with
> that...
>
> ...we have the 4th challenge here: for some "simple" architectures,
> the CPU number is saved bit-encoded on the instruction pointer, to
> allow bigger timestamps - this is set through the PSTORE_CPU_IN_IP
> define for such architectures. Hence, the approach here is to skip
> such architectures (at least in a first moment).
>
> TL;DR: let's factor KASLR offsets on pstore/ftrace for core kernel
> addresses, leaving module addresses out and also leaving the
> architectures that define PSTORE_CPU_IN_IP.
>
> Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
> ---
>
>
> Hi folks, first of all thanks in advance for reviews and comments!
>
> I was testing a pstore/ftrace patch the other day and noticed
> the lack of the KASLR support. But to my surprise, it was not
> as easy to fix up as I expected heh
>
> Main reason is the obvious thing with modules: the way to
> go, I think, is to somehow save the module name (or some other
> id?) and the instruction offset inside such module, to then
> resolve that in next boot, when printing. But that would require
> more intrusive changes in the way pstore/ftrace saves the IP
> (which is quite simple now), leading to some potentially
> meaningful perf overhead.
>
> Hence, I've decided to just mess with core kernel addresses
> so far, lemme know WDYT - should I somehow pursue fixing
> modules addr resolution as well? Or doesn't worth the changes?
> Any ideas on how to approach that? I noticed that currently,
> modules' symbols are sometimes resolved fine, sometimes they're
> bogus but point to the module at least (not some other random
> code), but eventually they are just nonsense addresses.
>
> Regarding the choice of using the MSB to store if an addr is core
> kernel or module, well this was also a choice taking into account
> simplicity and performance, lemme know please if it's no good and
> any suggestions on how to better do it, I can easily re-implement!
> Thanks again,
>
> Guilherme
>
>
> fs/pstore/ftrace.c | 33 +++++++++++++++++++++++++++++++--
> fs/pstore/inode.c | 6 ++++--
> fs/pstore/internal.h | 2 ++
> 3 files changed, 37 insertions(+), 4 deletions(-)
>
> diff --git a/fs/pstore/ftrace.c b/fs/pstore/ftrace.c
> index 13db123beac1..58f8204b23af 100644
> --- a/fs/pstore/ftrace.c
> +++ b/fs/pstore/ftrace.c
> @@ -18,10 +18,35 @@
> #include <linux/cache.h>
> #include <linux/slab.h>
> #include <asm/barrier.h>
> +#include <asm/setup.h>
> #include "internal.h"
>
> /* This doesn't need to be atomic: speed is chosen over correctness here. */
> static u64 pstore_ftrace_stamp;
> +unsigned long kaslr_off;
This should at least be "static", but why have it sitting in the data
segment at all, only to be scraped out by attackers with a arbitrary read
primitives? Can we just call kaslr_offset() directly as needed instead
(it's already an inline)?
-Kees
> +
> +static inline unsigned long adjust_ip(unsigned long ip)
> +{
> +#ifndef PSTORE_CPU_IN_IP
> + if (core_kernel_text(ip))
> + return ip - kaslr_off;
> +
> + __clear_bit(BITS_PER_LONG - 1, &ip);
> +#endif
> + return ip;
> +}
> +
> +inline unsigned long decode_ip(unsigned long ip)
> +{
> +#ifndef PSTORE_CPU_IN_IP
> + if (test_bit(BITS_PER_LONG - 1, &ip))
> + return ip + kaslr_off;
> +
> + __set_bit(BITS_PER_LONG - 1, &ip);
> +
> +#endif
> + return ip;
> +}
>
> static void notrace pstore_ftrace_call(unsigned long ip,
> unsigned long parent_ip,
> @@ -47,8 +72,8 @@ static void notrace pstore_ftrace_call(unsigned long ip,
>
> local_irq_save(flags);
>
> - rec.ip = ip;
> - rec.parent_ip = parent_ip;
> + rec.ip = adjust_ip(ip);
> + rec.parent_ip = adjust_ip(parent_ip);
> pstore_ftrace_write_timestamp(&rec, pstore_ftrace_stamp++);
> pstore_ftrace_encode_cpu(&rec, raw_smp_processor_id());
> psinfo->write(&record);
> @@ -132,6 +157,10 @@ void pstore_register_ftrace(void)
> if (!psinfo->write)
> return;
>
> +#ifdef CONFIG_RANDOMIZE_BASE
> + kaslr_off = kaslr_offset();
> +#endif
> +
> pstore_ftrace_dir = debugfs_create_dir("pstore", NULL);
>
> pstore_set_ftrace_enabled(record_ftrace);
> diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c
> index 83fa0bb3435a..62e678f3527d 100644
> --- a/fs/pstore/inode.c
> +++ b/fs/pstore/inode.c
> @@ -105,17 +105,19 @@ static int pstore_ftrace_seq_show(struct seq_file *s, void *v)
> struct pstore_private *ps = s->private;
> struct pstore_ftrace_seq_data *data = v;
> struct pstore_ftrace_record *rec;
> + unsigned long ip, parent_ip;
>
> if (!data)
> return 0;
>
> rec = (struct pstore_ftrace_record *)(ps->record->buf + data->off);
>
> + ip = decode_ip(rec->ip);
> + parent_ip = decode_ip(rec->parent_ip);
> seq_printf(s, "CPU:%d ts:%llu %08lx %08lx %ps <- %pS\n",
> pstore_ftrace_decode_cpu(rec),
> pstore_ftrace_read_timestamp(rec),
> - rec->ip, rec->parent_ip, (void *)rec->ip,
> - (void *)rec->parent_ip);
> + ip, parent_ip, (void *)ip, (void *)parent_ip);
>
> return 0;
> }
> diff --git a/fs/pstore/internal.h b/fs/pstore/internal.h
> index a0fc51196910..079284120db9 100644
> --- a/fs/pstore/internal.h
> +++ b/fs/pstore/internal.h
> @@ -9,6 +9,7 @@
> extern unsigned int kmsg_bytes;
>
> #ifdef CONFIG_PSTORE_FTRACE
> +extern unsigned long decode_ip(unsigned long ip);
> extern void pstore_register_ftrace(void);
> extern void pstore_unregister_ftrace(void);
> ssize_t pstore_ftrace_combine_log(char **dest_log, size_t *dest_log_size,
> @@ -16,6 +17,7 @@ ssize_t pstore_ftrace_combine_log(char **dest_log, size_t *dest_log_size,
> #else
> static inline void pstore_register_ftrace(void) {}
> static inline void pstore_unregister_ftrace(void) {}
> +static inline unsigned long decode_ip(unsigned long ip) { return ip; }
> static inline ssize_t
> pstore_ftrace_combine_log(char **dest_log, size_t *dest_log_size,
> const char *src_log, size_t src_log_size)
> --
> 2.50.1
>
>
--
Kees Cook
On 31/03/2026 18:48, Kees Cook wrote: > [...] >> /* This doesn't need to be atomic: speed is chosen over correctness here. */ >> static u64 pstore_ftrace_stamp; >> +unsigned long kaslr_off; > > This should at least be "static", but why have it sitting in the data > segment at all, only to be scraped out by attackers with a arbitrary read > primitives? Can we just call kaslr_offset() directly as needed instead > (it's already an inline)? > > -Kees > Hi Kees, thanks for the review! Totally feasible - I thought in some form of optimization, since it's tracing, but if you think doesn't worth, I can easily just put the call to kaslr_offset() there, as I did in my internal V0 heh I can try some perf measurements, let's see how it goes ... Cheers, Guilherme
On 13/03/2026 17:00, Guilherme G. Piccoli wrote: > The pstore ftrace frontend works by purely collecting the > instruction address, saving it on the persistent area through > the backend and when the log is read, on next boot for example, > the address is then resolved by using the regular printk symbol > lookup (%pS for example). > > Problem: if we are running a relocatable kernel with KASLR enabled, > this is a recipe for failure in the symbol resolution on next boots, > since the addresses are offset'ed by the KASLR address. So, naturally > the way to go is factor the KASLR address out of instruction address > collection, and adding the fresh offset when resolving the symbol > on future boots. > > Problem #2: modules also have varying addresses that float based > on module base address and potentially the module ordering in > memory, meaning factoring KASLR offset for them is useless. > So, let's hereby only take KASLR offset into account for core > kernel addresses, leaving module ones as is. > > And we have yet a 3rd complexity: not necessarily the check range > for core kernel addresses holds true on future boots, since the > module base address will vary. With that, the choice was to mark > the addresses as being core vs module based on its MSB. And with > that... > > ...we have the 4th challenge here: for some "simple" architectures, > the CPU number is saved bit-encoded on the instruction pointer, to > allow bigger timestamps - this is set through the PSTORE_CPU_IN_IP > define for such architectures. Hence, the approach here is to skip > such architectures (at least in a first moment). > > TL;DR: let's factor KASLR offsets on pstore/ftrace for core kernel > addresses, leaving module addresses out and also leaving the > architectures that define PSTORE_CPU_IN_IP. > > Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com> > --- > > > Hi folks, first of all thanks in advance for reviews and comments! > > I was testing a pstore/ftrace patch the other day and noticed > the lack of the KASLR support. But to my surprise, it was not > as easy to fix up as I expected heh > > Main reason is the obvious thing with modules: the way to > go, I think, is to somehow save the module name (or some other > id?) and the instruction offset inside such module, to then > resolve that in next boot, when printing. But that would require > more intrusive changes in the way pstore/ftrace saves the IP > (which is quite simple now), leading to some potentially > meaningful perf overhead. > > Hence, I've decided to just mess with core kernel addresses > so far, lemme know WDYT - should I somehow pursue fixing > modules addr resolution as well? Or doesn't worth the changes? > Any ideas on how to approach that? I noticed that currently, > modules' symbols are sometimes resolved fine, sometimes they're > bogus but point to the module at least (not some other random > code), but eventually they are just nonsense addresses. > > Regarding the choice of using the MSB to store if an addr is core > kernel or module, well this was also a choice taking into account > simplicity and performance, lemme know please if it's no good and > any suggestions on how to better do it, I can easily re-implement! > Thanks again, > > Guilherme > Hi Kees, gentle ping about this one - lemme know if you have suggestions or questions, and thanks in advance =) Guilherme
On Fri, 13 Mar 2026 17:00:22 -0300 "Guilherme G. Piccoli" <gpiccoli@igalia.com> wrote: > Hi folks, first of all thanks in advance for reviews and comments! > > I was testing a pstore/ftrace patch the other day and noticed > the lack of the KASLR support. But to my surprise, it was not > as easy to fix up as I expected heh > > Main reason is the obvious thing with modules: the way to > go, I think, is to somehow save the module name (or some other > id?) and the instruction offset inside such module, to then > resolve that in next boot, when printing. But that would require > more intrusive changes in the way pstore/ftrace saves the IP > (which is quite simple now), leading to some potentially > meaningful perf overhead. > > Hence, I've decided to just mess with core kernel addresses > so far, lemme know WDYT - should I somehow pursue fixing > modules addr resolution as well? Or doesn't worth the changes? > Any ideas on how to approach that? I noticed that currently, > modules' symbols are sometimes resolved fine, sometimes they're > bogus but point to the module at least (not some other random > code), but eventually they are just nonsense addresses. > > Regarding the choice of using the MSB to store if an addr is core > kernel or module, well this was also a choice taking into account > simplicity and performance, lemme know please if it's no good and > any suggestions on how to better do it, I can easily re-implement! > Thanks again, You can look at what ftrace does with the persistent ring buffer. It adds the offset data to a "scratch pad" that is saved in the persistent memory. https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/kernel/trace/trace.c#n5352 If you know your memory isn't reset over reboots, you can create a "persistent ring buffer" via the kernel command line: reserve_mem=20M:2M:trace trace_instance=boot_map@trace Read more about it here: https://docs.kernel.org/trace/debugging.html Then on reboot, the persistent ring buffer lives here: /sys/kernel/tracing/instances/boot_map/ You can enable tracing just like any other instance: # echo 1 > /sys/kernel/tracing/instances/boot_map/tracing_on # echo function_graph > /sys/kernel/tracing/instances/boot_map/current_tracer # cat /sys/kernel/tracing/instances/boot_map/trace Then reboot, if the memory wasn't corrupted or reset, the instance will have everything from the last boot, right to where it rebooted the machine. There's a file that shows the indexes of the kernel from the previous boot: # cat /sys/kernel/tracing/instances/boot_map/last_boot_info ffffffffa6000000 [kernel] ffffffffc0400000 drm ffffffffc0444000 wmi ffffffffc0446000 soundcore ffffffffc0447000 tpm_infineon ffffffffc0449000 lpc_ich ffffffffc044a000 serio_raw ffffffffc044b000 i2c_smbus ffffffffc044c000 i2c_i801 ffffffffc044f000 snd_seq_device ffffffffc0450000 e1000e ffffffffc047a000 intel_cstate ffffffffc047b000 video ffffffffc047f000 drm_kms_helper ffffffffc0493000 snd ffffffffc04a0000 intel_uncore ffffffffc04ad000 mei ffffffffc04bf000 snd_timer ffffffffc04c4000 snd_pcm ffffffffc04d7000 snd_seq ffffffffc04e2000 drm_display_helper ffffffffc04f6000 iTCO_vendor_support ffffffffc04f7000 mei_wdt ffffffffc04f8000 iTCO_wdt ffffffffc04f9000 mei_me ffffffffc04fe000 wmi_bmof ffffffffc04ff000 ttm ffffffffc050a000 rapl ffffffffc050b000 drm_buddy ffffffffc050e000 snd_hda_core ffffffffc0518000 ghash_clmulni_intel ffffffffc0519000 i2c_algo_bit ffffffffc051b000 snd_hwdep ffffffffc051d000 irqbypass ffffffffc051e000 drm_client_lib ffffffffc051f000 snd_hda_codec ffffffffc0531000 snd_intel_dspcfg ffffffffc0532000 kvm ffffffffc05ab000 snd_hda_intel ffffffffc05af000 kvm_intel ffffffffc05d5000 intel_powerclamp ffffffffc05d6000 coretemp ffffffffc05d7000 snd_hda_codec_generic ffffffffc05e4000 snd_hda_scodec_component ffffffffc05e5000 snd_hda_codec_realtek_lib ffffffffc05ea000 snd_hda_codec_alc269 ffffffffc05f2000 snd_hda_codec_hdmi ffffffffc05f7000 x86_pkg_temp_thermal ffffffffc05f8000 intel_rapl_common ffffffffc05fc000 intel_rapl_msr ffffffffc05fd000 snd_hda_codec_intelhdmi ffffffffc05ff000 llc ffffffffc0a00000 i915 ffffffffc0c10000 rfkill ffffffffc0c13000 vmw_vmci ffffffffc0c1d000 vsock ffffffffc0c23000 stp ffffffffc0c24000 bridge That has where the _text address was for the main kernel, and also where every module was loaded. If you enable tracing, that file will just show: # echo 1 > /sys/kernel/tracing/boot_map/events/sched/sched_switch/enable # cat /sys/kernel/tracing/instances/boot_map/last_boot_info # Current As it will not show the current mappings. Only the mappings of a previous boot. -- Steve
On 13/03/2026 17:28, Steven Rostedt wrote: > [...] > > You can look at what ftrace does with the persistent ring buffer. It adds > the offset data to a "scratch pad" that is saved in the persistent memory. > > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/kernel/trace/trace.c#n5352 > > If you know your memory isn't reset over reboots, you can create a > "persistent ring buffer" via the kernel command line: > > reserve_mem=20M:2M:trace trace_instance=boot_map@trace > > Read more about it here: https://docs.kernel.org/trace/debugging.html > > Then on reboot, the persistent ring buffer lives here: > > /sys/kernel/tracing/instances/boot_map/ > > You can enable tracing just like any other instance: > > # echo 1 > /sys/kernel/tracing/instances/boot_map/tracing_on > # echo function_graph > /sys/kernel/tracing/instances/boot_map/current_tracer > # cat /sys/kernel/tracing/instances/boot_map/trace > > Then reboot, if the memory wasn't corrupted or reset, the instance will > have everything from the last boot, right to where it rebooted the machine. > > There's a file that shows the indexes of the kernel from the previous boot: > > # cat /sys/kernel/tracing/instances/boot_map/last_boot_info > ffffffffa6000000 [kernel] > ffffffffc0400000 drm [...] Hi Steve, this is very interesting! Thanks for pointing that infrastructure. And I'm glad it confirms my impression that the full fix of that isn't trivial heh So, are you suggesting to use the ftrace infrastructure in the pstore/ftrace? Well, seeing how mature the ftrace infra is with regards the persistent ring buffer, I'd say pstore/ftrace+ramoops gets useless now heh The usage then for pstore/ftrace would be more with other backends, really low memory cases like ERST or UEFI, for example, in embedded maybe. And in this case, saving the full modules name table + offsets could incur some precious memory consumption and/or performance impact. Or maybe I'm talking nonsense and this would be quite OK ... guess worth taking a look. I'll wait a bit more to see what pstore maintainers think about that, if is worth to have the very simple KASLR fix or a bit more engineered solution that factors modules as well. Thanks again, Guilherme
On Fri, 13 Mar 2026 17:57:35 -0300 "Guilherme G. Piccoli" <gpiccoli@igalia.com> wrote: > Hi Steve, this is very interesting! Thanks for pointing that > infrastructure. And I'm glad it confirms my impression that the full fix > of that isn't trivial heh > > So, are you suggesting to use the ftrace infrastructure in the > pstore/ftrace? Well, seeing how mature the ftrace infra is with regards > the persistent ring buffer, I'd say pstore/ftrace+ramoops gets useless > now heh The persistent ring buffer only works when the memory is reliably consistent between soft reboots. It doesn't work for any other pstore interface. Thus, if you can rely on normal ram being available across reboots, then use ftrace. If not, then you have to use pstore. Hence, it doesn't make pstore useless. I would not use the ftrace scratchpad for pstore, as if that works, then just use ftrace ;-) > > The usage then for pstore/ftrace would be more with other backends, > really low memory cases like ERST or UEFI, for example, in embedded > maybe. And in this case, saving the full modules name table + offsets > could incur some precious memory consumption and/or performance impact. > Or maybe I'm talking nonsense and this would be quite OK ... guess worth > taking a look. Exactly (I wrote the above before reading this paragraph!) -- Steve > > I'll wait a bit more to see what pstore maintainers think about that, if > is worth to have the very simple KASLR fix or a bit more engineered > solution that factors modules as well.
On 15/03/2026 11:09, Steven Rostedt wrote: > On Fri, 13 Mar 2026 17:57:35 -0300 > [...] >> So, are you suggesting to use the ftrace infrastructure in the >> pstore/ftrace? Well, seeing how mature the ftrace infra is with regards >> the persistent ring buffer, I'd say pstore/ftrace+ramoops gets useless >> now heh > > The persistent ring buffer only works when the memory is reliably > consistent between soft reboots. It doesn't work for any other pstore > interface. Thus, if you can rely on normal ram being available across > reboots, then use ftrace. If not, then you have to use pstore. Hence, > it doesn't make pstore useless. > > I would not use the ftrace scratchpad for pstore, as if that works, > then just use ftrace ;-) > >> >> The usage then for pstore/ftrace would be more with other backends, >> really low memory cases like ERST or UEFI, for example, in embedded >> maybe. And in this case, saving the full modules name table + offsets >> could incur some precious memory consumption and/or performance impact. >> Or maybe I'm talking nonsense and this would be quite OK ... guess worth >> taking a look. > > Exactly (I wrote the above before reading this paragraph!) Perfect, thanks for confirming. I think the idea of factoring KASLR on pstore/ftrace (in a simple way) is then valid ... let's see others' opinions =) Cheers, Guilherme
Bah... Forgot to mention one important thing: this was tested fully on x86 and build-tested in all other arches I could find that implement KASLR, like arm64, riscv, ppc, mips, loongarch, S390. Cheers, Guilherme
© 2016 - 2026 Red Hat, Inc.