#ifdef CONFIG_BPF_SYSCALL
 DECLARE_PER_CPU(int, bpf_prog_active);
 
+extern const struct file_operations bpf_map_fops;
+extern const struct file_operations bpf_prog_fops;
+
 #define BPF_PROG_TYPE(_id, _name) \
        extern const struct bpf_prog_ops _name ## _prog_ops; \
        extern const struct bpf_verifier_ops _name ## _verifier_ops;
 
        return -EINVAL;
 }
 
-static const struct file_operations bpf_map_fops = {
+const struct file_operations bpf_map_fops = {
 #ifdef CONFIG_PROC_FS
        .show_fdinfo    = bpf_map_show_fdinfo,
 #endif
 }
 #endif
 
-static const struct file_operations bpf_prog_fops = {
+const struct file_operations bpf_prog_fops = {
 #ifdef CONFIG_PROC_FS
        .show_fdinfo    = bpf_prog_show_fdinfo,
 #endif
 
        return inode_has_perm(cred, file_inode(file), av, &ad);
 }
 
+#ifdef CONFIG_BPF_SYSCALL
+static int bpf_fd_pass(struct file *file, u32 sid);
+#endif
+
 /* Check whether a task can use an open file descriptor to
    access an inode in a given way.  Check access to the
    descriptor itself, and then use dentry_has_perm to
                        goto out;
        }
 
+#ifdef CONFIG_BPF_SYSCALL
+       rc = bpf_fd_pass(file, cred_sid(cred));
+       if (rc)
+               return rc;
+#endif
+
        /* av is zero if only checking access to the descriptor. */
        rc = 0;
        if (av)
                        return rc;
        }
 
+#ifdef CONFIG_BPF_SYSCALL
+       rc = bpf_fd_pass(file, sid);
+       if (rc)
+               return rc;
+#endif
+
        if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
                return 0;
 
        return av;
 }
 
+/* This function will check the file pass through unix socket or binder to see
+ * if it is a bpf related object. And apply correspinding checks on the bpf
+ * object based on the type. The bpf maps and programs, not like other files and
+ * socket, are using a shared anonymous inode inside the kernel as their inode.
+ * So checking that inode cannot identify if the process have privilege to
+ * access the bpf object and that's why we have to add this additional check in
+ * selinux_file_receive and selinux_binder_transfer_files.
+ */
+static int bpf_fd_pass(struct file *file, u32 sid)
+{
+       struct bpf_security_struct *bpfsec;
+       struct bpf_prog *prog;
+       struct bpf_map *map;
+       int ret;
+
+       if (file->f_op == &bpf_map_fops) {
+               map = file->private_data;
+               bpfsec = map->security;
+               ret = avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF,
+                                  bpf_map_fmode_to_av(file->f_mode), NULL);
+               if (ret)
+                       return ret;
+       } else if (file->f_op == &bpf_prog_fops) {
+               prog = file->private_data;
+               bpfsec = prog->aux->security;
+               ret = avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF,
+                                  BPF__PROG_RUN, NULL);
+               if (ret)
+                       return ret;
+       }
+       return 0;
+}
+
 static int selinux_bpf_map(struct bpf_map *map, fmode_t fmode)
 {
        u32 sid = current_sid();