[email protected]
[Top] [All Lists]

PERFORCE change 114776 for review

Subject: PERFORCE change 114776 for review
From: Jung-uk Kim
Date: Tue, 20 Feb 2007 23:42:44 GMT
http://perforce.freebsd.org/chv.cgi?CH=114776

Change 114776 by [email protected]_hammer on 2007/02/20 23:41:57

        IFC

Affected files ...

.. //depot/projects/linuxolator/src/sys/dev/iwi/if_iwi.c#8 integrate
.. //depot/projects/linuxolator/src/sys/dev/iwi/if_iwireg.h#3 integrate
.. //depot/projects/linuxolator/src/sys/dev/iwi/if_iwivar.h#3 integrate
.. //depot/projects/linuxolator/src/sys/kern/kern_jail.c#6 integrate
.. //depot/projects/linuxolator/src/sys/kern/sysv_ipc.c#4 integrate
.. //depot/projects/linuxolator/src/sys/kern/sysv_shm.c#4 integrate
.. //depot/projects/linuxolator/src/sys/kern/uipc_usrreq.c#8 integrate
.. //depot/projects/linuxolator/src/sys/net/if_ppp.c#6 integrate
.. //depot/projects/linuxolator/src/sys/netinet/tcp_input.c#8 integrate
.. //depot/projects/linuxolator/src/sys/netinet/udp.h#2 integrate
.. //depot/projects/linuxolator/src/sys/netinet/udp_usrreq.c#6 integrate
.. //depot/projects/linuxolator/src/sys/netinet/udp_var.h#2 integrate
.. //depot/projects/linuxolator/src/sys/netinet6/udp6_usrreq.c#4 integrate
.. //depot/projects/linuxolator/src/sys/security/audit/audit_arg.c#5 integrate
.. 
//depot/projects/linuxolator/src/sys/security/mac_bsdextended/mac_bsdextended.c#5
 integrate
.. //depot/projects/linuxolator/src/sys/sys/priv.h#3 integrate

Differences ...

==== //depot/projects/linuxolator/src/sys/dev/iwi/if_iwi.c#8 (text+ko) ====

@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/iwi/if_iwi.c,v 1.46 2007/02/15 17:21:31 luigi 
Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/iwi/if_iwi.c,v 1.48 2007/02/20 17:32:30 luigi 
Exp $");
 
 /*-
  * Intel(R) PRO/Wireless 2200BG/2225BG/2915ABG driver
@@ -157,6 +157,7 @@
 static int     iwi_reset(struct iwi_softc *);
 static int     iwi_load_ucode(struct iwi_softc *, const struct iwi_fw *);
 static int     iwi_load_firmware(struct iwi_softc *, const struct iwi_fw *);
+static void    iwi_release_fw_dma(struct iwi_softc *sc);
 static int     iwi_config(struct iwi_softc *);
 static int     iwi_get_firmware(struct iwi_softc *);
 static void    iwi_put_firmware(struct iwi_softc *);
@@ -331,34 +332,17 @@
                goto fail;
        }
 
-       error = iwi_alloc_tx_ring(sc, &sc->txq[0], IWI_TX_RING_COUNT,
-           IWI_CSR_TX1_RIDX, IWI_CSR_TX1_WIDX);
-       if (error != 0) {
-               device_printf(dev, "could not allocate Tx ring 1\n");
-               goto fail;
+       for (i = 0; i < 4; i++) {
+               error = iwi_alloc_tx_ring(sc, &sc->txq[i], IWI_TX_RING_COUNT,
+                   IWI_CSR_TX1_RIDX + i * 4,
+                   IWI_CSR_TX1_WIDX + i * 4);
+               if (error != 0) {
+                       device_printf(dev, "could not allocate Tx ring %d\n",
+                               i+i);
+                       goto fail;
+               }
        }
 
-       error = iwi_alloc_tx_ring(sc, &sc->txq[1], IWI_TX_RING_COUNT,
-           IWI_CSR_TX2_RIDX, IWI_CSR_TX2_WIDX);
-       if (error != 0) {
-               device_printf(dev, "could not allocate Tx ring 2\n");
-               goto fail;
-       }
-
-       error = iwi_alloc_tx_ring(sc, &sc->txq[2], IWI_TX_RING_COUNT,
-           IWI_CSR_TX3_RIDX, IWI_CSR_TX3_WIDX);
-       if (error != 0) {
-               device_printf(dev, "could not allocate Tx ring 3\n");
-               goto fail;
-       }
-
-       error = iwi_alloc_tx_ring(sc, &sc->txq[3], IWI_TX_RING_COUNT,
-           IWI_CSR_TX4_RIDX, IWI_CSR_TX4_WIDX);
-       if (error != 0) {
-               device_printf(dev, "could not allocate Tx ring 4\n");
-               goto fail;
-       }
-
        if (iwi_alloc_rx_ring(sc, &sc->rxq, IWI_RX_RING_COUNT) != 0) {
                device_printf(dev, "could not allocate Rx ring\n");
                goto fail;
@@ -496,6 +480,7 @@
                ieee80211_ifdetach(ic);
        }
        iwi_put_firmware(sc);
+       iwi_release_fw_dma(sc);
 
        iwi_free_cmd_ring(sc, &sc->cmdq);
        iwi_free_tx_ring(sc, &sc->txq[0]);
@@ -970,6 +955,7 @@
        struct ifnet *ifp = ic->ic_ifp;
        struct iwi_softc *sc = ifp->if_softc;
 
+       IWI_LOCK_CHECK(sc);
        DPRINTF(("%s: %s -> %s flags 0x%x\n", __func__,
                ieee80211_state_name[ic->ic_state],
                ieee80211_state_name[nstate], sc->flags));
@@ -1216,6 +1202,7 @@
 {
        struct ieee80211com *ic = &sc->sc_ic;
 
+       IWI_LOCK_CHECK(sc);
        ic->ic_curchan = &ic->ic_channels[chan];
        sc->curchan = chan;
 
@@ -1709,6 +1696,8 @@
 {
        struct iwi_cmd_desc *desc;
 
+       IWI_LOCK_CHECK(sc);
+
        if (sc->flags & IWI_FLAG_BUSY) {
                device_printf(sc->sc_dev, "%s: cmd %d not sent, busy\n",
                        __func__, type);
@@ -1771,6 +1760,7 @@
        int error, nsegs, hdrlen, i;
        int ismcast, flags, xflags, staid;
 
+       IWI_LOCK_CHECK(sc);
        wh = mtod(m0, const struct ieee80211_frame *);
        /* NB: only data frames use this path */
        hdrlen = ieee80211_hdrsize(wh);
@@ -2064,6 +2054,13 @@
 
        IWI_LOCK(sc);
 
+       /*
+        * wait until pending iwi_cmd() are completed, to avoid races
+        * that could cause problems.
+        */
+       while (sc->flags & IWI_FLAG_BUSY)
+               msleep(sc, &sc->sc_mtx, 0, "iwiioctl", hz);
+
        switch (cmd) {
        case SIOCSIFFLAGS:
                if (ifp->if_flags & IFF_UP) {
@@ -2080,7 +2077,6 @@
                                 */
                                sc->sc_rfkill_timer = 0;
                        }
-                       iwi_put_firmware(sc);
                }
                break;
 
@@ -2107,6 +2103,8 @@
        uint32_t tmp;
        int ntries;
 
+       IWI_LOCK_CHECK(sc);
+
        /* disable interrupts */
        CSR_WRITE_4(sc, IWI_CSR_INTR_MASK, 0);
 
@@ -2223,6 +2221,7 @@
  * This is necessary because we re-init the device sometimes
  * from a context where we cannot read from the filesystem
  * (e.g. from the taskqueue thread when rfkill is re-enabled).
+ * XXX return 0 on success, 1 on error.
  *
  * NB: the order of get'ing and put'ing images here is
  * intentional to support handling firmware images bundled
@@ -2306,33 +2305,38 @@
                /*
                 * Check and setup combined image.
                 */
-               if (fp->datasize < sizeof(hdr)) {
+               if (fp->datasize < sizeof(struct iwi_firmware_hdr)) {
                        device_printf(sc->sc_dev, "image '%s' too small\n",
                            fp->name);
                        goto bad;
                }
                hdr = (const struct iwi_firmware_hdr *)fp->data;
-               if (fp->datasize < sizeof(*hdr) + hdr->bsize + hdr->usize + 
hdr->fsize) {
+               if (fp->datasize < sizeof(*hdr) + le32toh(hdr->bsize) + 
le32toh(hdr->usize)
+                               + le32toh(hdr->fsize)) {
                        device_printf(sc->sc_dev, "image '%s' too small (2)\n",
                            fp->name);
                        goto bad;
                }
                sc->fw_boot.data = ((const char *) fp->data) + sizeof(*hdr);
-               sc->fw_boot.size = hdr->bsize;
+               sc->fw_boot.size = le32toh(hdr->bsize);
                sc->fw_boot.name = fp->name;
                sc->fw_uc.data = sc->fw_boot.data + sc->fw_boot.size;
-               sc->fw_uc.size = hdr->usize;
+               sc->fw_uc.size = le32toh(hdr->usize);
                sc->fw_uc.name = fp->name;
                sc->fw_fw.data = sc->fw_uc.data + sc->fw_uc.size;
-               sc->fw_fw.size = hdr->fsize;
+               sc->fw_fw.size = le32toh(hdr->fsize);
                sc->fw_fw.name = fp->name;
        }
+#if 0
+       device_printf(sc->sc_dev, "boot %d ucode %d fw %d bytes\n",
+               sc->fw_boot.size, sc->fw_uc.size, sc->fw_fw.size);
+#endif
 
        sc->fw_mode = ic->ic_opmode;
-       return 1;
+       return 0;
 bad:
        iwi_put_firmware(sc);
-       return 0;
+       return 1;
 }
 
 static void
@@ -2367,6 +2371,7 @@
        size_t size = fw->size;
        int i, ntries, error;
 
+       IWI_LOCK_CHECK(sc);
        error = 0;
        CSR_WRITE_4(sc, IWI_CSR_RST, CSR_READ_4(sc, IWI_CSR_RST) |
            IWI_RST_STOP_MASTER);
@@ -2439,6 +2444,7 @@
        uint32_t sentinel, ctl, src, dst, sum, len, mlen, tmp;
        int ntries, error;
 
+       IWI_LOCK_CHECK(sc);
        /* copy firmware image to DMA memory */
        memcpy(sc->fw_virtaddr, fw->data, fw->size);
 
@@ -2498,12 +2504,13 @@
                        break;
                DELAY(100);
        }
+       /* sync dma, just in case */
+       bus_dmamap_sync(sc->fw_dmat, sc->fw_map, BUS_DMASYNC_POSTWRITE);
        if (ntries == 400) {
                device_printf(sc->sc_dev,
                    "timeout processing command blocks for %s firmware\n",
                    fw->name);
-               error = EIO;
-               goto fail5;
+               return EIO;
        }
 
        /* we're done with command blocks processing */
@@ -2524,7 +2531,6 @@
                    "initialization to complete\n", fw->name);
        }
 
-fail5:
        return error;
 }
 
@@ -2580,6 +2586,7 @@
        struct iwi_txpower power;
        uint32_t data;
        int error, i;
+       IWI_LOCK_CHECK(sc);
 
        IEEE80211_ADDR_COPY(ic->ic_myaddr, IF_LLADDR(ifp));
        DPRINTF(("Setting MAC address to %6D\n", ic->ic_myaddr, ":"));
@@ -2707,6 +2714,8 @@
        struct iwi_scan_ext scan;
        int i, ix, start, scan_type, error;
 
+       IWI_LOCK_CHECK(sc);
+
        memset(&scan, 0, sizeof scan);
 
        /* XXX different dwell times for different scan types */
@@ -2908,7 +2917,8 @@
        struct iwi_rateset rs;
        uint16_t capinfo;
        int error;
-
+ 
+       IWI_LOCK_CHECK(sc);
        if (IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) {
                memset(&config, 0, sizeof config);
                config.bluetooth_coexistence = sc->bluetooth;
@@ -3077,6 +3087,66 @@
        IWI_UNLOCK(sc);
 }
 
+/*
+ * release dma resources for the firmware
+ */
+static void
+iwi_release_fw_dma(struct iwi_softc *sc)
+{
+       if (sc->fw_flags & IWI_FW_HAVE_PHY)
+               bus_dmamap_unload(sc->fw_dmat, sc->fw_map);
+       if (sc->fw_flags & IWI_FW_HAVE_MAP)
+               bus_dmamem_free(sc->fw_dmat, sc->fw_virtaddr, sc->fw_map);
+       if (sc->fw_flags & IWI_FW_HAVE_DMAT)
+               bus_dma_tag_destroy(sc->fw_dmat);
+
+       sc->fw_flags = 0;
+       sc->fw_dma_size = 0;
+       sc->fw_dmat = NULL;
+       sc->fw_map = NULL;
+       sc->fw_physaddr = 0;
+       sc->fw_virtaddr = NULL;
+}
+
+/*
+ * allocate the dma descriptor for the firmware.
+ * Return 0 on success, 1 on error.
+ * Must be called unlocked, protected by IWI_FLAG_FW_LOADING.
+ */
+static int
+iwi_init_fw_dma(struct iwi_softc *sc, int size)
+{
+       if (sc->fw_dma_size > size)
+               return 0;
+       if (bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 4, 0,
+           BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+           size, 1, size, 0, NULL, NULL, &sc->fw_dmat) != 0) {
+               device_printf(sc->sc_dev,
+                   "could not create firmware DMA tag\n");
+               goto error;
+       }
+       sc->fw_flags |= IWI_FW_HAVE_DMAT;
+       if (bus_dmamem_alloc(sc->fw_dmat, &sc->fw_virtaddr, 0,
+           &sc->fw_map) != 0) {
+               device_printf(sc->sc_dev,
+                   "could not allocate firmware DMA memory\n");
+               goto error;
+       }
+       sc->fw_flags |= IWI_FW_HAVE_MAP;
+       if (bus_dmamap_load(sc->fw_dmat, sc->fw_map, sc->fw_virtaddr,
+           size, iwi_dma_map_addr, &sc->fw_physaddr, 0) != 0) {
+               device_printf(sc->sc_dev, "could not load firmware DMA map\n");
+               goto error;
+       }
+       sc->fw_flags |= IWI_FW_HAVE_PHY;
+       sc->fw_dma_size = size;
+       return 0;
+
+error:
+       iwi_release_fw_dma(sc);
+       return 1;
+}
+
 static void
 iwi_init_locked(void *priv, int force)
 {
@@ -3087,8 +3157,11 @@
        int i;
        IWI_LOCK_DECL;
 
-       if (sc->flags & IWI_FLAG_FW_LOADING)
+       IWI_LOCK_CHECK(sc);
+       if (sc->flags & IWI_FLAG_FW_LOADING) {
+               device_printf(sc->sc_dev, "%s: already loading\n", __func__);
                return;         /* XXX: condvar? */
+       }
 
        iwi_stop(sc);
 
@@ -3100,53 +3173,34 @@
        sc->flags |= IWI_FLAG_FW_LOADING;
 
        IWI_UNLOCK(sc);
-       if (!iwi_get_firmware(sc)) {
+       if (iwi_get_firmware(sc)) {
                IWI_LOCK(sc);
                goto fail;
        }
 
        /* allocate DMA memory for mapping firmware image */
-       if (sc->fw_boot.size > sc->fw_dma_size)
-               sc->fw_dma_size = sc->fw_boot.size;
-       if (sc->fw_fw.size > sc->fw_dma_size)
-               sc->fw_dma_size = sc->fw_fw.size;
-       if (sc->fw_uc.size > sc->fw_dma_size)
-               sc->fw_dma_size = sc->fw_uc.size;
-
-       if (bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 4, 0, 
-           BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 
-           sc->fw_dma_size, 1, sc->fw_dma_size, 0, NULL, NULL, 
-           &sc->fw_dmat) != 0) {
-               device_printf(sc->sc_dev,
-                   "could not create firmware DMA tag\n");
+       i = sc->fw_fw.size;
+       if (sc->fw_boot.size > i)
+               i = sc->fw_boot.size;
+       /* XXX do we dma the ucode as well ? */
+       if (sc->fw_uc.size > i)
+               i = sc->fw_uc.size;
+       if (iwi_init_fw_dma(sc, i)) {
                IWI_LOCK(sc);
                goto fail;
        }
-       if (bus_dmamem_alloc(sc->fw_dmat, &sc->fw_virtaddr, 0,
-           &sc->fw_map) != 0) {
-               device_printf(sc->sc_dev,
-                   "could not allocate firmware DMA memory\n");
-               IWI_LOCK(sc);
-               goto fail2;
-       }
-       if (bus_dmamap_load(sc->fw_dmat, sc->fw_map, sc->fw_virtaddr,
-           sc->fw_dma_size, iwi_dma_map_addr, &sc->fw_physaddr, 0) != 0) {
-               device_printf(sc->sc_dev, "could not load firmware DMA map\n");
-               IWI_LOCK(sc);
-               goto fail3;
-       }
        IWI_LOCK(sc);
 
        if (iwi_load_firmware(sc, &sc->fw_boot) != 0) {
                device_printf(sc->sc_dev,
                    "could not load boot firmware %s\n", sc->fw_boot.name);
-               goto fail4;
+               goto fail;
        }
 
        if (iwi_load_ucode(sc, &sc->fw_uc) != 0) {
                device_printf(sc->sc_dev,
                    "could not load microcode %s\n", sc->fw_uc.name);
-               goto fail4;
+               goto fail;
        }
 
        iwi_stop_master(sc);
@@ -3181,15 +3235,10 @@
        if (iwi_load_firmware(sc, &sc->fw_fw) != 0) {
                device_printf(sc->sc_dev,
                    "could not load main firmware %s\n", sc->fw_fw.name);
-               goto fail4;
+               goto fail;
        }
        sc->flags |= IWI_FLAG_FW_INITED;
 
-       bus_dmamap_sync(sc->fw_dmat, sc->fw_map, BUS_DMASYNC_POSTWRITE);
-       bus_dmamap_unload(sc->fw_dmat, sc->fw_map);
-       bus_dmamem_free(sc->fw_dmat, sc->fw_virtaddr, sc->fw_map);
-       bus_dma_tag_destroy(sc->fw_dmat);
-
        if (iwi_config(sc) != 0) {
                device_printf(sc->sc_dev, "device configuration failed\n");
                goto fail;
@@ -3213,10 +3262,6 @@
        sc->flags &= ~IWI_FLAG_FW_LOADING;
        return;
 
-fail4: bus_dmamap_sync(sc->fw_dmat, sc->fw_map, BUS_DMASYNC_POSTWRITE);
-       bus_dmamap_unload(sc->fw_dmat, sc->fw_map);
-fail3: bus_dmamem_free(sc->fw_dmat, sc->fw_virtaddr, sc->fw_map);
-fail2: bus_dma_tag_destroy(sc->fw_dmat);
 fail:  ifp->if_flags &= ~IFF_UP;
        sc->flags &= ~IWI_FLAG_FW_LOADING;
        iwi_stop(sc);
@@ -3230,6 +3275,7 @@
        struct ieee80211com *ic = &sc->sc_ic;
        struct ifnet *ifp = ic->ic_ifp;
 
+       IWI_LOCK_CHECK(sc);     /* XXX: pretty sure this triggers */
        if (sc->sc_softled) {
                callout_stop(&sc->sc_ledtimer);
                sc->sc_blinking = 0;

==== //depot/projects/linuxolator/src/sys/dev/iwi/if_iwireg.h#3 (text+ko) ====

@@ -1,4 +1,4 @@
-/*     $FreeBSD: src/sys/dev/iwi/if_iwireg.h,v 1.13 2006/10/23 00:34:07 mlaier 
Exp $   */
+/*     $FreeBSD: src/sys/dev/iwi/if_iwireg.h,v 1.14 2007/02/20 14:29:09 luigi 
Exp $    */
 
 /*-
  * Copyright (c) 2004, 2005
@@ -134,7 +134,10 @@
 #define IWI_RATE_OFDM48        1
 #define IWI_RATE_OFDM54        3
 
-/* firmware binary image header, fields in little endian */
+/*
+ * Old version firmware images start with this header,
+ * fields are in little endian (le32) format.
+ */
 struct iwi_firmware_ohdr {
        uint32_t        version;
        uint32_t        mode;
@@ -150,6 +153,11 @@
 #define        IWI_FW_MODE_IBSS        1
 #define        IWI_FW_MODE_MONITOR     2
 
+/*
+ * New version firmware images contain boot, ucode and firmware
+ * all in one chunk. The header at the beginning gives the version
+ * and the size of each (sub)image, in le32 format.
+ */
 struct iwi_firmware_hdr {
        uint32_t        version;        /* version stamp */
        uint32_t        bsize;          /* size of boot image */

==== //depot/projects/linuxolator/src/sys/dev/iwi/if_iwivar.h#3 (text+ko) ====

@@ -1,4 +1,4 @@
-/*     $FreeBSD: src/sys/dev/iwi/if_iwivar.h,v 1.12 2007/02/15 17:21:31 luigi 
Exp $    */
+/*     $FreeBSD: src/sys/dev/iwi/if_iwivar.h,v 1.14 2007/02/20 17:32:30 luigi 
Exp $    */
 
 /*-
  * Copyright (c) 2004, 2005
@@ -149,7 +149,22 @@
        int                     mem_rid;
        int                     irq_rid;
 
+       /*
+        * The card needs external firmware images to work, which is made of a
+        * bootloader, microcode and firmware proper. In version 3.00 and
+        * above, all pieces are contained in a single image, preceded by a
+        * struct iwi_firmware_hdr indicating the size of the 3 pieces.
+        * Old firmware < 3.0 has separate boot and ucode, so we need to
+        * load all of them explicitly.
+        * To avoid issues related to fragmentation, we keep the block of
+        * dma-ble memory around until detach time, and reallocate it when
+        * it becomes too small. fw_dma_size is the size currently allocated.
+        */
        int                     fw_dma_size;
+       uint32_t                fw_flags;       /* allocation status */
+#define        IWI_FW_HAVE_DMAT        0x01
+#define        IWI_FW_HAVE_MAP         0x02
+#define        IWI_FW_HAVE_PHY         0x04
        bus_dma_tag_t           fw_dmat;
        bus_dmamap_t            fw_map;
        bus_addr_t              fw_physaddr;
@@ -216,6 +231,10 @@
  *     and must be kept in sync.
  */
 #define        IWI_LOCK_DECL   int     __waslocked = 0
+#define IWI_LOCK_CHECK(sc)     do {                            \
+       if (!mtx_owned(&(sc)->sc_mtx))  \
+               DPRINTF(("%s iwi_lock not held\n", __func__));          \
+} while (0)
 #define IWI_LOCK(sc)   do {                            \
        if (!(__waslocked = mtx_owned(&(sc)->sc_mtx)))  \
                mtx_lock(&(sc)->sc_mtx);                \

==== //depot/projects/linuxolator/src/sys/kern/kern_jail.c#6 (text+ko) ====

@@ -8,7 +8,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/kern/kern_jail.c,v 1.57 2007/02/19 13:33:09 
rwatson Exp $");
+__FBSDID("$FreeBSD: src/sys/kern/kern_jail.c,v 1.58 2007/02/20 00:12:52 
rwatson Exp $");
 
 #include "opt_mac.h"
 
@@ -596,7 +596,6 @@
                 */
        case PRIV_IPC_READ:
        case PRIV_IPC_WRITE:
-       case PRIV_IPC_EXEC:
        case PRIV_IPC_ADMIN:
        case PRIV_IPC_MSGSIZE:
        case PRIV_MQ_ADMIN:

==== //depot/projects/linuxolator/src/sys/kern/sysv_ipc.c#4 (text+ko) ====

@@ -1,8 +1,12 @@
 /*     $NetBSD: sysv_ipc.c,v 1.7 1994/06/29 06:33:11 cgd Exp $ */
 /*-
  * Copyright (c) 1994 Herb Peyerl <[email protected]>
+ * Copyright (c) 2006 nCircle Network Security, Inc.
  * All rights reserved.
  *
+ * This software was developed by Robert N. M. Watson for the TrustedBSD
+ * Project under contract to nCircle Network Security, Inc.
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -30,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/kern/sysv_ipc.c,v 1.31 2006/12/16 11:30:54 rwatson 
Exp $");
+__FBSDID("$FreeBSD: src/sys/kern/sysv_ipc.c,v 1.33 2007/02/20 00:06:59 rwatson 
Exp $");
 
 #include "opt_sysvipc.h"
 
@@ -39,6 +43,7 @@
 #include <sys/sem.h>
 #include <sys/shm.h>
 #include <sys/ipc.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/ucred.h>
 
@@ -72,50 +77,76 @@
  * Note: The MAC Framework does not require any modifications to the
  * ipcperm() function, as access control checks are performed throughout the
  * implementation of each primitive.  Those entry point calls complement the
- * ipcperm() discertionary checks.
+ * ipcperm() discertionary checks.  Unlike file system discretionary access
+ * control, the original create of an object is given the same rights as the
+ * current owner.
  */
 int
-ipcperm(td, perm, mode)
-       struct thread *td;
-       struct ipc_perm *perm;
-       int mode;
+ipcperm(struct thread *td, struct ipc_perm *perm, int acc_mode)
 {
        struct ucred *cred = td->td_ucred;
-       int error;
+       int error, obj_mode, dac_granted, priv_granted;
 
-       if (cred->cr_uid != perm->cuid && cred->cr_uid != perm->uid) {
-               /*
-                * For a non-create/owner, we require privilege to
-                * modify the object protections.  Note: some other
-                * implementations permit IPC_M to be delegated to
-                * unprivileged non-creator/owner uids/gids.
-                */
-               if (mode & IPC_M) {
-                       error = suser(td);
-                       if (error)
-                               return (error);
-               }
-               /*
-                * Try to match against creator/owner group; if not, fall
-                * back on other.
-                */
-               mode >>= 3;
-               if (!groupmember(perm->gid, cred) &&
-                   !groupmember(perm->cgid, cred))
-                       mode >>= 3;
+       dac_granted = 0;
+       if (cred->cr_uid == perm->cuid || cred->cr_uid == perm->uid) {
+               obj_mode = perm->mode;
+               dac_granted |= IPC_M;
+       } else if (groupmember(perm->gid, cred) ||
+           groupmember(perm->cgid, cred)) {
+               obj_mode = perm->mode;
+               obj_mode <<= 3;
        } else {
-               /*
-                * Always permit the creator/owner to update the object
-                * protections regardless of whether the object mode
-                * permits it.
-                */
-               if (mode & IPC_M)
-                       return (0);
+               obj_mode = perm->mode;
+               obj_mode <<= 6;
+       }
+
+       /*
+        * While the System V IPC permission model allows IPC_M to be
+        * granted, as part of the mode, our implementation requires
+        * privilege to adminster the object if not the owner or creator.
+        */
+#if 0
+       if (obj_mode & IPC_M)
+               dac_granted |= IPC_M;
+#endif
+       if (obj_mode & IPC_R)
+               dac_granted |= IPC_R;
+       if (obj_mode & IPC_W)
+               dac_granted |= IPC_W;
+
+       /*
+        * Simple case: all required rights are granted by DAC.
+        */
+       if ((dac_granted & acc_mode) == acc_mode)
+               return (0);
+
+       /*
+        * Privilege is required to satisfy the request.
+        */
+       priv_granted = 0;
+       if ((acc_mode & IPC_M) && !(dac_granted & IPC_M)) {
+               error = priv_check_cred(td->td_ucred, PRIV_IPC_ADMIN,
+                   SUSER_ALLOWJAIL);
+               if (error == 0)
+                       priv_granted |= IPC_M;
+       }
+
+       if ((acc_mode & IPC_R) && !(dac_granted & IPC_R)) {
+               error = priv_check_cred(td->td_ucred, PRIV_IPC_READ,
+                   SUSER_ALLOWJAIL);
+               if (error == 0)
+                       priv_granted |= IPC_R;
        }
 
-       if ((mode & perm->mode) != mode) {
-               if (suser(td) != 0)
-                       return (EACCES);
+       if ((acc_mode & IPC_W) && !(dac_granted & IPC_W)) {
+               error = priv_check_cred(td->td_ucred, PRIV_IPC_WRITE,
+                   SUSER_ALLOWJAIL);
+               if (error == 0)
+                       priv_granted |= IPC_W;
        }
-       return (0);
+
+       if (((dac_granted | priv_granted) & acc_mode) == acc_mode)
+               return (0);
+       else
+               return (EACCES);
 }

==== //depot/projects/linuxolator/src/sys/kern/sysv_shm.c#4 (text+ko) ====

@@ -60,7 +60,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/kern/sysv_shm.c,v 1.108 2006/10/22 11:52:13 
rwatson Exp $");
+__FBSDID("$FreeBSD: src/sys/kern/sysv_shm.c,v 1.109 2007/02/19 22:56:10 
rwatson Exp $");
 
 #include "opt_compat.h"
 #include "opt_sysvipc.h"
@@ -722,9 +722,6 @@
        if (error != 0)
                return (error);
 #endif
-       error = ipcperm(td, &shmseg->u.shm_perm, mode);
-       if (error)
-               return (error);
        if (uap->size && uap->size > shmseg->u.shm_segsz)
                return (EINVAL);
        td->td_retval[0] = IXSEQ_TO_IPCID(segnum, shmseg->u.shm_perm);

==== //depot/projects/linuxolator/src/sys/kern/uipc_usrreq.c#8 (text+ko) ====

@@ -41,12 +41,13 @@
  * connected in pairs (socketpair(2)), or bound/connected to using the file
  * system name space.  For most purposes, only the receive socket buffer is
  * used, as sending on one socket delivers directly to the receive socket
- * buffer of a second socket.  The implementation is substantially
- * complicated by the fact that "ancillary data", such as file descriptors or
- * credentials, may be passed across UNIX domain sockets.  The potential for
- * passing UNIX domain sockets over other UNIX domain sockets requires the
- * implementation of a simple garbage collector to find and tear down cycles
- * of disconnected sockets.
+ * buffer of a second socket.
+ *
+ * The implementation is substantially complicated by the fact that
+ * "ancillary data", such as file descriptors or credentials, may be passed
+ * across UNIX domain sockets.  The potential for passing UNIX domain sockets
+ * over other UNIX domain sockets requires the implementation of a simple
+ * garbage collector to find and tear down cycles of disconnected sockets.
  *
  * TODO:
  *     SEQPACKET, RDM
@@ -56,7 +57,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/kern/uipc_usrreq.c,v 1.194 2007/02/14 15:05:40 
rwatson Exp $");
+__FBSDID("$FreeBSD: src/sys/kern/uipc_usrreq.c,v 1.195 2007/02/20 10:50:02 
rwatson Exp $");
 
 #include "opt_mac.h"
 
@@ -184,7 +185,7 @@
 static int      unp_internalize(struct mbuf **, struct thread *);
 static int      unp_listen(struct socket *, struct unpcb *, int,
                   struct thread *);
-struct mbuf    *unp_addsockcred(struct thread *, struct mbuf *);
+static struct mbuf     *unp_addsockcred(struct thread *, struct mbuf *);
 
 /*
  * Definitions of protocols supported in the LOCAL domain.
@@ -461,10 +462,6 @@
        unp->unp_gencnt = ++unp_gencnt;
        --unp_count;
        if ((vp = unp->unp_vnode) != NULL) {
-               /*
-                * XXXRW: should v_socket be frobbed only while holding
-                * Giant?
-                */
                unp->unp_vnode->v_socket = NULL;
                unp->unp_vnode = NULL;
        }
@@ -1557,7 +1554,7 @@
        return (error);
 }
 
-struct mbuf *
+static struct mbuf *
 unp_addsockcred(struct thread *td, struct mbuf *control)
 {
        struct mbuf *m, *n, *n_prev;

==== //depot/projects/linuxolator/src/sys/net/if_ppp.c#6 (text+ko) ====

@@ -71,7 +71,7 @@
  * Paul Mackerras ([email protected]).
  */
 
-/* $FreeBSD: src/sys/net/if_ppp.c,v 1.119 2006/12/05 18:54:21 ume Exp $ */
+/* $FreeBSD: src/sys/net/if_ppp.c,v 1.120 2007/02/20 15:20:36 rwatson Exp $ */
 /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
 /* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */
 
@@ -719,7 +719,8 @@
         * XXXRW: Isn't this suser() check redundant to the one at the ifnet
         * layer?
         */
-       if ((error = suser(td)) != 0)
+       error = priv_check(td, PRIV_NET_SETIFMTU);
+       if (error)
            break;
        if (ifr->ifr_mtu > PPP_MAXMTU)
            error = EINVAL;

==== //depot/projects/linuxolator/src/sys/netinet/tcp_input.c#8 (text+ko) ====

@@ -27,7 +27,7 @@
  * SUCH DAMAGE.
  *
  *     @(#)tcp_input.c 8.12 (Berkeley) 5/24/95
- * $FreeBSD: src/sys/netinet/tcp_input.c,v 1.312 2007/02/01 18:32:13 andre Exp 
$
+ * $FreeBSD: src/sys/netinet/tcp_input.c,v 1.313 2007/02/20 10:20:02 rwatson 
Exp $
  */
 
 #include "opt_ipfw.h"          /* for ipfw_fwd         */
@@ -105,9 +105,9 @@
 SYSCTL_STRUCT(_net_inet_tcp, TCPCTL_STATS, stats, CTLFLAG_RW,
     &tcpstat , tcpstat, "TCP statistics (struct tcpstat, netinet/tcp_var.h)");
 
-static int log_in_vain = 0;
+static int tcp_log_in_vain = 0;
 SYSCTL_INT(_net_inet_tcp, OID_AUTO, log_in_vain, CTLFLAG_RW,
-    &log_in_vain, 0, "Log all incoming TCP connections");
+    &tcp_log_in_vain, 0, "Log all incoming TCP connections");
 
 static int blackhole = 0;
 SYSCTL_INT(_net_inet_tcp, OID_AUTO, blackhole, CTLFLAG_RW,
@@ -714,7 +714,7 @@
         * but should either do a listen or a connect soon.
         */
        if (inp == NULL) {
-               if (log_in_vain) {
+               if (tcp_log_in_vain) {
 #ifdef INET6
                        char dbuf[INET6_ADDRSTRLEN+2], sbuf[INET6_ADDRSTRLEN+2];
 #else
@@ -736,7 +736,7 @@
                                strcpy(dbuf, inet_ntoa(ip->ip_dst));
                                strcpy(sbuf, inet_ntoa(ip->ip_src));
                        }
-                       switch (log_in_vain) {
+                       switch (tcp_log_in_vain) {
                        case 1:
                                if ((thflags & TH_SYN) == 0)
                                        break;

==== //depot/projects/linuxolator/src/sys/netinet/udp.h#2 (text+ko) ====

@@ -1,6 +1,7 @@
 /*-
  * Copyright (c) 1982, 1986, 1993
- *     The Regents of the University of California.  All rights reserved.
+ *     The Regents of the University of California.
+ * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -27,14 +28,14 @@
  * SUCH DAMAGE.
  *
  *     @(#)udp.h       8.1 (Berkeley) 6/10/93
- * $FreeBSD: src/sys/netinet/udp.h,v 1.9 2005/01/07 01:45:45 imp Exp $
+ * $FreeBSD: src/sys/netinet/udp.h,v 1.10 2007/02/20 10:13:11 rwatson Exp $
  */
 
 #ifndef _NETINET_UDP_H_
-#define _NETINET_UDP_H_
+#define        _NETINET_UDP_H_
 
 /*
- * Udp protocol header.
+ * UDP protocol header.
  * Per RFC 768, September, 1981.
  */
 struct udphdr {

==== //depot/projects/linuxolator/src/sys/netinet/udp_usrreq.c#6 (text+ko) ====

@@ -1,6 +1,7 @@
 /*-
  * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
- *     The Regents of the University of California.  All rights reserved.
+ *     The Regents of the University of California.
+ * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -27,7 +28,7 @@
  * SUCH DAMAGE.
  *
  *     @(#)udp_usrreq.c        8.6 (Berkeley) 5/23/95
- * $FreeBSD: src/sys/netinet/udp_usrreq.c,v 1.200 2007/01/06 13:12:24 maxim 
Exp $
+ * $FreeBSD: src/sys/netinet/udp_usrreq.c,v 1.202 2007/02/20 10:20:02 rwatson 
Exp $
  */
 
 #include "opt_ipfw.h"
@@ -79,11 +80,11 @@
 
 #ifdef FAST_IPSEC
 #include <netipsec/ipsec.h>
-#endif /*FAST_IPSEC*/
+#endif
 
 #ifdef IPSEC
 #include <netinet6/ipsec.h>
-#endif /*IPSEC*/
+#endif
 
 #include <machine/in_cksum.h>
 
@@ -95,33 +96,28 @@
  */
 
 /*
- * BSD 4.2 defaulted the udp checksum to be off.  Turning off udp
- * checksums removes the only data integrity mechanism for packets and
- * malformed packets that would otherwise be discarded by bad checksums
- * may cause problems (especially for NFS data blocks).
+ * BSD 4.2 defaulted the udp checksum to be off.  Turning off udp checksums
+ * removes the only data integrity mechanism for packets and malformed
+ * packets that would otherwise be discarded by bad checksums may cause
+ * problems (especially for NFS data blocks).
  */
-#ifndef        COMPAT_42
 static int     udpcksum = 1;
-#else
-static int     udpcksum = 0;
-#endif
-SYSCTL_INT(_net_inet_udp, UDPCTL_CHECKSUM, checksum, CTLFLAG_RW,
-               &udpcksum, 0, "");
+SYSCTL_INT(_net_inet_udp, UDPCTL_CHECKSUM, checksum, CTLFLAG_RW, &udpcksum,
+    0, "");
 
-int    log_in_vain = 0;
+int    udp_log_in_vain = 0;
 SYSCTL_INT(_net_inet_udp, OID_AUTO, log_in_vain, CTLFLAG_RW,
-    &log_in_vain, 0, "Log all incoming UDP packets");
+    &udp_log_in_vain, 0, "Log all incoming UDP packets");
 
 static int     blackhole = 0;
-SYSCTL_INT(_net_inet_udp, OID_AUTO, blackhole, CTLFLAG_RW,
-       &blackhole, 0, "Do not send port unreachables for refused connects");
+SYSCTL_INT(_net_inet_udp, OID_AUTO, blackhole, CTLFLAG_RW, &blackhole, 0,
+    "Do not send port unreachables for refused connects");
 
 static int     strict_mcast_mship = 0;
 SYSCTL_INT(_net_inet_udp, OID_AUTO, strict_mcast_mship, CTLFLAG_RW,
-       &strict_mcast_mship, 0, "Only send multicast to member sockets");
+    &strict_mcast_mship, 0, "Only send multicast to member sockets");
 
 struct inpcbhead udb;          /* from udp_var.h */
-#define        udb6    udb  /* for KAME src sync over BSD*'s */
 struct inpcbinfo udbinfo;
 
 #ifndef UDBHASHSIZE
@@ -129,15 +125,15 @@
 #endif
 
 struct udpstat udpstat;        /* from udp_var.h */
-SYSCTL_STRUCT(_net_inet_udp, UDPCTL_STATS, stats, CTLFLAG_RW,
-    &udpstat, udpstat, "UDP statistics (struct udpstat, netinet/udp_var.h)");
+SYSCTL_STRUCT(_net_inet_udp, UDPCTL_STATS, stats, CTLFLAG_RW, &udpstat,
+    udpstat, "UDP statistics (struct udpstat, netinet/udp_var.h)");
 
-static void udp_append(struct inpcb *last, struct ip *ip, struct mbuf *n,
-               int off, struct sockaddr_in *udp_in);
+static void    udp_append(struct inpcb *last, struct ip *ip, struct mbuf *n,
+                   int off, struct sockaddr_in *udp_in);
 
-static void udp_detach(struct socket *so);
-static int udp_output(struct inpcb *, struct mbuf *, struct sockaddr *,
-               struct mbuf *, struct thread *);
+static void    udp_detach(struct socket *so);
+static int     udp_output(struct inpcb *, struct mbuf *, struct sockaddr *,
+                   struct mbuf *, struct thread *);
 
 static void
 udp_zone_change(void *tag)
@@ -163,7 +159,7 @@
        udbinfo.listhead = &udb;
        udbinfo.hashbase = hashinit(UDBHASHSIZE, M_PCB, &udbinfo.hashmask);
        udbinfo.porthashbase = hashinit(UDBHASHSIZE, M_PCB,
-                                       &udbinfo.porthashmask);
+           &udbinfo.porthashmask);
        udbinfo.ipi_zone = uma_zcreate("udpcb", sizeof(struct inpcb), NULL,
            NULL, udp_inpcb_init, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
        uma_zone_set_max(udbinfo.ipi_zone, maxsockets);
@@ -172,14 +168,12 @@
 }
 
 void
-udp_input(m, off)
-       register struct mbuf *m;
-       int off;

>>> TRUNCATED FOR MAIL (1000 lines) <<<
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/p4-projects
To unsubscribe, send any mail to "[email protected]"

<Prev in Thread] Current Thread [Next in Thread>
  • PERFORCE change 114776 for review, Jung-uk Kim <=