bpf: add new jited info fields in bpf_dev_offload and bpf_prog_info
authorJiong Wang <jiong.wang@netronome.com>
Wed, 17 Jan 2018 00:05:19 +0000 (16:05 -0800)
committerDaniel Borkmann <daniel@iogearbox.net>
Thu, 18 Jan 2018 00:26:15 +0000 (01:26 +0100)
For host JIT, there are "jited_len"/"bpf_func" fields in struct bpf_prog
used by all host JIT targets to get jited image and it's length. While for
offload, targets are likely to have different offload mechanisms that these
info are kept in device private data fields.

Therefore, BPF_OBJ_GET_INFO_BY_FD syscall needs an unified way to get JIT
length and contents info for offload targets.

One way is to introduce new callback to parse device private data then fill
those fields in bpf_prog_info. This might be a little heavy, the other way
is to add generic fields which will be initialized by all offload targets.

This patch follow the second approach to introduce two new fields in
struct bpf_dev_offload and teach bpf_prog_get_info_by_fd about them to fill
correct jited_prog_len and jited_prog_insns in bpf_prog_info.

Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: Jiong Wang <jiong.wang@netronome.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
include/linux/bpf.h
kernel/bpf/offload.c
kernel/bpf/syscall.c

index 5c2c104dc2c53451aa901f0cadf803461c582fe2..025b1c2f80532e32c5c12c53c55dfab0f07c8cb4 100644 (file)
@@ -234,6 +234,8 @@ struct bpf_prog_offload {
        struct list_head        offloads;
        bool                    dev_state;
        const struct bpf_prog_offload_ops *dev_ops;
+       void                    *jited_image;
+       u32                     jited_len;
 };
 
 struct bpf_prog_aux {
index a88cebf368bfb314e1d501b8bd58d93aadc352ff..6c0baa1cf8f8b1437e0f0fbdfa2ee7ec60e5fc53 100644 (file)
@@ -230,9 +230,12 @@ int bpf_prog_offload_info_fill(struct bpf_prog_info *info,
                .prog   = prog,
                .info   = info,
        };
+       struct bpf_prog_aux *aux = prog->aux;
        struct inode *ns_inode;
        struct path ns_path;
+       char __user *uinsns;
        void *res;
+       u32 ulen;
 
        res = ns_get_path_cb(&ns_path, bpf_prog_offload_info_fill_ns, &args);
        if (IS_ERR(res)) {
@@ -241,6 +244,26 @@ int bpf_prog_offload_info_fill(struct bpf_prog_info *info,
                return PTR_ERR(res);
        }
 
+       down_read(&bpf_devs_lock);
+
+       if (!aux->offload) {
+               up_read(&bpf_devs_lock);
+               return -ENODEV;
+       }
+
+       ulen = info->jited_prog_len;
+       info->jited_prog_len = aux->offload->jited_len;
+       if (info->jited_prog_len & ulen) {
+               uinsns = u64_to_user_ptr(info->jited_prog_insns);
+               ulen = min_t(u32, info->jited_prog_len, ulen);
+               if (copy_to_user(uinsns, aux->offload->jited_image, ulen)) {
+                       up_read(&bpf_devs_lock);
+                       return -EFAULT;
+               }
+       }
+
+       up_read(&bpf_devs_lock);
+
        ns_inode = ns_path.dentry->d_inode;
        info->netns_dev = new_encode_dev(ns_inode->i_sb->s_dev);
        info->netns_ino = ns_inode->i_ino;
index c691b9e972e304329737e9977bad0d067711b040..c28524483bf45c71c990b98d2afa42bf92a741e4 100644 (file)
@@ -1724,19 +1724,6 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
                goto done;
        }
 
-       ulen = info.jited_prog_len;
-       info.jited_prog_len = prog->jited_len;
-       if (info.jited_prog_len && ulen) {
-               if (bpf_dump_raw_ok()) {
-                       uinsns = u64_to_user_ptr(info.jited_prog_insns);
-                       ulen = min_t(u32, info.jited_prog_len, ulen);
-                       if (copy_to_user(uinsns, prog->bpf_func, ulen))
-                               return -EFAULT;
-               } else {
-                       info.jited_prog_insns = 0;
-               }
-       }
-
        ulen = info.xlated_prog_len;
        info.xlated_prog_len = bpf_prog_insn_size(prog);
        if (info.xlated_prog_len && ulen) {
@@ -1762,6 +1749,24 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
                err = bpf_prog_offload_info_fill(&info, prog);
                if (err)
                        return err;
+               goto done;
+       }
+
+       /* NOTE: the following code is supposed to be skipped for offload.
+        * bpf_prog_offload_info_fill() is the place to fill similar fields
+        * for offload.
+        */
+       ulen = info.jited_prog_len;
+       info.jited_prog_len = prog->jited_len;
+       if (info.jited_prog_len && ulen) {
+               if (bpf_dump_raw_ok()) {
+                       uinsns = u64_to_user_ptr(info.jited_prog_insns);
+                       ulen = min_t(u32, info.jited_prog_len, ulen);
+                       if (copy_to_user(uinsns, prog->bpf_func, ulen))
+                               return -EFAULT;
+               } else {
+                       info.jited_prog_insns = 0;
+               }
        }
 
 done: