235 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Converted from tools/testing/selftests/bpf/verifier/lwt.c */3 4#include <linux/bpf.h>5#include <bpf/bpf_helpers.h>6#include "bpf_misc.h"7 8SEC("lwt_in")9__description("invalid direct packet write for LWT_IN")10__failure __msg("cannot write into packet")11__naked void packet_write_for_lwt_in(void)12{13 asm volatile (" \14 r2 = *(u32*)(r1 + %[__sk_buff_data]); \15 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \16 r0 = r2; \17 r0 += 8; \18 if r0 > r3 goto l0_%=; \19 *(u8*)(r2 + 0) = r2; \20l0_%=: r0 = 0; \21 exit; \22" :23 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),24 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))25 : __clobber_all);26}27 28SEC("lwt_out")29__description("invalid direct packet write for LWT_OUT")30__failure __msg("cannot write into packet")31__naked void packet_write_for_lwt_out(void)32{33 asm volatile (" \34 r2 = *(u32*)(r1 + %[__sk_buff_data]); \35 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \36 r0 = r2; \37 r0 += 8; \38 if r0 > r3 goto l0_%=; \39 *(u8*)(r2 + 0) = r2; \40l0_%=: r0 = 0; \41 exit; \42" :43 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),44 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))45 : __clobber_all);46}47 48SEC("lwt_xmit")49__description("direct packet write for LWT_XMIT")50__success __retval(0)51__naked void packet_write_for_lwt_xmit(void)52{53 asm volatile (" \54 r2 = *(u32*)(r1 + %[__sk_buff_data]); \55 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \56 r0 = r2; \57 r0 += 8; \58 if r0 > r3 goto l0_%=; \59 *(u8*)(r2 + 0) = r2; \60l0_%=: r0 = 0; \61 exit; \62" :63 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),64 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))65 : __clobber_all);66}67 68SEC("lwt_in")69__description("direct packet read for LWT_IN")70__success __retval(0)71__naked void packet_read_for_lwt_in(void)72{73 asm volatile (" \74 r2 = *(u32*)(r1 + %[__sk_buff_data]); \75 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \76 r0 = r2; \77 r0 += 8; \78 if r0 > r3 goto l0_%=; \79 r0 = *(u8*)(r2 + 0); \80l0_%=: r0 = 0; \81 exit; \82" :83 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),84 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))85 : __clobber_all);86}87 88SEC("lwt_out")89__description("direct packet read for LWT_OUT")90__success __retval(0)91__naked void packet_read_for_lwt_out(void)92{93 asm volatile (" \94 r2 = *(u32*)(r1 + %[__sk_buff_data]); \95 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \96 r0 = r2; \97 r0 += 8; \98 if r0 > r3 goto l0_%=; \99 r0 = *(u8*)(r2 + 0); \100l0_%=: r0 = 0; \101 exit; \102" :103 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),104 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))105 : __clobber_all);106}107 108SEC("lwt_xmit")109__description("direct packet read for LWT_XMIT")110__success __retval(0)111__naked void packet_read_for_lwt_xmit(void)112{113 asm volatile (" \114 r2 = *(u32*)(r1 + %[__sk_buff_data]); \115 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \116 r0 = r2; \117 r0 += 8; \118 if r0 > r3 goto l0_%=; \119 r0 = *(u8*)(r2 + 0); \120l0_%=: r0 = 0; \121 exit; \122" :123 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),124 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))125 : __clobber_all);126}127 128SEC("lwt_xmit")129__description("overlapping checks for direct packet access")130__success __retval(0)131__naked void checks_for_direct_packet_access(void)132{133 asm volatile (" \134 r2 = *(u32*)(r1 + %[__sk_buff_data]); \135 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \136 r0 = r2; \137 r0 += 8; \138 if r0 > r3 goto l0_%=; \139 r1 = r2; \140 r1 += 6; \141 if r1 > r3 goto l0_%=; \142 r0 = *(u16*)(r2 + 6); \143l0_%=: r0 = 0; \144 exit; \145" :146 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),147 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))148 : __clobber_all);149}150 151SEC("lwt_xmit")152__description("make headroom for LWT_XMIT")153__success __retval(0)154__naked void make_headroom_for_lwt_xmit(void)155{156 asm volatile (" \157 r6 = r1; \158 r2 = 34; \159 r3 = 0; \160 call %[bpf_skb_change_head]; \161 /* split for s390 to succeed */ \162 r1 = r6; \163 r2 = 42; \164 r3 = 0; \165 call %[bpf_skb_change_head]; \166 r0 = 0; \167 exit; \168" :169 : __imm(bpf_skb_change_head)170 : __clobber_all);171}172 173SEC("socket")174__description("invalid access of tc_classid for LWT_IN")175__failure __msg("invalid bpf_context access")176__failure_unpriv177__naked void tc_classid_for_lwt_in(void)178{179 asm volatile (" \180 r0 = *(u32*)(r1 + %[__sk_buff_tc_classid]); \181 exit; \182" :183 : __imm_const(__sk_buff_tc_classid, offsetof(struct __sk_buff, tc_classid))184 : __clobber_all);185}186 187SEC("socket")188__description("invalid access of tc_classid for LWT_OUT")189__failure __msg("invalid bpf_context access")190__failure_unpriv191__naked void tc_classid_for_lwt_out(void)192{193 asm volatile (" \194 r0 = *(u32*)(r1 + %[__sk_buff_tc_classid]); \195 exit; \196" :197 : __imm_const(__sk_buff_tc_classid, offsetof(struct __sk_buff, tc_classid))198 : __clobber_all);199}200 201SEC("socket")202__description("invalid access of tc_classid for LWT_XMIT")203__failure __msg("invalid bpf_context access")204__failure_unpriv205__naked void tc_classid_for_lwt_xmit(void)206{207 asm volatile (" \208 r0 = *(u32*)(r1 + %[__sk_buff_tc_classid]); \209 exit; \210" :211 : __imm_const(__sk_buff_tc_classid, offsetof(struct __sk_buff, tc_classid))212 : __clobber_all);213}214 215SEC("lwt_in")216__description("check skb->tc_classid half load not permitted for lwt prog")217__failure __msg("invalid bpf_context access")218__naked void not_permitted_for_lwt_prog(void)219{220 asm volatile (221 "r0 = 0;"222#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__223 "r0 = *(u16*)(r1 + %[__sk_buff_tc_classid]);"224#else225 "r0 = *(u16*)(r1 + %[__imm_0]);"226#endif227 "exit;"228 :229 : __imm_const(__imm_0, offsetof(struct __sk_buff, tc_classid) + 2),230 __imm_const(__sk_buff_tc_classid, offsetof(struct __sk_buff, tc_classid))231 : __clobber_all);232}233 234char _license[] SEC("license") = "GPL";235