Note: This is a beta release of Red Hat Bugzilla 5.0. The data contained within is a snapshot of the live data so any changes you make will not be reflected in the production Bugzilla. Also email is disabled so feel free to test any aspect of the site that you want. File any problems you find or give feedback here.

Bug 161217

Summary: ypxfr crash in libc, xdr_string_internal
Product: [Fedora] Fedora Reporter: Ben Shi <benjamin.shi>
Component: ypservAssignee: Chris Feist <cfeist>
Status: CLOSED ERRATA QA Contact:
Severity: high Docs Contact:
Priority: medium    
Version: 4CC: edgar.hoch, jakub, steved, sundaram, tjb
Target Milestone: ---   
Target Release: ---   
Hardware: x86_64   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2005-09-05 05:24:44 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---

Description Ben Shi 2005-06-21 14:39:38 UTC
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 15:39:38 UTC
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 19:46:32 UTC
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 20:05:14 UTC
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 20:29:00 UTC
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 20:33:48 UTC
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 20:46:11 UTC
fair enough, so let's fix ypxfr, thanks for your help

Comment 7 Chris Feist 2005-06-24 15:22:45 UTC
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 18:14:09 UTC
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 19:12:42 UTC
This package has been pushed to final and will be available shortly.