This bug is due to a double-free in source3/librpc/crypto/gse.c where
gse_ctx->k5ctx is freed twice if gse_context_init fails and the err_out
path is taken.

The beginning of gse_context_init calls talloc_set_destructor to call
gse_context_destructor:

        talloc_set_destructor((TALLOC_CTX *)gse_ctx,
gse_context_destructor);

This gse_context_destructor callback function is triggered by calls to
TALLOC_FREE(gse_ctx) and frees pointers stored in the gse_ctx structure
including gse_ctx->k5ctx:

        if (gse_ctx->k5ctx) {
                if (gse_ctx->ccache) {
                        krb5_cc_close(gse_ctx->k5ctx, gse_ctx->ccache);
                        gse_ctx->ccache = NULL;
                }
                if (gse_ctx->keytab) {
                        krb5_kt_close(gse_ctx->k5ctx, gse_ctx->keytab);
                        gse_ctx->keytab = NULL;
                }
                krb5_free_context(gse_ctx->k5ctx);
                gse_ctx->k5ctx = NULL;
        }

However, if gse_context_init fails and takes the err_out path,
gse_ctx->k5ctx is freed without setting that pointer to NULL and then
immediately calls TALLOC_FREE(gse_ctx) which then attempts to free
gse_ctx->k5ctx a second time:

err_out:
        if (gse_ctx->k5ctx) {
                krb5_free_context(gse_ctx->k5ctx);
        }

        TALLOC_FREE(gse_ctx);

This results in the following double-free stack trace:

(gdb) bt
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1  0x00007ffff7443859 in __GI_abort () at abort.c:79
#2  0x00007ffff74ae3ee in __libc_message (action=action@entry=do_abort, 
fmt=fmt@entry=0x7ffff75d8285 "%s\n") at ../sysdeps/posix/libc_fatal.c:155
#3  0x00007ffff74b647c in malloc_printerr (str=str@entry=0x7ffff75da5d0 
"free(): double free detected in tcache 2") at malloc.c:5347
#4  0x00007ffff74b80ed in _int_free (av=0x7ffff7609b80 <main_arena>, 
p=0x5555555ce2c0, have_lock=0) at malloc.c:4201
#5  0x00007ffff6cc29f9 in krb5_free_context (context=0x5555555cdcd0) at 
../../source4/heimdal/lib/krb5/context.c:595
#6  0x00007ffff73e75d1 in gse_context_destructor (ptr=ptr@entry=0x5555555cdc50) 
at ../../source3/librpc/crypto/gse.c:84
#7  0x00007ffff776553e in _tc_free_internal (tc=0x5555555cdbf0, 
location=0x7ffff73f2480 "../../source3/librpc/crypto/gse.c:241") at 
../../talloc.c:1157
#8  0x00007ffff73e826c in gse_context_init 
(mem_ctx=mem_ctx@entry=0x5555555cdb60, do_sign=<optimized out>, 
do_seal=<optimized out>, add_gss_c_flags=<optimized out>, 
_gse_ctx=_gse_ctx@entry=0x7fffffffd500,
    ccache_name=<optimized out>) at ../../source3/librpc/crypto/gse.c:241
#9  0x00007ffff73e8433 in gse_init_client (ccache_name=0x0, realm=<optimized 
out>, username=<optimized out>, password=<optimized out>, _gse_ctx=<synthetic 
pointer>, add_gss_c_flags=<optimized out>,
    service=0x5555555ccdf0 "cifs", server=0x5555555ccfb0 "freenas", 
do_seal=<optimized out>, do_sign=<optimized out>, mem_ctx=0x5555555cdb60) at 
../../source3/librpc/crypto/gse.c:268
#10 gensec_gse_client_start (gensec_security=0x5555555cdb60) at 
../../source3/librpc/crypto/gse.c:786
#11 0x00007ffff7390453 in gensec_start_mech (gensec_security=0x5555555cdb60) at 
../../auth/gensec/gensec_start.c:743
#12 gensec_start_mech (gensec_security=0x5555555cdb60) at 
../../auth/gensec/gensec_start.c:704
#13 0x00007ffff7387822 in gensec_spnego_client_negTokenInit_step 
(gensec_security=0x5555555c9b70, spnego_state=0x5555555cc1b0, n=0x5555555cd4a0, 
spnego_in=<optimized out>, last_status=...,
    in_mem_ctx=<optimized out>, in_next=0x5555555cd3f8) at 
../../auth/gensec/spnego.c:633
#14 0x00007ffff7387e02 in gensec_spnego_client_negTokenInit_start 
(gensec_security=0x5555555c9b70, spnego_state=0x5555555cc1b0, n=0x5555555cd4a0, 
spnego_in=0x5555555cd368, in_mem_ctx=0x5555555cd340,
    in_next=0x5555555cd3f8) at ../../auth/gensec/spnego.c:537
#15 0x00007ffff7388b84 in gensec_spnego_update_pre (req=0x5555555cd190) at 
../../auth/gensec/spnego.c:1943
#16 gensec_spnego_update_send (mem_ctx=<optimized out>, ev=0x5555555aee90, 
gensec_security=<optimized out>, in=...) at ../../auth/gensec/spnego.c:1741
#17 0x00007ffff738f3b0 in gensec_update_send (mem_ctx=<optimized out>, 
ev=0x5555555aee90, gensec_security=0x5555555c9b70, in=...) at 
../../auth/gensec/gensec.c:449
#18 0x00007ffff7f6dba6 in cli_session_setup_gensec_local_next 
(req=0x5555555c9d90) at ../../source3/libsmb/cliconnect.c:997
#19 0x00007ffff7f6f520 in cli_session_setup_gensec_send 
(target_service=0x7ffff7fa478e "cifs", target_hostname=0x5555555ca480 
"freenas", creds=0x5555555adf90, cli=0x5555555adf90, ev=0x5555555aee90,
    mem_ctx=<optimized out>) at ../../source3/libsmb/cliconnect.c:977
#20 cli_session_setup_spnego_send (creds=0x5555555adf90, cli=0x5555555adf90, 
ev=0x5555555aee90, mem_ctx=<optimized out>) at 
../../source3/libsmb/cliconnect.c:1346
#21 cli_session_setup_creds_send (mem_ctx=mem_ctx@entry=0x5555555aee90, 
ev=ev@entry=0x5555555aee90, cli=cli@entry=0x5555555adf90, 
creds=creds@entry=0x5555555b4380) at ../../source3/libsmb/cliconnect.c:1505
#22 0x00007ffff7f6fcad in cli_session_setup_creds (cli=0x5555555adf90, 
creds=creds@entry=0x5555555b4380) at ../../source3/libsmb/cliconnect.c:1843
#23 0x00007ffff7f8ca57 in do_connect (ctx=ctx@entry=0x5555555aae90, 
server=<optimized out>, server@entry=0x5555555b4790 "freenas", 
share=share@entry=0x555555571183 "IPC$", auth_info=0x5555555b42f0,
    force_encrypt=<optimized out>, max_protocol=max_protocol@entry=13, port=0, 
name_type=32, pcli=0x7fffffffd8a0) at ../../source3/libsmb/clidfs.c:236
#24 0x00007ffff7f8cfa8 in cli_cm_connect (ctx=ctx@entry=0x5555555aae90, 
referring_cli=referring_cli@entry=0x0, server=server@entry=0x5555555b4790 
"freenas", share=share@entry=0x555555571183 "IPC$",
    auth_info=<optimized out>, force_encrypt=force_encrypt@entry=false, 
max_protocol=13, port=0, name_type=32, pcli=0x7fffffffd900) at 
../../source3/libsmb/clidfs.c:339
#25 0x00007ffff7f8d13f in cli_cm_open (ctx=0x5555555aae90, referring_cli=0x0, 
server=0x5555555b4790 "freenas", share=0x555555571183 "IPC$", 
auth_info=<optimized out>, force_encrypt=<optimized out>,
    max_protocol=13, port=0, name_type=32, pcli=0x55555557c398 <cli>) at 
../../source3/libsmb/clidfs.c:441
#26 0x000055555555edc0 in do_host_query (query_host=0x5555555b4790 "freenas") 
at ../../source3/client/client.c:6702
#27 main (argc=<optimized out>, argv=<optimized out>) at 
../../source3/client/client.c:6702
(gdb)

When explicitly setting gse_ctx->k5ctx to NULL after the free, this
crash no longer occurs and I can now access SMB shares successfully:

err_out:
        if (gse_ctx->k5ctx) {
                krb5_free_context(gse_ctx->k5ctx);
                gse_ctx->k5ctx = NULL;
        }

        TALLOC_FREE(gse_ctx);

This bug appears to have been fixed upstream by removing the explicit
krb5_free_context call here and depending on gse_context_destructor to
free the k5ctx member pointer:

err_out:
        TALLOC_FREE(gse_ctx);

-- 
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/1892145

Title:
  smbclient cannot connect anonymously in Kerberos context (freeipa)

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/samba/+bug/1892145/+subscriptions

-- 
ubuntu-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs

Reply via email to