1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2021 Facebook */ 3 #include <vmlinux.h> 4 #include <bpf/bpf_helpers.h> 5 6 extern struct prog_test_ref_kfunc *bpf_kfunc_call_test_acquire(unsigned long *sp) __ksym; 7 extern void bpf_kfunc_call_test_release(struct prog_test_ref_kfunc *p) __ksym; 8 extern void bpf_kfunc_call_test_mem_len_pass1(void *mem, int len) __ksym; 9 extern int *bpf_kfunc_call_test_get_rdwr_mem(struct prog_test_ref_kfunc *p, const int rdwr_buf_size) __ksym; 10 extern int *bpf_kfunc_call_test_get_rdonly_mem(struct prog_test_ref_kfunc *p, const int rdonly_buf_size) __ksym; 11 extern int *bpf_kfunc_call_test_acq_rdonly_mem(struct prog_test_ref_kfunc *p, const int rdonly_buf_size) __ksym; 12 extern void bpf_kfunc_call_int_mem_release(int *p) __ksym; 13 14 struct syscall_test_args { 15 __u8 data[16]; 16 size_t size; 17 }; 18 19 SEC("?syscall") 20 int kfunc_syscall_test_fail(struct syscall_test_args *args) 21 { 22 bpf_kfunc_call_test_mem_len_pass1(&args->data, sizeof(*args) + 1); 23 24 return 0; 25 } 26 27 SEC("?syscall") 28 int kfunc_syscall_test_null_fail(struct syscall_test_args *args) 29 { 30 /* Must be called with args as a NULL pointer 31 * we do not check for it to have the verifier consider that 32 * the pointer might not be null, and so we can load it. 33 * 34 * So the following can not be added: 35 * 36 * if (args) 37 * return -22; 38 */ 39 40 bpf_kfunc_call_test_mem_len_pass1(args, sizeof(*args)); 41 42 return 0; 43 } 44 45 SEC("?tc") 46 int kfunc_call_test_get_mem_fail_rdonly(struct __sk_buff *skb) 47 { 48 struct prog_test_ref_kfunc *pt; 49 unsigned long s = 0; 50 int *p = NULL; 51 int ret = 0; 52 53 pt = bpf_kfunc_call_test_acquire(&s); 54 if (pt) { 55 p = bpf_kfunc_call_test_get_rdonly_mem(pt, 2 * sizeof(int)); 56 if (p) 57 p[0] = 42; /* this is a read-only buffer, so -EACCES */ 58 else 59 ret = -1; 60 61 bpf_kfunc_call_test_release(pt); 62 } 63 return ret; 64 } 65 66 SEC("?tc") 67 int kfunc_call_test_get_mem_fail_use_after_free(struct __sk_buff *skb) 68 { 69 struct prog_test_ref_kfunc *pt; 70 unsigned long s = 0; 71 int *p = NULL; 72 int ret = 0; 73 74 pt = bpf_kfunc_call_test_acquire(&s); 75 if (pt) { 76 p = bpf_kfunc_call_test_get_rdwr_mem(pt, 2 * sizeof(int)); 77 if (p) { 78 p[0] = 42; 79 ret = p[1]; /* 108 */ 80 } else { 81 ret = -1; 82 } 83 84 bpf_kfunc_call_test_release(pt); 85 } 86 if (p) 87 ret = p[0]; /* p is not valid anymore */ 88 89 return ret; 90 } 91 92 SEC("?tc") 93 int kfunc_call_test_get_mem_fail_oob(struct __sk_buff *skb) 94 { 95 struct prog_test_ref_kfunc *pt; 96 unsigned long s = 0; 97 int *p = NULL; 98 int ret = 0; 99 100 pt = bpf_kfunc_call_test_acquire(&s); 101 if (pt) { 102 p = bpf_kfunc_call_test_get_rdonly_mem(pt, 2 * sizeof(int)); 103 if (p) 104 ret = p[2 * sizeof(int)]; /* oob access, so -EACCES */ 105 else 106 ret = -1; 107 108 bpf_kfunc_call_test_release(pt); 109 } 110 return ret; 111 } 112 113 int not_const_size = 2 * sizeof(int); 114 115 SEC("?tc") 116 int kfunc_call_test_get_mem_fail_not_const(struct __sk_buff *skb) 117 { 118 struct prog_test_ref_kfunc *pt; 119 unsigned long s = 0; 120 int *p = NULL; 121 int ret = 0; 122 123 pt = bpf_kfunc_call_test_acquire(&s); 124 if (pt) { 125 p = bpf_kfunc_call_test_get_rdonly_mem(pt, not_const_size); /* non const size, -EINVAL */ 126 if (p) 127 ret = p[0]; 128 else 129 ret = -1; 130 131 bpf_kfunc_call_test_release(pt); 132 } 133 return ret; 134 } 135 136 SEC("?tc") 137 int kfunc_call_test_mem_acquire_fail(struct __sk_buff *skb) 138 { 139 struct prog_test_ref_kfunc *pt; 140 unsigned long s = 0; 141 int *p = NULL; 142 int ret = 0; 143 144 pt = bpf_kfunc_call_test_acquire(&s); 145 if (pt) { 146 /* we are failing on this one, because we are not acquiring a PTR_TO_BTF_ID (a struct ptr) */ 147 p = bpf_kfunc_call_test_acq_rdonly_mem(pt, 2 * sizeof(int)); 148 if (p) 149 ret = p[0]; 150 else 151 ret = -1; 152 153 bpf_kfunc_call_int_mem_release(p); 154 155 bpf_kfunc_call_test_release(pt); 156 } 157 return ret; 158 } 159 160 char _license[] SEC("license") = "GPL"; 161