Synopsis: Problem with mmap(2) and many drivers.
NetBSD versions: 1.3 and 1.3.1, 1.3.2.
Thanks to: Chris Demetriou, Ted Lemon and Matthew Green.
Reported in NetBSD Advisory: NetBSD-SA1998-005
Notes: cd to src/sys and run `patch -p < thisfile' to apply.


Index: arch/alpha/pci/tga.c
===================================================================
RCS file: /cvsroot/src/sys/arch/alpha/pci/Attic/tga.c,v
retrieving revision 1.21
diff -c -r1.21 tga.c
*** tga.c       1997/09/25 01:32:04     1.21
--- tga.c       1998/11/19 14:38:15
***************
*** 401,407 ****
 {
       struct tga_softc *sc = v;

!       if (offset > sc->sc_dc->dc_tgaconf->tgac_cspace_size)
               return -1;
       return alpha_btop(sc->sc_dc->dc_paddr + offset);
 }
--- 401,407 ----
 {
       struct tga_softc *sc = v;

!       if (offset >= sc->sc_dc->dc_tgaconf->tgac_cspace_size || offset < 0)
               return -1;
       return alpha_btop(sc->sc_dc->dc_paddr + offset);
 }
Index: arch/alpha/tc/cfb.c
===================================================================
RCS file: /cvsroot/src/sys/arch/alpha/tc/cfb.c,v
retrieving revision 1.13
diff -c -r1.13 cfb.c
*** cfb.c       1997/09/25 01:32:09     1.13
--- cfb.c       1998/11/19 14:38:16
***************
*** 298,305 ****
 {
       struct cfb_softc *sc = v;

!       if (offset > CFB_SIZE)
!               return -1;
       return alpha_btop(sc->sc_dc->dc_paddr + offset);
 }

--- 298,305 ----
 {
       struct cfb_softc *sc = v;

!       if (offset >= CFB_SIZE || offset < 0)
!               return (-1);
       return alpha_btop(sc->sc_dc->dc_paddr + offset);
 }

Index: arch/alpha/tc/sfb.c
===================================================================
RCS file: /cvsroot/src/sys/arch/alpha/tc/sfb.c,v
retrieving revision 1.13
diff -c -r1.13 sfb.c
*** sfb.c       1997/09/25 01:32:12     1.13
--- sfb.c       1998/11/19 14:38:16
***************
*** 343,350 ****
 {
       struct sfb_softc *sc = v;

!       if (offset > SFB_SIZE)
!               return -1;
       return alpha_btop(sc->sc_dc->dc_paddr + offset);
 }

--- 343,350 ----
 {
       struct sfb_softc *sc = v;

!       if (offset >= SFB_SIZE || offset < 0)
!               return (-1);
       return alpha_btop(sc->sc_dc->dc_paddr + offset);
 }

Index: arch/alpha/wscons/wscons.c
===================================================================
RCS file: /cvsroot/src/sys/arch/alpha/wscons/wscons.c,v
retrieving revision 1.15
diff -c -r1.15 wscons.c
*** wscons.c    1997/09/02 13:20:58     1.15
--- wscons.c    1998/11/19 14:38:17
***************
*** 378,384 ****
 {
       struct wscons_softc *sc = wscons_cd.cd_devs[WSCUNIT(dev)];

!       if (sc->sc_ioctl != NULL)
               return (*sc->sc_mmap)(sc->sc_dev.dv_parent, offset, prot);
       else
               return -1;
--- 378,384 ----
 {
       struct wscons_softc *sc = wscons_cd.cd_devs[WSCUNIT(dev)];

!       if (sc->sc_ioctl != NULL && offset >= 0)
               return (*sc->sc_mmap)(sc->sc_dev.dv_parent, offset, prot);
       else
               return -1;
Index: arch/amiga/amiga/mem.c
===================================================================
RCS file: /cvsroot/src/sys/arch/amiga/amiga/mem.c,v
retrieving revision 1.18
diff -c -r1.18 mem.c
*** mem.c       1997/02/02 07:17:14     1.18
--- mem.c       1998/11/19 14:38:17
***************
*** 234,238 ****
       int off, prot;
 {

!       return (EOPNOTSUPP);
 }
--- 234,238 ----
       int off, prot;
 {

!       return (-1);
 }
Index: arch/arm32/arm32/mem.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arm32/arm32/mem.c,v
retrieving revision 1.3
diff -c -r1.3 mem.c
*** mem.c       1997/07/31 23:02:24     1.3
--- mem.c       1998/11/19 14:38:19
***************
*** 199,205 ****

       /* minor device 0 is physical memory */

!       if (off > ctob(physmem) &&
           suser(p->p_ucred, &p->p_acflag) != 0)
               return -1;
       return arm_byte_to_page(off);
--- 199,205 ----

       /* minor device 0 is physical memory */

!       if ((unsigned)off >= ctob(physmem) &&
           suser(p->p_ucred, &p->p_acflag) != 0)
               return -1;
       return arm_byte_to_page(off);
Index: arch/arm32/vidc/console/vidcconsole.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arm32/vidc/console/vidcconsole.c,v
retrieving revision 1.15
diff -c -r1.15 vidcconsole.c
*** vidcconsole.c       1997/10/14 11:49:19     1.15
--- vidcconsole.c       1998/11/19 14:38:30
***************
*** 807,813 ****
       int offset;
       int nprot;
 {
!       if (offset > videomemory.vidm_size)
               return (-1);
       return(arm_byte_to_page(((videomemory.vidm_pbase) + (offset))));
 }
--- 807,813 ----
       int offset;
       int nprot;
 {
!       if ((u_int)offset >= videomemory.vidm_size)
               return (-1);
       return(arm_byte_to_page(((videomemory.vidm_pbase) + (offset))));
 }
Index: arch/atari/atari/mem.c
===================================================================
RCS file: /cvsroot/src/sys/arch/atari/atari/mem.c,v
retrieving revision 1.9
diff -c -r1.9 mem.c
*** mem.c       1997/04/25 19:07:45     1.9
--- mem.c       1998/11/19 14:38:30
***************
*** 205,209 ****
       int off, prot;
 {

!       return (EOPNOTSUPP);
 }
--- 205,209 ----
       int off, prot;
 {

!       return (-1);
 }
Index: arch/bebox/bebox/mem.c
===================================================================
RCS file: /cvsroot/src/sys/arch/bebox/bebox/Attic/mem.c,v
retrieving revision 1.1
diff -c -r1.1 mem.c
*** mem.c       1997/10/14 06:47:47     1.1
--- mem.c       1998/11/19 14:38:31
***************
*** 150,154 ****
         dev_t dev;
         int off, prot;
 {
!       return EOPNOTSUPP;
 }
--- 150,154 ----
         dev_t dev;
         int off, prot;
 {
!       return -1;
 }
Index: arch/bebox/isa/pccons.c
===================================================================
RCS file: /cvsroot/src/sys/arch/bebox/isa/pccons.c,v
retrieving revision 1.1.2.1
diff -c -r1.1.2.1 pccons.c
*** pccons.c    1997/11/28 19:48:20     1.1.2.1
--- pccons.c    1998/11/19 14:38:36
***************
*** 1680,1686 ****
       int nprot;
 {

!       if (offset > 0x20000)
               return -1;
 #if 0
       return i386_btop(0xa0000 + offset);
--- 1680,1686 ----
       int nprot;
 {

!       if ((u_int)offset > 0x20000)
               return -1;
 #if 0
       return i386_btop(0xa0000 + offset);
Index: arch/hp300/hp300/mem.c
===================================================================
RCS file: /cvsroot/src/sys/arch/hp300/hp300/mem.c,v
retrieving revision 1.17
diff -c -r1.17 mem.c
*** mem.c       1997/06/10 18:51:31     1.17
--- mem.c       1998/11/19 14:38:37
***************
*** 226,232 ****
       /*
        * Allow access only in RAM.
        */
!       if ((unsigned)off < lowram || (unsigned)off >= 0xFFFFFFFC)
               return (-1);
!       return (m68k_btop(off));
 }
--- 226,232 ----
       /*
        * Allow access only in RAM.
        */
!       if ((u_int)off < lowram || (u_int)off >= 0xFFFFFFFC)
               return (-1);
!       return (m68k_btop((u_int)off));
 }
Index: arch/i386/i386/mem.c
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/i386/mem.c,v
retrieving revision 1.32
diff -c -r1.32 mem.c
*** mem.c       1997/03/24 21:16:59     1.32
--- mem.c       1998/11/19 14:38:39
***************
*** 198,207 ****
       switch (minor(dev)) {
 /* minor device 0 is physical memory */
       case 0:
!               if (off > ctob(physmem) &&
                   suser(p->p_ucred, &p->p_acflag) != 0)
                       return -1;
!               return i386_btop(off);

 /* minor device 1 is kernel memory */
       case 1:
--- 198,207 ----
       switch (minor(dev)) {
 /* minor device 0 is physical memory */
       case 0:
!               if ((u_int)off > ctob(physmem) &&
                   suser(p->p_ucred, &p->p_acflag) != 0)
                       return -1;
!               return i386_btop((u_int)off);

 /* minor device 1 is kernel memory */
       case 1:
Index: arch/i386/isa/pccons.c
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/isa/pccons.c,v
retrieving revision 1.113.2.3
diff -c -r1.113.2.3 pccons.c
*** pccons.c    1998/01/29 10:07:25     1.113.2.3
--- pccons.c    1998/11/19 14:38:42
***************
*** 2323,2329 ****
       int nprot;
 {

!       if (offset > 0x20000)
               return (-1);
       return (i386_btop(0xa0000 + offset));
 }
--- 2323,2329 ----
       int nprot;
 {

!       if ((u_int)offset > 0x20000)
               return (-1);
       return (i386_btop(0xa0000 + offset));
 }
Index: arch/i386/isa/pcvt/pcvt_drv.c
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/isa/pcvt/pcvt_drv.c,v
retrieving revision 1.40.4.1
diff -c -r1.40.4.1 pcvt_drv.c
*** pcvt_drv.c  1997/12/07 06:22:24     1.40.4.1
--- pcvt_drv.c  1998/11/19 14:38:44
***************
*** 771,777 ****
 int
 pcmmap(Dev_t dev, int offset, int nprot)
 {
!       if (offset > 0x20000)
               return -1;
       return i386_btop((0xa0000 + offset));
 }
--- 771,777 ----
 int
 pcmmap(Dev_t dev, int offset, int nprot)
 {
!       if ((u_int)offset >= 0x20000)
               return -1;
       return i386_btop((0xa0000 + offset));
 }
Index: arch/mac68k/dev/asc.c
===================================================================
RCS file: /cvsroot/src/sys/arch/mac68k/dev/Attic/asc.c,v
retrieving revision 1.24
diff -c -r1.24 asc.c
*** asc.c       1997/10/10 05:54:54     1.24
--- asc.c       1998/11/19 14:38:45
***************
*** 276,282 ****
       vm_offset_t pa;

       sc = asc_cd.cd_devs[unit];
!       if (off < MAC68K_ASC_LEN) {
               pa = pmap_extract(pmap_kernel(), (vm_offset_t)sc->sc_handle);
               return m68k_btop(pa + off);
       }
--- 276,282 ----
       vm_offset_t pa;

       sc = asc_cd.cd_devs[unit];
!       if ((u_int)off < MAC68K_ASC_LEN) {
               pa = pmap_extract(pmap_kernel(), (vm_offset_t)sc->sc_handle);
               return m68k_btop(pa + off);
       }
Index: arch/mac68k/dev/grf.c
===================================================================
RCS file: /cvsroot/src/sys/arch/mac68k/dev/grf.c,v
retrieving revision 1.45.4.1
diff -c -r1.45.4.1 grf.c
*** grf.c       1998/01/29 12:18:02     1.45.4.1
--- grf.c       1998/11/19 14:38:45
***************
*** 290,296 ****
               printf("grfmmap(%x): off %x, prot %x\n", dev, off, prot);
 #endif

!       if (off < m68k_round_page(gm->fbsize + gm->fboff))
               addr = m68k_btop((*gp->sc_phys)(gp) + off);
       else
               addr = (-1);    /* XXX bogus */
--- 290,296 ----
               printf("grfmmap(%x): off %x, prot %x\n", dev, off, prot);
 #endif

!       if (off >= 0 && off < m68k_round_page(gm->fbsize + gm->fboff))
               addr = m68k_btop((*gp->sc_phys)(gp) + off);
       else
               addr = (-1);    /* XXX bogus */
Index: arch/mips/mips/mem.c
===================================================================
RCS file: /cvsroot/src/sys/arch/mips/mips/mem.c,v
retrieving revision 1.11
diff -c -r1.11 mem.c
*** mem.c       1997/09/24 02:20:56     1.11
--- mem.c       1998/11/19 14:38:46
***************
*** 170,174 ****
       int off, prot;
 {

!       return (EOPNOTSUPP);
 }
--- 170,174 ----
       int off, prot;
 {

!       return (-1);
 }
Index: arch/mvme68k/mvme68k/mem.c
===================================================================
RCS file: /cvsroot/src/sys/arch/mvme68k/mvme68k/mem.c,v
retrieving revision 1.2
diff -c -r1.2 mem.c
*** mem.c       1997/02/02 08:27:15     1.2
--- mem.c       1998/11/19 14:38:47
***************
*** 216,222 ****
        * XXX could be extended to allow access to IO space but must
        * be very careful.
        */
!       if ((unsigned)off < lowram || (unsigned)off >= 0xFFFFFFFC)
               return (-1);
!       return (m68k_btop(off));
 }
--- 216,222 ----
        * XXX could be extended to allow access to IO space but must
        * be very careful.
        */
!       if ((u_int)off < lowram || (u_int)off >= 0xFFFFFFFC)
               return (-1);
!       return (m68k_btop((u_int)off));
 }
Index: arch/pc532/pc532/mem.c
===================================================================
RCS file: /cvsroot/src/sys/arch/pc532/pc532/mem.c,v
retrieving revision 1.15
diff -c -r1.15 mem.c
*** mem.c       1997/04/01 16:32:52     1.15
--- mem.c       1998/11/19 14:38:50
***************
*** 176,180 ****
       dev_t dev;
       int off, prot;
 {
!       return (EOPNOTSUPP);
 }
--- 176,180 ----
       dev_t dev;
       int off, prot;
 {
!       return (-1);
 }
Index: arch/pmax/dev/fb_usrreq.c
===================================================================
RCS file: /cvsroot/src/sys/arch/pmax/dev/fb_usrreq.c,v
retrieving revision 1.10
diff -c -r1.10 fb_usrreq.c
*** fb_usrreq.c 1997/06/22 07:42:30     1.10
--- fb_usrreq.c 1998/11/19 14:38:51
***************
*** 242,247 ****
--- 242,250 ----
       int len;
       register struct fbinfo *fi;

+       if (off < 0)
+               return (-1);
+
       if (minor(dev) >= fbcd.cd_ndevs ||
           (fi = fbcd.cd_devs[minor(dev)]) == NULL)
           return(-1);
Index: arch/pmax/dev/rcons.c
===================================================================
RCS file: /cvsroot/src/sys/arch/pmax/dev/rcons.c,v
retrieving revision 1.14
diff -c -r1.14 rcons.c
*** rcons.c     1996/10/13 13:14:00     1.14
--- rcons.c     1998/11/19 14:38:52
***************
*** 373,379 ****
        int off;
        int prot;
 {
!       return 0;
 }

 void
--- 373,380 ----
        int off;
        int prot;
 {
!
!       return -1;
 }

 void
Index: arch/powerpc/powerpc/mem.c
===================================================================
RCS file: /cvsroot/src/sys/arch/powerpc/powerpc/mem.c,v
retrieving revision 1.1
diff -c -r1.1 mem.c
*** mem.c       1996/09/30 16:34:50     1.1
--- mem.c       1998/11/19 14:38:52
***************
*** 150,154 ****
         dev_t dev;
         int off, prot;
 {
!       return EOPNOTSUPP;
 }
--- 150,154 ----
         dev_t dev;
         int off, prot;
 {
!       return -1;
 }
Index: arch/sparc/dev/cgeight.c
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc/dev/cgeight.c,v
retrieving revision 1.14
diff -c -r1.14 cgeight.c
*** cgeight.c   1997/10/05 18:24:32     1.14
--- cgeight.c   1998/11/19 14:38:53
***************
*** 449,455 ****
       if (off & PGOFSET)
               panic("cgeightmap");

!       if ((u_int)off >= NOOVERLAY) {
               off -= NOOVERLAY;

               /*
--- 449,457 ----
       if (off & PGOFSET)
               panic("cgeightmap");

!       if (off < 0)
!               return (-1);
!       else if ((u_int)off >= NOOVERLAY) {
               off -= NOOVERLAY;

               /*
***************
*** 457,463 ****
                * there really is. We compensate by double-mapping the
                * first page for as many other pages as it wants
                */
!               while (off >= COLOR_SIZE)
                       off -= COLOR_SIZE;      /* XXX thorpej ??? */

               poff = off + PFOUR_COLOR_OFF_COLOR;
--- 459,465 ----
                * there really is. We compensate by double-mapping the
                * first page for as many other pages as it wants
                */
!               while ((u_int)off >= COLOR_SIZE)
                       off -= COLOR_SIZE;      /* XXX thorpej ??? */

               poff = off + PFOUR_COLOR_OFF_COLOR;
Index: arch/sparc/dev/cgfour.c
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc/dev/cgfour.c,v
retrieving revision 1.14
diff -c -r1.14 cgfour.c
*** cgfour.c    1997/10/05 18:24:33     1.14
--- cgfour.c    1998/11/19 14:38:54
***************
*** 447,453 ****
       if (off & PGOFSET)
               panic("cgfourmap");

!       if ((u_int)off >= NOOVERLAY) {
               off -= NOOVERLAY;

               /*
--- 447,455 ----
       if (off & PGOFSET)
               panic("cgfourmap");

!       if (off < 0)
!               return (-1);
!       else if ((u_int)off >= NOOVERLAY) {
               off -= NOOVERLAY;

               /*
***************
*** 455,461 ****
                * there really is. We compensate by double-mapping the
                * first page for as many other pages as it wants
                */
!               while (off >= COLOR_SIZE)
                       off -= COLOR_SIZE;      /* XXX thorpej ??? */

               poff = off + PFOUR_COLOR_OFF_COLOR;
--- 457,463 ----
                * there really is. We compensate by double-mapping the
                * first page for as many other pages as it wants
                */
!               while ((u_int)off >= COLOR_SIZE)
                       off -= COLOR_SIZE;      /* XXX thorpej ??? */

               poff = off + PFOUR_COLOR_OFF_COLOR;
Index: arch/sparc/dev/cgfourteen.c
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc/dev/cgfourteen.c,v
retrieving revision 1.7
diff -c -r1.7 cgfourteen.c
*** cgfourteen.c        1997/05/24 20:16:08     1.7
--- cgfourteen.c        1998/11/19 14:38:56
***************
*** 576,581 ****
--- 576,584 ----
       if (off & PGOFSET)
               panic("cgfourteenmmap");

+       if (off < 0)
+               return (-1);
+
 #if defined(DEBUG) && defined(CG14_MAP_REGS) /* XXX: security hole */
       /*
        * Map the control registers into user space. Should only be
Index: arch/sparc/dev/cgthree.c
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc/dev/cgthree.c,v
retrieving revision 1.33
diff -c -r1.33 cgthree.c
*** cgthree.c   1997/05/24 20:16:11     1.33
--- cgthree.c   1998/11/19 14:38:57
***************
*** 437,442 ****
--- 437,444 ----

       if (off & PGOFSET)
               panic("cgthreemmap");
+       if (off < 0)
+               return (-1);
       if ((u_int)off >= NOOVERLAY)
               off -= NOOVERLAY;
       else if ((u_int)off >= START)
Index: arch/sun3/sun3/mem.c
===================================================================
RCS file: /cvsroot/src/sys/arch/sun3/sun3/mem.c,v
retrieving revision 1.26
diff -c -r1.26 mem.c
*** mem.c       1997/04/28 23:21:01     1.26
--- mem.c       1998/11/19 14:39:01
***************
*** 247,253 ****
       dev_t dev;
       int off, prot;
 {
!       register int v = off;

       /*
        * Check address validity.
--- 247,253 ----
       dev_t dev;
       int off, prot;
 {
!       register u_int v = off;

       /*
        * Check address validity.
Index: arch/sun3x/sun3x/mem.c
===================================================================
RCS file: /cvsroot/src/sys/arch/sun3x/sun3x/Attic/mem.c,v
retrieving revision 1.7
diff -c -r1.7 mem.c
*** mem.c       1997/04/25 18:46:10     1.7
--- mem.c       1998/11/19 14:39:01
***************
*** 236,242 ****
       dev_t dev;
       int off, prot;
 {
!       register int v = off;

       /*
        * Check address validity.
--- 236,242 ----
       dev_t dev;
       int off, prot;
 {
!       register u_int v = off;

       /*
        * Check address validity.
Index: arch/vax/vax/mem.c
===================================================================
RCS file: /cvsroot/src/sys/arch/vax/vax/mem.c,v
retrieving revision 1.9
diff -c -r1.9 mem.c
*** mem.c       1996/04/08 18:32:48     1.9
--- mem.c       1998/11/19 14:39:02
***************
*** 194,198 ****
       int off, prot;
 {

!       return (EOPNOTSUPP);
 }
--- 194,198 ----
       int off, prot;
 {

!       return (-1);
 }
Index: arch/x68k/x68k/mem.c
===================================================================
RCS file: /cvsroot/src/sys/arch/x68k/x68k/mem.c,v
retrieving revision 1.8
diff -c -r1.8 mem.c
*** mem.c       1997/10/10 17:43:16     1.8
--- mem.c       1998/11/19 14:39:03
***************
*** 224,230 ****
        * XXX could be extended to allow access to IO space but must
        * be very careful.
        */
!       if ((unsigned)off < lowram || (unsigned)off >= 0xFFFFFFFC)
               return (-1);
!       return (m68k_btop(off));
 }
--- 224,230 ----
        * XXX could be extended to allow access to IO space but must
        * be very careful.
        */
!       if ((u_int)off < lowram || (u_int)off >= 0xFFFFFFFC)
               return (-1);
!       return (m68k_btop((u_int)off));
 }
Index: dev/audio.c
===================================================================
RCS file: /cvsroot/src/sys/dev/audio.c,v
retrieving revision 1.77.2.1
diff -c -r1.77.2.1 audio.c
*** audio.c     1997/11/05 02:46:55     1.77.2.1
--- audio.c     1998/11/19 14:39:08
***************
*** 1648,1654 ****
       cb = &sc->sc_pr;
 #endif

!       if (off >= cb->bufsize)
               return -1;
       if (!cb->mmapped) {
               cb->mmapped = 1;
--- 1648,1654 ----
       cb = &sc->sc_pr;
 #endif

!       if ((u_int)off >= cb->bufsize)
               return -1;
       if (!cb->mmapped) {
               cb->mmapped = 1;
Index: dev/isa/isadma.c
===================================================================
RCS file: /cvsroot/src/sys/dev/isa/isadma.c,v
retrieving revision 1.32
diff -c -r1.32 isadma.c
*** isadma.c    1997/09/05 01:48:33     1.32
--- isadma.c    1998/11/19 14:39:15
***************
*** 579,584 ****
--- 579,587 ----
               panic("isa_dmamem_mmap");
       }

+       if (off < 0)
+               return (-1);
+
       seg.ds_addr = addr;
       seg.ds_len = size;