Skip to content

Commit 02079f0

Browse files
anakryikogregkh
authored andcommitted
uprobes: encapsulate preparation of uprobe args buffer
commit 3eaea21b4d27cff0017c20549aeb53034c58fc23 upstream. Move the logic of fetching temporary per-CPU uprobe buffer and storing uprobes args into it to a new helper function. Store data size as part of this buffer, simplifying interfaces a bit, as now we only pass single uprobe_cpu_buffer reference around, instead of pointer + dsize. This logic was duplicated across uprobe_dispatcher and uretprobe_dispatcher, and now will be centralized. All this is also in preparation to make this uprobe_cpu_buffer handling logic optional in the next patch. Link: https://lore.kernel.org/all/[email protected]/ [Masami: update for v6.9-rc3 kernel] Signed-off-by: Andrii Nakryiko <[email protected]> Reviewed-by: Jiri Olsa <[email protected]> Acked-by: Masami Hiramatsu (Google) <[email protected]> Signed-off-by: Masami Hiramatsu (Google) <[email protected]> Stable-dep-of: 373b9338c972 ("uprobe: avoid out-of-bounds memory access of fetching args") Signed-off-by: Sasha Levin <[email protected]> Signed-off-by: Vamsi Krishna Brahmajosyula <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent fdacd09 commit 02079f0

File tree

1 file changed

+41
-38
lines changed

1 file changed

+41
-38
lines changed

kernel/trace/trace_uprobe.c

Lines changed: 41 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -858,6 +858,7 @@ static const struct file_operations uprobe_profile_ops = {
858858
struct uprobe_cpu_buffer {
859859
struct mutex mutex;
860860
void *buf;
861+
int dsize;
861862
};
862863
static struct uprobe_cpu_buffer __percpu *uprobe_cpu_buffer;
863864
static int uprobe_buffer_refcnt;
@@ -947,9 +948,26 @@ static void uprobe_buffer_put(struct uprobe_cpu_buffer *ucb)
947948
mutex_unlock(&ucb->mutex);
948949
}
949950

951+
static struct uprobe_cpu_buffer *prepare_uprobe_buffer(struct trace_uprobe *tu,
952+
struct pt_regs *regs)
953+
{
954+
struct uprobe_cpu_buffer *ucb;
955+
int dsize, esize;
956+
957+
esize = SIZEOF_TRACE_ENTRY(is_ret_probe(tu));
958+
dsize = __get_data_size(&tu->tp, regs);
959+
960+
ucb = uprobe_buffer_get();
961+
ucb->dsize = tu->tp.size + dsize;
962+
963+
store_trace_args(ucb->buf, &tu->tp, regs, esize, dsize);
964+
965+
return ucb;
966+
}
967+
950968
static void __uprobe_trace_func(struct trace_uprobe *tu,
951969
unsigned long func, struct pt_regs *regs,
952-
struct uprobe_cpu_buffer *ucb, int dsize,
970+
struct uprobe_cpu_buffer *ucb,
953971
struct trace_event_file *trace_file)
954972
{
955973
struct uprobe_trace_entry_head *entry;
@@ -960,14 +978,14 @@ static void __uprobe_trace_func(struct trace_uprobe *tu,
960978

961979
WARN_ON(call != trace_file->event_call);
962980

963-
if (WARN_ON_ONCE(tu->tp.size + dsize > PAGE_SIZE))
981+
if (WARN_ON_ONCE(ucb->dsize > PAGE_SIZE))
964982
return;
965983

966984
if (trace_trigger_soft_disabled(trace_file))
967985
return;
968986

969987
esize = SIZEOF_TRACE_ENTRY(is_ret_probe(tu));
970-
size = esize + tu->tp.size + dsize;
988+
size = esize + ucb->dsize;
971989
entry = trace_event_buffer_reserve(&fbuffer, trace_file, size);
972990
if (!entry)
973991
return;
@@ -981,14 +999,14 @@ static void __uprobe_trace_func(struct trace_uprobe *tu,
981999
data = DATAOF_TRACE_ENTRY(entry, false);
9821000
}
9831001

984-
memcpy(data, ucb->buf, tu->tp.size + dsize);
1002+
memcpy(data, ucb->buf, ucb->dsize);
9851003

9861004
trace_event_buffer_commit(&fbuffer);
9871005
}
9881006

9891007
/* uprobe handler */
9901008
static int uprobe_trace_func(struct trace_uprobe *tu, struct pt_regs *regs,
991-
struct uprobe_cpu_buffer *ucb, int dsize)
1009+
struct uprobe_cpu_buffer *ucb)
9921010
{
9931011
struct event_file_link *link;
9941012

@@ -997,21 +1015,21 @@ static int uprobe_trace_func(struct trace_uprobe *tu, struct pt_regs *regs,
9971015

9981016
rcu_read_lock();
9991017
trace_probe_for_each_link_rcu(link, &tu->tp)
1000-
__uprobe_trace_func(tu, 0, regs, ucb, dsize, link->file);
1018+
__uprobe_trace_func(tu, 0, regs, ucb, link->file);
10011019
rcu_read_unlock();
10021020

10031021
return 0;
10041022
}
10051023

10061024
static void uretprobe_trace_func(struct trace_uprobe *tu, unsigned long func,
10071025
struct pt_regs *regs,
1008-
struct uprobe_cpu_buffer *ucb, int dsize)
1026+
struct uprobe_cpu_buffer *ucb)
10091027
{
10101028
struct event_file_link *link;
10111029

10121030
rcu_read_lock();
10131031
trace_probe_for_each_link_rcu(link, &tu->tp)
1014-
__uprobe_trace_func(tu, func, regs, ucb, dsize, link->file);
1032+
__uprobe_trace_func(tu, func, regs, ucb, link->file);
10151033
rcu_read_unlock();
10161034
}
10171035

@@ -1339,7 +1357,7 @@ static bool uprobe_perf_filter(struct uprobe_consumer *uc,
13391357

13401358
static void __uprobe_perf_func(struct trace_uprobe *tu,
13411359
unsigned long func, struct pt_regs *regs,
1342-
struct uprobe_cpu_buffer *ucb, int dsize)
1360+
struct uprobe_cpu_buffer *ucb)
13431361
{
13441362
struct trace_event_call *call = trace_probe_event_call(&tu->tp);
13451363
struct uprobe_trace_entry_head *entry;
@@ -1360,7 +1378,7 @@ static void __uprobe_perf_func(struct trace_uprobe *tu,
13601378

13611379
esize = SIZEOF_TRACE_ENTRY(is_ret_probe(tu));
13621380

1363-
size = esize + tu->tp.size + dsize;
1381+
size = esize + ucb->dsize;
13641382
size = ALIGN(size + sizeof(u32), sizeof(u64)) - sizeof(u32);
13651383
if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, "profile buffer not large enough"))
13661384
return;
@@ -1383,13 +1401,10 @@ static void __uprobe_perf_func(struct trace_uprobe *tu,
13831401
data = DATAOF_TRACE_ENTRY(entry, false);
13841402
}
13851403

1386-
memcpy(data, ucb->buf, tu->tp.size + dsize);
1387-
1388-
if (size - esize > tu->tp.size + dsize) {
1389-
int len = tu->tp.size + dsize;
1404+
memcpy(data, ucb->buf, ucb->dsize);
13901405

1391-
memset(data + len, 0, size - esize - len);
1392-
}
1406+
if (size - esize > ucb->dsize)
1407+
memset(data + ucb->dsize, 0, size - esize - ucb->dsize);
13931408

13941409
perf_trace_buf_submit(entry, size, rctx, call->event.type, 1, regs,
13951410
head, NULL);
@@ -1399,21 +1414,21 @@ static void __uprobe_perf_func(struct trace_uprobe *tu,
13991414

14001415
/* uprobe profile handler */
14011416
static int uprobe_perf_func(struct trace_uprobe *tu, struct pt_regs *regs,
1402-
struct uprobe_cpu_buffer *ucb, int dsize)
1417+
struct uprobe_cpu_buffer *ucb)
14031418
{
14041419
if (!uprobe_perf_filter(&tu->consumer, 0, current->mm))
14051420
return UPROBE_HANDLER_REMOVE;
14061421

14071422
if (!is_ret_probe(tu))
1408-
__uprobe_perf_func(tu, 0, regs, ucb, dsize);
1423+
__uprobe_perf_func(tu, 0, regs, ucb);
14091424
return 0;
14101425
}
14111426

14121427
static void uretprobe_perf_func(struct trace_uprobe *tu, unsigned long func,
14131428
struct pt_regs *regs,
1414-
struct uprobe_cpu_buffer *ucb, int dsize)
1429+
struct uprobe_cpu_buffer *ucb)
14151430
{
1416-
__uprobe_perf_func(tu, func, regs, ucb, dsize);
1431+
__uprobe_perf_func(tu, func, regs, ucb);
14171432
}
14181433

14191434
int bpf_get_uprobe_info(const struct perf_event *event, u32 *fd_type,
@@ -1479,10 +1494,8 @@ static int uprobe_dispatcher(struct uprobe_consumer *con, struct pt_regs *regs)
14791494
struct trace_uprobe *tu;
14801495
struct uprobe_dispatch_data udd;
14811496
struct uprobe_cpu_buffer *ucb;
1482-
int dsize, esize;
14831497
int ret = 0;
14841498

1485-
14861499
tu = container_of(con, struct trace_uprobe, consumer);
14871500
tu->nhit++;
14881501

@@ -1494,18 +1507,14 @@ static int uprobe_dispatcher(struct uprobe_consumer *con, struct pt_regs *regs)
14941507
if (WARN_ON_ONCE(!uprobe_cpu_buffer))
14951508
return 0;
14961509

1497-
dsize = __get_data_size(&tu->tp, regs);
1498-
esize = SIZEOF_TRACE_ENTRY(is_ret_probe(tu));
1499-
1500-
ucb = uprobe_buffer_get();
1501-
store_trace_args(ucb->buf, &tu->tp, regs, esize, dsize);
1510+
ucb = prepare_uprobe_buffer(tu, regs);
15021511

15031512
if (trace_probe_test_flag(&tu->tp, TP_FLAG_TRACE))
1504-
ret |= uprobe_trace_func(tu, regs, ucb, dsize);
1513+
ret |= uprobe_trace_func(tu, regs, ucb);
15051514

15061515
#ifdef CONFIG_PERF_EVENTS
15071516
if (trace_probe_test_flag(&tu->tp, TP_FLAG_PROFILE))
1508-
ret |= uprobe_perf_func(tu, regs, ucb, dsize);
1517+
ret |= uprobe_perf_func(tu, regs, ucb);
15091518
#endif
15101519
uprobe_buffer_put(ucb);
15111520
return ret;
@@ -1517,7 +1526,6 @@ static int uretprobe_dispatcher(struct uprobe_consumer *con,
15171526
struct trace_uprobe *tu;
15181527
struct uprobe_dispatch_data udd;
15191528
struct uprobe_cpu_buffer *ucb;
1520-
int dsize, esize;
15211529

15221530
tu = container_of(con, struct trace_uprobe, consumer);
15231531

@@ -1529,18 +1537,13 @@ static int uretprobe_dispatcher(struct uprobe_consumer *con,
15291537
if (WARN_ON_ONCE(!uprobe_cpu_buffer))
15301538
return 0;
15311539

1532-
dsize = __get_data_size(&tu->tp, regs);
1533-
esize = SIZEOF_TRACE_ENTRY(is_ret_probe(tu));
1534-
1535-
ucb = uprobe_buffer_get();
1536-
store_trace_args(ucb->buf, &tu->tp, regs, esize, dsize);
1537-
1540+
ucb = prepare_uprobe_buffer(tu, regs);
15381541
if (trace_probe_test_flag(&tu->tp, TP_FLAG_TRACE))
1539-
uretprobe_trace_func(tu, func, regs, ucb, dsize);
1542+
uretprobe_trace_func(tu, func, regs, ucb);
15401543

15411544
#ifdef CONFIG_PERF_EVENTS
15421545
if (trace_probe_test_flag(&tu->tp, TP_FLAG_PROFILE))
1543-
uretprobe_perf_func(tu, func, regs, ucb, dsize);
1546+
uretprobe_perf_func(tu, func, regs, ucb);
15441547
#endif
15451548
uprobe_buffer_put(ucb);
15461549
return 0;

0 commit comments

Comments
 (0)