Re: GPF from target_put_nacl()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, 2017-07-27 at 13:56 -0700, Justin Maggard wrote:
> I ran across a GPF after disabling demo-mode on an iSCSI target.  The
> backtrace pointed to target_put_nacl(), which was called from
> transport_free_session().

Can we see actual stack trace, and kernel version please..?

> A look at that function shows a pretty clear problem:
> 
>    543                  mutex_unlock(&se_tpg->acl_node_mutex);
>    544
>    545                  if (se_nacl->dynamic_stop)
>    546                          target_put_nacl(se_nacl);
>    547
>    548                  target_put_nacl(se_nacl);
>    549          }
> 
> So we make two calls to target_put_nacl() when se_nacl->dynamic_stop is true.

Correct.

> This got introduced by 01d4d6735589 (target: Fix multi-session dynamic
> se_node_acl double free OOPs).  It looks to me like we can just
> eliminate that first call, but I could easily be missing something.

The double put in transport_free_session() when se_nacl->dynamic_stop is
set is expected behavior, because when a dynamic se_node_acl is
generated it takes the initial reference in target_alloc_node_acl(), and
then a second reference in core_tpg_check_initiator_node_acl():

       /*
         * When allocating a dynamically generated node_acl, go ahead
         * and take the extra kref now before returning to the fabric
         * driver caller.
         *
         * Note this reference will be released at session shutdown
         * time within transport_free_session() code.
         */
        kref_get(&acl->acl_kref);
        acl->dynamic_node_acl = 1;

So for se_node_acl->dynamic_node_acl = 0 in transport_free_session(),
it's just dropping the se_node_acl->nacl_kref obtained by
core_tpg_get_initiator_node_acl().  Eg, it's not dropping the last
reference..

But during the se_node_acl->dynamic_node_acl = 1 free special case,
transport_free_session() is responsible for both target_put_nacl() calls
to actually free se_node_acl.

That is, normally for non dynamic ACLs, it's the configfs callback for
se_node_acl->acl_group rmdir into core_tpg_del_initiator_node_acl() that
drops the reference:

        target_put_nacl(acl);
        /*
         * Wait for last target_put_nacl() to complete in target_complete_nacl()
         * for active fabric session transport_deregister_session() callbacks.
         */
        wait_for_completion(&acl->acl_free_comp);

But since se_node_acl->dynamic_node_acl = 1 doesn't have a corresponding
configfs entry for user-space to remove, it's left up to
transport_free_session() to set se_node_acl->dynamic_stop and drop both
references to free se_node_acl.

--
To unsubscribe from this list: send the line "unsubscribe target-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux SCSI]     [Kernel Newbies]     [Linux SCSI Target Infrastructure]     [Share Photos]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Device Mapper]

  Powered by Linux