int mem_size;
        u64 msize_max_value;
        int ref_obj_id;
+       int dynptr_id;
        int map_uid;
        int func_id;
        struct btf *btf;
 
 static void __mark_dynptr_reg(struct bpf_reg_state *reg,
                              enum bpf_dynptr_type type,
-                             bool first_slot);
+                             bool first_slot, int dynptr_id);
 
 static void __mark_reg_not_init(const struct bpf_verifier_env *env,
                                struct bpf_reg_state *reg);
 
-static void mark_dynptr_stack_regs(struct bpf_reg_state *sreg1,
+static void mark_dynptr_stack_regs(struct bpf_verifier_env *env,
+                                  struct bpf_reg_state *sreg1,
                                   struct bpf_reg_state *sreg2,
                                   enum bpf_dynptr_type type)
 {
-       __mark_dynptr_reg(sreg1, type, true);
-       __mark_dynptr_reg(sreg2, type, false);
+       int id = ++env->id_gen;
+
+       __mark_dynptr_reg(sreg1, type, true, id);
+       __mark_dynptr_reg(sreg2, type, false, id);
 }
 
-static void mark_dynptr_cb_reg(struct bpf_reg_state *reg,
+static void mark_dynptr_cb_reg(struct bpf_verifier_env *env,
+                              struct bpf_reg_state *reg,
                               enum bpf_dynptr_type type)
 {
-       __mark_dynptr_reg(reg, type, true);
+       __mark_dynptr_reg(reg, type, true, ++env->id_gen);
 }
 
 static int destroy_if_dynptr_stack_slot(struct bpf_verifier_env *env,
        if (type == BPF_DYNPTR_TYPE_INVALID)
                return -EINVAL;
 
-       mark_dynptr_stack_regs(&state->stack[spi].spilled_ptr,
+       mark_dynptr_stack_regs(env, &state->stack[spi].spilled_ptr,
                               &state->stack[spi - 1].spilled_ptr, type);
 
        if (dynptr_type_refcounted(type)) {
 static int destroy_if_dynptr_stack_slot(struct bpf_verifier_env *env,
                                        struct bpf_func_state *state, int spi)
 {
-       int i;
+       struct bpf_func_state *fstate;
+       struct bpf_reg_state *dreg;
+       int i, dynptr_id;
 
        /* We always ensure that STACK_DYNPTR is never set partially,
         * hence just checking for slot_type[0] is enough. This is
                state->stack[spi - 1].slot_type[i] = STACK_INVALID;
        }
 
-       /* TODO: Invalidate any slices associated with this dynptr */
+       dynptr_id = state->stack[spi].spilled_ptr.id;
+       /* Invalidate any slices associated with this dynptr */
+       bpf_for_each_reg_in_vstate(env->cur_state, fstate, dreg, ({
+               /* Dynptr slices are only PTR_TO_MEM_OR_NULL and PTR_TO_MEM */
+               if (dreg->type != (PTR_TO_MEM | PTR_MAYBE_NULL) && dreg->type != PTR_TO_MEM)
+                       continue;
+               if (dreg->dynptr_id == dynptr_id) {
+                       if (!env->allow_ptr_leaks)
+                               __mark_reg_not_init(env, dreg);
+                       else
+                               __mark_reg_unknown(env, dreg);
+               }
+       }));
 
        /* Do not release reference state, we are destroying dynptr on stack,
         * not using some helper to release it. Just reset register.
 }
 
 static void __mark_dynptr_reg(struct bpf_reg_state *reg, enum bpf_dynptr_type type,
-                             bool first_slot)
+                             bool first_slot, int dynptr_id)
 {
        /* reg->type has no meaning for STACK_DYNPTR, but when we set reg for
         * callback arguments, it does need to be CONST_PTR_TO_DYNPTR, so simply
         */
        __mark_reg_known_zero(reg);
        reg->type = CONST_PTR_TO_DYNPTR;
+       /* Give each dynptr a unique id to uniquely associate slices to it. */
+       reg->id = dynptr_id;
        reg->dynptr.type = type;
        reg->dynptr.first_slot = first_slot;
 }
        }
 }
 
+static int dynptr_id(struct bpf_verifier_env *env, struct bpf_reg_state *reg)
+{
+       struct bpf_func_state *state = func(env, reg);
+       int spi;
+
+       if (reg->type == CONST_PTR_TO_DYNPTR)
+               return reg->id;
+       spi = dynptr_get_spi(env, reg);
+       if (spi < 0)
+               return spi;
+       return state->stack[spi].spilled_ptr.id;
+}
+
 static int dynptr_ref_obj_id(struct bpf_verifier_env *env, struct bpf_reg_state *reg)
 {
        struct bpf_func_state *state = func(env, reg);
         * callback_fn(const struct bpf_dynptr_t* dynptr, void *callback_ctx);
         */
        __mark_reg_not_init(env, &callee->regs[BPF_REG_0]);
-       mark_dynptr_cb_reg(&callee->regs[BPF_REG_1], BPF_DYNPTR_TYPE_LOCAL);
+       mark_dynptr_cb_reg(env, &callee->regs[BPF_REG_1], BPF_DYNPTR_TYPE_LOCAL);
        callee->regs[BPF_REG_2] = caller->regs[BPF_REG_3];
 
        /* unused */
                for (i = 0; i < MAX_BPF_FUNC_REG_ARGS; i++) {
                        if (arg_type_is_dynptr(fn->arg_type[i])) {
                                struct bpf_reg_state *reg = ®s[BPF_REG_1 + i];
-                               int ref_obj_id;
+                               int id, ref_obj_id;
+
+                               if (meta.dynptr_id) {
+                                       verbose(env, "verifier internal error: meta.dynptr_id already set\n");
+                                       return -EFAULT;
+                               }
 
                                if (meta.ref_obj_id) {
                                        verbose(env, "verifier internal error: meta.ref_obj_id already set\n");
                                        return -EFAULT;
                                }
 
+                               id = dynptr_id(env, reg);
+                               if (id < 0) {
+                                       verbose(env, "verifier internal error: failed to obtain dynptr id\n");
+                                       return id;
+                               }
+
                                ref_obj_id = dynptr_ref_obj_id(env, reg);
                                if (ref_obj_id < 0) {
                                        verbose(env, "verifier internal error: failed to obtain dynptr ref_obj_id\n");
                                        return ref_obj_id;
                                }
+
+                               meta.dynptr_id = id;
                                meta.ref_obj_id = ref_obj_id;
                                break;
                        }
                return -EFAULT;
        }
 
+       if (is_dynptr_ref_function(func_id))
+               regs[BPF_REG_0].dynptr_id = meta.dynptr_id;
+
        if (is_ptr_cast_function(func_id) || is_dynptr_ref_function(func_id)) {
                /* For release_reference() */
                regs[BPF_REG_0].ref_obj_id = meta.ref_obj_id;