Bug 161217 - ypxfr crash in libc, xdr_string_internal
ypxfr crash in libc, xdr_string_internal
Status: CLOSED ERRATA
Product: Fedora
Classification: Fedora
Component: ypserv (Show other bugs)
4
x86_64 Linux
medium Severity high
: ---
: ---
Assigned To: Chris Feist
:
Depends On:
Blocks:
  Show dependency treegraph
 
Reported: 2005-06-21 10:39 EDT by Ben Shi
Modified: 2007-11-30 17:11 EST (History)
5 users (show)

See Also:
Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Environment:
Last Closed: 2005-09-05 01:24:44 EDT
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
CRM:
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---


Attachments (Terms of Use)

  None (edit)
Description Ben Shi 2005-06-21 10:39:38 EDT
Description of problem:
running ypxfr cause core dump

Version-Release number of selected component (if applicable):


How reproducible:
run ypxfr

Steps to Reproduce:
1.
2.
3.
  
Actual results:
core dumps

Expected results:
transfer ypmaps

Additional info:

Here is running gdb outputs:

(gdb) bt
#0  0x00000036f07f021f in xdr_string_internal () from /lib64/libc.so.6
#1  0x00000036f07eafbc in clntudp_call () from /lib64/libc.so.6
#2  0x0000000000403551 in ypproc_master_2 (argp=Variable "argp" is not available.
) at ypxfr_clnt.c:45
#3  0x0000000000402359 in ypxfr (map=0x7fffffc7eb77 "protocols.byname", 
    source_host=0x7fffffc7eb49 "fspd1.aoa.twosigma.com", 
    source_domain=0x7fffffc7eb66 "nyc.twosigma.com", 
    target_domain=0x7fffffc7eb66 "nyc.twosigma.com", noclear=1, force=1)
    at ypxfr.c:423
#4  0x0000000000403180 in main (argc=Variable "argc" is not available.
) at ypxfr.c:839
#5  0x00000036f071c4cc in __libc_start_main () from /lib64/libc.so.6
#6  0x0000000000401ce9 in _start ()
#7  0x00007fffffc7cac8 in ?? ()
#8  0x0000000000000000 in ?? ()

diassemble
...
0x00000036f07f0218 <xdr_string_internal+168>:   test   %rbx,%rbx
0x00000036f07f021b <xdr_string_internal+171>:   je     0x36f07f0265
<xdr_string_internal+245>
0x00000036f07f021d <xdr_string_internal+173>:   mov    %edx,%eax
0x00000036f07f021f <xdr_string_internal+175>:   movb   $0x0,(%rax,%rbx,1)
0x00000036f07f0223 <xdr_string_internal+179>:   mov    0x14(%rsp),%edx
0x00000036f07f0227 <xdr_string_internal+183>:   mov    %rbx,%rsi
0x00000036f07f022a <xdr_string_internal+186>:   mov    %rbp,%rdi
...
Comment 1 Jakub Jelinek 2005-06-21 11:39:38 EDT
I have not debugged it, but from skimming the source that sounds like ypxfr
bug.
Both xdr_ypresp_order and xdr_ypresp_master fill in strings read from network,
with xdr_string and ~0 as the maxsize.  xdr_string allocates a new string
with malloc if the pointer passed to it is NULL, but otherwise will assume
the pointer passed to it points to a valid buffer, at least maxsize bytes
long.
So, before xdr_ypresp_order or xdr_ypresp_master is called, the structure
passed to it must be cleared and it is caller's responsibility to do so.
E.g. libc/nis/ypclnt.c when it uses these functions internally, it clears the
memory; ypclnt.c (ypmaster) has:
ypresp_master resp;
...
memset (&resp, '\0', sizeof (ypresp_master));
...
  result = do_ypcall (indomain, YPPROC_MASTER, (xdrproc_t) xdr_ypreq_nokey,
          (caddr_t) & req, (xdrproc_t) xdr_ypresp_master, (caddr_t) & resp);

Now, ypxfr in ypxfr.c passes uninitialized memory to those:
  struct ypresp_order resp_order;
  struct ypresp_master resp_master;
...
  if (ypproc_master_2 (&req_nokey, &resp_master, clnt_udp) != RPC_SUCCESS)
...
  if (ypproc_order_2 (&req_nokey, &resp_order, clnt_udp) != RPC_SUCCESS)

So, if you are lucky and the stack contains zeros in the right places, it will
not crash, otherwise it will.
Comment 2 Ben Shi 2005-06-21 15:46:32 EDT
so this fixed it:

--- ypxfr.c_    2005-06-21 19:44:12.000000000 -0400
+++ ypxfr.c     2005-06-21 19:42:19.000000000 -0400
@@ -420,6 +420,7 @@
      server name for the map on the master host. */
   req_nokey.domain = source_domain;
   req_nokey.map = map;
+  memset (&resp_master, '\0', sizeof (ypresp_master));
   if (ypproc_master_2 (&req_nokey, &resp_master, clnt_udp) != RPC_SUCCESS)
     {
       log_msg (clnt_sperror (clnt_udp, "ypproc_master_2"));
Comment 3 Jakub Jelinek 2005-06-21 16:05:14 EDT
There is memset (&resp_order, '\0', sizeof (resp_order));
needed somewhere before ypproc_order_2 call as well.
Comment 4 Ben Shi 2005-06-21 16:29:00 EDT
is this a spec change on libc? which calls for a behavior change on the caller?
the same ypxfr code works fine for previous version of libc.
Comment 5 Jakub Jelinek 2005-06-21 16:33:48 EDT
No, it is not.  glibc (and other sunrpc implementations) have always behaved
that way.
You might be lucky and see NULL in the right place on the stack when you don't
trigger it.
Comment 6 Ben Shi 2005-06-21 16:46:11 EDT
fair enough, so let's fix ypxfr, thanks for your help
Comment 7 Chris Feist 2005-06-24 11:22:45 EDT
I've put a fix for this into fc4 testing updates.  Can you please test this
package and verify that it fixes the problem?  It's ypserv-2.13-7.

http://download.fedora.redhat.com/pub/fedora/linux/core/updates/testing/4/
Comment 8 Thomas J. Baker 2005-07-20 14:14:09 EDT
This bug also affects i386 and the ypserv in testing fixes it. It would probably
be good to get this pushed to updates.
Comment 9 Chris Feist 2005-07-20 15:12:42 EDT
This package has been pushed to final and will be available shortly.

Note You need to log in before you can comment on or make changes to this bug.