[Nagiosplug-devel] Stack overflow in check_clamd/check_tcp

Andreas Ericsson ae at op5.se
Wed Oct 27 10:08:45 CEST 2010


On 10/26/2010 11:35 PM, Holger Weiß wrote:
> * Andreas Ericsson<ae at op5.se>  [2010-10-26 20:52]:
>> On 10/26/2010 07:37 PM, Holger Weiß wrote:
>>> | (gdb) bt
>>> | #0  0x0db1df4d in kill () from /usr/lib/libc.so.56.0
>>> | #1  0x0db803c3 in __stack_smash_handler (func=0x3c0012ec "np_net_connect",
>>> |     damaged=-809694338) at /usr/src/lib/libc/sys/stack_protector.c:89
>>> | #2  0x1c003a5d in np_net_connect (host_name=0x0, port=3310, sd=0x3c002064,
>>> |     proto=10652) at netutils.c:267
>>
>> So crap happens in netutils.c at line 267...
> 
> As you said (later on), that's the end of the np_net_connect() function.
> The stack protection code lets the process crash at this point because
> it detects that the return address has been modified since the function
> was called.
> 

But it shouldn't even REACH that point. You could basically put

  printf("Buggy compiler. This portion is never reached with a sane one");
  kill(getpid(), SIGABRT);

above line 267 and just KNOW that things would be right.

>>> | (gdb) step
>>> | 234                     memset(&su, 0, sizeof(su));
>>> | (gdb) step
>>> | 236                     strncpy(su.sun_path, host_name, UNIX_PATH_MAX);
>>> | (gdb) step
>>> | 235                     su.sun_family = AF_UNIX;
>>> | (gdb) step
>>> | 236                     strncpy(su.sun_path, host_name, UNIX_PATH_MAX);
>>> | (gdb) step
>>> | strncpy (dst=0xcfbe1940 "", src=0xcfbe1b7e "/tmp/clamd.socket", n=108)
>>> |     at /usr/src/lib/libc/string/strncpy.c:47
> 
> So line 236 is executed before line 235 and then line 236 is executed
> again?
> 

Probably a result of pipelining. 236 is queued before 235, because they
can both be executed simultaneously. You'll notice that the strncpy() is
only executed once though.

>>> | (gdb) step
>>> | np_net_connect (host_name=0xcfbe1b7e "/tmp/clamd.socket", port=3310,
>>> |     sd=0x3c002064, proto=6) at netutils.c:238
>>> | 238                     if(*sd<   0){
>>> | (gdb) step
>>> | 237                     *sd = socket(PF_UNIX, SOCK_STREAM, 0);
>>> | (gdb) step
>>> | 238                     if(*sd<   0){
>>> | (gdb) step
>>> | 241                     result = connect(*sd, (struct sockaddr *)&su, sizeof(su));
> 
> Hmm.
> 
>> So what the hell is going on?
> 
> No idea.  Looking through np_net_connect(), I don't see any suspicious
> code ...
> 

Same here, and it's not as if it's a huge function or anything. It
looks like a buggy compiler, but OpenBSD (wasn't it?) are rigorously
slow when it comes to upgrading and only use code that's been in
production a while before including it in their distro.

Weird, to say the least.

-- 
Andreas Ericsson                   andreas.ericsson at op5.se
OP5 AB                             www.op5.se
Tel: +46 8-230225                  Fax: +46 8-230231

Considering the successes of the wars on alcohol, poverty, drugs and
terror, I think we should give some serious thought to declaring war
on peace.




More information about the Devel mailing list