| Age | Commit message (Collapse) | Author | Files | Lines |
|
In __set_print_fmt(), LEN_OR_ZERO is defined as (len ? len - pos : 0).
If len is non-zero but smaller than pos, len - pos evaluates to a negative
integer. When passed as a size argument to snprintf(), this negative value
is cast to a large unsigned size_t, bypassing buffer size limits.
Ensure len > pos before subtracting to avoid integer underflow.
Link: https://lore.kernel.org/all/178454234934.290363.15247317871499514139.stgit@devnote2/
Fixes: 5bf652aaf46c ("tracing/probes: Integrate duplicate set_print_fmt()")
Cc: stable@vger.kernel.org
Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
|
|
If trace_probe_log.argc is 0 in __trace_probe_log_err(), the loop
constructing the command string will not execute and p will remain equal to
command. Writing to *(p - 1) will cause an out-of-bounds access before
command. This should not happen, but better to be treated.
Reject if trace_probe_log.argc is 0.
Link: https://lore.kernel.org/all/178454233992.290363.18323091580600697731.stgit@devnote2/
Fixes: ab105a4fb894 ("tracing: Use tracing error_log with probe events")
Cc: stable@vger.kernel.org
Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
|
|
In trace_probe_match_command_args(), a stack buffer buf[MAX_ARGSTR_LEN + 1]
(256 bytes) is used to format "<name>=<comm>". However, since name can
be up to 32 bytes (MAX_ARG_NAME_LEN) and comm up to 255 bytes
(MAX_ARGSTR_LEN), the formatted string can exceed 256 bytes and get
truncated by snprintf(), causing spurious argument matching failures.
Instead of formatting into a temporary buffer on stack, compare the
argument name, the '=' delimiter, and the comm expression directly.
Link: https://lore.kernel.org/all/178454233010.290363.10428767141343428804.stgit@devnote2/
Fixes: eb5bf81330a7 ("tracing/kprobe: Add per-probe delete from event")
Cc: stable@vger.kernel.org
Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
|
|
Hybrid automata monitors's clock variables have two different
representations:
- The invariant representation, which is the timestamp when the invariant
expires
- The guard representation, which is the timestamp when the clock is last
reset
This dual representation makes the logic quite difficult to follow (well,
at least for me). It also complicates the monitors and the generation tool,
as it requires conversion back and forth between the representation.
Simplify by using the clock variables for a single purpose: storing the
time stamp since the clock is last reset.
This also allows simplifying rvgen, which will be done in a follow-up
commit.
Reviewed-by: Gabriele Monaco <gmonaco@redhat.com>
Signed-off-by: Nam Cao <namcao@linutronix.de>
Link: https://lore.kernel.org/r/c0f600dcbf3d8b487c944406851a39146f4d91fa.1781847583.git.namcao@linutronix.de
Signed-off-by: Gabriele Monaco <gmonaco@redhat.com>
|
|
Cross-merge BPF and other fixes after downstream PR.
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
|
|
To avoid potential stack overflows on limited kernel stacks, convert
parse_probe_arg() from a recursive function into a loop-based
implementation with a simple local state stack.
Since recursion is eliminated using a loop with a fixed-size
stack in the context, this restricts the dereference nesting
depth. The maximum nesting depth of dereferences is now restricted
to the same limit as typecasts (TRACEPROBE_MAX_NESTED_LEVEL, which
is 8) and reports the same TOO_MANY_NESTED error. Update ftrace
selftests to reflect this restriction and simplify the checks.
Note that this change slightly alters the behavior of nested
dereferencing in fetcharg. Previously, dereferencing without BTF
allowed for up to 14 levels of nesting, whereas dereferencing
with BTF was limited to 3 levels. With this change, the nesting
depth is now limited to 8 levels in both cases.
Link: https://lore.kernel.org/all/178399141396.27810.5390060618628718661.stgit@devnote2/
Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
|
|
To support BTF argument parsing (such as accessing fields within nested
structures via typecasting), the maximum argument string length needs
to be extended. Extend MAX_ARGSTR_LEN from 63 to 255.
Since MAX_ARGSTR_LEN was previously reused to format command heads in
trace_*probe_match_command_head() functions, introduce a dedicated
MAX_COMMON_HEAD_LEN (63) macro for matching command heads and switch
these functions to use the new macro.
Link: https://lore.kernel.org/all/178399140457.27810.11387684872148824707.stgit@devnote2/
Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
|
|
Sort the C-macro ERRORS list alphabetically in trace_probe.h to make
it easier to find and maintain error entries.
Link: https://lore.kernel.org/all/178399139516.27810.14930549550788208142.stgit@devnote2/
Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
|
|
Decompose parse_probe_arg() by extracting register, memory/symbol,
dereference, immediate, and default BTF/CPU parsing handlers into
dedicated static helper functions (parse_probe_arg_register,
parse_probe_arg_mem_symbol, parse_probe_arg_deref, parse_probe_arg_imm,
and parse_probe_arg_default). This modularizes the recursive argument
parser and improves readability.
Link: https://lore.kernel.org/all/178399138581.27810.9471730417467607229.stgit@devnote2/
Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
|
|
Decompose parse_probe_vars() by extracting retval, stack, current task
struct, and function argument parsing logic into dedicated static
helper functions (parse_probe_var_retval, parse_probe_var_stack,
parse_probe_var_current, and parse_probe_var_arg). This simplifies
parse_probe_vars() and improves its readability.
Link: https://lore.kernel.org/all/178399137612.27810.14869178899276413372.stgit@devnote2/
Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
|
|
fp pointer and unsigned long have the same size on all relevant
architectures that build Linux. Furthermore this struct is only used in
architectures that do not set ARCH_DEFINE_ENCODE_FPROBE_HEADER which is
set only for 64bit architectures (apart from LoongArch).
Both fields are aligned on these architectures so the struct with
__packed and without it are the same.
Remove the __packed as it is unnecessary.
[Masami: Removed Fixes tag because this is not fixing any problem.]
Link: https://lore.kernel.org/all/20260428-topic-fprobe-packed-v7-1-v1-1-9abc9b866b4c@baylibre.com/
Signed-off-by: Markus Schneider-Pargmann (The Capable Hub) <msp@baylibre.com>
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
|
|
When tracing the kernel local variables, sometimes we need to get the
CPU local variables. To access it, current simple dereference is not
enough.
Thus, introduce a special this_cpu_read() dereference to access per-cpu
variable for the current CPU (accessing other CPU variable may race with
updates on other CPUs). Also this_cpu_ptr() is for accessing per-cpu
pointer.
Those are working as same as the kernel percpu macro.
Link: https://lore.kernel.org/all/178271367680.1176915.4711734074448973989.stgit@devnote2/
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
|
|
Since we can use the BTF to cast value to a structure pointer type,
it is useful to introduce "$current" special variable support to
fetcharg.
User can define a fetcharg to access current task_struct properties
using BTF info. e.g.
$current->cpus_ptr
Link: https://lore.kernel.org/all/178271366709.1176915.15320906169981578568.stgit@devnote2/
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
|
|
Add a field specifier option for the typecast. This works like
container_of() macro.
(STRUCT[,FIELD[.FIELD2...]])VAR
This is equivalent to :
container_of(VAR, struct STRUCT, FIELD[.FIELD2...])
For example:
echo "f tick_nohz_handler next_tick=(tick_sched,sched_timer)timer->next_tick" >> dynamic_events
This will trace tick_nohz_handler() with its tick_sched::next_tick which
is converted from @timer by contianer_of(tick, struct tick_sched, sched_timer).
So, if you enabkle both fprobes:tick_nohz_handler__entry and
timer:hrtimer_expire_entry events, we will see something like:
<idle>-0 [002] d.h1. 3778.087272: hrtimer_expire_entry: hrtimer=00000000d63db328 f
unction=tick_nohz_handler now=3777450051040
<idle>-0 [002] d.h1. 3778.087281: tick_nohz_handler__entry: (tick_nohz_handler+0x4
/0x140) next_tick=3777450000000
Link: https://lore.kernel.org/all/178271365745.1176915.725923927180862257.stgit@devnote2/
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
|
|
This allows type casting to various fetchargs without parentheses
by recursively calling parse_probe_arg on the target when type
casting is used.
For example, this allows the following expressions:
- (STRUCT)%REG->FIELD
- (STRUCT)$stackN->FIELD
- (STRUCT)@SYM->FIELD
Note that @SYM+/-OFFSET with typecast needs parentheses like:
- (STRUCT)(@SYM-8)->FIELD
Link: https://lore.kernel.org/all/178271364804.1176915.17600229399446264813.stgit@devnote2/
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
|
|
When we hit an open parenthesis right after typecast closing
parenthesis, it means we have nested typecast. This allows us to
typecast a generic data member in a structure to a pointer to
another structure.
For example, to cast a DATA_MEMBER of VAR structure to STRUCT pointer
and get MEMBER value.
(STRUCT)(VAR->DATA_MEMBER)->MEMBER
Also, we can nest typecast.
(STRUCT1)((STRUCT2)$ARG->FIELD2)->FIELD1
Currently the max nest level is limited to 3.
This also allows user to use typecasting for registers or stacks on
kprobe events. e.g.
(STRUCT)(%ax)->MEMBER
(STRUCT)($stack0)->MEMBER
Link: https://lore.kernel.org/all/178271363855.1176915.16793301788257446529.stgit@devnote2/
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
|
|
Support BTF typecast feature on other probe events, but only if it is
kernel function entry or return, and must use function parameter name
or $retval. This means you can do:
(STRUCT)PARAM->MEMBER
Note: you can not use other variables like $stackN, %reg etc. That
needs nesting support.
To support other probe events, we just need to use last_struct type
when we find a function parameter in parse_btf_arg().
This also updates <tracefs>/README file to show struct typecast.
Link: https://lore.kernel.org/all/178271362928.1176915.12235759508786922490.stgit@devnote2/
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
|
|
No user currently relies on sparse CPU masks, but the descriptor logic already
supports them via linear fallback. Remove the arbitrary limitation.
Link: https://patch.msgid.link/20260709160017.1729517-4-vdonnefort@google.com
Fixes: 2e67fabd8b77 ("ring-buffer: Introduce ring-buffer remotes")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
|
|
Pre-calculate desc->struct_len up-front in trace_remote_alloc_buffer()
with trace_buffer_desc_size() to fix double-counting.
While at it, use the accessor __first_ring_buffer_desc().
Link: https://patch.msgid.link/20260709160017.1729517-3-vdonnefort@google.com
Fixes: 96e43537af54 ("tracing: Introduce trace remotes")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
|
|
If page allocation fails in trace_remote_alloc_buffer(), desc->nr_cpus
is not yet incremented for the current CPU. As a consequence, on error,
half-allocated rb_desc will not be freed in trace_remote_free_buffer().
Increment desc->nr_cpus as soon as the first allocation for the current
CPU has succeeded.
Link: https://patch.msgid.link/20260709160017.1729517-2-vdonnefort@google.com
Fixes: 96e43537af54 ("tracing: Introduce trace remotes")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
|
|
parse_synth_field() builds a "__data_loc ..." type string before
assigning it to field->type. If the seq_buf check fails, the common
cleanup cannot free the temporary string. Free it before leaving.
Link: https://patch.msgid.link/20260603062533.1096320-2-pengyu@kylinos.cn
Signed-off-by: Yu Peng <pengyu@kylinos.cn>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
|
|
user_event_mm_dup() walks the parent mm's enabler list locklessly under
rcu_read_lock() during fork() (from copy_process()); it does not take
event_mutex:
rcu_read_lock();
list_for_each_entry_rcu(enabler, &old_mm->enablers, mm_enablers_link)
enabler->event = user_event_get(orig->event);
user_event_enabler_destroy() removes an enabler from that list with
list_del_rcu() and then, without waiting for a grace period, drops the
enabler's user_event reference with user_event_put() and frees the enabler
with kfree(). A reader that loaded the enabler before the list_del_rcu()
can still be walking it, which leads to two use-after-frees:
- kfree(enabler) frees the enabler while that reader dereferences
enabler->event.
- user_event_put() may drop the last reference to the user_event, which
is then freed (via delayed_destroy_user_event() on a work queue), while
the same reader does user_event_get(orig->event) on it.
Both are reachable by an unprivileged task that can open user_events_data:
one multithreaded process that registers an enabler and then concurrently
unregisters it and calls fork() triggers the race. KASAN reports a
slab-use-after-free in user_event_mm_dup() during clone(), with a
"refcount_t: addition on 0" warning when the user_event is freed.
The enabler use-after-free was found first; the user_event one was reported
by XIAO WU, and the earlier enabler-only fix did not address it.
Defer both the user_event_put() and the kfree(enabler) to a work item
queued with queue_rcu_work(), so they run only after an RCU grace period,
once all readers walking the enabler list have finished. The put must run
in process context because user_event_put() takes event_mutex on the last
reference, so a work queue is used rather than call_rcu(). The now-unlocked
put lets the locked argument of user_event_enabler_destroy() be removed;
all callers are updated.
Fixes: 7235759084a4 ("tracing/user_events: Use remote writes for event enablement")
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20260707165912.2560537-2-michael.bommarito@gmail.com
Reported-by: XIAO WU <xiaowu.417@qq.com>
Closes: https://lore.kernel.org/all/tencent_89647CE40DC452B891C65C94D1B271DE8E07@qq.com/
Suggested-by: Beau Belgrave <beaub@linux.microsoft.com>
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
|
|
Tracepoints require that RCU is watching. To prevent them from being used
in places that RCU is not watching, the trace_##event() macro always
calls rcu_is_watching() even when the event is not enabled and warns if
RCU is not watching. This is to make sure a warning is triggered even if
the tracepoint is never enabled (as it is only a bug when it is).
It was noticed that tracepoints could be hidden within
trace_#event#_enabled() calls, which are used to do extra work for the
tracepoint only if the tracepoint is enabled. But this also can hide the
fact that a tracepoint is placed in a location that can be called when RCU
is not watching.
Commit 9764e731ef6ab ("tracepoint: Add lockdep rcu_is_watching() check to
trace_##name##_enabled()") added a check to the trace_##event##_enabled()
macro to make sure RCU is watching when it is called to make sure not to
hide the bug of a tracepoint being called when RCU is not watching.
There is one case in the irq_disable tracepoint where it is within a
trace_irq_disable_enabled() block, but it checks if RCU is watching, and
if it isn't, it makes a call to ct_irq_enter() that makes RCU watch again.
But because trace_irq_disable_enabled() now checks if RCU is watching and
will trigger if it isn't. This is a false warning as the code within
the block handles this case.
Add a new internal macro __trace_##event##_enabled() that doesn't check if
RCU is watching, and convert the irq_enable/disable tracepoints over to
it.
Link: https://patch.msgid.link/20260701132744.6a7fc68b@robin
Reported-by: Geert Uytterhoeven <geert@linux-m68k.org>
Closes: https://lore.kernel.org/all/CAMuHMdXud_RpWag_hFqa2ByBGRxg6KnxGL1ObCWZrpTsk3TfAw@mail.gmail.com/
Fixes: 9764e731ef6ab ("tracepoint: Add lockdep rcu_is_watching() check to trace_##name##_enabled()")
Tested-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
|
|
String event fields are not necessarily NUL-terminated, so the filter
predicate functions (filter_pred_string(), filter_pred_strloc() and
filter_pred_strrelloc()) pass the field length to the regex match
callbacks, and the length-aware matchers honour it.
regex_match_glob() was the exception: it ignored the length and called
glob_match(), which scans the string until it hits a NUL byte. Some
string fields are not NUL-terminated. One example is the dynamic char
array of the xfs_* namespace tracepoints, which is copied without a
trailing NUL. For such a field, glob matching reads past the end of
the event field, causing a KASAN slab-out-of-bounds read in
glob_match(), reached via regex_match_glob() and filter_match_preds()
from the xfs_lookup tracepoint.
Add a length-bounded glob_match_len() and use it from regex_match_glob()
so glob matching always stops at the field boundary. The matching loop
is factored into a shared helper so glob_match() keeps its behaviour.
Fixes: 60f1d5e3bac4 ("ftrace: Support full glob matching")
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/da1aaf125fc3b63320b0c540fd6afa7c3d5b4f1a.1782836943.git.hhhuang@smu.edu.sg
Reported-by: Yuan Tan <yuantan098@gmail.com>
Reported-by: Yifan Wu <yifanwucs@gmail.com>
Reported-by: Juefei Pu <tomapufckgml@gmail.com>
Reported-by: Zhengchuan Liang <zcliangcn@gmail.com>
Reported-by: Xin Liu <bird@lzu.edu.cn>
Assisted-by: Codex:GPT-5.4
Signed-off-by: Huihui Huang <hhhuang@smu.edu.sg>
Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
|
|
func_set_flag() dereferences tr->current_trace_flags before verifying
that the current tracer is actually the function tracer. When the active
tracer has been switched away from "function" (e.g., to "wakeup_rt"),
tr->current_trace_flags can be NULL, leading to a NULL pointer
dereference and kernel crash.
The call chain that triggers this is:
trace_options_write()
-> __set_tracer_option()
-> trace->set_flag() /* func_set_flag */
In func_set_flag(), the first operation is:
if (!!set == !!(tr->current_trace_flags->val & bit))
This dereferences tr->current_trace_flags unconditionally. The safety
check that guards against a non-function tracer:
if (tr->current_trace != &function_trace)
return 0;
is placed *after* the dereference, which is too late.
This was observed with the following crash dump:
BUG: unable to handle page fault at 0000000000000000
RIP: func_set_flag+0xd
Call Trace:
__set_tracer_option+0x27
trace_options_write+0x75
vfs_write+0x12a
ksys_write+0x66
do_syscall_64+0x5b
RIP: ffffffff914c973d RSP: ff67ec88b01dfdf0 RFLAGS: 00010202
RAX: 0000000000000000 RBX: ff3a826e80354580 RCX: 0000000000000001
RDX: 0000000000000001 RSI: 0000000000000000 RDI: ffffffff93918080
The disassembly confirms the fault:
func_set_flag+0: mov 0x1f08(%rdi), %rax ; RAX = tr->current_trace_flags = NULL
func_set_flag+13: mov (%rax), %eax ; page fault: dereference NULL
At the time of the crash:
tr->current_trace_flags = 0x0 (NULL)
tr->current_trace = wakeup_rt_tracer (not function_trace)
The scenario is that a process opens a function tracer option file (such
as "func_stack_trace"), then the current tracer is switched to another
tracer (e.g., "wakeup_rt"), which sets current_trace_flags to NULL. When
the process subsequently writes to the option file, func_set_flag() is
invoked and crashes on the NULL dereference.
Fix this by moving the current_trace check before the
current_trace_flags dereference, so that func_set_flag() returns early
when the function tracer is not active.
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20260624061715.1445655-1-xiangzao@linux.alibaba.com
Fixes: 76680d0d2825 ("tracing: Have function tracer define options per instance")
Signed-off-by: Yuanhe Shu <xiangzao@linux.alibaba.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
|
|
The tracepoint_printk symbol is not exported, so make it
static to remove the following sparse warning:
kernel/trace/trace.c:90:5: warning: symbol 'tracepoint_printk' was not declared. Should it be static?
Fixes: dd293df6395a2 ("tracing: Move trace sysctls into trace.c")
Link: https://patch.msgid.link/20260617105822.904164-1-ben.dooks@codethink.co.uk
Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
|
|
Commit 8928e4a3be34 ("ring-buffer: Show persistent buffer dropped events
in trace_pipe file") split the "commit" variable in
ring_buffer_read_page() into "commit" (raw) and "size" (masked page
size), but the inner copy loop's terminator was changed to compare rpos
against "event_size" instead of "size".
rpos is the cumulative read offset within the page; event_size is the
length of the single event just copied. The loop thus breaks after the
first event, so only one event is copied per call. This regresses the
per-event memcpy path (partial reads, the active commit page, and
mapped/remote buffers) used by splice/trace_pipe_raw and mmap consumers
into a one-event-at-a-time read.
Compare rpos against the page size as the original code did.
Link: https://patch.msgid.link/20260616175538.111628-1-devnexen@gmail.com
Fixes: 8928e4a3be34 ("ring-buffer: Show persistent buffer dropped events in trace_pipe file")
Signed-off-by: David Carlier <devnexen@gmail.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
|
|
In tracing_set_tracer(), the assignment 'ret = 0' following the
__tracing_resize_ring_buffer() error check is a dead store. After
this point, all subsequent code paths either return with a constant
value (-EINVAL, 0, -EBUSY) or reassign ret before reading it
(tracing_arm_snapshot_locked, tracer_init).
Remove the unnecessary assignment.
No functional change.
Link: https://patch.msgid.link/6a2a37c4.f0a9eb5a.2fc603.7724@mx.google.com
Signed-off-by: Wayen.Yan <win847@gmail.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
|
|
This ensures that any RCU readers traversing the instance list
have finished, before releasing the reference on the tracer that
the instance points to.
Cc: stable@vger.kernel.org
Fixes: a6ed2aee54644 ("tracing: Switch to kvfree_rcu() API")
Link: https://patch.msgid.link/20260609045430.1589786-1-crwood@redhat.com
Suggested-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Crystal Wood <crwood@redhat.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
|
|
When RB_FORCE_8BYTE_ALIGNMENT is true, rb_calculate_event_length()
reserves the space of event->array[0] for placing the data length and
rb_update_event() stores the data length in event->array[0]
accordingly. As a result the whole event length will add extra 4 bytes
for sizeof(event.array[0]) unconditionally.
But ring_buffer_event_length() only subtracts the
sizeof(event->array[0]) for events larger than RB_MAX_SMALL_DATA +
sizeof(event->array[0]). As a result, small events on architectures
with RB_FORCE_8BYTE_ALIGNMENT=true report a data length that is 4
bytes larger than expected.
To fix it, add the RB_FORCE_8BYTE_ALIGNMENT as a condition to subtract
the size of that length field whenever RB_FORCE_8BYTE_ALIGNMENT is
true.
This issue is observed in a riscv64 kernel with
CONFIG_HAVE_64BIT_ALIGNED_ACCESS set to y, when we run ftrace selftest
trace_marker_raw.tc, we get the weird log: for cases where the id is
1..100, the number of data field is 8*N, but once id exceeds 100, the
number of data field becomes 8*N+4:
# 1 buf: 58 00 00 00 80 5e d1 63 (number of data field is 8*1)
...
# a buf: 58 ... (number of data field is 8*2)
...
# 64 buf: 58 ... (number of data field is 8*13)
# 65 buf: 58 ... (number of data field is 8*13+4)
After applying this change, the number of data field keeps being 8*N+4
consistently.
Link: https://patch.msgid.link/20260607072431.125633-2-hui.wang@canonical.com
Fixes: 2271048d1b3b ("ring-buffer: Do 8 byte alignment for 64 bit that can not handle 4 byte align")
Signed-off-by: Hui Wang <hui.wang@canonical.com>
Reviewed-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
|
|
Some __create_synth_event() error paths run after parse_synth_field()
succeeds but before the field is stored in fields[]. The common cleanup
then misses the field. Free it before freeing argv.
Link: https://patch.msgid.link/20260603062533.1096320-1-pengyu@kylinos.cn
Signed-off-by: Yu Peng <pengyu@kylinos.cn>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
|
|
Cross-merge BPF and other fixes after downstream PR.
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
|
|
For debugging probe events, it is helpful to verify the compiled
fetch instructions for each probe argument. This introduces a new
kernel config CONFIG_PROBE_EVENTS_DUMP_FETCHARG to decode the
instruction sequence of each argument and display it under a
commented line starting with '#' immediately following the dynamic
event definition (such as in dynamic_events, kprobe_events,
uprobe_events, etc.).
For example:
/sys/kernel/tracing # cat dynamic_events
p:kprobes/p_vfs_read_0 vfs_read arg1=+0(file):ustring arg2=%ax:x16
# arg1: ARG(0) -> ST_USTRING(offset=0,size=4) -> END
# arg2: REG(80) -> ST_RAW(size=2) -> END
Link: https://lore.kernel.org/all/178271359508.1176915.11895926894608440183.stgit@devnote2/
Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
|
|
The commit 69efd863a785 ("tracing/eprobes: Allow use of BTF names
to dereference pointers") allows eprobe to use event field without
"$" prefix when it is used with typecast, it is natual to allow it
without typecast.
Link: https://lore.kernel.org/all/178271358117.1176915.13520279547897961254.stgit@devnote2/
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
|
|
We can pass NULL as id pointer to btf_type_skip_modifiers if we do not
need the id of the returned btf_type.
Link: https://lore.kernel.org/all/20260623132937.3494895-1-martin@kaiser.cx/
Signed-off-by: Martin Kaiser <martin@kaiser.cx>
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
|
|
Since FETCH_OP_DATA is used solely to store immediate string
values, rename it to the more specific FETCH_OP_IMMSTR.
No behavior change, just rename it.
Link: https://lore.kernel.org/all/178217906914.643090.2958799486090467704.stgit@devnote2/
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
|
|
The shared probe argument parser rejects file offsets for kernel probes.
This path is used outside the kprobe event parser too, but the diagnostic
currently says "with kprobe" even when emitted from another probe path.
Make the diagnostic probe-agnostic.
Link: https://lore.kernel.org/all/20260622160032.99834-1-pyudistira519@gmail.com/
Signed-off-by: Yudistira Putra <pyudistira519@gmail.com>
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
|
|
The function name should be __register_tracepoint_fprobe.
Link: https://lore.kernel.org/all/20260507081041.885781-5-martin@kaiser.cx/
Signed-off-by: Martin Kaiser <martin@kaiser.cx>
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
|
|
Adding BPF_OBJ_GET_INFO_BY_FD support for tracing_multi links.
We expose following tracing_multi link data:
- attach_type of the program
- number of ids
- array of BTF ids
- array of its related kernel addresses
- array of cookies
The change follows the kprobe_multi and uprobe_multi link-info convention
of optional output arrays with an in/out count,
On top of standard tracing link data we also expose addresses, because they
are useful info for user (especially when the attachment was done via pattern).
This data is hidden when kallsyms does not allow exposing kernel pointer values.
Assisted-by: Codex:GPT-5
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Acked-by: Leon Hwang <leon.hwang@linux.dev>
Acked-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20260629212208.895962-2-jolsa@kernel.org
|
|
Pull probes fixes from Masami Hiramatsu:
"fprobe fixes and spelling typos:
- Fix NULL pointer dereference in fprobe_fgraph_entry(). Prevent
general protection faults by checking shadow-stack reservation
bounds. Skip mid-flight registered fprobes that were not counted
during sizing.
eprobe: fix string pointer extraction
- Correct the casting of string pointers read from the ringbuffer to
prevent truncation of base event pointer variables when
dereferencing FILTER_PTR_STRING fields.
tracing/probes: clean up argument parsing and BTF helper logic
- Make the $ prefix mandatory for comm access: Require the $ prefix
for special fetcharg variables like $comm and $COMM, preventing
naming conflicts with regular BTF-based event fields.
- Fix double addition of offset for @+FOFFSET: Clear the temporary
offset variable after setting the FETCH_OP_FOFFS instruction to
avoid applying the offset multiple times.
- Remove WARN_ON_ONCE from parse_btf_arg: Prevent triggering a kernel
warning via user-space input when creating a kprobe event on a raw
address.
- Fix typo in a log message: Correct a spelling error ("$-valiable")
in trace probe log messages.
samples/trace_events: improve error checking
- Validate the thread pointer returned from kthread_run() in the
trace events sample code to properly handle thread creation
failures"
* tag 'probes-fixes-v7.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace:
tracing/probes: Make the $ prefix mandatory for comm access
tracing/fprobe: Fix NULL pointer dereference in fprobe_fgraph_entry()
tracing/probes: Fix double addition of offset for @+FOFFSET
tracing: eprobe: read the complete FILTER_PTR_STRING pointer
tracing/events: Fix to check the simple_tsk_fn creation
tracing/probes: Remove WARN_ON_ONCE from parse_btf_arg
tracing: probes: fix typo in a log message
|
|
Since $comm or $COMM are not event field but special fetcharg
variables to access current->comm, It should not be accessed
without '$' prefix even with typecast.
Link: https://lore.kernel.org/all/178231209724.732967.12049805699091810641.stgit@devnote2/
Fixes: 69efd863a785 ("tracing/eprobes: Allow use of BTF names to dereference pointers")
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
|
|
fprobe_fgraph_entry() sizes a shadow-stack reservation in one walk of
the per-ip fprobe list and fills it in a second walk, both under
rcu_read_lock() only. A fprobe registered on an already-live ip can
become visible between the two walks, so the fill walk processes an
exit_handler the sizing walk did not count and used runs past
reserved_words. If the sizing walk counted nothing, fgraph_data is NULL
and the first write_fprobe_header() faults:
Oops: general protection fault, probably for non-canonical address ...
KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007]
RIP: 0010:fprobe_fgraph_entry+0xa38/0xf10 kernel/trace/fprobe.c:167
Call Trace:
<TASK>
function_graph_enter_regs+0x44c/0xa10 kernel/trace/fgraph.c:677
ftrace_graph_func+0xc5/0x140 arch/x86/kernel/ftrace.c:671
__kernel_text_address+0x9/0x40 kernel/extable.c:78
arch_stack_walk+0x117/0x170 arch/x86/kernel/stacktrace.c:26
kmem_cache_free+0x188/0x580 mm/slub.c:6378
tcp_data_queue+0x18d/0x6550 net/ipv4/tcp_input.c:5590
[...]
</TASK>
The list cannot be frozen across the two walks, so skip a node that does
not fit the reservation and count it as missed.
Link: https://lore.kernel.org/all/20260619184425.3824774-1-rhkrqnwk98@gmail.com/
Fixes: 4346ba160409 ("fprobe: Rewrite fprobe on function-graph tracer")
Signed-off-by: Sechang Lim <rhkrqnwk98@gmail.com>
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
|
|
Since commit 533059281ee5 ("tracing: probeevent: Introduce new argument
fetching code") wrongly use @offset local variable during the parsing,
the offset value is added twice when dereferencing.
Reset the @offset after setting it in FETCH_OP_FOFFS.
Link: https://lore.kernel.org/all/178217905962.643090.1978577464942171332.stgit@devnote2/
Fixes: 533059281ee5 ("tracing: probeevent: Introduce new argument fetching code")
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Cc: stable@vger.kernel.org
|
|
For a char * element in an event, the FILTER_PTR_STRING filter type is
used. When the event occurs, a pointer is stored in the ringbuffer.
If an eprobe references such a char * element of a "base event", the
stored pointer is truncated when it's read from the ringbuffer.
$ cd /sys/kernel/tracing
$ echo 'e rcu.rcu_utilization $s:x64 $s:string' > dynamic_events
$ echo 1 > tracing_on
$ echo 1 > events/eprobes/enable
$ sleep 1
$ echo 0 > events/eprobes/enable
$ cat trace
<idle>-0 ...: (rcu.rcu_utilization) arg1=0x4f arg2=(fault)
<idle>-0 ...: (rcu.rcu_utilization) arg1=0x2 arg2=(fault)
The problem is in get_event_field
val = (unsigned long)(*(char *)addr);
addr points to the position in the ringbuffer where the pointer was
stored. The assignment reads only the lowest byte of the pointer.
Fix the cast to read the whole pointer. The output of the test above
is now
<idle>-0 ... arg1=0xffffffff81c7d3f3 arg2="Start scheduler-tick"
<idle>-0 ... arg1=0xffffffff81c57340 arg2="End scheduler-tick"
Link: https://lore.kernel.org/all/20260620145339.3234726-1-martin@kaiser.cx/
Fixes: f04dec93466a ("tracing/eprobes: Fix reading of string fields")
Signed-off-by: Martin Kaiser <martin@kaiser.cx>
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
|
|
Sashiko found that user can cause this WARN_ON_ONCE() easily
with adding a kprobe event based on a raw address with BTF
parameter.
Since this is not an unexpected condition, remove the
WARN_ON_ONCE().
Link: https://lore.kernel.org/all/178177265367.2059927.13789953014706792126.stgit@mhiramat.tok.corp.google.com/
Link: https://sashiko.dev/#/patchset/178165816303.269421.7302603996990753309.stgit%40devnote2
Reported-by: Sashiko <sashiko-bot@kernel.org>
Fixes: b576e09701c7 ("tracing/probes: Support function parameters if BTF is available")
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
|
|
Fix a typo ("Invalid $-variable") in a log message.
Link: https://lore.kernel.org/all/20260507081041.885781-4-martin@kaiser.cx/
Fixes: ab105a4fb894 ("tracing: Use tracing error_log with probe events")
Signed-off-by: Martin Kaiser <martin@kaiser.cx>
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
|
|
As reported by sashiko we use __get_user without prior access_ok call on the
user space pointer. Adding the missing call for the whole pointer array.
Plus removing the err check in the error path, because it's not needed and
also we can return -ENOMEM directly from the first kvmalloc_array fail path.
Cc: stable@vger.kernel.org
[1] https://lore.kernel.org/bpf/20260611115503.AC16D1F00893@smtp.kernel.org/
Fixes: 0236fec57a15 ("bpf: Resolve symbols with ftrace_lookup_symbols for kprobe multi link")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://lore.kernel.org/bpf/20260611115503.AC16D1F00893@smtp.kernel.org/
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
Link: https://lore.kernel.org/r/20260616083056.405652-1-jolsa@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
|
|
Pull ring-buffer updates from Steven Rostedt
- Do not invalidate entire buffer for invalid sub-buffers
For the persistent ring buffer, if one sub-buffer is found to be
invalid, it invalidates the entire per CPU ring buffer. This can lose
a lot of valuable data if there's some corruption with the writes to
the buffer not syncing properly on a hard crash. Instead, if a
sub-buffer is found to be invalid, simply zero it out and mark it for
"missed events".
When the persistent ring buffer is read and a sub-buffer that was
cleared due to being invalid on boot up is discovered, the output
will show "[LOST EVENTS]" to let the user know that events were
missing at that location. Displaying the events from valid buffers
can still be useful.
- Add a test to be able to test corrupted sub-buffers
If a persistent ring buffer is created as "ptraingtest" and the new
config that adds the test is enabled, when a panic happens, the
kernel will randomly corrupt one of the per CPU ring buffers. On boot
up, the sub-buffers with the corruption should be cleared and
flagged. When reading this buffer, the missed events should should
[LOST EVENTS].
- Add commit number in the sub-buffer meta debug info
The commit is used to know the content of a meta page. Add it to the
buffer_meta file that is shown for each per CPU buffer.
- Clean up the persistent ring buffer validation code
Add some helper functions and make variable names more consistent.
* tag 'trace-ring-buffer-v7.2' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace:
ring-buffer: Better comment the use of RB_MISSED_EVENTS
ring-buffer: Show persistent buffer dropped events in trace_pipe file
ring-buffer: Show persistent buffer dropped events in trace file
ring-buffer: Have dropped subbuffers be persistent across reboots
ring-buffer: Cleanup buffer_data_page related code
ring-buffer: Cleanup persistent ring buffer validation
ring-buffer: Show commit numbers in buffer_meta file
ring-buffer: Add persistent ring buffer invalid-page inject test
ring-buffer: Skip invalid sub-buffers when rewinding persistent ring buffer
ring-buffer: Skip invalid sub-buffers when validating persistent ring buffer
|
|
Pull tracing updates from Steven Rostedt:
- Remove a redundant IS_ERR() check
trace_pipe_open() already checks for IS_ERR() and does it again in
the return path. Remove the return check.
- Export seq_buf_putmem_hex() to allow kunit tests against them
To add Kunit tests on seq_buf_putmem_hex(), it needs to be exported.
- Replace strcat() and strcpy() with seq_buf() logic
The code for synthetic events uses a series of strcat() and strcpy()
which can be error prone. Replace them with seq_buf() logic that does
all the necessary bound checking.
- Add a lockdep rcu_is_watching() to trace_##event##_enabled() call
The trace_##event##_enabled() is a static branch that is true if the
"event" is enabled. But this can hide bugs if this logic is in a
location where RCU is disabled and not "watching". It would only
trigger if lockdep is enabled and the event is enabled.
Add a "rcu_is_watching()" warning if lockdep is enabled in that
helper function to trigger regardless if the event is enabled or not.
- Remove the local variable in the trace_printk() macro
For name space integrity, remove the _______STR variable in the
trace_printk() macro for using the sizeof() macro directly.
- Use guard()s for the trace_recursion_record.c file
- Fix typo in a comment of eventfs_callback() kerneldoc
- Use trace_call__##event() in events within trace_##event##_enabled()
A couple of events are called within an if block guarded by
trace_##event##_enabled(). That is a static key that is only enabled
when the event is enabled. The trace_call_##event() calls the
tracepoint code directly without adding a redundant static key for
that check.
- Allow perf to read synthetic events
Currently, perf does not have the ability to enable a synthetic
event. If it does, it will either cause a kernel warning or error
with "No such device". Synthetic events are not much different than
kprobes and perf can handle fine with a few modifications.
- Replace printk(KERN_WARNING ...) with pr_warn()
- Replace krealloc() on an array with krealloc_array()
- Fix README file path name for synthetic events
- Change tracing_map tracing_map_array to use a flexible array
Instead of allocating a separate pointer to hold the pages field of
tracing_map_array, allocate the pages field as a flexible array when
allocating the structure.
- Fold trace_iterator_increment() into trace_find_next_entry_inc()
The function trace_iterator_increment() was only used by
trace_find_next_entry_inc(). It's not big enough to be a helper
function for one user. Fold it into its caller.
- Make field_var_str field a flexible array of hist_elt_data
Instead of allocating a separate pointer for the field_var_str array
of the hist_elt_data structure, allocate it as a flexible array when
allocating the structure.
- Disable KCOV for trace_irqsoff.c
Like trace_preemptirq.c, trace_irqsoff.c has code that will crash
when KCOV is enabled on ARM. The irqsoff tracing can be called on ARM
because the irqsoff tracing code can be run from early interrupt code
and produce coverage unrelated to syscall inputs.
- Fix warning in __unregister_ftrace_function() called by perf
Perf calls unregister_ftrace_function() without checking if its
ftrace_ops has already been unregistered. There's an error path where
on clean up it will unregister the ftrace_ops even if it wasn't
registered and causes a warning.
* tag 'trace-v7.2' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace:
perf/ftrace: Fix WARNING in __unregister_ftrace_function
tracing: Disable KCOV instrumentation for trace_irqsoff.o
tracing: Turn hist_elt_data field_var_str into a flexible array
tracing: Move trace_iterator_increment() into trace_find_next_entry_inc()
tracing: Simplify pages allocation for tracing_map logic
tracing: Fix README path for synthetic_events
tracing: Use krealloc_array() for trace option array growth
tracing/branch: Use pr_warn() instead of printk(KERN_WARNING)
tracing: Allow perf to read synthetic events
HID: Use trace_call__##name() at guarded tracepoint call sites
cpufreq: amd-pstate: Use trace_call__##name() at guarded tracepoint call site
tracefs: Fix typo in a comment of eventfs_callback() kerneldoc
tracing: Switch trace_recursion_record.c code over to use guard()
tracing: Remove local variable for argument detection from trace_printk()
tracepoint: Add lockdep rcu_is_watching() check to trace_##name##_enabled()
tracing: Bound synthetic-field strings with seq_buf
seq_buf: Export seq_buf_putmem_hex() and add KUnit tests
tracing: Remove redundant IS_ERR() check in trace_pipe_open()
|
|
Pull bpf updates from Alexei Starovoitov:
"Major changes:
- Recover from BPF arena page faults using a scratch page and add
ptep_try_set() for lockless empty-slot installs on x86 and arm64.
This allows BPF kfuncs to access arena pointers directly.
The 'arena_direct_access' stable branch was created for this work
and was pulled into sched-ext and bpf-next trees (Tejun Heo, Kumar
Kartikeya Dwivedi)
- Lift old restriction and support 6+ arguments in BPF programs and
kfuncs on x86 and arm64 (Yonghong Song, Puranjay Mohan)
Other features and fixes:
- Add 24-bit BTF vlen and reclaim unused bits in the BTF UAPI to ease
addition of new BTF kinds (Alan Maguire)
- Raise the maximum BPF call chain depth from 8 to 16 frames (Alexei
Starovoitov)
- Refactor object relationship tracking in the verifier and fix a
dynptr use-after-free bug (Amery Hung)
- Harden the signed program loader and reject exclusive maps as inner
maps (Daniel Borkmann)
- Replace the verifier min/max bounds fields with a circular number
(cnum) representation and improve 32->64 bit range refinements
(Eduard Zingerman)
- Introduce the arena library and runtime (libarena) with a buddy
allocator, rbtree and SPMC queue data structures, ASAN support and
a parallel test harness. Allow subprograms to return arena pointers
and switch to a BTF type-tag based __arena annotation (Emil
Tsalapatis)
- Cache build IDs in the sleepable stackmap path and avoid faultable
build ID reads under mm locks (Ihor Solodrai)
- Introduce the tracing_multi link to attach a single BPF program to
many kernel functions at once. Allow specifying the uprobe_multi
target via FD (Jiri Olsa)
- Extend the bpf_list family of kfuncs with bpf_list_add/del(), and
bpf_list_is_first/is_last/empty() (Kaitao Cheng)
- Extend the BPF syscall with common attributes support for
prog_load, btf_load and map_create (Leon Hwang)
- Wrap rhashtable as BPF map (Mykyta Yatsenko, Herbert Xu)
- Add sleepable support for tracepoint programs and fix deadlocks in
LRU map due to NMI reentry (Mykyta Yatsenko)
- Fix OOB access in bpf_flow_keys, fix nullness analysis of inner
arrays, enforce write checks for global subprograms (Nuoqi Gui)
- Report the maximum combined stack depth and print a breakdown of
instructions processed per subprogram (Paul Chaignon)
- Add an XDP load-balancer benchmark and arm64 JIT support for stack
arguments (Puranjay Mohan)
- Add kfuncs to traverse over wakeup_sources (Samuel Wu)
- Allow sleepable BPF programs to use LPM trie maps directly (Vlad
Poenaru)
- Many more fixes and cleanups across the verifier, BTF, sockmap,
devmap, bpffs, security hooks, s390/riscv/loongarch JITs,
rqspinlock, libbpf, bpftool, selftests"
* tag 'bpf-next-7.2' of git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next: (336 commits)
selftests/bpf: Work around llvm stack overflow in crypto progs
selftests/bpf: add test for bpf_msg_pop_data() overflow
bpf, sockmap: fix integer overflow in bpf_msg_pop_data() bounds check
sockmap: Fix use-after-free in udp_bpf_recvmsg()
bpf, sockmap: keep sk_msg copy state in sync
bpf, sockmap: Fix wrong rsge offset in bpf_msg_push_data()
bpf, sockmap: reject overflowing copy + len in bpf_msg_push_data()
selftsets/bpf: Retry map update on helper_fill_hashmap()
selftests/bpf: Add test for sleepable lsm_cgroup rejection
selftests/bpf: Add test to verify the fix for bpf_setsockopt() helper
bpf: Fix bpf_get/setsockopt to tos for ipv4-mapped ipv6 socket
selftests/bpf: Avoid static LLVM linking for cross builds
selftests/bpf: Use common CFLAGS for urandom_read
selftests/bpf: Initialize operation name before use
tools/bpf: build: Append extra cflags
libbpf: Initialize CFLAGS before including Makefile.include
bpftool: Append extra host flags
bpftool: Avoid adding EXTRA_CFLAGS to HOST_CFLAGS
bpftool: Pass host flags to bootstrap libbpf
selftests/bpf: correct CONFIG_PPC64 macro name in comment
...
|