PERFORCE change 114776 for review

Jung-uk Kim jkim at FreeBSD.org
Tue Feb 20 23:42:45 UTC 2007


http://perforce.freebsd.org/chv.cgi?CH=114776

Change 114776 by jkim at jkim_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 <hpeyerl at novatel.ca>
+ * 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 (paulus at cs.anu.edu.au).
  */
 
-/* $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) <<<


More information about the p4-projects mailing list