Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 13 Apr 1999 10:44:08 -0400
From:      Barry Lustig <barry@lustig.com>
To:        "David E. Cross" <crossd@cs.rpi.edu>
Cc:        freebsd-hackers@FreeBSD.ORG
Subject:   Re: ypserv 
Message-ID:  <19990413144409.16671.qmail@devious.lustig.com>
In-Reply-To: <199904122143.RAA25814@cs.rpi.edu>
References:  <199904122143.RAA25814@cs.rpi.edu>

next in thread | previous in thread | raw e-mail | index | archive | help
David,

  You need to compile ypserv with ElectricFence to start to track down this  
problem.  Otherwise, you don't see the problem until much later after the  
problem really occurs.

  I have a network with 3 2.x-stable machines running ypserv and 1  
3.x-stable machine running ypserv.  These machines serve yp to solaris 2.5.1,  
2.6, 2.7, irix 5.3, 6.2, 6.3, 6.4, 6.5, and openstep 4.2 machines.  I see  
dozens of SEGV's from the ypserv processes on the FreeBSD boxes.  Here is  
what I managed to find.  I was waiting for Bill Paul to get back to me on  
this, but haven't heard from him.


Here is a stack trace from one of my cores:

(gdb) bt
#0  0x62ef in readtcp (xprt=0x20524fcc,
    buf=0x2066b05c <Error reading address 0x2066b05c: Bad address>,  
len=4000)    at /usr/src/lib/libc/../libc/rpc/svc_tcp.c:346
#1  0xf103 in fill_input_buf (rstrm=0x204eefbc)
    at /usr/src/lib/libc/../libc/xdr/xdr_rec.c:510
#2  0xf1ed in skip_input_bytes (rstrm=0x204eefbc, cnt=4)
    at /usr/src/lib/libc/../libc/xdr/xdr_rec.c:576
#3  0xefd5 in xdrrec_eof (xdrs=0x204ece58)
    at /usr/src/lib/libc/../libc/xdr/xdr_rec.c:436
#4  0x636d in svctcp_stat (xprt=0x20524fcc)
    at /usr/src/lib/libc/../libc/rpc/svc_tcp.c:381
#5  0x7a0e in svc_getreqset (readfds=0xefbfd924)
    at /usr/src/lib/libc/../libc/rpc/svc.c:480
#6  0x4241 in yp_svc_run () at /usr/src/usr.sbin/ypserv/yp_main.c:144
#7  0x47e4 in main (argc=1, argv=0xefbfd99c)
    at /usr/src/usr.sbin/ypserv/yp_main.c:335

***	By the way, this is applicable to 3.x-Stable as well

If you follow the stack frames up, it is clear that the problem is stemming  
from svc_getreqset in libc/rpc/svc.c (which I've included below).  I get the  
SEGV at the call to SVC_STAT(xprt).  Based upon the values of sock and bit:

	$31 = (SVCXPRT *) 0x20524fcc
	(gdb) p sock
	$32 = 0
	(gdb) p bit
	$33 = 21
	(gdb) p *xprt
	Error accessing memory address 0x20524fcc: Bad address.

xprt should be pointing to xports[20].  Here is xports[20]

	(gdb) p xports[20]
	$28 = (SVCXPRT *) 0x0

I think that one of the children processes (or the parent process) may be  
calling svctcp_destroy(xprt) or svcudp_destroy(xprt) on the slot that the  
parent process (or child process) is working with.

barry

void
svc_getreqset(readfds)
  fd_set *readfds;
{
  enum xprt_stat stat;
  struct rpc_msg msg;
  int prog_found;
  u_long low_vers;
  u_long high_vers;
  struct svc_req r;
  register SVCXPRT *xprt;
  register u_long mask;
  register int bit;
  register u_long *maskp;
  register int setsize;
  register int sock;
  char cred_area[2*MAX_AUTH_BYTES + RQCRED_SIZE];
  msg.rm_call.cb_cred.oa_base = cred_area;
  msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]);
  r.rq_clntcred = &(cred_area[2*MAX_AUTH_BYTES]);


  setsize = _rpc_dtablesize();
  maskp = (u_long *)readfds->fds_bits;
  for (sock = 0; sock < setsize; sock += NFDBITS) {
      for (mask = *maskp++; (bit = ffs(mask)); mask ^= (1 << (bit - 1))) {
    /* sock has input waiting */
    xprt = xports[sock + bit - 1];
    if (xprt == NULL)
        /* But do we control sock? */
        continue;
    /* now receive msgs from xprtprt (support batch calls) */
    do {
      if (SVC_RECV(xprt, &msg)) {

        /* now find the exported program and call it */
        register struct svc_callout *s;
        enum auth_stat why;

        r.rq_xprt = xprt;
        r.rq_prog = msg.rm_call.cb_prog;
        r.rq_vers = msg.rm_call.cb_vers;
        r.rq_proc = msg.rm_call.cb_proc;
        r.rq_cred = msg.rm_call.cb_cred;
        /* first authenticate the message */
        if ((why= _authenticate(&r, &msg)) != AUTH_OK) {
          svcerr_auth(xprt, why);
          goto call_done;
        }
        /* now match message with a registered service*/
        prog_found = FALSE;
        low_vers = 0 - 1;
        high_vers = 0;
        for (s = svc_head; s != NULL_SVC; s = s->sc_next) {
          if (s->sc_prog == r.rq_prog) {
            if (s->sc_vers == r.rq_vers) {
              (*s->sc_dispatch)(&r, xprt);
              goto call_done;
            }  /* found correct version */
            prog_found = TRUE;
            if (s->sc_vers < low_vers)
              low_vers = s->sc_vers;
            if (s->sc_vers > high_vers)
              high_vers = s->sc_vers;
          }   /* found correct program */
        }
        /*
         * if we got here, the program or version
         * is not served ...
         */
        if (prog_found)
          svcerr_progvers(xprt,
          low_vers, high_vers);
        else
           svcerr_noprog(xprt);
        /* Fall through to ... */
      }
    call_done:
      if ((stat = SVC_STAT(xprt)) == XPRT_DIED){
        SVC_DESTROY(xprt);
        break;
      }
    } while (stat == XPRT_MOREREQS);
      }
  }
}


static void
svctcp_destroy(xprt)
        register SVCXPRT *xprt;
{
        register struct tcp_conn *cd = (struct tcp_conn *)xprt->xp_p1;

        xprt_unregister(xprt);
        (void)close(xprt->xp_sock);
        if (xprt->xp_port != 0) {
                /* a rendezvouser socket */
                xprt->xp_port = 0;
        } else {
                /* an actual connection socket */
                XDR_DESTROY(&(cd->xdrs));
        }
        mem_free((caddr_t)cd, sizeof(struct tcp_conn));
        mem_free((caddr_t)xprt, sizeof(SVCXPRT));
}


static void
svcudp_destroy(xprt)
        register SVCXPRT *xprt;
{
        register struct svcudp_data *su = su_data(xprt);

        xprt_unregister(xprt);
        (void)close(xprt->xp_sock);
        XDR_DESTROY(&(su->su_xdrs));
        mem_free(rpc_buffer(xprt), su->su_iosz);
        mem_free((caddr_t)su, sizeof(struct svcudp_data));
        mem_free((caddr_t)xprt, sizeof(SVCXPRT));
}


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?19990413144409.16671.qmail>