From 2d63e6a3d97132449451c2f66fe24a2dc4e2938f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 21 Sep 2022 11:13:41 +0200 Subject: scripts: coccicheck: use "grep -E" instead of "egrep" The latest version of grep claims that egrep is now obsolete so the build now contains warnings that look like: egrep: warning: egrep is obsolescent; using grep -E fix this up by moving the vdso Makefile to use "grep -E" instead. Cc: Julia Lawall Cc: Nicolas Palix Cc: cocci@inria.fr Signed-off-by: Greg Kroah-Hartman --- scripts/coccicheck | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/coccicheck b/scripts/coccicheck index caba0bff6da7..2956fce8fa4f 100755 --- a/scripts/coccicheck +++ b/scripts/coccicheck @@ -47,7 +47,7 @@ FLAGS="--very-quiet" # inspected there. # # --profile will not output if --very-quiet is used, so avoid it. -echo $SPFLAGS | egrep -e "--profile|--show-trying" 2>&1 > /dev/null +echo $SPFLAGS | grep -E -e "--profile|--show-trying" 2>&1 > /dev/null if [ $? -eq 0 ]; then FLAGS="--quiet" fi -- cgit v1.2.3 From 8a76145a2ec2a81dfe34d7ac42e8c242f095e8c8 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Wed, 5 Oct 2022 21:24:51 -0700 Subject: bpf: explicitly define BPF_FUNC_xxx integer values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Historically enum bpf_func_id's BPF_FUNC_xxx enumerators relied on implicit sequential values being assigned by compiler. This is convenient, as new BPF helpers are always added at the very end, but it also has its downsides, some of them being: - with over 200 helpers now it's very hard to know what's each helper's ID, which is often important to know when working with BPF assembly (e.g., by dumping raw bpf assembly instructions with llvm-objdump -d command). it's possible to work around this by looking into vmlinux.h, dumping /sys/btf/kernel/vmlinux, looking at libbpf-provided bpf_helper_defs.h, etc. But it always feels like an unnecessary step and one should be able to quickly figure this out from UAPI header. - when backporting and cherry-picking only some BPF helpers onto older kernels it's important to be able to skip some enum values for helpers that weren't backported, but preserve absolute integer IDs to keep BPF helper IDs stable so that BPF programs stay portable across upstream and backported kernels. While neither problem is insurmountable, they come up frequently enough and are annoying enough to warrant improving the situation. And for the backporting the problem can easily go unnoticed for a while, especially if backport is done with people not very familiar with BPF subsystem overall. Anyways, it's easy to fix this by making sure that __BPF_FUNC_MAPPER macro provides explicit helper IDs. Unfortunately that would potentially break existing users that use UAPI-exposed __BPF_FUNC_MAPPER and are expected to pass macro that accepts only symbolic helper identifier (e.g., map_lookup_elem for bpf_map_lookup_elem() helper). As such, we need to introduce a new macro (___BPF_FUNC_MAPPER) which would specify both identifier and integer ID, but in such a way as to allow existing __BPF_FUNC_MAPPER be expressed in terms of new ___BPF_FUNC_MAPPER macro. And that's what this patch is doing. To avoid duplication and allow __BPF_FUNC_MAPPER stay *exactly* the same, ___BPF_FUNC_MAPPER accepts arbitrary "context" arguments, which can be used to pass any extra macros, arguments, and whatnot. In our case we use this to pass original user-provided macro that expects single argument and __BPF_FUNC_MAPPER is using it's own three-argument __BPF_FUNC_MAPPER_APPLY intermediate macro to impedance-match new and old "callback" macros. Once we resolve this, we use new ___BPF_FUNC_MAPPER to define enum bpf_func_id with explicit values. The other users of __BPF_FUNC_MAPPER in kernel (namely in kernel/bpf/disasm.c) are kept exactly the same both as demonstration that backwards compat works, but also to avoid unnecessary code churn. Note that new ___BPF_FUNC_MAPPER() doesn't forcefully insert comma between values, as that might not be appropriate in all possible cases where ___BPF_FUNC_MAPPER might be used by users. This doesn't reduce usability, as it's trivial to insert that comma inside "callback" macro. To validate all the manually specified IDs are exactly right, we used BTF to compare before and after values: $ bpftool btf dump file ~/linux-build/default/vmlinux | rg bpf_func_id -A 211 > after.txt $ git stash # stach UAPI changes $ make -j90 ... re-building kernel without UAPI changes ... $ bpftool btf dump file ~/linux-build/default/vmlinux | rg bpf_func_id -A 211 > before.txt $ diff -u before.txt after.txt --- before.txt 2022-10-05 10:48:18.119195916 -0700 +++ after.txt 2022-10-05 10:46:49.446615025 -0700 @@ -1,4 +1,4 @@ -[14576] ENUM 'bpf_func_id' encoding=UNSIGNED size=4 vlen=211 +[9560] ENUM 'bpf_func_id' encoding=UNSIGNED size=4 vlen=211 'BPF_FUNC_unspec' val=0 'BPF_FUNC_map_lookup_elem' val=1 'BPF_FUNC_map_update_elem' val=2 As can be seen from diff above, the only thing that changed was resulting BTF type ID of ENUM bpf_func_id, not any of the enumerators, their names or integer values. The only other place that needed fixing was scripts/bpf_doc.py used to generate man pages and bpf_helper_defs.h header for libbpf and selftests. That script is tightly-coupled to exact shape of ___BPF_FUNC_MAPPER macro definition, so had to be trivially adapted. Cc: Quentin Monnet Reported-by: Andrea Terzolo Signed-off-by: Andrii Nakryiko Reviewed-by: Quentin Monnet Acked-by: Jiri Olsa Acked-by: Toke Høiland-Jørgensen Link: https://lore.kernel.org/r/20221006042452.2089843-1-andrii@kernel.org Signed-off-by: Alexei Starovoitov --- include/uapi/linux/bpf.h | 432 +++++++++++++++++++++-------------------- scripts/bpf_doc.py | 19 +- tools/include/uapi/linux/bpf.h | 432 +++++++++++++++++++++-------------------- 3 files changed, 447 insertions(+), 436 deletions(-) (limited to 'scripts') diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 51b9aa640ad2..17f61338f8f8 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -5436,225 +5436,231 @@ union bpf_attr { * larger than the size of the ring buffer, or which cannot fit * within a struct bpf_dynptr. */ -#define __BPF_FUNC_MAPPER(FN) \ - FN(unspec), \ - FN(map_lookup_elem), \ - FN(map_update_elem), \ - FN(map_delete_elem), \ - FN(probe_read), \ - FN(ktime_get_ns), \ - FN(trace_printk), \ - FN(get_prandom_u32), \ - FN(get_smp_processor_id), \ - FN(skb_store_bytes), \ - FN(l3_csum_replace), \ - FN(l4_csum_replace), \ - FN(tail_call), \ - FN(clone_redirect), \ - FN(get_current_pid_tgid), \ - FN(get_current_uid_gid), \ - FN(get_current_comm), \ - FN(get_cgroup_classid), \ - FN(skb_vlan_push), \ - FN(skb_vlan_pop), \ - FN(skb_get_tunnel_key), \ - FN(skb_set_tunnel_key), \ - FN(perf_event_read), \ - FN(redirect), \ - FN(get_route_realm), \ - FN(perf_event_output), \ - FN(skb_load_bytes), \ - FN(get_stackid), \ - FN(csum_diff), \ - FN(skb_get_tunnel_opt), \ - FN(skb_set_tunnel_opt), \ - FN(skb_change_proto), \ - FN(skb_change_type), \ - FN(skb_under_cgroup), \ - FN(get_hash_recalc), \ - FN(get_current_task), \ - FN(probe_write_user), \ - FN(current_task_under_cgroup), \ - FN(skb_change_tail), \ - FN(skb_pull_data), \ - FN(csum_update), \ - FN(set_hash_invalid), \ - FN(get_numa_node_id), \ - FN(skb_change_head), \ - FN(xdp_adjust_head), \ - FN(probe_read_str), \ - FN(get_socket_cookie), \ - FN(get_socket_uid), \ - FN(set_hash), \ - FN(setsockopt), \ - FN(skb_adjust_room), \ - FN(redirect_map), \ - FN(sk_redirect_map), \ - FN(sock_map_update), \ - FN(xdp_adjust_meta), \ - FN(perf_event_read_value), \ - FN(perf_prog_read_value), \ - FN(getsockopt), \ - FN(override_return), \ - FN(sock_ops_cb_flags_set), \ - FN(msg_redirect_map), \ - FN(msg_apply_bytes), \ - FN(msg_cork_bytes), \ - FN(msg_pull_data), \ - FN(bind), \ - FN(xdp_adjust_tail), \ - FN(skb_get_xfrm_state), \ - FN(get_stack), \ - FN(skb_load_bytes_relative), \ - FN(fib_lookup), \ - FN(sock_hash_update), \ - FN(msg_redirect_hash), \ - FN(sk_redirect_hash), \ - FN(lwt_push_encap), \ - FN(lwt_seg6_store_bytes), \ - FN(lwt_seg6_adjust_srh), \ - FN(lwt_seg6_action), \ - FN(rc_repeat), \ - FN(rc_keydown), \ - FN(skb_cgroup_id), \ - FN(get_current_cgroup_id), \ - FN(get_local_storage), \ - FN(sk_select_reuseport), \ - FN(skb_ancestor_cgroup_id), \ - FN(sk_lookup_tcp), \ - FN(sk_lookup_udp), \ - FN(sk_release), \ - FN(map_push_elem), \ - FN(map_pop_elem), \ - FN(map_peek_elem), \ - FN(msg_push_data), \ - FN(msg_pop_data), \ - FN(rc_pointer_rel), \ - FN(spin_lock), \ - FN(spin_unlock), \ - FN(sk_fullsock), \ - FN(tcp_sock), \ - FN(skb_ecn_set_ce), \ - FN(get_listener_sock), \ - FN(skc_lookup_tcp), \ - FN(tcp_check_syncookie), \ - FN(sysctl_get_name), \ - FN(sysctl_get_current_value), \ - FN(sysctl_get_new_value), \ - FN(sysctl_set_new_value), \ - FN(strtol), \ - FN(strtoul), \ - FN(sk_storage_get), \ - FN(sk_storage_delete), \ - FN(send_signal), \ - FN(tcp_gen_syncookie), \ - FN(skb_output), \ - FN(probe_read_user), \ - FN(probe_read_kernel), \ - FN(probe_read_user_str), \ - FN(probe_read_kernel_str), \ - FN(tcp_send_ack), \ - FN(send_signal_thread), \ - FN(jiffies64), \ - FN(read_branch_records), \ - FN(get_ns_current_pid_tgid), \ - FN(xdp_output), \ - FN(get_netns_cookie), \ - FN(get_current_ancestor_cgroup_id), \ - FN(sk_assign), \ - FN(ktime_get_boot_ns), \ - FN(seq_printf), \ - FN(seq_write), \ - FN(sk_cgroup_id), \ - FN(sk_ancestor_cgroup_id), \ - FN(ringbuf_output), \ - FN(ringbuf_reserve), \ - FN(ringbuf_submit), \ - FN(ringbuf_discard), \ - FN(ringbuf_query), \ - FN(csum_level), \ - FN(skc_to_tcp6_sock), \ - FN(skc_to_tcp_sock), \ - FN(skc_to_tcp_timewait_sock), \ - FN(skc_to_tcp_request_sock), \ - FN(skc_to_udp6_sock), \ - FN(get_task_stack), \ - FN(load_hdr_opt), \ - FN(store_hdr_opt), \ - FN(reserve_hdr_opt), \ - FN(inode_storage_get), \ - FN(inode_storage_delete), \ - FN(d_path), \ - FN(copy_from_user), \ - FN(snprintf_btf), \ - FN(seq_printf_btf), \ - FN(skb_cgroup_classid), \ - FN(redirect_neigh), \ - FN(per_cpu_ptr), \ - FN(this_cpu_ptr), \ - FN(redirect_peer), \ - FN(task_storage_get), \ - FN(task_storage_delete), \ - FN(get_current_task_btf), \ - FN(bprm_opts_set), \ - FN(ktime_get_coarse_ns), \ - FN(ima_inode_hash), \ - FN(sock_from_file), \ - FN(check_mtu), \ - FN(for_each_map_elem), \ - FN(snprintf), \ - FN(sys_bpf), \ - FN(btf_find_by_name_kind), \ - FN(sys_close), \ - FN(timer_init), \ - FN(timer_set_callback), \ - FN(timer_start), \ - FN(timer_cancel), \ - FN(get_func_ip), \ - FN(get_attach_cookie), \ - FN(task_pt_regs), \ - FN(get_branch_snapshot), \ - FN(trace_vprintk), \ - FN(skc_to_unix_sock), \ - FN(kallsyms_lookup_name), \ - FN(find_vma), \ - FN(loop), \ - FN(strncmp), \ - FN(get_func_arg), \ - FN(get_func_ret), \ - FN(get_func_arg_cnt), \ - FN(get_retval), \ - FN(set_retval), \ - FN(xdp_get_buff_len), \ - FN(xdp_load_bytes), \ - FN(xdp_store_bytes), \ - FN(copy_from_user_task), \ - FN(skb_set_tstamp), \ - FN(ima_file_hash), \ - FN(kptr_xchg), \ - FN(map_lookup_percpu_elem), \ - FN(skc_to_mptcp_sock), \ - FN(dynptr_from_mem), \ - FN(ringbuf_reserve_dynptr), \ - FN(ringbuf_submit_dynptr), \ - FN(ringbuf_discard_dynptr), \ - FN(dynptr_read), \ - FN(dynptr_write), \ - FN(dynptr_data), \ - FN(tcp_raw_gen_syncookie_ipv4), \ - FN(tcp_raw_gen_syncookie_ipv6), \ - FN(tcp_raw_check_syncookie_ipv4), \ - FN(tcp_raw_check_syncookie_ipv6), \ - FN(ktime_get_tai_ns), \ - FN(user_ringbuf_drain), \ +#define ___BPF_FUNC_MAPPER(FN, ctx...) \ + FN(unspec, 0, ##ctx) \ + FN(map_lookup_elem, 1, ##ctx) \ + FN(map_update_elem, 2, ##ctx) \ + FN(map_delete_elem, 3, ##ctx) \ + FN(probe_read, 4, ##ctx) \ + FN(ktime_get_ns, 5, ##ctx) \ + FN(trace_printk, 6, ##ctx) \ + FN(get_prandom_u32, 7, ##ctx) \ + FN(get_smp_processor_id, 8, ##ctx) \ + FN(skb_store_bytes, 9, ##ctx) \ + FN(l3_csum_replace, 10, ##ctx) \ + FN(l4_csum_replace, 11, ##ctx) \ + FN(tail_call, 12, ##ctx) \ + FN(clone_redirect, 13, ##ctx) \ + FN(get_current_pid_tgid, 14, ##ctx) \ + FN(get_current_uid_gid, 15, ##ctx) \ + FN(get_current_comm, 16, ##ctx) \ + FN(get_cgroup_classid, 17, ##ctx) \ + FN(skb_vlan_push, 18, ##ctx) \ + FN(skb_vlan_pop, 19, ##ctx) \ + FN(skb_get_tunnel_key, 20, ##ctx) \ + FN(skb_set_tunnel_key, 21, ##ctx) \ + FN(perf_event_read, 22, ##ctx) \ + FN(redirect, 23, ##ctx) \ + FN(get_route_realm, 24, ##ctx) \ + FN(perf_event_output, 25, ##ctx) \ + FN(skb_load_bytes, 26, ##ctx) \ + FN(get_stackid, 27, ##ctx) \ + FN(csum_diff, 28, ##ctx) \ + FN(skb_get_tunnel_opt, 29, ##ctx) \ + FN(skb_set_tunnel_opt, 30, ##ctx) \ + FN(skb_change_proto, 31, ##ctx) \ + FN(skb_change_type, 32, ##ctx) \ + FN(skb_under_cgroup, 33, ##ctx) \ + FN(get_hash_recalc, 34, ##ctx) \ + FN(get_current_task, 35, ##ctx) \ + FN(probe_write_user, 36, ##ctx) \ + FN(current_task_under_cgroup, 37, ##ctx) \ + FN(skb_change_tail, 38, ##ctx) \ + FN(skb_pull_data, 39, ##ctx) \ + FN(csum_update, 40, ##ctx) \ + FN(set_hash_invalid, 41, ##ctx) \ + FN(get_numa_node_id, 42, ##ctx) \ + FN(skb_change_head, 43, ##ctx) \ + FN(xdp_adjust_head, 44, ##ctx) \ + FN(probe_read_str, 45, ##ctx) \ + FN(get_socket_cookie, 46, ##ctx) \ + FN(get_socket_uid, 47, ##ctx) \ + FN(set_hash, 48, ##ctx) \ + FN(setsockopt, 49, ##ctx) \ + FN(skb_adjust_room, 50, ##ctx) \ + FN(redirect_map, 51, ##ctx) \ + FN(sk_redirect_map, 52, ##ctx) \ + FN(sock_map_update, 53, ##ctx) \ + FN(xdp_adjust_meta, 54, ##ctx) \ + FN(perf_event_read_value, 55, ##ctx) \ + FN(perf_prog_read_value, 56, ##ctx) \ + FN(getsockopt, 57, ##ctx) \ + FN(override_return, 58, ##ctx) \ + FN(sock_ops_cb_flags_set, 59, ##ctx) \ + FN(msg_redirect_map, 60, ##ctx) \ + FN(msg_apply_bytes, 61, ##ctx) \ + FN(msg_cork_bytes, 62, ##ctx) \ + FN(msg_pull_data, 63, ##ctx) \ + FN(bind, 64, ##ctx) \ + FN(xdp_adjust_tail, 65, ##ctx) \ + FN(skb_get_xfrm_state, 66, ##ctx) \ + FN(get_stack, 67, ##ctx) \ + FN(skb_load_bytes_relative, 68, ##ctx) \ + FN(fib_lookup, 69, ##ctx) \ + FN(sock_hash_update, 70, ##ctx) \ + FN(msg_redirect_hash, 71, ##ctx) \ + FN(sk_redirect_hash, 72, ##ctx) \ + FN(lwt_push_encap, 73, ##ctx) \ + FN(lwt_seg6_store_bytes, 74, ##ctx) \ + FN(lwt_seg6_adjust_srh, 75, ##ctx) \ + FN(lwt_seg6_action, 76, ##ctx) \ + FN(rc_repeat, 77, ##ctx) \ + FN(rc_keydown, 78, ##ctx) \ + FN(skb_cgroup_id, 79, ##ctx) \ + FN(get_current_cgroup_id, 80, ##ctx) \ + FN(get_local_storage, 81, ##ctx) \ + FN(sk_select_reuseport, 82, ##ctx) \ + FN(skb_ancestor_cgroup_id, 83, ##ctx) \ + FN(sk_lookup_tcp, 84, ##ctx) \ + FN(sk_lookup_udp, 85, ##ctx) \ + FN(sk_release, 86, ##ctx) \ + FN(map_push_elem, 87, ##ctx) \ + FN(map_pop_elem, 88, ##ctx) \ + FN(map_peek_elem, 89, ##ctx) \ + FN(msg_push_data, 90, ##ctx) \ + FN(msg_pop_data, 91, ##ctx) \ + FN(rc_pointer_rel, 92, ##ctx) \ + FN(spin_lock, 93, ##ctx) \ + FN(spin_unlock, 94, ##ctx) \ + FN(sk_fullsock, 95, ##ctx) \ + FN(tcp_sock, 96, ##ctx) \ + FN(skb_ecn_set_ce, 97, ##ctx) \ + FN(get_listener_sock, 98, ##ctx) \ + FN(skc_lookup_tcp, 99, ##ctx) \ + FN(tcp_check_syncookie, 100, ##ctx) \ + FN(sysctl_get_name, 101, ##ctx) \ + FN(sysctl_get_current_value, 102, ##ctx) \ + FN(sysctl_get_new_value, 103, ##ctx) \ + FN(sysctl_set_new_value, 104, ##ctx) \ + FN(strtol, 105, ##ctx) \ + FN(strtoul, 106, ##ctx) \ + FN(sk_storage_get, 107, ##ctx) \ + FN(sk_storage_delete, 108, ##ctx) \ + FN(send_signal, 109, ##ctx) \ + FN(tcp_gen_syncookie, 110, ##ctx) \ + FN(skb_output, 111, ##ctx) \ + FN(probe_read_user, 112, ##ctx) \ + FN(probe_read_kernel, 113, ##ctx) \ + FN(probe_read_user_str, 114, ##ctx) \ + FN(probe_read_kernel_str, 115, ##ctx) \ + FN(tcp_send_ack, 116, ##ctx) \ + FN(send_signal_thread, 117, ##ctx) \ + FN(jiffies64, 118, ##ctx) \ + FN(read_branch_records, 119, ##ctx) \ + FN(get_ns_current_pid_tgid, 120, ##ctx) \ + FN(xdp_output, 121, ##ctx) \ + FN(get_netns_cookie, 122, ##ctx) \ + FN(get_current_ancestor_cgroup_id, 123, ##ctx) \ + FN(sk_assign, 124, ##ctx) \ + FN(ktime_get_boot_ns, 125, ##ctx) \ + FN(seq_printf, 126, ##ctx) \ + FN(seq_write, 127, ##ctx) \ + FN(sk_cgroup_id, 128, ##ctx) \ + FN(sk_ancestor_cgroup_id, 129, ##ctx) \ + FN(ringbuf_output, 130, ##ctx) \ + FN(ringbuf_reserve, 131, ##ctx) \ + FN(ringbuf_submit, 132, ##ctx) \ + FN(ringbuf_discard, 133, ##ctx) \ + FN(ringbuf_query, 134, ##ctx) \ + FN(csum_level, 135, ##ctx) \ + FN(skc_to_tcp6_sock, 136, ##ctx) \ + FN(skc_to_tcp_sock, 137, ##ctx) \ + FN(skc_to_tcp_timewait_sock, 138, ##ctx) \ + FN(skc_to_tcp_request_sock, 139, ##ctx) \ + FN(skc_to_udp6_sock, 140, ##ctx) \ + FN(get_task_stack, 141, ##ctx) \ + FN(load_hdr_opt, 142, ##ctx) \ + FN(store_hdr_opt, 143, ##ctx) \ + FN(reserve_hdr_opt, 144, ##ctx) \ + FN(inode_storage_get, 145, ##ctx) \ + FN(inode_storage_delete, 146, ##ctx) \ + FN(d_path, 147, ##ctx) \ + FN(copy_from_user, 148, ##ctx) \ + FN(snprintf_btf, 149, ##ctx) \ + FN(seq_printf_btf, 150, ##ctx) \ + FN(skb_cgroup_classid, 151, ##ctx) \ + FN(redirect_neigh, 152, ##ctx) \ + FN(per_cpu_ptr, 153, ##ctx) \ + FN(this_cpu_ptr, 154, ##ctx) \ + FN(redirect_peer, 155, ##ctx) \ + FN(task_storage_get, 156, ##ctx) \ + FN(task_storage_delete, 157, ##ctx) \ + FN(get_current_task_btf, 158, ##ctx) \ + FN(bprm_opts_set, 159, ##ctx) \ + FN(ktime_get_coarse_ns, 160, ##ctx) \ + FN(ima_inode_hash, 161, ##ctx) \ + FN(sock_from_file, 162, ##ctx) \ + FN(check_mtu, 163, ##ctx) \ + FN(for_each_map_elem, 164, ##ctx) \ + FN(snprintf, 165, ##ctx) \ + FN(sys_bpf, 166, ##ctx) \ + FN(btf_find_by_name_kind, 167, ##ctx) \ + FN(sys_close, 168, ##ctx) \ + FN(timer_init, 169, ##ctx) \ + FN(timer_set_callback, 170, ##ctx) \ + FN(timer_start, 171, ##ctx) \ + FN(timer_cancel, 172, ##ctx) \ + FN(get_func_ip, 173, ##ctx) \ + FN(get_attach_cookie, 174, ##ctx) \ + FN(task_pt_regs, 175, ##ctx) \ + FN(get_branch_snapshot, 176, ##ctx) \ + FN(trace_vprintk, 177, ##ctx) \ + FN(skc_to_unix_sock, 178, ##ctx) \ + FN(kallsyms_lookup_name, 179, ##ctx) \ + FN(find_vma, 180, ##ctx) \ + FN(loop, 181, ##ctx) \ + FN(strncmp, 182, ##ctx) \ + FN(get_func_arg, 183, ##ctx) \ + FN(get_func_ret, 184, ##ctx) \ + FN(get_func_arg_cnt, 185, ##ctx) \ + FN(get_retval, 186, ##ctx) \ + FN(set_retval, 187, ##ctx) \ + FN(xdp_get_buff_len, 188, ##ctx) \ + FN(xdp_load_bytes, 189, ##ctx) \ + FN(xdp_store_bytes, 190, ##ctx) \ + FN(copy_from_user_task, 191, ##ctx) \ + FN(skb_set_tstamp, 192, ##ctx) \ + FN(ima_file_hash, 193, ##ctx) \ + FN(kptr_xchg, 194, ##ctx) \ + FN(map_lookup_percpu_elem, 195, ##ctx) \ + FN(skc_to_mptcp_sock, 196, ##ctx) \ + FN(dynptr_from_mem, 197, ##ctx) \ + FN(ringbuf_reserve_dynptr, 198, ##ctx) \ + FN(ringbuf_submit_dynptr, 199, ##ctx) \ + FN(ringbuf_discard_dynptr, 200, ##ctx) \ + FN(dynptr_read, 201, ##ctx) \ + FN(dynptr_write, 202, ##ctx) \ + FN(dynptr_data, 203, ##ctx) \ + FN(tcp_raw_gen_syncookie_ipv4, 204, ##ctx) \ + FN(tcp_raw_gen_syncookie_ipv6, 205, ##ctx) \ + FN(tcp_raw_check_syncookie_ipv4, 206, ##ctx) \ + FN(tcp_raw_check_syncookie_ipv6, 207, ##ctx) \ + FN(ktime_get_tai_ns, 208, ##ctx) \ + FN(user_ringbuf_drain, 209, ##ctx) \ /* */ +/* backwards-compatibility macros for users of __BPF_FUNC_MAPPER that don't + * know or care about integer value that is now passed as second argument + */ +#define __BPF_FUNC_MAPPER_APPLY(name, value, FN) FN(name), +#define __BPF_FUNC_MAPPER(FN) ___BPF_FUNC_MAPPER(__BPF_FUNC_MAPPER_APPLY, FN) + /* integer value in 'imm' field of BPF_CALL instruction selects which helper * function eBPF program intends to call */ -#define __BPF_ENUM_FN(x) BPF_FUNC_ ## x +#define __BPF_ENUM_FN(x, y) BPF_FUNC_ ## x = y, enum bpf_func_id { - __BPF_FUNC_MAPPER(__BPF_ENUM_FN) + ___BPF_FUNC_MAPPER(__BPF_ENUM_FN) __BPF_FUNC_MAX_ID, }; #undef __BPF_ENUM_FN diff --git a/scripts/bpf_doc.py b/scripts/bpf_doc.py index d5c389df6045..2fe07c9e3fe0 100755 --- a/scripts/bpf_doc.py +++ b/scripts/bpf_doc.py @@ -253,28 +253,27 @@ class HeaderParser(object): break def parse_define_helpers(self): - # Parse FN(...) in #define __BPF_FUNC_MAPPER to compare later with the + # Parse FN(...) in #define ___BPF_FUNC_MAPPER to compare later with the # number of unique function names present in description and use the # correct enumeration value. # Note: seek_to(..) discards the first line below the target search text, - # resulting in FN(unspec) being skipped and not added to self.define_unique_helpers. - self.seek_to('#define __BPF_FUNC_MAPPER(FN)', + # resulting in FN(unspec, 0, ##ctx) being skipped and not added to + # self.define_unique_helpers. + self.seek_to('#define ___BPF_FUNC_MAPPER(FN, ctx...)', 'Could not find start of eBPF helper definition list') # Searches for one FN(\w+) define or a backslash for newline - p = re.compile('\s*FN\((\w+)\)|\\\\') + p = re.compile('\s*FN\((\w+), (\d+), ##ctx\)|\\\\') fn_defines_str = '' - i = 1 # 'unspec' is skipped as mentioned above while True: capture = p.match(self.line) if capture: fn_defines_str += self.line - self.helper_enum_vals[capture.expand(r'bpf_\1')] = i - i += 1 + self.helper_enum_vals[capture.expand(r'bpf_\1')] = int(capture[2]) else: break self.line = self.reader.readline() # Find the number of occurences of FN(\w+) - self.define_unique_helpers = re.findall('FN\(\w+\)', fn_defines_str) + self.define_unique_helpers = re.findall('FN\(\w+, \d+, ##ctx\)', fn_defines_str) def assign_helper_values(self): seen_helpers = set() @@ -423,7 +422,7 @@ class PrinterHelpersRST(PrinterRST): """ def __init__(self, parser): self.elements = parser.helpers - self.elem_number_check(parser.desc_unique_helpers, parser.define_unique_helpers, 'helper', '__BPF_FUNC_MAPPER') + self.elem_number_check(parser.desc_unique_helpers, parser.define_unique_helpers, 'helper', '___BPF_FUNC_MAPPER') def print_header(self): header = '''\ @@ -636,7 +635,7 @@ class PrinterHelpers(Printer): """ def __init__(self, parser): self.elements = parser.helpers - self.elem_number_check(parser.desc_unique_helpers, parser.define_unique_helpers, 'helper', '__BPF_FUNC_MAPPER') + self.elem_number_check(parser.desc_unique_helpers, parser.define_unique_helpers, 'helper', '___BPF_FUNC_MAPPER') type_fwds = [ 'struct bpf_fib_lookup', diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 51b9aa640ad2..17f61338f8f8 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -5436,225 +5436,231 @@ union bpf_attr { * larger than the size of the ring buffer, or which cannot fit * within a struct bpf_dynptr. */ -#define __BPF_FUNC_MAPPER(FN) \ - FN(unspec), \ - FN(map_lookup_elem), \ - FN(map_update_elem), \ - FN(map_delete_elem), \ - FN(probe_read), \ - FN(ktime_get_ns), \ - FN(trace_printk), \ - FN(get_prandom_u32), \ - FN(get_smp_processor_id), \ - FN(skb_store_bytes), \ - FN(l3_csum_replace), \ - FN(l4_csum_replace), \ - FN(tail_call), \ - FN(clone_redirect), \ - FN(get_current_pid_tgid), \ - FN(get_current_uid_gid), \ - FN(get_current_comm), \ - FN(get_cgroup_classid), \ - FN(skb_vlan_push), \ - FN(skb_vlan_pop), \ - FN(skb_get_tunnel_key), \ - FN(skb_set_tunnel_key), \ - FN(perf_event_read), \ - FN(redirect), \ - FN(get_route_realm), \ - FN(perf_event_output), \ - FN(skb_load_bytes), \ - FN(get_stackid), \ - FN(csum_diff), \ - FN(skb_get_tunnel_opt), \ - FN(skb_set_tunnel_opt), \ - FN(skb_change_proto), \ - FN(skb_change_type), \ - FN(skb_under_cgroup), \ - FN(get_hash_recalc), \ - FN(get_current_task), \ - FN(probe_write_user), \ - FN(current_task_under_cgroup), \ - FN(skb_change_tail), \ - FN(skb_pull_data), \ - FN(csum_update), \ - FN(set_hash_invalid), \ - FN(get_numa_node_id), \ - FN(skb_change_head), \ - FN(xdp_adjust_head), \ - FN(probe_read_str), \ - FN(get_socket_cookie), \ - FN(get_socket_uid), \ - FN(set_hash), \ - FN(setsockopt), \ - FN(skb_adjust_room), \ - FN(redirect_map), \ - FN(sk_redirect_map), \ - FN(sock_map_update), \ - FN(xdp_adjust_meta), \ - FN(perf_event_read_value), \ - FN(perf_prog_read_value), \ - FN(getsockopt), \ - FN(override_return), \ - FN(sock_ops_cb_flags_set), \ - FN(msg_redirect_map), \ - FN(msg_apply_bytes), \ - FN(msg_cork_bytes), \ - FN(msg_pull_data), \ - FN(bind), \ - FN(xdp_adjust_tail), \ - FN(skb_get_xfrm_state), \ - FN(get_stack), \ - FN(skb_load_bytes_relative), \ - FN(fib_lookup), \ - FN(sock_hash_update), \ - FN(msg_redirect_hash), \ - FN(sk_redirect_hash), \ - FN(lwt_push_encap), \ - FN(lwt_seg6_store_bytes), \ - FN(lwt_seg6_adjust_srh), \ - FN(lwt_seg6_action), \ - FN(rc_repeat), \ - FN(rc_keydown), \ - FN(skb_cgroup_id), \ - FN(get_current_cgroup_id), \ - FN(get_local_storage), \ - FN(sk_select_reuseport), \ - FN(skb_ancestor_cgroup_id), \ - FN(sk_lookup_tcp), \ - FN(sk_lookup_udp), \ - FN(sk_release), \ - FN(map_push_elem), \ - FN(map_pop_elem), \ - FN(map_peek_elem), \ - FN(msg_push_data), \ - FN(msg_pop_data), \ - FN(rc_pointer_rel), \ - FN(spin_lock), \ - FN(spin_unlock), \ - FN(sk_fullsock), \ - FN(tcp_sock), \ - FN(skb_ecn_set_ce), \ - FN(get_listener_sock), \ - FN(skc_lookup_tcp), \ - FN(tcp_check_syncookie), \ - FN(sysctl_get_name), \ - FN(sysctl_get_current_value), \ - FN(sysctl_get_new_value), \ - FN(sysctl_set_new_value), \ - FN(strtol), \ - FN(strtoul), \ - FN(sk_storage_get), \ - FN(sk_storage_delete), \ - FN(send_signal), \ - FN(tcp_gen_syncookie), \ - FN(skb_output), \ - FN(probe_read_user), \ - FN(probe_read_kernel), \ - FN(probe_read_user_str), \ - FN(probe_read_kernel_str), \ - FN(tcp_send_ack), \ - FN(send_signal_thread), \ - FN(jiffies64), \ - FN(read_branch_records), \ - FN(get_ns_current_pid_tgid), \ - FN(xdp_output), \ - FN(get_netns_cookie), \ - FN(get_current_ancestor_cgroup_id), \ - FN(sk_assign), \ - FN(ktime_get_boot_ns), \ - FN(seq_printf), \ - FN(seq_write), \ - FN(sk_cgroup_id), \ - FN(sk_ancestor_cgroup_id), \ - FN(ringbuf_output), \ - FN(ringbuf_reserve), \ - FN(ringbuf_submit), \ - FN(ringbuf_discard), \ - FN(ringbuf_query), \ - FN(csum_level), \ - FN(skc_to_tcp6_sock), \ - FN(skc_to_tcp_sock), \ - FN(skc_to_tcp_timewait_sock), \ - FN(skc_to_tcp_request_sock), \ - FN(skc_to_udp6_sock), \ - FN(get_task_stack), \ - FN(load_hdr_opt), \ - FN(store_hdr_opt), \ - FN(reserve_hdr_opt), \ - FN(inode_storage_get), \ - FN(inode_storage_delete), \ - FN(d_path), \ - FN(copy_from_user), \ - FN(snprintf_btf), \ - FN(seq_printf_btf), \ - FN(skb_cgroup_classid), \ - FN(redirect_neigh), \ - FN(per_cpu_ptr), \ - FN(this_cpu_ptr), \ - FN(redirect_peer), \ - FN(task_storage_get), \ - FN(task_storage_delete), \ - FN(get_current_task_btf), \ - FN(bprm_opts_set), \ - FN(ktime_get_coarse_ns), \ - FN(ima_inode_hash), \ - FN(sock_from_file), \ - FN(check_mtu), \ - FN(for_each_map_elem), \ - FN(snprintf), \ - FN(sys_bpf), \ - FN(btf_find_by_name_kind), \ - FN(sys_close), \ - FN(timer_init), \ - FN(timer_set_callback), \ - FN(timer_start), \ - FN(timer_cancel), \ - FN(get_func_ip), \ - FN(get_attach_cookie), \ - FN(task_pt_regs), \ - FN(get_branch_snapshot), \ - FN(trace_vprintk), \ - FN(skc_to_unix_sock), \ - FN(kallsyms_lookup_name), \ - FN(find_vma), \ - FN(loop), \ - FN(strncmp), \ - FN(get_func_arg), \ - FN(get_func_ret), \ - FN(get_func_arg_cnt), \ - FN(get_retval), \ - FN(set_retval), \ - FN(xdp_get_buff_len), \ - FN(xdp_load_bytes), \ - FN(xdp_store_bytes), \ - FN(copy_from_user_task), \ - FN(skb_set_tstamp), \ - FN(ima_file_hash), \ - FN(kptr_xchg), \ - FN(map_lookup_percpu_elem), \ - FN(skc_to_mptcp_sock), \ - FN(dynptr_from_mem), \ - FN(ringbuf_reserve_dynptr), \ - FN(ringbuf_submit_dynptr), \ - FN(ringbuf_discard_dynptr), \ - FN(dynptr_read), \ - FN(dynptr_write), \ - FN(dynptr_data), \ - FN(tcp_raw_gen_syncookie_ipv4), \ - FN(tcp_raw_gen_syncookie_ipv6), \ - FN(tcp_raw_check_syncookie_ipv4), \ - FN(tcp_raw_check_syncookie_ipv6), \ - FN(ktime_get_tai_ns), \ - FN(user_ringbuf_drain), \ +#define ___BPF_FUNC_MAPPER(FN, ctx...) \ + FN(unspec, 0, ##ctx) \ + FN(map_lookup_elem, 1, ##ctx) \ + FN(map_update_elem, 2, ##ctx) \ + FN(map_delete_elem, 3, ##ctx) \ + FN(probe_read, 4, ##ctx) \ + FN(ktime_get_ns, 5, ##ctx) \ + FN(trace_printk, 6, ##ctx) \ + FN(get_prandom_u32, 7, ##ctx) \ + FN(get_smp_processor_id, 8, ##ctx) \ + FN(skb_store_bytes, 9, ##ctx) \ + FN(l3_csum_replace, 10, ##ctx) \ + FN(l4_csum_replace, 11, ##ctx) \ + FN(tail_call, 12, ##ctx) \ + FN(clone_redirect, 13, ##ctx) \ + FN(get_current_pid_tgid, 14, ##ctx) \ + FN(get_current_uid_gid, 15, ##ctx) \ + FN(get_current_comm, 16, ##ctx) \ + FN(get_cgroup_classid, 17, ##ctx) \ + FN(skb_vlan_push, 18, ##ctx) \ + FN(skb_vlan_pop, 19, ##ctx) \ + FN(skb_get_tunnel_key, 20, ##ctx) \ + FN(skb_set_tunnel_key, 21, ##ctx) \ + FN(perf_event_read, 22, ##ctx) \ + FN(redirect, 23, ##ctx) \ + FN(get_route_realm, 24, ##ctx) \ + FN(perf_event_output, 25, ##ctx) \ + FN(skb_load_bytes, 26, ##ctx) \ + FN(get_stackid, 27, ##ctx) \ + FN(csum_diff, 28, ##ctx) \ + FN(skb_get_tunnel_opt, 29, ##ctx) \ + FN(skb_set_tunnel_opt, 30, ##ctx) \ + FN(skb_change_proto, 31, ##ctx) \ + FN(skb_change_type, 32, ##ctx) \ + FN(skb_under_cgroup, 33, ##ctx) \ + FN(get_hash_recalc, 34, ##ctx) \ + FN(get_current_task, 35, ##ctx) \ + FN(probe_write_user, 36, ##ctx) \ + FN(current_task_under_cgroup, 37, ##ctx) \ + FN(skb_change_tail, 38, ##ctx) \ + FN(skb_pull_data, 39, ##ctx) \ + FN(csum_update, 40, ##ctx) \ + FN(set_hash_invalid, 41, ##ctx) \ + FN(get_numa_node_id, 42, ##ctx) \ + FN(skb_change_head, 43, ##ctx) \ + FN(xdp_adjust_head, 44, ##ctx) \ + FN(probe_read_str, 45, ##ctx) \ + FN(get_socket_cookie, 46, ##ctx) \ + FN(get_socket_uid, 47, ##ctx) \ + FN(set_hash, 48, ##ctx) \ + FN(setsockopt, 49, ##ctx) \ + FN(skb_adjust_room, 50, ##ctx) \ + FN(redirect_map, 51, ##ctx) \ + FN(sk_redirect_map, 52, ##ctx) \ + FN(sock_map_update, 53, ##ctx) \ + FN(xdp_adjust_meta, 54, ##ctx) \ + FN(perf_event_read_value, 55, ##ctx) \ + FN(perf_prog_read_value, 56, ##ctx) \ + FN(getsockopt, 57, ##ctx) \ + FN(override_return, 58, ##ctx) \ + FN(sock_ops_cb_flags_set, 59, ##ctx) \ + FN(msg_redirect_map, 60, ##ctx) \ + FN(msg_apply_bytes, 61, ##ctx) \ + FN(msg_cork_bytes, 62, ##ctx) \ + FN(msg_pull_data, 63, ##ctx) \ + FN(bind, 64, ##ctx) \ + FN(xdp_adjust_tail, 65, ##ctx) \ + FN(skb_get_xfrm_state, 66, ##ctx) \ + FN(get_stack, 67, ##ctx) \ + FN(skb_load_bytes_relative, 68, ##ctx) \ + FN(fib_lookup, 69, ##ctx) \ + FN(sock_hash_update, 70, ##ctx) \ + FN(msg_redirect_hash, 71, ##ctx) \ + FN(sk_redirect_hash, 72, ##ctx) \ + FN(lwt_push_encap, 73, ##ctx) \ + FN(lwt_seg6_store_bytes, 74, ##ctx) \ + FN(lwt_seg6_adjust_srh, 75, ##ctx) \ + FN(lwt_seg6_action, 76, ##ctx) \ + FN(rc_repeat, 77, ##ctx) \ + FN(rc_keydown, 78, ##ctx) \ + FN(skb_cgroup_id, 79, ##ctx) \ + FN(get_current_cgroup_id, 80, ##ctx) \ + FN(get_local_storage, 81, ##ctx) \ + FN(sk_select_reuseport, 82, ##ctx) \ + FN(skb_ancestor_cgroup_id, 83, ##ctx) \ + FN(sk_lookup_tcp, 84, ##ctx) \ + FN(sk_lookup_udp, 85, ##ctx) \ + FN(sk_release, 86, ##ctx) \ + FN(map_push_elem, 87, ##ctx) \ + FN(map_pop_elem, 88, ##ctx) \ + FN(map_peek_elem, 89, ##ctx) \ + FN(msg_push_data, 90, ##ctx) \ + FN(msg_pop_data, 91, ##ctx) \ + FN(rc_pointer_rel, 92, ##ctx) \ + FN(spin_lock, 93, ##ctx) \ + FN(spin_unlock, 94, ##ctx) \ + FN(sk_fullsock, 95, ##ctx) \ + FN(tcp_sock, 96, ##ctx) \ + FN(skb_ecn_set_ce, 97, ##ctx) \ + FN(get_listener_sock, 98, ##ctx) \ + FN(skc_lookup_tcp, 99, ##ctx) \ + FN(tcp_check_syncookie, 100, ##ctx) \ + FN(sysctl_get_name, 101, ##ctx) \ + FN(sysctl_get_current_value, 102, ##ctx) \ + FN(sysctl_get_new_value, 103, ##ctx) \ + FN(sysctl_set_new_value, 104, ##ctx) \ + FN(strtol, 105, ##ctx) \ + FN(strtoul, 106, ##ctx) \ + FN(sk_storage_get, 107, ##ctx) \ + FN(sk_storage_delete, 108, ##ctx) \ + FN(send_signal, 109, ##ctx) \ + FN(tcp_gen_syncookie, 110, ##ctx) \ + FN(skb_output, 111, ##ctx) \ + FN(probe_read_user, 112, ##ctx) \ + FN(probe_read_kernel, 113, ##ctx) \ + FN(probe_read_user_str, 114, ##ctx) \ + FN(probe_read_kernel_str, 115, ##ctx) \ + FN(tcp_send_ack, 116, ##ctx) \ + FN(send_signal_thread, 117, ##ctx) \ + FN(jiffies64, 118, ##ctx) \ + FN(read_branch_records, 119, ##ctx) \ + FN(get_ns_current_pid_tgid, 120, ##ctx) \ + FN(xdp_output, 121, ##ctx) \ + FN(get_netns_cookie, 122, ##ctx) \ + FN(get_current_ancestor_cgroup_id, 123, ##ctx) \ + FN(sk_assign, 124, ##ctx) \ + FN(ktime_get_boot_ns, 125, ##ctx) \ + FN(seq_printf, 126, ##ctx) \ + FN(seq_write, 127, ##ctx) \ + FN(sk_cgroup_id, 128, ##ctx) \ + FN(sk_ancestor_cgroup_id, 129, ##ctx) \ + FN(ringbuf_output, 130, ##ctx) \ + FN(ringbuf_reserve, 131, ##ctx) \ + FN(ringbuf_submit, 132, ##ctx) \ + FN(ringbuf_discard, 133, ##ctx) \ + FN(ringbuf_query, 134, ##ctx) \ + FN(csum_level, 135, ##ctx) \ + FN(skc_to_tcp6_sock, 136, ##ctx) \ + FN(skc_to_tcp_sock, 137, ##ctx) \ + FN(skc_to_tcp_timewait_sock, 138, ##ctx) \ + FN(skc_to_tcp_request_sock, 139, ##ctx) \ + FN(skc_to_udp6_sock, 140, ##ctx) \ + FN(get_task_stack, 141, ##ctx) \ + FN(load_hdr_opt, 142, ##ctx) \ + FN(store_hdr_opt, 143, ##ctx) \ + FN(reserve_hdr_opt, 144, ##ctx) \ + FN(inode_storage_get, 145, ##ctx) \ + FN(inode_storage_delete, 146, ##ctx) \ + FN(d_path, 147, ##ctx) \ + FN(copy_from_user, 148, ##ctx) \ + FN(snprintf_btf, 149, ##ctx) \ + FN(seq_printf_btf, 150, ##ctx) \ + FN(skb_cgroup_classid, 151, ##ctx) \ + FN(redirect_neigh, 152, ##ctx) \ + FN(per_cpu_ptr, 153, ##ctx) \ + FN(this_cpu_ptr, 154, ##ctx) \ + FN(redirect_peer, 155, ##ctx) \ + FN(task_storage_get, 156, ##ctx) \ + FN(task_storage_delete, 157, ##ctx) \ + FN(get_current_task_btf, 158, ##ctx) \ + FN(bprm_opts_set, 159, ##ctx) \ + FN(ktime_get_coarse_ns, 160, ##ctx) \ + FN(ima_inode_hash, 161, ##ctx) \ + FN(sock_from_file, 162, ##ctx) \ + FN(check_mtu, 163, ##ctx) \ + FN(for_each_map_elem, 164, ##ctx) \ + FN(snprintf, 165, ##ctx) \ + FN(sys_bpf, 166, ##ctx) \ + FN(btf_find_by_name_kind, 167, ##ctx) \ + FN(sys_close, 168, ##ctx) \ + FN(timer_init, 169, ##ctx) \ + FN(timer_set_callback, 170, ##ctx) \ + FN(timer_start, 171, ##ctx) \ + FN(timer_cancel, 172, ##ctx) \ + FN(get_func_ip, 173, ##ctx) \ + FN(get_attach_cookie, 174, ##ctx) \ + FN(task_pt_regs, 175, ##ctx) \ + FN(get_branch_snapshot, 176, ##ctx) \ + FN(trace_vprintk, 177, ##ctx) \ + FN(skc_to_unix_sock, 178, ##ctx) \ + FN(kallsyms_lookup_name, 179, ##ctx) \ + FN(find_vma, 180, ##ctx) \ + FN(loop, 181, ##ctx) \ + FN(strncmp, 182, ##ctx) \ + FN(get_func_arg, 183, ##ctx) \ + FN(get_func_ret, 184, ##ctx) \ + FN(get_func_arg_cnt, 185, ##ctx) \ + FN(get_retval, 186, ##ctx) \ + FN(set_retval, 187, ##ctx) \ + FN(xdp_get_buff_len, 188, ##ctx) \ + FN(xdp_load_bytes, 189, ##ctx) \ + FN(xdp_store_bytes, 190, ##ctx) \ + FN(copy_from_user_task, 191, ##ctx) \ + FN(skb_set_tstamp, 192, ##ctx) \ + FN(ima_file_hash, 193, ##ctx) \ + FN(kptr_xchg, 194, ##ctx) \ + FN(map_lookup_percpu_elem, 195, ##ctx) \ + FN(skc_to_mptcp_sock, 196, ##ctx) \ + FN(dynptr_from_mem, 197, ##ctx) \ + FN(ringbuf_reserve_dynptr, 198, ##ctx) \ + FN(ringbuf_submit_dynptr, 199, ##ctx) \ + FN(ringbuf_discard_dynptr, 200, ##ctx) \ + FN(dynptr_read, 201, ##ctx) \ + FN(dynptr_write, 202, ##ctx) \ + FN(dynptr_data, 203, ##ctx) \ + FN(tcp_raw_gen_syncookie_ipv4, 204, ##ctx) \ + FN(tcp_raw_gen_syncookie_ipv6, 205, ##ctx) \ + FN(tcp_raw_check_syncookie_ipv4, 206, ##ctx) \ + FN(tcp_raw_check_syncookie_ipv6, 207, ##ctx) \ + FN(ktime_get_tai_ns, 208, ##ctx) \ + FN(user_ringbuf_drain, 209, ##ctx) \ /* */ +/* backwards-compatibility macros for users of __BPF_FUNC_MAPPER that don't + * know or care about integer value that is now passed as second argument + */ +#define __BPF_FUNC_MAPPER_APPLY(name, value, FN) FN(name), +#define __BPF_FUNC_MAPPER(FN) ___BPF_FUNC_MAPPER(__BPF_FUNC_MAPPER_APPLY, FN) + /* integer value in 'imm' field of BPF_CALL instruction selects which helper * function eBPF program intends to call */ -#define __BPF_ENUM_FN(x) BPF_FUNC_ ## x +#define __BPF_ENUM_FN(x, y) BPF_FUNC_ ## x = y, enum bpf_func_id { - __BPF_FUNC_MAPPER(__BPF_ENUM_FN) + ___BPF_FUNC_MAPPER(__BPF_ENUM_FN) __BPF_FUNC_MAX_ID, }; #undef __BPF_ENUM_FN -- cgit v1.2.3 From ce3e44a09dce74ca68fa56c23333378d936969b0 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Wed, 5 Oct 2022 21:24:52 -0700 Subject: scripts/bpf_doc.py: update logic to not assume sequential enum values Relax bpf_doc.py's expectation of all BPF_FUNC_xxx enumerators having sequential values increasing by one. Instead, only make sure that relative order of BPF helper descriptions in comments matches enumerators definitions order. Also additionally make sure that helper IDs are not duplicated. And also make sure that for cases when we have multiple descriptions for the same BPF helper (e.g., for bpf_get_socket_cookie()), all such descriptions are grouped together. Such checks should capture all the same (and more) issues in upstream UAPI headers, but also handle backported kernels correctly. Reported-by: Alexei Starovoitov Signed-off-by: Andrii Nakryiko Reviewed-by: Quentin Monnet Link: https://lore.kernel.org/r/20221006042452.2089843-2-andrii@kernel.org Signed-off-by: Alexei Starovoitov --- scripts/bpf_doc.py | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) (limited to 'scripts') diff --git a/scripts/bpf_doc.py b/scripts/bpf_doc.py index 2fe07c9e3fe0..c0e6690be82a 100755 --- a/scripts/bpf_doc.py +++ b/scripts/bpf_doc.py @@ -97,6 +97,7 @@ class HeaderParser(object): self.desc_unique_helpers = set() self.define_unique_helpers = [] self.helper_enum_vals = {} + self.helper_enum_pos = {} self.desc_syscalls = [] self.enum_syscalls = [] @@ -264,42 +265,60 @@ class HeaderParser(object): # Searches for one FN(\w+) define or a backslash for newline p = re.compile('\s*FN\((\w+), (\d+), ##ctx\)|\\\\') fn_defines_str = '' + i = 0 while True: capture = p.match(self.line) if capture: fn_defines_str += self.line - self.helper_enum_vals[capture.expand(r'bpf_\1')] = int(capture[2]) + helper_name = capture.expand(r'bpf_\1') + self.helper_enum_vals[helper_name] = int(capture[2]) + self.helper_enum_pos[helper_name] = i + i += 1 else: break self.line = self.reader.readline() # Find the number of occurences of FN(\w+) self.define_unique_helpers = re.findall('FN\(\w+, \d+, ##ctx\)', fn_defines_str) - def assign_helper_values(self): + def validate_helpers(self): + last_helper = '' seen_helpers = set() + seen_enum_vals = set() + i = 0 for helper in self.helpers: proto = helper.proto_break_down() name = proto['name'] try: enum_val = self.helper_enum_vals[name] + enum_pos = self.helper_enum_pos[name] except KeyError: raise Exception("Helper %s is missing from enum bpf_func_id" % name) + if name in seen_helpers: + if last_helper != name: + raise Exception("Helper %s has multiple descriptions which are not grouped together" % name) + continue + # Enforce current practice of having the descriptions ordered # by enum value. + if enum_pos != i: + raise Exception("Helper %s (ID %d) comment order (#%d) must be aligned with its position (#%d) in enum bpf_func_id" % (name, enum_val, i + 1, enum_pos + 1)) + if enum_val in seen_enum_vals: + raise Exception("Helper %s has duplicated value %d" % (name, enum_val)) + seen_helpers.add(name) - desc_val = len(seen_helpers) - if desc_val != enum_val: - raise Exception("Helper %s comment order (#%d) must be aligned with its position (#%d) in enum bpf_func_id" % (name, desc_val, enum_val)) + last_helper = name + seen_enum_vals.add(enum_val) helper.enum_val = enum_val + i += 1 def run(self): self.parse_desc_syscall() self.parse_enum_syscall() self.parse_desc_helpers() self.parse_define_helpers() - self.assign_helper_values() + self.validate_helpers() self.reader.close() ############################################################################### -- cgit v1.2.3 From df19817f3ff3de28e87139b6d172c0094402e1f2 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Tue, 27 Sep 2022 10:45:50 -0600 Subject: docs: sphinx-pre-install: don't require the RTD theme We don't default to the RTD theme anymore, so sphinx-pre-install need not insist on installing it. Acked-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet --- Documentation/sphinx/requirements.txt | 1 - scripts/sphinx-pre-install | 8 -------- 2 files changed, 9 deletions(-) (limited to 'scripts') diff --git a/Documentation/sphinx/requirements.txt b/Documentation/sphinx/requirements.txt index 2c573541ab71..335b53df35e2 100644 --- a/Documentation/sphinx/requirements.txt +++ b/Documentation/sphinx/requirements.txt @@ -1,4 +1,3 @@ # jinja2>=3.1 is not compatible with Sphinx<4.0 jinja2<3.1 -sphinx_rtd_theme Sphinx==2.4.4 diff --git a/scripts/sphinx-pre-install b/scripts/sphinx-pre-install index ec84fc62774e..1fb88fdceec3 100755 --- a/scripts/sphinx-pre-install +++ b/scripts/sphinx-pre-install @@ -362,7 +362,6 @@ sub give_debian_hints() { my %map = ( "python-sphinx" => "python3-sphinx", - "sphinx_rtd_theme" => "python3-sphinx-rtd-theme", "ensurepip" => "python3-venv", "virtualenv" => "virtualenv", "dot" => "graphviz", @@ -397,7 +396,6 @@ sub give_redhat_hints() { my %map = ( "python-sphinx" => "python3-sphinx", - "sphinx_rtd_theme" => "python3-sphinx_rtd_theme", "virtualenv" => "python3-virtualenv", "dot" => "graphviz", "convert" => "ImageMagick", @@ -475,7 +473,6 @@ sub give_opensuse_hints() { my %map = ( "python-sphinx" => "python3-sphinx", - "sphinx_rtd_theme" => "python3-sphinx_rtd_theme", "virtualenv" => "python3-virtualenv", "dot" => "graphviz", "convert" => "ImageMagick", @@ -523,7 +520,6 @@ sub give_mageia_hints() { my %map = ( "python-sphinx" => "python3-sphinx", - "sphinx_rtd_theme" => "python3-sphinx_rtd_theme", "virtualenv" => "python3-virtualenv", "dot" => "graphviz", "convert" => "ImageMagick", @@ -567,7 +563,6 @@ sub give_mageia_hints() sub give_arch_linux_hints() { my %map = ( - "sphinx_rtd_theme" => "python-sphinx_rtd_theme", "virtualenv" => "python-virtualenv", "dot" => "graphviz", "convert" => "imagemagick", @@ -598,7 +593,6 @@ sub give_arch_linux_hints() sub give_gentoo_hints() { my %map = ( - "sphinx_rtd_theme" => "dev-python/sphinx_rtd_theme", "virtualenv" => "dev-python/virtualenv", "dot" => "media-gfx/graphviz", "convert" => "media-gfx/imagemagick", @@ -895,7 +889,6 @@ sub recommend_sphinx_version($) $verbose_warn_install = 0; add_package("python-sphinx", 0); - check_python_module("sphinx_rtd_theme", 1); check_distros(); @@ -968,7 +961,6 @@ sub check_needs() check_perl_module("Pod::Usage", 0); check_program("make", 0); check_program("gcc", 0); - check_python_module("sphinx_rtd_theme", 1) if (!$virtualenv); check_program("dot", 1); check_program("convert", 1); -- cgit v1.2.3 From 0c0a6d8934e2081df93ba0bfc0cf615cc9c06988 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 15 Sep 2022 13:11:10 +0200 Subject: objtool: Add --hacks=skylake Make the call/func sections selectable via the --hacks option. Signed-off-by: Peter Zijlstra (Intel) Signed-off-by: Thomas Gleixner Signed-off-by: Peter Zijlstra (Intel) Link: https://lore.kernel.org/r/20220915111146.120821440@infradead.org --- scripts/Makefile.lib | 1 + tools/objtool/builtin-check.c | 7 ++++++- tools/objtool/check.c | 10 ++++++---- tools/objtool/include/objtool/builtin.h | 1 + 4 files changed, 14 insertions(+), 5 deletions(-) (limited to 'scripts') diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 3aa384cec76b..85f02756dc9c 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -254,6 +254,7 @@ objtool := $(objtree)/tools/objtool/objtool objtool-args-$(CONFIG_HAVE_JUMP_LABEL_HACK) += --hacks=jump_label objtool-args-$(CONFIG_HAVE_NOINSTR_HACK) += --hacks=noinstr +objtool-args-$(CONFIG_CALL_DEPTH_TRACKING) += --hacks=skylake objtool-args-$(CONFIG_X86_KERNEL_IBT) += --ibt objtool-args-$(CONFIG_FTRACE_MCOUNT_USE_OBJTOOL) += --mcount objtool-args-$(CONFIG_UNWINDER_ORC) += --orc diff --git a/tools/objtool/builtin-check.c b/tools/objtool/builtin-check.c index 24fbe803a0d3..0a04f8ea4432 100644 --- a/tools/objtool/builtin-check.c +++ b/tools/objtool/builtin-check.c @@ -57,12 +57,17 @@ static int parse_hacks(const struct option *opt, const char *str, int unset) found = true; } + if (!str || strstr(str, "skylake")) { + opts.hack_skylake = true; + found = true; + } + return found ? 0 : -1; } const struct option check_options[] = { OPT_GROUP("Actions:"), - OPT_CALLBACK_OPTARG('h', "hacks", NULL, NULL, "jump_label,noinstr", "patch toolchain bugs/limitations", parse_hacks), + OPT_CALLBACK_OPTARG('h', "hacks", NULL, NULL, "jump_label,noinstr,skylake", "patch toolchain bugs/limitations", parse_hacks), OPT_BOOLEAN('i', "ibt", &opts.ibt, "validate and annotate IBT"), OPT_BOOLEAN('m', "mcount", &opts.mcount, "annotate mcount/fentry calls for ftrace"), OPT_BOOLEAN('n', "noinstr", &opts.noinstr, "validate noinstr rules"), diff --git a/tools/objtool/check.c b/tools/objtool/check.c index f578e030e8bb..1461c8894fb7 100644 --- a/tools/objtool/check.c +++ b/tools/objtool/check.c @@ -4352,10 +4352,12 @@ int check(struct objtool_file *file) goto out; warnings += ret; - ret = create_direct_call_sections(file); - if (ret < 0) - goto out; - warnings += ret; + if (opts.hack_skylake) { + ret = create_direct_call_sections(file); + if (ret < 0) + goto out; + warnings += ret; + } } if (opts.mcount) { diff --git a/tools/objtool/include/objtool/builtin.h b/tools/objtool/include/objtool/builtin.h index 42a52f1a0add..22092a9f3cf6 100644 --- a/tools/objtool/include/objtool/builtin.h +++ b/tools/objtool/include/objtool/builtin.h @@ -14,6 +14,7 @@ struct opts { bool dump_orc; bool hack_jump_label; bool hack_noinstr; + bool hack_skylake; bool ibt; bool mcount; bool noinstr; -- cgit v1.2.3 From eaf710ceb5ae284778a87c0d0f2348c19e3e4751 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Fri, 30 Sep 2022 11:52:09 -0600 Subject: docs: improve the HTML formatting of kerneldoc comments Make a few changes to cause functions documented by kerneldoc to stand out better in the rendered documentation. Specifically, change kernel-doc to put the description section into a ".. container::" section, then add a bit of CSS to indent that section relative to the function prototype (or struct or enum definition). Tweak a few other CSS parameters while in the neighborhood to improve the formatting. Acked-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet --- Documentation/sphinx-static/custom.css | 16 +++++++++- scripts/kernel-doc | 54 +++++++++++++++++++++------------- 2 files changed, 48 insertions(+), 22 deletions(-) (limited to 'scripts') diff --git a/Documentation/sphinx-static/custom.css b/Documentation/sphinx-static/custom.css index 6b0e554cea0a..9b36f7abd24f 100644 --- a/Documentation/sphinx-static/custom.css +++ b/Documentation/sphinx-static/custom.css @@ -10,5 +10,19 @@ div.body h3 { font-size: 130%; } /* Tighten up the layout slightly */ div.body { padding: 0 15px 0 10px; } -div.document { margin: 20px 10px 0 10px; } div.sphinxsidebarwrapper { padding: 1em 0.4em; } +/* Tweak document margins and don't force width */ +div.document { + margin: 20px 10px 0 10px; + width: auto; +} + +/* + * Parameters for the display of function prototypes and such included + * from C source files. + */ +dl.function, dl.struct, dl.enum { margin-top: 2em; background-color: #ecf0f3; } +/* indent lines 2+ of multi-line function prototypes */ +dl.function dt { margin-left: 10em; text-indent: -10em; } +dt.sig-object { font-size: larger; } +div.kernelindent { margin-left: 2em; margin-right: 4em; } diff --git a/scripts/kernel-doc b/scripts/kernel-doc index aea04365bc69..11bafc8e85ab 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -866,48 +866,53 @@ sub output_function_rst(%) { print "\n"; } - print "**Parameters**\n\n"; + # + # Put our descriptive text into a container (thus an HTML
) to help + # set the function prototypes apart. + # + print ".. container:: kernelindent\n\n"; $lineprefix = " "; + print $lineprefix . "**Parameters**\n\n"; foreach $parameter (@{$args{'parameterlist'}}) { my $parameter_name = $parameter; $parameter_name =~ s/\[.*//; $type = $args{'parametertypes'}{$parameter}; if ($type ne "") { - print "``$type``\n"; + print $lineprefix . "``$type``\n"; } else { - print "``$parameter``\n"; + print $lineprefix . "``$parameter``\n"; } print_lineno($parameterdesc_start_lines{$parameter_name}); + $lineprefix = " "; if (defined($args{'parameterdescs'}{$parameter_name}) && $args{'parameterdescs'}{$parameter_name} ne $undescribed) { output_highlight_rst($args{'parameterdescs'}{$parameter_name}); } else { - print " *undescribed*\n"; + print $lineprefix . "*undescribed*\n"; } + $lineprefix = " "; print "\n"; } - $lineprefix = $oldprefix; output_section_rst(@_); + $lineprefix = $oldprefix; } sub output_section_rst(%) { my %args = %{$_[0]}; my $section; my $oldprefix = $lineprefix; - $lineprefix = ""; foreach $section (@{$args{'sectionlist'}}) { - print "**$section**\n\n"; + print $lineprefix . "**$section**\n\n"; print_lineno($section_start_lines{$section}); output_highlight_rst($args{'sections'}{$section}); print "\n"; } print "\n"; - $lineprefix = $oldprefix; } sub output_enum_rst(%) { @@ -915,6 +920,7 @@ sub output_enum_rst(%) { my ($parameter); my $oldprefix = $lineprefix; my $count; + my $outer; if ($sphinx_major < 3) { my $name = "enum " . $args{'enum'}; @@ -924,22 +930,25 @@ sub output_enum_rst(%) { print "\n\n.. c:enum:: " . $name . "\n\n"; } print_lineno($declaration_start_line); - $lineprefix = " "; + $lineprefix = " "; output_highlight_rst($args{'purpose'}); print "\n"; - print "**Constants**\n\n"; - $lineprefix = " "; + print ".. container:: kernelindent\n\n"; + $outer = $lineprefix . " "; + $lineprefix = $outer . " "; + print $outer . "**Constants**\n\n"; foreach $parameter (@{$args{'parameterlist'}}) { - print "``$parameter``\n"; + print $outer . "``$parameter``\n"; + if ($args{'parameterdescs'}{$parameter} ne $undescribed) { output_highlight_rst($args{'parameterdescs'}{$parameter}); } else { - print " *undescribed*\n"; + print $lineprefix . "*undescribed*\n"; } print "\n"; } - + print "\n"; $lineprefix = $oldprefix; output_section_rst(@_); } @@ -982,18 +991,19 @@ sub output_struct_rst(%) { } } print_lineno($declaration_start_line); - $lineprefix = " "; + $lineprefix = " "; output_highlight_rst($args{'purpose'}); print "\n"; - print "**Definition**\n\n"; - print "::\n\n"; + print ".. container:: kernelindent\n\n"; + print $lineprefix . "**Definition**::\n\n"; my $declaration = $args{'definition'}; - $declaration =~ s/\t/ /g; - print " " . $args{'type'} . " " . $args{'struct'} . " {\n$declaration };\n\n"; + $lineprefix = $lineprefix . " "; + $declaration =~ s/\t/$lineprefix/g; + print $lineprefix . $args{'type'} . " " . $args{'struct'} . " {\n$declaration" . $lineprefix . "};\n\n"; - print "**Members**\n\n"; $lineprefix = " "; + print $lineprefix . "**Members**\n\n"; foreach $parameter (@{$args{'parameterlist'}}) { ($parameter =~ /^#/) && next; @@ -1003,8 +1013,10 @@ sub output_struct_rst(%) { ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; $type = $args{'parametertypes'}{$parameter}; print_lineno($parameterdesc_start_lines{$parameter_name}); - print "``" . $parameter . "``\n"; + print $lineprefix . "``" . $parameter . "``\n"; + $lineprefix = " "; output_highlight_rst($args{'parameterdescs'}{$parameter_name}); + $lineprefix = " "; print "\n"; } print "\n"; -- cgit v1.2.3 From ae5a16c8da92f511fe633d0872043cd317966092 Mon Sep 17 00:00:00 2001 From: Alexandre Torgue Date: Fri, 21 Oct 2022 10:44:47 +0200 Subject: scripts: dtc: only show unique unit address warning for enabled nodes In some cases an hardware peripheral can be used for two exclusive usages. For example, on STM32MP15 we have the same peripheral for I2S and SPI. We have dedicated driver for each usage and so a dedicated device node in devicetree. To avoid to get useless warnings running "make W=1 dtbs", this patch adds the "-Wunique_unit_address_if_enabled" flag for a make with W=1. In this case we will detect a duplicate address only if both devices are enabled in the devicetree, which is a real error case. Signed-off-by: Alexandre Torgue Link: https://lore.kernel.org/r/20221021084447.5550-1-alexandre.torgue@foss.st.com [robh: Refactor options and keep 'unique_unit_address' for W=2] Signed-off-by: Rob Herring --- scripts/Makefile.lib | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'scripts') diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 3aa384cec76b..969de3b7bb30 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -334,7 +334,8 @@ quiet_cmd_gzip = GZIP $@ # DTC # --------------------------------------------------------------------------- DTC ?= $(objtree)/scripts/dtc/dtc -DTC_FLAGS += -Wno-interrupt_provider +DTC_FLAGS += -Wno-interrupt_provider \ + -Wno-unique_unit_address # Disable noisy checks by default ifeq ($(findstring 1,$(KBUILD_EXTRA_WARN)),) @@ -342,14 +343,17 @@ DTC_FLAGS += -Wno-unit_address_vs_reg \ -Wno-avoid_unnecessary_addr_size \ -Wno-alias_paths \ -Wno-graph_child_address \ - -Wno-simple_bus_reg \ - -Wno-unique_unit_address + -Wno-simple_bus_reg +else +DTC_FLAGS += \ + -Wunique_unit_address_if_enabled endif ifneq ($(findstring 2,$(KBUILD_EXTRA_WARN)),) DTC_FLAGS += -Wnode_name_chars_strict \ -Wproperty_name_chars_strict \ - -Winterrupt_provider + -Winterrupt_provider \ + -Wunique_unit_address endif DTC_FLAGS += $(DTC_FLAGS_$(basetarget)) -- cgit v1.2.3 From c4bcfb38a95edb1021a53f2d0356a78120ecfbe4 Mon Sep 17 00:00:00 2001 From: Yonghong Song Date: Tue, 25 Oct 2022 21:28:50 -0700 Subject: bpf: Implement cgroup storage available to non-cgroup-attached bpf progs Similar to sk/inode/task storage, implement similar cgroup local storage. There already exists a local storage implementation for cgroup-attached bpf programs. See map type BPF_MAP_TYPE_CGROUP_STORAGE and helper bpf_get_local_storage(). But there are use cases such that non-cgroup attached bpf progs wants to access cgroup local storage data. For example, tc egress prog has access to sk and cgroup. It is possible to use sk local storage to emulate cgroup local storage by storing data in socket. But this is a waste as it could be lots of sockets belonging to a particular cgroup. Alternatively, a separate map can be created with cgroup id as the key. But this will introduce additional overhead to manipulate the new map. A cgroup local storage, similar to existing sk/inode/task storage, should help for this use case. The life-cycle of storage is managed with the life-cycle of the cgroup struct. i.e. the storage is destroyed along with the owning cgroup with a call to bpf_cgrp_storage_free() when cgroup itself is deleted. The userspace map operations can be done by using a cgroup fd as a key passed to the lookup, update and delete operations. Typically, the following code is used to get the current cgroup: struct task_struct *task = bpf_get_current_task_btf(); ... task->cgroups->dfl_cgrp ... and in structure task_struct definition: struct task_struct { .... struct css_set __rcu *cgroups; .... } With sleepable program, accessing task->cgroups is not protected by rcu_read_lock. So the current implementation only supports non-sleepable program and supporting sleepable program will be the next step together with adding rcu_read_lock protection for rcu tagged structures. Since map name BPF_MAP_TYPE_CGROUP_STORAGE has been used for old cgroup local storage support, the new map name BPF_MAP_TYPE_CGRP_STORAGE is used for cgroup storage available to non-cgroup-attached bpf programs. The old cgroup storage supports bpf_get_local_storage() helper to get the cgroup data. The new cgroup storage helper bpf_cgrp_storage_get() can provide similar functionality. While old cgroup storage pre-allocates storage memory, the new mechanism can also pre-allocate with a user space bpf_map_update_elem() call to avoid potential run-time memory allocation failure. Therefore, the new cgroup storage can provide all functionality w.r.t. the old one. So in uapi bpf.h, the old BPF_MAP_TYPE_CGROUP_STORAGE is alias to BPF_MAP_TYPE_CGROUP_STORAGE_DEPRECATED to indicate the old cgroup storage can be deprecated since the new one can provide the same functionality. Acked-by: David Vernet Signed-off-by: Yonghong Song Link: https://lore.kernel.org/r/20221026042850.673791-1-yhs@fb.com Signed-off-by: Alexei Starovoitov --- include/linux/bpf.h | 7 ++ include/linux/bpf_types.h | 1 + include/linux/cgroup-defs.h | 4 + include/uapi/linux/bpf.h | 50 ++++++++- kernel/bpf/Makefile | 2 +- kernel/bpf/bpf_cgrp_storage.c | 247 +++++++++++++++++++++++++++++++++++++++++ kernel/bpf/helpers.c | 6 + kernel/bpf/syscall.c | 3 +- kernel/bpf/verifier.c | 13 ++- kernel/cgroup/cgroup.c | 1 + kernel/trace/bpf_trace.c | 4 + scripts/bpf_doc.py | 2 + tools/include/uapi/linux/bpf.h | 50 ++++++++- 13 files changed, 385 insertions(+), 5 deletions(-) create mode 100644 kernel/bpf/bpf_cgrp_storage.c (limited to 'scripts') diff --git a/include/linux/bpf.h b/include/linux/bpf.h index a5dbac8f5aba..9fd68b0b3e9c 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -2041,6 +2041,7 @@ struct bpf_link *bpf_link_by_id(u32 id); const struct bpf_func_proto *bpf_base_func_proto(enum bpf_func_id func_id); void bpf_task_storage_free(struct task_struct *task); +void bpf_cgrp_storage_free(struct cgroup *cgroup); bool bpf_prog_has_kfunc_call(const struct bpf_prog *prog); const struct btf_func_model * bpf_jit_find_kfunc_model(const struct bpf_prog *prog, @@ -2295,6 +2296,10 @@ static inline bool has_current_bpf_ctx(void) static inline void bpf_prog_inc_misses_counter(struct bpf_prog *prog) { } + +static inline void bpf_cgrp_storage_free(struct cgroup *cgroup) +{ +} #endif /* CONFIG_BPF_SYSCALL */ void __bpf_free_used_btfs(struct bpf_prog_aux *aux, @@ -2535,6 +2540,8 @@ extern const struct bpf_func_proto bpf_copy_from_user_task_proto; extern const struct bpf_func_proto bpf_set_retval_proto; extern const struct bpf_func_proto bpf_get_retval_proto; extern const struct bpf_func_proto bpf_user_ringbuf_drain_proto; +extern const struct bpf_func_proto bpf_cgrp_storage_get_proto; +extern const struct bpf_func_proto bpf_cgrp_storage_delete_proto; const struct bpf_func_proto *tracing_prog_func_proto( enum bpf_func_id func_id, const struct bpf_prog *prog); diff --git a/include/linux/bpf_types.h b/include/linux/bpf_types.h index 2c6a4f2562a7..d4ee3ccd3753 100644 --- a/include/linux/bpf_types.h +++ b/include/linux/bpf_types.h @@ -86,6 +86,7 @@ BPF_MAP_TYPE(BPF_MAP_TYPE_PROG_ARRAY, prog_array_map_ops) BPF_MAP_TYPE(BPF_MAP_TYPE_PERF_EVENT_ARRAY, perf_event_array_map_ops) #ifdef CONFIG_CGROUPS BPF_MAP_TYPE(BPF_MAP_TYPE_CGROUP_ARRAY, cgroup_array_map_ops) +BPF_MAP_TYPE(BPF_MAP_TYPE_CGRP_STORAGE, cgrp_storage_map_ops) #endif #ifdef CONFIG_CGROUP_BPF BPF_MAP_TYPE(BPF_MAP_TYPE_CGROUP_STORAGE, cgroup_storage_map_ops) diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h index 8f481d1b159a..c466fdc3a32a 100644 --- a/include/linux/cgroup-defs.h +++ b/include/linux/cgroup-defs.h @@ -504,6 +504,10 @@ struct cgroup { /* Used to store internal freezer state */ struct cgroup_freezer_state freezer; +#ifdef CONFIG_BPF_SYSCALL + struct bpf_local_storage __rcu *bpf_cgrp_storage; +#endif + /* All ancestors including self */ struct cgroup *ancestors[]; }; diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 17f61338f8f8..94659f6b3395 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -922,7 +922,14 @@ enum bpf_map_type { BPF_MAP_TYPE_CPUMAP, BPF_MAP_TYPE_XSKMAP, BPF_MAP_TYPE_SOCKHASH, - BPF_MAP_TYPE_CGROUP_STORAGE, + BPF_MAP_TYPE_CGROUP_STORAGE_DEPRECATED, + /* BPF_MAP_TYPE_CGROUP_STORAGE is available to bpf programs attaching + * to a cgroup. The newer BPF_MAP_TYPE_CGRP_STORAGE is available to + * both cgroup-attached and other progs and supports all functionality + * provided by BPF_MAP_TYPE_CGROUP_STORAGE. So mark + * BPF_MAP_TYPE_CGROUP_STORAGE deprecated. + */ + BPF_MAP_TYPE_CGROUP_STORAGE = BPF_MAP_TYPE_CGROUP_STORAGE_DEPRECATED, BPF_MAP_TYPE_REUSEPORT_SOCKARRAY, BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE, BPF_MAP_TYPE_QUEUE, @@ -935,6 +942,7 @@ enum bpf_map_type { BPF_MAP_TYPE_TASK_STORAGE, BPF_MAP_TYPE_BLOOM_FILTER, BPF_MAP_TYPE_USER_RINGBUF, + BPF_MAP_TYPE_CGRP_STORAGE, }; /* Note that tracing related programs such as @@ -5435,6 +5443,44 @@ union bpf_attr { * **-E2BIG** if user-space has tried to publish a sample which is * larger than the size of the ring buffer, or which cannot fit * within a struct bpf_dynptr. + * + * void *bpf_cgrp_storage_get(struct bpf_map *map, struct cgroup *cgroup, void *value, u64 flags) + * Description + * Get a bpf_local_storage from the *cgroup*. + * + * Logically, it could be thought of as getting the value from + * a *map* with *cgroup* as the **key**. From this + * perspective, the usage is not much different from + * **bpf_map_lookup_elem**\ (*map*, **&**\ *cgroup*) except this + * helper enforces the key must be a cgroup struct and the map must also + * be a **BPF_MAP_TYPE_CGRP_STORAGE**. + * + * In reality, the local-storage value is embedded directly inside of the + * *cgroup* object itself, rather than being located in the + * **BPF_MAP_TYPE_CGRP_STORAGE** map. When the local-storage value is + * queried for some *map* on a *cgroup* object, the kernel will perform an + * O(n) iteration over all of the live local-storage values for that + * *cgroup* object until the local-storage value for the *map* is found. + * + * An optional *flags* (**BPF_LOCAL_STORAGE_GET_F_CREATE**) can be + * used such that a new bpf_local_storage will be + * created if one does not exist. *value* can be used + * together with **BPF_LOCAL_STORAGE_GET_F_CREATE** to specify + * the initial value of a bpf_local_storage. If *value* is + * **NULL**, the new bpf_local_storage will be zero initialized. + * Return + * A bpf_local_storage pointer is returned on success. + * + * **NULL** if not found or there was an error in adding + * a new bpf_local_storage. + * + * long bpf_cgrp_storage_delete(struct bpf_map *map, struct cgroup *cgroup) + * Description + * Delete a bpf_local_storage from a *cgroup*. + * Return + * 0 on success. + * + * **-ENOENT** if the bpf_local_storage cannot be found. */ #define ___BPF_FUNC_MAPPER(FN, ctx...) \ FN(unspec, 0, ##ctx) \ @@ -5647,6 +5693,8 @@ union bpf_attr { FN(tcp_raw_check_syncookie_ipv6, 207, ##ctx) \ FN(ktime_get_tai_ns, 208, ##ctx) \ FN(user_ringbuf_drain, 209, ##ctx) \ + FN(cgrp_storage_get, 210, ##ctx) \ + FN(cgrp_storage_delete, 211, ##ctx) \ /* */ /* backwards-compatibility macros for users of __BPF_FUNC_MAPPER that don't diff --git a/kernel/bpf/Makefile b/kernel/bpf/Makefile index 341c94f208f4..3a12e6b400a2 100644 --- a/kernel/bpf/Makefile +++ b/kernel/bpf/Makefile @@ -25,7 +25,7 @@ ifeq ($(CONFIG_PERF_EVENTS),y) obj-$(CONFIG_BPF_SYSCALL) += stackmap.o endif ifeq ($(CONFIG_CGROUPS),y) -obj-$(CONFIG_BPF_SYSCALL) += cgroup_iter.o +obj-$(CONFIG_BPF_SYSCALL) += cgroup_iter.o bpf_cgrp_storage.o endif obj-$(CONFIG_CGROUP_BPF) += cgroup.o ifeq ($(CONFIG_INET),y) diff --git a/kernel/bpf/bpf_cgrp_storage.c b/kernel/bpf/bpf_cgrp_storage.c new file mode 100644 index 000000000000..309403800f82 --- /dev/null +++ b/kernel/bpf/bpf_cgrp_storage.c @@ -0,0 +1,247 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2022 Meta Platforms, Inc. and affiliates. + */ + +#include +#include +#include +#include +#include + +DEFINE_BPF_STORAGE_CACHE(cgroup_cache); + +static DEFINE_PER_CPU(int, bpf_cgrp_storage_busy); + +static void bpf_cgrp_storage_lock(void) +{ + migrate_disable(); + this_cpu_inc(bpf_cgrp_storage_busy); +} + +static void bpf_cgrp_storage_unlock(void) +{ + this_cpu_dec(bpf_cgrp_storage_busy); + migrate_enable(); +} + +static bool bpf_cgrp_storage_trylock(void) +{ + migrate_disable(); + if (unlikely(this_cpu_inc_return(bpf_cgrp_storage_busy) != 1)) { + this_cpu_dec(bpf_cgrp_storage_busy); + migrate_enable(); + return false; + } + return true; +} + +static struct bpf_local_storage __rcu **cgroup_storage_ptr(void *owner) +{ + struct cgroup *cg = owner; + + return &cg->bpf_cgrp_storage; +} + +void bpf_cgrp_storage_free(struct cgroup *cgroup) +{ + struct bpf_local_storage *local_storage; + bool free_cgroup_storage = false; + unsigned long flags; + + rcu_read_lock(); + local_storage = rcu_dereference(cgroup->bpf_cgrp_storage); + if (!local_storage) { + rcu_read_unlock(); + return; + } + + bpf_cgrp_storage_lock(); + raw_spin_lock_irqsave(&local_storage->lock, flags); + free_cgroup_storage = bpf_local_storage_unlink_nolock(local_storage); + raw_spin_unlock_irqrestore(&local_storage->lock, flags); + bpf_cgrp_storage_unlock(); + rcu_read_unlock(); + + if (free_cgroup_storage) + kfree_rcu(local_storage, rcu); +} + +static struct bpf_local_storage_data * +cgroup_storage_lookup(struct cgroup *cgroup, struct bpf_map *map, bool cacheit_lockit) +{ + struct bpf_local_storage *cgroup_storage; + struct bpf_local_storage_map *smap; + + cgroup_storage = rcu_dereference_check(cgroup->bpf_cgrp_storage, + bpf_rcu_lock_held()); + if (!cgroup_storage) + return NULL; + + smap = (struct bpf_local_storage_map *)map; + return bpf_local_storage_lookup(cgroup_storage, smap, cacheit_lockit); +} + +static void *bpf_cgrp_storage_lookup_elem(struct bpf_map *map, void *key) +{ + struct bpf_local_storage_data *sdata; + struct cgroup *cgroup; + int fd; + + fd = *(int *)key; + cgroup = cgroup_get_from_fd(fd); + if (IS_ERR(cgroup)) + return ERR_CAST(cgroup); + + bpf_cgrp_storage_lock(); + sdata = cgroup_storage_lookup(cgroup, map, true); + bpf_cgrp_storage_unlock(); + cgroup_put(cgroup); + return sdata ? sdata->data : NULL; +} + +static int bpf_cgrp_storage_update_elem(struct bpf_map *map, void *key, + void *value, u64 map_flags) +{ + struct bpf_local_storage_data *sdata; + struct cgroup *cgroup; + int fd; + + fd = *(int *)key; + cgroup = cgroup_get_from_fd(fd); + if (IS_ERR(cgroup)) + return PTR_ERR(cgroup); + + bpf_cgrp_storage_lock(); + sdata = bpf_local_storage_update(cgroup, (struct bpf_local_storage_map *)map, + value, map_flags, GFP_ATOMIC); + bpf_cgrp_storage_unlock(); + cgroup_put(cgroup); + return PTR_ERR_OR_ZERO(sdata); +} + +static int cgroup_storage_delete(struct cgroup *cgroup, struct bpf_map *map) +{ + struct bpf_local_storage_data *sdata; + + sdata = cgroup_storage_lookup(cgroup, map, false); + if (!sdata) + return -ENOENT; + + bpf_selem_unlink(SELEM(sdata), true); + return 0; +} + +static int bpf_cgrp_storage_delete_elem(struct bpf_map *map, void *key) +{ + struct cgroup *cgroup; + int err, fd; + + fd = *(int *)key; + cgroup = cgroup_get_from_fd(fd); + if (IS_ERR(cgroup)) + return PTR_ERR(cgroup); + + bpf_cgrp_storage_lock(); + err = cgroup_storage_delete(cgroup, map); + bpf_cgrp_storage_unlock(); + cgroup_put(cgroup); + return err; +} + +static int notsupp_get_next_key(struct bpf_map *map, void *key, void *next_key) +{ + return -ENOTSUPP; +} + +static struct bpf_map *cgroup_storage_map_alloc(union bpf_attr *attr) +{ + return bpf_local_storage_map_alloc(attr, &cgroup_cache); +} + +static void cgroup_storage_map_free(struct bpf_map *map) +{ + bpf_local_storage_map_free(map, &cgroup_cache, NULL); +} + +/* *gfp_flags* is a hidden argument provided by the verifier */ +BPF_CALL_5(bpf_cgrp_storage_get, struct bpf_map *, map, struct cgroup *, cgroup, + void *, value, u64, flags, gfp_t, gfp_flags) +{ + struct bpf_local_storage_data *sdata; + + WARN_ON_ONCE(!bpf_rcu_lock_held()); + if (flags & ~(BPF_LOCAL_STORAGE_GET_F_CREATE)) + return (unsigned long)NULL; + + if (!cgroup) + return (unsigned long)NULL; + + if (!bpf_cgrp_storage_trylock()) + return (unsigned long)NULL; + + sdata = cgroup_storage_lookup(cgroup, map, true); + if (sdata) + goto unlock; + + /* only allocate new storage, when the cgroup is refcounted */ + if (!percpu_ref_is_dying(&cgroup->self.refcnt) && + (flags & BPF_LOCAL_STORAGE_GET_F_CREATE)) + sdata = bpf_local_storage_update(cgroup, (struct bpf_local_storage_map *)map, + value, BPF_NOEXIST, gfp_flags); + +unlock: + bpf_cgrp_storage_unlock(); + return IS_ERR_OR_NULL(sdata) ? (unsigned long)NULL : (unsigned long)sdata->data; +} + +BPF_CALL_2(bpf_cgrp_storage_delete, struct bpf_map *, map, struct cgroup *, cgroup) +{ + int ret; + + WARN_ON_ONCE(!bpf_rcu_lock_held()); + if (!cgroup) + return -EINVAL; + + if (!bpf_cgrp_storage_trylock()) + return -EBUSY; + + ret = cgroup_storage_delete(cgroup, map); + bpf_cgrp_storage_unlock(); + return ret; +} + +BTF_ID_LIST_SINGLE(cgroup_storage_map_btf_ids, struct, bpf_local_storage_map) +const struct bpf_map_ops cgrp_storage_map_ops = { + .map_meta_equal = bpf_map_meta_equal, + .map_alloc_check = bpf_local_storage_map_alloc_check, + .map_alloc = cgroup_storage_map_alloc, + .map_free = cgroup_storage_map_free, + .map_get_next_key = notsupp_get_next_key, + .map_lookup_elem = bpf_cgrp_storage_lookup_elem, + .map_update_elem = bpf_cgrp_storage_update_elem, + .map_delete_elem = bpf_cgrp_storage_delete_elem, + .map_check_btf = bpf_local_storage_map_check_btf, + .map_btf_id = &cgroup_storage_map_btf_ids[0], + .map_owner_storage_ptr = cgroup_storage_ptr, +}; + +const struct bpf_func_proto bpf_cgrp_storage_get_proto = { + .func = bpf_cgrp_storage_get, + .gpl_only = false, + .ret_type = RET_PTR_TO_MAP_VALUE_OR_NULL, + .arg1_type = ARG_CONST_MAP_PTR, + .arg2_type = ARG_PTR_TO_BTF_ID, + .arg2_btf_id = &bpf_cgroup_btf_id[0], + .arg3_type = ARG_PTR_TO_MAP_VALUE_OR_NULL, + .arg4_type = ARG_ANYTHING, +}; + +const struct bpf_func_proto bpf_cgrp_storage_delete_proto = { + .func = bpf_cgrp_storage_delete, + .gpl_only = false, + .ret_type = RET_INTEGER, + .arg1_type = ARG_CONST_MAP_PTR, + .arg2_type = ARG_PTR_TO_BTF_ID, + .arg2_btf_id = &bpf_cgroup_btf_id[0], +}; diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c index a6b04faed282..124fd199ce5c 100644 --- a/kernel/bpf/helpers.c +++ b/kernel/bpf/helpers.c @@ -1663,6 +1663,12 @@ bpf_base_func_proto(enum bpf_func_id func_id) return &bpf_dynptr_write_proto; case BPF_FUNC_dynptr_data: return &bpf_dynptr_data_proto; +#ifdef CONFIG_CGROUPS + case BPF_FUNC_cgrp_storage_get: + return &bpf_cgrp_storage_get_proto; + case BPF_FUNC_cgrp_storage_delete: + return &bpf_cgrp_storage_delete_proto; +#endif default: break; } diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index a0b4266196a8..11df90962101 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -1016,7 +1016,8 @@ static int map_check_btf(struct bpf_map *map, const struct btf *btf, map->map_type != BPF_MAP_TYPE_CGROUP_STORAGE && map->map_type != BPF_MAP_TYPE_SK_STORAGE && map->map_type != BPF_MAP_TYPE_INODE_STORAGE && - map->map_type != BPF_MAP_TYPE_TASK_STORAGE) + map->map_type != BPF_MAP_TYPE_TASK_STORAGE && + map->map_type != BPF_MAP_TYPE_CGRP_STORAGE) return -ENOTSUPP; if (map->spin_lock_off + sizeof(struct bpf_spin_lock) > map->value_size) { diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index ddc1452cf023..8f849a763b79 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -6350,6 +6350,11 @@ static int check_map_func_compatibility(struct bpf_verifier_env *env, func_id != BPF_FUNC_task_storage_delete) goto error; break; + case BPF_MAP_TYPE_CGRP_STORAGE: + if (func_id != BPF_FUNC_cgrp_storage_get && + func_id != BPF_FUNC_cgrp_storage_delete) + goto error; + break; case BPF_MAP_TYPE_BLOOM_FILTER: if (func_id != BPF_FUNC_map_peek_elem && func_id != BPF_FUNC_map_push_elem) @@ -6462,6 +6467,11 @@ static int check_map_func_compatibility(struct bpf_verifier_env *env, if (map->map_type != BPF_MAP_TYPE_TASK_STORAGE) goto error; break; + case BPF_FUNC_cgrp_storage_get: + case BPF_FUNC_cgrp_storage_delete: + if (map->map_type != BPF_MAP_TYPE_CGRP_STORAGE) + goto error; + break; default: break; } @@ -14139,7 +14149,8 @@ static int do_misc_fixups(struct bpf_verifier_env *env) if (insn->imm == BPF_FUNC_task_storage_get || insn->imm == BPF_FUNC_sk_storage_get || - insn->imm == BPF_FUNC_inode_storage_get) { + insn->imm == BPF_FUNC_inode_storage_get || + insn->imm == BPF_FUNC_cgrp_storage_get) { if (env->prog->aux->sleepable) insn_buf[0] = BPF_MOV64_IMM(BPF_REG_5, (__force __s32)GFP_KERNEL); else diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index 764bdd5fd8d1..12001928511b 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c @@ -5245,6 +5245,7 @@ static void css_free_rwork_fn(struct work_struct *work) atomic_dec(&cgrp->root->nr_cgrps); cgroup1_pidlist_destroy_all(cgrp); cancel_work_sync(&cgrp->release_agent_work); + bpf_cgrp_storage_free(cgrp); if (cgroup_parent(cgrp)) { /* diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index eed1bd952c3a..ce0228c72a93 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -1455,6 +1455,10 @@ bpf_tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) return &bpf_get_current_cgroup_id_proto; case BPF_FUNC_get_current_ancestor_cgroup_id: return &bpf_get_current_ancestor_cgroup_id_proto; + case BPF_FUNC_cgrp_storage_get: + return &bpf_cgrp_storage_get_proto; + case BPF_FUNC_cgrp_storage_delete: + return &bpf_cgrp_storage_delete_proto; #endif case BPF_FUNC_send_signal: return &bpf_send_signal_proto; diff --git a/scripts/bpf_doc.py b/scripts/bpf_doc.py index c0e6690be82a..fdb0aff8cb5a 100755 --- a/scripts/bpf_doc.py +++ b/scripts/bpf_doc.py @@ -685,6 +685,7 @@ class PrinterHelpers(Printer): 'struct udp6_sock', 'struct unix_sock', 'struct task_struct', + 'struct cgroup', 'struct __sk_buff', 'struct sk_msg_md', @@ -742,6 +743,7 @@ class PrinterHelpers(Printer): 'struct udp6_sock', 'struct unix_sock', 'struct task_struct', + 'struct cgroup', 'struct path', 'struct btf_ptr', 'struct inode', diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 17f61338f8f8..94659f6b3395 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -922,7 +922,14 @@ enum bpf_map_type { BPF_MAP_TYPE_CPUMAP, BPF_MAP_TYPE_XSKMAP, BPF_MAP_TYPE_SOCKHASH, - BPF_MAP_TYPE_CGROUP_STORAGE, + BPF_MAP_TYPE_CGROUP_STORAGE_DEPRECATED, + /* BPF_MAP_TYPE_CGROUP_STORAGE is available to bpf programs attaching + * to a cgroup. The newer BPF_MAP_TYPE_CGRP_STORAGE is available to + * both cgroup-attached and other progs and supports all functionality + * provided by BPF_MAP_TYPE_CGROUP_STORAGE. So mark + * BPF_MAP_TYPE_CGROUP_STORAGE deprecated. + */ + BPF_MAP_TYPE_CGROUP_STORAGE = BPF_MAP_TYPE_CGROUP_STORAGE_DEPRECATED, BPF_MAP_TYPE_REUSEPORT_SOCKARRAY, BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE, BPF_MAP_TYPE_QUEUE, @@ -935,6 +942,7 @@ enum bpf_map_type { BPF_MAP_TYPE_TASK_STORAGE, BPF_MAP_TYPE_BLOOM_FILTER, BPF_MAP_TYPE_USER_RINGBUF, + BPF_MAP_TYPE_CGRP_STORAGE, }; /* Note that tracing related programs such as @@ -5435,6 +5443,44 @@ union bpf_attr { * **-E2BIG** if user-space has tried to publish a sample which is * larger than the size of the ring buffer, or which cannot fit * within a struct bpf_dynptr. + * + * void *bpf_cgrp_storage_get(struct bpf_map *map, struct cgroup *cgroup, void *value, u64 flags) + * Description + * Get a bpf_local_storage from the *cgroup*. + * + * Logically, it could be thought of as getting the value from + * a *map* with *cgroup* as the **key**. From this + * perspective, the usage is not much different from + * **bpf_map_lookup_elem**\ (*map*, **&**\ *cgroup*) except this + * helper enforces the key must be a cgroup struct and the map must also + * be a **BPF_MAP_TYPE_CGRP_STORAGE**. + * + * In reality, the local-storage value is embedded directly inside of the + * *cgroup* object itself, rather than being located in the + * **BPF_MAP_TYPE_CGRP_STORAGE** map. When the local-storage value is + * queried for some *map* on a *cgroup* object, the kernel will perform an + * O(n) iteration over all of the live local-storage values for that + * *cgroup* object until the local-storage value for the *map* is found. + * + * An optional *flags* (**BPF_LOCAL_STORAGE_GET_F_CREATE**) can be + * used such that a new bpf_local_storage will be + * created if one does not exist. *value* can be used + * together with **BPF_LOCAL_STORAGE_GET_F_CREATE** to specify + * the initial value of a bpf_local_storage. If *value* is + * **NULL**, the new bpf_local_storage will be zero initialized. + * Return + * A bpf_local_storage pointer is returned on success. + * + * **NULL** if not found or there was an error in adding + * a new bpf_local_storage. + * + * long bpf_cgrp_storage_delete(struct bpf_map *map, struct cgroup *cgroup) + * Description + * Delete a bpf_local_storage from a *cgroup*. + * Return + * 0 on success. + * + * **-ENOENT** if the bpf_local_storage cannot be found. */ #define ___BPF_FUNC_MAPPER(FN, ctx...) \ FN(unspec, 0, ##ctx) \ @@ -5647,6 +5693,8 @@ union bpf_attr { FN(tcp_raw_check_syncookie_ipv6, 207, ##ctx) \ FN(ktime_get_tai_ns, 208, ##ctx) \ FN(user_ringbuf_drain, 209, ##ctx) \ + FN(cgrp_storage_get, 210, ##ctx) \ + FN(cgrp_storage_delete, 211, ##ctx) \ /* */ /* backwards-compatibility macros for users of __BPF_FUNC_MAPPER that don't -- cgit v1.2.3 From 363547d2191cbc32ca954ba75d72908712398ff2 Mon Sep 17 00:00:00 2001 From: Andrew Davis Date: Mon, 24 Oct 2022 12:34:28 -0500 Subject: kbuild: Allow DTB overlays to built from .dtso named source files Currently DTB Overlays (.dtbo) are build from source files with the same extension (.dts) as the base DTs (.dtb). This may become confusing and even lead to wrong results. For example, a composite DTB (created from a base DTB and a set of overlays) might have the same name as one of the overlays that create it. Different files should be generated from differently named sources. .dtb <-> .dts .dtbo <-> .dtso We do not remove the ability to compile DTBO files from .dts files here, only add a new rule allowing the .dtso file name. The current .dts named overlays can be renamed with time. After all have been renamed we can remove the other rule. Signed-off-by: Andrew Davis Reviewed-by: Geert Uytterhoeven Tested-by: Geert Uytterhoeven Reviewed-by: Frank Rowand Tested-by: Frank Rowand Link: https://lore.kernel.org/r/20221024173434.32518-2-afd@ti.com Signed-off-by: Rob Herring --- scripts/Makefile.lib | 3 +++ 1 file changed, 3 insertions(+) (limited to 'scripts') diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 3aa384cec76b..0376a6f18bfb 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -408,6 +408,9 @@ $(obj)/%.dtb: $(src)/%.dts $(DTC) $(DT_TMP_SCHEMA) FORCE $(obj)/%.dtbo: $(src)/%.dts $(DTC) FORCE $(call if_changed_dep,dtc) +$(obj)/%.dtbo: $(src)/%.dtso $(DTC) FORCE + $(call if_changed_dep,dtc) + dtc-tmp = $(subst $(comma),_,$(dot-target).dts.tmp) # Bzip2 -- cgit v1.2.3 From 941214a512d8c80d47e720c17ec17e8539175e93 Mon Sep 17 00:00:00 2001 From: Andrew Davis Date: Mon, 24 Oct 2022 12:34:29 -0500 Subject: kbuild: Allow DTB overlays to built into .dtbo.S files DTB files can be built into the kernel by converting them to assembly files then assembling them into object files. We extend this here for DTB overlays with the .dtso extensions. We change the start and end delimiting tag prefix to make it clear that this data came from overlay files. [Based on patch by Frank Rowand ] Signed-off-by: Andrew Davis Reviewed-by: Geert Uytterhoeven Tested-by: Geert Uytterhoeven Reviewed-by: Frank Rowand Tested-by: Frank Rowand Link: https://lore.kernel.org/r/20221024173434.32518-3-afd@ti.com Signed-off-by: Rob Herring --- scripts/Makefile.lib | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 0376a6f18bfb..250b9fd73f6d 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -358,7 +358,7 @@ DTC_FLAGS += $(DTC_FLAGS_$(basetarget)) DTC_FLAGS += $(if $(filter $(patsubst $(obj)/%,%,$@), $(base-dtb-y)), -@) # Generate an assembly file to wrap the output of the device tree compiler -quiet_cmd_dt_S_dtb= DTB $@ +quiet_cmd_dt_S_dtb= DTBS $@ cmd_dt_S_dtb= \ { \ echo '\#include '; \ @@ -375,6 +375,24 @@ cmd_dt_S_dtb= \ $(obj)/%.dtb.S: $(obj)/%.dtb FORCE $(call if_changed,dt_S_dtb) +# Generate an assembly file to wrap the output of the device tree compiler +quiet_cmd_dt_S_dtbo= DTBOS $@ +cmd_dt_S_dtbo= \ +{ \ + echo '\#include '; \ + echo '.section .dtb.init.rodata,"a"'; \ + echo '.balign STRUCT_ALIGNMENT'; \ + echo '.global __dtbo_$(subst -,_,$(*F))_begin'; \ + echo '__dtbo_$(subst -,_,$(*F))_begin:'; \ + echo '.incbin "$<" '; \ + echo '__dtbo_$(subst -,_,$(*F))_end:'; \ + echo '.global __dtbo_$(subst -,_,$(*F))_end'; \ + echo '.balign STRUCT_ALIGNMENT'; \ +} > $@ + +$(obj)/%.dtbo.S: $(obj)/%.dtbo FORCE + $(call if_changed,dt_S_dtbo) + quiet_cmd_dtc = DTC $@ cmd_dtc = $(HOSTCC) -E $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \ $(DTC) -o $@ -b 0 \ -- cgit v1.2.3 From 2348e6bf44213c5f447ff698e43c089185241ed7 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Tue, 18 Oct 2022 22:12:00 +0800 Subject: riscv: remove special treatment for the link order of head.o arch/riscv/kernel/head.o does not need any special treatment - the only requirement is the ".head.text" section must be placed before the normal ".text" section. The linker script does the right thing to do. The build system does not need to manipulate the link order of head.o. Signed-off-by: Jisheng Zhang Link: https://lore.kernel.org/r/20221018141200.1040-1-jszhang@kernel.org Signed-off-by: Palmer Dabbelt --- scripts/head-object-list.txt | 1 - 1 file changed, 1 deletion(-) (limited to 'scripts') diff --git a/scripts/head-object-list.txt b/scripts/head-object-list.txt index b16326a92c45..105ea7ac4751 100644 --- a/scripts/head-object-list.txt +++ b/scripts/head-object-list.txt @@ -39,7 +39,6 @@ arch/powerpc/kernel/entry_64.o arch/powerpc/kernel/fpu.o arch/powerpc/kernel/vector.o arch/powerpc/kernel/prom_init.o -arch/riscv/kernel/head.o arch/s390/kernel/head64.o arch/sh/kernel/head_32.o arch/sparc/kernel/head_32.o -- cgit v1.2.3 From 03699f271de1f4df6369cd379506539cd7d590d3 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Fri, 2 Sep 2022 14:33:44 -0700 Subject: string: Rewrite and add more kern-doc for the str*() functions While there were varying degrees of kern-doc for various str*()-family functions, many needed updating and clarification, or to just be entirely written. Update (and relocate) existing kern-doc and add missing functions, sadly shaking my head at how many times I have written "Do not use this function". Include the results in the core kernel API doc. Cc: Bagas Sanjaya Cc: Andy Shevchenko Cc: Rasmus Villemoes Cc: Andrew Morton Cc: linux-hardening@vger.kernel.org Tested-by: Akira Yokosawa Link: https://lore.kernel.org/lkml/9b0cf584-01b3-3013-b800-1ef59fe82476@gmail.com Signed-off-by: Kees Cook --- Documentation/core-api/kernel-api.rst | 3 + include/linux/fortify-string.h | 133 +++++++++++++++++++++++++++++++--- lib/string.c | 82 --------------------- scripts/kernel-doc | 6 +- 4 files changed, 131 insertions(+), 93 deletions(-) (limited to 'scripts') diff --git a/Documentation/core-api/kernel-api.rst b/Documentation/core-api/kernel-api.rst index 06f4ab122697..0d0c4f87057c 100644 --- a/Documentation/core-api/kernel-api.rst +++ b/Documentation/core-api/kernel-api.rst @@ -36,6 +36,9 @@ String Conversions String Manipulation ------------------- +.. kernel-doc:: include/linux/fortify-string.h + :internal: + .. kernel-doc:: lib/string.c :export: diff --git a/include/linux/fortify-string.h b/include/linux/fortify-string.h index 0f00a551939a..e5b39b1cc2fc 100644 --- a/include/linux/fortify-string.h +++ b/include/linux/fortify-string.h @@ -106,13 +106,13 @@ extern char *__underlying_strncpy(char *p, const char *q, __kernel_size_t size) * Instead, please choose an alternative, so that the expectation * of @p's contents is unambiguous: * - * +--------------------+-----------------+------------+ - * | @p needs to be: | padded to @size | not padded | - * +====================+=================+============+ - * | NUL-terminated | strscpy_pad() | strscpy() | - * +--------------------+-----------------+------------+ - * | not NUL-terminated | strtomem_pad() | strtomem() | - * +--------------------+-----------------+------------+ + * +--------------------+--------------------+------------+ + * | **p** needs to be: | padded to **size** | not padded | + * +====================+====================+============+ + * | NUL-terminated | strscpy_pad() | strscpy() | + * +--------------------+--------------------+------------+ + * | not NUL-terminated | strtomem_pad() | strtomem() | + * +--------------------+--------------------+------------+ * * Note strscpy*()'s differing return values for detecting truncation, * and strtomem*()'s expectation that the destination is marked with @@ -131,6 +131,21 @@ char *strncpy(char * const POS p, const char *q, __kernel_size_t size) return __underlying_strncpy(p, q, size); } +/** + * strcat - Append a string to an existing string + * + * @p: pointer to NUL-terminated string to append to + * @q: pointer to NUL-terminated source string to append from + * + * Do not use this function. While FORTIFY_SOURCE tries to avoid + * read and write overflows, this is only possible when the + * destination buffer size is known to the compiler. Prefer + * building the string with formatting, via scnprintf() or similar. + * At the very least, use strncat(). + * + * Returns @p. + * + */ __FORTIFY_INLINE __diagnose_as(__builtin_strcat, 1, 2) char *strcat(char * const POS p, const char *q) { @@ -144,6 +159,16 @@ char *strcat(char * const POS p, const char *q) } extern __kernel_size_t __real_strnlen(const char *, __kernel_size_t) __RENAME(strnlen); +/** + * strnlen - Return bounded count of characters in a NUL-terminated string + * + * @p: pointer to NUL-terminated string to count. + * @maxlen: maximum number of characters to count. + * + * Returns number of characters in @p (NOT including the final NUL), or + * @maxlen, if no NUL has been found up to there. + * + */ __FORTIFY_INLINE __kernel_size_t strnlen(const char * const POS p, __kernel_size_t maxlen) { size_t p_size = __member_size(p); @@ -169,6 +194,19 @@ __FORTIFY_INLINE __kernel_size_t strnlen(const char * const POS p, __kernel_size * possible for strlen() to be used on compile-time strings for use in * static initializers (i.e. as a constant expression). */ +/** + * strlen - Return count of characters in a NUL-terminated string + * + * @p: pointer to NUL-terminated string to count. + * + * Do not use this function unless the string length is known at + * compile-time. When @p is unterminated, this function may crash + * or return unexpected counts that could lead to memory content + * exposures. Prefer strnlen(). + * + * Returns number of characters in @p (NOT including the final NUL). + * + */ #define strlen(p) \ __builtin_choose_expr(__is_constexpr(__builtin_strlen(p)), \ __builtin_strlen(p), __fortify_strlen(p)) @@ -187,8 +225,26 @@ __kernel_size_t __fortify_strlen(const char * const POS p) return ret; } -/* defined after fortified strlen to reuse it */ +/* Defined after fortified strlen() to reuse it. */ extern size_t __real_strlcpy(char *, const char *, size_t) __RENAME(strlcpy); +/** + * strlcpy - Copy a string into another string buffer + * + * @p: pointer to destination of copy + * @q: pointer to NUL-terminated source string to copy + * @size: maximum number of bytes to write at @p + * + * If strlen(@q) >= @size, the copy of @q will be truncated at + * @size - 1 bytes. @p will always be NUL-terminated. + * + * Do not use this function. While FORTIFY_SOURCE tries to avoid + * over-reads when calculating strlen(@q), it is still possible. + * Prefer strscpy(), though note its different return values for + * detecting truncation. + * + * Returns total number of bytes written to @p, including terminating NUL. + * + */ __FORTIFY_INLINE size_t strlcpy(char * const POS p, const char * const POS q, size_t size) { size_t p_size = __member_size(p); @@ -214,8 +270,32 @@ __FORTIFY_INLINE size_t strlcpy(char * const POS p, const char * const POS q, si return q_len; } -/* defined after fortified strnlen to reuse it */ +/* Defined after fortified strnlen() to reuse it. */ extern ssize_t __real_strscpy(char *, const char *, size_t) __RENAME(strscpy); +/** + * strscpy - Copy a C-string into a sized buffer + * + * @p: Where to copy the string to + * @q: Where to copy the string from + * @size: Size of destination buffer + * + * Copy the source string @p, or as much of it as fits, into the destination + * @q buffer. The behavior is undefined if the string buffers overlap. The + * destination @p buffer is always NUL terminated, unless it's zero-sized. + * + * Preferred to strlcpy() since the API doesn't require reading memory + * from the source @q string beyond the specified @size bytes, and since + * the return value is easier to error-check than strlcpy()'s. + * In addition, the implementation is robust to the string changing out + * from underneath it, unlike the current strlcpy() implementation. + * + * Preferred to strncpy() since it always returns a valid string, and + * doesn't unnecessarily force the tail of the destination buffer to be + * zero padded. If padding is desired please use strscpy_pad(). + * + * Returns the number of characters copied in @p (not including the + * trailing %NUL) or -E2BIG if @size is 0 or the copy of @q was truncated. + */ __FORTIFY_INLINE ssize_t strscpy(char * const POS p, const char * const POS q, size_t size) { size_t len; @@ -261,7 +341,26 @@ __FORTIFY_INLINE ssize_t strscpy(char * const POS p, const char * const POS q, s return __real_strscpy(p, q, len); } -/* defined after fortified strlen and strnlen to reuse them */ +/** + * strncat - Append a string to an existing string + * + * @p: pointer to NUL-terminated string to append to + * @q: pointer to source string to append from + * @count: Maximum bytes to read from @q + * + * Appends at most @count bytes from @q (stopping at the first + * NUL byte) after the NUL-terminated string at @p. @p will be + * NUL-terminated. + * + * Do not use this function. While FORTIFY_SOURCE tries to avoid + * read and write overflows, this is only possible when the sizes + * of @p and @q are known to the compiler. Prefer building the + * string with formatting, via scnprintf() or similar. + * + * Returns @p. + * + */ +/* Defined after fortified strlen() and strnlen() to reuse them. */ __FORTIFY_INLINE __diagnose_as(__builtin_strncat, 1, 2, 3) char *strncat(char * const POS p, const char * const POS q, __kernel_size_t count) { @@ -572,6 +671,20 @@ __FORTIFY_INLINE void *kmemdup(const void * const POS0 p, size_t size, gfp_t gfp return __real_kmemdup(p, size, gfp); } +/** + * strcpy - Copy a string into another string buffer + * + * @p: pointer to destination of copy + * @q: pointer to NUL-terminated source string to copy + * + * Do not use this function. While FORTIFY_SOURCE tries to avoid + * overflows, this is only possible when the sizes of @q and @p are + * known to the compiler. Prefer strscpy(), though note its different + * return values for detecting truncation. + * + * Returns @p. + * + */ /* Defined after fortified strlen to reuse it. */ __FORTIFY_INLINE __diagnose_as(__builtin_strcpy, 1, 2) char *strcpy(char * const POS p, const char * const POS q) diff --git a/lib/string.c b/lib/string.c index 3371d26a0e39..4fb566ea610f 100644 --- a/lib/string.c +++ b/lib/string.c @@ -76,11 +76,6 @@ EXPORT_SYMBOL(strcasecmp); #endif #ifndef __HAVE_ARCH_STRCPY -/** - * strcpy - Copy a %NUL terminated string - * @dest: Where to copy the string to - * @src: Where to copy the string from - */ char *strcpy(char *dest, const char *src) { char *tmp = dest; @@ -93,19 +88,6 @@ EXPORT_SYMBOL(strcpy); #endif #ifndef __HAVE_ARCH_STRNCPY -/** - * strncpy - Copy a length-limited, C-string - * @dest: Where to copy the string to - * @src: Where to copy the string from - * @count: The maximum number of bytes to copy - * - * The result is not %NUL-terminated if the source exceeds - * @count bytes. - * - * In the case where the length of @src is less than that of - * count, the remainder of @dest will be padded with %NUL. - * - */ char *strncpy(char *dest, const char *src, size_t count) { char *tmp = dest; @@ -122,17 +104,6 @@ EXPORT_SYMBOL(strncpy); #endif #ifndef __HAVE_ARCH_STRLCPY -/** - * strlcpy - Copy a C-string into a sized buffer - * @dest: Where to copy the string to - * @src: Where to copy the string from - * @size: size of destination buffer - * - * Compatible with ``*BSD``: the result is always a valid - * NUL-terminated string that fits in the buffer (unless, - * of course, the buffer size is zero). It does not pad - * out the result like strncpy() does. - */ size_t strlcpy(char *dest, const char *src, size_t size) { size_t ret = strlen(src); @@ -148,30 +119,6 @@ EXPORT_SYMBOL(strlcpy); #endif #ifndef __HAVE_ARCH_STRSCPY -/** - * strscpy - Copy a C-string into a sized buffer - * @dest: Where to copy the string to - * @src: Where to copy the string from - * @count: Size of destination buffer - * - * Copy the string, or as much of it as fits, into the dest buffer. The - * behavior is undefined if the string buffers overlap. The destination - * buffer is always NUL terminated, unless it's zero-sized. - * - * Preferred to strlcpy() since the API doesn't require reading memory - * from the src string beyond the specified "count" bytes, and since - * the return value is easier to error-check than strlcpy()'s. - * In addition, the implementation is robust to the string changing out - * from underneath it, unlike the current strlcpy() implementation. - * - * Preferred to strncpy() since it always returns a valid string, and - * doesn't unnecessarily force the tail of the destination buffer to be - * zeroed. If zeroing is desired please use strscpy_pad(). - * - * Returns: - * * The number of characters copied (not including the trailing %NUL) - * * -E2BIG if count is 0 or @src was truncated. - */ ssize_t strscpy(char *dest, const char *src, size_t count) { const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS; @@ -266,11 +213,6 @@ char *stpcpy(char *__restrict__ dest, const char *__restrict__ src) EXPORT_SYMBOL(stpcpy); #ifndef __HAVE_ARCH_STRCAT -/** - * strcat - Append one %NUL-terminated string to another - * @dest: The string to be appended to - * @src: The string to append to it - */ char *strcat(char *dest, const char *src) { char *tmp = dest; @@ -285,15 +227,6 @@ EXPORT_SYMBOL(strcat); #endif #ifndef __HAVE_ARCH_STRNCAT -/** - * strncat - Append a length-limited, C-string to another - * @dest: The string to be appended to - * @src: The string to append to it - * @count: The maximum numbers of bytes to copy - * - * Note that in contrast to strncpy(), strncat() ensures the result is - * terminated. - */ char *strncat(char *dest, const char *src, size_t count) { char *tmp = dest; @@ -314,12 +247,6 @@ EXPORT_SYMBOL(strncat); #endif #ifndef __HAVE_ARCH_STRLCAT -/** - * strlcat - Append a length-limited, C-string to another - * @dest: The string to be appended to - * @src: The string to append to it - * @count: The size of the destination buffer. - */ size_t strlcat(char *dest, const char *src, size_t count) { size_t dsize = strlen(dest); @@ -484,10 +411,6 @@ EXPORT_SYMBOL(strnchr); #endif #ifndef __HAVE_ARCH_STRLEN -/** - * strlen - Find the length of a string - * @s: The string to be sized - */ size_t strlen(const char *s) { const char *sc; @@ -500,11 +423,6 @@ EXPORT_SYMBOL(strlen); #endif #ifndef __HAVE_ARCH_STRNLEN -/** - * strnlen - Find the length of a length-limited string - * @s: The string to be sized - * @count: The maximum number of bytes to search - */ size_t strnlen(const char *s, size_t count) { const char *sc; diff --git a/scripts/kernel-doc b/scripts/kernel-doc index aea04365bc69..adbc4d307770 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1448,6 +1448,8 @@ sub create_parameterlist($$$$) { foreach my $arg (split($splitter, $args)) { # strip comments $arg =~ s/\/\*.*\*\///; + # ignore argument attributes + $arg =~ s/\sPOS0?\s/ /; # strip leading/trailing spaces $arg =~ s/^\s*//; $arg =~ s/\s*$//; @@ -1657,6 +1659,7 @@ sub dump_function($$) { $prototype =~ s/^__inline +//; $prototype =~ s/^__always_inline +//; $prototype =~ s/^noinline +//; + $prototype =~ s/^__FORTIFY_INLINE +//; $prototype =~ s/__init +//; $prototype =~ s/__init_or_module +//; $prototype =~ s/__deprecated +//; @@ -1666,7 +1669,8 @@ sub dump_function($$) { $prototype =~ s/__weak +//; $prototype =~ s/__sched +//; $prototype =~ s/__printf\s*\(\s*\d*\s*,\s*\d*\s*\) +//; - $prototype =~ s/__alloc_size\s*\(\s*\d+\s*(?:,\s*\d+\s*)?\) +//; + $prototype =~ s/__(?:re)?alloc_size\s*\(\s*\d+\s*(?:,\s*\d+\s*)?\) +//; + $prototype =~ s/__diagnose_as\s*\(\s*\S+\s*(?:,\s*\d+\s*)*\) +//; my $define = $prototype =~ s/^#\s*define\s+//; #ak added $prototype =~ s/__attribute_const__ +//; $prototype =~ s/__attribute__\s*\(\( -- cgit v1.2.3 From b341b20d648bb7e9a3307c33163e7399f0913e66 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 28 Oct 2022 21:08:19 +0200 Subject: x86: Add prefix symbols for function padding When code is compiled with: -fpatchable-function-entry=${PADDING_BYTES},${PADDING_BYTES} functions will have PADDING_BYTES of NOP in front of them. Unwinders and other things that symbolize code locations will typically attribute these bytes to the preceding function. Given that these bytes nominally belong to the following symbol this mis-attribution is confusing. Inspired by the fact that CFI_CLANG emits __cfi_##name symbols to claim these bytes, use objtool to emit __pfx_##name symbols to do the same when CFI_CLANG is not used. This then shows the callthunk for symbol 'name' as: __pfx_##name+0x6/0x10 Signed-off-by: Peter Zijlstra (Intel) Tested-by: Yujie Liu Link: https://lkml.kernel.org/r/20221028194453.592512209@infradead.org --- arch/x86/Kconfig | 4 ++++ scripts/Makefile.lib | 1 + 2 files changed, 5 insertions(+) (limited to 'scripts') diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index b52ad13f0f44..32818aa1dca4 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -2471,6 +2471,10 @@ config CALL_THUNKS def_bool n select FUNCTION_ALIGNMENT_16B +config PREFIX_SYMBOLS + def_bool y + depends on CALL_THUNKS && !CFI_CLANG + menuconfig SPECULATION_MITIGATIONS bool "Mitigations for speculative execution vulnerabilities" default y diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 85f02756dc9c..2e03bcbf2b9b 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -265,6 +265,7 @@ objtool-args-$(CONFIG_STACK_VALIDATION) += --stackval objtool-args-$(CONFIG_HAVE_STATIC_CALL_INLINE) += --static-call objtool-args-$(CONFIG_HAVE_UACCESS_VALIDATION) += --uaccess objtool-args-$(CONFIG_GCOV_KERNEL) += --no-unreachable +objtool-args-$(CONFIG_PREFIX_SYMBOLS) += --prefix=$(CONFIG_FUNCTION_PADDING_BYTES) objtool-args = $(objtool-args-y) \ $(if $(delay-objtool), --link) \ -- cgit v1.2.3 From 931ab63664f02b17d2213ef36b83e1e50190a0aa Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 27 Oct 2022 11:28:14 +0200 Subject: x86/ibt: Implement FineIBT Implement an alternative CFI scheme that merges both the fine-grained nature of kCFI but also takes full advantage of the coarse grained hardware CFI as provided by IBT. To contrast: kCFI is a pure software CFI scheme and relies on being able to read text -- specifically the instruction *before* the target symbol, and does the hash validation *before* doing the call (otherwise control flow is compromised already). FineIBT is a software and hardware hybrid scheme; by ensuring every branch target starts with a hash validation it is possible to place the hash validation after the branch. This has several advantages: o the (hash) load is avoided; no memop; no RX requirement. o IBT WAIT-FOR-ENDBR state is a speculation stop; by placing the hash validation in the immediate instruction after the branch target there is a minimal speculation window and the whole is a viable defence against SpectreBHB. o Kees feels obliged to mention it is slightly more vulnerable when the attacker can write code. Obviously this patch relies on kCFI, but additionally it also relies on the padding from the call-depth-tracking patches. It uses this padding to place the hash-validation while the call-sites are re-written to modify the indirect target to be 16 bytes in front of the original target, thus hitting this new preamble. Notably, there is no hardware that needs call-depth-tracking (Skylake) and supports IBT (Tigerlake and onwards). Suggested-by: Joao Moreira (Intel) Signed-off-by: Peter Zijlstra (Intel) Reviewed-by: Kees Cook Link: https://lore.kernel.org/r/20221027092842.634714496@infradead.org --- arch/um/kernel/um_arch.c | 5 + arch/x86/Kconfig | 14 +- arch/x86/Makefile | 2 +- arch/x86/include/asm/alternative.h | 2 + arch/x86/include/asm/linkage.h | 6 +- arch/x86/kernel/alternative.c | 253 +++++++++++++++++++++++++++++++++++-- arch/x86/kernel/cpu/common.c | 1 + arch/x86/kernel/module.c | 20 ++- arch/x86/kernel/vmlinux.lds.S | 9 ++ include/linux/bpf.h | 2 +- scripts/Makefile.lib | 1 + 11 files changed, 294 insertions(+), 21 deletions(-) (limited to 'scripts') diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 8adf8e89b255..786b44dc20c9 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -444,6 +444,11 @@ void apply_returns(s32 *start, s32 *end) { } +void apply_fineibt(s32 *start_retpoline, s32 *end_retpoline, + s32 *start_cfi, s32 *end_cfi) +{ +} + void apply_alternatives(struct alt_instr *start, struct alt_instr *end) { } diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 32818aa1dca4..479ee63898f5 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -2463,17 +2463,27 @@ config FUNCTION_PADDING_BYTES default FUNCTION_PADDING_CFI if CFI_CLANG default FUNCTION_ALIGNMENT +config CALL_PADDING + def_bool n + depends on CC_HAS_ENTRY_PADDING && OBJTOOL + select FUNCTION_ALIGNMENT_16B + +config FINEIBT + def_bool y + depends on X86_KERNEL_IBT && CFI_CLANG && RETPOLINE + select CALL_PADDING + config HAVE_CALL_THUNKS def_bool y depends on CC_HAS_ENTRY_PADDING && RETHUNK && OBJTOOL config CALL_THUNKS def_bool n - select FUNCTION_ALIGNMENT_16B + select CALL_PADDING config PREFIX_SYMBOLS def_bool y - depends on CALL_THUNKS && !CFI_CLANG + depends on CALL_PADDING && !CFI_CLANG menuconfig SPECULATION_MITIGATIONS bool "Mitigations for speculative execution vulnerabilities" diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 1640e005092b..a3a07df8a609 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -208,7 +208,7 @@ ifdef CONFIG_SLS KBUILD_CFLAGS += -mharden-sls=all endif -ifdef CONFIG_CALL_THUNKS +ifdef CONFIG_CALL_PADDING PADDING_CFLAGS := -fpatchable-function-entry=$(CONFIG_FUNCTION_PADDING_BYTES),$(CONFIG_FUNCTION_PADDING_BYTES) KBUILD_CFLAGS += $(PADDING_CFLAGS) export PADDING_CFLAGS diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h index 664c0779375c..7659217f4d49 100644 --- a/arch/x86/include/asm/alternative.h +++ b/arch/x86/include/asm/alternative.h @@ -78,6 +78,8 @@ extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end); extern void apply_retpolines(s32 *start, s32 *end); extern void apply_returns(s32 *start, s32 *end); extern void apply_ibt_endbr(s32 *start, s32 *end); +extern void apply_fineibt(s32 *start_retpoline, s32 *end_retpoine, + s32 *start_cfi, s32 *end_cfi); struct module; struct paravirt_patch_site; diff --git a/arch/x86/include/asm/linkage.h b/arch/x86/include/asm/linkage.h index 45e0df850645..dd9b8118f784 100644 --- a/arch/x86/include/asm/linkage.h +++ b/arch/x86/include/asm/linkage.h @@ -15,7 +15,7 @@ #define __ALIGN .balign CONFIG_FUNCTION_ALIGNMENT, 0x90; #define __ALIGN_STR __stringify(__ALIGN) -#if defined(CONFIG_CALL_THUNKS) && !defined(__DISABLE_EXPORTS) && !defined(BUILD_VDSO) +#if defined(CONFIG_CALL_PADDING) && !defined(__DISABLE_EXPORTS) && !defined(BUILD_VDSO) #define FUNCTION_PADDING .skip CONFIG_FUNCTION_ALIGNMENT, 0x90; #else #define FUNCTION_PADDING @@ -57,7 +57,7 @@ #endif /* __ASSEMBLY__ */ /* - * Depending on -fpatchable-function-entry=N,N usage (CONFIG_CALL_THUNKS) the + * Depending on -fpatchable-function-entry=N,N usage (CONFIG_CALL_PADDING) the * CFI symbol layout changes. * * Without CALL_THUNKS: @@ -81,7 +81,7 @@ * In both cases the whole thing is FUNCTION_ALIGNMENT aligned and sized. */ -#ifdef CONFIG_CALL_THUNKS +#ifdef CONFIG_CALL_PADDING #define CFI_PRE_PADDING #define CFI_POST_PADDING .skip CONFIG_FUNCTION_PADDING_BYTES, 0x90; #else diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index b4ac4e58c010..91b0e63a6238 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -116,6 +116,7 @@ static void __init_or_module add_nops(void *insns, unsigned int len) extern s32 __retpoline_sites[], __retpoline_sites_end[]; extern s32 __return_sites[], __return_sites_end[]; +extern s32 __cfi_sites[], __cfi_sites_end[]; extern s32 __ibt_endbr_seal[], __ibt_endbr_seal_end[]; extern struct alt_instr __alt_instructions[], __alt_instructions_end[]; extern s32 __smp_locks[], __smp_locks_end[]; @@ -656,6 +657,28 @@ void __init_or_module noinline apply_returns(s32 *start, s32 *end) { } #ifdef CONFIG_X86_KERNEL_IBT +static void poison_endbr(void *addr, bool warn) +{ + u32 endbr, poison = gen_endbr_poison(); + + if (WARN_ON_ONCE(get_kernel_nofault(endbr, addr))) + return; + + if (!is_endbr(endbr)) { + WARN_ON_ONCE(warn); + return; + } + + DPRINTK("ENDBR at: %pS (%px)", addr, addr); + + /* + * When we have IBT, the lack of ENDBR will trigger #CP + */ + DUMP_BYTES(((u8*)addr), 4, "%px: orig: ", addr); + DUMP_BYTES(((u8*)&poison), 4, "%px: repl: ", addr); + text_poke_early(addr, &poison, 4); +} + /* * Generated by: objtool --ibt */ @@ -664,31 +687,232 @@ void __init_or_module noinline apply_ibt_endbr(s32 *start, s32 *end) s32 *s; for (s = start; s < end; s++) { - u32 endbr, poison = gen_endbr_poison(); void *addr = (void *)s + *s; - if (WARN_ON_ONCE(get_kernel_nofault(endbr, addr))) - continue; + poison_endbr(addr, true); + if (IS_ENABLED(CONFIG_FINEIBT)) + poison_endbr(addr - 16, false); + } +} + +#else + +void __init_or_module noinline apply_ibt_endbr(s32 *start, s32 *end) { } + +#endif /* CONFIG_X86_KERNEL_IBT */ + +#ifdef CONFIG_FINEIBT +/* + * kCFI FineIBT + * + * __cfi_\func: __cfi_\func: + * movl $0x12345678,%eax // 5 endbr64 // 4 + * nop subl $0x12345678,%r10d // 7 + * nop jz 1f // 2 + * nop ud2 // 2 + * nop 1: nop // 1 + * nop + * nop + * nop + * nop + * nop + * nop + * nop + * + * + * caller: caller: + * movl $(-0x12345678),%r10d // 6 movl $0x12345678,%r10d // 6 + * addl $-15(%r11),%r10d // 4 sub $16,%r11 // 4 + * je 1f // 2 nop4 // 4 + * ud2 // 2 + * 1: call __x86_indirect_thunk_r11 // 5 call *%r11; nop2; // 5 + * + */ + +asm( ".pushsection .rodata \n" + "fineibt_preamble_start: \n" + " endbr64 \n" + " subl $0x12345678, %r10d \n" + " je fineibt_preamble_end \n" + " ud2 \n" + " nop \n" + "fineibt_preamble_end: \n" + ".popsection\n" +); + +extern u8 fineibt_preamble_start[]; +extern u8 fineibt_preamble_end[]; + +#define fineibt_preamble_size (fineibt_preamble_end - fineibt_preamble_start) +#define fineibt_preamble_hash 7 + +asm( ".pushsection .rodata \n" + "fineibt_caller_start: \n" + " movl $0x12345678, %r10d \n" + " sub $16, %r11 \n" + ASM_NOP4 + "fineibt_caller_end: \n" + ".popsection \n" +); + +extern u8 fineibt_caller_start[]; +extern u8 fineibt_caller_end[]; + +#define fineibt_caller_size (fineibt_caller_end - fineibt_caller_start) +#define fineibt_caller_hash 2 + +#define fineibt_caller_jmp (fineibt_caller_size - 2) + +static u32 decode_preamble_hash(void *addr) +{ + u8 *p = addr; + + /* b8 78 56 34 12 mov $0x12345678,%eax */ + if (p[0] == 0xb8) + return *(u32 *)(addr + 1); + + return 0; /* invalid hash value */ +} + +static u32 decode_caller_hash(void *addr) +{ + u8 *p = addr; + + /* 41 ba 78 56 34 12 mov $0x12345678,%r10d */ + if (p[0] == 0x41 && p[1] == 0xba) + return -*(u32 *)(addr + 2); + + /* e8 0c 78 56 34 12 jmp.d8 +12 */ + if (p[0] == JMP8_INSN_OPCODE && p[1] == fineibt_caller_jmp) + return -*(u32 *)(addr + 2); + + return 0; /* invalid hash value */ +} + +/* .retpoline_sites */ +static int cfi_disable_callers(s32 *start, s32 *end) +{ + /* + * Disable kCFI by patching in a JMP.d8, this leaves the hash immediate + * in tact for later usage. Also see decode_caller_hash() and + * cfi_rewrite_callers(). + */ + const u8 jmp[] = { JMP8_INSN_OPCODE, fineibt_caller_jmp }; + s32 *s; - if (WARN_ON_ONCE(!is_endbr(endbr))) + for (s = start; s < end; s++) { + void *addr = (void *)s + *s; + u32 hash; + + addr -= fineibt_caller_size; + hash = decode_caller_hash(addr); + if (!hash) /* nocfi callers */ continue; - DPRINTK("ENDBR at: %pS (%px)", addr, addr); + text_poke_early(addr, jmp, 2); + } - /* - * When we have IBT, the lack of ENDBR will trigger #CP - */ - DUMP_BYTES(((u8*)addr), 4, "%px: orig: ", addr); - DUMP_BYTES(((u8*)&poison), 4, "%px: repl: ", addr); - text_poke_early(addr, &poison, 4); + return 0; +} + +/* .cfi_sites */ +static int cfi_rewrite_preamble(s32 *start, s32 *end) +{ + s32 *s; + + for (s = start; s < end; s++) { + void *addr = (void *)s + *s; + u32 hash; + + hash = decode_preamble_hash(addr); + if (WARN(!hash, "no CFI hash found at: %pS %px %*ph\n", + addr, addr, 5, addr)) + return -EINVAL; + + text_poke_early(addr, fineibt_preamble_start, fineibt_preamble_size); + WARN_ON(*(u32 *)(addr + fineibt_preamble_hash) != 0x12345678); + text_poke_early(addr + fineibt_preamble_hash, &hash, 4); } + + return 0; +} + +/* .retpoline_sites */ +static int cfi_rewrite_callers(s32 *start, s32 *end) +{ + s32 *s; + + for (s = start; s < end; s++) { + void *addr = (void *)s + *s; + u32 hash; + + addr -= fineibt_caller_size; + hash = decode_caller_hash(addr); + if (hash) { + text_poke_early(addr, fineibt_caller_start, fineibt_caller_size); + WARN_ON(*(u32 *)(addr + fineibt_caller_hash) != 0x12345678); + text_poke_early(addr + fineibt_caller_hash, &hash, 4); + } + /* rely on apply_retpolines() */ + } + + return 0; +} + +static void __apply_fineibt(s32 *start_retpoline, s32 *end_retpoline, + s32 *start_cfi, s32 *end_cfi, bool builtin) +{ + int ret; + + if (WARN_ONCE(fineibt_preamble_size != 16, + "FineIBT preamble wrong size: %ld", fineibt_preamble_size)) + return; + + if (!HAS_KERNEL_IBT || !cpu_feature_enabled(X86_FEATURE_IBT)) + return; + + /* + * Rewrite the callers to not use the __cfi_ stubs, such that we might + * rewrite them. This disables all CFI. If this succeeds but any of the + * later stages fails, we're without CFI. + */ + ret = cfi_disable_callers(start_retpoline, end_retpoline); + if (ret) + goto err; + + ret = cfi_rewrite_preamble(start_cfi, end_cfi); + if (ret) + goto err; + + ret = cfi_rewrite_callers(start_retpoline, end_retpoline); + if (ret) + goto err; + + if (builtin) + pr_info("Using FineIBT CFI\n"); + + return; + +err: + pr_err("Something went horribly wrong trying to rewrite the CFI implementation.\n"); } #else -void __init_or_module noinline apply_ibt_endbr(s32 *start, s32 *end) { } +static void __apply_fineibt(s32 *start_retpoline, s32 *end_retpoline, + s32 *start_cfi, s32 *end_cfi, bool builtin) +{ +} -#endif /* CONFIG_X86_KERNEL_IBT */ +#endif + +void apply_fineibt(s32 *start_retpoline, s32 *end_retpoline, + s32 *start_cfi, s32 *end_cfi) +{ + return __apply_fineibt(start_retpoline, end_retpoline, + start_cfi, end_cfi, + /* .builtin = */ false); +} #ifdef CONFIG_SMP static void alternatives_smp_lock(const s32 *start, const s32 *end, @@ -996,6 +1220,9 @@ void __init alternative_instructions(void) */ apply_paravirt(__parainstructions, __parainstructions_end); + __apply_fineibt(__retpoline_sites, __retpoline_sites_end, + __cfi_sites, __cfi_sites_end, true); + /* * Rewrite the retpolines, must be done before alternatives since * those can rewrite the retpoline thunks. diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 2bec4b4b2c50..423a760fa9de 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -609,6 +609,7 @@ static __always_inline void setup_cet(struct cpuinfo_x86 *c) if (!ibt_selftest()) { pr_err("IBT selftest: Failed!\n"); + wrmsrl(MSR_IA32_S_CET, 0); setup_clear_cpu_cap(X86_FEATURE_IBT); return; } diff --git a/arch/x86/kernel/module.c b/arch/x86/kernel/module.c index 2fb9de2cef40..0142982e94c5 100644 --- a/arch/x86/kernel/module.c +++ b/arch/x86/kernel/module.c @@ -255,7 +255,7 @@ int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *s, *text = NULL, *alt = NULL, *locks = NULL, *para = NULL, *orc = NULL, *orc_ip = NULL, *retpolines = NULL, *returns = NULL, *ibt_endbr = NULL, - *calls = NULL; + *calls = NULL, *cfi = NULL; char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) { @@ -277,6 +277,8 @@ int module_finalize(const Elf_Ehdr *hdr, returns = s; if (!strcmp(".call_sites", secstrings + s->sh_name)) calls = s; + if (!strcmp(".cfi_sites", secstrings + s->sh_name)) + cfi = s; if (!strcmp(".ibt_endbr_seal", secstrings + s->sh_name)) ibt_endbr = s; } @@ -289,6 +291,22 @@ int module_finalize(const Elf_Ehdr *hdr, void *pseg = (void *)para->sh_addr; apply_paravirt(pseg, pseg + para->sh_size); } + if (retpolines || cfi) { + void *rseg = NULL, *cseg = NULL; + unsigned int rsize = 0, csize = 0; + + if (retpolines) { + rseg = (void *)retpolines->sh_addr; + rsize = retpolines->sh_size; + } + + if (cfi) { + cseg = (void *)cfi->sh_addr; + csize = cfi->sh_size; + } + + apply_fineibt(rseg, rseg + rsize, cseg, cseg + csize); + } if (retpolines) { void *rseg = (void *)retpolines->sh_addr; apply_retpolines(rseg, rseg + retpolines->sh_size); diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S index 49f3f86433c7..2e0ee14229bf 100644 --- a/arch/x86/kernel/vmlinux.lds.S +++ b/arch/x86/kernel/vmlinux.lds.S @@ -309,6 +309,15 @@ SECTIONS } #endif +#ifdef CONFIG_FINEIBT + . = ALIGN(8); + .cfi_sites : AT(ADDR(.cfi_sites) - LOAD_OFFSET) { + __cfi_sites = .; + *(.cfi_sites) + __cfi_sites_end = .; + } +#endif + /* * struct alt_inst entries. From the header (alternative.h): * "Alternative instructions for different CPU types or capabilities" diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 5296aea9b5b4..923a3d508047 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -984,7 +984,7 @@ int arch_prepare_bpf_dispatcher(void *image, void *buf, s64 *funcs, int num_func } #ifdef CONFIG_X86_64 -#ifdef CONFIG_CALL_THUNKS +#ifdef CONFIG_CALL_PADDING #define BPF_DISPATCHER_ATTRIBUTES __attribute__((patchable_function_entry(5+CONFIG_FUNCTION_PADDING_BYTES,CONFIG_FUNCTION_PADDING_BYTES))) #else #define BPF_DISPATCHER_ATTRIBUTES __attribute__((patchable_function_entry(5))) diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 2e03bcbf2b9b..2b2fab705a63 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -256,6 +256,7 @@ objtool-args-$(CONFIG_HAVE_JUMP_LABEL_HACK) += --hacks=jump_label objtool-args-$(CONFIG_HAVE_NOINSTR_HACK) += --hacks=noinstr objtool-args-$(CONFIG_CALL_DEPTH_TRACKING) += --hacks=skylake objtool-args-$(CONFIG_X86_KERNEL_IBT) += --ibt +objtool-args-$(CONFIG_FINEIBT) += --cfi objtool-args-$(CONFIG_FTRACE_MCOUNT_USE_OBJTOOL) += --mcount objtool-args-$(CONFIG_UNWINDER_ORC) += --orc objtool-args-$(CONFIG_RETPOLINE) += --retpoline -- cgit v1.2.3 From 994b7ac1697b4581b7726d2ac64321e3c840229b Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 13 Oct 2022 08:35:00 +0900 Subject: arm64: remove special treatment for the link order of head.o In the previous discussion (see the Link tag), Ard pointed out that arm/arm64/kernel/head.o does not need any special treatment - the only piece that must appear right at the start of the binary image is the image header which is emitted into .head.text. The linker script does the right thing to do. The build system does not need to manipulate the link order of head.o. Link: https://lore.kernel.org/lkml/CAMj1kXH77Ja8bSsq2Qj8Ck9iSZKw=1F8Uy-uAWGVDm4-CG=EuA@mail.gmail.com/ Suggested-by: Ard Biesheuvel Signed-off-by: Masahiro Yamada Reviewed-by: Nicolas Schier Link: https://lore.kernel.org/r/20221012233500.156764-1-masahiroy@kernel.org Signed-off-by: Will Deacon --- scripts/head-object-list.txt | 1 - 1 file changed, 1 deletion(-) (limited to 'scripts') diff --git a/scripts/head-object-list.txt b/scripts/head-object-list.txt index b16326a92c45..f226e45e3b7b 100644 --- a/scripts/head-object-list.txt +++ b/scripts/head-object-list.txt @@ -15,7 +15,6 @@ arch/alpha/kernel/head.o arch/arc/kernel/head.o arch/arm/kernel/head-nommu.o arch/arm/kernel/head.o -arch/arm64/kernel/head.o arch/csky/kernel/head.o arch/hexagon/kernel/head.o arch/ia64/kernel/head.o -- cgit v1.2.3 From 68c76ad4a9571a2b603665c85cf8229bcf04982a Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 27 Oct 2022 17:59:06 +0200 Subject: arm64: unwind: add asynchronous unwind tables to kernel and modules Enable asynchronous unwind table generation for both the core kernel as well as modules, and emit the resulting .eh_frame sections as init code so we can use the unwind directives for code patching at boot or module load time. This will be used by dynamic shadow call stack support, which will rely on code patching rather than compiler codegen to emit the shadow call stack push and pop instructions. Signed-off-by: Ard Biesheuvel Reviewed-by: Nick Desaulniers Reviewed-by: Sami Tolvanen Tested-by: Sami Tolvanen Link: https://lore.kernel.org/r/20221027155908.1940624-2-ardb@kernel.org Signed-off-by: Will Deacon --- arch/arm64/Kconfig | 3 +++ arch/arm64/Makefile | 5 +++++ arch/arm64/include/asm/module.lds.h | 8 ++++++++ arch/arm64/kernel/pi/Makefile | 1 + arch/arm64/kernel/vmlinux.lds.S | 13 +++++++++++++ arch/arm64/kvm/hyp/nvhe/Makefile | 1 + drivers/firmware/efi/libstub/Makefile | 1 + include/asm-generic/vmlinux.lds.h | 9 +++++++-- scripts/module.lds.S | 6 ++++++ 9 files changed, 45 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 505c8a1ccbe0..7e3a9cf2193d 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -370,6 +370,9 @@ config KASAN_SHADOW_OFFSET default 0xeffffff800000000 if ARM64_VA_BITS_36 && KASAN_SW_TAGS default 0xffffffffffffffff +config UNWIND_TABLES + bool + source "arch/arm64/Kconfig.platforms" menu "Kernel Features" diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile index 5e56d26a2239..7868a176993f 100644 --- a/arch/arm64/Makefile +++ b/arch/arm64/Makefile @@ -45,8 +45,13 @@ KBUILD_CFLAGS += $(call cc-option,-mabi=lp64) KBUILD_AFLAGS += $(call cc-option,-mabi=lp64) # Avoid generating .eh_frame* sections. +ifneq ($(CONFIG_UNWIND_TABLES),y) KBUILD_CFLAGS += -fno-asynchronous-unwind-tables -fno-unwind-tables KBUILD_AFLAGS += -fno-asynchronous-unwind-tables -fno-unwind-tables +else +KBUILD_CFLAGS += -fasynchronous-unwind-tables +KBUILD_AFLAGS += -fasynchronous-unwind-tables +endif ifeq ($(CONFIG_STACKPROTECTOR_PER_TASK),y) prepare: stack_protector_prepare diff --git a/arch/arm64/include/asm/module.lds.h b/arch/arm64/include/asm/module.lds.h index 094701ec5500..dbba4b7559aa 100644 --- a/arch/arm64/include/asm/module.lds.h +++ b/arch/arm64/include/asm/module.lds.h @@ -17,4 +17,12 @@ SECTIONS { */ .text.hot : { *(.text.hot) } #endif + +#ifdef CONFIG_UNWIND_TABLES + /* + * Currently, we only use unwind info at module load time, so we can + * put it into the .init allocation. + */ + .init.eh_frame : { *(.eh_frame) } +#endif } diff --git a/arch/arm64/kernel/pi/Makefile b/arch/arm64/kernel/pi/Makefile index 839291430cb3..4c0ea3cd4ea4 100644 --- a/arch/arm64/kernel/pi/Makefile +++ b/arch/arm64/kernel/pi/Makefile @@ -7,6 +7,7 @@ KBUILD_CFLAGS := $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) -fpie \ -I$(srctree)/scripts/dtc/libfdt -fno-stack-protector \ -include $(srctree)/include/linux/hidden.h \ -D__DISABLE_EXPORTS -ffreestanding -D__NO_FORTIFY \ + -fno-asynchronous-unwind-tables -fno-unwind-tables \ $(call cc-option,-fno-addrsig) # remove SCS flags from all objects in this directory diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S index 45131e354e27..4c13dafc98b8 100644 --- a/arch/arm64/kernel/vmlinux.lds.S +++ b/arch/arm64/kernel/vmlinux.lds.S @@ -121,6 +121,17 @@ jiffies = jiffies_64; #define TRAMP_TEXT #endif +#ifdef CONFIG_UNWIND_TABLES +#define UNWIND_DATA_SECTIONS \ + .eh_frame : { \ + __eh_frame_start = .; \ + *(.eh_frame) \ + __eh_frame_end = .; \ + } +#else +#define UNWIND_DATA_SECTIONS +#endif + /* * The size of the PE/COFF section that covers the kernel image, which * runs from _stext to _edata, must be a round multiple of the PE/COFF @@ -231,6 +242,8 @@ SECTIONS __alt_instructions_end = .; } + UNWIND_DATA_SECTIONS + . = ALIGN(SEGMENT_ALIGN); __inittext_end = .; __initdata_begin = .; diff --git a/arch/arm64/kvm/hyp/nvhe/Makefile b/arch/arm64/kvm/hyp/nvhe/Makefile index be0a2bc3e20d..530347cdebe3 100644 --- a/arch/arm64/kvm/hyp/nvhe/Makefile +++ b/arch/arm64/kvm/hyp/nvhe/Makefile @@ -96,6 +96,7 @@ KBUILD_CFLAGS := $(filter-out $(CC_FLAGS_FTRACE) $(CC_FLAGS_SCS) $(CC_FLAGS_CFI) # when profile optimization is applied. gen-hyprel does not support SHT_REL and # causes a build failure. Remove profile optimization flags. KBUILD_CFLAGS := $(filter-out -fprofile-sample-use=% -fprofile-use=%, $(KBUILD_CFLAGS)) +KBUILD_CFLAGS += -fno-asynchronous-unwind-tables -fno-unwind-tables # KVM nVHE code is run at a different exception code with a different map, so # compiler instrumentation that inserts callbacks or checks into the code may diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile index b1601aad7e1a..1016f0b5311d 100644 --- a/drivers/firmware/efi/libstub/Makefile +++ b/drivers/firmware/efi/libstub/Makefile @@ -20,6 +20,7 @@ cflags-$(CONFIG_X86) += -m$(BITS) -D__KERNEL__ \ # disable the stackleak plugin cflags-$(CONFIG_ARM64) := $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \ -fpie $(DISABLE_STACKLEAK_PLUGIN) \ + -fno-unwind-tables -fno-asynchronous-unwind-tables \ $(call cc-option,-mbranch-protection=none) cflags-$(CONFIG_ARM) := $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \ -fno-builtin -fpic \ diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index d06ada2341cb..0cca179e5106 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -1027,14 +1027,19 @@ * keep any .init_array.* sections. * https://bugs.llvm.org/show_bug.cgi?id=46478 */ +#ifdef CONFIG_UNWIND_TABLES +#define DISCARD_EH_FRAME +#else +#define DISCARD_EH_FRAME *(.eh_frame) +#endif #if defined(CONFIG_GCOV_KERNEL) || defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KCSAN) # ifdef CONFIG_CONSTRUCTORS # define SANITIZER_DISCARDS \ - *(.eh_frame) + DISCARD_EH_FRAME # else # define SANITIZER_DISCARDS \ *(.init_array) *(.init_array.*) \ - *(.eh_frame) + DISCARD_EH_FRAME # endif #else # define SANITIZER_DISCARDS diff --git a/scripts/module.lds.S b/scripts/module.lds.S index da4bddd26171..bf5bcf2836d8 100644 --- a/scripts/module.lds.S +++ b/scripts/module.lds.S @@ -3,6 +3,12 @@ * Archs are free to supply their own linker scripts. ld will * combine them automatically. */ +#ifdef CONFIG_UNWIND_TABLES +#define DISCARD_EH_FRAME +#else +#define DISCARD_EH_FRAME *(.eh_frame) +#endif + SECTIONS { /DISCARD/ : { *(.discard) -- cgit v1.2.3 From ea3723a541c198c84e81a0e975dba6c18764393e Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 1 Nov 2022 12:54:44 -0500 Subject: scripts/dtc: Update to upstream version v1.6.1-63-g55778a03df61 It's been a while since the last sync and Lee needs commit 73590342fc85 ("libfdt: prevent integer overflow in fdt_next_tag"). This adds the following commits from upstream: 55778a03df61 libfdt: tests: add get_next_tag_invalid_prop_len 73590342fc85 libfdt: prevent integer overflow in fdt_next_tag 035fb90d5375 libfdt: add fdt_get_property_by_offset_w helper 98a07006c48d Makefile: fix infinite recursion by dropping non-existent `%.output` a036cc7b0c10 Makefile: limit make re-execution to avoid infinite spin c6e92108bcd9 libdtc: remove duplicate judgments e37c25677dc9 Don't generate erroneous fixups from reference to path 50454658f2b5 libfdt: Don't mask fdt_get_name() returned error e64a204196c9 manual.txt: Follow README.md and remove Jon f508c83fe6f0 Update README in MANIFEST.in and setup.py to README.md c2ccf8a77dd2 Add description of Signed-off-by lines 90b9d9de42ca Split out information for contributors to CONTRIBUTING.md 0ee1d479b23a Remove Jon Loeliger from maintainers list b33a73c62c1c Convert README to README.md 7ad60734b1c1 Allow static building with meson fd9b8c96c780 Allow static building with make fda71da26e7f libfdt: Handle failed get_name() on BEGIN_NODE c7c7f17a83d5 Fix test script to run also on dash shell 01f23ffe1679 Add missing relref_merge test to meson test list ed310803ea89 pylibfdt: add FdtRo.get_path() c001fc01a43e pylibfdt: fix swig build in install 26c54f840d23 tests: add test cases for label-relative path references ec7986e682cf dtc: introduce label relative path references 651410e54cb9 util: introduce xstrndup helper 4048aed12b81 setup.py: fix out of tree build ff5afb96d0c0 Handle integer overflow in check_property_phandle_args() ca7294434309 README: Explain how to add a new API function c0c2e115f82e Fix a UB when fdt_get_string return null cd5f69cbc0d4 tests: setprop_inplace: use xstrdup instead of unchecked strdup a04f69025003 pylibfdt: add Property.as_*int*_array() 83102717d7c4 pylibfdt: add Property.as_stringlist() d152126bb029 Fix Python crash on getprop deallocation 17739b7ef510 Support 'r' format for printing raw bytes with fdtget 45f3d1a095dd libfdt: overlay: make overlay_get_target() public c19a4bafa514 libfdt: fix an incorrect integer promotion 1cc41b1c969f pylibfdt: Add packaging metadata db72398cd437 README: Update pylibfdt install instructions 383e148b70a4 pylibfdt: fix with Python 3.10 23b56cb7e189 pylibfdt: Move setup.py to the top level 69a760747d8d pylibfdt: Split setup.py author name and email 0b106a77dbdc pylibfdt: Use setuptools_scm for the version c691776ddb26 pylibfdt: Use setuptools instead of distutils 5216f3f1bbb7 libfdt: Add static lib to meson build 4eda2590f481 CI: Cirrus: bump used FreeBSD from 12.1 to 13.0 Link: https://lore.kernel.org/r/20221101181427.1808703-1-robh@kernel.org/ Signed-off-by: Rob Herring --- scripts/dtc/checks.c | 15 +++++++++------ scripts/dtc/dtc-lexer.l | 2 +- scripts/dtc/dtc-parser.y | 13 +++++++++++++ scripts/dtc/libfdt/fdt.c | 20 +++++++++++-------- scripts/dtc/libfdt/fdt.h | 4 ++-- scripts/dtc/libfdt/fdt_addresses.c | 2 +- scripts/dtc/libfdt/fdt_overlay.c | 29 +++++++--------------------- scripts/dtc/libfdt/fdt_ro.c | 2 +- scripts/dtc/libfdt/libfdt.h | 25 ++++++++++++++++++++++++ scripts/dtc/livetree.c | 39 +++++++++++++++++++++++++++++++++++--- scripts/dtc/util.c | 15 +++++++++++++-- scripts/dtc/util.h | 4 +++- scripts/dtc/version_gen.h | 2 +- 13 files changed, 124 insertions(+), 48 deletions(-) (limited to 'scripts') diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c index 781ba1129a8e..9f31d2607182 100644 --- a/scripts/dtc/checks.c +++ b/scripts/dtc/checks.c @@ -1382,10 +1382,10 @@ struct provider { }; static void check_property_phandle_args(struct check *c, - struct dt_info *dti, - struct node *node, - struct property *prop, - const struct provider *provider) + struct dt_info *dti, + struct node *node, + struct property *prop, + const struct provider *provider) { struct node *root = dti->dt; unsigned int cell, cellsize = 0; @@ -1401,6 +1401,7 @@ static void check_property_phandle_args(struct check *c, struct node *provider_node; struct property *cellprop; cell_t phandle; + unsigned int expected; phandle = propval_cell_n(prop, cell); /* @@ -1450,10 +1451,12 @@ static void check_property_phandle_args(struct check *c, break; } - if (prop->val.len < ((cell + cellsize + 1) * sizeof(cell_t))) { + expected = (cell + cellsize + 1) * sizeof(cell_t); + if ((expected <= cell) || prop->val.len < expected) { FAIL_PROP(c, dti, node, prop, - "property size (%d) too small for cell size %d", + "property size (%d) too small for cell size %u", prop->val.len, cellsize); + break; } } } diff --git a/scripts/dtc/dtc-lexer.l b/scripts/dtc/dtc-lexer.l index 5568b4ae84cf..de60a70b6bdb 100644 --- a/scripts/dtc/dtc-lexer.l +++ b/scripts/dtc/dtc-lexer.l @@ -200,7 +200,7 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...); return DT_LABEL_REF; } -<*>"&{/"{PATHCHAR}*\} { /* new-style path reference */ +<*>"&{"{PATHCHAR}*\} { /* new-style path reference */ yytext[yyleng-1] = '\0'; DPRINT("Ref: %s\n", yytext+2); yylval.labelref = xstrdup(yytext+2); diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y index a0316a3cc309..46457d4bc0aa 100644 --- a/scripts/dtc/dtc-parser.y +++ b/scripts/dtc/dtc-parser.y @@ -23,6 +23,12 @@ extern void yyerror(char const *s); extern struct dt_info *parser_output; extern bool treesource_error; + +static bool is_ref_relative(const char *ref) +{ + return ref[0] != '/' && strchr(&ref[1], '/'); +} + %} %union { @@ -169,6 +175,8 @@ devicetree: */ if (!($-1 & DTSF_PLUGIN)) ERROR(&@2, "Label or path %s not found", $1); + else if (is_ref_relative($1)) + ERROR(&@2, "Label-relative reference %s not supported in plugin", $1); $$ = add_orphan_node( name_node(build_node(NULL, NULL, NULL), ""), @@ -178,6 +186,9 @@ devicetree: { struct node *target = get_node_by_ref($1, $3); + if (($-1 & DTSF_PLUGIN) && is_ref_relative($3)) + ERROR(&@2, "Label-relative reference %s not supported in plugin", $3); + if (target) { add_label(&target->labels, $2); merge_nodes(target, $4); @@ -193,6 +204,8 @@ devicetree: * so $-1 is what we want (plugindecl) */ if ($-1 & DTSF_PLUGIN) { + if (is_ref_relative($2)) + ERROR(&@2, "Label-relative reference %s not supported in plugin", $2); add_orphan_node($1, $3, $2); } else { struct node *target = get_node_by_ref($1, $2); diff --git a/scripts/dtc/libfdt/fdt.c b/scripts/dtc/libfdt/fdt.c index 9fe7cf4b747d..20c6415b9ced 100644 --- a/scripts/dtc/libfdt/fdt.c +++ b/scripts/dtc/libfdt/fdt.c @@ -106,7 +106,6 @@ int fdt_check_header(const void *fdt) } hdrsize = fdt_header_size(fdt); if (!can_assume(VALID_DTB)) { - if ((fdt_totalsize(fdt) < hdrsize) || (fdt_totalsize(fdt) > INT_MAX)) return -FDT_ERR_TRUNCATED; @@ -115,9 +114,7 @@ int fdt_check_header(const void *fdt) if (!check_off_(hdrsize, fdt_totalsize(fdt), fdt_off_mem_rsvmap(fdt))) return -FDT_ERR_TRUNCATED; - } - if (!can_assume(VALID_DTB)) { /* Bounds check structure block */ if (!can_assume(LATEST) && fdt_version(fdt) < 17) { if (!check_off_(hdrsize, fdt_totalsize(fdt), @@ -165,7 +162,7 @@ const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) { const fdt32_t *tagp, *lenp; - uint32_t tag; + uint32_t tag, len, sum; int offset = startoffset; const char *p; @@ -191,12 +188,19 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp)); if (!can_assume(VALID_DTB) && !lenp) return FDT_END; /* premature end */ + + len = fdt32_to_cpu(*lenp); + sum = len + offset; + if (!can_assume(VALID_DTB) && + (INT_MAX <= sum || sum < (uint32_t) offset)) + return FDT_END; /* premature end */ + /* skip-name offset, length and value */ - offset += sizeof(struct fdt_property) - FDT_TAGSIZE - + fdt32_to_cpu(*lenp); + offset += sizeof(struct fdt_property) - FDT_TAGSIZE + len; + if (!can_assume(LATEST) && - fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 && - ((offset - fdt32_to_cpu(*lenp)) % 8) != 0) + fdt_version(fdt) < 0x10 && len >= 8 && + ((offset - len) % 8) != 0) offset += 4; break; diff --git a/scripts/dtc/libfdt/fdt.h b/scripts/dtc/libfdt/fdt.h index 0c91aa7f67b5..f2e68807f277 100644 --- a/scripts/dtc/libfdt/fdt.h +++ b/scripts/dtc/libfdt/fdt.h @@ -35,14 +35,14 @@ struct fdt_reserve_entry { struct fdt_node_header { fdt32_t tag; - char name[]; + char name[0]; }; struct fdt_property { fdt32_t tag; fdt32_t len; fdt32_t nameoff; - char data[]; + char data[0]; }; #endif /* !__ASSEMBLY */ diff --git a/scripts/dtc/libfdt/fdt_addresses.c b/scripts/dtc/libfdt/fdt_addresses.c index 9a82cd0ba2f9..c40ba094f1f8 100644 --- a/scripts/dtc/libfdt/fdt_addresses.c +++ b/scripts/dtc/libfdt/fdt_addresses.c @@ -73,7 +73,7 @@ int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset, /* check validity of address */ prop = data; if (addr_cells == 1) { - if ((addr > UINT32_MAX) || ((UINT32_MAX + 1 - addr) < size)) + if ((addr > UINT32_MAX) || (((uint64_t) UINT32_MAX + 1 - addr) < size)) return -FDT_ERR_BADVALUE; fdt32_st(prop, (uint32_t)addr); diff --git a/scripts/dtc/libfdt/fdt_overlay.c b/scripts/dtc/libfdt/fdt_overlay.c index d217e79b6722..5c0c3981b89d 100644 --- a/scripts/dtc/libfdt/fdt_overlay.c +++ b/scripts/dtc/libfdt/fdt_overlay.c @@ -40,37 +40,22 @@ static uint32_t overlay_get_target_phandle(const void *fdto, int fragment) return fdt32_to_cpu(*val); } -/** - * overlay_get_target - retrieves the offset of a fragment's target - * @fdt: Base device tree blob - * @fdto: Device tree overlay blob - * @fragment: node offset of the fragment in the overlay - * @pathp: pointer which receives the path of the target (or NULL) - * - * overlay_get_target() retrieves the target offset in the base - * device tree of a fragment, no matter how the actual targeting is - * done (through a phandle or a path) - * - * returns: - * the targeted node offset in the base device tree - * Negative error code on error - */ -static int overlay_get_target(const void *fdt, const void *fdto, - int fragment, char const **pathp) +int fdt_overlay_target_offset(const void *fdt, const void *fdto, + int fragment_offset, char const **pathp) { uint32_t phandle; const char *path = NULL; int path_len = 0, ret; /* Try first to do a phandle based lookup */ - phandle = overlay_get_target_phandle(fdto, fragment); + phandle = overlay_get_target_phandle(fdto, fragment_offset); if (phandle == (uint32_t)-1) return -FDT_ERR_BADPHANDLE; /* no phandle, try path */ if (!phandle) { /* And then a path based lookup */ - path = fdt_getprop(fdto, fragment, "target-path", &path_len); + path = fdt_getprop(fdto, fragment_offset, "target-path", &path_len); if (path) ret = fdt_path_offset(fdt, path); else @@ -636,7 +621,7 @@ static int overlay_merge(void *fdt, void *fdto) if (overlay < 0) return overlay; - target = overlay_get_target(fdt, fdto, fragment, NULL); + target = fdt_overlay_target_offset(fdt, fdto, fragment, NULL); if (target < 0) return target; @@ -779,7 +764,7 @@ static int overlay_symbol_update(void *fdt, void *fdto) return -FDT_ERR_BADOVERLAY; /* get the target of the fragment */ - ret = overlay_get_target(fdt, fdto, fragment, &target_path); + ret = fdt_overlay_target_offset(fdt, fdto, fragment, &target_path); if (ret < 0) return ret; target = ret; @@ -801,7 +786,7 @@ static int overlay_symbol_update(void *fdt, void *fdto) if (!target_path) { /* again in case setprop_placeholder changed it */ - ret = overlay_get_target(fdt, fdto, fragment, &target_path); + ret = fdt_overlay_target_offset(fdt, fdto, fragment, &target_path); if (ret < 0) return ret; target = ret; diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c index 17584da25760..9f6c551a22c2 100644 --- a/scripts/dtc/libfdt/fdt_ro.c +++ b/scripts/dtc/libfdt/fdt_ro.c @@ -481,12 +481,12 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset, if (!can_assume(VALID_INPUT)) { name = fdt_get_string(fdt, fdt32_ld_(&prop->nameoff), &namelen); + *namep = name; if (!name) { if (lenp) *lenp = namelen; return NULL; } - *namep = name; } else { *namep = fdt_string(fdt, fdt32_ld_(&prop->nameoff)); } diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt/libfdt.h index ce31e844856a..77ccff19911e 100644 --- a/scripts/dtc/libfdt/libfdt.h +++ b/scripts/dtc/libfdt/libfdt.h @@ -660,6 +660,13 @@ int fdt_next_property_offset(const void *fdt, int offset); const struct fdt_property *fdt_get_property_by_offset(const void *fdt, int offset, int *lenp); +static inline struct fdt_property *fdt_get_property_by_offset_w(void *fdt, + int offset, + int *lenp) +{ + return (struct fdt_property *)(uintptr_t) + fdt_get_property_by_offset(fdt, offset, lenp); +} /** * fdt_get_property_namelen - find a property based on substring @@ -2116,6 +2123,24 @@ int fdt_del_node(void *fdt, int nodeoffset); */ int fdt_overlay_apply(void *fdt, void *fdto); +/** + * fdt_overlay_target_offset - retrieves the offset of a fragment's target + * @fdt: Base device tree blob + * @fdto: Device tree overlay blob + * @fragment_offset: node offset of the fragment in the overlay + * @pathp: pointer which receives the path of the target (or NULL) + * + * fdt_overlay_target_offset() retrieves the target offset in the base + * device tree of a fragment, no matter how the actual targeting is + * done (through a phandle or a path) + * + * returns: + * the targeted node offset in the base device tree + * Negative error code on error + */ +int fdt_overlay_target_offset(const void *fdt, const void *fdto, + int fragment_offset, char const **pathp); + /**********************************************************************/ /* Debugging / informational functions */ /**********************************************************************/ diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c index cc612370ec61..f46a098d5ada 100644 --- a/scripts/dtc/livetree.c +++ b/scripts/dtc/livetree.c @@ -581,12 +581,39 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle) struct node *get_node_by_ref(struct node *tree, const char *ref) { + struct node *target = tree; + const char *label = NULL, *path = NULL; + if (streq(ref, "/")) return tree; - else if (ref[0] == '/') - return get_node_by_path(tree, ref); + + if (ref[0] == '/') + path = ref; else - return get_node_by_label(tree, ref); + label = ref; + + if (label) { + const char *slash = strchr(label, '/'); + char *buf = NULL; + + if (slash) { + buf = xstrndup(label, slash - label); + label = buf; + path = slash + 1; + } + + target = get_node_by_label(tree, label); + + free(buf); + + if (!target) + return NULL; + } + + if (path) + target = get_node_by_path(target, path); + + return target; } cell_t get_node_phandle(struct node *root, struct node *node) @@ -892,6 +919,12 @@ static void add_fixup_entry(struct dt_info *dti, struct node *fn, /* m->ref can only be a REF_PHANDLE, but check anyway */ assert(m->type == REF_PHANDLE); + /* The format only permits fixups for references to label, not + * references to path */ + if (strchr(m->ref, '/')) + die("Can't generate fixup for reference to path &{%s}\n", + m->ref); + /* there shouldn't be any ':' in the arguments */ if (strchr(node->fullpath, ':') || strchr(prop->name, ':')) die("arguments should not contain ':'\n"); diff --git a/scripts/dtc/util.c b/scripts/dtc/util.c index 40274fb79236..507f0120cd13 100644 --- a/scripts/dtc/util.c +++ b/scripts/dtc/util.c @@ -33,6 +33,17 @@ char *xstrdup(const char *s) return d; } +char *xstrndup(const char *s, size_t n) +{ + size_t len = strnlen(s, n) + 1; + char *d = xmalloc(len); + + memcpy(d, s, len - 1); + d[len - 1] = '\0'; + + return d; +} + int xavsprintf_append(char **strp, const char *fmt, va_list ap) { int n, size = 0; /* start with 128 bytes */ @@ -353,11 +364,11 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size) } /* we should now have a type */ - if ((*fmt == '\0') || !strchr("iuxs", *fmt)) + if ((*fmt == '\0') || !strchr("iuxsr", *fmt)) return -1; /* convert qualifier (bhL) to byte size */ - if (*fmt != 's') + if (*fmt != 's' && *fmt != 'r') *size = qualifier == 'b' ? 1 : qualifier == 'h' ? 2 : qualifier == 'l' ? 4 : -1; diff --git a/scripts/dtc/util.h b/scripts/dtc/util.h index c45b2c295aa5..9d38edee9736 100644 --- a/scripts/dtc/util.h +++ b/scripts/dtc/util.h @@ -61,6 +61,7 @@ static inline void *xrealloc(void *p, size_t len) } extern char *xstrdup(const char *s); +extern char *xstrndup(const char *s, size_t len); extern int PRINTF(2, 3) xasprintf(char **strp, const char *fmt, ...); extern int PRINTF(2, 3) xasprintf_append(char **strp, const char *fmt, ...); @@ -143,6 +144,7 @@ int utilfdt_write_err(const char *filename, const void *blob); * i signed integer * u unsigned integer * x hex + * r raw * * TODO: Implement ll modifier (8 bytes) * TODO: Implement o type (octal) @@ -160,7 +162,7 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size); */ #define USAGE_TYPE_MSG \ - "\ts=string, i=int, u=unsigned, x=hex\n" \ + "\ts=string, i=int, u=unsigned, x=hex, r=raw\n" \ "\tOptional modifier prefix:\n" \ "\t\thh or b=byte, h=2 byte, l=4 byte (default)"; diff --git a/scripts/dtc/version_gen.h b/scripts/dtc/version_gen.h index 785cc4c57326..0f303087b043 100644 --- a/scripts/dtc/version_gen.h +++ b/scripts/dtc/version_gen.h @@ -1 +1 @@ -#define DTC_VERSION "DTC 1.6.1-g0a3a9d34" +#define DTC_VERSION "DTC 1.6.1-g55778a03" -- cgit v1.2.3 From fcdf7197cf23ef452c30f376d31d73bdf7946de8 Mon Sep 17 00:00:00 2001 From: Zhen Lei Date: Wed, 2 Nov 2022 16:49:13 +0800 Subject: scripts/kallsyms: rename build_initial_tok_table() Except for the function build_initial_tok_table(), no token abbreviation is used elsewhere. $ cat scripts/kallsyms.c | grep tok | wc -l 33 $ cat scripts/kallsyms.c | grep token | wc -l 31 Here, it would be clearer to use the full name. Signed-off-by: Zhen Lei Reviewed-by: Petr Mladek Signed-off-by: Luis Chamberlain --- scripts/kallsyms.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c index 03fa07ad45d9..ab105bdde4ef 100644 --- a/scripts/kallsyms.c +++ b/scripts/kallsyms.c @@ -573,7 +573,7 @@ static void forget_symbol(const unsigned char *symbol, int len) } /* do the initial token count */ -static void build_initial_tok_table(void) +static void build_initial_token_table(void) { unsigned int i; @@ -698,7 +698,7 @@ static void insert_real_symbols_in_table(void) static void optimize_token_table(void) { - build_initial_tok_table(); + build_initial_token_table(); insert_real_symbols_in_table(); -- cgit v1.2.3 From 60443c88f3a89fd303a9e8c0e84895910675c316 Mon Sep 17 00:00:00 2001 From: Zhen Lei Date: Wed, 2 Nov 2022 16:49:14 +0800 Subject: kallsyms: Improve the performance of kallsyms_lookup_name() Currently, to search for a symbol, we need to expand the symbols in 'kallsyms_names' one by one, and then use the expanded string for comparison. It's O(n). If we sort names in ascending order like addresses, we can also use binary search. It's O(log(n)). In order not to change the implementation of "/proc/kallsyms", the table kallsyms_names[] is still stored in a one-to-one correspondence with the address in ascending order. Add array kallsyms_seqs_of_names[], it's indexed by the sequence number of the sorted names, and the corresponding content is the sequence number of the sorted addresses. For example: Assume that the index of NameX in array kallsyms_seqs_of_names[] is 'i', the content of kallsyms_seqs_of_names[i] is 'k', then the corresponding address of NameX is kallsyms_addresses[k]. The offset in kallsyms_names[] is get_symbol_offset(k). Note that the memory usage will increase by (4 * kallsyms_num_syms) bytes, the next two patches will reduce (1 * kallsyms_num_syms) bytes and properly handle the case CONFIG_LTO_CLANG=y. Performance test results: (x86) Before: min=234, max=10364402, avg=5206926 min=267, max=11168517, avg=5207587 After: min=1016, max=90894, avg=7272 min=1014, max=93470, avg=7293 The average lookup performance of kallsyms_lookup_name() improved 715x. Signed-off-by: Zhen Lei Signed-off-by: Luis Chamberlain --- kernel/kallsyms.c | 86 ++++++++++++++++++++++++++++++++++++++++------ kernel/kallsyms_internal.h | 1 + scripts/kallsyms.c | 37 ++++++++++++++++++++ 3 files changed, 113 insertions(+), 11 deletions(-) (limited to 'scripts') diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c index 60c20f301a6b..ba351dfa109b 100644 --- a/kernel/kallsyms.c +++ b/kernel/kallsyms.c @@ -187,26 +187,90 @@ static bool cleanup_symbol_name(char *s) return false; } +static int compare_symbol_name(const char *name, char *namebuf) +{ + int ret; + + ret = strcmp(name, namebuf); + if (!ret) + return ret; + + if (cleanup_symbol_name(namebuf) && !strcmp(name, namebuf)) + return 0; + + return ret; +} + +static int kallsyms_lookup_names(const char *name, + unsigned int *start, + unsigned int *end) +{ + int ret; + int low, mid, high; + unsigned int seq, off; + char namebuf[KSYM_NAME_LEN]; + + low = 0; + high = kallsyms_num_syms - 1; + + while (low <= high) { + mid = low + (high - low) / 2; + seq = kallsyms_seqs_of_names[mid]; + off = get_symbol_offset(seq); + kallsyms_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf)); + ret = compare_symbol_name(name, namebuf); + if (ret > 0) + low = mid + 1; + else if (ret < 0) + high = mid - 1; + else + break; + } + + if (low > high) + return -ESRCH; + + low = mid; + while (low) { + seq = kallsyms_seqs_of_names[low - 1]; + off = get_symbol_offset(seq); + kallsyms_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf)); + if (compare_symbol_name(name, namebuf)) + break; + low--; + } + *start = low; + + if (end) { + high = mid; + while (high < kallsyms_num_syms - 1) { + seq = kallsyms_seqs_of_names[high + 1]; + off = get_symbol_offset(seq); + kallsyms_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf)); + if (compare_symbol_name(name, namebuf)) + break; + high++; + } + *end = high; + } + + return 0; +} + /* Lookup the address for this symbol. Returns 0 if not found. */ unsigned long kallsyms_lookup_name(const char *name) { - char namebuf[KSYM_NAME_LEN]; - unsigned long i; - unsigned int off; + int ret; + unsigned int i; /* Skip the search for empty string. */ if (!*name) return 0; - for (i = 0, off = 0; i < kallsyms_num_syms; i++) { - off = kallsyms_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf)); - - if (strcmp(namebuf, name) == 0) - return kallsyms_sym_address(i); + ret = kallsyms_lookup_names(name, &i, NULL); + if (!ret) + return kallsyms_sym_address(kallsyms_seqs_of_names[i]); - if (cleanup_symbol_name(namebuf) && strcmp(namebuf, name) == 0) - return kallsyms_sym_address(i); - } return module_kallsyms_lookup_name(name); } diff --git a/kernel/kallsyms_internal.h b/kernel/kallsyms_internal.h index 2d0c6f2f0243..a04b7a5cb1e3 100644 --- a/kernel/kallsyms_internal.h +++ b/kernel/kallsyms_internal.h @@ -26,5 +26,6 @@ extern const char kallsyms_token_table[] __weak; extern const u16 kallsyms_token_index[] __weak; extern const unsigned int kallsyms_markers[] __weak; +extern const unsigned int kallsyms_seqs_of_names[] __weak; #endif // LINUX_KALLSYMS_INTERNAL_H_ diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c index ab105bdde4ef..df2d93fb0e8d 100644 --- a/scripts/kallsyms.c +++ b/scripts/kallsyms.c @@ -49,6 +49,7 @@ _Static_assert( struct sym_entry { unsigned long long addr; unsigned int len; + unsigned int seq; unsigned int start_pos; unsigned int percpu_absolute; unsigned char sym[]; @@ -410,6 +411,35 @@ static int symbol_absolute(const struct sym_entry *s) return s->percpu_absolute; } +static int compare_names(const void *a, const void *b) +{ + int ret; + char sa_namebuf[KSYM_NAME_LEN]; + char sb_namebuf[KSYM_NAME_LEN]; + const struct sym_entry *sa = *(const struct sym_entry **)a; + const struct sym_entry *sb = *(const struct sym_entry **)b; + + expand_symbol(sa->sym, sa->len, sa_namebuf); + expand_symbol(sb->sym, sb->len, sb_namebuf); + ret = strcmp(&sa_namebuf[1], &sb_namebuf[1]); + if (!ret) { + if (sa->addr > sb->addr) + return 1; + else if (sa->addr < sb->addr) + return -1; + + /* keep old order */ + return (int)(sa->seq - sb->seq); + } + + return ret; +} + +static void sort_symbols_by_name(void) +{ + qsort(table, table_cnt, sizeof(table[0]), compare_names); +} + static void write_src(void) { unsigned int i, k, off; @@ -495,6 +525,7 @@ static void write_src(void) for (i = 0; i < table_cnt; i++) { if ((i & 0xFF) == 0) markers[i >> 8] = off; + table[i]->seq = i; /* There cannot be any symbol of length zero. */ if (table[i]->len == 0) { @@ -535,6 +566,12 @@ static void write_src(void) free(markers); + sort_symbols_by_name(); + output_label("kallsyms_seqs_of_names"); + for (i = 0; i < table_cnt; i++) + printf("\t.long\t%u\n", table[i]->seq); + printf("\n"); + output_label("kallsyms_token_table"); off = 0; for (i = 0; i < 256; i++) { -- cgit v1.2.3 From 010a0aad39fccceba4a07d30d163158a39c704f3 Mon Sep 17 00:00:00 2001 From: Zhen Lei Date: Wed, 2 Nov 2022 16:49:15 +0800 Subject: kallsyms: Correctly sequence symbols when CONFIG_LTO_CLANG=y LLVM appends various suffixes for local functions and variables, suffixes observed: - foo.llvm.[0-9a-f]+ - foo.[0-9a-f]+ Therefore, when CONFIG_LTO_CLANG=y, kallsyms_lookup_name() needs to truncate the suffix of the symbol name before comparing the local function or variable name. Old implementation code: - if (strcmp(namebuf, name) == 0) - return kallsyms_sym_address(i); - if (cleanup_symbol_name(namebuf) && strcmp(namebuf, name) == 0) - return kallsyms_sym_address(i); The preceding process is traversed by address from low to high. That is, for those with the same name after the suffix is removed, the one with the smallest address is returned first. Therefore, when sorting in the tool, if the raw names are the same, they should be sorted by address in ascending order. ASCII[.] = 2e ASCII[0-9] = 30,39 ASCII[A-Z] = 41,5a ASCII[_] = 5f ASCII[a-z] = 61,7a According to the preceding ASCII code values, the following sorting result is strictly followed. --------------------------------- | main-key | sub-key | |---------------------------------| | | addr_lowest | | | ... | | . | ... | | | addr_highest | |---------------------------------| | ? | | //? is [_A-Za-z0-9] --------------------------------- Signed-off-by: Zhen Lei Signed-off-by: Luis Chamberlain --- scripts/kallsyms.c | 36 ++++++++++++++++++++++++++++++++++-- scripts/link-vmlinux.sh | 4 ++++ 2 files changed, 38 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c index df2d93fb0e8d..07ecf7e5c49f 100644 --- a/scripts/kallsyms.c +++ b/scripts/kallsyms.c @@ -78,6 +78,7 @@ static unsigned int table_size, table_cnt; static int all_symbols; static int absolute_percpu; static int base_relative; +static int lto_clang; static int token_profit[0x10000]; @@ -89,7 +90,7 @@ static unsigned char best_table_len[256]; static void usage(void) { fprintf(stderr, "Usage: kallsyms [--all-symbols] [--absolute-percpu] " - "[--base-relative] in.map > out.S\n"); + "[--base-relative] [--lto-clang] in.map > out.S\n"); exit(1); } @@ -411,6 +412,34 @@ static int symbol_absolute(const struct sym_entry *s) return s->percpu_absolute; } +static char * s_name(char *buf) +{ + /* Skip the symbol type */ + return buf + 1; +} + +static void cleanup_symbol_name(char *s) +{ + char *p; + + if (!lto_clang) + return; + + /* + * ASCII[.] = 2e + * ASCII[0-9] = 30,39 + * ASCII[A-Z] = 41,5a + * ASCII[_] = 5f + * ASCII[a-z] = 61,7a + * + * As above, replacing '.' with '\0' does not affect the main sorting, + * but it helps us with subsorting. + */ + p = strchr(s, '.'); + if (p) + *p = '\0'; +} + static int compare_names(const void *a, const void *b) { int ret; @@ -421,7 +450,9 @@ static int compare_names(const void *a, const void *b) expand_symbol(sa->sym, sa->len, sa_namebuf); expand_symbol(sb->sym, sb->len, sb_namebuf); - ret = strcmp(&sa_namebuf[1], &sb_namebuf[1]); + cleanup_symbol_name(s_name(sa_namebuf)); + cleanup_symbol_name(s_name(sb_namebuf)); + ret = strcmp(s_name(sa_namebuf), s_name(sb_namebuf)); if (!ret) { if (sa->addr > sb->addr) return 1; @@ -855,6 +886,7 @@ int main(int argc, char **argv) {"all-symbols", no_argument, &all_symbols, 1}, {"absolute-percpu", no_argument, &absolute_percpu, 1}, {"base-relative", no_argument, &base_relative, 1}, + {"lto-clang", no_argument, <o_clang, 1}, {}, }; diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index 918470d768e9..32e573943cf0 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -156,6 +156,10 @@ kallsyms() kallsymopt="${kallsymopt} --base-relative" fi + if is_enabled CONFIG_LTO_CLANG; then + kallsymopt="${kallsymopt} --lto-clang" + fi + info KSYMS ${2} scripts/kallsyms ${kallsymopt} ${1} > ${2} } -- cgit v1.2.3 From 19bd8981dc2ee35fdc81ab1b0104b607c917d470 Mon Sep 17 00:00:00 2001 From: Zhen Lei Date: Wed, 2 Nov 2022 16:49:16 +0800 Subject: kallsyms: Reduce the memory occupied by kallsyms_seqs_of_names[] kallsyms_seqs_of_names[] records the symbol index sorted by address, the maximum value in kallsyms_seqs_of_names[] is the number of symbols. And 2^24 = 16777216, which means that three bytes are enough to store the index. This can help us save (1 * kallsyms_num_syms) bytes of memory. Signed-off-by: Zhen Lei Signed-off-by: Luis Chamberlain --- kernel/kallsyms.c | 18 ++++++++++++++---- kernel/kallsyms_internal.h | 2 +- scripts/kallsyms.c | 5 ++++- 3 files changed, 19 insertions(+), 6 deletions(-) (limited to 'scripts') diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c index ba351dfa109b..48f36fd7e10b 100644 --- a/kernel/kallsyms.c +++ b/kernel/kallsyms.c @@ -201,6 +201,16 @@ static int compare_symbol_name(const char *name, char *namebuf) return ret; } +static unsigned int get_symbol_seq(int index) +{ + unsigned int i, seq = 0; + + for (i = 0; i < 3; i++) + seq = (seq << 8) | kallsyms_seqs_of_names[3 * index + i]; + + return seq; +} + static int kallsyms_lookup_names(const char *name, unsigned int *start, unsigned int *end) @@ -215,7 +225,7 @@ static int kallsyms_lookup_names(const char *name, while (low <= high) { mid = low + (high - low) / 2; - seq = kallsyms_seqs_of_names[mid]; + seq = get_symbol_seq(mid); off = get_symbol_offset(seq); kallsyms_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf)); ret = compare_symbol_name(name, namebuf); @@ -232,7 +242,7 @@ static int kallsyms_lookup_names(const char *name, low = mid; while (low) { - seq = kallsyms_seqs_of_names[low - 1]; + seq = get_symbol_seq(low - 1); off = get_symbol_offset(seq); kallsyms_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf)); if (compare_symbol_name(name, namebuf)) @@ -244,7 +254,7 @@ static int kallsyms_lookup_names(const char *name, if (end) { high = mid; while (high < kallsyms_num_syms - 1) { - seq = kallsyms_seqs_of_names[high + 1]; + seq = get_symbol_seq(high + 1); off = get_symbol_offset(seq); kallsyms_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf)); if (compare_symbol_name(name, namebuf)) @@ -269,7 +279,7 @@ unsigned long kallsyms_lookup_name(const char *name) ret = kallsyms_lookup_names(name, &i, NULL); if (!ret) - return kallsyms_sym_address(kallsyms_seqs_of_names[i]); + return kallsyms_sym_address(get_symbol_seq(i)); return module_kallsyms_lookup_name(name); } diff --git a/kernel/kallsyms_internal.h b/kernel/kallsyms_internal.h index a04b7a5cb1e3..27fabdcc40f5 100644 --- a/kernel/kallsyms_internal.h +++ b/kernel/kallsyms_internal.h @@ -26,6 +26,6 @@ extern const char kallsyms_token_table[] __weak; extern const u16 kallsyms_token_index[] __weak; extern const unsigned int kallsyms_markers[] __weak; -extern const unsigned int kallsyms_seqs_of_names[] __weak; +extern const u8 kallsyms_seqs_of_names[] __weak; #endif // LINUX_KALLSYMS_INTERNAL_H_ diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c index 07ecf7e5c49f..04e04fbd9625 100644 --- a/scripts/kallsyms.c +++ b/scripts/kallsyms.c @@ -600,7 +600,10 @@ static void write_src(void) sort_symbols_by_name(); output_label("kallsyms_seqs_of_names"); for (i = 0; i < table_cnt; i++) - printf("\t.long\t%u\n", table[i]->seq); + printf("\t.byte 0x%02x, 0x%02x, 0x%02x\n", + (unsigned char)(table[i]->seq >> 16), + (unsigned char)(table[i]->seq >> 8), + (unsigned char)(table[i]->seq >> 0)); printf("\n"); output_label("kallsyms_token_table"); -- cgit v1.2.3 From 2d77de1581bb5b470486edaf17a7d70151131afd Mon Sep 17 00:00:00 2001 From: Srikar Dronamraju Date: Tue, 27 Sep 2022 13:22:11 +0530 Subject: scripts/faddr2line: Fix regression in name resolution on ppc64le Commit 1d1a0e7c5100 ("scripts/faddr2line: Fix overlapping text section failures") can cause faddr2line to fail on ppc64le on some distributions, while it works fine on other distributions. The failure can be attributed to differences in the readelf output. $ ./scripts/faddr2line vmlinux find_busiest_group+0x00 no match for find_busiest_group+0x00 On ppc64le, readelf adds the localentry tag before the symbol name on some distributions, and adds the localentry tag after the symbol name on other distributions. This problem has been discussed previously: https://lore.kernel.org/bpf/20191211160133.GB4580@calabresa/ This problem can be overcome by filtering out the localentry tags in the readelf output. Similar fixes are already present in the kernel by way of the following commits: 1fd6cee127e2 ("libbpf: Fix VERSIONED_SYM_COUNT number parsing") aa915931ac3e ("libbpf: Fix readelf output parsing for Fedora") [jpoimboe: rework commit log] Fixes: 1d1a0e7c5100 ("scripts/faddr2line: Fix overlapping text section failures") Signed-off-by: Srikar Dronamraju Acked-by: Naveen N. Rao Reviewed-by: Thadeu Lima de Souza Cascardo Link: https://lore.kernel.org/r/20220927075211.897152-1-srikar@linux.vnet.ibm.com Signed-off-by: Josh Poimboeuf Signed-off-by: Peter Zijlstra --- scripts/faddr2line | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'scripts') diff --git a/scripts/faddr2line b/scripts/faddr2line index 5514c23f45c2..0e73aca4f908 100755 --- a/scripts/faddr2line +++ b/scripts/faddr2line @@ -74,7 +74,8 @@ command -v ${ADDR2LINE} >/dev/null 2>&1 || die "${ADDR2LINE} isn't installed" find_dir_prefix() { local objfile=$1 - local start_kernel_addr=$(${READELF} --symbols --wide $objfile | ${AWK} '$8 == "start_kernel" {printf "0x%s", $2}') + local start_kernel_addr=$(${READELF} --symbols --wide $objfile | sed 's/\[.*\]//' | + ${AWK} '$8 == "start_kernel" {printf "0x%s", $2}') [[ -z $start_kernel_addr ]] && return local file_line=$(${ADDR2LINE} -e $objfile $start_kernel_addr) @@ -178,7 +179,7 @@ __faddr2line() { found=2 break fi - done < <(${READELF} --symbols --wide $objfile | ${AWK} -v sec=$sym_sec '$7 == sec' | sort --key=2) + done < <(${READELF} --symbols --wide $objfile | sed 's/\[.*\]//' | ${AWK} -v sec=$sym_sec '$7 == sec' | sort --key=2) if [[ $found = 0 ]]; then warn "can't find symbol: sym_name: $sym_name sym_sec: $sym_sec sym_addr: $sym_addr sym_elf_size: $sym_elf_size" @@ -259,7 +260,7 @@ __faddr2line() { DONE=1 - done < <(${READELF} --symbols --wide $objfile | ${AWK} -v fn=$sym_name '$4 == "FUNC" && $8 == fn') + done < <(${READELF} --symbols --wide $objfile | sed 's/\[.*\]//' | ${AWK} -v fn=$sym_name '$4 == "FUNC" && $8 == fn') } [[ $# -lt 2 ]] && usage -- cgit v1.2.3 From 280981d6994e0700abd36647b141e73059851e66 Mon Sep 17 00:00:00 2001 From: Sathvika Vasireddy Date: Mon, 14 Nov 2022 23:27:49 +0530 Subject: objtool: Add --mnop as an option to --mcount Some architectures (powerpc) may not support ftrace locations being nop'ed out at build time. Introduce CONFIG_HAVE_OBJTOOL_NOP_MCOUNT for objtool, as a means for architectures to enable nop'ing of ftrace locations. Add --mnop as an option to objtool --mcount, to indicate support for the same. Also, make sure that --mnop can be passed as an option to objtool only when --mcount is passed. Tested-by: Naveen N. Rao Reviewed-by: Naveen N. Rao Acked-by: Josh Poimboeuf Reviewed-by: Christophe Leroy Signed-off-by: Sathvika Vasireddy Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20221114175754.1131267-12-sv@linux.ibm.com --- Makefile | 4 +++- arch/x86/Kconfig | 1 + kernel/trace/Kconfig | 7 +++++++ scripts/Makefile.lib | 3 +++ tools/objtool/builtin-check.c | 14 ++++++++++++++ tools/objtool/check.c | 19 ++++++++++--------- tools/objtool/include/objtool/builtin.h | 1 + 7 files changed, 39 insertions(+), 10 deletions(-) (limited to 'scripts') diff --git a/Makefile b/Makefile index d148a55bfd0f..53c2b715d0bf 100644 --- a/Makefile +++ b/Makefile @@ -933,7 +933,9 @@ ifdef CONFIG_FTRACE_MCOUNT_USE_CC endif endif ifdef CONFIG_FTRACE_MCOUNT_USE_OBJTOOL - CC_FLAGS_USING += -DCC_USING_NOP_MCOUNT + ifdef CONFIG_HAVE_OBJTOOL_NOP_MCOUNT + CC_FLAGS_USING += -DCC_USING_NOP_MCOUNT + endif endif ifdef CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT ifdef CONFIG_HAVE_C_RECORDMCOUNT diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 67745ceab0db..4be7c06a5d18 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -195,6 +195,7 @@ config X86 select HAVE_CONTEXT_TRACKING_USER_OFFSTACK if HAVE_CONTEXT_TRACKING_USER select HAVE_C_RECORDMCOUNT select HAVE_OBJTOOL_MCOUNT if HAVE_OBJTOOL + select HAVE_OBJTOOL_NOP_MCOUNT if HAVE_OBJTOOL_MCOUNT select HAVE_BUILDTIME_MCOUNT_SORT select HAVE_DEBUG_KMEMLEAK select HAVE_DMA_CONTIGUOUS diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index e9e95c790b8e..2b782321376a 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig @@ -82,6 +82,13 @@ config HAVE_OBJTOOL_MCOUNT help Arch supports objtool --mcount +config HAVE_OBJTOOL_NOP_MCOUNT + bool + help + Arch supports the objtool options --mcount with --mnop. + An architecture can select this if it wants to enable nop'ing + of ftrace locations. + config HAVE_C_RECORDMCOUNT bool help diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 3aa384cec76b..658f541c2782 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -256,6 +256,9 @@ objtool-args-$(CONFIG_HAVE_JUMP_LABEL_HACK) += --hacks=jump_label objtool-args-$(CONFIG_HAVE_NOINSTR_HACK) += --hacks=noinstr objtool-args-$(CONFIG_X86_KERNEL_IBT) += --ibt objtool-args-$(CONFIG_FTRACE_MCOUNT_USE_OBJTOOL) += --mcount +ifdef CONFIG_FTRACE_MCOUNT_USE_OBJTOOL +objtool-args-$(CONFIG_HAVE_OBJTOOL_NOP_MCOUNT) += --mnop +endif objtool-args-$(CONFIG_UNWINDER_ORC) += --orc objtool-args-$(CONFIG_RETPOLINE) += --retpoline objtool-args-$(CONFIG_RETHUNK) += --rethunk diff --git a/tools/objtool/builtin-check.c b/tools/objtool/builtin-check.c index 24fbe803a0d3..9bd347d3c244 100644 --- a/tools/objtool/builtin-check.c +++ b/tools/objtool/builtin-check.c @@ -82,6 +82,7 @@ const struct option check_options[] = { OPT_BOOLEAN(0, "dry-run", &opts.dryrun, "don't write modifications"), OPT_BOOLEAN(0, "link", &opts.link, "object is a linked object"), OPT_BOOLEAN(0, "module", &opts.module, "object is part of a kernel module"), + OPT_BOOLEAN(0, "mnop", &opts.mnop, "nop out mcount call sites"), OPT_BOOLEAN(0, "no-unreachable", &opts.no_unreachable, "skip 'unreachable instruction' warnings"), OPT_BOOLEAN(0, "sec-address", &opts.sec_address, "print section addresses in warnings"), OPT_BOOLEAN(0, "stats", &opts.stats, "print statistics"), @@ -150,6 +151,16 @@ static bool opts_valid(void) return false; } +static bool mnop_opts_valid(void) +{ + if (opts.mnop && !opts.mcount) { + ERROR("--mnop requires --mcount"); + return false; + } + + return true; +} + static bool link_opts_valid(struct objtool_file *file) { if (opts.link) @@ -198,6 +209,9 @@ int objtool_run(int argc, const char **argv) if (!file) return 1; + if (!mnop_opts_valid()) + return 1; + if (!link_opts_valid(file)) return 1; diff --git a/tools/objtool/check.c b/tools/objtool/check.c index b64518c7c7b4..71cf4b4ba1da 100644 --- a/tools/objtool/check.c +++ b/tools/objtool/check.c @@ -1256,17 +1256,18 @@ static void annotate_call_site(struct objtool_file *file, if (opts.mcount && sym->fentry) { if (sibling) WARN_FUNC("Tail call to __fentry__ !?!?", insn->sec, insn->offset); + if (opts.mnop) { + if (reloc) { + reloc->type = R_NONE; + elf_write_reloc(file->elf, reloc); + } - if (reloc) { - reloc->type = R_NONE; - elf_write_reloc(file->elf, reloc); - } - - elf_write_insn(file->elf, insn->sec, - insn->offset, insn->len, - arch_nop_insn(insn->len)); + elf_write_insn(file->elf, insn->sec, + insn->offset, insn->len, + arch_nop_insn(insn->len)); - insn->type = INSN_NOP; + insn->type = INSN_NOP; + } list_add_tail(&insn->call_node, &file->mcount_loc_list); return; diff --git a/tools/objtool/include/objtool/builtin.h b/tools/objtool/include/objtool/builtin.h index 42a52f1a0add..0785707c5a92 100644 --- a/tools/objtool/include/objtool/builtin.h +++ b/tools/objtool/include/objtool/builtin.h @@ -31,6 +31,7 @@ struct opts { bool backup; bool dryrun; bool link; + bool mnop; bool module; bool no_unreachable; bool sec_address; -- cgit v1.2.3 From dcad240c15c10bebdccd1f29f1a44787528f2d76 Mon Sep 17 00:00:00 2001 From: Andrew Davis Date: Mon, 14 Nov 2022 14:59:39 -0600 Subject: kbuild: Cleanup DT Overlay intermediate files as appropriate %.dtbo.o and %.dtbo.S files are used to build-in DT Overlay. They should should not be removed by Make or the kernel will be needlessly rebuilt. These should be removed by "clean" and ignored by git like other intermediate files. Reported-by: Andy Shevchenko Signed-off-by: Andrew Davis Fixes: 941214a512d8 ("kbuild: Allow DTB overlays to built into .dtbo.S files") Tested-by: Andy Shevchenko Acked-by: Masahiro Yamada Link: https://lore.kernel.org/r/20221114205939.27994-1-afd@ti.com Signed-off-by: Rob Herring --- .gitignore | 1 + Makefile | 4 +++- scripts/Makefile.build | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/.gitignore b/.gitignore index 5da004814678..3ec73ead6757 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ *.dtb *.dtbo *.dtb.S +*.dtbo.S *.dwo *.elf *.gcno diff --git a/Makefile b/Makefile index f41ec8c8426b..2687e0e88e18 100644 --- a/Makefile +++ b/Makefile @@ -2001,7 +2001,9 @@ clean: $(clean-dirs) @find $(or $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \ \( -name '*.[aios]' -o -name '*.rsi' -o -name '*.ko' -o -name '.*.cmd' \ -o -name '*.ko.*' \ - -o -name '*.dtb' -o -name '*.dtbo' -o -name '*.dtb.S' -o -name '*.dt.yaml' \ + -o -name '*.dtb' -o -name '*.dtbo' \ + -o -name '*.dtb.S' -o -name '*.dtbo.S' \ + -o -name '*.dt.yaml' \ -o -name '*.dwo' -o -name '*.lst' \ -o -name '*.su' -o -name '*.mod' -o -name '*.usyms' \ -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \ diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 41f3602fc8de..3ceab076127b 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -468,10 +468,12 @@ intermediate_targets = $(foreach sfx, $(2), \ $(filter %$(strip $(1)), $(targets)))) # %.asn1.o <- %.asn1.[ch] <- %.asn1 # %.dtb.o <- %.dtb.S <- %.dtb <- %.dts +# %.dtbo.o <- %.dtbo.S <- %.dtbo <- %.dtso # %.lex.o <- %.lex.c <- %.l # %.tab.o <- %.tab.[ch] <- %.y targets += $(call intermediate_targets, .asn1.o, .asn1.c .asn1.h) \ $(call intermediate_targets, .dtb.o, .dtb.S .dtb) \ + $(call intermediate_targets, .dtbo.o, .dtbo.S .dtbo) \ $(call intermediate_targets, .lex.o, .lex.c) \ $(call intermediate_targets, .tab.o, .tab.c .tab.h) -- cgit v1.2.3 From 9b71f79f6e349251e529ef25f2d3bf8aa6168d26 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 19 Oct 2022 15:28:43 -0500 Subject: checkpatch: add warning for non-lore mailing list URLs The lkml.org, marc.info, spinics.net, etc archives are not quite as useful as lore.kernel.org because they use different styles, add advertising, and may disappear in the future. The lore archives are more consistent and more likely to stick around, so prefer https://lore.kernel.org URLs when they exist. [bhelgaas@google.com: only warn if we see "http" before the archive hostname] Link: https://lkml.kernel.org/r/20221114224315.GA939630@bhelgaas Link: https://lkml.kernel.org/r/20221019202843.40810-1-helgaas@kernel.org Signed-off-by: Bjorn Helgaas Reviewed-by: Peter Collingbourne Cc: Andy Whitcroft Cc: Dwaipayan Ray Cc: Kees Cook Cc: Lukas Bulwahn Cc: Randy Dunlap # build-tested Cc: Joe Perches Signed-off-by: Andrew Morton --- scripts/checkpatch.pl | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 1e5e66ae5a52..bd1b9d7a1647 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -702,6 +702,17 @@ sub find_standard_signature { return ""; } +our $obsolete_archives = qr{(?xi: + \Qfreedesktop.org/archives/dri-devel\E | + \Qlists.infradead.org\E | + \Qlkml.org\E | + \Qmail-archive.com\E | + \Qmailman.alsa-project.org/pipermail\E | + \Qmarc.info\E | + \Qozlabs.org/pipermail\E | + \Qspinics.net\E +)}; + our @typeListMisordered = ( qr{char\s+(?:un)?signed}, qr{int\s+(?:(?:un)?signed\s+)?short\s}, @@ -3324,6 +3335,12 @@ sub process { $last_git_commit_id_linenr = $linenr if ($line =~ /\bcommit\s*$/i); } +# Check for mailing list archives other than lore.kernel.org + if ($rawline =~ m{http.*\b$obsolete_archives}) { + WARN("PREFER_LORE_ARCHIVE", + "Use lore.kernel.org archive links when possible - see https://lore.kernel.org/lists.html\n" . $herecurr); + } + # Check for added, moved or deleted files if (!$reported_maintainer_file && !$in_commit_log && ($line =~ /^(?:new|deleted) file mode\s*\d+\s*$/ || -- cgit v1.2.3 From dc3f4dee81cd85b039d07b8d75cfbae4668a15d2 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Thu, 27 Oct 2022 15:43:34 +0200 Subject: scripts: checkpatch: allow "case" macros Do not report errors like below: ./scripts/checkpatch.pl -f drivers/net/wireless/ath/ath10k/wmi.h ERROR: Macros with complex values should be enclosed in parentheses +#define C2S(x) case x: return #x since many "case ..." macros are already used by some in-kernel drivers. Link: https://lkml.kernel.org/r/20221027134334.164301-1-stf_xl@wp.pl Signed-off-by: Stanislaw Gruszka Acked-by: Joe Perches Signed-off-by: Andrew Morton --- scripts/checkpatch.pl | 1 + 1 file changed, 1 insertion(+) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index bd1b9d7a1647..29517897baa1 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -5918,6 +5918,7 @@ sub process { $dstat !~ /$exceptions/ && $dstat !~ /^\.$Ident\s*=/ && # .foo = $dstat !~ /^(?:\#\s*$Ident|\#\s*$Constant)\s*$/ && # stringification #foo + $dstat !~ /^case\b/ && # case ... $dstat !~ /^do\s*$Constant\s*while\s*$Constant;?$/ && # do {...} while (...); // do {...} while (...) $dstat !~ /^while\s*$Constant\s*$Constant\s*$/ && # while (...) {...} $dstat !~ /^for\s*$Constant$/ && # for (...) -- cgit v1.2.3 From 7b9cbc7701d562e60ae0836dbad27ea9cf7e0f8d Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 8 Nov 2022 11:07:12 +0000 Subject: scripts/spelling.txt: add more spellings to spelling.txt Some of the more common spelling mistakes and typos that I've found while fixing up spelling mistakes in the kernel in the past year. Link: https://lkml.kernel.org/r/20221108110712.114611-1-colin.i.king@gmail.com Signed-off-by: Colin Ian King Signed-off-by: Andrew Morton --- scripts/spelling.txt | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/spelling.txt b/scripts/spelling.txt index 8435b99452b6..ded8bcfc0247 100644 --- a/scripts/spelling.txt +++ b/scripts/spelling.txt @@ -23,6 +23,7 @@ absoulte||absolute acccess||access acceess||access accelaration||acceleration +accelearion||acceleration acceleratoin||acceleration accelleration||acceleration accesing||accessing @@ -58,6 +59,7 @@ acording||according activete||activate actived||activated actualy||actually +actvie||active acumulating||accumulating acumulative||accumulative acumulator||accumulator @@ -253,6 +255,7 @@ brigde||bridge broadcase||broadcast broadcat||broadcast bufer||buffer +bufferred||buffered bufufer||buffer cacluated||calculated caculate||calculate @@ -273,6 +276,7 @@ cant||can't cant'||can't canot||cannot cann't||can't +cannnot||cannot capabilites||capabilities capabilties||capabilities capabilty||capability @@ -309,6 +313,7 @@ chiled||child chked||checked chnage||change chnages||changes +chnange||change chnnel||channel choosen||chosen chouse||chose @@ -439,6 +444,7 @@ defferred||deferred definate||definite definately||definitely definiation||definition +definiton||definition defintion||definition defintions||definitions defualt||default @@ -452,6 +458,7 @@ delare||declare delares||declares delaring||declaring delemiter||delimiter +delibrately||deliberately delievered||delivered demodualtor||demodulator demension||dimension @@ -481,6 +488,7 @@ destroied||destroyed detabase||database deteced||detected detectt||detect +detroyed||destroyed develope||develop developement||development developped||developed @@ -507,6 +515,7 @@ dimention||dimension dimesions||dimensions diconnected||disconnected disabed||disabled +disasembler||disassembler disble||disable disgest||digest disired||desired @@ -666,6 +675,7 @@ finanize||finalize findn||find finilizes||finalizes finsih||finish +fliter||filter flusing||flushing folloing||following followign||following @@ -725,6 +735,7 @@ hanled||handled happend||happened hardare||hardware harware||hardware +hardward||hardware havind||having heirarchically||hierarchically heirarchy||hierarchy @@ -740,6 +751,7 @@ howver||however hsould||should hypervior||hypervisor hypter||hyper +idel||idle identidier||identifier iligal||illegal illigal||illegal @@ -931,9 +943,11 @@ matchs||matches mathimatical||mathematical mathimatic||mathematic mathimatics||mathematics +maxmium||maximum maximium||maximum maxium||maximum mechamism||mechanism +mechanim||mechanism meetign||meeting memeory||memory memmber||member @@ -942,6 +956,7 @@ memroy||memory ment||meant mergable||mergeable mesage||message +mesages||messages messags||messages messgaes||messages messsage||message @@ -983,8 +998,9 @@ monochromo||monochrome monocrome||monochrome mopdule||module mroe||more -multipler||multiplier mulitplied||multiplied +muliple||multiple +multipler||multiplier multidimensionnal||multidimensional multipe||multiple multple||multiple @@ -1109,6 +1125,7 @@ peroid||period persistance||persistence persistant||persistent phoneticly||phonetically +plaform||platform plalform||platform platfoem||platform platfrom||platform @@ -1236,6 +1253,7 @@ refering||referring refernces||references refernnce||reference refrence||reference +regiser||register registed||registered registerd||registered registeration||registration @@ -1276,6 +1294,7 @@ reseting||resetting reseved||reserved reseverd||reserved resizeable||resizable +resotre||restore resouce||resource resouces||resources resoures||resources @@ -1314,6 +1333,7 @@ runtine||runtime sacrifying||sacrificing safly||safely safty||safety +satify||satisfy savable||saveable scaleing||scaling scaned||scanned @@ -1365,10 +1385,12 @@ similiar||similar simlar||similar simliar||similar simpified||simplified +simultaneusly||simultaneously simultanous||simultaneous singaled||signaled singal||signal singed||signed +slect||select sleeped||slept sliped||slipped softwade||software @@ -1438,6 +1460,7 @@ suported||supported suport||support supportet||supported suppored||supported +supporing||supporting supportin||supporting suppoted||supported suppported||supported @@ -1475,15 +1498,18 @@ sytem||system sythesis||synthesis taht||that tained||tainted +tarffic||traffic tansmit||transmit targetted||targeted targetting||targeting taskelt||tasklet teh||the +temeprature||temperature temorary||temporary temproarily||temporarily temperture||temperature thead||thread +theads||threads therfore||therefore thier||their threds||threads @@ -1533,12 +1559,14 @@ ture||true tyep||type udpate||update uesd||used +unknwon||unknown uknown||unknown usccess||success uncommited||uncommitted uncompatible||incompatible unconditionaly||unconditionally undeflow||underflow +undelying||underlying underun||underrun unecessary||unnecessary unexecpted||unexpected @@ -1569,11 +1597,14 @@ unneedingly||unnecessarily unnsupported||unsupported unmached||unmatched unprecise||imprecise +unpriviledged||unprivileged +unpriviliged||unprivileged unregester||unregister unresgister||unregister unrgesiter||unregister unsinged||unsigned unstabel||unstable +unsolicted||unsolicited unsolicitied||unsolicited unsuccessfull||unsuccessful unsuported||unsupported -- cgit v1.2.3 From 0d2573a2b7838a4f6934c2835e6730b38df4bcc9 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 9 Nov 2022 14:30:55 +0100 Subject: modpost: Join broken long printed messages Breaking long printed messages in multiple lines makes it very hard to look up where they originated from. Signed-off-by: Geert Uytterhoeven Reviewed-by: Nicolas Schier Signed-off-by: Masahiro Yamada --- scripts/mod/file2alias.c | 18 +++++++----------- scripts/mod/modpost.c | 8 +++----- 2 files changed, 10 insertions(+), 16 deletions(-) (limited to 'scripts') diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 80d973144fde..7df23905fdf1 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -140,25 +140,22 @@ static void device_id_check(const char *modname, const char *device_id, int i; if (size % id_size || size < id_size) { - fatal("%s: sizeof(struct %s_device_id)=%lu is not a modulo " - "of the size of " - "section __mod_%s___device_table=%lu.\n" - "Fix definition of struct %s_device_id " - "in mod_devicetable.h\n", + fatal("%s: sizeof(struct %s_device_id)=%lu is not a modulo of the size of section __mod_%s___device_table=%lu.\n" + "Fix definition of struct %s_device_id in mod_devicetable.h\n", modname, device_id, id_size, device_id, size, device_id); } /* Verify last one is a terminator */ for (i = 0; i < id_size; i++ ) { if (*(uint8_t*)(symval+size-id_size+i)) { - fprintf(stderr,"%s: struct %s_device_id is %lu bytes. " - "The last of %lu is:\n", + fprintf(stderr, + "%s: struct %s_device_id is %lu bytes. The last of %lu is:\n", modname, device_id, id_size, size / id_size); for (i = 0; i < id_size; i++ ) fprintf(stderr,"0x%02x ", *(uint8_t*)(symval+size-id_size+i) ); fprintf(stderr,"\n"); - fatal("%s: struct %s_device_id is not terminated " - "with a NULL entry!\n", modname, device_id); + fatal("%s: struct %s_device_id is not terminated with a NULL entry!\n", + modname, device_id); } } } @@ -1154,8 +1151,7 @@ static int do_amba_entry(const char *filename, DEF_FIELD(symval, amba_id, mask); if ((id & mask) != id) - fatal("%s: Masked-off bit(s) of AMBA device ID are non-zero: " - "id=0x%08X, mask=0x%08X. Please fix this driver.\n", + fatal("%s: Masked-off bit(s) of AMBA device ID are non-zero: id=0x%08X, mask=0x%08X. Please fix this driver.\n", filename, id, mask); p += sprintf(alias, "amba:d"); diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 2c80da0220c3..56d856f2e511 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -519,9 +519,8 @@ static int parse_elf(struct elf_info *info, const char *filename) int nobits = sechdrs[i].sh_type == SHT_NOBITS; if (!nobits && sechdrs[i].sh_offset > info->size) { - fatal("%s is truncated. sechdrs[i].sh_offset=%lu > " - "sizeof(*hrd)=%zu\n", filename, - (unsigned long)sechdrs[i].sh_offset, + fatal("%s is truncated. sechdrs[i].sh_offset=%lu > sizeof(*hrd)=%zu\n", + filename, (unsigned long)sechdrs[i].sh_offset, sizeof(*hdr)); return 0; } @@ -1355,8 +1354,7 @@ static void report_extable_warnings(const char* modname, struct elf_info* elf, get_pretty_name(is_function(tosym), &to_pretty_name, &to_pretty_name_p); - warn("%s(%s+0x%lx): Section mismatch in reference" - " from the %s %s%s to the %s %s:%s%s\n", + warn("%s(%s+0x%lx): Section mismatch in reference from the %s %s%s to the %s %s:%s%s\n", modname, fromsec, (long)r->r_offset, from_pretty_name, fromsym_name, from_pretty_name_p, to_pretty_name, tosec, tosym_name, to_pretty_name_p); -- cgit v1.2.3 From 9f8fe647797a4bc049bc7cceaf3a63584678ba04 Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Thu, 10 Nov 2022 11:59:05 -0800 Subject: Makefile.debug: support for -gz=zstd Make DEBUG_INFO_COMPRESSED a choice; DEBUG_INFO_COMPRESSED_NONE is the default, DEBUG_INFO_COMPRESSED_ZLIB uses zlib, DEBUG_INFO_COMPRESSED_ZSTD uses zstd. This renames the existing KConfig option DEBUG_INFO_COMPRESSED to DEBUG_INFO_COMPRESSED_ZLIB so users upgrading may need to reset the new Kconfigs. Some quick N=1 measurements with du, /usr/bin/time -v, and bloaty: clang-16, x86_64 defconfig plus CONFIG_DEBUG_INFO=y CONFIG_DEBUG_INFO_COMPRESSED_NONE=y: Elapsed (wall clock) time (h:mm:ss or m:ss): 0:55.43 488M vmlinux 27.6% 136Mi 0.0% 0 .debug_info 6.1% 30.2Mi 0.0% 0 .debug_str_offsets 3.5% 17.2Mi 0.0% 0 .debug_line 3.3% 16.3Mi 0.0% 0 .debug_loclists 0.9% 4.62Mi 0.0% 0 .debug_str clang-16, x86_64 defconfig plus CONFIG_DEBUG_INFO=y CONFIG_DEBUG_INFO_COMPRESSED_ZLIB=y: Elapsed (wall clock) time (h:mm:ss or m:ss): 1:00.35 385M vmlinux 21.8% 85.4Mi 0.0% 0 .debug_info 2.1% 8.26Mi 0.0% 0 .debug_str_offsets 2.1% 8.24Mi 0.0% 0 .debug_loclists 1.9% 7.48Mi 0.0% 0 .debug_line 0.5% 1.94Mi 0.0% 0 .debug_str clang-16, x86_64 defconfig plus CONFIG_DEBUG_INFO=y CONFIG_DEBUG_INFO_COMPRESSED_ZSTD=y: Elapsed (wall clock) time (h:mm:ss or m:ss): 0:59.69 373M vmlinux 21.4% 81.4Mi 0.0% 0 .debug_info 2.3% 8.85Mi 0.0% 0 .debug_loclists 1.5% 5.71Mi 0.0% 0 .debug_line 0.5% 1.95Mi 0.0% 0 .debug_str_offsets 0.4% 1.62Mi 0.0% 0 .debug_str That's only a 3.11% overall binary size savings over zlib, but at no performance regression. Link: https://maskray.me/blog/2022-09-09-zstd-compressed-debug-sections Link: https://maskray.me/blog/2022-01-23-compressed-debug-sections Suggested-by: Sedat Dilek (DHL Supply Chain) Reviewed-by: Nathan Chancellor Signed-off-by: Nick Desaulniers Signed-off-by: Masahiro Yamada --- lib/Kconfig.debug | 29 +++++++++++++++++++++++++++-- scripts/Makefile.debug | 6 +++++- 2 files changed, 32 insertions(+), 3 deletions(-) (limited to 'scripts') diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index c3c0b077ade3..d93dbe5a1d14 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -312,8 +312,21 @@ config DEBUG_INFO_REDUCED DEBUG_INFO build and compile times are reduced too. Only works with newer gcc versions. -config DEBUG_INFO_COMPRESSED - bool "Compressed debugging information" +choice + prompt "Compressed Debug information" + help + Compress the resulting debug info. Results in smaller debug info sections, + but requires that consumers are able to decompress the results. + + If unsure, choose DEBUG_INFO_COMPRESSED_NONE. + +config DEBUG_INFO_COMPRESSED_NONE + bool "Don't compress debug information" + help + Don't compress debug info sections. + +config DEBUG_INFO_COMPRESSED_ZLIB + bool "Compress debugging information with zlib" depends on $(cc-option,-gz=zlib) depends on $(ld-option,--compress-debug-sections=zlib) help @@ -327,6 +340,18 @@ config DEBUG_INFO_COMPRESSED preferable to setting $KDEB_COMPRESS to "none" which would be even larger. +config DEBUG_INFO_COMPRESSED_ZSTD + bool "Compress debugging information with zstd" + depends on $(cc-option,-gz=zstd) + depends on $(ld-option,--compress-debug-sections=zstd) + help + Compress the debug information using zstd. This may provide better + compression than zlib, for about the same time costs, but requires newer + toolchain support. Requires GCC 13.0+ or Clang 16.0+, binutils 2.40+, and + zstd. + +endchoice # "Compressed Debug information" + config DEBUG_INFO_SPLIT bool "Produce split debuginfo in .dwo files" depends on $(cc-option,-gsplit-dwarf) diff --git a/scripts/Makefile.debug b/scripts/Makefile.debug index 332c486f705f..059ff38fe0cb 100644 --- a/scripts/Makefile.debug +++ b/scripts/Makefile.debug @@ -27,10 +27,14 @@ else DEBUG_RUSTFLAGS += -Cdebuginfo=2 endif -ifdef CONFIG_DEBUG_INFO_COMPRESSED +ifdef CONFIG_DEBUG_INFO_COMPRESSED_ZLIB DEBUG_CFLAGS += -gz=zlib KBUILD_AFLAGS += -gz=zlib KBUILD_LDFLAGS += --compress-debug-sections=zlib +else ifdef CONFIG_DEBUG_INFO_COMPRESSED_ZSTD +DEBUG_CFLAGS += -gz=zstd +KBUILD_AFLAGS += -gz=zstd +KBUILD_LDFLAGS += --compress-debug-sections=zstd endif KBUILD_CFLAGS += $(DEBUG_CFLAGS) -- cgit v1.2.3 From 30daacc571d1416f24abd4cc49910ff9322a8cf6 Mon Sep 17 00:00:00 2001 From: KaiLong Wang Date: Sun, 13 Nov 2022 17:29:50 +0800 Subject: modpost: fix array_size.cocci warning Fix following coccicheck warning: scripts/mod/sumversion.c:219:48-49: WARNING: Use ARRAY_SIZE scripts/mod/sumversion.c:156:48-49: WARNING: Use ARRAY_SIZE Signed-off-by: KaiLong Wang Signed-off-by: Masahiro Yamada --- scripts/mod/sumversion.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/mod/sumversion.c b/scripts/mod/sumversion.c index 6bf9caca0968..31066bfdba04 100644 --- a/scripts/mod/sumversion.c +++ b/scripts/mod/sumversion.c @@ -153,7 +153,7 @@ static void md4_transform(uint32_t *hash, uint32_t const *in) static inline void md4_transform_helper(struct md4_ctx *ctx) { - le32_to_cpu_array(ctx->block, sizeof(ctx->block) / sizeof(uint32_t)); + le32_to_cpu_array(ctx->block, ARRAY_SIZE(ctx->block)); md4_transform(ctx->hash, ctx->block); } @@ -216,7 +216,7 @@ static void md4_final_ascii(struct md4_ctx *mctx, char *out, unsigned int len) le32_to_cpu_array(mctx->block, (sizeof(mctx->block) - sizeof(uint64_t)) / sizeof(uint32_t)); md4_transform(mctx->hash, mctx->block); - cpu_to_le32_array(mctx->hash, sizeof(mctx->hash) / sizeof(uint32_t)); + cpu_to_le32_array(mctx->hash, ARRAY_SIZE(mctx->hash)); snprintf(out, len, "%08X%08X%08X%08X", mctx->hash[0], mctx->hash[1], mctx->hash[2], mctx->hash[3]); -- cgit v1.2.3 From 1791360cb37ff5ef797afe9006cb315ebb7e969e Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 13 Nov 2022 19:59:41 +0900 Subject: kconfig: remove unneeded variable in get_prompt_str() The variable 'accessible' is redundant. Signed-off-by: Masahiro Yamada --- scripts/kconfig/menu.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'scripts') diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c index 109325f31bef..b90fff833588 100644 --- a/scripts/kconfig/menu.c +++ b/scripts/kconfig/menu.c @@ -724,10 +724,8 @@ static void get_prompt_str(struct gstr *r, struct property *prop, menu = prop->menu; for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) { - bool accessible = menu_is_visible(menu); - submenu[i++] = menu; - if (location == NULL && accessible) + if (location == NULL && menu_is_visible(menu)) location = menu; } if (head && location) { -- cgit v1.2.3 From 4d980fd111237ab64705b982f61f284c2a7885e5 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 13 Nov 2022 19:59:42 +0900 Subject: kconfig: remove const qualifier from str_get() update_text() apparently edits the buffer returned by str_get(). (and there is no reason why it shouldn't) Remove 'const' quailifier and casting. Signed-off-by: Masahiro Yamada --- scripts/kconfig/lkc.h | 2 +- scripts/kconfig/mconf.c | 4 ++-- scripts/kconfig/util.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'scripts') diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h index 6ac2eabe109d..e7118d62a45f 100644 --- a/scripts/kconfig/lkc.h +++ b/scripts/kconfig/lkc.h @@ -76,7 +76,7 @@ struct gstr str_new(void); void str_free(struct gstr *gs); void str_append(struct gstr *gs, const char *s); void str_printf(struct gstr *gs, const char *fmt, ...); -const char *str_get(struct gstr *gs); +char *str_get(struct gstr *gs); /* menu.c */ void _menu_init(void); diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c index 9d3cf510562f..d7f7e1bf7dd4 100644 --- a/scripts/kconfig/mconf.c +++ b/scripts/kconfig/mconf.c @@ -440,8 +440,8 @@ again: res = get_relations_str(sym_arr, &head); set_subtitle(); - dres = show_textbox_ext("Search Results", (char *) - str_get(&res), 0, 0, keys, &vscroll, + dres = show_textbox_ext("Search Results", str_get(&res), 0, 0, + keys, &vscroll, &hscroll, &update_text, (void *) &data); again = false; diff --git a/scripts/kconfig/util.c b/scripts/kconfig/util.c index 29585394df71..b78f114ad48c 100644 --- a/scripts/kconfig/util.c +++ b/scripts/kconfig/util.c @@ -74,7 +74,7 @@ void str_printf(struct gstr *gs, const char *fmt, ...) } /* Retrieve value of growable string */ -const char *str_get(struct gstr *gs) +char *str_get(struct gstr *gs) { return gs->s; } -- cgit v1.2.3 From be5ea98983efe2a2c5156c3b43e35a076d5b640d Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 13 Nov 2022 19:59:43 +0900 Subject: kconfig: remove redundant (void *) cast in search_conf() The (void *) cast is redundant because the last argument of show_textbox_ext() is an opaque pointer. Signed-off-by: Masahiro Yamada --- scripts/kconfig/mconf.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c index d7f7e1bf7dd4..9c549683c627 100644 --- a/scripts/kconfig/mconf.c +++ b/scripts/kconfig/mconf.c @@ -441,8 +441,7 @@ again: res = get_relations_str(sym_arr, &head); set_subtitle(); dres = show_textbox_ext("Search Results", str_get(&res), 0, 0, - keys, &vscroll, - &hscroll, &update_text, (void *) + keys, &vscroll, &hscroll, &update_text, &data); again = false; for (i = 0; i < JUMP_NB && keys[i]; i++) -- cgit v1.2.3 From f8f4dc7685c72c8ef86420566a38a4f786613851 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 15 Nov 2022 03:10:55 +0900 Subject: scripts/jobserver-exec: parse the last --jobserver-auth= option In the GNU Make manual, the section "Sharing Job Slots with GNU make" says: Be aware that the MAKEFLAGS variable may contain multiple instances of the --jobserver-auth= option. Only the last instance is relevant. Take the last element of the array, not the first. Link: https://www.gnu.org/software/make/manual/html_node/Job-Slots.html Signed-off-by: Masahiro Yamada Reviewed-by: Nicolas Schier --- scripts/jobserver-exec | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/jobserver-exec b/scripts/jobserver-exec index 8762887a970c..4192855f5b8b 100755 --- a/scripts/jobserver-exec +++ b/scripts/jobserver-exec @@ -23,7 +23,9 @@ try: opts = [x for x in flags.split(" ") if x.startswith("--jobserver")] # Parse out R,W file descriptor numbers and set them nonblocking. - fds = opts[0].split("=", 1)[1] + # If the MAKEFLAGS variable contains multiple instances of the + # --jobserver-auth= option, the last one is relevant. + fds = opts[-1].split("=", 1)[1] reader, writer = [int(x) for x in fds.split(",", 1)] # Open a private copy of reader to avoid setting nonblocking # on an unexpecting process with the same reader fd. -- cgit v1.2.3 From 5724ac5589ad93d35d95a845222f566175c681b8 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 17 Nov 2022 10:30:33 +0900 Subject: kbuild: deb-pkg: get rid of |flex:native workaround from Build-Depends "| flex:native" was a workaround (suggested by Ben, see Link) because "MultiArch: foreign" was missing in the flex package on some old distros when commit e3a22850664f ("deb-pkg: generate correct build dependencies") was applied. It seems fixing the flex package has been completed. Get rid of the workaround. Link: https://lore.kernel.org/linux-kbuild/ab49b0582ef12b14b1a68877263b81813e2492a2.camel@decadent.org.uk/ Link: https://wiki.debian.org/CrossBuildPackagingGuidelines Signed-off-by: Masahiro Yamada Reviewed-by: Ben Hutchings --- scripts/package/mkdebian | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/package/mkdebian b/scripts/package/mkdebian index a3ac5a716e9f..6cf383225b8b 100755 --- a/scripts/package/mkdebian +++ b/scripts/package/mkdebian @@ -175,7 +175,7 @@ Section: kernel Priority: optional Maintainer: $maintainer Rules-Requires-Root: no -Build-Depends: bc, rsync, kmod, cpio, bison, flex | flex:native $extra_build_depends +Build-Depends: bc, rsync, kmod, cpio, bison, flex $extra_build_depends Homepage: https://www.kernel.org/ Package: $packagename-$version -- cgit v1.2.3 From a2430b25c31840a6dcbf95c65415d5fee2984dbc Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 19 Nov 2022 04:15:50 +0900 Subject: kbuild: add kbuild-file macro While building, installing, cleaning, Kbuild visits sub-directories and includes 'Kbuild' or 'Makefile' that exists there. Add 'kbuild-file' macro, and reuse it from scripts/Makefie.* Signed-off-by: Masahiro Yamada Reviewed-by: Nicolas Schier Reviewed-by: Alexander Lobakin Tested-by: Alexander Lobakin --- scripts/Kbuild.include | 5 +++++ scripts/Makefile.asm-generic | 6 +++--- scripts/Makefile.build | 6 +----- scripts/Makefile.clean | 5 +---- scripts/Makefile.dtbinst | 2 +- scripts/Makefile.modpost | 2 +- 6 files changed, 12 insertions(+), 14 deletions(-) (limited to 'scripts') diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include index 2bc08ace38a3..cbe28744637b 100644 --- a/scripts/Kbuild.include +++ b/scripts/Kbuild.include @@ -40,6 +40,11 @@ escsq = $(subst $(squote),'\$(squote)',$1) # Quote a string to pass it to C files. foo => '"foo"' stringify = $(squote)$(quote)$1$(quote)$(squote) +### +# The path to Kbuild or Makefile. Kbuild has precedence over Makefile. +kbuild-dir = $(if $(filter /%,$(src)),$(src),$(srctree)/$(src)) +kbuild-file = $(or $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Makefile) + ### # Easy method for doing a status message kecho := : diff --git a/scripts/Makefile.asm-generic b/scripts/Makefile.asm-generic index 1d501c57f9ef..8d01b37b7677 100644 --- a/scripts/Makefile.asm-generic +++ b/scripts/Makefile.asm-generic @@ -10,15 +10,15 @@ PHONY := all all: src := $(subst /generated,,$(obj)) --include $(src)/Kbuild + +include $(srctree)/scripts/Kbuild.include +-include $(kbuild-file) # $(generic)/Kbuild lists mandatory-y. Exclude um since it is a special case. ifneq ($(SRCARCH),um) include $(srctree)/$(generic)/Kbuild endif -include $(srctree)/scripts/Kbuild.include - redundant := $(filter $(mandatory-y) $(generated-y), $(generic-y)) redundant += $(foreach f, $(generic-y), $(if $(wildcard $(srctree)/$(src)/$(f)),$(f))) redundant := $(sort $(redundant)) diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 41f3602fc8de..37cf88d076e8 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -38,11 +38,7 @@ subdir-ccflags-y := include $(srctree)/scripts/Kbuild.include include $(srctree)/scripts/Makefile.compiler - -# The filename Kbuild has precedence over Makefile -kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src)) -include $(or $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Makefile) - +include $(kbuild-file) include $(srctree)/scripts/Makefile.lib # Do not include hostprogs rules unless needed. diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean index 878cec648959..3649900696dd 100644 --- a/scripts/Makefile.clean +++ b/scripts/Makefile.clean @@ -9,10 +9,7 @@ PHONY := __clean __clean: include $(srctree)/scripts/Kbuild.include - -# The filename Kbuild has precedence over Makefile -kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src)) -include $(or $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Makefile) +include $(kbuild-file) # Figure out what we need to build from the various variables # ========================================================================== diff --git a/scripts/Makefile.dtbinst b/scripts/Makefile.dtbinst index 190d781e84f4..2ab936e4179d 100644 --- a/scripts/Makefile.dtbinst +++ b/scripts/Makefile.dtbinst @@ -15,7 +15,7 @@ __dtbs_install: include include/config/auto.conf include $(srctree)/scripts/Kbuild.include -include $(src)/Makefile +include $(kbuild-file) dtbs := $(addprefix $(dst)/, $(dtb-y) $(if $(CONFIG_OF_ALL_DTBS),$(dtb-))) subdirs := $(addprefix $(obj)/, $(subdir-y) $(subdir-m)) diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost index e41dee64d429..55a72f5eb76d 100644 --- a/scripts/Makefile.modpost +++ b/scripts/Makefile.modpost @@ -93,7 +93,7 @@ obj := $(KBUILD_EXTMOD) src := $(obj) # Include the module's Makefile to find KBUILD_EXTRA_SYMBOLS -include $(or $(wildcard $(src)/Kbuild), $(src)/Makefile) +include $(kbuild-file) module.symvers-if-present := $(wildcard Module.symvers) output-symdump := $(KBUILD_EXTMOD)/Module.symvers -- cgit v1.2.3 From 598afa050403ddbb015ad4d9f8e6b911c3c93d33 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 19 Nov 2022 04:15:51 +0900 Subject: kbuild: warn objects shared among multiple modules If an object is shared among multiple modules, and some of them are configured as 'm', but the others as 'y', the shared object is built as modular, then linked to the modules and vmlinux. This is a potential issue because the expected CFLAGS are different between modules and builtins. Commit 637a642f5ca5 ("zstd: Fixing mixed module-builtin objects") reported that this could be even more fatal in some cases such as Clang LTO. That commit fixed lib/zlib/zstd_{compress,decompress}, but there are still more instances of breakage. This commit adds a W=1 warning for shared objects, so that the kbuild test robot, which provides build tests with W=1, will avoid a new breakage slipping in. Quick compile tests on v6.1-rc4 detected the following: scripts/Makefile.build:252: ./drivers/block/rnbd/Makefile: rnbd-common.o is added to multiple modules: rnbd-client rnbd-server scripts/Makefile.build:252: ./drivers/crypto/marvell/octeontx2/Makefile: cn10k_cpt.o is added to multiple modules: rvu_cptpf rvu_cptvf scripts/Makefile.build:252: ./drivers/crypto/marvell/octeontx2/Makefile: otx2_cptlf.o is added to multiple modules: rvu_cptpf rvu_cptvf scripts/Makefile.build:252: ./drivers/crypto/marvell/octeontx2/Makefile: otx2_cpt_mbox_common.o is added to multiple modules: rvu_cptpf rvu_cptvf scripts/Makefile.build:252: ./drivers/edac/Makefile: skx_common.o is added to multiple modules: i10nm_edac skx_edac scripts/Makefile.build:252: ./drivers/gpu/drm/bridge/imx/Makefile: imx-ldb-helper.o is added to multiple modules: imx8qm-ldb imx8qxp-ldb scripts/Makefile.build:252: ./drivers/mfd/Makefile: rsmu_core.o is added to multiple modules: rsmu-i2c rsmu-spi scripts/Makefile.build:252: ./drivers/mtd/tests/Makefile: mtd_test.o is added to multiple modules: mtd_nandbiterrs mtd_oobtest mtd_pagetest mtd_readtest mtd_speedtest mtd_stresstest mtd_subpagetest mtd_torturetest scripts/Makefile.build:252: ./drivers/net/dsa/ocelot/Makefile: felix.o is added to multiple modules: mscc_felix mscc_seville scripts/Makefile.build:252: ./drivers/net/ethernet/cavium/liquidio/Makefile: cn23xx_pf_device.o is added to multiple modules: liquidio liquidio_vf scripts/Makefile.build:252: ./drivers/net/ethernet/cavium/liquidio/Makefile: cn23xx_vf_device.o is added to multiple modules: liquidio liquidio_vf scripts/Makefile.build:252: ./drivers/net/ethernet/cavium/liquidio/Makefile: cn66xx_device.o is added to multiple modules: liquidio liquidio_vf scripts/Makefile.build:252: ./drivers/net/ethernet/cavium/liquidio/Makefile: cn68xx_device.o is added to multiple modules: liquidio liquidio_vf scripts/Makefile.build:252: ./drivers/net/ethernet/cavium/liquidio/Makefile: lio_core.o is added to multiple modules: liquidio liquidio_vf scripts/Makefile.build:252: ./drivers/net/ethernet/cavium/liquidio/Makefile: lio_ethtool.o is added to multiple modules: liquidio liquidio_vf scripts/Makefile.build:252: ./drivers/net/ethernet/cavium/liquidio/Makefile: octeon_device.o is added to multiple modules: liquidio liquidio_vf scripts/Makefile.build:252: ./drivers/net/ethernet/cavium/liquidio/Makefile: octeon_droq.o is added to multiple modules: liquidio liquidio_vf scripts/Makefile.build:252: ./drivers/net/ethernet/cavium/liquidio/Makefile: octeon_mailbox.o is added to multiple modules: liquidio liquidio_vf scripts/Makefile.build:252: ./drivers/net/ethernet/cavium/liquidio/Makefile: octeon_mem_ops.o is added to multiple modules: liquidio liquidio_vf scripts/Makefile.build:252: ./drivers/net/ethernet/cavium/liquidio/Makefile: octeon_nic.o is added to multiple modules: liquidio liquidio_vf scripts/Makefile.build:252: ./drivers/net/ethernet/cavium/liquidio/Makefile: request_manager.o is added to multiple modules: liquidio liquidio_vf scripts/Makefile.build:252: ./drivers/net/ethernet/cavium/liquidio/Makefile: response_manager.o is added to multiple modules: liquidio liquidio_vf scripts/Makefile.build:252: ./drivers/net/ethernet/freescale/dpaa2/Makefile: dpaa2-mac.o is added to multiple modules: fsl-dpaa2-eth fsl-dpaa2-switch scripts/Makefile.build:252: ./drivers/net/ethernet/freescale/dpaa2/Makefile: dpmac.o is added to multiple modules: fsl-dpaa2-eth fsl-dpaa2-switch scripts/Makefile.build:252: ./drivers/net/ethernet/freescale/enetc/Makefile: enetc_cbdr.o is added to multiple modules: fsl-enetc fsl-enetc-vf scripts/Makefile.build:252: ./drivers/net/ethernet/freescale/enetc/Makefile: enetc_ethtool.o is added to multiple modules: fsl-enetc fsl-enetc-vf scripts/Makefile.build:252: ./drivers/net/ethernet/freescale/enetc/Makefile: enetc.o is added to multiple modules: fsl-enetc fsl-enetc-vf scripts/Makefile.build:252: ./drivers/net/ethernet/hisilicon/hns3/Makefile: hns3_common/hclge_comm_cmd.o is added to multiple modules: hclge hclgevf scripts/Makefile.build:252: ./drivers/net/ethernet/hisilicon/hns3/Makefile: hns3_common/hclge_comm_rss.o is added to multiple modules: hclge hclgevf scripts/Makefile.build:252: ./drivers/net/ethernet/hisilicon/hns3/Makefile: hns3_common/hclge_comm_tqp_stats.o is added to multiple modules: hclge hclgevf scripts/Makefile.build:252: ./drivers/net/ethernet/marvell/octeontx2/nic/Makefile: otx2_dcbnl.o is added to multiple modules: rvu_nicpf rvu_nicvf scripts/Makefile.build:252: ./drivers/net/ethernet/marvell/octeontx2/nic/Makefile: otx2_devlink.o is added to multiple modules: rvu_nicpf rvu_nicvf scripts/Makefile.build:252: ./drivers/net/ethernet/ti/Makefile: cpsw_ale.o is added to multiple modules: keystone_netcp keystone_netcp_ethss ti_cpsw ti_cpsw_new scripts/Makefile.build:252: ./drivers/net/ethernet/ti/Makefile: cpsw_ethtool.o is added to multiple modules: ti_cpsw ti_cpsw_new scripts/Makefile.build:252: ./drivers/net/ethernet/ti/Makefile: cpsw_priv.o is added to multiple modules: ti_cpsw ti_cpsw_new scripts/Makefile.build:252: ./drivers/net/ethernet/ti/Makefile: cpsw_sl.o is added to multiple modules: ti_cpsw ti_cpsw_new scripts/Makefile.build:252: ./drivers/net/ethernet/ti/Makefile: davinci_cpdma.o is added to multiple modules: ti_cpsw ti_cpsw_new ti_davinci_emac scripts/Makefile.build:252: ./drivers/platform/x86/intel/int3472/Makefile: common.o is added to multiple modules: intel_skl_int3472_discrete intel_skl_int3472_tps68470 scripts/Makefile.build:252: ./sound/soc/codecs/Makefile: wcd-clsh-v2.o is added to multiple modules: snd-soc-wcd9335 snd-soc-wcd934x snd-soc-wcd938x Once all the warnings are fixed, it can become an error without the W= option. Signed-off-by: Masahiro Yamada Reviewed-by: Alexander Lobakin Tested-by: Alexander Lobakin Reviewed-by: Nicolas Schier --- scripts/Makefile.build | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'scripts') diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 37cf88d076e8..799df12b53f3 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -222,6 +222,10 @@ endif cmd_check_local_export = $(srctree)/scripts/check-local-export $@ +ifneq ($(findstring 1, $(KBUILD_EXTRA_WARN)),) +cmd_warn_shared_object = $(if $(word 2, $(modname-multi)),$(warning $(kbuild-file): $*.o is added to multiple modules: $(modname-multi))) +endif + define rule_cc_o_c $(call cmd_and_fixdep,cc_o_c) $(call cmd,gen_ksymdeps) @@ -231,6 +235,7 @@ define rule_cc_o_c $(call cmd,gen_objtooldep) $(call cmd,gen_symversions_c) $(call cmd,record_mcount) + $(call cmd,warn_shared_object) endef define rule_as_o_S @@ -239,6 +244,7 @@ define rule_as_o_S $(call cmd,check_local_export) $(call cmd,gen_objtooldep) $(call cmd,gen_symversions_S) + $(call cmd,warn_shared_object) endef # Built-in and composite module parts -- cgit v1.2.3 From 8818039f959b2efc0d6f2cb101f8061332f0c77e Mon Sep 17 00:00:00 2001 From: Ivan Vecera Date: Mon, 21 Nov 2022 09:48:45 -0500 Subject: kbuild: add ability to make source rpm buildable using koji MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changes: - added new target 'srcrpm-pkg' to generate source rpm - added required build tools to spec file - removed locally compiled host tools to force their re-compile Signed-off-by: Ivan Vecera Signed-off-by: Jonathan Toppins Acked-by: Íñigo Huguet Tested-by: Ivan Vecera Signed-off-by: Masahiro Yamada --- scripts/Makefile.package | 10 ++++++++++ scripts/package/mkspec | 7 +++++++ 2 files changed, 17 insertions(+) (limited to 'scripts') diff --git a/scripts/Makefile.package b/scripts/Makefile.package index 8bbcced67c22..1290f1c631fb 100644 --- a/scripts/Makefile.package +++ b/scripts/Makefile.package @@ -62,6 +62,16 @@ rpm-pkg: +rpmbuild $(RPMOPTS) --target $(UTS_MACHINE)-linux -ta $(KERNELPATH).tar.gz \ --define='_smp_mflags %{nil}' +# srcrpm-pkg +# --------------------------------------------------------------------------- +PHONY += srcrpm-pkg +srcrpm-pkg: + $(MAKE) clean + $(CONFIG_SHELL) $(MKSPEC) >$(objtree)/kernel.spec + $(call cmd,src_tar,$(KERNELPATH),kernel.spec) + +rpmbuild $(RPMOPTS) --target $(UTS_MACHINE)-linux -ts $(KERNELPATH).tar.gz \ + --define='_smp_mflags %{nil}' --define='_srcrpmdir $(srctree)' + # binrpm-pkg # --------------------------------------------------------------------------- PHONY += binrpm-pkg diff --git a/scripts/package/mkspec b/scripts/package/mkspec index 70392fd2fd29..dda00a948a01 100755 --- a/scripts/package/mkspec +++ b/scripts/package/mkspec @@ -33,6 +33,8 @@ EXCLUDES="$RCS_TAR_IGNORE --exclude=*vmlinux* --exclude=*.mod \ --exclude=*.o --exclude=*.ko --exclude=*.cmd --exclude=Documentation \ --exclude=.config.old --exclude=.missing-syscalls.d --exclude=*.s" +test -n "$LOCALVERSION" && MAKE="$MAKE LOCALVERSION=$LOCALVERSION" + # We can label the here-doc lines for conditional output to the spec file # # Labels: @@ -49,6 +51,9 @@ sed -e '/^DEL/d' -e 's/^\t*//' < Date: Fri, 18 Nov 2022 22:36:31 +0900 Subject: scripts/kallsyms.c Make the comment up-to-date with current implementation The comment in scripts/kallsyms.c describing the usage of scripts/kallsyms does not reflect the latest implementation. Fix the comment to be equivalent to what the usage() function prints. Signed-off-by: Yuma Ueda Reviewed-by: Miguel Ojeda Link: https://lore.kernel.org/r/20221118133631.4554-1-cyan@0x00a1e9.dev Signed-off-by: Greg Kroah-Hartman --- scripts/kallsyms.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c index 03fa07ad45d9..46d1afaaf4cd 100644 --- a/scripts/kallsyms.c +++ b/scripts/kallsyms.c @@ -5,7 +5,8 @@ * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. * - * Usage: nm -n vmlinux | scripts/kallsyms [--all-symbols] > symbols.S + * Usage: kallsyms [--all-symbols] [--absolute-percpu] + * [--base-relative] in.map > out.S * * Table compression uses all the unused char codes on the symbols and * maps these to the most used substrings (tokens). For instance, it might -- cgit v1.2.3 From df1f1ea9569eef05c006aeae1d65fbf6c2339677 Mon Sep 17 00:00:00 2001 From: Paran Lee Date: Thu, 24 Nov 2022 07:00:44 +0900 Subject: scripts: add rust in scripts/Makefile.package Add rust argument at TAR_CONTENT in scripts/Makefile.package script with alphabetical order. Signed-off-by: Paran Lee Signed-off-by: Masahiro Yamada --- scripts/Makefile.package | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/Makefile.package b/scripts/Makefile.package index 8bbcced67c22..2a90139ecbe1 100644 --- a/scripts/Makefile.package +++ b/scripts/Makefile.package @@ -30,8 +30,8 @@ KBUILD_PKG_ROOTCMD ?="fakeroot -u" export KDEB_SOURCENAME # Include only those top-level files that are needed by make, plus the GPL copy TAR_CONTENT := Documentation LICENSES arch block certs crypto drivers fs \ - include init io_uring ipc kernel lib mm net samples scripts \ - security sound tools usr virt \ + include init io_uring ipc kernel lib mm net rust \ + samples scripts security sound tools usr virt \ .config .scmversion Makefile \ Kbuild Kconfig COPYING $(wildcard localversion*) MKSPEC := $(srctree)/scripts/package/mkspec -- cgit v1.2.3 From 248043299bf61134fb675d16963e11f49e79b05b Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 25 Nov 2022 12:12:49 +0200 Subject: modpost: Mark uuid_le type to be suitable only for MEI The uuid_le type is used only in MEI ABI, do not advertise it for others. While at it, comment out that UUID types are not to be used in a new code. Signed-off-by: Andy Shevchenko --- scripts/mod/file2alias.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'scripts') diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 7df23905fdf1..91c2e7ba5e52 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -34,19 +34,23 @@ typedef Elf64_Addr kernel_ulong_t; typedef uint32_t __u32; typedef uint16_t __u16; typedef unsigned char __u8; + +/* UUID types for backward compatibility, don't use in new code */ typedef struct { __u8 b[16]; } guid_t; -/* backwards compatibility, don't use in new code */ -typedef struct { - __u8 b[16]; -} uuid_le; typedef struct { __u8 b[16]; } uuid_t; + #define UUID_STRING_LEN 36 +/* MEI UUID type, don't use anywhere else */ +typedef struct { + __u8 b[16]; +} uuid_le; + /* Big exception to the "don't include kernel headers into userspace, which * even potentially has different endianness and word sizes, since * we handle those differences explicitly below */ -- cgit v1.2.3 From 632ce1377dbbdabff575d33bec9c79d75ef0395a Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Tue, 29 Nov 2022 16:29:27 -0400 Subject: scripts/kernel-doc: support EXPORT_SYMBOL_NS_GPL() with -export Parse EXPORT_SYMBOL_NS_GPL() in addition to EXPORT_SYMBOL_GPL() for use with the -export flag. Link: https://lore.kernel.org/r/4-v6-a196d26f289e+11787-iommufd_jgg@nvidia.com Acked-by: Jonathan Corbet Signed-off-by: Jason Gunthorpe --- scripts/kernel-doc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'scripts') diff --git a/scripts/kernel-doc b/scripts/kernel-doc index aea04365bc69..48e3feca3170 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -256,6 +256,7 @@ my $doc_inline_sect = '\s*\*\s*(@\s*[\w][\w\.]*\s*):(.*)'; my $doc_inline_end = '^\s*\*/\s*$'; my $doc_inline_oneline = '^\s*/\*\*\s*(@[\w\s]+):\s*(.*)\s*\*/\s*$'; my $export_symbol = '^\s*EXPORT_SYMBOL(_GPL)?\s*\(\s*(\w+)\s*\)\s*;'; +my $export_symbol_ns = '^\s*EXPORT_SYMBOL_NS(_GPL)?\s*\(\s*(\w+)\s*,\s*\w+\)\s*;'; my $function_pointer = qr{([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)}; my $attribute = qr{__attribute__\s*\(\([a-z0-9,_\*\s\(\)]*\)\)}i; @@ -1948,6 +1949,10 @@ sub process_export_file($) { next if (defined($nosymbol_table{$2})); $function_table{$2} = 1; } + if (/$export_symbol_ns/) { + next if (defined($nosymbol_table{$2})); + $function_table{$2} = 1; + } } close(IN); @@ -2419,12 +2424,12 @@ found on PATH. =item -export Only output documentation for the symbols that have been exported using -EXPORT_SYMBOL() or EXPORT_SYMBOL_GPL() in any input FILE or -export-file FILE. +EXPORT_SYMBOL() and related macros in any input FILE or -export-file FILE. =item -internal Only output documentation for the symbols that have NOT been exported using -EXPORT_SYMBOL() or EXPORT_SYMBOL_GPL() in any input FILE or -export-file FILE. +EXPORT_SYMBOL() and related macros in any input FILE or -export-file FILE. =item -function NAME @@ -2451,8 +2456,7 @@ Do not output DOC: sections. =item -export-file FILE -Specify an additional FILE in which to look for EXPORT_SYMBOL() and -EXPORT_SYMBOL_GPL(). +Specify an additional FILE in which to look for EXPORT_SYMBOL information. To be used with -export or -internal. -- cgit v1.2.3 From 3965292ad0ca70320f1c632f2ac3b886c88b9e80 Mon Sep 17 00:00:00 2001 From: Liao Chang Date: Fri, 4 Nov 2022 15:05:23 +0800 Subject: checkpatch: add check for array allocator family argument order These array allocator family are sometimes misused with the first and second arguments switched. Same issue with calloc, kvcalloc, kvmalloc_array etc. Bleat if sizeof is the first argument. Link: https://lore.kernel.org/lkml/5374345c-7973-6a3c-d559-73bf4ac15079@redhat.com/ Link: https://lkml.kernel.org/r/20221104070523.60296-1-liaochang1@huawei.com Signed-off-by: Liao Chang Acked-by: Joe Perches Cc: Lukas Bulwahn Cc: Christophe JAILLET Cc: Andy Whitcroft Cc: Bagas Sanjaya Cc: Dwaipayan Ray Cc: Paolo Bonzini Signed-off-by: Andrew Morton --- scripts/checkpatch.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 29517897baa1..78cc595b98ce 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -7146,7 +7146,7 @@ sub process { } # check for alloc argument mismatch - if ($line =~ /\b((?:devm_)?(?:kcalloc|kmalloc_array))\s*\(\s*sizeof\b/) { + if ($line =~ /\b((?:devm_)?((?:k|kv)?(calloc|malloc_array)(?:_node)?))\s*\(\s*sizeof\b/) { WARN("ALLOC_ARRAY_ARGS", "$1 uses number as first arg, sizeof is generally wrong\n" . $herecurr); } -- cgit v1.2.3 From ecaa6ddff2fd843c0236a931bcc62bf239956617 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Thu, 10 Nov 2022 17:41:37 +0100 Subject: rust: add `build_error` crate The `build_error` crate provides a function `build_error` which will panic at compile-time if executed in const context and, by default, will cause a build error if not executed at compile time and the optimizer does not optimise away the call. The `CONFIG_RUST_BUILD_ASSERT_ALLOW` kernel option allows to relax the default build failure and convert it to a runtime check. If the runtime check fails, `panic!` will be called. Its functionality will be exposed to users as a couple macros in the `kernel` crate in the following patch, thus some documentation here refers to them for simplicity. Signed-off-by: Gary Guo Reviewed-by: Wei Liu [Reworded, adapted for upstream and applied latest changes] Signed-off-by: Miguel Ojeda --- lib/Kconfig.debug | 16 ++++++++++++++++ rust/Makefile | 22 +++++++++++++++++----- rust/build_error.rs | 31 +++++++++++++++++++++++++++++++ rust/exports.c | 5 +++++ scripts/generate_rust_analyzer.py | 8 +++++++- 5 files changed, 76 insertions(+), 6 deletions(-) create mode 100644 rust/build_error.rs (limited to 'scripts') diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 29280072dc0e..452c9f06c2bc 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -2801,6 +2801,22 @@ config RUST_OVERFLOW_CHECKS If unsure, say Y. +config RUST_BUILD_ASSERT_ALLOW + bool "Allow unoptimized build-time assertions" + depends on RUST + help + Controls how are `build_error!` and `build_assert!` handled during build. + + If calls to them exist in the binary, it may indicate a violated invariant + or that the optimizer failed to verify the invariant during compilation. + + This should not happen, thus by default the build is aborted. However, + as an escape hatch, you can choose Y here to ignore them during build + and let the check be carried at runtime (with `panic!` being called if + the check fails). + + If unsure, say N. + endmenu # "Rust" source "Documentation/Kconfig" diff --git a/rust/Makefile b/rust/Makefile index 7700d3853404..ff70c4c916f8 100644 --- a/rust/Makefile +++ b/rust/Makefile @@ -19,6 +19,12 @@ obj-$(CONFIG_RUST) += alloc.o bindings.o kernel.o always-$(CONFIG_RUST) += exports_alloc_generated.h exports_bindings_generated.h \ exports_kernel_generated.h +ifdef CONFIG_RUST_BUILD_ASSERT_ALLOW +obj-$(CONFIG_RUST) += build_error.o +else +always-$(CONFIG_RUST) += build_error.o +endif + obj-$(CONFIG_RUST) += exports.o # Avoids running `$(RUSTC)` for the sysroot when it may not be available. @@ -108,7 +114,7 @@ rustdoc-alloc: $(src)/alloc/lib.rs rustdoc-core rustdoc-compiler_builtins FORCE $(call if_changed,rustdoc) rustdoc-kernel: private rustc_target_flags = --extern alloc \ - --extern macros=$(objtree)/$(obj)/libmacros.so \ + --extern build_error --extern macros=$(objtree)/$(obj)/libmacros.so \ --extern bindings rustdoc-kernel: $(src)/kernel/lib.rs rustdoc-core rustdoc-macros \ rustdoc-compiler_builtins rustdoc-alloc $(obj)/libmacros.so \ @@ -126,6 +132,9 @@ quiet_cmd_rustc_test_library = RUSTC TL $< -L$(objtree)/$(obj)/test \ --crate-name $(subst rusttest-,,$(subst rusttestlib-,,$@)) $< +rusttestlib-build_error: $(src)/build_error.rs rusttest-prepare FORCE + $(call if_changed,rustc_test_library) + rusttestlib-macros: private rustc_target_flags = --extern proc_macro rusttestlib-macros: private rustc_test_library_proc = yes rusttestlib-macros: $(src)/macros/lib.rs rusttest-prepare FORCE @@ -216,9 +225,9 @@ rusttest-macros: $(src)/macros/lib.rs rusttest-prepare FORCE $(call if_changed,rustdoc_test) rusttest-kernel: private rustc_target_flags = --extern alloc \ - --extern macros --extern bindings + --extern build_error --extern macros --extern bindings rusttest-kernel: $(src)/kernel/lib.rs rusttest-prepare \ - rusttestlib-macros rusttestlib-bindings FORCE + rusttestlib-build_error rusttestlib-macros rusttestlib-bindings FORCE $(call if_changed,rustc_test) $(call if_changed,rustc_test_library) @@ -366,6 +375,9 @@ $(obj)/alloc.o: private rustc_target_flags = $(alloc-cfgs) $(obj)/alloc.o: $(src)/alloc/lib.rs $(obj)/compiler_builtins.o FORCE $(call if_changed_dep,rustc_library) +$(obj)/build_error.o: $(src)/build_error.rs $(obj)/compiler_builtins.o FORCE + $(call if_changed_dep,rustc_library) + $(obj)/bindings.o: $(src)/bindings/lib.rs \ $(obj)/compiler_builtins.o \ $(obj)/bindings/bindings_generated.rs \ @@ -373,8 +385,8 @@ $(obj)/bindings.o: $(src)/bindings/lib.rs \ $(call if_changed_dep,rustc_library) $(obj)/kernel.o: private rustc_target_flags = --extern alloc \ - --extern macros --extern bindings -$(obj)/kernel.o: $(src)/kernel/lib.rs $(obj)/alloc.o \ + --extern build_error --extern macros --extern bindings +$(obj)/kernel.o: $(src)/kernel/lib.rs $(obj)/alloc.o $(obj)/build_error.o \ $(obj)/libmacros.so $(obj)/bindings.o FORCE $(call if_changed_dep,rustc_library) diff --git a/rust/build_error.rs b/rust/build_error.rs new file mode 100644 index 000000000000..fa24eeef9929 --- /dev/null +++ b/rust/build_error.rs @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Build-time error. +//! +//! This crate provides a [const function][const-functions] `build_error`, which will panic in +//! compile-time if executed in [const context][const-context], and will cause a build error +//! if not executed at compile time and the optimizer does not optimise away the call. +//! +//! It is used by `build_assert!` in the kernel crate, allowing checking of +//! conditions that could be checked statically, but could not be enforced in +//! Rust yet (e.g. perform some checks in [const functions][const-functions], but those +//! functions could still be called in the runtime). +//! +//! For details on constant evaluation in Rust, please see the [Reference][const-eval]. +//! +//! [const-eval]: https://doc.rust-lang.org/reference/const_eval.html +//! [const-functions]: https://doc.rust-lang.org/reference/const_eval.html#const-functions +//! [const-context]: https://doc.rust-lang.org/reference/const_eval.html#const-context + +#![no_std] + +/// Panics if executed in [const context][const-context], or triggers a build error if not. +/// +/// [const-context]: https://doc.rust-lang.org/reference/const_eval.html#const-context +#[inline(never)] +#[cold] +#[export_name = "rust_build_error"] +#[track_caller] +pub const fn build_error(msg: &'static str) -> ! { + panic!("{}", msg); +} diff --git a/rust/exports.c b/rust/exports.c index bb7cc64cecd0..83e2a7070cae 100644 --- a/rust/exports.c +++ b/rust/exports.c @@ -19,3 +19,8 @@ #include "exports_alloc_generated.h" #include "exports_bindings_generated.h" #include "exports_kernel_generated.h" + +// For modules using `rust/build_error.rs`. +#ifdef CONFIG_RUST_BUILD_ASSERT_ALLOW +EXPORT_SYMBOL_RUST_GPL(rust_build_error); +#endif diff --git a/scripts/generate_rust_analyzer.py b/scripts/generate_rust_analyzer.py index 75bb611bd751..ecc7ea9a4dcf 100755 --- a/scripts/generate_rust_analyzer.py +++ b/scripts/generate_rust_analyzer.py @@ -67,6 +67,12 @@ def generate_crates(srctree, objtree, sysroot_src): ) crates[-1]["proc_macro_dylib_path"] = "rust/libmacros.so" + append_crate( + "build_error", + srctree / "rust" / "build_error.rs", + ["core", "compiler_builtins"], + ) + append_crate( "bindings", srctree / "rust"/ "bindings" / "lib.rs", @@ -78,7 +84,7 @@ def generate_crates(srctree, objtree, sysroot_src): append_crate( "kernel", srctree / "rust" / "kernel" / "lib.rs", - ["core", "alloc", "macros", "bindings"], + ["core", "alloc", "macros", "build_error", "bindings"], cfg=cfg, ) crates[-1]["source"] = { -- cgit v1.2.3 From 270605317366e4535d8d9fc3d9da1ad0fb3c9d45 Mon Sep 17 00:00:00 2001 From: Kumar Kartikeya Dwivedi Date: Thu, 8 Dec 2022 02:11:37 +0530 Subject: bpf: Rework process_dynptr_func Recently, user ringbuf support introduced a PTR_TO_DYNPTR register type for use in callback state, because in case of user ringbuf helpers, there is no dynptr on the stack that is passed into the callback. To reflect such a state, a special register type was created. However, some checks have been bypassed incorrectly during the addition of this feature. First, for arg_type with MEM_UNINIT flag which initialize a dynptr, they must be rejected for such register type. Secondly, in the future, there are plans to add dynptr helpers that operate on the dynptr itself and may change its offset and other properties. In all of these cases, PTR_TO_DYNPTR shouldn't be allowed to be passed to such helpers, however the current code simply returns 0. The rejection for helpers that release the dynptr is already handled. For fixing this, we take a step back and rework existing code in a way that will allow fitting in all classes of helpers and have a coherent model for dealing with the variety of use cases in which dynptr is used. First, for ARG_PTR_TO_DYNPTR, it can either be set alone or together with a DYNPTR_TYPE_* constant that denotes the only type it accepts. Next, helpers which initialize a dynptr use MEM_UNINIT to indicate this fact. To make the distinction clear, use MEM_RDONLY flag to indicate that the helper only operates on the memory pointed to by the dynptr, not the dynptr itself. In C parlance, it would be equivalent to taking the dynptr as a point to const argument. When either of these flags are not present, the helper is allowed to mutate both the dynptr itself and also the memory it points to. Currently, the read only status of the memory is not tracked in the dynptr, but it would be trivial to add this support inside dynptr state of the register. With these changes and renaming PTR_TO_DYNPTR to CONST_PTR_TO_DYNPTR to better reflect its usage, it can no longer be passed to helpers that initialize a dynptr, i.e. bpf_dynptr_from_mem, bpf_ringbuf_reserve_dynptr. A note to reviewers is that in code that does mark_stack_slots_dynptr, and unmark_stack_slots_dynptr, we implicitly rely on the fact that PTR_TO_STACK reg is the only case that can reach that code path, as one cannot pass CONST_PTR_TO_DYNPTR to helpers that don't set MEM_RDONLY. In both cases such helpers won't be setting that flag. The next patch will add a couple of selftest cases to make sure this doesn't break. Fixes: 205715673844 ("bpf: Add bpf_user_ringbuf_drain() helper") Acked-by: Joanne Koong Signed-off-by: Kumar Kartikeya Dwivedi Link: https://lore.kernel.org/r/20221207204141.308952-4-memxor@gmail.com Signed-off-by: Alexei Starovoitov --- include/linux/bpf.h | 4 +- include/uapi/linux/bpf.h | 8 +- kernel/bpf/helpers.c | 18 +- kernel/bpf/verifier.c | 227 +++++++++++++++------ scripts/bpf_doc.py | 1 + tools/include/uapi/linux/bpf.h | 8 +- .../selftests/bpf/prog_tests/user_ringbuf.c | 4 +- 7 files changed, 191 insertions(+), 79 deletions(-) (limited to 'scripts') diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 4920ac252754..3de24cfb7a3d 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -775,7 +775,7 @@ enum bpf_reg_type { PTR_TO_MEM, /* reg points to valid memory region */ PTR_TO_BUF, /* reg points to a read/write buffer */ PTR_TO_FUNC, /* reg points to a bpf program function */ - PTR_TO_DYNPTR, /* reg points to a dynptr */ + CONST_PTR_TO_DYNPTR, /* reg points to a const struct bpf_dynptr */ __BPF_REG_TYPE_MAX, /* Extended reg_types. */ @@ -2828,7 +2828,7 @@ void bpf_dynptr_init(struct bpf_dynptr_kern *ptr, void *data, enum bpf_dynptr_type type, u32 offset, u32 size); void bpf_dynptr_set_null(struct bpf_dynptr_kern *ptr); int bpf_dynptr_check_size(u32 size); -u32 bpf_dynptr_get_size(struct bpf_dynptr_kern *ptr); +u32 bpf_dynptr_get_size(const struct bpf_dynptr_kern *ptr); #ifdef CONFIG_BPF_LSM void bpf_cgroup_atype_get(u32 attach_btf_id, int cgroup_atype); diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index f89de51a45db..464ca3f01fe7 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -5293,7 +5293,7 @@ union bpf_attr { * Return * Nothing. Always succeeds. * - * long bpf_dynptr_read(void *dst, u32 len, struct bpf_dynptr *src, u32 offset, u64 flags) + * long bpf_dynptr_read(void *dst, u32 len, const struct bpf_dynptr *src, u32 offset, u64 flags) * Description * Read *len* bytes from *src* into *dst*, starting from *offset* * into *src*. @@ -5303,7 +5303,7 @@ union bpf_attr { * of *src*'s data, -EINVAL if *src* is an invalid dynptr or if * *flags* is not 0. * - * long bpf_dynptr_write(struct bpf_dynptr *dst, u32 offset, void *src, u32 len, u64 flags) + * long bpf_dynptr_write(const struct bpf_dynptr *dst, u32 offset, void *src, u32 len, u64 flags) * Description * Write *len* bytes from *src* into *dst*, starting from *offset* * into *dst*. @@ -5313,7 +5313,7 @@ union bpf_attr { * of *dst*'s data, -EINVAL if *dst* is an invalid dynptr or if *dst* * is a read-only dynptr or if *flags* is not 0. * - * void *bpf_dynptr_data(struct bpf_dynptr *ptr, u32 offset, u32 len) + * void *bpf_dynptr_data(const struct bpf_dynptr *ptr, u32 offset, u32 len) * Description * Get a pointer to the underlying dynptr data. * @@ -5414,7 +5414,7 @@ union bpf_attr { * Drain samples from the specified user ring buffer, and invoke * the provided callback for each such sample: * - * long (\*callback_fn)(struct bpf_dynptr \*dynptr, void \*ctx); + * long (\*callback_fn)(const struct bpf_dynptr \*dynptr, void \*ctx); * * If **callback_fn** returns 0, the helper will continue to try * and drain the next sample, up to a maximum of diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c index 6ed5875b97a3..fa1093d4ad6b 100644 --- a/kernel/bpf/helpers.c +++ b/kernel/bpf/helpers.c @@ -1404,7 +1404,7 @@ static const struct bpf_func_proto bpf_kptr_xchg_proto = { #define DYNPTR_SIZE_MASK 0xFFFFFF #define DYNPTR_RDONLY_BIT BIT(31) -static bool bpf_dynptr_is_rdonly(struct bpf_dynptr_kern *ptr) +static bool bpf_dynptr_is_rdonly(const struct bpf_dynptr_kern *ptr) { return ptr->size & DYNPTR_RDONLY_BIT; } @@ -1414,7 +1414,7 @@ static void bpf_dynptr_set_type(struct bpf_dynptr_kern *ptr, enum bpf_dynptr_typ ptr->size |= type << DYNPTR_TYPE_SHIFT; } -u32 bpf_dynptr_get_size(struct bpf_dynptr_kern *ptr) +u32 bpf_dynptr_get_size(const struct bpf_dynptr_kern *ptr) { return ptr->size & DYNPTR_SIZE_MASK; } @@ -1438,7 +1438,7 @@ void bpf_dynptr_set_null(struct bpf_dynptr_kern *ptr) memset(ptr, 0, sizeof(*ptr)); } -static int bpf_dynptr_check_off_len(struct bpf_dynptr_kern *ptr, u32 offset, u32 len) +static int bpf_dynptr_check_off_len(const struct bpf_dynptr_kern *ptr, u32 offset, u32 len) { u32 size = bpf_dynptr_get_size(ptr); @@ -1483,7 +1483,7 @@ static const struct bpf_func_proto bpf_dynptr_from_mem_proto = { .arg4_type = ARG_PTR_TO_DYNPTR | DYNPTR_TYPE_LOCAL | MEM_UNINIT, }; -BPF_CALL_5(bpf_dynptr_read, void *, dst, u32, len, struct bpf_dynptr_kern *, src, +BPF_CALL_5(bpf_dynptr_read, void *, dst, u32, len, const struct bpf_dynptr_kern *, src, u32, offset, u64, flags) { int err; @@ -1506,12 +1506,12 @@ static const struct bpf_func_proto bpf_dynptr_read_proto = { .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_UNINIT_MEM, .arg2_type = ARG_CONST_SIZE_OR_ZERO, - .arg3_type = ARG_PTR_TO_DYNPTR, + .arg3_type = ARG_PTR_TO_DYNPTR | MEM_RDONLY, .arg4_type = ARG_ANYTHING, .arg5_type = ARG_ANYTHING, }; -BPF_CALL_5(bpf_dynptr_write, struct bpf_dynptr_kern *, dst, u32, offset, void *, src, +BPF_CALL_5(bpf_dynptr_write, const struct bpf_dynptr_kern *, dst, u32, offset, void *, src, u32, len, u64, flags) { int err; @@ -1532,14 +1532,14 @@ static const struct bpf_func_proto bpf_dynptr_write_proto = { .func = bpf_dynptr_write, .gpl_only = false, .ret_type = RET_INTEGER, - .arg1_type = ARG_PTR_TO_DYNPTR, + .arg1_type = ARG_PTR_TO_DYNPTR | MEM_RDONLY, .arg2_type = ARG_ANYTHING, .arg3_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg4_type = ARG_CONST_SIZE_OR_ZERO, .arg5_type = ARG_ANYTHING, }; -BPF_CALL_3(bpf_dynptr_data, struct bpf_dynptr_kern *, ptr, u32, offset, u32, len) +BPF_CALL_3(bpf_dynptr_data, const struct bpf_dynptr_kern *, ptr, u32, offset, u32, len) { int err; @@ -1560,7 +1560,7 @@ static const struct bpf_func_proto bpf_dynptr_data_proto = { .func = bpf_dynptr_data, .gpl_only = false, .ret_type = RET_PTR_TO_DYNPTR_MEM_OR_NULL, - .arg1_type = ARG_PTR_TO_DYNPTR, + .arg1_type = ARG_PTR_TO_DYNPTR | MEM_RDONLY, .arg2_type = ARG_ANYTHING, .arg3_type = ARG_CONST_ALLOC_SIZE_OR_ZERO, }; diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index eb742ac75844..a880776bd999 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -592,7 +592,7 @@ static const char *reg_type_str(struct bpf_verifier_env *env, [PTR_TO_BUF] = "buf", [PTR_TO_FUNC] = "func", [PTR_TO_MAP_KEY] = "map_key", - [PTR_TO_DYNPTR] = "dynptr_ptr", + [CONST_PTR_TO_DYNPTR] = "dynptr_ptr", }; if (type & PTR_MAYBE_NULL) { @@ -725,6 +725,28 @@ static bool dynptr_type_refcounted(enum bpf_dynptr_type type) return type == BPF_DYNPTR_TYPE_RINGBUF; } +static void __mark_dynptr_reg(struct bpf_reg_state *reg, + enum bpf_dynptr_type type, + bool first_slot); + +static void __mark_reg_not_init(const struct bpf_verifier_env *env, + struct bpf_reg_state *reg); + +static void mark_dynptr_stack_regs(struct bpf_reg_state *sreg1, + struct bpf_reg_state *sreg2, + enum bpf_dynptr_type type) +{ + __mark_dynptr_reg(sreg1, type, true); + __mark_dynptr_reg(sreg2, type, false); +} + +static void mark_dynptr_cb_reg(struct bpf_reg_state *reg, + enum bpf_dynptr_type type) +{ + __mark_dynptr_reg(reg, type, true); +} + + static int mark_stack_slots_dynptr(struct bpf_verifier_env *env, struct bpf_reg_state *reg, enum bpf_arg_type arg_type, int insn_idx) { @@ -746,9 +768,8 @@ static int mark_stack_slots_dynptr(struct bpf_verifier_env *env, struct bpf_reg_ if (type == BPF_DYNPTR_TYPE_INVALID) return -EINVAL; - state->stack[spi].spilled_ptr.dynptr.first_slot = true; - state->stack[spi].spilled_ptr.dynptr.type = type; - state->stack[spi - 1].spilled_ptr.dynptr.type = type; + mark_dynptr_stack_regs(&state->stack[spi].spilled_ptr, + &state->stack[spi - 1].spilled_ptr, type); if (dynptr_type_refcounted(type)) { /* The id is used to track proper releasing */ @@ -756,8 +777,8 @@ static int mark_stack_slots_dynptr(struct bpf_verifier_env *env, struct bpf_reg_ if (id < 0) return id; - state->stack[spi].spilled_ptr.id = id; - state->stack[spi - 1].spilled_ptr.id = id; + state->stack[spi].spilled_ptr.ref_obj_id = id; + state->stack[spi - 1].spilled_ptr.ref_obj_id = id; } return 0; @@ -779,25 +800,23 @@ static int unmark_stack_slots_dynptr(struct bpf_verifier_env *env, struct bpf_re } /* Invalidate any slices associated with this dynptr */ - if (dynptr_type_refcounted(state->stack[spi].spilled_ptr.dynptr.type)) { - release_reference(env, state->stack[spi].spilled_ptr.id); - state->stack[spi].spilled_ptr.id = 0; - state->stack[spi - 1].spilled_ptr.id = 0; - } - - state->stack[spi].spilled_ptr.dynptr.first_slot = false; - state->stack[spi].spilled_ptr.dynptr.type = 0; - state->stack[spi - 1].spilled_ptr.dynptr.type = 0; + if (dynptr_type_refcounted(state->stack[spi].spilled_ptr.dynptr.type)) + WARN_ON_ONCE(release_reference(env, state->stack[spi].spilled_ptr.ref_obj_id)); + __mark_reg_not_init(env, &state->stack[spi].spilled_ptr); + __mark_reg_not_init(env, &state->stack[spi - 1].spilled_ptr); return 0; } static bool is_dynptr_reg_valid_uninit(struct bpf_verifier_env *env, struct bpf_reg_state *reg) { struct bpf_func_state *state = func(env, reg); - int spi = get_spi(reg->off); - int i; + int spi, i; + + if (reg->type == CONST_PTR_TO_DYNPTR) + return false; + spi = get_spi(reg->off); if (!is_spi_bounds_valid(state, spi, BPF_DYNPTR_NR_SLOTS)) return true; @@ -813,9 +832,14 @@ static bool is_dynptr_reg_valid_uninit(struct bpf_verifier_env *env, struct bpf_ static bool is_dynptr_reg_valid_init(struct bpf_verifier_env *env, struct bpf_reg_state *reg) { struct bpf_func_state *state = func(env, reg); - int spi = get_spi(reg->off); + int spi; int i; + /* This already represents first slot of initialized bpf_dynptr */ + if (reg->type == CONST_PTR_TO_DYNPTR) + return true; + + spi = get_spi(reg->off); if (!is_spi_bounds_valid(state, spi, BPF_DYNPTR_NR_SLOTS) || !state->stack[spi].spilled_ptr.dynptr.first_slot) return false; @@ -834,15 +858,19 @@ static bool is_dynptr_type_expected(struct bpf_verifier_env *env, struct bpf_reg { struct bpf_func_state *state = func(env, reg); enum bpf_dynptr_type dynptr_type; - int spi = get_spi(reg->off); + int spi; /* ARG_PTR_TO_DYNPTR takes any type of dynptr */ if (arg_type == ARG_PTR_TO_DYNPTR) return true; dynptr_type = arg_to_dynptr_type(arg_type); - - return state->stack[spi].spilled_ptr.dynptr.type == dynptr_type; + if (reg->type == CONST_PTR_TO_DYNPTR) { + return reg->dynptr.type == dynptr_type; + } else { + spi = get_spi(reg->off); + return state->stack[spi].spilled_ptr.dynptr.type == dynptr_type; + } } /* The reg state of a pointer or a bounded scalar was saved when @@ -1354,9 +1382,6 @@ static const int caller_saved[CALLER_SAVED_REGS] = { BPF_REG_0, BPF_REG_1, BPF_REG_2, BPF_REG_3, BPF_REG_4, BPF_REG_5 }; -static void __mark_reg_not_init(const struct bpf_verifier_env *env, - struct bpf_reg_state *reg); - /* This helper doesn't clear reg->id */ static void ___mark_reg_known(struct bpf_reg_state *reg, u64 imm) { @@ -1419,6 +1444,19 @@ static void mark_reg_known_zero(struct bpf_verifier_env *env, __mark_reg_known_zero(regs + regno); } +static void __mark_dynptr_reg(struct bpf_reg_state *reg, enum bpf_dynptr_type type, + bool first_slot) +{ + /* reg->type has no meaning for STACK_DYNPTR, but when we set reg for + * callback arguments, it does need to be CONST_PTR_TO_DYNPTR, so simply + * set it unconditionally as it is ignored for STACK_DYNPTR anyway. + */ + __mark_reg_known_zero(reg); + reg->type = CONST_PTR_TO_DYNPTR; + reg->dynptr.type = type; + reg->dynptr.first_slot = first_slot; +} + static void mark_ptr_not_null_reg(struct bpf_reg_state *reg) { if (base_type(reg->type) == PTR_TO_MAP_VALUE) { @@ -5857,19 +5895,58 @@ static int process_kptr_func(struct bpf_verifier_env *env, int regno, return 0; } +/* There are two register types representing a bpf_dynptr, one is PTR_TO_STACK + * which points to a stack slot, and the other is CONST_PTR_TO_DYNPTR. + * + * In both cases we deal with the first 8 bytes, but need to mark the next 8 + * bytes as STACK_DYNPTR in case of PTR_TO_STACK. In case of + * CONST_PTR_TO_DYNPTR, we are guaranteed to get the beginning of the object. + * + * Mutability of bpf_dynptr is at two levels, one is at the level of struct + * bpf_dynptr itself, i.e. whether the helper is receiving a pointer to struct + * bpf_dynptr or pointer to const struct bpf_dynptr. In the former case, it can + * mutate the view of the dynptr and also possibly destroy it. In the latter + * case, it cannot mutate the bpf_dynptr itself but it can still mutate the + * memory that dynptr points to. + * + * The verifier will keep track both levels of mutation (bpf_dynptr's in + * reg->type and the memory's in reg->dynptr.type), but there is no support for + * readonly dynptr view yet, hence only the first case is tracked and checked. + * + * This is consistent with how C applies the const modifier to a struct object, + * where the pointer itself inside bpf_dynptr becomes const but not what it + * points to. + * + * Helpers which do not mutate the bpf_dynptr set MEM_RDONLY in their argument + * type, and declare it as 'const struct bpf_dynptr *' in their prototype. + */ int process_dynptr_func(struct bpf_verifier_env *env, int regno, - enum bpf_arg_type arg_type, - struct bpf_call_arg_meta *meta) + enum bpf_arg_type arg_type, struct bpf_call_arg_meta *meta) { struct bpf_reg_state *regs = cur_regs(env), *reg = ®s[regno]; - /* We only need to check for initialized / uninitialized helper - * dynptr args if the dynptr is not PTR_TO_DYNPTR, as the - * assumption is that if it is, that a helper function - * initialized the dynptr on behalf of the BPF program. + /* MEM_UNINIT and MEM_RDONLY are exclusive, when applied to an + * ARG_PTR_TO_DYNPTR (or ARG_PTR_TO_DYNPTR | DYNPTR_TYPE_*): + */ + if ((arg_type & (MEM_UNINIT | MEM_RDONLY)) == (MEM_UNINIT | MEM_RDONLY)) { + verbose(env, "verifier internal error: misconfigured dynptr helper type flags\n"); + return -EFAULT; + } + /* MEM_UNINIT - Points to memory that is an appropriate candidate for + * constructing a mutable bpf_dynptr object. + * + * Currently, this is only possible with PTR_TO_STACK + * pointing to a region of at least 16 bytes which doesn't + * contain an existing bpf_dynptr. + * + * MEM_RDONLY - Points to a initialized bpf_dynptr that will not be + * mutated or destroyed. However, the memory it points to + * may be mutated. + * + * None - Points to a initialized dynptr that can be mutated and + * destroyed, including mutation of the memory it points + * to. */ - if (base_type(reg->type) == PTR_TO_DYNPTR) - return 0; if (arg_type & MEM_UNINIT) { if (!is_dynptr_reg_valid_uninit(env, reg)) { verbose(env, "Dynptr has to be an uninitialized dynptr\n"); @@ -5885,7 +5962,13 @@ int process_dynptr_func(struct bpf_verifier_env *env, int regno, } meta->uninit_dynptr_regno = regno; - } else { + } else /* MEM_RDONLY and None case from above */ { + /* For the reg->type == PTR_TO_STACK case, bpf_dynptr is never const */ + if (reg->type == CONST_PTR_TO_DYNPTR && !(arg_type & MEM_RDONLY)) { + verbose(env, "cannot pass pointer to const bpf_dynptr, the helper mutates it\n"); + return -EINVAL; + } + if (!is_dynptr_reg_valid_init(env, reg)) { verbose(env, "Expected an initialized dynptr as arg #%d\n", @@ -5893,7 +5976,8 @@ int process_dynptr_func(struct bpf_verifier_env *env, int regno, return -EINVAL; } - if (!is_dynptr_type_expected(env, reg, arg_type)) { + /* Fold modifiers (in this case, MEM_RDONLY) when checking expected type */ + if (!is_dynptr_type_expected(env, reg, arg_type & ~MEM_RDONLY)) { const char *err_extra = ""; switch (arg_type & DYNPTR_TYPE_FLAG_MASK) { @@ -6056,7 +6140,7 @@ static const struct bpf_reg_types kptr_types = { .types = { PTR_TO_MAP_VALUE } } static const struct bpf_reg_types dynptr_types = { .types = { PTR_TO_STACK, - PTR_TO_DYNPTR | DYNPTR_TYPE_LOCAL, + CONST_PTR_TO_DYNPTR, } }; @@ -6241,12 +6325,16 @@ int check_func_arg_reg_off(struct bpf_verifier_env *env, return __check_ptr_off_reg(env, reg, regno, fixed_off_ok); } -static u32 stack_slot_get_id(struct bpf_verifier_env *env, struct bpf_reg_state *reg) +static u32 dynptr_ref_obj_id(struct bpf_verifier_env *env, struct bpf_reg_state *reg) { struct bpf_func_state *state = func(env, reg); - int spi = get_spi(reg->off); + int spi; + + if (reg->type == CONST_PTR_TO_DYNPTR) + return reg->ref_obj_id; - return state->stack[spi].spilled_ptr.id; + spi = get_spi(reg->off); + return state->stack[spi].spilled_ptr.ref_obj_id; } static int check_func_arg(struct bpf_verifier_env *env, u32 arg, @@ -6311,11 +6399,22 @@ skip_type_check: if (arg_type_is_release(arg_type)) { if (arg_type_is_dynptr(arg_type)) { struct bpf_func_state *state = func(env, reg); - int spi = get_spi(reg->off); + int spi; - if (!is_spi_bounds_valid(state, spi, BPF_DYNPTR_NR_SLOTS) || - !state->stack[spi].spilled_ptr.id) { - verbose(env, "arg %d is an unacquired reference\n", regno); + /* Only dynptr created on stack can be released, thus + * the get_spi and stack state checks for spilled_ptr + * should only be done before process_dynptr_func for + * PTR_TO_STACK. + */ + if (reg->type == PTR_TO_STACK) { + spi = get_spi(reg->off); + if (!is_spi_bounds_valid(state, spi, BPF_DYNPTR_NR_SLOTS) || + !state->stack[spi].spilled_ptr.ref_obj_id) { + verbose(env, "arg %d is an unacquired reference\n", regno); + return -EINVAL; + } + } else { + verbose(env, "cannot release unowned const bpf_dynptr\n"); return -EINVAL; } } else if (!reg->ref_obj_id && !register_is_null(reg)) { @@ -7289,11 +7388,10 @@ static int set_user_ringbuf_callback_state(struct bpf_verifier_env *env, { /* bpf_user_ringbuf_drain(struct bpf_map *map, void *callback_fn, void * callback_ctx, u64 flags); - * callback_fn(struct bpf_dynptr_t* dynptr, void *callback_ctx); + * callback_fn(const struct bpf_dynptr_t* dynptr, void *callback_ctx); */ __mark_reg_not_init(env, &callee->regs[BPF_REG_0]); - callee->regs[BPF_REG_1].type = PTR_TO_DYNPTR | DYNPTR_TYPE_LOCAL; - __mark_reg_known_zero(&callee->regs[BPF_REG_1]); + mark_dynptr_cb_reg(&callee->regs[BPF_REG_1], BPF_DYNPTR_TYPE_LOCAL); callee->regs[BPF_REG_2] = caller->regs[BPF_REG_3]; /* unused */ @@ -7687,7 +7785,15 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn regs = cur_regs(env); + /* This can only be set for PTR_TO_STACK, as CONST_PTR_TO_DYNPTR cannot + * be reinitialized by any dynptr helper. Hence, mark_stack_slots_dynptr + * is safe to do directly. + */ if (meta.uninit_dynptr_regno) { + if (regs[meta.uninit_dynptr_regno].type == CONST_PTR_TO_DYNPTR) { + verbose(env, "verifier internal error: CONST_PTR_TO_DYNPTR cannot be initialized\n"); + return -EFAULT; + } /* we write BPF_DW bits (8 bytes) at a time */ for (i = 0; i < BPF_DYNPTR_SIZE; i += 8) { err = check_mem_access(env, insn_idx, meta.uninit_dynptr_regno, @@ -7705,15 +7811,24 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn if (meta.release_regno) { err = -EINVAL; - if (arg_type_is_dynptr(fn->arg_type[meta.release_regno - BPF_REG_1])) + /* This can only be set for PTR_TO_STACK, as CONST_PTR_TO_DYNPTR cannot + * be released by any dynptr helper. Hence, unmark_stack_slots_dynptr + * is safe to do directly. + */ + if (arg_type_is_dynptr(fn->arg_type[meta.release_regno - BPF_REG_1])) { + if (regs[meta.release_regno].type == CONST_PTR_TO_DYNPTR) { + verbose(env, "verifier internal error: CONST_PTR_TO_DYNPTR cannot be released\n"); + return -EFAULT; + } err = unmark_stack_slots_dynptr(env, ®s[meta.release_regno]); - else if (meta.ref_obj_id) + } else if (meta.ref_obj_id) { err = release_reference(env, meta.ref_obj_id); - /* meta.ref_obj_id can only be 0 if register that is meant to be - * released is NULL, which must be > R0. - */ - else if (register_is_null(®s[meta.release_regno])) + } else if (register_is_null(®s[meta.release_regno])) { + /* meta.ref_obj_id can only be 0 if register that is meant to be + * released is NULL, which must be > R0. + */ err = 0; + } if (err) { verbose(env, "func %s#%d reference has not been acquired before\n", func_id_name(func_id), func_id); @@ -7787,11 +7902,7 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn return -EFAULT; } - if (base_type(reg->type) != PTR_TO_DYNPTR) - /* Find the id of the dynptr we're - * tracking the reference of - */ - meta.ref_obj_id = stack_slot_get_id(env, reg); + meta.ref_obj_id = dynptr_ref_obj_id(env, reg); break; } } @@ -8848,12 +8959,12 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_ break; case KF_ARG_PTR_TO_DYNPTR: if (reg->type != PTR_TO_STACK && - reg->type != PTR_TO_DYNPTR) { + reg->type != CONST_PTR_TO_DYNPTR) { verbose(env, "arg#%d expected pointer to stack or dynptr_ptr\n", i); return -EINVAL; } - ret = process_dynptr_func(env, regno, ARG_PTR_TO_DYNPTR, NULL); + ret = process_dynptr_func(env, regno, ARG_PTR_TO_DYNPTR | MEM_RDONLY, NULL); if (ret < 0) return ret; break; diff --git a/scripts/bpf_doc.py b/scripts/bpf_doc.py index fdb0aff8cb5a..e8d90829f23e 100755 --- a/scripts/bpf_doc.py +++ b/scripts/bpf_doc.py @@ -752,6 +752,7 @@ class PrinterHelpers(Printer): 'struct bpf_timer', 'struct mptcp_sock', 'struct bpf_dynptr', + 'const struct bpf_dynptr', 'struct iphdr', 'struct ipv6hdr', } diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index f89de51a45db..464ca3f01fe7 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -5293,7 +5293,7 @@ union bpf_attr { * Return * Nothing. Always succeeds. * - * long bpf_dynptr_read(void *dst, u32 len, struct bpf_dynptr *src, u32 offset, u64 flags) + * long bpf_dynptr_read(void *dst, u32 len, const struct bpf_dynptr *src, u32 offset, u64 flags) * Description * Read *len* bytes from *src* into *dst*, starting from *offset* * into *src*. @@ -5303,7 +5303,7 @@ union bpf_attr { * of *src*'s data, -EINVAL if *src* is an invalid dynptr or if * *flags* is not 0. * - * long bpf_dynptr_write(struct bpf_dynptr *dst, u32 offset, void *src, u32 len, u64 flags) + * long bpf_dynptr_write(const struct bpf_dynptr *dst, u32 offset, void *src, u32 len, u64 flags) * Description * Write *len* bytes from *src* into *dst*, starting from *offset* * into *dst*. @@ -5313,7 +5313,7 @@ union bpf_attr { * of *dst*'s data, -EINVAL if *dst* is an invalid dynptr or if *dst* * is a read-only dynptr or if *flags* is not 0. * - * void *bpf_dynptr_data(struct bpf_dynptr *ptr, u32 offset, u32 len) + * void *bpf_dynptr_data(const struct bpf_dynptr *ptr, u32 offset, u32 len) * Description * Get a pointer to the underlying dynptr data. * @@ -5414,7 +5414,7 @@ union bpf_attr { * Drain samples from the specified user ring buffer, and invoke * the provided callback for each such sample: * - * long (\*callback_fn)(struct bpf_dynptr \*dynptr, void \*ctx); + * long (\*callback_fn)(const struct bpf_dynptr \*dynptr, void \*ctx); * * If **callback_fn** returns 0, the helper will continue to try * and drain the next sample, up to a maximum of diff --git a/tools/testing/selftests/bpf/prog_tests/user_ringbuf.c b/tools/testing/selftests/bpf/prog_tests/user_ringbuf.c index 02b18d018b36..aefa0a474e58 100644 --- a/tools/testing/selftests/bpf/prog_tests/user_ringbuf.c +++ b/tools/testing/selftests/bpf/prog_tests/user_ringbuf.c @@ -673,8 +673,8 @@ static struct { {"user_ringbuf_callback_write_forbidden", "invalid mem access 'dynptr_ptr'"}, {"user_ringbuf_callback_null_context_write", "invalid mem access 'scalar'"}, {"user_ringbuf_callback_null_context_read", "invalid mem access 'scalar'"}, - {"user_ringbuf_callback_discard_dynptr", "arg 1 is an unacquired reference"}, - {"user_ringbuf_callback_submit_dynptr", "arg 1 is an unacquired reference"}, + {"user_ringbuf_callback_discard_dynptr", "cannot release unowned const bpf_dynptr"}, + {"user_ringbuf_callback_submit_dynptr", "cannot release unowned const bpf_dynptr"}, {"user_ringbuf_callback_invalid_return", "At callback return the register R0 has value"}, }; -- cgit v1.2.3 From 80b6093b55e31c2c40ff082fb32523d4e852954f Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 6 Dec 2022 13:07:31 +0900 Subject: kbuild: add -Wundef to KBUILD_CPPFLAGS for W=1 builds The use of an undefined macro in an #if directive is warned, but only in *.c files. No warning from other files such as *.S, *.lds.S. Since -Wundef is a preprocessor-related warning, it should be added to KBUILD_CPPFLAGS instead of KBUILD_CFLAGS. My previous attempt [1] uncovered several issues. I could not finish fixing them all. This commit adds -Wundef to KBUILD_CPPFLAGS for W=1 builds in order to block new breakages. (The kbuild test robot tests with W=1) We can fix the warnings one by one. After fixing all of them, we can make it default in the top Makefile, and remove -Wundef from KBUILD_CFLAGS. [1]: https://lore.kernel.org/all/20221012180118.331005-2-masahiroy@kernel.org/ Signed-off-by: Masahiro Yamada Reviewed-by: Nathan Chancellor Reviewed-by: Nick Desaulniers --- scripts/Makefile.extrawarn | 1 + 1 file changed, 1 insertion(+) (limited to 'scripts') diff --git a/scripts/Makefile.extrawarn b/scripts/Makefile.extrawarn index 6bbba36c5969..40cd13eca82e 100644 --- a/scripts/Makefile.extrawarn +++ b/scripts/Makefile.extrawarn @@ -38,6 +38,7 @@ KBUILD_CFLAGS += -Wno-sign-compare KBUILD_CFLAGS += -Wno-type-limits KBUILD_CFLAGS += -Wno-shift-negative-value +KBUILD_CPPFLAGS += -Wundef KBUILD_CPPFLAGS += -DKBUILD_EXTRA_WARN1 else -- cgit v1.2.3 From e4412739472b743e18860ad8d979a7ceb3071652 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 13 Oct 2022 03:18:41 +0900 Subject: Documentation: raise minimum supported version of binutils to 2.25 Binutils 2.23 was released in 2012. Almost 10 years old. We already require GCC 5.1, released in 2015. Bump the binutils version to 2.25, which was released some months before GCC 5.1. With this applied, some subsystems can start to clean up code. Examples: arch/arm/Kconfig.assembler arch/mips/vdso/Kconfig arch/powerpc/Makefile arch/x86/Kconfig.assembler Signed-off-by: Masahiro Yamada Acked-by: Linus Torvalds Reviewed-by: Nick Desaulniers --- Documentation/process/changes.rst | 4 ++-- scripts/min-tool-version.sh | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'scripts') diff --git a/Documentation/process/changes.rst b/Documentation/process/changes.rst index 9844ca3a71a6..ef540865ad22 100644 --- a/Documentation/process/changes.rst +++ b/Documentation/process/changes.rst @@ -35,7 +35,7 @@ Rust (optional) 1.62.0 rustc --version bindgen (optional) 0.56.0 bindgen --version GNU make 3.82 make --version bash 4.2 bash --version -binutils 2.23 ld -v +binutils 2.25 ld -v flex 2.5.35 flex --version bison 2.0 bison --version pahole 1.16 pahole --version @@ -119,7 +119,7 @@ Bash 4.2 or newer is needed. Binutils -------- -Binutils 2.23 or newer is needed to build the kernel. +Binutils 2.25 or newer is needed to build the kernel. pkg-config ---------- diff --git a/scripts/min-tool-version.sh b/scripts/min-tool-version.sh index 201bccfbc678..a814f1efb39d 100755 --- a/scripts/min-tool-version.sh +++ b/scripts/min-tool-version.sh @@ -14,7 +14,7 @@ fi case "$1" in binutils) - echo 2.23.0 + echo 2.25.0 ;; gcc) echo 5.1.0 -- cgit v1.2.3 From fccb3d3eda8d19b893e1fd18e8c70b78784b2a72 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 11 Dec 2022 11:46:47 +0900 Subject: kbuild: add test-{ge,gt,le,lt} macros GNU Make 4.4 introduced $(intcmp ...), which is useful to compare two integers without forking a new process. Add test-{ge,gt,le,lt} macros, which work more efficiently with GNU Make >= 4.4. For older Make versions, they fall back to the 'test' shell command. The first two parameters to $(intcmp ...) must not be empty. To avoid the syntax error, I appended '0' to them. Fortunately, '00' is treated as '0'. This is needed because CONFIG options may expand to an empty string when the kernel configuration is not included. Signed-off-by: Masahiro Yamada Acked-by: Palmer Dabbelt # RISC-V Reviewed-by: Nathan Chancellor Reviewed-by: Nicolas Schier --- Makefile | 2 +- arch/riscv/Makefile | 2 +- arch/x86/Makefile | 2 +- scripts/Kbuild.include | 16 ++++++++++++++++ scripts/Makefile.compiler | 4 ++-- 5 files changed, 21 insertions(+), 5 deletions(-) (limited to 'scripts') diff --git a/Makefile b/Makefile index 6b047daa46cc..ff36288ae671 100644 --- a/Makefile +++ b/Makefile @@ -994,7 +994,7 @@ KBUILD_LDFLAGS += -mllvm -import-instr-limit=5 # Check for frame size exceeding threshold during prolog/epilog insertion # when using lld < 13.0.0. ifneq ($(CONFIG_FRAME_WARN),0) -ifeq ($(shell test $(CONFIG_LLD_VERSION) -lt 130000; echo $$?),0) +ifeq ($(call test-lt, $(CONFIG_LLD_VERSION), 130000),y) KBUILD_LDFLAGS += -plugin-opt=-warn-stack-size=$(CONFIG_FRAME_WARN) endif endif diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile index 0d13b597cb55..faf2c2177094 100644 --- a/arch/riscv/Makefile +++ b/arch/riscv/Makefile @@ -37,7 +37,7 @@ else endif ifeq ($(CONFIG_LD_IS_LLD),y) -ifeq ($(shell test $(CONFIG_LLD_VERSION) -lt 150000; echo $$?),0) +ifeq ($(call test-lt, $(CONFIG_LLD_VERSION), 150000),y) KBUILD_CFLAGS += -mno-relax KBUILD_AFLAGS += -mno-relax ifndef CONFIG_AS_IS_LLVM diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 415a5d138de4..e72c7a49cd59 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -211,7 +211,7 @@ endif KBUILD_LDFLAGS += -m elf_$(UTS_MACHINE) ifdef CONFIG_LTO_CLANG -ifeq ($(shell test $(CONFIG_LLD_VERSION) -lt 130000; echo $$?),0) +ifeq ($(call test-lt, $(CONFIG_LLD_VERSION), 130000),y) KBUILD_LDFLAGS += -plugin-opt=-stack-alignment=$(if $(CONFIG_X86_32),4,8) endif endif diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include index cbe28744637b..3be7c2d75667 100644 --- a/scripts/Kbuild.include +++ b/scripts/Kbuild.include @@ -11,6 +11,22 @@ space := $(empty) $(empty) space_escape := _-_SPACE_-_ pound := \# +### +# Comparison macros. +# Usage: $(call test-lt, $(CONFIG_LLD_VERSION), 150000) +# +# Use $(intcmp ...) if supported. (Make >= 4.4) +# Otherwise, fall back to the 'test' shell command. +ifeq ($(intcmp 1,0,,,y),y) +test-ge = $(intcmp $(strip $1)0, $(strip $2)0,,y,y) +test-gt = $(intcmp $(strip $1)0, $(strip $2)0,,,y) +else +test-ge = $(shell test $(strip $1)0 -ge $(strip $2)0 && echo y) +test-gt = $(shell test $(strip $1)0 -gt $(strip $2)0 && echo y) +endif +test-le = $(call test-ge, $2, $1) +test-lt = $(call test-gt, $2, $1) + ### # Name of target with a '.' as filename prefix. foo/bar.o => foo/.bar.o dot-target = $(dir $@).$(notdir $@) diff --git a/scripts/Makefile.compiler b/scripts/Makefile.compiler index 20d353dcabfb..3d8adfd34af1 100644 --- a/scripts/Makefile.compiler +++ b/scripts/Makefile.compiler @@ -63,11 +63,11 @@ cc-disable-warning = $(call try-run,\ # gcc-min-version # Usage: cflags-$(call gcc-min-version, 70100) += -foo -gcc-min-version = $(shell [ $(CONFIG_GCC_VERSION)0 -ge $(1)0 ] && echo y) +gcc-min-version = $(call test-ge, $(CONFIG_GCC_VERSION), $1) # clang-min-version # Usage: cflags-$(call clang-min-version, 110000) += -foo -clang-min-version = $(shell [ $(CONFIG_CLANG_VERSION)0 -ge $(1)0 ] && echo y) +clang-min-version = $(call test-ge, $(CONFIG_CLANG_VERSION), $1) # ld-option # Usage: KBUILD_LDFLAGS += $(call ld-option, -X, -Y) -- cgit v1.2.3 From a5db80c65dbf9144de155f8a0f08becc9c307db0 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 11 Dec 2022 18:49:18 +0900 Subject: kbuild: do not sort after reading modules.order modules.order lists modules in the deterministic order (that is why "modules order"), and there is no duplication in the list. $(sort ) is pointless. Signed-off-by: Masahiro Yamada Reviewed-by: Nicolas Schier --- scripts/Makefile.modfinal | 2 +- scripts/Makefile.modinst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal index 25bedd83644b..4705d32388f3 100644 --- a/scripts/Makefile.modfinal +++ b/scripts/Makefile.modfinal @@ -13,7 +13,7 @@ include $(srctree)/scripts/Kbuild.include include $(srctree)/scripts/Makefile.lib # find all modules listed in modules.order -modules := $(sort $(shell cat $(MODORDER))) +modules := $(shell cat $(MODORDER)) __modfinal: $(modules) @: diff --git a/scripts/Makefile.modinst b/scripts/Makefile.modinst index a4c987c23750..f4cff42069ad 100644 --- a/scripts/Makefile.modinst +++ b/scripts/Makefile.modinst @@ -9,7 +9,7 @@ __modinst: include include/config/auto.conf include $(srctree)/scripts/Kbuild.include -modules := $(sort $(shell cat $(MODORDER))) +modules := $(shell cat $(MODORDER)) ifeq ($(KBUILD_EXTMOD),) dst := $(MODLIB)/kernel -- cgit v1.2.3 From 6768fa4bcb6c1618248f135d04b9287ba2724ae0 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 11 Dec 2022 11:54:47 +0900 Subject: kbuild: add read-file macro Since GNU Make 4.2, $(file ...) supports the read operater '<', which is useful to read a file without forking a new process. No warning is shown even if the input file is missing. For older Make versions, it falls back to the cat command. Signed-off-by: Masahiro Yamada Reviewed-by: Nicolas Schier Reviewed-by: Alexander Lobakin Tested-by: Alexander Lobakin --- Makefile | 2 +- scripts/Kbuild.include | 14 ++++++++++++++ scripts/Makefile.modfinal | 2 +- scripts/Makefile.modinst | 2 +- 4 files changed, 17 insertions(+), 3 deletions(-) (limited to 'scripts') diff --git a/Makefile b/Makefile index ff36288ae671..591485152a95 100644 --- a/Makefile +++ b/Makefile @@ -376,7 +376,7 @@ else # !mixed-build include $(srctree)/scripts/Kbuild.include # Read KERNELRELEASE from include/config/kernel.release (if it exists) -KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null) +KERNELRELEASE = $(call read-file, include/config/kernel.release) KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION) export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include index 3be7c2d75667..21e76ba0de17 100644 --- a/scripts/Kbuild.include +++ b/scripts/Kbuild.include @@ -10,6 +10,10 @@ empty := space := $(empty) $(empty) space_escape := _-_SPACE_-_ pound := \# +define newline + + +endef ### # Comparison macros. @@ -61,6 +65,16 @@ stringify = $(squote)$(quote)$1$(quote)$(squote) kbuild-dir = $(if $(filter /%,$(src)),$(src),$(srctree)/$(src)) kbuild-file = $(or $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Makefile) +### +# Read a file, replacing newlines with spaces +# +# Make 4.2 or later can read a file by using its builtin function. +ifneq ($(filter-out 3.% 4.0 4.1, $(MAKE_VERSION)),) +read-file = $(subst $(newline),$(space),$(file < $1)) +else +read-file = $(shell cat $1 2>/dev/null) +endif + ### # Easy method for doing a status message kecho := : diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal index 4705d32388f3..83f2797e530c 100644 --- a/scripts/Makefile.modfinal +++ b/scripts/Makefile.modfinal @@ -13,7 +13,7 @@ include $(srctree)/scripts/Kbuild.include include $(srctree)/scripts/Makefile.lib # find all modules listed in modules.order -modules := $(shell cat $(MODORDER)) +modules := $(call read-file, $(MODORDER)) __modfinal: $(modules) @: diff --git a/scripts/Makefile.modinst b/scripts/Makefile.modinst index f4cff42069ad..65aac6be78ec 100644 --- a/scripts/Makefile.modinst +++ b/scripts/Makefile.modinst @@ -9,7 +9,7 @@ __modinst: include include/config/auto.conf include $(srctree)/scripts/Kbuild.include -modules := $(shell cat $(MODORDER)) +modules := $(call read-file, $(MODORDER)) ifeq ($(KBUILD_EXTMOD),) dst := $(MODLIB)/kernel -- cgit v1.2.3 From 3122c84409d578a5df8bcb1953547e0b871ac4c2 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 11 Dec 2022 11:54:48 +0900 Subject: kconfig: refactor Makefile to reduce process forks Refactor Makefile and use read-file macro. For Make >= 4.2, it can read out a file by using the built-in function. Signed-off-by: Masahiro Yamada Reviewed-by: Nicolas Schier --- scripts/kconfig/.gitignore | 4 +++- scripts/kconfig/Makefile | 45 +++++++++++++++++++++++--------------------- scripts/kconfig/gconf-cfg.sh | 7 +++++-- scripts/kconfig/mconf-cfg.sh | 25 +++++++++++++----------- scripts/kconfig/nconf-cfg.sh | 23 ++++++++++++---------- scripts/kconfig/qconf-cfg.sh | 10 +++++++--- scripts/remove-stale-files | 2 ++ 7 files changed, 68 insertions(+), 48 deletions(-) (limited to 'scripts') diff --git a/scripts/kconfig/.gitignore b/scripts/kconfig/.gitignore index 500e7424b3ef..c8a3f9cd52f0 100644 --- a/scripts/kconfig/.gitignore +++ b/scripts/kconfig/.gitignore @@ -1,5 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only /conf /[gmnq]conf -/[gmnq]conf-cfg +/[gmnq]conf-cflags +/[gmnq]conf-libs +/qconf-bin /qconf-moc.cc diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile index b8ef0fb4bbef..0b1d15efaeb0 100644 --- a/scripts/kconfig/Makefile +++ b/scripts/kconfig/Makefile @@ -159,11 +159,12 @@ conf-objs := conf.o $(common-objs) hostprogs += nconf nconf-objs := nconf.o nconf.gui.o $(common-objs) -HOSTLDLIBS_nconf = $(shell . $(obj)/nconf-cfg && echo $$libs) -HOSTCFLAGS_nconf.o = $(shell . $(obj)/nconf-cfg && echo $$cflags) -HOSTCFLAGS_nconf.gui.o = $(shell . $(obj)/nconf-cfg && echo $$cflags) +HOSTLDLIBS_nconf = $(call read-file, $(obj)/nconf-libs) +HOSTCFLAGS_nconf.o = $(call read-file, $(obj)/nconf-cflags) +HOSTCFLAGS_nconf.gui.o = $(call read-file, $(obj)/nconf-cflags) -$(obj)/nconf.o $(obj)/nconf.gui.o: $(obj)/nconf-cfg +$(obj)/nconf: | $(obj)/nconf-libs +$(obj)/nconf.o $(obj)/nconf.gui.o: | $(obj)/nconf-cflags # mconf: Used for the menuconfig target based on lxdialog hostprogs += mconf @@ -171,27 +172,28 @@ lxdialog := $(addprefix lxdialog/, \ checklist.o inputbox.o menubox.o textbox.o util.o yesno.o) mconf-objs := mconf.o $(lxdialog) $(common-objs) -HOSTLDLIBS_mconf = $(shell . $(obj)/mconf-cfg && echo $$libs) +HOSTLDLIBS_mconf = $(call read-file, $(obj)/mconf-libs) $(foreach f, mconf.o $(lxdialog), \ - $(eval HOSTCFLAGS_$f = $$(shell . $(obj)/mconf-cfg && echo $$$$cflags))) + $(eval HOSTCFLAGS_$f = $$(call read-file, $(obj)/mconf-cflags))) -$(addprefix $(obj)/, mconf.o $(lxdialog)): $(obj)/mconf-cfg +$(obj)/mconf: | $(obj)/mconf-libs +$(addprefix $(obj)/, mconf.o $(lxdialog)): | $(obj)/mconf-cflags # qconf: Used for the xconfig target based on Qt hostprogs += qconf qconf-cxxobjs := qconf.o qconf-moc.o qconf-objs := images.o $(common-objs) -HOSTLDLIBS_qconf = $(shell . $(obj)/qconf-cfg && echo $$libs) -HOSTCXXFLAGS_qconf.o = $(shell . $(obj)/qconf-cfg && echo $$cflags) -HOSTCXXFLAGS_qconf-moc.o = $(shell . $(obj)/qconf-cfg && echo $$cflags) - -$(obj)/qconf.o: $(obj)/qconf-cfg +HOSTLDLIBS_qconf = $(call read-file, $(obj)/qconf-libs) +HOSTCXXFLAGS_qconf.o = -std=c++11 -fPIC $(call read-file, $(obj)/qconf-cflags) +HOSTCXXFLAGS_qconf-moc.o = -std=c++11 -fPIC $(call read-file, $(obj)/qconf-cflags) +$(obj)/qconf: | $(obj)/qconf-libs +$(obj)/qconf.o $(obj)/qconf-moc.o: | $(obj)/qconf-cflags quiet_cmd_moc = MOC $@ - cmd_moc = $(shell . $(obj)/qconf-cfg && echo $$moc) $< -o $@ + cmd_moc = $(call read-file, $(obj)/qconf-bin)/moc $< -o $@ -$(obj)/qconf-moc.cc: $(src)/qconf.h $(obj)/qconf-cfg FORCE +$(obj)/qconf-moc.cc: $(src)/qconf.h FORCE | $(obj)/qconf-bin $(call if_changed,moc) targets += qconf-moc.cc @@ -200,15 +202,16 @@ targets += qconf-moc.cc hostprogs += gconf gconf-objs := gconf.o images.o $(common-objs) -HOSTLDLIBS_gconf = $(shell . $(obj)/gconf-cfg && echo $$libs) -HOSTCFLAGS_gconf.o = $(shell . $(obj)/gconf-cfg && echo $$cflags) +HOSTLDLIBS_gconf = $(call read-file, $(obj)/gconf-libs) +HOSTCFLAGS_gconf.o = $(call read-file, $(obj)/gconf-cflags) -$(obj)/gconf.o: $(obj)/gconf-cfg +$(obj)/gconf: | $(obj)/gconf-libs +$(obj)/gconf.o: | $(obj)/gconf-cflags # check if necessary packages are available, and configure build flags -filechk_conf_cfg = $(CONFIG_SHELL) $< +cmd_conf_cfg = $< $(addprefix $(obj)/$*conf-, cflags libs bin) -$(obj)/%conf-cfg: $(src)/%conf-cfg.sh FORCE - $(call filechk,conf_cfg) +$(obj)/%conf-cflags $(obj)/%conf-libs $(obj)/%conf-bin: $(src)/%conf-cfg.sh + $(call cmd,conf_cfg) -clean-files += *conf-cfg +clean-files += *conf-cflags *conf-libs *conf-bin diff --git a/scripts/kconfig/gconf-cfg.sh b/scripts/kconfig/gconf-cfg.sh index cbd90c28c05f..040d8f338820 100755 --- a/scripts/kconfig/gconf-cfg.sh +++ b/scripts/kconfig/gconf-cfg.sh @@ -1,6 +1,9 @@ #!/bin/sh # SPDX-License-Identifier: GPL-2.0 +cflags=$1 +libs=$2 + PKG="gtk+-2.0 gmodule-2.0 libglade-2.0" if [ -z "$(command -v ${HOSTPKG_CONFIG})" ]; then @@ -26,5 +29,5 @@ if ! ${HOSTPKG_CONFIG} --atleast-version=2.0.0 gtk+-2.0; then exit 1 fi -echo cflags=\"$(${HOSTPKG_CONFIG} --cflags $PKG)\" -echo libs=\"$(${HOSTPKG_CONFIG} --libs $PKG)\" +${HOSTPKG_CONFIG} --cflags ${PKG} > ${cflags} +${HOSTPKG_CONFIG} --libs ${PKG} > ${libs} diff --git a/scripts/kconfig/mconf-cfg.sh b/scripts/kconfig/mconf-cfg.sh index 025b565e0b7c..1e61f50a5905 100755 --- a/scripts/kconfig/mconf-cfg.sh +++ b/scripts/kconfig/mconf-cfg.sh @@ -1,19 +1,22 @@ #!/bin/sh # SPDX-License-Identifier: GPL-2.0 +cflags=$1 +libs=$2 + PKG="ncursesw" PKG2="ncurses" if [ -n "$(command -v ${HOSTPKG_CONFIG})" ]; then if ${HOSTPKG_CONFIG} --exists $PKG; then - echo cflags=\"$(${HOSTPKG_CONFIG} --cflags $PKG)\" - echo libs=\"$(${HOSTPKG_CONFIG} --libs $PKG)\" + ${HOSTPKG_CONFIG} --cflags ${PKG} > ${cflags} + ${HOSTPKG_CONFIG} --libs ${PKG} > ${libs} exit 0 fi - if ${HOSTPKG_CONFIG} --exists $PKG2; then - echo cflags=\"$(${HOSTPKG_CONFIG} --cflags $PKG2)\" - echo libs=\"$(${HOSTPKG_CONFIG} --libs $PKG2)\" + if ${HOSTPKG_CONFIG} --exists ${PKG2}; then + ${HOSTPKG_CONFIG} --cflags ${PKG2} > ${cflags} + ${HOSTPKG_CONFIG} --libs ${PKG2} > ${libs} exit 0 fi fi @@ -22,22 +25,22 @@ fi # (Even if it is installed, some distributions such as openSUSE cannot # find ncurses by pkg-config.) if [ -f /usr/include/ncursesw/ncurses.h ]; then - echo cflags=\"-D_GNU_SOURCE -I/usr/include/ncursesw\" - echo libs=\"-lncursesw\" + echo -D_GNU_SOURCE -I/usr/include/ncursesw > ${cflags} + echo -lncursesw > ${libs} exit 0 fi if [ -f /usr/include/ncurses/ncurses.h ]; then - echo cflags=\"-D_GNU_SOURCE -I/usr/include/ncurses\" - echo libs=\"-lncurses\" + echo -D_GNU_SOURCE -I/usr/include/ncurses > ${cflags} + echo -lncurses > ${libs} exit 0 fi # As a final fallback before giving up, check if $HOSTCC knows of a default # ncurses installation (e.g. from a vendor-specific sysroot). if echo '#include ' | ${HOSTCC} -E - >/dev/null 2>&1; then - echo cflags=\"-D_GNU_SOURCE\" - echo libs=\"-lncurses\" + echo -D_GNU_SOURCE > ${cflags} + echo -lncurses > ${libs} exit 0 fi diff --git a/scripts/kconfig/nconf-cfg.sh b/scripts/kconfig/nconf-cfg.sh index 3a10bac2adb3..f871a2160e36 100755 --- a/scripts/kconfig/nconf-cfg.sh +++ b/scripts/kconfig/nconf-cfg.sh @@ -1,19 +1,22 @@ #!/bin/sh # SPDX-License-Identifier: GPL-2.0 +cflags=$1 +libs=$2 + PKG="ncursesw menuw panelw" PKG2="ncurses menu panel" if [ -n "$(command -v ${HOSTPKG_CONFIG})" ]; then if ${HOSTPKG_CONFIG} --exists $PKG; then - echo cflags=\"$(${HOSTPKG_CONFIG} --cflags $PKG)\" - echo libs=\"$(${HOSTPKG_CONFIG} --libs $PKG)\" + ${HOSTPKG_CONFIG} --cflags ${PKG} > ${cflags} + ${HOSTPKG_CONFIG} --libs ${PKG} > ${libs} exit 0 fi if ${HOSTPKG_CONFIG} --exists $PKG2; then - echo cflags=\"$(${HOSTPKG_CONFIG} --cflags $PKG2)\" - echo libs=\"$(${HOSTPKG_CONFIG} --libs $PKG2)\" + ${HOSTPKG_CONFIG} --cflags ${PKG2} > ${cflags} + ${HOSTPKG_CONFIG} --libs ${PKG2} > ${libs} exit 0 fi fi @@ -22,20 +25,20 @@ fi # (Even if it is installed, some distributions such as openSUSE cannot # find ncurses by pkg-config.) if [ -f /usr/include/ncursesw/ncurses.h ]; then - echo cflags=\"-D_GNU_SOURCE -I/usr/include/ncursesw\" - echo libs=\"-lncursesw -lmenuw -lpanelw\" + echo -D_GNU_SOURCE -I/usr/include/ncursesw > ${cflags} + echo -lncursesw -lmenuw -lpanelw > ${libs} exit 0 fi if [ -f /usr/include/ncurses/ncurses.h ]; then - echo cflags=\"-D_GNU_SOURCE -I/usr/include/ncurses\" - echo libs=\"-lncurses -lmenu -lpanel\" + echo -D_GNU_SOURCE -I/usr/include/ncurses > ${cflags} + echo -lncurses -lmenu -lpanel > ${libs} exit 0 fi if [ -f /usr/include/ncurses.h ]; then - echo cflags=\"-D_GNU_SOURCE\" - echo libs=\"-lncurses -lmenu -lpanel\" + echo -D_GNU_SOURCE > ${cflags} + echo -lncurses -lmenu -lpanel > ${libs} exit 0 fi diff --git a/scripts/kconfig/qconf-cfg.sh b/scripts/kconfig/qconf-cfg.sh index ad652cb53947..117f36e568fc 100755 --- a/scripts/kconfig/qconf-cfg.sh +++ b/scripts/kconfig/qconf-cfg.sh @@ -1,6 +1,10 @@ #!/bin/sh # SPDX-License-Identifier: GPL-2.0 +cflags=$1 +libs=$2 +bin=$3 + PKG="Qt5Core Qt5Gui Qt5Widgets" if [ -z "$(command -v ${HOSTPKG_CONFIG})" ]; then @@ -11,9 +15,9 @@ if [ -z "$(command -v ${HOSTPKG_CONFIG})" ]; then fi if ${HOSTPKG_CONFIG} --exists $PKG; then - echo cflags=\"-std=c++11 -fPIC $(${HOSTPKG_CONFIG} --cflags $PKG)\" - echo libs=\"$(${HOSTPKG_CONFIG} --libs $PKG)\" - echo moc=\"$(${HOSTPKG_CONFIG} --variable=host_bins Qt5Core)/moc\" + ${HOSTPKG_CONFIG} --cflags ${PKG} > ${cflags} + ${HOSTPKG_CONFIG} --libs ${PKG} > ${libs} + ${HOSTPKG_CONFIG} --variable=host_bins Qt5Core > ${bin} exit 0 fi diff --git a/scripts/remove-stale-files b/scripts/remove-stale-files index ccadfa3afb2b..64b14aa5aebf 100755 --- a/scripts/remove-stale-files +++ b/scripts/remove-stale-files @@ -47,3 +47,5 @@ rm -f arch/riscv/purgatory/kexec-purgatory.c rm -f scripts/extract-cert rm -f arch/x86/purgatory/kexec-purgatory.c + +rm -f scripts/kconfig/[gmnq]conf-cfg -- cgit v1.2.3 From 875ef1a57f32fcb91010dc9bc8bd1166956a579e Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 11 Dec 2022 12:10:59 +0900 Subject: kbuild: use .NOTINTERMEDIATE for future GNU Make versions In Kbuild, some files are generated by chains of pattern/implicit rules. For example, *.dtb.o files in drivers/of/unittest-data/Makefile are generated by the chain of 3 pattern rules, like this: %.dts -> %.dtb -> %.dtb.S -> %.dtb.o Here, %.dts is the real source, %.dtb.o is the final target. %.dtb and %.dtb.S are called "intermediate files". As GNU Make manual [1] says, intermediate files are treated differently in two ways: (a) The first difference is what happens if the intermediate file does not exist. If an ordinary file 'b' does not exist, and make considers a target that depends on 'b', it invariably creates 'b' and then updates the target from 'b'. But if 'b' is an intermediate file, then make can leave well enough alone: it won't create 'b' unless one of its prerequisites is out of date. This means the target depending on 'b' won't be rebuilt either, unless there is some other reason to update that target: for example the target doesn't exist or a different prerequisite is newer than the target. (b) The second difference is that if make does create 'b' in order to update something else, it deletes 'b' later on after it is no longer needed. Therefore, an intermediate file which did not exist before make also does not exist after make. make reports the deletion to you by printing a 'rm' command showing which file it is deleting. The combination of these is problematic for Kbuild because most of the build rules depend on FORCE and the if_changed* macros really determine if the target should be updated. So, all missing files, whether they are intermediate or not, are always rebuilt. To see the problem, delete ".SECONDARY:" from scripts/Kbuild.include, and repeat this command: $ make allmodconfig drivers/of/unittest-data/ The intermediate files will be deleted, which results in rebuilding intermediate and final objects in the next run of make. In the old days, people suppressed (b) in inconsistent ways. As commit 54a702f70589 ("kbuild: mark $(targets) as .SECONDARY and remove .PRECIOUS markers") noted, you should not use .PRECIOUS because .PRECIOUS has the following behavior (c), which is not likely what you want. (c) If make is killed or interrupted during the execution of their recipes, the target is not deleted. Also, the target is not deleted on error even if .DELETE_ON_ERROR is specified. .SECONDARY is a much better way to disable (b), but a small problem is that .SECONDARY enables (a), which gives a side-effect to $?; prerequisites marked as .SECONDARY do not appear in $?. This is a drawback for Kbuild. I thought it was a bug and opened a bug report. As Paul, the GNU Make maintainer, concluded in [2], this is not a bug. A good news is that, GNU Make 4.4 added the perfect solution, .NOTINTERMEDIATE, which cancels both (a) and (b). For clarificaton, my understanding of .INTERMEDIATE, .SECONDARY, .PRECIOUS and .NOTINTERMEDIATE are as follows: (a) (b) (c) .INTERMEDIATE enable enable disable .SECONDARY enable disable disable .PRECIOUS disable disable enable .NOTINTERMEDIATE disable disable disable However, GNU Make 4.4 has a bug for the global .NOTINTERMEDIATE. [3] It was fixed by commit 6164608900ad ("[SV 63417] Ensure global .NOTINTERMEDIATE disables all intermediates"), and will be available in the next release of GNU Make. The following is the gain for .NOTINTERMEDIATE: [Current Make] $ make allnoconfig vmlinux [ full build ] $ rm include/linux/device.h $ make vmlinux CALL scripts/checksyscalls.sh Make does not notice the removal of . [Future Make] $ make-latest allnoconfig vmlinux [ full build ] $ rm include/linux/device.h $ make-latest vmlinux CC arch/x86/kernel/asm-offsets.s In file included from ./include/linux/writeback.h:13, from ./include/linux/memcontrol.h:22, from ./include/linux/swap.h:9, from ./include/linux/suspend.h:5, from arch/x86/kernel/asm-offsets.c:13: ./include/linux/blk_types.h:11:10: fatal error: linux/device.h: No such file or directory 11 | #include | ^~~~~~~~~~~~~~~~ compilation terminated. make-latest[1]: *** [scripts/Makefile.build:114: arch/x86/kernel/asm-offsets.s] Error 1 make-latest: *** [Makefile:1282: prepare0] Error 2 Make notices the removal of , and rebuilds objects that depended on . There exists a source file that includes , and it raises an error. To see detailed background information, refer to commit 2d3b1b8f0da7 ("kbuild: drop $(wildcard $^) check in if_changed* for faster rebuild"). [1]: https://www.gnu.org/software/make/manual/make.html#Chained-Rules [2]: https://savannah.gnu.org/bugs/?55532 [3]: https://savannah.gnu.org/bugs/?63417 Signed-off-by: Masahiro Yamada --- scripts/Kbuild.include | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'scripts') diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include index 21e76ba0de17..2f7356b2990b 100644 --- a/scripts/Kbuild.include +++ b/scripts/Kbuild.include @@ -185,9 +185,6 @@ endif make-cmd = $(call escsq,$(subst $(pound),$$(pound),$(subst $$,$$$$,$(cmd_$(1))))) # Find any prerequisites that are newer than target or that do not exist. -# (This is not true for now; $? should contain any non-existent prerequisites, -# but it does not work as expected when .SECONDARY is present. This seems a bug -# of GNU Make.) # PHONY targets skipped in both cases. newer-prereqs = $(filter-out $(PHONY),$?) @@ -263,4 +260,14 @@ endif .DELETE_ON_ERROR: # do not delete intermediate files automatically +# +# .NOTINTERMEDIATE is more correct, but only available on newer Make versions. +# Make 4.4 introduced .NOTINTERMEDIATE, and it appears in .FEATURES, but the +# global .NOTINTERMEDIATE does not work. We can use it on Make > 4.4. +# Use .SECONDARY for older Make versions, but "newer-prereq" cannot detect +# deleted files. +ifneq ($(and $(filter notintermediate, $(.FEATURES)),$(filter-out 4.4,$(MAKE_VERSION))),) +.NOTINTERMEDIATE: +else .SECONDARY: +endif -- cgit v1.2.3 From 3d36f4298ba91fbdec6bc56aa7bb0663cba6ab0c Mon Sep 17 00:00:00 2001 From: Youling Tang Date: Sat, 10 Dec 2022 22:39:48 +0800 Subject: LoongArch: Switch to relative exception tables Similar to other architectures such as arm64, x86, riscv and so on, use offsets relative to the exception table entry values rather than their absolute addresses for both the exception location and the fixup. However, LoongArch label difference because it will actually produce two relocations, a pair of R_LARCH_ADD32 and R_LARCH_SUB32. Take simple code below for example: $ cat test_ex_table.S .section .text 1: nop .section __ex_table,"a" .balign 4 .long (1b - .) .previous $ loongarch64-unknown-linux-gnu-gcc -c test_ex_table.S $ loongarch64-unknown-linux-gnu-readelf -Wr test_ex_table.o Relocation section '.rela__ex_table' at offset 0x100 contains 2 entries: Offset Info Type Symbol's Value Symbol's Name + Addend 0000000000000000 0000000600000032 R_LARCH_ADD32 0000000000000000 .L1^B1 + 0 0000000000000000 0000000500000037 R_LARCH_SUB32 0000000000000000 L0^A + 0 The modpost will complain the R_LARCH_SUB32 relocation, so we need to patch modpost.c to skip this relocation for .rela__ex_table section. Signed-off-by: Youling Tang Signed-off-by: Huacai Chen --- arch/loongarch/include/asm/asm-extable.h | 12 ++++++------ arch/loongarch/include/asm/extable.h | 26 ++++++++++++++++++++++++++ arch/loongarch/include/asm/uaccess.h | 2 +- arch/loongarch/mm/extable.c | 32 ++++++++++++++++++++++---------- scripts/mod/modpost.c | 13 +++++++++++++ scripts/sorttable.c | 2 +- 6 files changed, 69 insertions(+), 18 deletions(-) create mode 100644 arch/loongarch/include/asm/extable.h (limited to 'scripts') diff --git a/arch/loongarch/include/asm/asm-extable.h b/arch/loongarch/include/asm/asm-extable.h index 4f615bf56727..74f8bc75472a 100644 --- a/arch/loongarch/include/asm/asm-extable.h +++ b/arch/loongarch/include/asm/asm-extable.h @@ -6,9 +6,9 @@ #define __ASM_EXTABLE_RAW(insn, fixup) \ .pushsection __ex_table, "a"; \ - .balign 8; \ - .quad (insn); \ - .quad (fixup); \ + .balign 4; \ + .long ((insn) - .); \ + .long ((fixup) - .); \ .popsection; .macro _asm_extable, insn, fixup @@ -22,9 +22,9 @@ #define __ASM_EXTABLE_RAW(insn, fixup) \ ".pushsection __ex_table, \"a\"\n" \ - ".balign 8\n" \ - ".quad ((" insn "))\n" \ - ".quad ((" fixup "))\n" \ + ".balign 4\n" \ + ".long ((" insn ") - .)\n" \ + ".long ((" fixup ") - .)\n" \ ".popsection\n" #define _ASM_EXTABLE(insn, fixup) \ diff --git a/arch/loongarch/include/asm/extable.h b/arch/loongarch/include/asm/extable.h new file mode 100644 index 000000000000..b571c89705d1 --- /dev/null +++ b/arch/loongarch/include/asm/extable.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_LOONGARCH_EXTABLE_H +#define _ASM_LOONGARCH_EXTABLE_H + +/* + * The exception table consists of pairs of relative offsets: the first + * is the relative offset to an instruction that is allowed to fault, + * and the second is the relative offset at which the program should + * continue. No registers are modified, so it is entirely up to the + * continuation code to figure out what to do. + * + * All the routines below use bits of fixup code that are out of line + * with the main instruction path. This means when everything is well, + * we don't even have to jump over them. Further, they do not intrude + * on our cache or tlb entries. + */ + +struct exception_table_entry { + int insn, fixup; +}; + +#define ARCH_HAS_RELATIVE_EXTABLE + +bool fixup_exception(struct pt_regs *regs); + +#endif diff --git a/arch/loongarch/include/asm/uaccess.h b/arch/loongarch/include/asm/uaccess.h index bf9a4e218ac0..e33282e0bdef 100644 --- a/arch/loongarch/include/asm/uaccess.h +++ b/arch/loongarch/include/asm/uaccess.h @@ -15,8 +15,8 @@ #include #include #include +#include #include -#include #include extern u64 __ua_limit; diff --git a/arch/loongarch/mm/extable.c b/arch/loongarch/mm/extable.c index bc20988f2b87..08a9a7d6357a 100644 --- a/arch/loongarch/mm/extable.c +++ b/arch/loongarch/mm/extable.c @@ -3,20 +3,32 @@ * Copyright (C) 2020-2022 Loongson Technology Corporation Limited */ #include -#include -#include #include +#include +#include + +static inline unsigned long +get_ex_fixup(const struct exception_table_entry *ex) +{ + return ((unsigned long)&ex->fixup + ex->fixup); +} -int fixup_exception(struct pt_regs *regs) +static bool ex_handler_fixup(const struct exception_table_entry *ex, + struct pt_regs *regs) { - const struct exception_table_entry *fixup; + regs->csr_era = get_ex_fixup(ex); - fixup = search_exception_tables(exception_era(regs)); - if (fixup) { - regs->csr_era = fixup->fixup; + return true; +} + + +bool fixup_exception(struct pt_regs *regs) +{ + const struct exception_table_entry *ex; - return 1; - } + ex = search_exception_tables(exception_era(regs)); + if (!ex) + return false; - return 0; + return ex_handler_fixup(ex, regs); } diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 2c80da0220c3..9321c0a05ffd 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -1523,6 +1523,14 @@ static int addend_mips_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) #define R_RISCV_SUB32 39 #endif +#ifndef EM_LOONGARCH +#define EM_LOONGARCH 258 +#endif + +#ifndef R_LARCH_SUB32 +#define R_LARCH_SUB32 55 +#endif + static void section_rela(const char *modname, struct elf_info *elf, Elf_Shdr *sechdr) { @@ -1564,6 +1572,11 @@ static void section_rela(const char *modname, struct elf_info *elf, ELF_R_TYPE(r.r_info) == R_RISCV_SUB32) continue; break; + case EM_LOONGARCH: + if (!strcmp("__ex_table", fromsec) && + ELF_R_TYPE(r.r_info) == R_LARCH_SUB32) + continue; + break; } sym = elf->symtab_start + r_sym; /* Skip special sections */ diff --git a/scripts/sorttable.c b/scripts/sorttable.c index fba40e99f354..0f2beda80478 100644 --- a/scripts/sorttable.c +++ b/scripts/sorttable.c @@ -312,12 +312,12 @@ static int do_file(char const *const fname, void *addr) case EM_PARISC: case EM_PPC: case EM_PPC64: + case EM_LOONGARCH: custom_sort = sort_relative_table; break; case EM_ARCOMPACT: case EM_ARCV2: case EM_ARM: - case EM_LOONGARCH: case EM_MICROBLAZE: case EM_MIPS: case EM_XTENSA: -- cgit v1.2.3 From 26bc82441250f2e01621f5b26606a4f6926ee3ad Mon Sep 17 00:00:00 2001 From: Youling Tang Date: Sat, 10 Dec 2022 22:39:59 +0800 Subject: LoongArch: extable: Add `type` and `data` fields This is a LoongArch port of commit d6e2cc564775 ("arm64: extable: add `type` and `data` fields"). Subsequent patches will add specialized handlers for fixups, in addition to the simple PC fixup we have today. In preparation, this patch adds a new `type` field to struct exception_table_entry, and uses this to distinguish the fixup and other cases. A `data` field is also added so that subsequent patches can associate data specific to each exception site (e.g. register numbers). Handlers are named ex_handler_*() for consistency, following the example of x86. At the same time, get_ex_fixup() is split out into a helper so that it can be used by other ex_handler_*() functions in the subsequent patches. Signed-off-by: Youling Tang Signed-off-by: Huacai Chen --- arch/loongarch/include/asm/asm-extable.h | 15 +++++++++++---- arch/loongarch/include/asm/extable.h | 11 +++++++++++ arch/loongarch/kernel/vmlinux.lds.S | 3 +-- arch/loongarch/mm/extable.c | 7 ++++++- scripts/sorttable.c | 2 +- 5 files changed, 30 insertions(+), 8 deletions(-) (limited to 'scripts') diff --git a/arch/loongarch/include/asm/asm-extable.h b/arch/loongarch/include/asm/asm-extable.h index 74f8bc75472a..634bd770e3c4 100644 --- a/arch/loongarch/include/asm/asm-extable.h +++ b/arch/loongarch/include/asm/asm-extable.h @@ -2,17 +2,22 @@ #ifndef __ASM_ASM_EXTABLE_H #define __ASM_ASM_EXTABLE_H +#define EX_TYPE_NONE 0 +#define EX_TYPE_FIXUP 1 + #ifdef __ASSEMBLY__ -#define __ASM_EXTABLE_RAW(insn, fixup) \ +#define __ASM_EXTABLE_RAW(insn, fixup, type, data) \ .pushsection __ex_table, "a"; \ .balign 4; \ .long ((insn) - .); \ .long ((fixup) - .); \ + .short (type); \ + .short (data); \ .popsection; .macro _asm_extable, insn, fixup - __ASM_EXTABLE_RAW(\insn, \fixup) + __ASM_EXTABLE_RAW(\insn, \fixup, EX_TYPE_FIXUP, 0) .endm #else /* __ASSEMBLY__ */ @@ -20,15 +25,17 @@ #include #include -#define __ASM_EXTABLE_RAW(insn, fixup) \ +#define __ASM_EXTABLE_RAW(insn, fixup, type, data) \ ".pushsection __ex_table, \"a\"\n" \ ".balign 4\n" \ ".long ((" insn ") - .)\n" \ ".long ((" fixup ") - .)\n" \ + ".short (" type ")\n" \ + ".short (" data ")\n" \ ".popsection\n" #define _ASM_EXTABLE(insn, fixup) \ - __ASM_EXTABLE_RAW(#insn, #fixup) + __ASM_EXTABLE_RAW(#insn, #fixup, __stringify(EX_TYPE_FIXUP), "0") #endif /* __ASSEMBLY__ */ diff --git a/arch/loongarch/include/asm/extable.h b/arch/loongarch/include/asm/extable.h index b571c89705d1..92612b4364a1 100644 --- a/arch/loongarch/include/asm/extable.h +++ b/arch/loongarch/include/asm/extable.h @@ -17,10 +17,21 @@ struct exception_table_entry { int insn, fixup; + short type, data; }; #define ARCH_HAS_RELATIVE_EXTABLE +#define swap_ex_entry_fixup(a, b, tmp, delta) \ +do { \ + (a)->fixup = (b)->fixup + (delta); \ + (b)->fixup = (tmp).fixup - (delta); \ + (a)->type = (b)->type; \ + (b)->type = (tmp).type; \ + (a)->data = (b)->data; \ + (b)->data = (tmp).data; \ +} while (0) + bool fixup_exception(struct pt_regs *regs); #endif diff --git a/arch/loongarch/kernel/vmlinux.lds.S b/arch/loongarch/kernel/vmlinux.lds.S index b3309a5e695b..efecda0c2361 100644 --- a/arch/loongarch/kernel/vmlinux.lds.S +++ b/arch/loongarch/kernel/vmlinux.lds.S @@ -4,6 +4,7 @@ #include #define PAGE_SIZE _PAGE_SIZE +#define RO_EXCEPTION_TABLE_ALIGN 4 /* * Put .bss..swapper_pg_dir as the first thing in .bss. This will @@ -53,8 +54,6 @@ SECTIONS . = ALIGN(PECOFF_SEGMENT_ALIGN); _etext = .; - EXCEPTION_TABLE(16) - .got : ALIGN(16) { *(.got) } .plt : ALIGN(16) { *(.plt) } .got.plt : ALIGN(16) { *(.got.plt) } diff --git a/arch/loongarch/mm/extable.c b/arch/loongarch/mm/extable.c index 08a9a7d6357a..fd2395221cff 100644 --- a/arch/loongarch/mm/extable.c +++ b/arch/loongarch/mm/extable.c @@ -30,5 +30,10 @@ bool fixup_exception(struct pt_regs *regs) if (!ex) return false; - return ex_handler_fixup(ex, regs); + switch (ex->type) { + case EX_TYPE_FIXUP: + return ex_handler_fixup(ex, regs); + } + + BUG(); } diff --git a/scripts/sorttable.c b/scripts/sorttable.c index 0f2beda80478..83cdb843d92f 100644 --- a/scripts/sorttable.c +++ b/scripts/sorttable.c @@ -304,6 +304,7 @@ static int do_file(char const *const fname, void *addr) switch (r2(&ehdr->e_machine)) { case EM_386: case EM_AARCH64: + case EM_LOONGARCH: case EM_RISCV: case EM_S390: case EM_X86_64: @@ -312,7 +313,6 @@ static int do_file(char const *const fname, void *addr) case EM_PARISC: case EM_PPC: case EM_PPC64: - case EM_LOONGARCH: custom_sort = sort_relative_table; break; case EM_ARCOMPACT: -- cgit v1.2.3 From a0a458fbd6f2317832e2d74acdbfa2451c3f4b8f Mon Sep 17 00:00:00 2001 From: Qing Zhang Date: Sat, 10 Dec 2022 22:40:15 +0800 Subject: LoongArch/ftrace: Add recordmcount support Recordmcount utility under scripts is run, after compiling each object, to find out all the locations of calling _mcount() and put them into specific seciton named __mcount_loc. Then the linker collects all such information into a table in the kernel image (between __start_mcount_loc and __stop_mcount_loc) for later use by ftrace. This patch adds LoongArch specific definitions to identify such locations. And on LoongArch, only the C version is used to build the kernel now that CONFIG_HAVE_C_RECORDMCOUNT is on. Acked-by: Steven Rostedt (Google) Signed-off-by: Qing Zhang Signed-off-by: Huacai Chen --- arch/loongarch/Kconfig | 2 ++ scripts/recordmcount.c | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) (limited to 'scripts') diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig index 72a41e08f9f4..8b81cf9a6503 100644 --- a/arch/loongarch/Kconfig +++ b/arch/loongarch/Kconfig @@ -85,11 +85,13 @@ config LOONGARCH select HAVE_ARCH_TRANSPARENT_HUGEPAGE select HAVE_ASM_MODVERSIONS select HAVE_CONTEXT_TRACKING_USER + select HAVE_C_RECORDMCOUNT select HAVE_DEBUG_STACKOVERFLOW select HAVE_DMA_CONTIGUOUS select HAVE_EBPF_JIT select HAVE_EXIT_THREAD select HAVE_FAST_GUP + select HAVE_FTRACE_MCOUNT_RECORD select HAVE_FUNCTION_GRAPH_TRACER select HAVE_FUNCTION_TRACER select HAVE_GENERIC_VDSO diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c index cce12e1971d8..e30216525325 100644 --- a/scripts/recordmcount.c +++ b/scripts/recordmcount.c @@ -38,6 +38,14 @@ #define R_AARCH64_ABS64 257 #endif +#ifndef EM_LOONGARCH +#define EM_LOONGARCH 258 +#define R_LARCH_32 1 +#define R_LARCH_64 2 +#define R_LARCH_MARK_LA 20 +#define R_LARCH_SOP_PUSH_PLT_PCREL 29 +#endif + #define R_ARM_PC24 1 #define R_ARM_THM_CALL 10 #define R_ARM_CALL 28 @@ -441,6 +449,28 @@ static int arm64_is_fake_mcount(Elf64_Rel const *rp) return ELF64_R_TYPE(w8(rp->r_info)) != R_AARCH64_CALL26; } +static int LARCH32_is_fake_mcount(Elf32_Rel const *rp) +{ + switch (ELF64_R_TYPE(w(rp->r_info))) { + case R_LARCH_MARK_LA: + case R_LARCH_SOP_PUSH_PLT_PCREL: + return 0; + } + + return 1; +} + +static int LARCH64_is_fake_mcount(Elf64_Rel const *rp) +{ + switch (ELF64_R_TYPE(w(rp->r_info))) { + case R_LARCH_MARK_LA: + case R_LARCH_SOP_PUSH_PLT_PCREL: + return 0; + } + + return 1; +} + /* 64-bit EM_MIPS has weird ELF64_Rela.r_info. * http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf * We interpret Table 29 Relocation Operation (Elf64_Rel, Elf64_Rela) [p.40] @@ -558,6 +588,7 @@ static int do_file(char const *const fname) break; case EM_IA_64: reltype = R_IA64_IMM64; break; case EM_MIPS: /* reltype: e_class */ break; + case EM_LOONGARCH: /* reltype: e_class */ break; case EM_PPC: reltype = R_PPC_ADDR32; break; case EM_PPC64: reltype = R_PPC64_ADDR64; break; case EM_S390: /* reltype: e_class */ break; @@ -589,6 +620,10 @@ static int do_file(char const *const fname) reltype = R_MIPS_32; is_fake_mcount32 = MIPS32_is_fake_mcount; } + if (w2(ehdr->e_machine) == EM_LOONGARCH) { + reltype = R_LARCH_32; + is_fake_mcount32 = LARCH32_is_fake_mcount; + } if (do32(ehdr, fname, reltype) < 0) goto out; break; @@ -610,6 +645,10 @@ static int do_file(char const *const fname) Elf64_r_info = MIPS64_r_info; is_fake_mcount64 = MIPS64_is_fake_mcount; } + if (w2(ghdr->e_machine) == EM_LOONGARCH) { + reltype = R_LARCH_64; + is_fake_mcount64 = LARCH64_is_fake_mcount; + } if (do64(ghdr, fname, reltype) < 0) goto out; break; -- cgit v1.2.3 From f65a486821cfd363833079b2a7b0769250ee21c9 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 11 Dec 2022 22:04:07 +0900 Subject: kbuild: change module.order to list *.o instead of *.ko scripts/Makefile.build replaces the suffix .o with .ko, then scripts/Makefile.modpost calls the sed command to change .ko back to the original .o suffix. Instead of converting the suffixes back-and-forth, store the .o paths in modules.order, and replace it with .ko in 'make modules_install'. This avoids the unneeded sed command. Signed-off-by: Masahiro Yamada Reviewed-by: Luis Chamberlain --- Makefile | 2 +- scripts/Makefile.build | 2 +- scripts/Makefile.modfinal | 6 +++--- scripts/Makefile.modinst | 2 +- scripts/Makefile.modpost | 7 +++++-- scripts/clang-tools/gen_compile_commands.py | 8 ++++---- scripts/gen_autoksyms.sh | 2 +- scripts/mod/modpost.c | 11 ++++------- scripts/modules-check.sh | 2 +- 9 files changed, 21 insertions(+), 21 deletions(-) (limited to 'scripts') diff --git a/Makefile b/Makefile index 591485152a95..f506879e7452 100644 --- a/Makefile +++ b/Makefile @@ -1564,7 +1564,7 @@ __modinst_pre: rm -f $(MODLIB)/build ; \ ln -s $(CURDIR) $(MODLIB)/build ; \ fi - @sed 's:^:kernel/:' modules.order > $(MODLIB)/modules.order + @sed 's:^\(.*\)\.o$$:kernel/\1.ko:' modules.order > $(MODLIB)/modules.order @cp -f modules.builtin $(MODLIB)/ @cp -f $(objtree)/modules.builtin.modinfo $(MODLIB)/ diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 799df12b53f3..267eb7aac5b2 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -435,7 +435,7 @@ $(obj)/built-in.a: $(real-obj-y) FORCE # modules.order unless contained modules are updated. cmd_modules_order = { $(foreach m, $(real-prereqs), \ - $(if $(filter %/modules.order, $m), cat $m, echo $(patsubst %.o,%.ko,$m));) :; } \ + $(if $(filter %/modules.order, $m), cat $m, echo $m);) :; } \ > $@ $(obj)/modules.order: $(obj-m) FORCE diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal index 83f2797e530c..a30d5b08eee9 100644 --- a/scripts/Makefile.modfinal +++ b/scripts/Makefile.modfinal @@ -15,7 +15,7 @@ include $(srctree)/scripts/Makefile.lib # find all modules listed in modules.order modules := $(call read-file, $(MODORDER)) -__modfinal: $(modules) +__modfinal: $(modules:%.o=%.ko) @: # modname and part-of-module are set to make c_flags define proper module flags @@ -57,13 +57,13 @@ if_changed_except = $(if $(call newer_prereqs_except,$(2))$(cmd-check), \ printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd, @:) # Re-generate module BTFs if either module's .ko or vmlinux changed -$(modules): %.ko: %.o %.mod.o scripts/module.lds $(and $(CONFIG_DEBUG_INFO_BTF_MODULES),$(KBUILD_BUILTIN),vmlinux) FORCE +%.ko: %.o %.mod.o scripts/module.lds $(and $(CONFIG_DEBUG_INFO_BTF_MODULES),$(KBUILD_BUILTIN),vmlinux) FORCE +$(call if_changed_except,ld_ko_o,vmlinux) ifdef CONFIG_DEBUG_INFO_BTF_MODULES +$(if $(newer-prereqs),$(call cmd,btf_ko)) endif -targets += $(modules) $(modules:.ko=.mod.o) +targets += $(modules:%.o=%.ko) $(modules:%.o=%.mod.o) # Add FORCE to the prequisites of a target to force it to be always rebuilt. # --------------------------------------------------------------------------- diff --git a/scripts/Makefile.modinst b/scripts/Makefile.modinst index 65aac6be78ec..836391e5d209 100644 --- a/scripts/Makefile.modinst +++ b/scripts/Makefile.modinst @@ -26,7 +26,7 @@ suffix-$(CONFIG_MODULE_COMPRESS_GZIP) := .gz suffix-$(CONFIG_MODULE_COMPRESS_XZ) := .xz suffix-$(CONFIG_MODULE_COMPRESS_ZSTD) := .zst -modules := $(patsubst $(extmod_prefix)%, $(dst)/%$(suffix-y), $(modules)) +modules := $(patsubst $(extmod_prefix)%.o, $(dst)/%.ko$(suffix-y), $(modules)) __modinst: $(modules) @: diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost index 55a72f5eb76d..f814a6acd200 100644 --- a/scripts/Makefile.modpost +++ b/scripts/Makefile.modpost @@ -107,7 +107,10 @@ ifneq ($(KBUILD_MODPOST_WARN)$(missing-input),) modpost-args += -w endif -modorder-if-needed := $(if $(KBUILD_MODULES), $(MODORDER)) +ifdef KBUILD_MODULES +modorder-if-needed := $(MODORDER) +modpost-args += -T $(MODORDER) +endif MODPOST = scripts/mod/modpost @@ -119,7 +122,7 @@ quiet_cmd_modpost = MODPOST $@ echo >&2 "WARNING: $(missing-input) is missing."; \ echo >&2 " Modules may not have dependencies or modversions."; \ echo >&2 " You may get many unresolved symbol warnings.";) \ - sed 's/ko$$/o/' $(or $(modorder-if-needed), /dev/null) | $(MODPOST) $(modpost-args) -T - $(vmlinux.o-if-present) + $(MODPOST) $(modpost-args) $(vmlinux.o-if-present) targets += $(output-symdump) $(output-symdump): $(modorder-if-needed) $(vmlinux.o-if-present) $(module.symvers-if-present) $(MODPOST) FORCE diff --git a/scripts/clang-tools/gen_compile_commands.py b/scripts/clang-tools/gen_compile_commands.py index d800b2c0af97..0227522959a4 100755 --- a/scripts/clang-tools/gen_compile_commands.py +++ b/scripts/clang-tools/gen_compile_commands.py @@ -138,10 +138,10 @@ def cmdfiles_for_modorder(modorder): """ with open(modorder) as f: for line in f: - ko = line.rstrip() - base, ext = os.path.splitext(ko) - if ext != '.ko': - sys.exit('{}: module path must end with .ko'.format(ko)) + obj = line.rstrip() + base, ext = os.path.splitext(obj) + if ext != '.o': + sys.exit('{}: module path must end with .o'.format(obj)) mod = base + '.mod' # Read from *.mod, to get a list of objects that compose the module. with open(mod) as m: diff --git a/scripts/gen_autoksyms.sh b/scripts/gen_autoksyms.sh index 653fadbad302..12bcfae940ee 100755 --- a/scripts/gen_autoksyms.sh +++ b/scripts/gen_autoksyms.sh @@ -48,7 +48,7 @@ cat > "$output_file" << EOT EOT { - [ -n "${read_modorder}" ] && sed 's/ko$/usyms/' modules.order | xargs cat + [ -n "${read_modorder}" ] && sed 's/o$/usyms/' modules.order | xargs cat echo "$needed_symbols" [ -n "$ksym_wl" ] && cat "$ksym_wl" } | sed -e 's/ /\n/g' | sed -n -e '/^$/!p' | diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 56d856f2e511..b48838a71bf6 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -1856,11 +1856,9 @@ static void read_symbols_from_files(const char *filename) FILE *in = stdin; char fname[PATH_MAX]; - if (strcmp(filename, "-") != 0) { - in = fopen(filename, "r"); - if (!in) - fatal("Can't open filenames file %s: %m", filename); - } + in = fopen(filename, "r"); + if (!in) + fatal("Can't open filenames file %s: %m", filename); while (fgets(fname, PATH_MAX, in) != NULL) { if (strends(fname, "\n")) @@ -1868,8 +1866,7 @@ static void read_symbols_from_files(const char *filename) read_symbols(fname); } - if (in != stdin) - fclose(in); + fclose(in); } #define SZ 500 diff --git a/scripts/modules-check.sh b/scripts/modules-check.sh index e06327722263..4c8da90de78e 100755 --- a/scripts/modules-check.sh +++ b/scripts/modules-check.sh @@ -16,7 +16,7 @@ check_same_name_modules() for m in $(sed 's:.*/::' "$1" | sort | uniq -d) do echo "error: the following would cause module name conflict:" >&2 - sed -n "/\/$m/s:^: :p" "$1" >&2 + sed -n "/\/$m/s:^\(.*\)\.o\$: \1.ko:p" "$1" >&2 exit_code=1 done } -- cgit v1.2.3 From 3d57e1b7b1d42d4040f0d993b66ff06beda02c54 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 11 Dec 2022 22:04:08 +0900 Subject: kbuild: refactor the prerequisites of the modpost rule The prerequisites of modpost are cluttered. The variables *-if-present and *-if-needed are unreadable. It is cleaner to append them into modpost-deps. Signed-off-by: Masahiro Yamada --- scripts/Makefile.modpost | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) (limited to 'scripts') diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost index f814a6acd200..5eb5e8280379 100644 --- a/scripts/Makefile.modpost +++ b/scripts/Makefile.modpost @@ -38,6 +38,8 @@ __modpost: include include/config/auto.conf include $(srctree)/scripts/Kbuild.include +MODPOST = scripts/mod/modpost + modpost-args = \ $(if $(CONFIG_MODVERSIONS),-m) \ $(if $(CONFIG_MODULE_SRCVERSION_ALL),-a) \ @@ -46,6 +48,8 @@ modpost-args = \ $(if $(CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS)$(KBUILD_NSDEPS),-N) \ -o $@ +modpost-deps := $(MODPOST) + # 'make -i -k' ignores compile errors, and builds as many modules as possible. ifneq ($(findstring i,$(filter-out --%,$(MAKEFLAGS))),) modpost-args += -n @@ -78,12 +82,13 @@ targets += .vmlinux.objs .vmlinux.objs: vmlinux.a $(KBUILD_VMLINUX_LIBS) FORCE $(call if_changed,vmlinux_objs) -vmlinux.o-if-present := $(wildcard vmlinux.o) -output-symdump := vmlinux.symvers - -ifdef KBUILD_MODULES -output-symdump := $(if $(vmlinux.o-if-present), Module.symvers, modules-only.symvers) -missing-input := $(filter-out $(vmlinux.o-if-present),vmlinux.o) +ifeq ($(wildcard vmlinux.o),) +missing-input := vmlinux.o +output-symdump := modules-only.symvers +else +modpost-args += vmlinux.o +modpost-deps += vmlinux.o +output-symdump := $(if $(KBUILD_MODULES), Module.symvers, vmlinux.symvers) endif else @@ -95,11 +100,16 @@ src := $(obj) # Include the module's Makefile to find KBUILD_EXTRA_SYMBOLS include $(kbuild-file) -module.symvers-if-present := $(wildcard Module.symvers) output-symdump := $(KBUILD_EXTMOD)/Module.symvers -missing-input := $(filter-out $(module.symvers-if-present), Module.symvers) -modpost-args += -e $(addprefix -i ,$(module.symvers-if-present) $(KBUILD_EXTRA_SYMBOLS)) +ifeq ($(wildcard Module.symvers),) +missing-input := Module.symvers +else +modpost-args += -i Module.symvers +modpost-deps += Module.symvers +endif + +modpost-args += -e $(addprefix -i , $(KBUILD_EXTRA_SYMBOLS)) endif # ($(KBUILD_EXTMOD),) @@ -108,12 +118,10 @@ modpost-args += -w endif ifdef KBUILD_MODULES -modorder-if-needed := $(MODORDER) modpost-args += -T $(MODORDER) +modpost-deps += $(MODORDER) endif -MODPOST = scripts/mod/modpost - # Read out modules.order to pass in modpost. # Otherwise, allmodconfig would fail with "Argument list too long". quiet_cmd_modpost = MODPOST $@ @@ -122,10 +130,10 @@ quiet_cmd_modpost = MODPOST $@ echo >&2 "WARNING: $(missing-input) is missing."; \ echo >&2 " Modules may not have dependencies or modversions."; \ echo >&2 " You may get many unresolved symbol warnings.";) \ - $(MODPOST) $(modpost-args) $(vmlinux.o-if-present) + $(MODPOST) $(modpost-args) targets += $(output-symdump) -$(output-symdump): $(modorder-if-needed) $(vmlinux.o-if-present) $(module.symvers-if-present) $(MODPOST) FORCE +$(output-symdump): $(modpost-deps) FORCE $(call if_changed,modpost) __modpost: $(output-symdump) -- cgit v1.2.3 From 19331e84c3873256537d446afec1f6c507f8c4ef Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Tue, 13 Dec 2022 11:35:29 -0700 Subject: modpost: Include '.text.*' in TEXT_SECTIONS Commit 6c730bfc894f ("modpost: handle -ffunction-sections") added ".text.*" to the OTHER_TEXT_SECTIONS macro to fix certain section mismatch warnings. Unfortunately, this makes it impossible for modpost to warn about section mismatches with LTO, which implies '-ffunction-sections', as all functions are put in their own '.text.' sections, which may still reference functions in sections they are not supposed to, such as __init. Fix this by moving ".text.*" into TEXT_SECTIONS, so that configurations with '-ffunction-sections' will see warnings about mismatched sections. Link: https://lore.kernel.org/Y39kI3MOtVI5BAnV@google.com/ Reported-by: Vincent Donnefort Reviewed-and-tested-by: Alexander Lobakin Reviewed-by: Sami Tolvanen Tested-by: Vincent Donnefort Signed-off-by: Nathan Chancellor Signed-off-by: Masahiro Yamada --- scripts/mod/modpost.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index b48838a71bf6..640e1a244ba9 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -822,10 +822,10 @@ static void check_section(const char *modname, struct elf_info *elf, #define ALL_EXIT_SECTIONS EXIT_SECTIONS, ALL_XXXEXIT_SECTIONS #define DATA_SECTIONS ".data", ".data.rel" -#define TEXT_SECTIONS ".text", ".text.unlikely", ".sched.text", \ +#define TEXT_SECTIONS ".text", ".text.*", ".sched.text", \ ".kprobes.text", ".cpuidle.text", ".noinstr.text" #define OTHER_TEXT_SECTIONS ".ref.text", ".head.text", ".spinlock.text", \ - ".fixup", ".entry.text", ".exception.text", ".text.*", \ + ".fixup", ".entry.text", ".exception.text", \ ".coldtext", ".softirqentry.text" #define INIT_SECTIONS ".init.*" -- cgit v1.2.3 From 731c4eac848ff9dd42776da8ed3407b257e3abf0 Mon Sep 17 00:00:00 2001 From: Veronika Kabatova Date: Wed, 14 Dec 2022 14:20:02 +0100 Subject: buildtar: fix tarballs with EFI_ZBOOT enabled When CONFIG_EFI_ZBOOT is enabled, the binary name is not Image.gz anymore but vmlinuz.efi. No vmlinuz gets put into the tarball as the buildtar script doesn't recognize this name. Remedy this by adding the binary name to the list of acceptable files to package. Reported-by: CKI Project Signed-off-by: Veronika Kabatova Acked-by: Ard Biesheuvel Signed-off-by: Masahiro Yamada --- scripts/package/buildtar | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/package/buildtar b/scripts/package/buildtar index cb54c7f1aa80..4d6f0b128efd 100755 --- a/scripts/package/buildtar +++ b/scripts/package/buildtar @@ -122,7 +122,7 @@ case "${ARCH}" in fi ;; arm64) - for i in Image.bz2 Image.gz Image.lz4 Image.lzma Image.lzo ; do + for i in Image.bz2 Image.gz Image.lz4 Image.lzma Image.lzo vmlinuz.efi ; do if [ -f "${objtree}/arch/arm64/boot/${i}" ] ; then cp -v -- "${objtree}/arch/arm64/boot/${i}" "${tmpdir}/boot/vmlinuz-${KERNELRELEASE}" break -- cgit v1.2.3 From da8daff9405e55baa1f797b77a7c629a89f4d764 Mon Sep 17 00:00:00 2001 From: Bhaskar Chowdhury Date: Sat, 17 Dec 2022 11:21:48 +0530 Subject: kconfig: Add static text for search information in help menu Add few static text to explain how one can bring up the search dialog box by pressing the forward slash key anywhere on this interface. Signed-off-by: Bhaskar Chowdhury Acked-by: Randy Dunlap Signed-off-by: Masahiro Yamada --- scripts/kconfig/mconf.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'scripts') diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c index 9c549683c627..e67e0db50b2e 100644 --- a/scripts/kconfig/mconf.c +++ b/scripts/kconfig/mconf.c @@ -161,6 +161,12 @@ static const char mconf_readme[] = "(especially with a larger number of unrolled categories) than the\n" "default mode.\n" "\n" + +"Search\n" +"-------\n" +"Pressing the forward-slash (/) anywhere brings up a search dialog box.\n" +"\n" + "Different color themes available\n" "--------------------------------\n" "It is possible to select different color themes using the variable\n" -- cgit v1.2.3 From 9c9b55a59416a87fc73c479d78cb3218076dbc30 Mon Sep 17 00:00:00 2001 From: Jun ASAKA Date: Tue, 27 Dec 2022 17:21:57 +0800 Subject: kbuild: add a missing line for help message The help message line for building the source RPM package was missing. Added it. Signed-off-by: Jun ASAKA Reviewed-by: Nathan Chancellor Signed-off-by: Masahiro Yamada --- scripts/Makefile.package | 1 + 1 file changed, 1 insertion(+) (limited to 'scripts') diff --git a/scripts/Makefile.package b/scripts/Makefile.package index 539e9f765d64..525a2820976f 100644 --- a/scripts/Makefile.package +++ b/scripts/Makefile.package @@ -158,6 +158,7 @@ $(perf-tar-pkgs): PHONY += help help: @echo ' rpm-pkg - Build both source and binary RPM kernel packages' + @echo ' srcrpm-pkg - Build only the source kernel RPM package' @echo ' binrpm-pkg - Build only the binary kernel RPM package' @echo ' deb-pkg - Build both source and binary deb kernel packages' @echo ' bindeb-pkg - Build only the binary kernel deb package' -- cgit v1.2.3 From 63ffe00d8c939eda1a8fa87484ca4537e13a20b7 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Tue, 27 Dec 2022 15:48:21 -0600 Subject: kbuild: Fix running modpost with musl libc commit 3d57e1b7b1d4 ("kbuild: refactor the prerequisites of the modpost rule") moved 'vmlinux.o' inside modpost-args, possibly before some of the other options. However, getopt() in musl libc follows POSIX and stops looking for options upon reaching the first non-option argument. As a result, the '-T' option is misinterpreted as a positional argument, and the build fails: make -f ./scripts/Makefile.modpost scripts/mod/modpost -E -o Module.symvers vmlinux.o -T modules.order -T: No such file or directory make[1]: *** [scripts/Makefile.modpost:137: Module.symvers] Error 1 make: *** [Makefile:1960: modpost] Error 2 The fix is to move all options before 'vmlinux.o' in modpost-args. Fixes: 3d57e1b7b1d4 ("kbuild: refactor the prerequisites of the modpost rule") Signed-off-by: Samuel Holland Reviewed-by: Nathan Chancellor Signed-off-by: Masahiro Yamada --- scripts/Makefile.modpost | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'scripts') diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost index 5eb5e8280379..0ee296cf520c 100644 --- a/scripts/Makefile.modpost +++ b/scripts/Makefile.modpost @@ -55,6 +55,17 @@ ifneq ($(findstring i,$(filter-out --%,$(MAKEFLAGS))),) modpost-args += -n endif +ifneq ($(KBUILD_MODPOST_WARN)$(missing-input),) +modpost-args += -w +endif + +# Read out modules.order to pass in modpost. +# Otherwise, allmodconfig would fail with "Argument list too long". +ifdef KBUILD_MODULES +modpost-args += -T $(MODORDER) +modpost-deps += $(MODORDER) +endif + ifeq ($(KBUILD_EXTMOD),) # Generate the list of in-tree objects in vmlinux @@ -113,17 +124,6 @@ modpost-args += -e $(addprefix -i , $(KBUILD_EXTRA_SYMBOLS)) endif # ($(KBUILD_EXTMOD),) -ifneq ($(KBUILD_MODPOST_WARN)$(missing-input),) -modpost-args += -w -endif - -ifdef KBUILD_MODULES -modpost-args += -T $(MODORDER) -modpost-deps += $(MODORDER) -endif - -# Read out modules.order to pass in modpost. -# Otherwise, allmodconfig would fail with "Argument list too long". quiet_cmd_modpost = MODPOST $@ cmd_modpost = \ $(if $(missing-input), \ -- cgit v1.2.3 From 02a893bc99757d75b7abb43b74f210dfa3df8c4b Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 29 Dec 2022 04:10:14 +0900 Subject: kbuild: rpm-pkg: add libelf-devel as alternative for BuildRequires Guoqing Jiang reports that openSUSE cannot compile the kernel rpm due to "BuildRequires: elfutils-libelf-devel" added by commit 8818039f959b ("kbuild: add ability to make source rpm buildable using koji"). The relevant package name in openSUSE is libelf-devel. Add it as an alternative package. BTW, if it is impossible to solve the build requirement, the final resort would be: $ make RPMOPTS=--nodeps rpm-pkg This passes --nodeps to the rpmbuild command so it will not verify build dependencies. This is useful to test rpm builds on non-rpm system. On Debian/Ubuntu, for example, you can install rpmbuild by 'apt-get install rpm'. NOTE1: Likewise, it is possible to bypass the build dependency check for debian package builds: $ make DPKG_FLAGS=-d deb-pkg NOTE2: The 'or' operator is supported since RPM 4.13. So, old distros such as CentOS 7 will break. I suggest installing newer rpmbuild in such cases. Link: https://lore.kernel.org/linux-kbuild/ee227d24-9c94-bfa3-166a-4ee6b5dfea09@linux.dev/T/#u Fixes: 8818039f959b ("kbuild: add ability to make source rpm buildable using koji") Reported-by: Guoqing Jiang Signed-off-by: Masahiro Yamada Reviewed-by: Nathan Chancellor Tested-by: Guoqing Jiang Acked-by: Jonathan Toppins --- scripts/package/mkspec | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/package/mkspec b/scripts/package/mkspec index dda00a948a01..adab28fa7f89 100755 --- a/scripts/package/mkspec +++ b/scripts/package/mkspec @@ -51,7 +51,8 @@ sed -e '/^DEL/d' -e 's/^\t*//' < Date: Fri, 30 Dec 2022 17:16:42 +0900 Subject: fixdep: remove unneeded inclusion This is unneeded since commit 69304379ff03 ("fixdep: use fflush() and ferror() to ensure successful write to files"). Signed-off-by: Masahiro Yamada --- scripts/basic/fixdep.c | 1 - 1 file changed, 1 deletion(-) (limited to 'scripts') diff --git a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c index 2328f9a641da..f932aeaba71a 100644 --- a/scripts/basic/fixdep.c +++ b/scripts/basic/fixdep.c @@ -94,7 +94,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3