]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/net/kext_net.c
xnu-792.17.14.tar.gz
[apple/xnu.git] / bsd / net / kext_net.c
index d96e427d0054412ae23485b3bff65f0510b6b32a..c9ba8eb8316b6e612fd2e3e9ddf75756f6ef1609 100644 (file)
@@ -1,23 +1,29 @@
 /*
  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
  *
- * @APPLE_LICENSE_HEADER_START@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License").  You may not use this file except in compliance with the
- * License.  Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
+ * 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
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * 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.
  * 
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * 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,
  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License.
+ * 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_LICENSE_HEADER_END@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 /* Copyright (C) 1999 Apple Computer, Inc.  */
 
@@ -41,6 +47,8 @@
 /* List of kernel extensions (networking) known to kernel */
 struct nf_list nf_list;
 
+static int sockfilter_fix_symantec_bug(struct NFDescriptor* theirDesc);
+
 /*
  * Register a global filter for the specified protocol
  * Make a few checks and then insert the new descriptor in the
@@ -55,6 +63,13 @@ register_sockfilter(struct NFDescriptor *nfp, struct NFDescriptor *nfp1,
        if (nfp == NULL)
                return(EINVAL);
 
+       /* Fix Symantec's broken NPC kext */
+       if (nfp->nf_handle == 0xf1ab02de) {
+               int err = sockfilter_fix_symantec_bug(nfp);
+               if (err != 0)
+                       return err;
+       }
+
        s = splhigh();
        if (!NF_initted)
        {       NF_initted = 1;
@@ -87,7 +102,8 @@ register_sockfilter(struct NFDescriptor *nfp, struct NFDescriptor *nfp1,
        return(0);
 }
 
-unregister_sockfilter(struct NFDescriptor *nfp, struct protosw *pr, int flags)
+int
+unregister_sockfilter(struct NFDescriptor *nfp, struct protosw *pr, __unused int flags)
 {      int s;
 
        s = splhigh();
@@ -120,7 +136,7 @@ find_nke(unsigned int handle)
  */
 int
 nke_insert(struct socket *so, struct so_nke *np)
-{      int s, error;
+{
        struct kextcb *kp, *kp1;
        struct NFDescriptor *nf1, *nf2 = NULL;
 
@@ -191,3 +207,143 @@ nke_insert(struct socket *so, struct so_nke *np)
                (*kp->e_soif->sf_socreate)(so, so->so_proto, kp);
        return(0);
 }
+
+/*
+ * The following gunk is a fix for Symantec's broken NPC kext
+ * Symantec's NPC kext does not check that the kextcb->e_fcb
+ * is not NULL before derefing it. The result is a panic in
+ * the very few cases where the e_fcb is actually NULL.
+ *
+ * This gross chunk of code copies the old function ptrs
+ * supplied by the kext and wraps a few select ones in
+ * our own functions that just check for NULL before
+ * calling in to the kext.
+ */
+
+static struct sockif*  g_symantec_if_funcs = NULL;
+static struct sockutil*        g_symantec_util_funcs = NULL;
+static int sym_fix_sbflush(struct sockbuf *, struct kextcb *);
+static int sym_fix_sbappend(struct sockbuf *, struct mbuf *, struct kextcb *);
+static int sym_fix_soclose(struct socket *, struct kextcb *);
+static int sym_fix_sofree(struct socket *, struct kextcb *);
+static int sym_fix_soconnect(struct socket *, struct sockaddr *, struct kextcb *);
+static int sym_fix_soisconnected(struct socket *, struct kextcb *);
+static int sym_fix_sosend(struct socket *, struct sockaddr **, struct uio **, struct mbuf **,
+                       struct mbuf **, int *, struct kextcb *);
+static int sym_fix_socantrcvmore(struct socket *, struct kextcb *);
+static int sym_fix_socontrol(struct socket *, struct sockopt *, struct kextcb *);
+
+static int sockfilter_fix_symantec_bug(struct NFDescriptor* theirDesc)
+{
+       if (!g_symantec_if_funcs ) {
+               MALLOC(g_symantec_if_funcs, struct sockif*, sizeof(*g_symantec_if_funcs), M_TEMP, M_WAITOK);
+               
+               if (!g_symantec_if_funcs)
+                       return ENOMEM;
+               
+               *g_symantec_if_funcs = *theirDesc->nf_soif;
+       }
+       
+       if (!g_symantec_util_funcs) {
+               MALLOC(g_symantec_util_funcs, struct sockutil*, sizeof(*g_symantec_util_funcs), M_TEMP, M_WAITOK);
+               
+               if (!g_symantec_util_funcs)
+                       return ENOMEM;
+               
+               *g_symantec_util_funcs = *theirDesc->nf_soutil;
+       }
+       
+       if (theirDesc->nf_soutil->su_sbflush)
+               theirDesc->nf_soutil->su_sbflush = sym_fix_sbflush;
+       if (theirDesc->nf_soutil->su_sbappend)
+               theirDesc->nf_soutil->su_sbappend = sym_fix_sbappend;
+       if (theirDesc->nf_soif->sf_soclose)
+               theirDesc->nf_soif->sf_soclose = sym_fix_soclose;
+       if (theirDesc->nf_soif->sf_sofree)
+               theirDesc->nf_soif->sf_sofree = sym_fix_sofree;
+       if (theirDesc->nf_soif->sf_soconnect)
+               theirDesc->nf_soif->sf_soconnect = sym_fix_soconnect;
+       if (theirDesc->nf_soif->sf_soisconnected)
+               theirDesc->nf_soif->sf_soisconnected = sym_fix_soisconnected;
+       if (theirDesc->nf_soif->sf_sosend)
+               theirDesc->nf_soif->sf_sosend = sym_fix_sosend;
+       if (theirDesc->nf_soif->sf_socantrcvmore)
+               theirDesc->nf_soif->sf_socantrcvmore = sym_fix_socantrcvmore;
+       if (theirDesc->nf_soif->sf_socontrol)
+               theirDesc->nf_soif->sf_socontrol = sym_fix_socontrol;
+       
+       return 0;
+}
+
+static int sym_fix_sbflush(struct sockbuf *p1, struct kextcb *p2)
+{
+       if (p2->e_fcb != NULL && g_symantec_util_funcs)
+               return g_symantec_util_funcs->su_sbflush(p1, p2);
+       else
+               return 0;
+}
+
+static int sym_fix_sbappend(struct sockbuf *p1, struct mbuf *p2, struct kextcb *p3)
+{
+       if (p3->e_fcb != NULL && g_symantec_util_funcs)
+               return g_symantec_util_funcs->su_sbappend(p1, p2, p3);
+       else
+               return 0;
+}
+
+static int sym_fix_soclose(struct socket *p1, struct kextcb *p2)
+{
+       if (p2->e_fcb != NULL && g_symantec_if_funcs)
+               return g_symantec_if_funcs->sf_soclose(p1, p2);
+       else
+               return 0;
+}
+
+static int sym_fix_sofree(struct socket *p1, struct kextcb *p2)
+{
+       if (p2->e_fcb != NULL && g_symantec_if_funcs)
+               return g_symantec_if_funcs->sf_sofree(p1, p2);
+       else
+               return 0;
+}
+
+static int sym_fix_soconnect(struct socket *p1, struct sockaddr *p2, struct kextcb *p3)
+{
+       if (p3->e_fcb != NULL && g_symantec_if_funcs)
+               return g_symantec_if_funcs->sf_soconnect(p1, p2, p3);
+       else
+               return 0;
+}
+
+static int sym_fix_soisconnected(struct socket *p1, struct kextcb *p2)
+{
+       if (p2->e_fcb != NULL && g_symantec_if_funcs)
+               return g_symantec_if_funcs->sf_soisconnected(p1, p2);
+       else
+               return 0;
+}
+
+static int sym_fix_sosend(struct socket *p1, struct sockaddr **p2, struct uio **p3, struct mbuf **p4,
+                       struct mbuf **p5, int *p6, struct kextcb *p7)
+{
+       if (p7->e_fcb != NULL && g_symantec_if_funcs)
+               return g_symantec_if_funcs->sf_sosend(p1, p2, p3, p4, p5, p6, p7);
+       else
+               return 0;
+}
+
+static int sym_fix_socantrcvmore(struct socket *p1, struct kextcb *p2)
+{
+       if (p2->e_fcb != NULL && g_symantec_if_funcs)
+               return g_symantec_if_funcs->sf_socantrcvmore(p1, p2);
+       else
+               return 0;
+}
+
+static int sym_fix_socontrol(struct socket *p1, struct sockopt *p2, struct kextcb *p3)
+{
+       if (p3->e_fcb != NULL && g_symantec_if_funcs)
+               return g_symantec_if_funcs->sf_socontrol(p1, p2, p3);
+       else
+               return 0;
+}