/* check read/write into map element returned by bpf_map_lookup_elem() */
 static int __check_map_access(struct bpf_verifier_env *env, u32 regno, int off,
-                           int size)
+                             int size, bool zero_size_allowed)
 {
        struct bpf_reg_state *regs = cur_regs(env);
        struct bpf_map *map = regs[regno].map_ptr;
 
-       if (off < 0 || size <= 0 || off + size > map->value_size) {
+       if (off < 0 || size < 0 || (size == 0 && !zero_size_allowed) ||
+           off + size > map->value_size) {
                verbose(env, "invalid access to map value, value_size=%d off=%d size=%d\n",
                        map->value_size, off, size);
                return -EACCES;
 
 /* check read/write into a map element with possible variable offset */
 static int check_map_access(struct bpf_verifier_env *env, u32 regno,
-                           int off, int size)
+                           int off, int size, bool zero_size_allowed)
 {
        struct bpf_verifier_state *state = env->cur_state;
        struct bpf_reg_state *reg = &state->regs[regno];
                        regno);
                return -EACCES;
        }
-       err = __check_map_access(env, regno, reg->smin_value + off, size);
+       err = __check_map_access(env, regno, reg->smin_value + off, size,
+                                zero_size_allowed);
        if (err) {
                verbose(env, "R%d min value is outside of the array range\n",
                        regno);
                        regno);
                return -EACCES;
        }
-       err = __check_map_access(env, regno, reg->umax_value + off, size);
+       err = __check_map_access(env, regno, reg->umax_value + off, size,
+                                zero_size_allowed);
        if (err)
                verbose(env, "R%d max value is outside of the array range\n",
                        regno);
 }
 
 static int __check_packet_access(struct bpf_verifier_env *env, u32 regno,
-                                int off, int size)
+                                int off, int size, bool zero_size_allowed)
 {
        struct bpf_reg_state *regs = cur_regs(env);
        struct bpf_reg_state *reg = ®s[regno];
 
-       if (off < 0 || size <= 0 || (u64)off + size > reg->range) {
+       if (off < 0 || size < 0 || (size == 0 && !zero_size_allowed) ||
+           (u64)off + size > reg->range) {
                verbose(env, "invalid access to packet, off=%d size=%d, R%d(id=%d,off=%d,r=%d)\n",
                        off, size, regno, reg->id, reg->off, reg->range);
                return -EACCES;
 }
 
 static int check_packet_access(struct bpf_verifier_env *env, u32 regno, int off,
-                              int size)
+                              int size, bool zero_size_allowed)
 {
        struct bpf_reg_state *regs = cur_regs(env);
        struct bpf_reg_state *reg = ®s[regno];
                        regno);
                return -EACCES;
        }
-       err = __check_packet_access(env, regno, off, size);
+       err = __check_packet_access(env, regno, off, size, zero_size_allowed);
        if (err) {
                verbose(env, "R%d offset is outside of the packet\n", regno);
                return err;
                        return -EACCES;
                }
 
-               err = check_map_access(env, regno, off, size);
+               err = check_map_access(env, regno, off, size, false);
                if (!err && t == BPF_READ && value_regno >= 0)
                        mark_reg_unknown(env, regs, value_regno);
 
                                value_regno);
                        return -EACCES;
                }
-               err = check_packet_access(env, regno, off, size);
+               err = check_packet_access(env, regno, off, size, false);
                if (!err && t == BPF_READ && value_regno >= 0)
                        mark_reg_unknown(env, regs, value_regno);
        } else {
        }
        off = regs[regno].off + regs[regno].var_off.value;
        if (off >= 0 || off < -MAX_BPF_STACK || off + access_size > 0 ||
-           access_size <= 0) {
+           access_size < 0 || (access_size == 0 && !zero_size_allowed)) {
                verbose(env, "invalid stack type R%d off=%d access_size=%d\n",
                        regno, off, access_size);
                return -EACCES;
        switch (reg->type) {
        case PTR_TO_PACKET:
        case PTR_TO_PACKET_META:
-               return check_packet_access(env, regno, reg->off, access_size);
+               return check_packet_access(env, regno, reg->off, access_size,
+                                          zero_size_allowed);
        case PTR_TO_MAP_VALUE:
-               return check_map_access(env, regno, reg->off, access_size);
+               return check_map_access(env, regno, reg->off, access_size,
+                                       zero_size_allowed);
        default: /* scalar_value|ptr_to_stack or invalid ptr */
                return check_stack_boundary(env, regno, access_size,
                                            zero_size_allowed, meta);
                }
                if (type_is_pkt_pointer(type))
                        err = check_packet_access(env, regno, reg->off,
-                                                 meta->map_ptr->key_size);
+                                                 meta->map_ptr->key_size,
+                                                 false);
                else
                        err = check_stack_boundary(env, regno,
                                                   meta->map_ptr->key_size,
                }
                if (type_is_pkt_pointer(type))
                        err = check_packet_access(env, regno, reg->off,
-                                                 meta->map_ptr->value_size);
+                                                 meta->map_ptr->value_size,
+                                                 false);
                else
                        err = check_stack_boundary(env, regno,
                                                   meta->map_ptr->value_size,