Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'bpf-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf

Pull bpf fixes from Alexei Starovoitov:

- Fix BPF builds due to -fms-extensions. selftests (Alexei
Starovoitov), bpftool (Quentin Monnet).

- Fix build of net/smc when CONFIG_BPF_SYSCALL=y, but CONFIG_BPF_JIT=n
(Geert Uytterhoeven)

- Fix livepatch/BPF interaction and support reliable unwinding through
BPF stack frames (Josh Poimboeuf)

- Do not audit capability check in arm64 JIT (Ondrej Mosnacek)

- Fix truncated dmabuf BPF iterator reads (T.J. Mercier)

- Fix verifier assumptions of bpf_d_path's output buffer (Shuran Liu)

- Fix warnings in libbpf when built with -Wdiscarded-qualifiers under
C23 (Mikhail Gavrilov)

* tag 'bpf-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf:
selftests/bpf: add regression test for bpf_d_path()
bpf: Fix verifier assumptions of bpf_d_path's output buffer
selftests/bpf: Add test for truncated dmabuf_iter reads
bpf: Fix truncated dmabuf iterator reads
x86/unwind/orc: Support reliable unwinding through BPF stack frames
bpf: Add bpf_has_frame_pointer()
bpf, arm64: Do not audit capability check in do_jit()
libbpf: Fix -Wdiscarded-qualifiers under C23
bpftool: Fix build warnings due to MS extensions
net: smc: SMC_HS_CTRL_BPF should depend on BPF_JIT
selftests/bpf: Add -fms-extensions to bpf build flags

+256 -48
+1 -1
arch/arm64/net/bpf_jit_comp.c
··· 1004 1004 arm64_get_spectre_v2_state() == SPECTRE_VULNERABLE) 1005 1005 return; 1006 1006 1007 - if (capable(CAP_SYS_ADMIN)) 1007 + if (ns_capable_noaudit(&init_user_ns, CAP_SYS_ADMIN)) 1008 1008 return; 1009 1009 1010 1010 if (supports_clearbhb(SCOPE_SYSTEM)) {
+27 -12
arch/x86/kernel/unwind_orc.c
··· 2 2 #include <linux/objtool.h> 3 3 #include <linux/module.h> 4 4 #include <linux/sort.h> 5 + #include <linux/bpf.h> 5 6 #include <asm/ptrace.h> 6 7 #include <asm/stacktrace.h> 7 8 #include <asm/unwind.h> ··· 173 172 } 174 173 #endif 175 174 175 + /* Fake frame pointer entry -- used as a fallback for generated code */ 176 + static struct orc_entry orc_fp_entry = { 177 + .type = ORC_TYPE_CALL, 178 + .sp_reg = ORC_REG_BP, 179 + .sp_offset = 16, 180 + .bp_reg = ORC_REG_PREV_SP, 181 + .bp_offset = -16, 182 + }; 183 + 184 + static struct orc_entry *orc_bpf_find(unsigned long ip) 185 + { 186 + #ifdef CONFIG_BPF_JIT 187 + if (bpf_has_frame_pointer(ip)) 188 + return &orc_fp_entry; 189 + #endif 190 + 191 + return NULL; 192 + } 193 + 176 194 /* 177 195 * If we crash with IP==0, the last successfully executed instruction 178 196 * was probably an indirect function call with a NULL function pointer, ··· 204 184 .sp_reg = ORC_REG_SP, 205 185 .bp_reg = ORC_REG_UNDEFINED, 206 186 .type = ORC_TYPE_CALL 207 - }; 208 - 209 - /* Fake frame pointer entry -- used as a fallback for generated code */ 210 - static struct orc_entry orc_fp_entry = { 211 - .type = ORC_TYPE_CALL, 212 - .sp_reg = ORC_REG_BP, 213 - .sp_offset = 16, 214 - .bp_reg = ORC_REG_PREV_SP, 215 - .bp_offset = -16, 216 187 }; 217 188 218 189 static struct orc_entry *orc_find(unsigned long ip) ··· 246 235 247 236 /* Module lookup: */ 248 237 orc = orc_module_find(ip); 238 + if (orc) 239 + return orc; 240 + 241 + /* BPF lookup: */ 242 + orc = orc_bpf_find(ip); 249 243 if (orc) 250 244 return orc; 251 245 ··· 511 495 if (!orc) { 512 496 /* 513 497 * As a fallback, try to assume this code uses a frame pointer. 514 - * This is useful for generated code, like BPF, which ORC 515 - * doesn't know about. This is just a guess, so the rest of 516 - * the unwind is no longer considered reliable. 498 + * This is just a guess, so the rest of the unwind is no longer 499 + * considered reliable. 517 500 */ 518 501 orc = &orc_fp_entry; 519 502 state->error = true;
+12
arch/x86/net/bpf_jit_comp.c
··· 1678 1678 emit_prologue(&prog, image, stack_depth, 1679 1679 bpf_prog_was_classic(bpf_prog), tail_call_reachable, 1680 1680 bpf_is_subprog(bpf_prog), bpf_prog->aux->exception_cb); 1681 + 1682 + bpf_prog->aux->ksym.fp_start = prog - temp; 1683 + 1681 1684 /* Exception callback will clobber callee regs for its own use, and 1682 1685 * restore the original callee regs from main prog's stack frame. 1683 1686 */ ··· 2739 2736 pop_r12(&prog); 2740 2737 } 2741 2738 EMIT1(0xC9); /* leave */ 2739 + bpf_prog->aux->ksym.fp_end = prog - temp; 2740 + 2742 2741 emit_return(&prog, image + addrs[i - 1] + (prog - temp)); 2743 2742 break; 2744 2743 ··· 3330 3325 } 3331 3326 EMIT1(0x55); /* push rbp */ 3332 3327 EMIT3(0x48, 0x89, 0xE5); /* mov rbp, rsp */ 3328 + if (im) 3329 + im->ksym.fp_start = prog - (u8 *)rw_image; 3330 + 3333 3331 if (!is_imm8(stack_size)) { 3334 3332 /* sub rsp, stack_size */ 3335 3333 EMIT3_off32(0x48, 0x81, 0xEC, stack_size); ··· 3470 3462 emit_ldx(&prog, BPF_DW, BPF_REG_0, BPF_REG_FP, -8); 3471 3463 3472 3464 emit_ldx(&prog, BPF_DW, BPF_REG_6, BPF_REG_FP, -rbx_off); 3465 + 3473 3466 EMIT1(0xC9); /* leave */ 3467 + if (im) 3468 + im->ksym.fp_end = prog - (u8 *)rw_image; 3469 + 3474 3470 if (flags & BPF_TRAMP_F_SKIP_FRAME) { 3475 3471 /* skip our return address and return to parent */ 3476 3472 EMIT4(0x48, 0x83, 0xC4, 8); /* add rsp, 8 */
+3
include/linux/bpf.h
··· 1283 1283 struct list_head lnode; 1284 1284 struct latch_tree_node tnode; 1285 1285 bool prog; 1286 + u32 fp_start; 1287 + u32 fp_end; 1286 1288 }; 1287 1289 1288 1290 enum bpf_tramp_prog_type { ··· 1513 1511 void bpf_image_ksym_del(struct bpf_ksym *ksym); 1514 1512 void bpf_ksym_add(struct bpf_ksym *ksym); 1515 1513 void bpf_ksym_del(struct bpf_ksym *ksym); 1514 + bool bpf_has_frame_pointer(unsigned long ip); 1516 1515 int bpf_jit_charge_modmem(u32 size); 1517 1516 void bpf_jit_uncharge_modmem(u32 size); 1518 1517 bool bpf_prog_has_trampoline(const struct bpf_prog *prog);
+16
kernel/bpf/core.c
··· 760 760 NULL; 761 761 } 762 762 763 + bool bpf_has_frame_pointer(unsigned long ip) 764 + { 765 + struct bpf_ksym *ksym; 766 + unsigned long offset; 767 + 768 + guard(rcu)(); 769 + 770 + ksym = bpf_ksym_find(ip); 771 + if (!ksym || !ksym->fp_start || !ksym->fp_end) 772 + return false; 773 + 774 + offset = ip - ksym->start; 775 + 776 + return offset >= ksym->fp_start && offset < ksym->fp_end; 777 + } 778 + 763 779 const struct exception_table_entry *search_bpf_extables(unsigned long addr) 764 780 { 765 781 const struct exception_table_entry *e = NULL;
+49 -7
kernel/bpf/dmabuf_iter.c
··· 6 6 #include <linux/kernel.h> 7 7 #include <linux/seq_file.h> 8 8 9 + struct dmabuf_iter_priv { 10 + /* 11 + * If this pointer is non-NULL, the buffer's refcount is elevated to 12 + * prevent destruction between stop/start. If reading is not resumed and 13 + * start is never called again, then dmabuf_iter_seq_fini drops the 14 + * reference when the iterator is released. 15 + */ 16 + struct dma_buf *dmabuf; 17 + }; 18 + 9 19 static void *dmabuf_iter_seq_start(struct seq_file *seq, loff_t *pos) 10 20 { 11 - if (*pos) 12 - return NULL; 21 + struct dmabuf_iter_priv *p = seq->private; 22 + 23 + if (*pos) { 24 + struct dma_buf *dmabuf = p->dmabuf; 25 + 26 + if (!dmabuf) 27 + return NULL; 28 + 29 + /* 30 + * Always resume from where we stopped, regardless of the value 31 + * of pos. 32 + */ 33 + p->dmabuf = NULL; 34 + return dmabuf; 35 + } 13 36 14 37 return dma_buf_iter_begin(); 15 38 } ··· 77 54 { 78 55 struct dma_buf *dmabuf = v; 79 56 80 - if (dmabuf) 81 - dma_buf_put(dmabuf); 57 + if (dmabuf) { 58 + struct dmabuf_iter_priv *p = seq->private; 59 + 60 + p->dmabuf = dmabuf; 61 + } 82 62 } 83 63 84 64 static const struct seq_operations dmabuf_iter_seq_ops = { ··· 97 71 seq_puts(seq, "dmabuf iter\n"); 98 72 } 99 73 74 + static int dmabuf_iter_seq_init(void *priv, struct bpf_iter_aux_info *aux) 75 + { 76 + struct dmabuf_iter_priv *p = (struct dmabuf_iter_priv *)priv; 77 + 78 + p->dmabuf = NULL; 79 + return 0; 80 + } 81 + 82 + static void dmabuf_iter_seq_fini(void *priv) 83 + { 84 + struct dmabuf_iter_priv *p = (struct dmabuf_iter_priv *)priv; 85 + 86 + if (p->dmabuf) 87 + dma_buf_put(p->dmabuf); 88 + } 89 + 100 90 static const struct bpf_iter_seq_info dmabuf_iter_seq_info = { 101 91 .seq_ops = &dmabuf_iter_seq_ops, 102 - .init_seq_private = NULL, 103 - .fini_seq_private = NULL, 104 - .seq_priv_size = 0, 92 + .init_seq_private = dmabuf_iter_seq_init, 93 + .fini_seq_private = dmabuf_iter_seq_fini, 94 + .seq_priv_size = sizeof(struct dmabuf_iter_priv), 105 95 }; 106 96 107 97 static struct bpf_iter_reg bpf_dmabuf_reg_info = {
+1 -1
kernel/trace/bpf_trace.c
··· 965 965 .ret_type = RET_INTEGER, 966 966 .arg1_type = ARG_PTR_TO_BTF_ID, 967 967 .arg1_btf_id = &bpf_d_path_btf_ids[0], 968 - .arg2_type = ARG_PTR_TO_MEM, 968 + .arg2_type = ARG_PTR_TO_MEM | MEM_WRITE, 969 969 .arg3_type = ARG_CONST_SIZE_OR_ZERO, 970 970 .allowed = bpf_d_path_allowed, 971 971 };
+1 -1
net/smc/Kconfig
··· 22 22 23 23 config SMC_HS_CTRL_BPF 24 24 bool "Generic eBPF hook for SMC handshake flow" 25 - depends on SMC && BPF_SYSCALL 25 + depends on SMC && BPF_JIT && BPF_SYSCALL 26 26 default y 27 27 help 28 28 SMC_HS_CTRL_BPF enables support to register generic eBPF hook for SMC
+2
tools/bpf/bpftool/Makefile
··· 224 224 225 225 $(OUTPUT)%.bpf.o: skeleton/%.bpf.c $(OUTPUT)vmlinux.h $(LIBBPF_BOOTSTRAP) 226 226 $(QUIET_CLANG)$(CLANG) \ 227 + -Wno-microsoft-anon-tag \ 228 + -fms-extensions \ 227 229 -I$(or $(OUTPUT),.) \ 228 230 -I$(srctree)/tools/include/uapi/ \ 229 231 -I$(LIBBPF_BOOTSTRAP_INCLUDE) \
+4 -3
tools/lib/bpf/libbpf.c
··· 8484 8484 struct bpf_object *obj = ctx; 8485 8485 const struct btf_type *t; 8486 8486 struct extern_desc *ext; 8487 - char *res; 8487 + const char *res; 8488 8488 8489 8489 res = strstr(sym_name, ".llvm."); 8490 8490 if (sym_type == 'd' && res) ··· 11818 11818 * 11819 11819 * [0] fb6a421fb615 ("kallsyms: Match symbols exactly with CONFIG_LTO_CLANG") 11820 11820 */ 11821 - char sym_trim[256], *psym_trim = sym_trim, *sym_sfx; 11821 + char sym_trim[256], *psym_trim = sym_trim; 11822 + const char *sym_sfx; 11822 11823 11823 11824 if (!(sym_sfx = strstr(sym_name, ".llvm."))) 11824 11825 return 0; ··· 12402 12401 if (!search_paths[i]) 12403 12402 continue; 12404 12403 for (s = search_paths[i]; s != NULL; s = strchr(s, ':')) { 12405 - char *next_path; 12404 + const char *next_path; 12406 12405 int seg_len; 12407 12406 12408 12407 if (s[0] == ':')
+2
tools/testing/selftests/bpf/Makefile
··· 437 437 -I$(abspath $(OUTPUT)/../usr/include) \ 438 438 -std=gnu11 \ 439 439 -fno-strict-aliasing \ 440 + -Wno-microsoft-anon-tag \ 441 + -fms-extensions \ 440 442 -Wno-compare-distinct-pointer-types \ 441 443 -Wno-initializer-overrides \ 442 444 #
+73 -18
tools/testing/selftests/bpf/prog_tests/d_path.c
··· 38 38 return readlink(buf, src.paths[src.cnt++], MAX_PATH_LEN); 39 39 } 40 40 41 + static inline long syscall_close(int fd) 42 + { 43 + return syscall(__NR_close_range, 44 + (unsigned int)fd, 45 + (unsigned int)fd, 46 + 0u); 47 + } 48 + 41 49 static int trigger_fstat_events(pid_t pid) 42 50 { 43 51 int sockfd = -1, procfd = -1, devfd = -1; ··· 112 104 /* sys_close no longer triggers filp_close, but we can 113 105 * call sys_close_range instead which still does 114 106 */ 115 - #define close(fd) syscall(__NR_close_range, fd, fd, 0) 116 - 117 - close(pipefd[0]); 118 - close(pipefd[1]); 119 - close(sockfd); 120 - close(procfd); 121 - close(devfd); 122 - close(localfd); 123 - close(indicatorfd); 124 - 125 - #undef close 107 + syscall_close(pipefd[0]); 108 + syscall_close(pipefd[1]); 109 + syscall_close(sockfd); 110 + syscall_close(procfd); 111 + syscall_close(devfd); 112 + syscall_close(localfd); 113 + syscall_close(indicatorfd); 126 114 return ret; 115 + } 116 + 117 + static void attach_and_load(struct test_d_path **skel) 118 + { 119 + int err; 120 + 121 + *skel = test_d_path__open_and_load(); 122 + if (CHECK(!*skel, "setup", "d_path skeleton failed\n")) 123 + goto cleanup; 124 + 125 + err = test_d_path__attach(*skel); 126 + if (CHECK(err, "setup", "attach failed: %d\n", err)) 127 + goto cleanup; 128 + 129 + (*skel)->bss->my_pid = getpid(); 130 + return; 131 + 132 + cleanup: 133 + test_d_path__destroy(*skel); 134 + *skel = NULL; 127 135 } 128 136 129 137 static void test_d_path_basic(void) ··· 148 124 struct test_d_path *skel; 149 125 int err; 150 126 151 - skel = test_d_path__open_and_load(); 152 - if (CHECK(!skel, "setup", "d_path skeleton failed\n")) 153 - goto cleanup; 154 - 155 - err = test_d_path__attach(skel); 156 - if (CHECK(err, "setup", "attach failed: %d\n", err)) 127 + attach_and_load(&skel); 128 + if (!skel) 157 129 goto cleanup; 158 130 159 131 bss = skel->bss; 160 - bss->my_pid = getpid(); 161 132 162 133 err = trigger_fstat_events(bss->my_pid); 163 134 if (err < 0) ··· 214 195 test_d_path_check_types__destroy(skel); 215 196 } 216 197 198 + /* Check if the verifier correctly generates code for 199 + * accessing the memory modified by d_path helper. 200 + */ 201 + static void test_d_path_mem_access(void) 202 + { 203 + int localfd = -1; 204 + char path_template[] = "/dev/shm/d_path_loadgen.XXXXXX"; 205 + struct test_d_path__bss *bss; 206 + struct test_d_path *skel; 207 + 208 + attach_and_load(&skel); 209 + if (!skel) 210 + goto cleanup; 211 + 212 + bss = skel->bss; 213 + 214 + localfd = mkstemp(path_template); 215 + if (CHECK(localfd < 0, "trigger", "mkstemp failed\n")) 216 + goto cleanup; 217 + 218 + if (CHECK(fallocate(localfd, 0, 0, 1024) < 0, "trigger", "fallocate failed\n")) 219 + goto cleanup; 220 + remove(path_template); 221 + 222 + if (CHECK(!bss->path_match_fallocate, "check", 223 + "failed to read fallocate path")) 224 + goto cleanup; 225 + 226 + cleanup: 227 + syscall_close(localfd); 228 + test_d_path__destroy(skel); 229 + } 230 + 217 231 void test_d_path(void) 218 232 { 219 233 if (test__start_subtest("basic")) ··· 257 205 258 206 if (test__start_subtest("check_alloc_mem")) 259 207 test_d_path_check_types(); 208 + 209 + if (test__start_subtest("check_mem_access")) 210 + test_d_path_mem_access(); 260 211 }
+42 -5
tools/testing/selftests/bpf/prog_tests/dmabuf_iter.c
··· 73 73 return -1; 74 74 } 75 75 76 - static int create_sys_heap_dmabuf(void) 76 + static int create_sys_heap_dmabuf(size_t bytes) 77 77 { 78 - sysheap_test_buffer_size = 20 * getpagesize(); 79 - 80 78 struct dma_heap_allocation_data data = { 81 - .len = sysheap_test_buffer_size, 79 + .len = bytes, 82 80 .fd = 0, 83 81 .fd_flags = O_RDWR | O_CLOEXEC, 84 82 .heap_flags = 0, ··· 108 110 static int create_test_buffers(void) 109 111 { 110 112 udmabuf = create_udmabuf(); 111 - sysheap_dmabuf = create_sys_heap_dmabuf(); 113 + 114 + sysheap_test_buffer_size = 20 * getpagesize(); 115 + sysheap_dmabuf = create_sys_heap_dmabuf(sysheap_test_buffer_size); 112 116 113 117 if (udmabuf < 0 || sysheap_dmabuf < 0) 114 118 return -1; ··· 219 219 close(iter_fd); 220 220 } 221 221 222 + static void subtest_dmabuf_iter_check_lots_of_buffers(struct dmabuf_iter *skel) 223 + { 224 + int iter_fd; 225 + char buf[1024]; 226 + size_t total_bytes_read = 0; 227 + ssize_t bytes_read; 228 + 229 + iter_fd = bpf_iter_create(bpf_link__fd(skel->links.dmabuf_collector)); 230 + if (!ASSERT_OK_FD(iter_fd, "iter_create")) 231 + return; 232 + 233 + while ((bytes_read = read(iter_fd, buf, sizeof(buf))) > 0) 234 + total_bytes_read += bytes_read; 235 + 236 + ASSERT_GT(total_bytes_read, getpagesize(), "total_bytes_read"); 237 + 238 + close(iter_fd); 239 + } 240 + 241 + 222 242 static void subtest_dmabuf_iter_check_open_coded(struct dmabuf_iter *skel, int map_fd) 223 243 { 224 244 LIBBPF_OPTS(bpf_test_run_opts, topts); ··· 295 275 subtest_dmabuf_iter_check_no_infinite_reads(skel); 296 276 if (test__start_subtest("default_iter")) 297 277 subtest_dmabuf_iter_check_default_iter(skel); 278 + if (test__start_subtest("lots_of_buffers")) { 279 + size_t NUM_BUFS = 100; 280 + int buffers[NUM_BUFS]; 281 + int i; 282 + 283 + for (i = 0; i < NUM_BUFS; ++i) { 284 + buffers[i] = create_sys_heap_dmabuf(getpagesize()); 285 + if (!ASSERT_OK_FD(buffers[i], "dmabuf_fd")) 286 + goto cleanup_bufs; 287 + } 288 + 289 + subtest_dmabuf_iter_check_lots_of_buffers(skel); 290 + 291 + cleanup_bufs: 292 + for (--i; i >= 0; --i) 293 + close(buffers[i]); 294 + } 298 295 if (test__start_subtest("open_coded")) 299 296 subtest_dmabuf_iter_check_open_coded(skel, map_fd); 300 297
+23
tools/testing/selftests/bpf/progs/test_d_path.c
··· 17 17 18 18 int called_stat = 0; 19 19 int called_close = 0; 20 + int path_match_fallocate = 0; 20 21 21 22 SEC("fentry/security_inode_getattr") 22 23 int BPF_PROG(prog_stat, struct path *path, struct kstat *stat, ··· 60 59 61 60 rets_close[cnt] = ret; 62 61 cnt_close++; 62 + return 0; 63 + } 64 + 65 + SEC("fentry/vfs_fallocate") 66 + int BPF_PROG(prog_fallocate, struct file *file, int mode, loff_t offset, loff_t len) 67 + { 68 + pid_t pid = bpf_get_current_pid_tgid() >> 32; 69 + int ret = 0; 70 + char path_fallocate[MAX_PATH_LEN] = {}; 71 + 72 + if (pid != my_pid) 73 + return 0; 74 + 75 + ret = bpf_d_path(&file->f_path, 76 + path_fallocate, MAX_PATH_LEN); 77 + if (ret < 0) 78 + return 0; 79 + 80 + if (!path_fallocate[0]) 81 + return 0; 82 + 83 + path_match_fallocate = 1; 63 84 return 0; 64 85 } 65 86