root/drivers/media/rc/bpf-lirc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. BPF_CALL_1
  2. BPF_CALL_4
  3. BPF_CALL_3
  4. lirc_mode2_func_proto
  5. lirc_mode2_is_valid_access
  6. lirc_bpf_attach
  7. lirc_bpf_detach
  8. lirc_bpf_run
  9. lirc_bpf_free
  10. lirc_prog_attach
  11. lirc_prog_detach
  12. lirc_prog_query

   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 }

/* [<][>][^][v][top][bottom][index][help] */