NetBSD-Bugs archive

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

lib/46773: librpc segfaults when out of memory



>Number:         46773
>Category:       lib
>Synopsis:       librpc segfaults when out of memory
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    lib-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Aug 06 07:05:00 +0000 2012
>Originator:     Thorsten Brehm
>Release:        5.1.2
>Organization:
>Environment:
>Description:
When system is out of or low on memory, "xdrrec_create" in 
"src/lib/libc/rpc/xdrrec_create.c" bails out, prints the warning 
"xdrrec_create: out of memory", and leaves xdrs->x_private == NULL.

However, the "makefd_xprt" does not check if "xdrrec_create" was successful and 
will segfault in this case (by dereferencing "xdrs->x_private" unconditionally).

Attached patch adds appropriate checks to "xdrrec_create" callers, so they also 
bail out when "xdrrec_create" did.
>How-To-Repeat:
Allocate all available memory and trigger a call to any RPC server.
>Fix:
Index: clnt_vc.c
===================================================================
RCS file: /cvsroot/src/lib/libc/rpc/clnt_vc.c,v
retrieving revision 1.18
diff -w -u -r1.18 clnt_vc.c
--- clnt_vc.c   13 Mar 2012 21:13:44 -0000      1.18
+++ clnt_vc.c   4 Aug 2012 09:50:46 -0000
@@ -301,6 +301,8 @@
        recvsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsz);
        xdrrec_create(&(ct->ct_xdrs), sendsz, recvsz,
            h->cl_private, read_vc, write_vc);
+       if (ct->ct_xdrs.x_private == NULL)
+               goto fooy;
        return (h);
 
 fooy:
Index: svc_vc.c
===================================================================
RCS file: /cvsroot/src/lib/libc/rpc/svc_vc.c,v
retrieving revision 1.26
diff -w -u -r1.26 svc_vc.c
--- svc_vc.c    20 Mar 2012 17:14:50 -0000      1.26
+++ svc_vc.c    4 Aug 2012 09:50:47 -0000
@@ -260,7 +260,7 @@
 makefd_xprt(int fd, u_int sendsize, u_int recvsize)
 {
        SVCXPRT *xprt;
-       struct cf_conn *cd;
+       struct cf_conn *cd = NULL;
        const char *netid;
        struct __rpc_sockinfo si;
  
@@ -276,9 +276,11 @@
        cd->strm_stat = XPRT_IDLE;
        xdrrec_create(&(cd->xdrs), sendsize, recvsize,
            (caddr_t)(void *)xprt, read_vc, write_vc);
+       if (cd->xdrs.x_private == NULL)
+               goto out;
        xprt->xp_p1 = (caddr_t)(void *)cd;
        xprt->xp_verf.oa_base = cd->verf_body;
-       svc_vc_ops(xprt);  /* truely deals with calls */
+       svc_vc_ops(xprt);  /* truly deals with calls */
        xprt->xp_port = 0;  /* this is a connection, not a rendezvouser */
        xprt->xp_fd = fd;
        if (__rpc_fd2sockinfo(fd, &si) && __rpc_sockinfo2netid(&si, &netid))
@@ -289,6 +291,8 @@
        return xprt;
 out:
        warn("svc_tcp: makefd_xprt");
+       if (cd)
+               mem_free(cd, sizeof(struct cf_conn));
        if (xprt)
                mem_free(xprt, sizeof(SVCXPRT));
        return NULL;



Home | Main Index | Thread Index | Old Index