extern const struct bpf_func_proto bpf_find_vma_proto;
 extern const struct bpf_func_proto bpf_loop_proto;
 extern const struct bpf_func_proto bpf_strncmp_proto;
+extern const struct bpf_func_proto bpf_copy_from_user_task_proto;
 
 const struct bpf_func_proto *tracing_prog_func_proto(
   enum bpf_func_id func_id, const struct bpf_prog *prog);
 
  *             associated to *xdp_md*, at *offset*.
  *     Return
  *             0 on success, or a negative error in case of failure.
+ *
+ * long bpf_copy_from_user_task(void *dst, u32 size, const void *user_ptr, struct task_struct *tsk, u64 flags)
+ *     Description
+ *             Read *size* bytes from user space address *user_ptr* in *tsk*'s
+ *             address space, and stores the data in *dst*. *flags* is not
+ *             used yet and is provided for future extensibility. This helper
+ *             can only be used by sleepable programs.
+ *     Return
+ *             0 on success, or a negative error in case of failure. On error
+ *             *dst* buffer is zeroed out.
  */
 #define __BPF_FUNC_MAPPER(FN)          \
        FN(unspec),                     \
        FN(xdp_get_buff_len),           \
        FN(xdp_load_bytes),             \
        FN(xdp_store_bytes),            \
+       FN(copy_from_user_task),        \
        /* */
 
 /* integer value in 'imm' field of BPF_CALL instruction selects which helper
 
 #include <linux/pid_namespace.h>
 #include <linux/proc_ns.h>
 #include <linux/security.h>
+#include <linux/btf_ids.h>
 
 #include "../../lib/kstrtox.h"
 
        .arg3_type      = ARG_ANYTHING,
 };
 
+BPF_CALL_5(bpf_copy_from_user_task, void *, dst, u32, size,
+          const void __user *, user_ptr, struct task_struct *, tsk, u64, flags)
+{
+       int ret;
+
+       /* flags is not used yet */
+       if (unlikely(flags))
+               return -EINVAL;
+
+       if (unlikely(!size))
+               return 0;
+
+       ret = access_process_vm(tsk, (unsigned long)user_ptr, dst, size, 0);
+       if (ret == size)
+               return 0;
+
+       memset(dst, 0, size);
+       /* Return -EFAULT for partial read */
+       return ret < 0 ? ret : -EFAULT;
+}
+
+const struct bpf_func_proto bpf_copy_from_user_task_proto = {
+       .func           = bpf_copy_from_user_task,
+       .gpl_only       = false,
+       .ret_type       = RET_INTEGER,
+       .arg1_type      = ARG_PTR_TO_UNINIT_MEM,
+       .arg2_type      = ARG_CONST_SIZE_OR_ZERO,
+       .arg3_type      = ARG_ANYTHING,
+       .arg4_type      = ARG_PTR_TO_BTF_ID,
+       .arg4_btf_id    = &btf_tracing_ids[BTF_TRACING_TYPE_TASK],
+       .arg5_type      = ARG_ANYTHING
+};
+
 BPF_CALL_2(bpf_per_cpu_ptr, const void *, ptr, u32, cpu)
 {
        if (cpu >= nr_cpu_ids)
 
                return &bpf_get_task_stack_proto;
        case BPF_FUNC_copy_from_user:
                return prog->aux->sleepable ? &bpf_copy_from_user_proto : NULL;
+       case BPF_FUNC_copy_from_user_task:
+               return prog->aux->sleepable ? &bpf_copy_from_user_task_proto : NULL;
        case BPF_FUNC_snprintf_btf:
                return &bpf_snprintf_btf_proto;
        case BPF_FUNC_per_cpu_ptr:
 
  *             associated to *xdp_md*, at *offset*.
  *     Return
  *             0 on success, or a negative error in case of failure.
+ *
+ * long bpf_copy_from_user_task(void *dst, u32 size, const void *user_ptr, struct task_struct *tsk, u64 flags)
+ *     Description
+ *             Read *size* bytes from user space address *user_ptr* in *tsk*'s
+ *             address space, and stores the data in *dst*. *flags* is not
+ *             used yet and is provided for future extensibility. This helper
+ *             can only be used by sleepable programs.
+ *     Return
+ *             0 on success, or a negative error in case of failure. On error
+ *             *dst* buffer is zeroed out.
  */
 #define __BPF_FUNC_MAPPER(FN)          \
        FN(unspec),                     \
        FN(xdp_get_buff_len),           \
        FN(xdp_load_bytes),             \
        FN(xdp_store_bytes),            \
+       FN(copy_from_user_task),        \
        /* */
 
 /* integer value in 'imm' field of BPF_CALL instruction selects which helper