From patchwork Wed Feb 5 22:50:32 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 13961988 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3DD29215F42; Wed, 5 Feb 2025 22:50:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738795823; cv=none; b=uY4KvOQ9LvsVaW0dFkudZudl/hRNWQAdXk7rfe7FNpVY9JT3F8sXtEc5SYaIBMQzRRRQ8urJLCBDn0JSMsKlKecSm0ZTHZMdYJVJHI41pTls7oltx7ghYrB607GJbiLWYDJoWBgtIbzpfpwG9iTizrqknP4zAAAmw2iWIRqUU5U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738795823; c=relaxed/simple; bh=3F/kaXBBCLh1rGkixTsYYK7kejIscXvJuFT418+4694=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=ILpehjgS2DaTPGgg6ODiMZ2h5GryJEHcF9/DJOJAwjziWFXE1+sCEFl8biScRZshUmIh3iXZoCbPiY1HKWQ/ElNNCjTUckAy7uDzOp/6LX/NRWI1Y3nQQzFC66AVOARFGAoVusSYY07pDiP9Z3iLS32f8LY2B4ceNoWT84GPS7Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id BB9CEC4CEE2; Wed, 5 Feb 2025 22:50:22 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.98) (envelope-from ) id 1tfoEZ-00000007gTd-1067; Wed, 05 Feb 2025 17:51:03 -0500 Message-ID: <20250205225103.090463674@goodmis.org> User-Agent: quilt/0.68 Date: Wed, 05 Feb 2025 17:50:32 -0500 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton Subject: [PATCH 1/8] ring-buffer: Use kaslr address instead of text delta References: <20250205225031.799739376@goodmis.org> Precedence: bulk X-Mailing-List: linux-trace-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Steven Rostedt Instead of saving off the text and data pointers and using them to compare with the current boot's text and data pointers, just save off the KASLR offset. Then that can be used to figure out how to read the previous boots buffer. The last_boot_info will now show this offset, but only if it is for a previous boot: # cat instances/boot_mapped/last_boot_info Offset: 39000000 # echo function > instances/boot_mapped/current_tracer # cat instances/boot_mapped/last_boot_info Offset: current If the KASLR offset saved is for the current boot, the last_boot_info will show the value of "current". Signed-off-by: Steven Rostedt (Google) Acked-by: Masami Hiramatsu (Google) --- include/linux/ring_buffer.h | 3 +-- kernel/trace/ring_buffer.c | 31 ++++++++++++------------------- kernel/trace/trace.c | 30 +++++++++++++++++++++--------- kernel/trace/trace.h | 9 +++++---- 4 files changed, 39 insertions(+), 34 deletions(-) diff --git a/include/linux/ring_buffer.h b/include/linux/ring_buffer.h index 17fbb7855295..8de035f4f0d9 100644 --- a/include/linux/ring_buffer.h +++ b/include/linux/ring_buffer.h @@ -94,8 +94,7 @@ struct trace_buffer *__ring_buffer_alloc_range(unsigned long size, unsigned flag unsigned long range_size, struct lock_class_key *key); -bool ring_buffer_last_boot_delta(struct trace_buffer *buffer, long *text, - long *data); +bool ring_buffer_last_boot_delta(struct trace_buffer *buffer, unsigned long *kaslr_addr); /* * Because the ring buffer is generic, if other users of the ring buffer get diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index b8e0ae15ca5b..7146b780176f 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -31,6 +31,7 @@ #include #include +#include #include "trace.h" @@ -49,8 +50,7 @@ static void update_pages_handler(struct work_struct *work); struct ring_buffer_meta { int magic; int struct_size; - unsigned long text_addr; - unsigned long data_addr; + unsigned long kaslr_addr; unsigned long first_buffer; unsigned long head_buffer; unsigned long commit_buffer; @@ -550,8 +550,7 @@ struct trace_buffer { unsigned long range_addr_start; unsigned long range_addr_end; - long last_text_delta; - long last_data_delta; + unsigned long kaslr_addr; unsigned int subbuf_size; unsigned int subbuf_order; @@ -1874,16 +1873,13 @@ static void rb_meta_validate_events(struct ring_buffer_per_cpu *cpu_buffer) } } -/* Used to calculate data delta */ -static char rb_data_ptr[] = ""; - -#define THIS_TEXT_PTR ((unsigned long)rb_meta_init_text_addr) -#define THIS_DATA_PTR ((unsigned long)rb_data_ptr) - static void rb_meta_init_text_addr(struct ring_buffer_meta *meta) { - meta->text_addr = THIS_TEXT_PTR; - meta->data_addr = THIS_DATA_PTR; +#ifdef CONFIG_RANDOMIZE_BASE + meta->kaslr_addr = kaslr_offset(); +#else + meta->kaslr_addr = 0; +#endif } static void rb_range_meta_init(struct trace_buffer *buffer, int nr_pages) @@ -1906,8 +1902,7 @@ static void rb_range_meta_init(struct trace_buffer *buffer, int nr_pages) meta->first_buffer += delta; meta->head_buffer += delta; meta->commit_buffer += delta; - buffer->last_text_delta = THIS_TEXT_PTR - meta->text_addr; - buffer->last_data_delta = THIS_DATA_PTR - meta->data_addr; + buffer->kaslr_addr = meta->kaslr_addr; continue; } @@ -2459,17 +2454,15 @@ struct trace_buffer *__ring_buffer_alloc_range(unsigned long size, unsigned flag * * Returns: The true if the delta is non zero */ -bool ring_buffer_last_boot_delta(struct trace_buffer *buffer, long *text, - long *data) +bool ring_buffer_last_boot_delta(struct trace_buffer *buffer, unsigned long *kaslr_addr) { if (!buffer) return false; - if (!buffer->last_text_delta) + if (!buffer->kaslr_addr) return false; - *text = buffer->last_text_delta; - *data = buffer->last_data_delta; + *kaslr_addr = buffer->kaslr_addr; return true; } diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 1496a5ac33ae..a9e8eaf1d47e 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -50,7 +50,7 @@ #include #include -#include /* COMMAND_LINE_SIZE */ +#include /* COMMAND_LINE_SIZE and kaslr_offset() */ #include "trace.h" #include "trace_output.h" @@ -4193,7 +4193,7 @@ static enum print_line_t print_trace_fmt(struct trace_iterator *iter) * safe to use if the array has delta offsets * Force printing via the fields. */ - if ((tr->text_delta || tr->data_delta) && + if ((tr->text_delta) && event->type > __TRACE_LAST_TYPE) return print_event_fields(iter, event); @@ -5996,7 +5996,7 @@ ssize_t tracing_resize_ring_buffer(struct trace_array *tr, static void update_last_data(struct trace_array *tr) { - if (!tr->text_delta && !tr->data_delta) + if (!(tr->flags & TRACE_ARRAY_FL_LAST_BOOT)) return; /* @@ -6009,7 +6009,8 @@ static void update_last_data(struct trace_array *tr) /* Using current data now */ tr->text_delta = 0; - tr->data_delta = 0; + + tr->flags &= ~TRACE_ARRAY_FL_LAST_BOOT; } /** @@ -6827,8 +6828,17 @@ tracing_last_boot_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t seq_buf_init(&seq, buf, 64); - seq_buf_printf(&seq, "text delta:\t%ld\n", tr->text_delta); - seq_buf_printf(&seq, "data delta:\t%ld\n", tr->data_delta); + /* + * Do not leak KASLR address. This only shows the KASLR address of + * the last boot. When the ring buffer is started, the LAST_BOOT + * flag gets cleared, and this should only report "current". + * Otherwise it shows the KASLR address from the previous boot which + * should not be the same as the current boot. + */ + if (!(tr->flags & TRACE_ARRAY_FL_LAST_BOOT)) + seq_buf_puts(&seq, "Offset: current\n"); + else + seq_buf_printf(&seq, "Offset: %lx\n", tr->kaslr_addr); return simple_read_from_buffer(ubuf, cnt, ppos, buf, seq_buf_used(&seq)); } @@ -9212,8 +9222,10 @@ allocate_trace_buffer(struct trace_array *tr, struct array_buffer *buf, int size tr->range_addr_start, tr->range_addr_size); - ring_buffer_last_boot_delta(buf->buffer, - &tr->text_delta, &tr->data_delta); +#ifdef CONFIG_RANDOMIZE_BASE + if (ring_buffer_last_boot_delta(buf->buffer, &tr->kaslr_addr)) + tr->text_delta = kaslr_offset() - tr->kaslr_addr; +#endif /* * This is basically the same as a mapped buffer, * with the same restrictions. @@ -10461,7 +10473,7 @@ __init static void enable_instances(void) * to it. */ if (start) { - tr->flags |= TRACE_ARRAY_FL_BOOT; + tr->flags |= TRACE_ARRAY_FL_BOOT | TRACE_ARRAY_FL_LAST_BOOT; tr->ref++; } diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 9c21ba45b7af..abe8169c3e87 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -348,8 +348,8 @@ struct trace_array { unsigned int mapped; unsigned long range_addr_start; unsigned long range_addr_size; + unsigned long kaslr_addr; long text_delta; - long data_delta; struct trace_pid_list __rcu *filtered_pids; struct trace_pid_list __rcu *filtered_no_pids; @@ -433,9 +433,10 @@ struct trace_array { }; enum { - TRACE_ARRAY_FL_GLOBAL = BIT(0), - TRACE_ARRAY_FL_BOOT = BIT(1), - TRACE_ARRAY_FL_MOD_INIT = BIT(2), + TRACE_ARRAY_FL_GLOBAL = BIT(0), + TRACE_ARRAY_FL_BOOT = BIT(1), + TRACE_ARRAY_FL_LAST_BOOT = BIT(2), + TRACE_ARRAY_FL_MOD_INIT = BIT(3), }; #ifdef CONFIG_MODULES From patchwork Wed Feb 5 22:50:33 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 13961992 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8D22921A44F; Wed, 5 Feb 2025 22:50:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738795823; cv=none; b=dDhyGgmL++sEyGb1e+dknDYTCEPRXqIRKciEkoKttryK26eEwZqbiN+Sm8+iDBegCw/IsYOEWv6sTIjoxsiXYopf0dBpnOKv8iyNwFW6N20mSb61C/irS9WiMCuOxUeUJzIOd+d4xwSCQ1ppggIuO+BfDlmbSsuC1n2z8YU/dDY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738795823; c=relaxed/simple; bh=KWx+nKfsPYhG7VvvVT6qCZf6sy4hNxqWWF6sr4CGiUA=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=VB3CaS5hg7H+eVCetynOX7ypK+U659+hCnjZpfzf3HULyeOydXfpFCwwAwyrG3fLVB/qOPw0UMny5SS23KC/kaOgo+VOK4Cz32BgIDYhtt7VS4pLzbHqaSN7aMqkY8v/IHhvnnmkxRtwA73d3PK1OPtBYdLpTH7aBm3RPP252dU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1EEFEC4CEE5; Wed, 5 Feb 2025 22:50:23 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.98) (envelope-from ) id 1tfoEZ-00000007gU9-1hJu; Wed, 05 Feb 2025 17:51:03 -0500 Message-ID: <20250205225103.259337686@goodmis.org> User-Agent: quilt/0.68 Date: Wed, 05 Feb 2025 17:50:33 -0500 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton Subject: [PATCH 2/8] ring-buffer: Add buffer meta data for persistent ring buffer References: <20250205225031.799739376@goodmis.org> Precedence: bulk X-Mailing-List: linux-trace-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Steven Rostedt Instead of just having a meta data at the first page of each sub buffer that has duplicate data, add a new meta page to the entire block of memory that holds the duplicate data and remove it from the sub buffer meta data. This will open up the extra memory in this first page to be used by the tracer for its own persistent data. Signed-off-by: Steven Rostedt (Google) --- kernel/trace/ring_buffer.c | 165 ++++++++++++++++++++++++++----------- 1 file changed, 115 insertions(+), 50 deletions(-) diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 7146b780176f..0446d053dbd6 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -49,7 +49,12 @@ static void update_pages_handler(struct work_struct *work); struct ring_buffer_meta { int magic; - int struct_size; + int struct_sizes; + unsigned long total_size; + unsigned long buffers_offset; +}; + +struct ring_buffer_cpu_meta { unsigned long kaslr_addr; unsigned long first_buffer; unsigned long head_buffer; @@ -517,7 +522,7 @@ struct ring_buffer_per_cpu { struct mutex mapping_lock; unsigned long *subbuf_ids; /* ID to subbuf VA */ struct trace_buffer_meta *meta_page; - struct ring_buffer_meta *ring_meta; + struct ring_buffer_cpu_meta *ring_meta; /* ring buffer pages to update, > 0 to add, < 0 to remove */ long nr_pages_to_update; @@ -550,6 +555,8 @@ struct trace_buffer { unsigned long range_addr_start; unsigned long range_addr_end; + struct ring_buffer_meta *meta; + unsigned long kaslr_addr; unsigned int subbuf_size; @@ -1270,7 +1277,7 @@ static void rb_head_page_activate(struct ring_buffer_per_cpu *cpu_buffer) rb_set_list_to_head(head->list.prev); if (cpu_buffer->ring_meta) { - struct ring_buffer_meta *meta = cpu_buffer->ring_meta; + struct ring_buffer_cpu_meta *meta = cpu_buffer->ring_meta; meta->head_buffer = (unsigned long)head->page; } } @@ -1568,7 +1575,7 @@ static void rb_check_pages(struct ring_buffer_per_cpu *cpu_buffer) static unsigned long rb_range_align_subbuf(unsigned long addr, int subbuf_size, int nr_subbufs) { - addr += sizeof(struct ring_buffer_meta) + + addr += sizeof(struct ring_buffer_cpu_meta) + sizeof(int) * nr_subbufs; return ALIGN(addr, subbuf_size); } @@ -1579,19 +1586,22 @@ rb_range_align_subbuf(unsigned long addr, int subbuf_size, int nr_subbufs) static void *rb_range_meta(struct trace_buffer *buffer, int nr_pages, int cpu) { int subbuf_size = buffer->subbuf_size + BUF_PAGE_HDR_SIZE; - unsigned long ptr = buffer->range_addr_start; - struct ring_buffer_meta *meta; + struct ring_buffer_cpu_meta *meta; + struct ring_buffer_meta *bmeta; + unsigned long ptr; int nr_subbufs; - if (!ptr) + bmeta = buffer->meta; + if (!bmeta) return NULL; + ptr = (unsigned long)bmeta + bmeta->buffers_offset; + meta = (struct ring_buffer_cpu_meta *)ptr; + /* When nr_pages passed in is zero, the first meta has already been initialized */ if (!nr_pages) { - meta = (struct ring_buffer_meta *)ptr; nr_subbufs = meta->nr_subbufs; } else { - meta = NULL; /* Include the reader page */ nr_subbufs = nr_pages + 1; } @@ -1623,7 +1633,7 @@ static void *rb_range_meta(struct trace_buffer *buffer, int nr_pages, int cpu) } /* Return the start of subbufs given the meta pointer */ -static void *rb_subbufs_from_meta(struct ring_buffer_meta *meta) +static void *rb_subbufs_from_meta(struct ring_buffer_cpu_meta *meta) { int subbuf_size = meta->subbuf_size; unsigned long ptr; @@ -1639,7 +1649,7 @@ static void *rb_subbufs_from_meta(struct ring_buffer_meta *meta) */ static void *rb_range_buffer(struct ring_buffer_per_cpu *cpu_buffer, int idx) { - struct ring_buffer_meta *meta; + struct ring_buffer_cpu_meta *meta; unsigned long ptr; int subbuf_size; @@ -1664,14 +1674,73 @@ static void *rb_range_buffer(struct ring_buffer_per_cpu *cpu_buffer, int idx) return (void *)ptr; } +/* + * See if the existing memory contains a valid meta section. + * if so, use that, otherwise initialize it. + */ +static bool rb_meta_init(struct trace_buffer *buffer) +{ + unsigned long ptr = buffer->range_addr_start; + struct ring_buffer_meta *bmeta; + unsigned long total_size; + int struct_sizes; + + bmeta = (struct ring_buffer_meta *)ptr; + buffer->meta = bmeta; + + total_size = buffer->range_addr_end - buffer->range_addr_start; + + struct_sizes = sizeof(struct ring_buffer_cpu_meta); + struct_sizes |= sizeof(*bmeta) << 16; + + /* The first buffer will start one page after the meta page */ + ptr += sizeof(*bmeta); + ptr = ALIGN(ptr, PAGE_SIZE); + + if (bmeta->magic != RING_BUFFER_META_MAGIC) { + pr_info("Ring buffer boot meta mismatch of magic\n"); + goto init; + } + + if (bmeta->struct_sizes != struct_sizes) { + pr_info("Ring buffer boot meta mismatch of struct size\n"); + goto init; + } + + if (bmeta->total_size != total_size) { + pr_info("Ring buffer boot meta mismatch of total size\n"); + goto init; + } + + if (bmeta->buffers_offset > bmeta->total_size) { + pr_info("Ring buffer boot meta mismatch of offset outside of total size\n"); + goto init; + } + + if (bmeta->buffers_offset != (void *)ptr - (void *)bmeta) { + pr_info("Ring buffer boot meta mismatch of first buffer offset\n"); + goto init; + } + + return true; + + init: + bmeta->magic = RING_BUFFER_META_MAGIC; + bmeta->struct_sizes = struct_sizes; + bmeta->total_size = total_size; + bmeta->buffers_offset = (void *)ptr - (void *)bmeta; + + return false; +} + /* * See if the existing memory contains valid ring buffer data. * As the previous kernel must be the same as this kernel, all * the calculations (size of buffers and number of buffers) * must be the same. */ -static bool rb_meta_valid(struct ring_buffer_meta *meta, int cpu, - struct trace_buffer *buffer, int nr_pages) +static bool rb_cpu_meta_valid(struct ring_buffer_cpu_meta *meta, int cpu, + struct trace_buffer *buffer, int nr_pages) { int subbuf_size = PAGE_SIZE; struct buffer_data_page *subbuf; @@ -1679,20 +1748,6 @@ static bool rb_meta_valid(struct ring_buffer_meta *meta, int cpu, unsigned long buffers_end; int i; - /* Check the meta magic and meta struct size */ - if (meta->magic != RING_BUFFER_META_MAGIC || - meta->struct_size != sizeof(*meta)) { - pr_info("Ring buffer boot meta[%d] mismatch of magic or struct size\n", cpu); - return false; - } - - /* The subbuffer's size and number of subbuffers must match */ - if (meta->subbuf_size != subbuf_size || - meta->nr_subbufs != nr_pages + 1) { - pr_info("Ring buffer boot meta [%d] mismatch of subbuf_size/nr_pages\n", cpu); - return false; - } - buffers_start = meta->first_buffer; buffers_end = meta->first_buffer + (subbuf_size * meta->nr_subbufs); @@ -1730,7 +1785,7 @@ static bool rb_meta_valid(struct ring_buffer_meta *meta, int cpu, return true; } -static int rb_meta_subbuf_idx(struct ring_buffer_meta *meta, void *subbuf); +static int rb_meta_subbuf_idx(struct ring_buffer_cpu_meta *meta, void *subbuf); static int rb_read_data_buffer(struct buffer_data_page *dpage, int tail, int cpu, unsigned long long *timestamp, u64 *delta_ptr) @@ -1797,7 +1852,7 @@ static int rb_validate_buffer(struct buffer_data_page *dpage, int cpu) /* If the meta data has been validated, now validate the events */ static void rb_meta_validate_events(struct ring_buffer_per_cpu *cpu_buffer) { - struct ring_buffer_meta *meta = cpu_buffer->ring_meta; + struct ring_buffer_cpu_meta *meta = cpu_buffer->ring_meta; struct buffer_page *head_page; unsigned long entry_bytes = 0; unsigned long entries = 0; @@ -1873,7 +1928,7 @@ static void rb_meta_validate_events(struct ring_buffer_per_cpu *cpu_buffer) } } -static void rb_meta_init_text_addr(struct ring_buffer_meta *meta) +static void rb_meta_init_text_addr(struct ring_buffer_cpu_meta *meta) { #ifdef CONFIG_RANDOMIZE_BASE meta->kaslr_addr = kaslr_offset(); @@ -1884,18 +1939,25 @@ static void rb_meta_init_text_addr(struct ring_buffer_meta *meta) static void rb_range_meta_init(struct trace_buffer *buffer, int nr_pages) { - struct ring_buffer_meta *meta; + struct ring_buffer_cpu_meta *meta; + struct ring_buffer_meta *bmeta; unsigned long delta; void *subbuf; + bool valid = false; int cpu; int i; + if (rb_meta_init(buffer)) + valid = true; + + bmeta = buffer->meta; + for (cpu = 0; cpu < nr_cpu_ids; cpu++) { void *next_meta; meta = rb_range_meta(buffer, nr_pages, cpu); - if (rb_meta_valid(meta, cpu, buffer, nr_pages)) { + if (valid && rb_cpu_meta_valid(meta, cpu, buffer, nr_pages)) { /* Make the mappings match the current address */ subbuf = rb_subbufs_from_meta(meta); delta = (unsigned long)subbuf - meta->first_buffer; @@ -1913,9 +1975,6 @@ static void rb_range_meta_init(struct trace_buffer *buffer, int nr_pages) memset(meta, 0, next_meta - (void *)meta); - meta->magic = RING_BUFFER_META_MAGIC; - meta->struct_size = sizeof(*meta); - meta->nr_subbufs = nr_pages + 1; meta->subbuf_size = PAGE_SIZE; @@ -1943,7 +2002,7 @@ static void rb_range_meta_init(struct trace_buffer *buffer, int nr_pages) static void *rbm_start(struct seq_file *m, loff_t *pos) { struct ring_buffer_per_cpu *cpu_buffer = m->private; - struct ring_buffer_meta *meta = cpu_buffer->ring_meta; + struct ring_buffer_cpu_meta *meta = cpu_buffer->ring_meta; unsigned long val; if (!meta) @@ -1968,7 +2027,7 @@ static void *rbm_next(struct seq_file *m, void *v, loff_t *pos) static int rbm_show(struct seq_file *m, void *v) { struct ring_buffer_per_cpu *cpu_buffer = m->private; - struct ring_buffer_meta *meta = cpu_buffer->ring_meta; + struct ring_buffer_cpu_meta *meta = cpu_buffer->ring_meta; unsigned long val = (unsigned long)v; if (val == 1) { @@ -2017,7 +2076,7 @@ int ring_buffer_meta_seq_init(struct file *file, struct trace_buffer *buffer, in static void rb_meta_buffer_update(struct ring_buffer_per_cpu *cpu_buffer, struct buffer_page *bpage) { - struct ring_buffer_meta *meta = cpu_buffer->ring_meta; + struct ring_buffer_cpu_meta *meta = cpu_buffer->ring_meta; if (meta->head_buffer == (unsigned long)bpage->page) cpu_buffer->head_page = bpage; @@ -2032,7 +2091,7 @@ static int __rb_allocate_pages(struct ring_buffer_per_cpu *cpu_buffer, long nr_pages, struct list_head *pages) { struct trace_buffer *buffer = cpu_buffer->buffer; - struct ring_buffer_meta *meta = NULL; + struct ring_buffer_cpu_meta *meta = NULL; struct buffer_page *bpage, *tmp; bool user_thread = current->mm != NULL; gfp_t mflags; @@ -2156,7 +2215,7 @@ static struct ring_buffer_per_cpu * rb_allocate_cpu_buffer(struct trace_buffer *buffer, long nr_pages, int cpu) { struct ring_buffer_per_cpu *cpu_buffer; - struct ring_buffer_meta *meta; + struct ring_buffer_cpu_meta *meta; struct buffer_page *bpage; struct page *page; int ret; @@ -2327,10 +2386,16 @@ static struct trace_buffer *alloc_buffer(unsigned long size, unsigned flags, /* If start/end are specified, then that overrides size */ if (start && end) { + unsigned long buffers_start; unsigned long ptr; int n; size = end - start; + + /* Subtract the buffer meta data */ + size -= PAGE_SIZE; + buffers_start = start + PAGE_SIZE; + size = size / nr_cpu_ids; /* @@ -2340,7 +2405,7 @@ static struct trace_buffer *alloc_buffer(unsigned long size, unsigned flags, * needed, plus account for the integer array index that * will be appended to the meta data. */ - nr_pages = (size - sizeof(struct ring_buffer_meta)) / + nr_pages = (size - sizeof(struct ring_buffer_cpu_meta)) / (subbuf_size + sizeof(int)); /* Need at least two pages plus the reader page */ if (nr_pages < 3) @@ -2348,8 +2413,8 @@ static struct trace_buffer *alloc_buffer(unsigned long size, unsigned flags, again: /* Make sure that the size fits aligned */ - for (n = 0, ptr = start; n < nr_cpu_ids; n++) { - ptr += sizeof(struct ring_buffer_meta) + + for (n = 0, ptr = buffers_start; n < nr_cpu_ids; n++) { + ptr += sizeof(struct ring_buffer_cpu_meta) + sizeof(int) * nr_pages; ptr = ALIGN(ptr, subbuf_size); ptr += subbuf_size * nr_pages; @@ -3075,7 +3140,7 @@ static void rb_inc_iter(struct ring_buffer_iter *iter) } /* Return the index into the sub-buffers for a given sub-buffer */ -static int rb_meta_subbuf_idx(struct ring_buffer_meta *meta, void *subbuf) +static int rb_meta_subbuf_idx(struct ring_buffer_cpu_meta *meta, void *subbuf) { void *subbuf_array; @@ -3087,7 +3152,7 @@ static int rb_meta_subbuf_idx(struct ring_buffer_meta *meta, void *subbuf) static void rb_update_meta_head(struct ring_buffer_per_cpu *cpu_buffer, struct buffer_page *next_page) { - struct ring_buffer_meta *meta = cpu_buffer->ring_meta; + struct ring_buffer_cpu_meta *meta = cpu_buffer->ring_meta; unsigned long old_head = (unsigned long)next_page->page; unsigned long new_head; @@ -3104,7 +3169,7 @@ static void rb_update_meta_head(struct ring_buffer_per_cpu *cpu_buffer, static void rb_update_meta_reader(struct ring_buffer_per_cpu *cpu_buffer, struct buffer_page *reader) { - struct ring_buffer_meta *meta = cpu_buffer->ring_meta; + struct ring_buffer_cpu_meta *meta = cpu_buffer->ring_meta; void *old_reader = cpu_buffer->reader_page->page; void *new_reader = reader->page; int id; @@ -3733,7 +3798,7 @@ rb_set_commit_to_write(struct ring_buffer_per_cpu *cpu_buffer) rb_page_write(cpu_buffer->commit_page)); rb_inc_page(&cpu_buffer->commit_page); if (cpu_buffer->ring_meta) { - struct ring_buffer_meta *meta = cpu_buffer->ring_meta; + struct ring_buffer_cpu_meta *meta = cpu_buffer->ring_meta; meta->commit_buffer = (unsigned long)cpu_buffer->commit_page->page; } /* add barrier to keep gcc from optimizing too much */ @@ -5986,7 +6051,7 @@ rb_reset_cpu(struct ring_buffer_per_cpu *cpu_buffer) if (cpu_buffer->mapped) { rb_update_meta_page(cpu_buffer); if (cpu_buffer->ring_meta) { - struct ring_buffer_meta *meta = cpu_buffer->ring_meta; + struct ring_buffer_cpu_meta *meta = cpu_buffer->ring_meta; meta->commit_buffer = meta->head_buffer; } } @@ -6020,7 +6085,7 @@ static void reset_disabled_cpu_buffer(struct ring_buffer_per_cpu *cpu_buffer) void ring_buffer_reset_cpu(struct trace_buffer *buffer, int cpu) { struct ring_buffer_per_cpu *cpu_buffer = buffer->buffers[cpu]; - struct ring_buffer_meta *meta; + struct ring_buffer_cpu_meta *meta; if (!cpumask_test_cpu(cpu, buffer->cpumask)) return; @@ -6058,7 +6123,7 @@ EXPORT_SYMBOL_GPL(ring_buffer_reset_cpu); void ring_buffer_reset_online_cpus(struct trace_buffer *buffer) { struct ring_buffer_per_cpu *cpu_buffer; - struct ring_buffer_meta *meta; + struct ring_buffer_cpu_meta *meta; int cpu; /* prevent another thread from changing buffer sizes */ From patchwork Wed Feb 5 22:50:34 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 13961990 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 78A99219E8D; Wed, 5 Feb 2025 22:50:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738795823; cv=none; b=hBAhs2hRizTW78uJKRql3bOlveO1TQp9TcAMhYNkmViPZwVcFwRwYatK5sqJo/JemuLUkIPtNsXjVzRpBl4xChEwX20STei1DDIYsdkVtD5FpMVia3k9f1ZxV3CewPr35c0so5OUJpRKCZx+osGaBx8TIAHAxlouIbBP6iURRhw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738795823; c=relaxed/simple; bh=CuFfCrM/KWTO6l4n6Pk5lAeKKczZbJi1XocjxEN0ARQ=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=cLucNNS6AHQct3mtoJhFbUm998ahcrpAQfkTYhTacjYroLfMo7bhK0slxTBKESP86jcn0aLhvN0bE6z6Bq/S4Wgyyt1i7+nF9PUGGYtOdMHZKUiF3jUl46N47e4+LxR+5jYfqVNgtro+cZKb/3DeYkIS6K69af2AxH839nbWR7s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1FE51C4CEE6; Wed, 5 Feb 2025 22:50:23 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.98) (envelope-from ) id 1tfoEZ-00000007gUd-2Prk; Wed, 05 Feb 2025 17:51:03 -0500 Message-ID: <20250205225103.425325060@goodmis.org> User-Agent: quilt/0.68 Date: Wed, 05 Feb 2025 17:50:34 -0500 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton Subject: [PATCH 3/8] ring-buffer: Add ring_buffer_meta_scratch() References: <20250205225031.799739376@goodmis.org> Precedence: bulk X-Mailing-List: linux-trace-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Steven Rostedt Now that there's one page at the start of the persistent memory used by the ring buffer, make the part of that page that is not used by the ring buffer available for the tracer to use. This will allow the tracer to store its own persistent data. Signed-off-by: Steven Rostedt (Google) Reviewed-by: Masami Hiramatsu (Google) --- include/linux/ring_buffer.h | 1 + kernel/trace/ring_buffer.c | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/include/linux/ring_buffer.h b/include/linux/ring_buffer.h index 8de035f4f0d9..b95f940fd07a 100644 --- a/include/linux/ring_buffer.h +++ b/include/linux/ring_buffer.h @@ -95,6 +95,7 @@ struct trace_buffer *__ring_buffer_alloc_range(unsigned long size, unsigned flag struct lock_class_key *key); bool ring_buffer_last_boot_delta(struct trace_buffer *buffer, unsigned long *kaslr_addr); +void *ring_buffer_meta_scratch(struct trace_buffer *buffer, unsigned int *size); /* * Because the ring buffer is generic, if other users of the ring buffer get diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 0446d053dbd6..5a81ff785665 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -1730,6 +1730,9 @@ static bool rb_meta_init(struct trace_buffer *buffer) bmeta->total_size = total_size; bmeta->buffers_offset = (void *)ptr - (void *)bmeta; + /* Zero out the scatch pad */ + memset((void *)bmeta + sizeof(*bmeta), 0, PAGE_SIZE - sizeof(*bmeta)); + return false; } @@ -2532,6 +2535,16 @@ bool ring_buffer_last_boot_delta(struct trace_buffer *buffer, unsigned long *kas return true; } +void *ring_buffer_meta_scratch(struct trace_buffer *buffer, unsigned int *size) +{ + if (!buffer || !buffer->meta) + return NULL; + + *size = PAGE_SIZE - sizeof(*buffer->meta); + + return (void *)buffer->meta + sizeof(*buffer->meta); +} + /** * ring_buffer_free - free a ring buffer. * @buffer: the buffer to free. From patchwork Wed Feb 5 22:50:35 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 13961991 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8D28621A450; Wed, 5 Feb 2025 22:50:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738795823; cv=none; b=koBt5ay5hYEWFKgvfH05lmHRdJAFE41S334+78VaxjrCA6aWsRI1YO3orz+PVaaGHEd8wFPHw0oMv2p/U9z3rhTZsX6HYSYuozHj8LJ/5sFk36v4MOBMcom14dhsqWEf01PZDm6HEvk0RAMWkC7jU+gHe57DUtGWv3IQDUjGVLU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738795823; c=relaxed/simple; bh=KzEsDQvkXIUiOxDlG2zAYbasAvlRkiTu3GNzggoIWGQ=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=iKOkTsdERRRx1hfH4OaA/RUeLjBO15f5ix2ioUHuJC2dl7osItkUAZaRs6FOgbzERckunluCs/vIenvYRLqJ7G7EaczKzYdRQKeahWBaBLxQC1d9iGD0Oa5ajFhxXhBRTRSdcWyQ6WTpQEqx0akgSe4f1/mw6W/b9GPNr/zcnjA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 360B4C4CEE7; Wed, 5 Feb 2025 22:50:23 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.98) (envelope-from ) id 1tfoEZ-00000007gV7-36cq; Wed, 05 Feb 2025 17:51:03 -0500 Message-ID: <20250205225103.596907199@goodmis.org> User-Agent: quilt/0.68 Date: Wed, 05 Feb 2025 17:50:35 -0500 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton Subject: [PATCH 4/8] tracing: Have persistent trace instances save KASLR offset References: <20250205225031.799739376@goodmis.org> Precedence: bulk X-Mailing-List: linux-trace-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Steven Rostedt There's no reason to save the KASLR offset for the ring buffer itself. That is used by the tracer. Now that the tracer has a way to save data in the persistent memory of the ring buffer, have the tracing infrastructure take care of the saving of the KASLR offset. Signed-off-by: Steven Rostedt (Google) --- include/linux/ring_buffer.h | 1 - kernel/trace/ring_buffer.c | 47 ------------------------------------- kernel/trace/trace.c | 38 ++++++++++++++++++++++++++---- kernel/trace/trace.h | 6 +++-- 4 files changed, 38 insertions(+), 54 deletions(-) diff --git a/include/linux/ring_buffer.h b/include/linux/ring_buffer.h index b95f940fd07a..d6d9c94e8d8a 100644 --- a/include/linux/ring_buffer.h +++ b/include/linux/ring_buffer.h @@ -94,7 +94,6 @@ struct trace_buffer *__ring_buffer_alloc_range(unsigned long size, unsigned flag unsigned long range_size, struct lock_class_key *key); -bool ring_buffer_last_boot_delta(struct trace_buffer *buffer, unsigned long *kaslr_addr); void *ring_buffer_meta_scratch(struct trace_buffer *buffer, unsigned int *size); /* diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 5a81ff785665..a42406287281 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -55,7 +55,6 @@ struct ring_buffer_meta { }; struct ring_buffer_cpu_meta { - unsigned long kaslr_addr; unsigned long first_buffer; unsigned long head_buffer; unsigned long commit_buffer; @@ -557,8 +556,6 @@ struct trace_buffer { struct ring_buffer_meta *meta; - unsigned long kaslr_addr; - unsigned int subbuf_size; unsigned int subbuf_order; unsigned int max_data_size; @@ -1931,15 +1928,6 @@ static void rb_meta_validate_events(struct ring_buffer_per_cpu *cpu_buffer) } } -static void rb_meta_init_text_addr(struct ring_buffer_cpu_meta *meta) -{ -#ifdef CONFIG_RANDOMIZE_BASE - meta->kaslr_addr = kaslr_offset(); -#else - meta->kaslr_addr = 0; -#endif -} - static void rb_range_meta_init(struct trace_buffer *buffer, int nr_pages) { struct ring_buffer_cpu_meta *meta; @@ -1967,7 +1955,6 @@ static void rb_range_meta_init(struct trace_buffer *buffer, int nr_pages) meta->first_buffer += delta; meta->head_buffer += delta; meta->commit_buffer += delta; - buffer->kaslr_addr = meta->kaslr_addr; continue; } @@ -1984,7 +1971,6 @@ static void rb_range_meta_init(struct trace_buffer *buffer, int nr_pages) subbuf = rb_subbufs_from_meta(meta); meta->first_buffer = (unsigned long)subbuf; - rb_meta_init_text_addr(meta); /* * The buffers[] array holds the order of the sub-buffers @@ -2514,27 +2500,6 @@ struct trace_buffer *__ring_buffer_alloc_range(unsigned long size, unsigned flag return alloc_buffer(size, flags, order, start, start + range_size, key); } -/** - * ring_buffer_last_boot_delta - return the delta offset from last boot - * @buffer: The buffer to return the delta from - * @text: Return text delta - * @data: Return data delta - * - * Returns: The true if the delta is non zero - */ -bool ring_buffer_last_boot_delta(struct trace_buffer *buffer, unsigned long *kaslr_addr) -{ - if (!buffer) - return false; - - if (!buffer->kaslr_addr) - return false; - - *kaslr_addr = buffer->kaslr_addr; - - return true; -} - void *ring_buffer_meta_scratch(struct trace_buffer *buffer, unsigned int *size) { if (!buffer || !buffer->meta) @@ -6098,7 +6063,6 @@ static void reset_disabled_cpu_buffer(struct ring_buffer_per_cpu *cpu_buffer) void ring_buffer_reset_cpu(struct trace_buffer *buffer, int cpu) { struct ring_buffer_per_cpu *cpu_buffer = buffer->buffers[cpu]; - struct ring_buffer_cpu_meta *meta; if (!cpumask_test_cpu(cpu, buffer->cpumask)) return; @@ -6117,11 +6081,6 @@ void ring_buffer_reset_cpu(struct trace_buffer *buffer, int cpu) atomic_dec(&cpu_buffer->record_disabled); atomic_dec(&cpu_buffer->resize_disabled); - /* Make sure persistent meta now uses this buffer's addresses */ - meta = rb_range_meta(buffer, 0, cpu_buffer->cpu); - if (meta) - rb_meta_init_text_addr(meta); - mutex_unlock(&buffer->mutex); } EXPORT_SYMBOL_GPL(ring_buffer_reset_cpu); @@ -6136,7 +6095,6 @@ EXPORT_SYMBOL_GPL(ring_buffer_reset_cpu); void ring_buffer_reset_online_cpus(struct trace_buffer *buffer) { struct ring_buffer_per_cpu *cpu_buffer; - struct ring_buffer_cpu_meta *meta; int cpu; /* prevent another thread from changing buffer sizes */ @@ -6164,11 +6122,6 @@ void ring_buffer_reset_online_cpus(struct trace_buffer *buffer) reset_disabled_cpu_buffer(cpu_buffer); - /* Make sure persistent meta now uses this buffer's addresses */ - meta = rb_range_meta(buffer, 0, cpu_buffer->cpu); - if (meta) - rb_meta_init_text_addr(meta); - atomic_dec(&cpu_buffer->record_disabled); atomic_sub(RESET_BIT, &cpu_buffer->resize_disabled); } diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index a9e8eaf1d47e..cb9f8e6878a0 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -5994,8 +5994,14 @@ ssize_t tracing_resize_ring_buffer(struct trace_array *tr, return ret; } +struct trace_scratch { + unsigned long kaslr_addr; +}; + static void update_last_data(struct trace_array *tr) { + struct trace_scratch *tscratch; + if (!(tr->flags & TRACE_ARRAY_FL_LAST_BOOT)) return; @@ -6010,6 +6016,17 @@ static void update_last_data(struct trace_array *tr) /* Using current data now */ tr->text_delta = 0; + if (!tr->scratch) + return; + + tscratch = tr->scratch; + + /* Set the persistent ring buffer meta data to this address */ +#ifdef CONFIG_RANDOMIZE_BASE + tscratch->kaslr_addr = kaslr_offset(); +#else + tscratch->kaslr_addr = 0; +#endif tr->flags &= ~TRACE_ARRAY_FL_LAST_BOOT; } @@ -6823,6 +6840,7 @@ static ssize_t tracing_last_boot_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) { struct trace_array *tr = filp->private_data; + struct trace_scratch *tscratch = tr->scratch; struct seq_buf seq; char buf[64]; @@ -6835,10 +6853,10 @@ tracing_last_boot_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t * Otherwise it shows the KASLR address from the previous boot which * should not be the same as the current boot. */ - if (!(tr->flags & TRACE_ARRAY_FL_LAST_BOOT)) + if (!tscratch || !(tr->flags & TRACE_ARRAY_FL_LAST_BOOT)) seq_buf_puts(&seq, "Offset: current\n"); else - seq_buf_printf(&seq, "Offset: %lx\n", tr->kaslr_addr); + seq_buf_printf(&seq, "Offset: %lx\n", tscratch->kaslr_addr); return simple_read_from_buffer(ubuf, cnt, ppos, buf, seq_buf_used(&seq)); } @@ -9212,6 +9230,8 @@ static int allocate_trace_buffer(struct trace_array *tr, struct array_buffer *buf, int size) { enum ring_buffer_flags rb_flags; + unsigned int scratch_size; + void *scratch; rb_flags = tr->trace_flags & TRACE_ITER_OVERWRITE ? RB_FL_OVERWRITE : 0; @@ -9222,10 +9242,20 @@ allocate_trace_buffer(struct trace_array *tr, struct array_buffer *buf, int size tr->range_addr_start, tr->range_addr_size); + scratch = ring_buffer_meta_scratch(buf->buffer, &scratch_size); + if (scratch) { + tr->scratch = scratch; + tr->scratch_size = scratch_size; + #ifdef CONFIG_RANDOMIZE_BASE - if (ring_buffer_last_boot_delta(buf->buffer, &tr->kaslr_addr)) - tr->text_delta = kaslr_offset() - tr->kaslr_addr; + { + struct trace_scratch *tscratch = tr->scratch; + + if (tscratch->kaslr_addr) + tr->text_delta = kaslr_offset() - tscratch->kaslr_addr; + } #endif + } /* * This is basically the same as a mapped buffer, * with the same restrictions. diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index abe8169c3e87..3a020fb82a34 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -348,8 +348,11 @@ struct trace_array { unsigned int mapped; unsigned long range_addr_start; unsigned long range_addr_size; - unsigned long kaslr_addr; long text_delta; + void *scratch; /* pointer in persistent memory */ + int scratch_size; + + int buffer_disabled; struct trace_pid_list __rcu *filtered_pids; struct trace_pid_list __rcu *filtered_no_pids; @@ -367,7 +370,6 @@ struct trace_array { * CONFIG_TRACER_MAX_TRACE. */ arch_spinlock_t max_lock; - int buffer_disabled; #ifdef CONFIG_FTRACE_SYSCALLS int sys_refcount_enter; int sys_refcount_exit; From patchwork Wed Feb 5 22:50:36 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 13961993 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8DA4621A453; Wed, 5 Feb 2025 22:50:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738795823; cv=none; b=gRyoKLfDd1jntTIcy+6GjUl8mvjJ3qO8MiDRcOzXIR5w2b5CsuNXiHoMaZ0m+roMjNLP1fugvS4BONGFboEUP349O+1TMMxJRxIrO9QiGw4hxUdJKIm9otKbMfbH73OJadpl8qEw9PdRrjfKnshXDlbL8clYKFFOyEpQoT+/9J4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738795823; c=relaxed/simple; bh=NGlDmyhKE+eXxsSImJtT/RQQNDcwlx1ewF9KadcrQKs=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=Yk/qTK2dXr/n+19AuEjEjSPpcef5NQBbRDqd1Iyq40CdbCHI3ue/GjHCo0lNjpgigwh2x50sftSx1cjr0AzG+3t+IVbOTQHnne7FDTR2LTvE0acCIQMcgOTrVMvl6Wu8IcchBLzK7QAVAulvTATUmemkCTIFaHMVA09C+x/n1+k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6924FC4CED1; Wed, 5 Feb 2025 22:50:23 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.98) (envelope-from ) id 1tfoEZ-00000007gVb-3pBn; Wed, 05 Feb 2025 17:51:03 -0500 Message-ID: <20250205225103.760856859@goodmis.org> User-Agent: quilt/0.68 Date: Wed, 05 Feb 2025 17:50:36 -0500 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton , Luis Chamberlain , Petr Pavlu , Sami Tolvanen , Daniel Gomez , linux-modules@vger.kernel.org Subject: [PATCH 5/8] module: Add module_for_each_mod() function References: <20250205225031.799739376@goodmis.org> Precedence: bulk X-Mailing-List: linux-trace-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Steven Rostedt The tracing system needs a way to save all the currently loaded modules and their addresses into persistent memory so that it can evaluate the addresses on a reboot from a crash. When the persistent memory trace starts, it will load the module addresses and names into the persistent memory. To do so, it will call the module_for_each_mod() function and pass it a function and data structure to get called on each loaded module. Then it can record the memory. This only implements that function. Cc: Luis Chamberlain Cc: Petr Pavlu Cc: Sami Tolvanen Cc: Daniel Gomez Cc: linux-modules@vger.kernel.org Signed-off-by: Steven Rostedt (Google) --- include/linux/module.h | 6 ++++++ kernel/module/main.c | 14 ++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/include/linux/module.h b/include/linux/module.h index 23792d5d7b74..9e1f42f03511 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -779,6 +779,8 @@ static inline void *module_writable_address(struct module *mod, void *loc) return __module_writable_address(mod, loc); } +void module_for_each_mod(int(*func)(struct module *mod, void *data), void *data); + #else /* !CONFIG_MODULES... */ static inline struct module *__module_address(unsigned long addr) @@ -891,6 +893,10 @@ static inline void *module_writable_address(struct module *mod, void *loc) { return loc; } + +static inline void module_for_each_mod(int(*func)(struct module *mod, void *data), void *data) +{ +} #endif /* CONFIG_MODULES */ #ifdef CONFIG_SYSFS diff --git a/kernel/module/main.c b/kernel/module/main.c index 1fb9ad289a6f..ea1fe313fb89 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -3809,6 +3809,20 @@ bool is_module_text_address(unsigned long addr) return ret; } +void module_for_each_mod(int(*func)(struct module *mod, void *data), void *data) +{ + struct module *mod; + + preempt_disable(); + list_for_each_entry_rcu(mod, &modules, list) { + if (mod->state == MODULE_STATE_UNFORMED) + continue; + if (func(mod, data)) + break; + } + preempt_enable(); +} + /** * __module_text_address() - get the module whose code contains an address. * @addr: the address. From patchwork Wed Feb 5 22:50:37 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 13961994 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EA3EA21C9F8; Wed, 5 Feb 2025 22:50:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738795824; cv=none; b=NJIzgK+x82qnk4CvW+hkUPuHt6wchNPnlzRF69DHXX1pXLakIQ1Eg4z05AKvq5yGz/7lZumL83pKrnw+wy4l2DelvAw5QKOEqdNuJQVU9wJLpI668vRz4BLY/M9jvp0gCSxvGgfpkOmDIkWx3yZqb88p9Eu+bRvV4QGZSLrYLPY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738795824; c=relaxed/simple; bh=acT27wujFzHBmghTMfek6s956/UyXG1nRM3Qxh/UYIk=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=P2ah6fIKmWBw4dO9HYZSSxTkwgz7hUJmv5oa29oTWwBTzwf1sUoHKEnTq5FiTK6VcLqqB1XXVxsDgclMWmnoj3f5yAwueFLUKp2aPIBuHL58oZ62rx+tMxinAKyK3shrMXZV1up17oWhK+5CC9S4rNsGiy1/U5xnPc+XiM/NtuA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 954C5C4CEE6; Wed, 5 Feb 2025 22:50:23 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.98) (envelope-from ) id 1tfoEa-00000007gW5-0Jht; Wed, 05 Feb 2025 17:51:04 -0500 Message-ID: <20250205225103.930895467@goodmis.org> User-Agent: quilt/0.68 Date: Wed, 05 Feb 2025 17:50:37 -0500 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton Subject: [PATCH 6/8] tracing: Have persistent trace instances save module addresses References: <20250205225031.799739376@goodmis.org> Precedence: bulk X-Mailing-List: linux-trace-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Steven Rostedt For trace instances that are mapped to persistent memory, have them use the scratch area to save the currently loaded modules. This will allow where the modules have been loaded on the next boot so that their addresses can be deciphered by using where they were loaded previously. Signed-off-by: Steven Rostedt (Google) --- kernel/trace/trace.c | 99 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 87 insertions(+), 12 deletions(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index cb9f8e6878a0..a8e5f7ac2193 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -5994,14 +5994,60 @@ ssize_t tracing_resize_ring_buffer(struct trace_array *tr, return ret; } +struct trace_mod_entry { + unsigned long mod_addr; + char mod_name[MODULE_NAME_LEN]; +}; + struct trace_scratch { unsigned long kaslr_addr; + unsigned long nr_entries; + struct trace_mod_entry entries[]; }; +static int save_mod(struct module *mod, void *data) +{ + struct trace_array *tr = data; + struct trace_scratch *tscratch; + struct trace_mod_entry *entry; + unsigned int size; + + tscratch = tr->scratch; + if (!tscratch) + return -1; + size = tr->scratch_size; + + if (struct_size(tscratch, entries, tscratch->nr_entries + 1) > size) + return -1; + + entry = &tscratch->entries[tscratch->nr_entries]; + + tscratch->nr_entries++; + + entry->mod_addr = (unsigned long)mod->mem[MOD_TEXT].base; + strscpy(entry->mod_name, mod->name); + + return 0; +} + static void update_last_data(struct trace_array *tr) { struct trace_scratch *tscratch; + if (!(tr->flags & TRACE_ARRAY_FL_BOOT)) + return; + + /* Reset the module list and reload them */ + if (tr->scratch) { + struct trace_scratch *tscratch = tr->scratch; + + memset(tscratch->entries, 0, + flex_array_size(tscratch, entries, tscratch->nr_entries)); + tscratch->nr_entries = 0; + + module_for_each_mod(save_mod, tr); + } + if (!(tr->flags & TRACE_ARRAY_FL_LAST_BOOT)) return; @@ -9226,6 +9272,46 @@ static struct dentry *trace_instance_dir; static void init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer); +static void setup_trace_scratch(struct trace_array *tr, void *scratch, unsigned int size) +{ + struct trace_scratch *tscratch = scratch; + struct trace_mod_entry *entry; + + if (!scratch) + return; + + tr->scratch = scratch; + tr->scratch_size = size; + +#ifdef CONFIG_RANDOMIZE_BASE + if (tscratch->kaslr_addr) + tr->text_delta = kaslr_offset() - tscratch->kaslr_addr; +#endif + + if (struct_size(tscratch, entries, tscratch->nr_entries) > size) + goto reset; + + /* Check if each module name is a valid string */ + for (int i = 0; i < tscratch->nr_entries; i++) { + int n; + + entry = &tscratch->entries[i]; + + for (n = 0; n < MODULE_NAME_LEN; n++) { + if (entry->mod_name[n] == '\0') + break; + if (!isprint(entry->mod_name[n])) + goto reset; + } + if (n == MODULE_NAME_LEN) + goto reset; + } + return; + reset: + /* Invalid trace modules */ + memset(scratch, 0, size); +} + static int allocate_trace_buffer(struct trace_array *tr, struct array_buffer *buf, int size) { @@ -9243,19 +9329,8 @@ allocate_trace_buffer(struct trace_array *tr, struct array_buffer *buf, int size tr->range_addr_size); scratch = ring_buffer_meta_scratch(buf->buffer, &scratch_size); - if (scratch) { - tr->scratch = scratch; - tr->scratch_size = scratch_size; + setup_trace_scratch(tr, scratch, scratch_size); -#ifdef CONFIG_RANDOMIZE_BASE - { - struct trace_scratch *tscratch = tr->scratch; - - if (tscratch->kaslr_addr) - tr->text_delta = kaslr_offset() - tscratch->kaslr_addr; - } -#endif - } /* * This is basically the same as a mapped buffer, * with the same restrictions. From patchwork Wed Feb 5 22:50:38 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 13961995 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0F0EB21CA15; Wed, 5 Feb 2025 22:50:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738795824; cv=none; b=mSfKjoOAPFnGWuthZZeLHM23UaajzwOZbEozqiRjffmUllxFA2aQtA/urDztbdUZ9WAE9wPM29apUqRm69ULKtLZt+vDOYP4WzHT5MaHZxIzAWjAe+hjVFXMTMaqKLTb0O3qQSt+8jcLNzkTGC3gLbnbAobVydpwM90pRSpX+mg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738795824; c=relaxed/simple; bh=1sdF2NBoWm5Mamd9+JN7fxCR634ZF4plAOnnC3jjZ2s=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=cB348aAOXaIACqW/14jcg6Wy76/+Gu0bXisZqirIHXIBLGR9n/Uw+2DYjnFLt+1CVoE3EVf/Xk1KC5raxLzmT8Z1faq97HFF14ipETHVvGIlBfbRu3UWK4DvZxE2pECUOO7pLRIRR+GzmKl7ncsZOxXGv7RORsGmTgjMsGigYyU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id E753DC4CEE4; Wed, 5 Feb 2025 22:50:23 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.98) (envelope-from ) id 1tfoEa-00000007gWZ-11TE; Wed, 05 Feb 2025 17:51:04 -0500 Message-ID: <20250205225104.096389081@goodmis.org> User-Agent: quilt/0.68 Date: Wed, 05 Feb 2025 17:50:38 -0500 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton Subject: [PATCH 7/8] tracing: Show module names and addresses of last boot References: <20250205225031.799739376@goodmis.org> Precedence: bulk X-Mailing-List: linux-trace-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Steven Rostedt Add the last boot module's names and addresses to the last_boot_info file. This only shows the module information from a previous boot. If the buffer is started and is recording the current boot, this file still will only show "current". # cat instances/boot_mapped/last_boot_info Offset: 10c00000 ffffffffc00ca000 usb_serial_simple ffffffffc00ae000 usbserial ffffffffc008b000 bfq # echo function > instances/boot_mapped/current_tracer # cat instances/boot_mapped/last_boot_info Offset: current Signed-off-by: Steven Rostedt (Google) --- kernel/trace/trace.c | 103 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 90 insertions(+), 13 deletions(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index a8e5f7ac2193..7b4027804cd4 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -6005,6 +6005,8 @@ struct trace_scratch { struct trace_mod_entry entries[]; }; +static DEFINE_MUTEX(scratch_mutex); + static int save_mod(struct module *mod, void *data) { struct trace_array *tr = data; @@ -6012,6 +6014,8 @@ static int save_mod(struct module *mod, void *data) struct trace_mod_entry *entry; unsigned int size; + guard(mutex)(&scratch_mutex); + tscratch = tr->scratch; if (!tscratch) return -1; @@ -6882,15 +6886,47 @@ tracing_total_entries_read(struct file *filp, char __user *ubuf, return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); } -static ssize_t -tracing_last_boot_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) +#define LAST_BOOT_HEADER ((void *)1) + +static void *l_next(struct seq_file *m, void *v, loff_t *pos) { - struct trace_array *tr = filp->private_data; + struct trace_array *tr = m->private; struct trace_scratch *tscratch = tr->scratch; - struct seq_buf seq; - char buf[64]; + unsigned int index = *pos; + + (*pos)++; + + if (*pos == 1) + return LAST_BOOT_HEADER; + + /* Only show offsets of the last boot data */ + if (!tscratch || !(tr->flags & TRACE_ARRAY_FL_LAST_BOOT)) + return NULL; + + /* *pos 0 is for the header, 1 is for the first module */ + index--; + + if (index >= tscratch->nr_entries) + return NULL; - seq_buf_init(&seq, buf, 64); + return &tscratch->entries[index]; +} + +static void *l_start(struct seq_file *m, loff_t *pos) +{ + mutex_lock(&scratch_mutex); + + return l_next(m, NULL, pos); +} + +static void l_stop(struct seq_file *m, void *p) +{ + mutex_unlock(&scratch_mutex); +} + +static void show_last_boot_header(struct seq_file *m, struct trace_array *tr) +{ + struct trace_scratch *tscratch = tr->scratch; /* * Do not leak KASLR address. This only shows the KASLR address of @@ -6900,11 +6936,52 @@ tracing_last_boot_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t * should not be the same as the current boot. */ if (!tscratch || !(tr->flags & TRACE_ARRAY_FL_LAST_BOOT)) - seq_buf_puts(&seq, "Offset: current\n"); + seq_puts(m, "Offset: current\n"); else - seq_buf_printf(&seq, "Offset: %lx\n", tscratch->kaslr_addr); + seq_printf(m, "Offset: %lx\n", tscratch->kaslr_addr); +} - return simple_read_from_buffer(ubuf, cnt, ppos, buf, seq_buf_used(&seq)); +static int l_show(struct seq_file *m, void *v) +{ + struct trace_array *tr = m->private; + struct trace_mod_entry *entry = v; + + if (v == LAST_BOOT_HEADER) { + show_last_boot_header(m, tr); + return 0; + } + + seq_printf(m, "%lx %s\n", entry->mod_addr, entry->mod_name); + return 0; +} + +static const struct seq_operations last_boot_seq_ops = { + .start = l_start, + .next = l_next, + .stop = l_stop, + .show = l_show, +}; + +static int tracing_last_boot_open(struct inode *inode, struct file *file) +{ + struct trace_array *tr = inode->i_private; + struct seq_file *m; + int ret; + + ret = tracing_check_open_get_tr(tr); + if (ret) + return ret; + + ret = seq_open(file, &last_boot_seq_ops); + if (ret) { + trace_array_put(tr); + return ret; + } + + m = file->private_data; + m->private = tr; + + return 0; } static int tracing_buffer_meta_open(struct inode *inode, struct file *filp) @@ -7533,10 +7610,10 @@ static const struct file_operations trace_time_stamp_mode_fops = { }; static const struct file_operations last_boot_fops = { - .open = tracing_open_generic_tr, - .read = tracing_last_boot_read, - .llseek = generic_file_llseek, - .release = tracing_release_generic_tr, + .open = tracing_last_boot_open, + .read = seq_read, + .llseek = seq_lseek, + .release = tracing_seq_release, }; #ifdef CONFIG_TRACER_SNAPSHOT From patchwork Wed Feb 5 22:50:39 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 13961996 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 765E521D59F; Wed, 5 Feb 2025 22:50:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738795824; cv=none; b=gdcFOBEwElrq4MR/vo91ZRuRfq2oi+rzDnfl5W2FOrvxWn+OFNvpP4n5cxgYwae3yZLS4UjEzrlWYIsAbVDRqqcqKYWjDou1VZ6MRm5F3+Cq0fwucjKlzXAsEN/OC/xyzAep3pvsazXALrytF1MwsNGvvc/cKUGj+6BUg95YBhw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738795824; c=relaxed/simple; bh=Lsu5iZQzFu+2B0eBrtELwZKqmytJ22BtyklPdTBJ0Z0=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=tmQGCItNxWMcyI1vyZm/JXzCsy6ow/NU6zKHCXcEnYUmdtyui7CwaE/7q8EMTwJ1SH5dvxfMMOwDgz2Kxs2el/HMd4JcJTHwM4mw9/gmvULormssPeoh3OYlQOjYtNbi9M8cULvNxQELbvAWctSSgTaLcFvWqK932ZFu4eD1lqI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id E7503C4CED1; Wed, 5 Feb 2025 22:50:23 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.98) (envelope-from ) id 1tfoEa-00000007gX5-1j5K; Wed, 05 Feb 2025 17:51:04 -0500 Message-ID: <20250205225104.264333506@goodmis.org> User-Agent: quilt/0.68 Date: Wed, 05 Feb 2025 17:50:39 -0500 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton Subject: [PATCH 8/8] tracing: Update modules to persistent instances when loaded References: <20250205225031.799739376@goodmis.org> Precedence: bulk X-Mailing-List: linux-trace-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Steven Rostedt When a module is loaded and a persistent buffer is actively tracing, add it to the list of modules in the persistent memory. Signed-off-by: Steven Rostedt (Google) --- kernel/trace/trace.c | 25 +++++++++++++++++++++++ kernel/trace/trace.h | 2 ++ kernel/trace/trace_events.c | 40 ++++++++++++++++++++++++++----------- 3 files changed, 55 insertions(+), 12 deletions(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 7b4027804cd4..443f2bc5b856 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -10088,6 +10088,30 @@ static void trace_module_remove_evals(struct module *mod) static inline void trace_module_remove_evals(struct module *mod) { } #endif /* CONFIG_TRACE_EVAL_MAP_FILE */ +static bool trace_array_active(struct trace_array *tr) +{ + if (tr->current_trace != &nop_trace) + return true; + + /* 0 is no events, 1 is all disabled */ + return trace_events_enabled(tr, NULL) > 1; +} + +static void trace_module_record(struct module *mod) +{ + struct trace_array *tr; + + list_for_each_entry(tr, &ftrace_trace_arrays, list) { + /* Update any persistent trace array that has already been started */ + if ((tr->flags & (TRACE_ARRAY_FL_BOOT | TRACE_ARRAY_FL_LAST_BOOT)) == + TRACE_ARRAY_FL_BOOT) { + /* Only update if the trace array is active */ + if (trace_array_active(tr)) + save_mod(mod, tr); + } + } +} + static int trace_module_notify(struct notifier_block *self, unsigned long val, void *data) { @@ -10096,6 +10120,7 @@ static int trace_module_notify(struct notifier_block *self, switch (val) { case MODULE_STATE_COMING: trace_module_add_evals(mod); + trace_module_record(mod); break; case MODULE_STATE_GOING: trace_module_remove_evals(mod); diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 3a020fb82a34..90493220c362 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -786,6 +786,8 @@ extern void trace_find_cmdline(int pid, char comm[]); extern int trace_find_tgid(int pid); extern void trace_event_follow_fork(struct trace_array *tr, bool enable); +extern int trace_events_enabled(struct trace_array *tr, const char *system); + #ifdef CONFIG_DYNAMIC_FTRACE extern unsigned long ftrace_update_tot_cnt; extern unsigned long ftrace_number_of_pages; diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 4cb275316e51..107767afe0ab 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -1811,28 +1811,28 @@ event_enable_write(struct file *filp, const char __user *ubuf, size_t cnt, return cnt; } -static ssize_t -system_enable_read(struct file *filp, char __user *ubuf, size_t cnt, - loff_t *ppos) +/* + * Returns: + * 0 : no events exist? + * 1 : all events are disabled + * 2 : all events are enabled + * 3 : some events are enabled and some are enabled + */ +int trace_events_enabled(struct trace_array *tr, const char *system) { - const char set_to_char[4] = { '?', '0', '1', 'X' }; - struct trace_subsystem_dir *dir = filp->private_data; - struct event_subsystem *system = dir->subsystem; struct trace_event_call *call; struct trace_event_file *file; - struct trace_array *tr = dir->tr; - char buf[2]; int set = 0; - int ret; - mutex_lock(&event_mutex); + guard(mutex)(&event_mutex); + list_for_each_entry(file, &tr->events, list) { call = file->event_call; if ((call->flags & TRACE_EVENT_FL_IGNORE_ENABLE) || !trace_event_name(call) || !call->class || !call->class->reg) continue; - if (system && strcmp(call->class->system, system->name) != 0) + if (system && strcmp(call->class->system, system) != 0) continue; /* @@ -1848,7 +1848,23 @@ system_enable_read(struct file *filp, char __user *ubuf, size_t cnt, if (set == 3) break; } - mutex_unlock(&event_mutex); + + return set; +} + +static ssize_t +system_enable_read(struct file *filp, char __user *ubuf, size_t cnt, + loff_t *ppos) +{ + const char set_to_char[4] = { '?', '0', '1', 'X' }; + struct trace_subsystem_dir *dir = filp->private_data; + struct event_subsystem *system = dir->subsystem; + struct trace_array *tr = dir->tr; + char buf[2]; + int set; + int ret; + + set = trace_events_enabled(tr, system ? system->name : NULL); buf[0] = set_to_char[set]; buf[1] = '\n';