struct bpf_call_arg_meta {
        struct bpf_map *map_ptr;
+       bool raw_mode;
+       int regno;
+       int access_size;
 };
 
 /* verbose verifier prints what it's seeing
  * and all elements of stack are initialized
  */
 static int check_stack_boundary(struct verifier_env *env, int regno,
-                               int access_size, bool zero_size_allowed)
+                               int access_size, bool zero_size_allowed,
+                               struct bpf_call_arg_meta *meta)
 {
        struct verifier_state *state = &env->cur_state;
        struct reg_state *regs = state->regs;
                return -EACCES;
        }
 
+       if (meta && meta->raw_mode) {
+               meta->access_size = access_size;
+               meta->regno = regno;
+               return 0;
+       }
+
        for (i = 0; i < access_size; i++) {
                if (state->stack_slot_type[MAX_BPF_STACK + off + i] != STACK_MISC) {
                        verbose("invalid indirect read from stack off %d+%d size %d\n",
                expected_type = CONST_PTR_TO_MAP;
        } else if (arg_type == ARG_PTR_TO_CTX) {
                expected_type = PTR_TO_CTX;
-       } else if (arg_type == ARG_PTR_TO_STACK) {
+       } else if (arg_type == ARG_PTR_TO_STACK ||
+                  arg_type == ARG_PTR_TO_RAW_STACK) {
                expected_type = PTR_TO_STACK;
                /* One exception here. In case function allows for NULL to be
                 * passed in as argument, it's a CONST_IMM type. Final test
                 */
                if (reg->type == CONST_IMM && reg->imm == 0)
                        expected_type = CONST_IMM;
+               meta->raw_mode = arg_type == ARG_PTR_TO_RAW_STACK;
        } else {
                verbose("unsupported arg_type %d\n", arg_type);
                return -EFAULT;
                        return -EACCES;
                }
                err = check_stack_boundary(env, regno, meta->map_ptr->key_size,
-                                          false);
+                                          false, NULL);
        } else if (arg_type == ARG_PTR_TO_MAP_VALUE) {
                /* bpf_map_xxx(..., map_ptr, ..., value) call:
                 * check [value, value + map->value_size) validity
                        return -EACCES;
                }
                err = check_stack_boundary(env, regno,
-                                          meta->map_ptr->value_size, false);
+                                          meta->map_ptr->value_size,
+                                          false, NULL);
        } else if (arg_type == ARG_CONST_STACK_SIZE ||
                   arg_type == ARG_CONST_STACK_SIZE_OR_ZERO) {
                bool zero_size_allowed = (arg_type == ARG_CONST_STACK_SIZE_OR_ZERO);
                        return -EACCES;
                }
                err = check_stack_boundary(env, regno - 1, reg->imm,
-                                          zero_size_allowed);
+                                          zero_size_allowed, meta);
        }
 
        return err;
        return 0;
 }
 
+static int check_raw_mode(const struct bpf_func_proto *fn)
+{
+       int count = 0;
+
+       if (fn->arg1_type == ARG_PTR_TO_RAW_STACK)
+               count++;
+       if (fn->arg2_type == ARG_PTR_TO_RAW_STACK)
+               count++;
+       if (fn->arg3_type == ARG_PTR_TO_RAW_STACK)
+               count++;
+       if (fn->arg4_type == ARG_PTR_TO_RAW_STACK)
+               count++;
+       if (fn->arg5_type == ARG_PTR_TO_RAW_STACK)
+               count++;
+
+       return count > 1 ? -EINVAL : 0;
+}
+
 static int check_call(struct verifier_env *env, int func_id)
 {
        struct verifier_state *state = &env->cur_state;
 
        memset(&meta, 0, sizeof(meta));
 
+       /* We only support one arg being in raw mode at the moment, which
+        * is sufficient for the helper functions we have right now.
+        */
+       err = check_raw_mode(fn);
+       if (err) {
+               verbose("kernel subsystem misconfigured func %d\n", func_id);
+               return err;
+       }
+
        /* check args */
        err = check_func_arg(env, BPF_REG_1, fn->arg1_type, &meta);
        if (err)
        if (err)
                return err;
 
+       /* Mark slots with STACK_MISC in case of raw mode, stack offset
+        * is inferred from register state.
+        */
+       for (i = 0; i < meta.access_size; i++) {
+               err = check_mem_access(env, meta.regno, i, BPF_B, BPF_WRITE, -1);
+               if (err)
+                       return err;
+       }
+
        /* reset caller saved regs */
        for (i = 0; i < CALLER_SAVED_REGS; i++) {
                reg = regs + caller_saved[i];