]> 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 cfe0d5df6b07b3b264549c525aca47e6723fdcc3..56d3be6642f423401bea722ecee1640a1287336e 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * Copyright (c) 2000-2007 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 */
@@ -167,7 +167,7 @@ static int bp_getfile(struct sockaddr_in *bpsin, const char *key,
 
 /* mountd RPC */
 static int md_mount(struct sockaddr_in *mdsin, char *path, int v3, int sotype,
-       u_char *fhp, u_long *fhlenp);
+       u_char *fhp, u_int32_t *fhlenp);
 
 /* other helpers */
 static int get_file_handle(struct nfs_dlmount *ndmntp);
@@ -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.
@@ -216,11 +210,17 @@ nfs_boot_init(struct nfs_diskless *nd)
            error = ENOMEM;
            goto failed;
        }
+       MALLOC_ZONE(nd->nd_root.ndm_mntfrom, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
+       if (!nd->nd_root.ndm_mntfrom) {
+           printf("nfs_boot: can't allocate root mntfrom buffer\n");
+           error = ENOMEM;
+           goto failed;
+       }
        sin_p = &nd->nd_root.ndm_saddr;
        bzero((caddr_t)sin_p, sizeof(*sin_p));
        sin_p->sin_len = sizeof(*sin_p);
        sin_p->sin_family = AF_INET;
-       if (netboot_rootpath(&sin_p->sin_addr, nd->nd_root.ndm_host, 
+       if (netboot_rootpath(&sin_p->sin_addr, nd->nd_root.ndm_host,
                             sizeof(nd->nd_root.ndm_host),
                             nd->nd_root.ndm_path, MAXPATHLEN) == TRUE) {
            do_bpgetfile = FALSE;
@@ -270,6 +270,12 @@ nfs_boot_init(struct nfs_diskless *nd)
                        error = ENOMEM;
                        goto failed;
                }
+               MALLOC_ZONE(nd->nd_private.ndm_mntfrom, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
+               if (!nd->nd_private.ndm_mntfrom) {
+                       printf("nfs_boot: can't allocate private host buffer\n");
+                       error = ENOMEM;
+                       goto failed;
+               }
                error = bp_getfile(&bp_sin, "private", 
                                   &nd->nd_private.ndm_saddr,
                                   nd->nd_private.ndm_host,
@@ -341,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;
@@ -357,10 +362,12 @@ get_file_handle(ndmntp)
                return (error);
 
        /* Construct remote path (for getmntinfo(3)) */
-       dp = ndmntp->ndm_host;
-       endp = dp + MNAMELEN - 1;
-       dp += strlen(dp);
-       *dp++ = ':';
+       dp = ndmntp->ndm_mntfrom;
+       endp = dp + MAXPATHLEN - 1;
+       for (sp = ndmntp->ndm_host; *sp && dp < endp;)
+               *dp++ = *sp++;
+       if (dp < endp)
+               *dp++ = ':';
        for (sp = ndmntp->ndm_path; *sp && dp < endp;)
                *dp++ = *sp++;
        *dp = '\0';
@@ -399,7 +406,7 @@ mbuf_get_with_len(size_t msg_len, mbuf_t *m)
  * String representation for RPC.
  */
 struct rpc_string {
-       u_long len;             /* length without null or padding */
+       u_int32_t len;          /* length without null or padding */
        u_char data[4]; /* data (longer, of course) */
     /* data is padded to a long-word boundary */
 };
@@ -408,11 +415,11 @@ struct rpc_string {
 
 /*
  * Inet address in RPC messages
- * (Note, really four longs, NOT chars.  Blech.)
+ * (Note, really four 32-bit ints, NOT chars.  Blech.)
  */
 struct bp_inaddr {
-       u_long  atype;
-       long    addr[4];
+       u_int32_t  atype;
+       int32_t addr[4];
 };
 
 
@@ -432,17 +439,16 @@ 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 {
-               u_long call_prog;
-               u_long call_vers;
-               u_long call_proc;
-               u_long call_arglen;
+               u_int32_t call_prog;
+               u_int32_t call_vers;
+               u_int32_t call_proc;
+               u_int32_t call_arglen;
                struct bp_inaddr call_ia;
        } *call;
 
@@ -453,7 +459,8 @@ bp_whoami(bpsin, my_ip, gw_ip)
        int error;
        size_t msg_len, cn_len, dn_len;
        u_char *p;
-       long *lp;
+       int32_t *lp;
+        size_t encapsulated_size;
 
        /*
         * Get message buffer of sufficient size.
@@ -502,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;
 
@@ -512,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;
@@ -527,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;
@@ -568,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.
@@ -623,13 +631,13 @@ 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 >= MNAMELEN)
+       if (sn_len >= MAXHOSTNAMELEN)
                goto bad;
        bcopy(str->data, serv_name, sn_len);
        serv_name[sn_len] = '\0';
@@ -637,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))
@@ -655,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;
@@ -683,22 +691,22 @@ 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_long *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;
        struct rdata {
-               u_long  errno;
-               u_char  data[NFSX_V3FHMAX + sizeof(u_long)];
+               u_int32_t       errno;
+               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;
@@ -738,25 +746,26 @@ md_mount(mdsin, path, v3, sotype, fhp, fhlenp)
         * + a v3 filehandle length + a v3 filehandle
         */
        mlen = mbuf_len(m);
-       if (mlen < (int)sizeof(u_long))
+       if (mlen < sizeof(u_int32_t))
                goto bad;
        rdata = mbuf_data(m);
        error = ntohl(rdata->errno);
        if (error)
                goto out;
        if (v3) {
-               u_long fhlen;
+               u_int32_t fhlen;
                u_char *fh;
-               if (mlen < (int)sizeof(u_long)*2)
+               if (mlen < sizeof(u_int32_t)*2)
                        goto bad;
-               fhlen = ntohl(*(u_long*)rdata->data);
-               fh = rdata->data + sizeof(u_long);
-               if (mlen < (int)(sizeof(u_long)*2 + fhlen))
+               fhlen = ntohl(*(u_int32_t*)rdata->data);
+               fh = rdata->data + sizeof(u_int32_t);
+               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_long) + NFSX_V2FH))
+               if (mlen < (sizeof(u_int32_t) + NFSX_V2FH))
                        goto bad;
                bcopy(rdata->data, fhp, NFSX_V2FH);
                *fhlenp = NFSX_V2FH;