NetBSD-Bugs archive

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

bin/60481: kpasswdd(8): free of stack buffer on exit



>Number:         60481
>Category:       bin
>Synopsis:       kpasswdd(8): free of stack buffer on exit
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    bin-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Jul 23 02:05:00 +0000 2026
>Originator:     Taylor R Campbell
>Release:        current, 11, 10, 9, ....
>Organization:
The kNetBSD Heimdallation, Incore dumped
>Environment:
>Description:
	Found a kpasswdd.core lying around on a KDC host from a while
	back.

Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x000070131a70f647 in free () from /usr/lib/libc.so.12
(gdb) bt
#0  0x000070131a70f647 in free () from /usr/lib/libc.so.12
#1  0x00000001bf40417a in doit ()
#2  0x00000001bf404b9b in main ()
(gdb) fr 1
#1  0x00000001bf40417a in doit ()
(gdb) disas
...
   0x00000001bf40414b <+3279>:  xor    %ebx,%ebx
   0x00000001bf40414d <+3281>:  mov    -0x6e0(%rbp),%r12d
   0x00000001bf404154 <+3288>:  mov    -0x6f8(%rbp),%r13
   0x00000001bf40415b <+3295>:  mov    0x0(%r13,%rbx,4),%edi
   0x00000001bf404160 <+3300>:  call   0x1bf402b40 <close@plt>
   0x00000001bf404165 <+3305>:  add    $0x1,%rbx
   0x00000001bf404169 <+3309>:  cmp    %ebx,%r12d
   0x00000001bf40416c <+3312>:  ja     0x1bf40415b <doit+3295>
   0x00000001bf40416e <+3314>:  mov    -0x6f8(%rbp),%rdi
   0x00000001bf404175 <+3321>:  call   0x1bf4026b0 <free@plt>
=> 0x00000001bf40417a <+3326>:  mov    -0x6bc(%rbp),%edx

	Looks like that's here:

    855     for (i = 0; i < n; ++i)
    856 	close(sockets[i]);
 => 857     free(sockets);

https://nxr.netbsd.org/xref/src/crypto/external/bsd/heimdal/dist/kpasswd/kpasswdd.c?r=1.5#855

	What's sockets?  Well, since kpasswdd(8) is running under
	inetd(8), it probably came out of this:

    729 #ifdef INETD_SUPPORT
    730     int fdz;
    731     int from_inetd;
    732     socklen_t fromlen;
    733     krb5_address my_addr;
    734     struct sockaddr_storage __local;
    735     struct sockaddr *localsa = (struct sockaddr *)&__local;
    736 #endif
...
    782 #ifdef INETD_SUPPORT
    783     } else {
    784         n = 1;
    785         maxfd = 0;
    786 	fdz = 0;
 => 787         sockets = &fdz;
    788         FD_ZERO(&real_fdset);
    789         FD_SET(0, &real_fdset);
    790     }
    791 #endif

	That's not something you can pass to free(3)!

>How-To-Repeat:

	1. run kpasswdd(8) under inetd(8) like we suggest with the
	   default inetd.conf
	2. use kpasswd(1) to make sure it has started
	3. send kpasswdd(8) SIGTERM
	4. (send it SIGTERM again if you caught it in the signal race
	   window that I notice by code inspection)

>Fix:

#ifdef INETD_SUPPORT
	if (!from_inetd)
#endif




Home | Main Index | Thread Index | Old Index