| @@ -1371,33 +1371,33 @@ static DECLARE_BITMAP(enabled_perf_exit_syscalls, NR_syscalls); · 1370 unmodified lines |
| 1371 | 1371 | static int sys_perf_refcount_enter; |
| 1372 | 1372 | static int sys_perf_refcount_exit; |
| 1373 | 1373 | |
| 1374 | | −static int perf_call_bpf_enter(struct trace_event_call *call, struct pt_regs *regs, |
| 1374 | +static int perf_call_bpf_enter(struct trace_event_call *call, |
| 1375 | 1375 | struct syscall_metadata *sys_data, |
| 1376 | | − struct syscall_trace_enter *rec) |
| 1376 | + int syscall_nr, unsigned long *args) |
| 1377 | 1377 | { |
| 1378 | 1378 | struct syscall_tp_t { |
| 1379 | 1379 | struct trace_entry ent; |
| 1380 | 1380 | int syscall_nr; |
| 1381 | 1381 | unsigned long args[SYSCALL_DEFINE_MAXARGS]; |
| 1382 | 1382 | } __aligned(8) param; |
| 1383 | + struct pt_regs regs = {}; |
| 1383 | 1384 | int i; |
| 1384 | 1385 | |
| 1385 | 1386 | BUILD_BUG_ON(sizeof(param.ent) < sizeof(void *)); |
| 1386 | 1387 | |
| 1387 | | − /* bpf prog requires 'regs' to be the first member in the ctx (a.k.a. ¶m) */ |
| 1388 | | − perf_fetch_caller_regs(regs); |
| 1389 | | − *(struct pt_regs **)¶m = regs; |
| 1390 | | − param.syscall_nr = rec->nr; |
| 1388 | + /* bpf prog requires 'regs' to be the first member in the ctx */ |
| 1389 | + perf_fetch_caller_regs(®s); |
| 1390 | + *(struct pt_regs **)¶m = ®s; |
| 1391 | + param.syscall_nr = syscall_nr; |
| 1391 | 1392 | for (i = 0; i < sys_data->nb_args; i++) |
| 1392 | | − param.args[i] = rec->args[i]; |
| 1393 | | − return trace_call_bpf(call, ¶m); |
| 1393 | + param.args[i] = args[i]; |
| 1394 | + return trace_call_bpf_faultable(call, ¶m); |
| 1394 | 1395 | } |
| 1395 | 1396 | |
| 1396 | 1397 | static void perf_syscall_enter(void *ignore, struct pt_regs *regs, long id) |
| 1397 | 1398 | { |
| 1398 | 1399 | struct syscall_metadata *sys_data; |
| 1399 | 1400 | struct syscall_trace_enter *rec; |
| 1400 | | − struct pt_regs *fake_regs; |
| 1401 | 1401 | struct hlist_head *head; |
| 1402 | 1402 | unsigned long args[6]; |
| 1403 | 1403 | bool valid_prog_array; |
| @@ -1410,12 +1410,7 @@ static void perf_syscall_enter(void *ignore, struct pt_regs *regs, long id) · 6 unmodified lines |
| 1410 | 1410 | int size = 0; |
| 1411 | 1411 | int uargs = 0; |
| 1412 | 1412 | |
| 1413 | | − /* |
| 1414 | | − * Syscall probe called with preemption enabled, but the ring |
| 1415 | | − * buffer and per-cpu data require preemption to be disabled. |
| 1416 | | − */ |
| 1417 | 1413 | might_fault(); |
| 1418 | | − guard(preempt_notrace)(); |
| 1419 | 1414 | |
| 1420 | 1415 | syscall_nr = trace_get_syscall_nr(current, regs); |
| 1421 | 1416 | if (syscall_nr < 0 || syscall_nr >= NR_syscalls) |
| @@ -1429,6 +1424,26 @@ static void perf_syscall_enter(void *ignore, struct pt_regs *regs, long id) · 7 unmodified lines |
| 1429 | 1424 | |
| 1430 | 1425 | syscall_get_arguments(current, regs, args); |
| 1431 | 1426 | |
| 1427 | + /* |
| 1428 | + * Run BPF program in faultable context before per-cpu buffer |
| 1429 | + * allocation, allowing sleepable BPF programs to execute. |
| 1430 | + */ |
| 1431 | + valid_prog_array = bpf_prog_array_valid(sys_data->enter_event); |
| 1432 | + if (valid_prog_array && |
| 1433 | + !perf_call_bpf_enter(sys_data->enter_event, sys_data, |
| 1434 | + syscall_nr, args)) |
| 1435 | + return; |
| 1436 | + |
| 1437 | + /* |
| 1438 | + * Per-cpu ring buffer and perf event list operations require |
| 1439 | + * preemption to be disabled. |
| 1440 | + */ |
| 1441 | + guard(preempt_notrace)(); |
| 1442 | + |
| 1443 | + head = this_cpu_ptr(sys_data->enter_event->perf_events); |
| 1444 | + if (hlist_empty(head)) |
| 1445 | + return; |
| 1446 | + |
| 1432 | 1447 | /* Check if this syscall event faults in user space memory */ |
| 1433 | 1448 | mayfault = sys_data->user_mask != 0; |
| 1434 | 1449 | |
| @@ -1438,17 +1453,12 @@ static void perf_syscall_enter(void *ignore, struct pt_regs *regs, long id) · 3 unmodified lines |
| 1438 | 1453 | return; |
| 1439 | 1454 | } |
| 1440 | 1455 | |
| 1441 | | − head = this_cpu_ptr(sys_data->enter_event->perf_events); |
| 1442 | | − valid_prog_array = bpf_prog_array_valid(sys_data->enter_event); |
| 1443 | | − if (!valid_prog_array && hlist_empty(head)) |
| 1444 | | − return; |
| 1445 | | − |
| 1446 | 1456 | /* get the size after alignment with the u32 buffer size field */ |
| 1447 | 1457 | size += sizeof(unsigned long) * sys_data->nb_args + sizeof(*rec); |
| 1448 | 1458 | size = ALIGN(size + sizeof(u32), sizeof(u64)); |
| 1449 | 1459 | size -= sizeof(u32); |
| 1450 | 1460 | |
| 1451 | | − rec = perf_trace_buf_alloc(size, &fake_regs, &rctx); |
| 1461 | + rec = perf_trace_buf_alloc(size, NULL, &rctx); |
| 1452 | 1462 | if (!rec) |
| 1453 | 1463 | return; |
| 1454 | 1464 | |
| @@ -1458,13 +1468,6 @@ static void perf_syscall_enter(void *ignore, struct pt_regs *regs, long id) · 3 unmodified lines |
| 1458 | 1468 | if (mayfault) |
| 1459 | 1469 | syscall_put_data(sys_data, rec, user_ptr, size, user_sizes, uargs); |
| 1460 | 1470 | |
| 1461 | | − if ((valid_prog_array && |
| 1462 | | − !perf_call_bpf_enter(sys_data->enter_event, fake_regs, sys_data, rec)) || |
| 1463 | | − hlist_empty(head)) { |
| 1464 | | − perf_swevent_put_recursion_context(rctx); |
| 1465 | | − return; |
| 1466 | | − } |
| 1467 | | − |
| 1468 | 1471 | perf_trace_buf_submit(rec, size, rctx, |
| 1469 | 1472 | sys_data->enter_event->event.type, 1, regs, |
| 1470 | 1473 | head, NULL); |
| @@ -1514,40 +1517,35 @@ static void perf_sysenter_disable(struct trace_event_call *call) · 43 unmodified lines |
| 1514 | 1517 | syscall_fault_buffer_disable(); |
| 1515 | 1518 | } |
| 1516 | 1519 | |
| 1517 | | −static int perf_call_bpf_exit(struct trace_event_call *call, struct pt_regs *regs, |
| 1518 | | − struct syscall_trace_exit *rec) |
| 1520 | +static int perf_call_bpf_exit(struct trace_event_call *call, |
| 1521 | + int syscall_nr, long ret_val) |
| 1519 | 1522 | { |
| 1520 | 1523 | struct syscall_tp_t { |
| 1521 | 1524 | struct trace_entry ent; |
| 1522 | 1525 | int syscall_nr; |
| 1523 | 1526 | unsigned long ret; |
| 1524 | 1527 | } __aligned(8) param; |
| 1525 | | − |
| 1526 | | − /* bpf prog requires 'regs' to be the first member in the ctx (a.k.a. ¶m) */ |
| 1527 | | − perf_fetch_caller_regs(regs); |
| 1528 | | − *(struct pt_regs **)¶m = regs; |
| 1529 | | − param.syscall_nr = rec->nr; |
| 1530 | | − param.ret = rec->ret; |
| 1531 | | − return trace_call_bpf(call, ¶m); |
| 1528 | + struct pt_regs regs = {}; |
| 1529 | + |
| 1530 | + /* bpf prog requires 'regs' to be the first member in the ctx */ |
| 1531 | + perf_fetch_caller_regs(®s); |
| 1532 | + *(struct pt_regs **)¶m = ®s; |
| 1533 | + param.syscall_nr = syscall_nr; |
| 1534 | + param.ret = ret_val; |
| 1535 | + return trace_call_bpf_faultable(call, ¶m); |
| 1532 | 1536 | } |
| 1533 | 1537 | |
| 1534 | 1538 | static void perf_syscall_exit(void *ignore, struct pt_regs *regs, long ret) |
| 1535 | 1539 | { |
| 1536 | 1540 | struct syscall_metadata *sys_data; |
| 1537 | 1541 | struct syscall_trace_exit *rec; |
| 1538 | | − struct pt_regs *fake_regs; |
| 1539 | 1542 | struct hlist_head *head; |
| 1540 | 1543 | bool valid_prog_array; |
| 1541 | 1544 | int syscall_nr; |
| 1542 | 1545 | int rctx; |
| 1543 | 1546 | int size; |
| 1544 | 1547 | |
| 1545 | | − /* |
| 1546 | | − * Syscall probe called with preemption enabled, but the ring |
| 1547 | | − * buffer and per-cpu data require preemption to be disabled. |
| 1548 | | − */ |
| 1549 | 1548 | might_fault(); |
| 1550 | | − guard(preempt_notrace)(); |
| 1551 | 1549 | |
| 1552 | 1550 | syscall_nr = trace_get_syscall_nr(current, regs); |
| 1553 | 1551 | if (syscall_nr < 0 || syscall_nr >= NR_syscalls) |
| @@ -1559,29 +1557,37 @@ static void perf_syscall_exit(void *ignore, struct pt_regs *regs, long ret) · 5 unmodified lines |
| 1559 | 1557 | if (!sys_data) |
| 1560 | 1558 | return; |
| 1561 | 1559 | |
| 1562 | | − head = this_cpu_ptr(sys_data->exit_event->perf_events); |
| 1560 | + /* |
| 1561 | + * Run BPF program in faultable context before per-cpu buffer |
| 1562 | + * allocation, allowing sleepable BPF programs to execute. |
| 1563 | + */ |
| 1563 | 1564 | valid_prog_array = bpf_prog_array_valid(sys_data->exit_event); |
| 1564 | | − if (!valid_prog_array && hlist_empty(head)) |
| 1565 | + if (valid_prog_array && |
| 1566 | + !perf_call_bpf_exit(sys_data->exit_event, syscall_nr, |
| 1567 | + syscall_get_return_value(current, regs))) |
| 1568 | + return; |
| 1569 | + |
| 1570 | + /* |
| 1571 | + * Per-cpu ring buffer and perf event list operations require |
| 1572 | + * preemption to be disabled. |
| 1573 | + */ |
| 1574 | + guard(preempt_notrace)(); |
| 1575 | + |
| 1576 | + head = this_cpu_ptr(sys_data->exit_event->perf_events); |
| 1577 | + if (hlist_empty(head)) |
| 1565 | 1578 | return; |
| 1566 | 1579 | |
| 1567 | 1580 | /* We can probably do that at build time */ |
| 1568 | 1581 | size = ALIGN(sizeof(*rec) + sizeof(u32), sizeof(u64)); |
| 1569 | 1582 | size -= sizeof(u32); |
| 1570 | 1583 | |
| 1571 | | − rec = perf_trace_buf_alloc(size, &fake_regs, &rctx); |
| 1584 | + rec = perf_trace_buf_alloc(size, NULL, &rctx); |
| 1572 | 1585 | if (!rec) |
| 1573 | 1586 | return; |
| 1574 | 1587 | |
| 1575 | 1588 | rec->nr = syscall_nr; |
| 1576 | 1589 | rec->ret = syscall_get_return_value(current, regs); |
| 1577 | 1590 | |
| 1578 | | − if ((valid_prog_array && |
| 1579 | | − !perf_call_bpf_exit(sys_data->exit_event, fake_regs, rec)) || |
| 1580 | | − hlist_empty(head)) { |
| 1581 | | − perf_swevent_put_recursion_context(rctx); |
| 1582 | | − return; |
| 1583 | | − } |
| 1584 | | − |
| 1585 | 1591 | perf_trace_buf_submit(rec, size, rctx, sys_data->exit_event->event.type, |
| 1586 | 1592 | 1, regs, head, NULL); |
| 1587 | 1593 | } |