1 // SPDX-License-Identifier: GPL-2.0 2 // bpf-lirc.c - handles bpf 3 // 4 // Copyright (C) 2018 Sean Young <sean@mess.org> 5 6 #include <linux/bpf.h> 7 #include <linux/filter.h> 8 #include <linux/bpf_lirc.h> 9 #include "rc-core-priv.h" 10 11 #define lirc_rcu_dereference(p) \ 12 rcu_dereference_protected(p, lockdep_is_held(&ir_raw_handler_lock)) 13 14 /* 15 * BPF interface for raw IR 16 */ 17 const struct bpf_prog_ops lirc_mode2_prog_ops = { 18 }; 19 20 BPF_CALL_1(bpf_rc_repeat, u32*, sample) 21 { 22 struct ir_raw_event_ctrl *ctrl; 23 24 ctrl = container_of(sample, struct ir_raw_event_ctrl, bpf_sample); 25 26 rc_repeat(ctrl->dev); 27 28 return 0; 29 } 30 31 static const struct bpf_func_proto rc_repeat_proto = { 32 .func = bpf_rc_repeat, 33 .gpl_only = true, /* rc_repeat is EXPORT_SYMBOL_GPL */ 34 .ret_type = RET_INTEGER, 35 .arg1_type = ARG_PTR_TO_CTX, 36 }; 37 38 /* 39 * Currently rc-core does not support 64-bit scancodes, but there are many 40 * known protocols with more than 32 bits. So, define the interface as u64 41 * as a future-proof. 42 */ 43 BPF_CALL_4(bpf_rc_keydown, u32*, sample, u32, protocol, u64, scancode, 44 u32, toggle) 45 { 46 struct ir_raw_event_ctrl *ctrl; 47 48 ctrl = container_of(sample, struct ir_raw_event_ctrl, bpf_sample); 49 50 rc_keydown(ctrl->dev, protocol, scancode, toggle != 0); 51 52 return 0; 53 } 54 55 static const struct bpf_func_proto rc_keydown_proto = { 56 .func = bpf_rc_keydown, 57 .gpl_only = true, /* rc_keydown is EXPORT_SYMBOL_GPL */ 58 .ret_type = RET_INTEGER, 59 .arg1_type = ARG_PTR_TO_CTX, 60 .arg2_type = ARG_ANYTHING, 61 .arg3_type = ARG_ANYTHING, 62 .arg4_type = ARG_ANYTHING, 63 }; 64 65 BPF_CALL_3(bpf_rc_pointer_rel, u32*, sample, s32, rel_x, s32, rel_y) 66 { 67 struct ir_raw_event_ctrl *ctrl; 68 69 ctrl = container_of(sample, struct ir_raw_event_ctrl, bpf_sample); 70 71 input_report_rel(ctrl->dev->input_dev, REL_X, rel_x); 72 input_report_rel(ctrl->dev->input_dev, REL_Y, rel_y); 73 input_sync(ctrl->dev->input_dev); 74 75 return 0; 76 } 77 78 static const struct bpf_func_proto rc_pointer_rel_proto = { 79 .func = bpf_rc_pointer_rel, 80 .gpl_only = true, 81 .ret_type = RET_INTEGER, 82 .arg1_type = ARG_PTR_TO_CTX, 83 .arg2_type = ARG_ANYTHING, 84 .arg3_type = ARG_ANYTHING, 85 }; 86 87 static const struct bpf_func_proto * 88 lirc_mode2_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) 89 { 90 switch (func_id) { 91 case BPF_FUNC_rc_repeat: 92 return &rc_repeat_proto; 93 case BPF_FUNC_rc_keydown: 94 return &rc_keydown_proto; 95 case BPF_FUNC_rc_pointer_rel: 96 return &rc_pointer_rel_proto; 97 case BPF_FUNC_map_lookup_elem: 98 return &bpf_map_lookup_elem_proto; 99 case BPF_FUNC_map_update_elem: 100 return &bpf_map_update_elem_proto; 101 case BPF_FUNC_map_delete_elem: 102 return &bpf_map_delete_elem_proto; 103 case BPF_FUNC_map_push_elem: 104 return &bpf_map_push_elem_proto; 105 case BPF_FUNC_map_pop_elem: 106 return &bpf_map_pop_elem_proto; 107 case BPF_FUNC_map_peek_elem: 108 return &bpf_map_peek_elem_proto; 109 case BPF_FUNC_ktime_get_ns: 110 return &bpf_ktime_get_ns_proto; 111 case BPF_FUNC_tail_call: 112 return &bpf_tail_call_proto; 113 case BPF_FUNC_get_prandom_u32: 114 return &bpf_get_prandom_u32_proto; 115 case BPF_FUNC_trace_printk: 116 if (capable(CAP_SYS_ADMIN)) 117 return bpf_get_trace_printk_proto(); 118 /* fall through */ 119 default: 120 return NULL; 121 } 122 } 123 124 static bool lirc_mode2_is_valid_access(int off, int size, 125 enum bpf_access_type type, 126 const struct bpf_prog *prog, 127 struct bpf_insn_access_aux *info) 128 { 129 /* We have one field of u32 */ 130 return type == BPF_READ && off == 0 && size == sizeof(u32); 131 } 132 133 const struct bpf_verifier_ops lirc_mode2_verifier_ops = { 134 .get_func_proto = lirc_mode2_func_proto, 135 .is_valid_access = lirc_mode2_is_valid_access 136 }; 137 138 #define BPF_MAX_PROGS 64 139 140 static int lirc_bpf_attach(struct rc_dev *rcdev, struct bpf_prog *prog) 141 { 142 struct bpf_prog_array *old_array; 143 struct bpf_prog_array *new_array; 144 struct ir_raw_event_ctrl *raw; 145 int ret; 146 147 if (rcdev->driver_type != RC_DRIVER_IR_RAW) 148 return -EINVAL; 149 150 ret = mutex_lock_interruptible(&ir_raw_handler_lock); 151 if (ret) 152 return ret; 153 154 raw = rcdev->raw; 155 if (!raw) { 156 ret = -ENODEV; 157 goto unlock; 158 } 159 160 old_array = lirc_rcu_dereference(raw->progs); 161 if (old_array && bpf_prog_array_length(old_array) >= BPF_MAX_PROGS) { 162 ret = -E2BIG; 163 goto unlock; 164 } 165 166 ret = bpf_prog_array_copy(old_array, NULL, prog, &new_array); 167 if (ret < 0) 168 goto unlock; 169 170 rcu_assign_pointer(raw->progs, new_array); 171 bpf_prog_array_free(old_array); 172 173 unlock: 174 mutex_unlock(&ir_raw_handler_lock); 175 return ret; 176 } 177 178 static int lirc_bpf_detach(struct rc_dev *rcdev, struct bpf_prog *prog) 179 { 180 struct bpf_prog_array *old_array; 181 struct bpf_prog_array *new_array; 182 struct ir_raw_event_ctrl *raw; 183 int ret; 184 185 if (rcdev->driver_type != RC_DRIVER_IR_RAW) 186 return -EINVAL; 187 188 ret = mutex_lock_interruptible(&ir_raw_handler_lock); 189 if (ret) 190 return ret; 191 192 raw = rcdev->raw; 193 if (!raw) { 194 ret = -ENODEV; 195 goto unlock; 196 } 197 198 old_array = lirc_rcu_dereference(raw->progs); 199 ret = bpf_prog_array_copy(old_array, prog, NULL, &new_array); 200 /* 201 * Do not use bpf_prog_array_delete_safe() as we would end up 202 * with a dummy entry in the array, and the we would free the 203 * dummy in lirc_bpf_free() 204 */ 205 if (ret) 206 goto unlock; 207 208 rcu_assign_pointer(raw->progs, new_array); 209 bpf_prog_array_free(old_array); 210 bpf_prog_put(prog); 211 unlock: 212 mutex_unlock(&ir_raw_handler_lock); 213 return ret; 214 } 215 216 void lirc_bpf_run(struct rc_dev *rcdev, u32 sample) 217 { 218 struct ir_raw_event_ctrl *raw = rcdev->raw; 219 220 raw->bpf_sample = sample; 221 222 if (raw->progs) 223 BPF_PROG_RUN_ARRAY(raw->progs, &raw->bpf_sample, BPF_PROG_RUN); 224 } 225 226 /* 227 * This should be called once the rc thread has been stopped, so there can be 228 * no concurrent bpf execution. 229 * 230 * Should be called with the ir_raw_handler_lock held. 231 */ 232 void lirc_bpf_free(struct rc_dev *rcdev) 233 { 234 struct bpf_prog_array_item *item; 235 struct bpf_prog_array *array; 236 237 array = lirc_rcu_dereference(rcdev->raw->progs); 238 if (!array) 239 return; 240 241 for (item = array->items; item->prog; item++) 242 bpf_prog_put(item->prog); 243 244 bpf_prog_array_free(array); 245 } 246 247 int lirc_prog_attach(const union bpf_attr *attr, struct bpf_prog *prog) 248 { 249 struct rc_dev *rcdev; 250 int ret; 251 252 if (attr->attach_flags) 253 return -EINVAL; 254 255 rcdev = rc_dev_get_from_fd(attr->target_fd); 256 if (IS_ERR(rcdev)) 257 return PTR_ERR(rcdev); 258 259 ret = lirc_bpf_attach(rcdev, prog); 260 261 put_device(&rcdev->dev); 262 263 return ret; 264 } 265 266 int lirc_prog_detach(const union bpf_attr *attr) 267 { 268 struct bpf_prog *prog; 269 struct rc_dev *rcdev; 270 int ret; 271 272 if (attr->attach_flags) 273 return -EINVAL; 274 275 prog = bpf_prog_get_type(attr->attach_bpf_fd, 276 BPF_PROG_TYPE_LIRC_MODE2); 277 if (IS_ERR(prog)) 278 return PTR_ERR(prog); 279 280 rcdev = rc_dev_get_from_fd(attr->target_fd); 281 if (IS_ERR(rcdev)) { 282 bpf_prog_put(prog); 283 return PTR_ERR(rcdev); 284 } 285 286 ret = lirc_bpf_detach(rcdev, prog); 287 288 bpf_prog_put(prog); 289 put_device(&rcdev->dev); 290 291 return ret; 292 } 293 294 int lirc_prog_query(const union bpf_attr *attr, union bpf_attr __user *uattr) 295 { 296 __u32 __user *prog_ids = u64_to_user_ptr(attr->query.prog_ids); 297 struct bpf_prog_array *progs; 298 struct rc_dev *rcdev; 299 u32 cnt, flags = 0; 300 int ret; 301 302 if (attr->query.query_flags) 303 return -EINVAL; 304 305 rcdev = rc_dev_get_from_fd(attr->query.target_fd); 306 if (IS_ERR(rcdev)) 307 return PTR_ERR(rcdev); 308 309 if (rcdev->driver_type != RC_DRIVER_IR_RAW) { 310 ret = -EINVAL; 311 goto put; 312 } 313 314 ret = mutex_lock_interruptible(&ir_raw_handler_lock); 315 if (ret) 316 goto put; 317 318 progs = lirc_rcu_dereference(rcdev->raw->progs); 319 cnt = progs ? bpf_prog_array_length(progs) : 0; 320 321 if (copy_to_user(&uattr->query.prog_cnt, &cnt, sizeof(cnt))) { 322 ret = -EFAULT; 323 goto unlock; 324 } 325 326 if (copy_to_user(&uattr->query.attach_flags, &flags, sizeof(flags))) { 327 ret = -EFAULT; 328 goto unlock; 329 } 330 331 if (attr->query.prog_cnt != 0 && prog_ids && cnt) 332 ret = bpf_prog_array_copy_to_user(progs, prog_ids, cnt); 333 334 unlock: 335 mutex_unlock(&ir_raw_handler_lock); 336 put: 337 put_device(&rcdev->dev); 338 339 return ret; 340 } 341