162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* Converted from tools/testing/selftests/bpf/verifier/lwt.c */ 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include <linux/bpf.h> 562306a36Sopenharmony_ci#include <bpf/bpf_helpers.h> 662306a36Sopenharmony_ci#include "bpf_misc.h" 762306a36Sopenharmony_ci 862306a36Sopenharmony_ciSEC("lwt_in") 962306a36Sopenharmony_ci__description("invalid direct packet write for LWT_IN") 1062306a36Sopenharmony_ci__failure __msg("cannot write into packet") 1162306a36Sopenharmony_ci__naked void packet_write_for_lwt_in(void) 1262306a36Sopenharmony_ci{ 1362306a36Sopenharmony_ci asm volatile (" \ 1462306a36Sopenharmony_ci r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 1562306a36Sopenharmony_ci r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 1662306a36Sopenharmony_ci r0 = r2; \ 1762306a36Sopenharmony_ci r0 += 8; \ 1862306a36Sopenharmony_ci if r0 > r3 goto l0_%=; \ 1962306a36Sopenharmony_ci *(u8*)(r2 + 0) = r2; \ 2062306a36Sopenharmony_cil0_%=: r0 = 0; \ 2162306a36Sopenharmony_ci exit; \ 2262306a36Sopenharmony_ci" : 2362306a36Sopenharmony_ci : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 2462306a36Sopenharmony_ci __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 2562306a36Sopenharmony_ci : __clobber_all); 2662306a36Sopenharmony_ci} 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ciSEC("lwt_out") 2962306a36Sopenharmony_ci__description("invalid direct packet write for LWT_OUT") 3062306a36Sopenharmony_ci__failure __msg("cannot write into packet") 3162306a36Sopenharmony_ci__naked void packet_write_for_lwt_out(void) 3262306a36Sopenharmony_ci{ 3362306a36Sopenharmony_ci asm volatile (" \ 3462306a36Sopenharmony_ci r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 3562306a36Sopenharmony_ci r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 3662306a36Sopenharmony_ci r0 = r2; \ 3762306a36Sopenharmony_ci r0 += 8; \ 3862306a36Sopenharmony_ci if r0 > r3 goto l0_%=; \ 3962306a36Sopenharmony_ci *(u8*)(r2 + 0) = r2; \ 4062306a36Sopenharmony_cil0_%=: r0 = 0; \ 4162306a36Sopenharmony_ci exit; \ 4262306a36Sopenharmony_ci" : 4362306a36Sopenharmony_ci : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 4462306a36Sopenharmony_ci __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 4562306a36Sopenharmony_ci : __clobber_all); 4662306a36Sopenharmony_ci} 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ciSEC("lwt_xmit") 4962306a36Sopenharmony_ci__description("direct packet write for LWT_XMIT") 5062306a36Sopenharmony_ci__success __retval(0) 5162306a36Sopenharmony_ci__naked void packet_write_for_lwt_xmit(void) 5262306a36Sopenharmony_ci{ 5362306a36Sopenharmony_ci asm volatile (" \ 5462306a36Sopenharmony_ci r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 5562306a36Sopenharmony_ci r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 5662306a36Sopenharmony_ci r0 = r2; \ 5762306a36Sopenharmony_ci r0 += 8; \ 5862306a36Sopenharmony_ci if r0 > r3 goto l0_%=; \ 5962306a36Sopenharmony_ci *(u8*)(r2 + 0) = r2; \ 6062306a36Sopenharmony_cil0_%=: r0 = 0; \ 6162306a36Sopenharmony_ci exit; \ 6262306a36Sopenharmony_ci" : 6362306a36Sopenharmony_ci : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 6462306a36Sopenharmony_ci __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 6562306a36Sopenharmony_ci : __clobber_all); 6662306a36Sopenharmony_ci} 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ciSEC("lwt_in") 6962306a36Sopenharmony_ci__description("direct packet read for LWT_IN") 7062306a36Sopenharmony_ci__success __retval(0) 7162306a36Sopenharmony_ci__naked void packet_read_for_lwt_in(void) 7262306a36Sopenharmony_ci{ 7362306a36Sopenharmony_ci asm volatile (" \ 7462306a36Sopenharmony_ci r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 7562306a36Sopenharmony_ci r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 7662306a36Sopenharmony_ci r0 = r2; \ 7762306a36Sopenharmony_ci r0 += 8; \ 7862306a36Sopenharmony_ci if r0 > r3 goto l0_%=; \ 7962306a36Sopenharmony_ci r0 = *(u8*)(r2 + 0); \ 8062306a36Sopenharmony_cil0_%=: r0 = 0; \ 8162306a36Sopenharmony_ci exit; \ 8262306a36Sopenharmony_ci" : 8362306a36Sopenharmony_ci : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 8462306a36Sopenharmony_ci __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 8562306a36Sopenharmony_ci : __clobber_all); 8662306a36Sopenharmony_ci} 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ciSEC("lwt_out") 8962306a36Sopenharmony_ci__description("direct packet read for LWT_OUT") 9062306a36Sopenharmony_ci__success __retval(0) 9162306a36Sopenharmony_ci__naked void packet_read_for_lwt_out(void) 9262306a36Sopenharmony_ci{ 9362306a36Sopenharmony_ci asm volatile (" \ 9462306a36Sopenharmony_ci r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 9562306a36Sopenharmony_ci r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 9662306a36Sopenharmony_ci r0 = r2; \ 9762306a36Sopenharmony_ci r0 += 8; \ 9862306a36Sopenharmony_ci if r0 > r3 goto l0_%=; \ 9962306a36Sopenharmony_ci r0 = *(u8*)(r2 + 0); \ 10062306a36Sopenharmony_cil0_%=: r0 = 0; \ 10162306a36Sopenharmony_ci exit; \ 10262306a36Sopenharmony_ci" : 10362306a36Sopenharmony_ci : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 10462306a36Sopenharmony_ci __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 10562306a36Sopenharmony_ci : __clobber_all); 10662306a36Sopenharmony_ci} 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ciSEC("lwt_xmit") 10962306a36Sopenharmony_ci__description("direct packet read for LWT_XMIT") 11062306a36Sopenharmony_ci__success __retval(0) 11162306a36Sopenharmony_ci__naked void packet_read_for_lwt_xmit(void) 11262306a36Sopenharmony_ci{ 11362306a36Sopenharmony_ci asm volatile (" \ 11462306a36Sopenharmony_ci r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 11562306a36Sopenharmony_ci r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 11662306a36Sopenharmony_ci r0 = r2; \ 11762306a36Sopenharmony_ci r0 += 8; \ 11862306a36Sopenharmony_ci if r0 > r3 goto l0_%=; \ 11962306a36Sopenharmony_ci r0 = *(u8*)(r2 + 0); \ 12062306a36Sopenharmony_cil0_%=: r0 = 0; \ 12162306a36Sopenharmony_ci exit; \ 12262306a36Sopenharmony_ci" : 12362306a36Sopenharmony_ci : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 12462306a36Sopenharmony_ci __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 12562306a36Sopenharmony_ci : __clobber_all); 12662306a36Sopenharmony_ci} 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ciSEC("lwt_xmit") 12962306a36Sopenharmony_ci__description("overlapping checks for direct packet access") 13062306a36Sopenharmony_ci__success __retval(0) 13162306a36Sopenharmony_ci__naked void checks_for_direct_packet_access(void) 13262306a36Sopenharmony_ci{ 13362306a36Sopenharmony_ci asm volatile (" \ 13462306a36Sopenharmony_ci r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 13562306a36Sopenharmony_ci r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 13662306a36Sopenharmony_ci r0 = r2; \ 13762306a36Sopenharmony_ci r0 += 8; \ 13862306a36Sopenharmony_ci if r0 > r3 goto l0_%=; \ 13962306a36Sopenharmony_ci r1 = r2; \ 14062306a36Sopenharmony_ci r1 += 6; \ 14162306a36Sopenharmony_ci if r1 > r3 goto l0_%=; \ 14262306a36Sopenharmony_ci r0 = *(u16*)(r2 + 6); \ 14362306a36Sopenharmony_cil0_%=: r0 = 0; \ 14462306a36Sopenharmony_ci exit; \ 14562306a36Sopenharmony_ci" : 14662306a36Sopenharmony_ci : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 14762306a36Sopenharmony_ci __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 14862306a36Sopenharmony_ci : __clobber_all); 14962306a36Sopenharmony_ci} 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ciSEC("lwt_xmit") 15262306a36Sopenharmony_ci__description("make headroom for LWT_XMIT") 15362306a36Sopenharmony_ci__success __retval(0) 15462306a36Sopenharmony_ci__naked void make_headroom_for_lwt_xmit(void) 15562306a36Sopenharmony_ci{ 15662306a36Sopenharmony_ci asm volatile (" \ 15762306a36Sopenharmony_ci r6 = r1; \ 15862306a36Sopenharmony_ci r2 = 34; \ 15962306a36Sopenharmony_ci r3 = 0; \ 16062306a36Sopenharmony_ci call %[bpf_skb_change_head]; \ 16162306a36Sopenharmony_ci /* split for s390 to succeed */ \ 16262306a36Sopenharmony_ci r1 = r6; \ 16362306a36Sopenharmony_ci r2 = 42; \ 16462306a36Sopenharmony_ci r3 = 0; \ 16562306a36Sopenharmony_ci call %[bpf_skb_change_head]; \ 16662306a36Sopenharmony_ci r0 = 0; \ 16762306a36Sopenharmony_ci exit; \ 16862306a36Sopenharmony_ci" : 16962306a36Sopenharmony_ci : __imm(bpf_skb_change_head) 17062306a36Sopenharmony_ci : __clobber_all); 17162306a36Sopenharmony_ci} 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ciSEC("socket") 17462306a36Sopenharmony_ci__description("invalid access of tc_classid for LWT_IN") 17562306a36Sopenharmony_ci__failure __msg("invalid bpf_context access") 17662306a36Sopenharmony_ci__failure_unpriv 17762306a36Sopenharmony_ci__naked void tc_classid_for_lwt_in(void) 17862306a36Sopenharmony_ci{ 17962306a36Sopenharmony_ci asm volatile (" \ 18062306a36Sopenharmony_ci r0 = *(u32*)(r1 + %[__sk_buff_tc_classid]); \ 18162306a36Sopenharmony_ci exit; \ 18262306a36Sopenharmony_ci" : 18362306a36Sopenharmony_ci : __imm_const(__sk_buff_tc_classid, offsetof(struct __sk_buff, tc_classid)) 18462306a36Sopenharmony_ci : __clobber_all); 18562306a36Sopenharmony_ci} 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ciSEC("socket") 18862306a36Sopenharmony_ci__description("invalid access of tc_classid for LWT_OUT") 18962306a36Sopenharmony_ci__failure __msg("invalid bpf_context access") 19062306a36Sopenharmony_ci__failure_unpriv 19162306a36Sopenharmony_ci__naked void tc_classid_for_lwt_out(void) 19262306a36Sopenharmony_ci{ 19362306a36Sopenharmony_ci asm volatile (" \ 19462306a36Sopenharmony_ci r0 = *(u32*)(r1 + %[__sk_buff_tc_classid]); \ 19562306a36Sopenharmony_ci exit; \ 19662306a36Sopenharmony_ci" : 19762306a36Sopenharmony_ci : __imm_const(__sk_buff_tc_classid, offsetof(struct __sk_buff, tc_classid)) 19862306a36Sopenharmony_ci : __clobber_all); 19962306a36Sopenharmony_ci} 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ciSEC("socket") 20262306a36Sopenharmony_ci__description("invalid access of tc_classid for LWT_XMIT") 20362306a36Sopenharmony_ci__failure __msg("invalid bpf_context access") 20462306a36Sopenharmony_ci__failure_unpriv 20562306a36Sopenharmony_ci__naked void tc_classid_for_lwt_xmit(void) 20662306a36Sopenharmony_ci{ 20762306a36Sopenharmony_ci asm volatile (" \ 20862306a36Sopenharmony_ci r0 = *(u32*)(r1 + %[__sk_buff_tc_classid]); \ 20962306a36Sopenharmony_ci exit; \ 21062306a36Sopenharmony_ci" : 21162306a36Sopenharmony_ci : __imm_const(__sk_buff_tc_classid, offsetof(struct __sk_buff, tc_classid)) 21262306a36Sopenharmony_ci : __clobber_all); 21362306a36Sopenharmony_ci} 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ciSEC("lwt_in") 21662306a36Sopenharmony_ci__description("check skb->tc_classid half load not permitted for lwt prog") 21762306a36Sopenharmony_ci__failure __msg("invalid bpf_context access") 21862306a36Sopenharmony_ci__naked void not_permitted_for_lwt_prog(void) 21962306a36Sopenharmony_ci{ 22062306a36Sopenharmony_ci asm volatile ( 22162306a36Sopenharmony_ci "r0 = 0;" 22262306a36Sopenharmony_ci#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 22362306a36Sopenharmony_ci "r0 = *(u16*)(r1 + %[__sk_buff_tc_classid]);" 22462306a36Sopenharmony_ci#else 22562306a36Sopenharmony_ci "r0 = *(u16*)(r1 + %[__imm_0]);" 22662306a36Sopenharmony_ci#endif 22762306a36Sopenharmony_ci "exit;" 22862306a36Sopenharmony_ci : 22962306a36Sopenharmony_ci : __imm_const(__imm_0, offsetof(struct __sk_buff, tc_classid) + 2), 23062306a36Sopenharmony_ci __imm_const(__sk_buff_tc_classid, offsetof(struct __sk_buff, tc_classid)) 23162306a36Sopenharmony_ci : __clobber_all); 23262306a36Sopenharmony_ci} 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_cichar _license[] SEC("license") = "GPL"; 235