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