]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/nfs/nfs_boot.c
xnu-4570.61.1.tar.gz
[apple/xnu.git] / bsd / nfs / nfs_boot.c
index 33bc25128498fe8ef1995f2a3ff5cc4394a9f29d..56d3be6642f423401bea722ecee1640a1287336e 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * Copyright (c) 2000-2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2016 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- * 
+ *
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
  * unlawful or unlicensed copies of an Apple operating system, or to
  * circumvent, violate, or enable the circumvention or violation of, any
  * terms of an Apple operating system software license agreement.
- * 
+ *
  * Please obtain a copy of the License at
  * http://www.opensource.apple.com/apsl/ and read it before using this file.
- * 
+ *
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
@@ -22,7 +22,7 @@
  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  * Please see the License for the specific language governing rights and
  * limitations under the License.
- * 
+ *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 /* Copyright (c) 1995, 1997 NeXT Computer, Inc. All Rights Reserved */
@@ -177,13 +177,7 @@ static int get_file_handle(struct nfs_dlmount *ndmntp);
 #define IP_CH(ip)      ((u_char *)ip)
 #define IP_LIST(ip)    IP_CH(ip)[0],IP_CH(ip)[1],IP_CH(ip)[2],IP_CH(ip)[3]
 
-extern boolean_t
-netboot_iaddr(struct in_addr * iaddr_p);
-
-extern boolean_t
-netboot_rootpath(struct in_addr * server_ip,
-                char * name, int name_len, 
-                char * path, int path_len);
+#include <sys/netboot.h>
 
 /*
  * Called with an empty nfs_diskless struct to be filled in.
@@ -353,8 +347,7 @@ failed:
 }
 
 static int
-get_file_handle(ndmntp)
-       struct nfs_dlmount *ndmntp;
+get_file_handle(struct nfs_dlmount *ndmntp)
 {
        char *sp, *dp, *endp;
        int error;
@@ -446,10 +439,9 @@ struct bp_inaddr {
  * know about us (don't want to broadcast a getport call).
  */
 static int
-bp_whoami(bpsin, my_ip, gw_ip)
-       struct sockaddr_in *bpsin;
-       struct in_addr *my_ip;
-       struct in_addr *gw_ip;
+bp_whoami(struct sockaddr_in *bpsin,
+       struct in_addr *my_ip,
+       struct in_addr *gw_ip)
 {
        /* RPC structures for PMAPPROC_CALLIT */
        struct whoami_call {
@@ -468,6 +460,7 @@ bp_whoami(bpsin, my_ip, gw_ip)
        size_t msg_len, cn_len, dn_len;
        u_char *p;
        int32_t *lp;
+        size_t encapsulated_size;
 
        /*
         * Get message buffer of sufficient size.
@@ -516,8 +509,10 @@ bp_whoami(bpsin, my_ip, gw_ip)
        bpsin->sin_addr.s_addr = sin.sin_addr.s_addr;
 
        /* length of encapsulated results */
-       if (msg_len < (ntohl(*lp) + sizeof(*lp)))
+       if (os_add_overflow((size_t) ntohl(*lp), sizeof(*lp), &encapsulated_size)
+               || msg_len < encapsulated_size) {
                goto bad;
+       }
        msg_len = ntohl(*lp++);
        p = (u_char*)lp;
 
@@ -526,7 +521,7 @@ bp_whoami(bpsin, my_ip, gw_ip)
                goto bad;
        str = (struct rpc_string *)p;
        cn_len = ntohl(str->len);
-       if (msg_len < cn_len)
+       if ((msg_len - 4) < cn_len)
                goto bad;
        if (cn_len >= MAXHOSTNAMELEN)
                goto bad;
@@ -541,7 +536,7 @@ bp_whoami(bpsin, my_ip, gw_ip)
                goto bad;
        str = (struct rpc_string *)p;
        dn_len = ntohl(str->len);
-       if (msg_len < dn_len)
+       if ((msg_len - 4) < dn_len)
                goto bad;
        if (dn_len >= MAXHOSTNAMELEN)
                goto bad;
@@ -582,20 +577,19 @@ out:
  *     server pathname
  */
 static int
-bp_getfile(bpsin, key, md_sin, serv_name, pathname)
-       struct sockaddr_in *bpsin;
-       const char *key;
-       struct sockaddr_in *md_sin;
-       char *serv_name;
-       char *pathname;
+bp_getfile(struct sockaddr_in *bpsin,
+       const char *key,
+       struct sockaddr_in *md_sin,
+       char *serv_name,
+       char *pathname)
 {
        struct rpc_string *str;
        mbuf_t m;
        struct bp_inaddr *bia;
        struct sockaddr_in *sin;
        u_char *p, *q;
-       int error, msg_len;
-       int cn_len, key_len, sn_len, path_len;
+       int error;
+       size_t msg_len, cn_len, key_len, sn_len, path_len;
 
        /*
         * Get message buffer of sufficient size.
@@ -637,11 +631,11 @@ bp_getfile(bpsin, key, md_sin, serv_name, pathname)
        msg_len = mbuf_len(m);
 
        /* server name */
-       if (msg_len < (int)sizeof(*str))
+       if (msg_len < sizeof(*str))
                goto bad;
        str = (struct rpc_string *)p;
        sn_len = ntohl(str->len);
-       if (msg_len < sn_len)
+       if ((msg_len - 4) < sn_len)
                goto bad;
        if (sn_len >= MAXHOSTNAMELEN)
                goto bad;
@@ -651,7 +645,7 @@ bp_getfile(bpsin, key, md_sin, serv_name, pathname)
        msg_len -= RPC_STR_SIZE(sn_len);
 
        /* server IP address (mountd) */
-       if (msg_len < (int)sizeof(*bia))
+       if (msg_len < sizeof(*bia))
                goto bad;
        bia = (struct bp_inaddr *)p;
        if (bia->atype != htonl(1))
@@ -669,11 +663,11 @@ bp_getfile(bpsin, key, md_sin, serv_name, pathname)
        msg_len -= sizeof(*bia);
 
        /* server pathname */
-       if (msg_len < (int)sizeof(*str))
+       if (msg_len < sizeof(*str))
                goto bad;
        str = (struct rpc_string *)p;
        path_len = ntohl(str->len);
-       if (msg_len < path_len)
+       if ((msg_len - 4) < path_len)
                goto bad;
        if (path_len >= MAXPATHLEN)
                goto bad;
@@ -697,13 +691,12 @@ out:
  * Also, sets sin->sin_port to the NFS service port.
  */
 static int
-md_mount(mdsin, path, v3, sotype, fhp, fhlenp)
-       struct sockaddr_in *mdsin;              /* mountd server address */
-       char *path;
-       int v3;
-       int sotype;
-       u_char *fhp;
-       u_int32_t *fhlenp;
+md_mount(struct sockaddr_in *mdsin,            /* mountd server address */
+       char *path,
+       int v3,
+       int sotype,
+       u_char *fhp,
+       u_int32_t *fhlenp)
 {
        /* The RPC structures */
        struct rpc_string *str;
@@ -712,7 +705,8 @@ md_mount(mdsin, path, v3, sotype, fhp, fhlenp)
                u_char  data[NFSX_V3FHMAX + sizeof(u_int32_t)];
        } *rdata;
        mbuf_t m;
-       int error, mlen, slen;
+       size_t mlen;
+       int error, slen;
        int mntversion = v3 ? RPCMNT_VER3 : RPCMNT_VER1;
        int proto = (sotype == SOCK_STREAM) ? IPPROTO_TCP : IPPROTO_UDP;
        in_port_t mntport, nfsport;
@@ -752,7 +746,7 @@ md_mount(mdsin, path, v3, sotype, fhp, fhlenp)
         * + a v3 filehandle length + a v3 filehandle
         */
        mlen = mbuf_len(m);
-       if (mlen < (int)sizeof(u_int32_t))
+       if (mlen < sizeof(u_int32_t))
                goto bad;
        rdata = mbuf_data(m);
        error = ntohl(rdata->errno);
@@ -761,16 +755,17 @@ md_mount(mdsin, path, v3, sotype, fhp, fhlenp)
        if (v3) {
                u_int32_t fhlen;
                u_char *fh;
-               if (mlen < (int)sizeof(u_int32_t)*2)
+               if (mlen < sizeof(u_int32_t)*2)
                        goto bad;
                fhlen = ntohl(*(u_int32_t*)rdata->data);
                fh = rdata->data + sizeof(u_int32_t);
-               if (mlen < (int)(sizeof(u_int32_t)*2 + fhlen))
+               if (mlen < (sizeof(u_int32_t)*2 + fhlen)
+                       || fhlen >= (NFSX_V3FHMAX + sizeof(u_int32_t)))
                        goto bad;
                bcopy(fh, fhp, fhlen);
                *fhlenp = fhlen;
        } else {
-               if (mlen < ((int)sizeof(u_int32_t) + NFSX_V2FH))
+               if (mlen < (sizeof(u_int32_t) + NFSX_V2FH))
                        goto bad;
                bcopy(rdata->data, fhp, NFSX_V2FH);
                *fhlenp = NFSX_V2FH;