Skip Menu |
 

To: krb5-bugs@mit.edu
Date: Tue, 3 Mar 2020 11:04:34 +0100
From: andi@notmuch.email
Subject: Segfault in k5_primary_domain
Download (untitled) / with headers
text/plain 4.4KiB
On NixOS we started to see segfaults when executing `gsasl` tests in our build
infrastructure that origin in the krb5 library. The particular test that
failed was the `old-simple` test with the following stack trace:

Show quoted text
> 0x00007ffff7f433c1 in __strlen_avx2 () from /nix/store/dp9nhj3ng2hw3cfn0x0w867z0d3kp0i7-glibc-2.30/lib/libc.so.6
> #0 0x00007ffff7f433c1 in __strlen_avx2 () from /nix/store/dp9nhj3ng2hw3cfn0x0w867z0d3kp0i7-glibc-2.30/lib/libc.so.6
> #1 0x00007ffff7e75a0e in strdup () from /nix/store/dp9nhj3ng2hw3cfn0x0w867z0d3kp0i7-glibc-2.30/lib/libc.so.6
> #2 0x00007ffff7cf5f79 in k5_primary_domain () at dnsglue.c:506
> #3 0x00007ffff7cff10b in qualify_shortname (context=context@entry=0x410be0, host=host@entry=0x410610 "") at sn2princ.c:74
> #4 0x00007ffff7cff2c2 in k5_expand_hostname (context=context@entry=0x410be0, host=host@entry=0x410610 "", is_fallback=is_fallback@entry=0, canonhost_out=canonhost_out@entry=0x7fffffff8fc0) at sn2princ.c:128
> #5 0x00007ffff7cff3a1 in krb5_expand_hostname (context=context@entry=0x410be0, host=host@entry=0x410610 "", canonhost_out=canonhost_out@entry=0x7fffffff8fc0) at sn2princ.c:164
> #6 0x00007ffff7cff5f6 in krb5_sname_to_principal (context=0x410be0, hostname=0x410610 "", sname=0x40f5b0 "", type=type@entry=3, princ_out=princ_out@entry=0x7fffffff9088) at sn2princ.c:219
> #7 0x00007ffff7d8d6a8 in krb5_gss_import_name (minor_status=0x7fffffffb2b4, input_name_buffer=0x40f480, input_name_type=0x40f640, output_name=0x7fffffffb1c0) at import_name.c:166
> #8 0x00007ffff7d789bc in gssint_import_internal_name (minor_status=minor_status@entry=0x7fffffffb2b4, mech_type=0x40e290, union_name=union_name@entry=0x40fad0, internal_name=internal_name@entry=0x7fffffffb1c0) at g_glue.c:400
> #9 0x00007ffff7d74661 in gss_add_cred_from (minor_status=minor_status@entry=0x7fffffffb2b4, input_cred_handle=0x410bb0, desired_name=desired_name@entry=0x40fad0, desired_mech=<optimized out>, cred_usage=cred_usage@entry=2, initiator_time_req=initiator_time_req@entry=0, acceptor_time_req=0, cred_store=0x0, output_cred_handle=0x0, actual_mechs=0x0, initiator_time_rec=0x0, acceptor_time_rec=0x0) at g_acquire_cred.c:512
> #10 0x00007ffff7d74cbb in gss_acquire_cred_from (minor_status=minor_status@entry=0x7fffffffb394, desired_name=0x40fad0, time_req=time_req@entry=0, desired_mechs=desired_mechs@entry=0x0, cred_usage=cred_usage@entry=2, cred_store=cred_store@entry=0x0, output_cred_handle=0x40d740, actual_mechs=0x0, time_rec=0x0) at g_acquire_cred.c:190
> #11 0x00007ffff7d74dd1 in gss_acquire_cred (minor_status=minor_status@entry=0x7fffffffb394, desired_name=<optimized out>, time_req=time_req@entry=0, desired_mechs=desired_mechs@entry=0x0, cred_usage=cred_usage@entry=2, output_cred_handle=output_cred_handle@entry=0x40d740, actual_mechs=0x0, time_rec=0x0) at g_acquire_cred.c:107
> #12 0x00007ffff7fc32c6 in _gsasl_gssapi_server_start (sctx=<optimized out>, mech_data=0x40dfc8) at server.c:98
> #13 0x00007ffff7fb317e in setup (ctx=ctx@entry=0x40a6b0, mech=mech@entry=0x7ffff7fc7445 "GSSAPI", sctx=sctx@entry=0x40dfb0, n_mechs=n_mechs@entry=13, mechs=mechs@entry=0x40d760, clientp=clientp@entry=0) at xstart.c:69
> #14 0x00007ffff7fb31f2 in start (ctx=ctx@entry=0x40a6b0, mech=0x7ffff7fc7445 "GSSAPI", sctx=sctx@entry=0x7fffffffb480, n_mechs=13, mechs=0x40d760, clientp=clientp@entry=0) at xstart.c:94
> #15 0x00007ffff7fb324f in gsasl_server_start (ctx=ctx@entry=0x40a6b0, mech=<optimized out>, sctx=sctx@entry=0x7fffffffb480) at xstart.c:139
> #16 0x00007ffff7fb2fd2 in _gsasl_listmech (ctx=0x40a6b0, mechs=0x40d760, n_mechs=13, out=out@entry=0x7fffffffb4e0, clientp=clientp@entry=0) at listmech.c:44
> #17 0x00007ffff7fb30b8 in gsasl_server_mechlist (ctx=<optimized out>, out=out@entry=0x7fffffffb4e0) at listmech.c:95
> #18 0x00007ffff7fb3f39 in gsasl_server_listmech (ctx=<optimized out>, out=out@entry=0x7fffffffb540 "ANONYMOUS EXTERNAL LOGIN PLAIN SECURID DIGEST-MD5 CRAM-MD5 SCRAM-SHA-1 SAML20 OPENID20 GSSAPI GS2-KRB5", outlen=outlen@entry=0x7fffffffb538) at obsolete.c:94
> #19 0x0000000000402dbf in doit () at old-simple.c:438
> #20 0x0000000000403a7e in main (argc=<optimized out>, argv=0x7fffffffd668) at utils.c:140

After looking at the implementation of `k5_primary_domain` it became
obvious that the result of the res_ninit(3) call is never validated. The
call doesn't fail but the `res_state` structure doesn't seem to be fully
populated as expected. At least `h.dnsrch[0]` is NULL leading to
`strdup` segfaulting the application.
To: "Kerberos Version 5 Issues via RT" <rt@krbdev.mit.edu>
From: andi@notmuch.email
Date: Tue, 3 Mar 2020 19:49:40 +0100
Subject: Re: [krbdev.mit.edu #8881] AutoReply: Segfault in k5_primary_domain

One small addition:

krb5 version used: 1.18
Subject: git commit
From: ghudson@mit.edu

Fix null dereference qualifying short hostnames

Fix the dnsglue.c PRIMARY_DOMAIN macro not to call strdup() with a
null pointer if no DNS search path is configured.

https://github.com/krb5/krb5/commit/cd82bf377e7fad2409c76bf8b241920692f34fda
Author: Greg Hudson <ghudson@mit.edu>
Commit: cd82bf377e7fad2409c76bf8b241920692f34fda
Branch: master
src/lib/krb5/os/dnsglue.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
Subject: git commit
From: ghudson@mit.edu

Fix null dereference qualifying short hostnames

Fix the dnsglue.c PRIMARY_DOMAIN macro not to call strdup() with a
null pointer if no DNS search path is configured.

(cherry picked from commit cd82bf377e7fad2409c76bf8b241920692f34fda)

https://github.com/krb5/krb5/commit/c57b3f7f36c417c72ac66b014e705bf457babd26
Author: Greg Hudson <ghudson@mit.edu>
Commit: c57b3f7f36c417c72ac66b014e705bf457babd26
Branch: krb5-1.18
src/lib/krb5/os/dnsglue.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
Date: Tue, 24 Mar 2020 16:46:16 +0100
Subject: krb5 crashes in k5_primary_domain
From: "Jiri Slaby" <jslaby@suse.cz>
To: krb5-bugs@mit.edu
Download (untitled) / with headers
text/plain 4.4KiB
When no domain is set during bootup (but is set later), nfs invokes krb
and nfs+krb crashes:
Show quoted text
> #0 __strlen_sse2 () at ../sysdeps/x86_64/multiarch/../strlen.S:120
> #1 0x00007fe592ad7adf in __GI___strdup (s=0x0) at strdup.c:41
> #2 0x00007fe592903e89 in k5_primary_domain () at dnsglue.c:506
> #3 qualify_shortname (context=<optimized out>, host=0x7ffc8968f3d0
"anemoi") at sn2princ.c:74
Show quoted text
> #4 k5_expand_hostname (context=context@entry=0x556b5f5bf5a0,
host=host@entry=0x7ffc8968f3d0 "anemoi",
is_fallback=is_fallback@entry=0,
canonhost_out=canonhost_out@entry=0x7ffc8968f3b8) at sn2princ.c:128
Show quoted text
> #5 0x00007fe592903eea in krb5_expand_hostname
(context=context@entry=0x556b5f5bf5a0, host=host@entry=0x7ffc8968f3d0
"anemoi", canonhost_out=canonhost_out@entry=0x7ffc8968f3b8) at
sn2princ.c:164
Show quoted text
> #6 0x00007fe592906500 in krb5_sname_to_principal
(context=0x556b5f5bf5a0, hostname=0x7ffc8968f3d0 "anemoi",
hostname@entry=0x0, sname=sname@entry=0x556b5f5bdc80 "nfs",
type=type@entry=3, princ_out=princ_out@entry=0x7ffc8968f488)
Show quoted text
> at sn2princ.c:219
> #7 0x00007fe592a111c3 in krb5_gss_import_name
(minor_status=0x7ffc8969178c, input_name_buffer=<optimized out>,
input_name_type=<optimized out>, output_name=0x7ffc89691690) at
import_name.c:166
Show quoted text
> #8 0x00007fe592a2a088 in gssint_import_internal_name
(minor_status=minor_status@entry=0x7ffc8969178c,
mech_type=mech_type@entry=0x556b5f5bcc70,
union_name=union_name@entry=0x556b5f5a3a20,
Show quoted text
> internal_name=internal_name@entry=0x7ffc89691690) at g_glue.c:400
> #9 0x00007fe592a2b820 in gss_add_cred_from
(minor_status=minor_status@entry=0x7ffc8969178c,
input_cred_handle=<optimized out>,
desired_name=desired_name@entry=0x556b5f5a3a20, desired_mech=<optimized
Show quoted text
out>,
Show quoted text
> cred_usage=cred_usage@entry=2,
initiator_time_req=initiator_time_req@entry=4294967295,
acceptor_time_req=4294967295, cred_store=0x0, output_cred_handle=0x0,
actual_mechs=0x0, initiator_time_rec=0x0, acceptor_time_rec=0x0)
Show quoted text
> at g_acquire_cred.c:512
> #10 0x00007fe592a2de3f in gss_acquire_cred_from
(minor_status=0x7ffc89691864, desired_name=0x556b5f5a3a20,
time_req=4294967295, desired_mechs=0x0, cred_usage=2,
cred_store=cred_store@entry=0x0, output_cred_handle=0x556b5eff0378,
Show quoted text
> actual_mechs=0x0, time_rec=0x0) at g_acquire_cred.c:190
> #11 0x00007fe592a2e096 in gss_acquire_cred (minor_status=<optimized
Show quoted text
out>, desired_name=<optimized out>, time_req=<optimized out>,
desired_mechs=<optimized out>, cred_usage=<optimized out>,
output_cred_handle=<optimized out>,
Show quoted text
> actual_mechs=0x0, time_rec=0x0) at g_acquire_cred.c:107
> #12 0x0000556b5efec956 in ?? ()
> #13 0x0000556b5efe8f4d in ?? ()
> #14 0x00007fe592a6fceb in __libc_start_main (main=0x556b5efe8520,
argc=1, argv=0x7ffc89691a48, init=<optimized out>, fini=<optimized out>,
rtld_fini=<optimized out>, stack_end=0x7ffc89691a38) at
../csu/libc-start.c:308
Show quoted text
> #15 0x0000556b5efe921a in ?? ()


Show quoted text
> (gdb) p h
> $1 = {retrans = 5, retry = 2, options = 705, nscount = 1, nsaddr_list
= {{sin_family = 2, sin_port = 13568, sin_addr = {s_addr = 16777343},
sin_zero = "\000\000\000\000\000\000\000"}, {sin_family = 0, sin_port =
0, sin_addr = {
Show quoted text
> s_addr = 0}, sin_zero = "\000\000\000\000\000\000\000"},
{sin_family = 0, sin_port = 0, sin_addr = {s_addr = 0}, sin_zero =
"\000\000\000\000\000\000\000"}}, id = 0, dnsrch = {0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0},
Show quoted text
> defdname = '\000' <repeats 255 times>, pfcode = 0, ndots = 1, nsort
= 0, ipv6_unavail = 0, unused = 0, sort_list = {{addr = {s_addr = 0},
mask = 0}, {addr = {s_addr = 0}, mask = 0}, {addr = {s_addr = 0}, mask =
0}, {addr = {
Show quoted text
> s_addr = 0}, mask = 0}, {addr = {s_addr = 0}, mask = 0}, {addr
= {s_addr = 0}, mask = 0}, {addr = {s_addr = 0}, mask = 0}, {addr =
{s_addr = 0}, mask = 0}, {addr = {s_addr = 0}, mask = 0}, {addr =
{s_addr = 0},
Show quoted text
> mask = 0}}, __glibc_unused_qhook = 0x0, __glibc_unused_rhook =
0x0, res_h_errno = 0, _vcsock = -1, _flags = 0, _u = {pad =
"\000\000\000\000\000\000\000\000\377\377\377\377", '\000' <repeats 36
Show quoted text
times>, "a\200\257H", _ext = {
Show quoted text
> nscount = 0, nsmap = {0, 0, 0}, nssocks = {-1, 0, 0}, nscount6 =
0, nsinit = 0, nsaddrs = {0x0, 0x0, 0x0}, __glibc_reserved =
{1219461217, 648608350}}}}
Show quoted text
> (gdb) p h.dnsrch
> $2 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}



Trying to strdup the NULL pointer is not a good idea. So
k5_primary_domain should return NULL if the domain is NULL. Something like:
-#define PRIMARY_DOMAIN(h) strdup(h.dnsrch[0])
+#define PRIMARY_DOMAIN(h) ((h).dnsrch[0] ? strdup((h).dnsrch[0]) : NULL)

And perhaps for the old res_init case too.

thanks,
--
js
suse labs
This bug has been fixed on master (commit cd82bf377e7fad2409c76bf8b241920692f34fda) and the fix will be in the 1.18.1 patch release.