Synopsis: mp(2) of append-only files may result in corrupted data.map(2)
NetBSD versions: 1.0, 1.1, 1.2, and 1.2.1, 1.3 and 1.3.1.
Thanks to: Luke Mewburn, Darren Reed and Matthew Green.
Reported in NetBSD Advisory: NetBSD-SA1998-003

Index: vm_mmap.c
===================================================================
RCS file: /cvsroot/src/sys/vm/vm_mmap.c,v
retrieving revision 1.56
diff -c -r1.56 vm_mmap.c
*** vm_mmap.c   1998/03/28 16:58:30     1.56
--- vm_mmap.c   1998/05/10 11:44:40
***************
*** 55,60 ****
--- 55,61 ----
 #include <sys/file.h>
 #include <sys/mman.h>
 #include <sys/conf.h>
+ #include <sys/stat.h>

 #include <sys/mount.h>
 #include <sys/syscallargs.h>
***************
*** 130,135 ****
--- 131,137 ----
               syscallarg(long) pad;
               syscallarg(off_t) pos;
       } */ *uap = v;
+       struct vattr va;
       register struct filedesc *fdp = p->p_fd;
       register struct file *fp;
       struct vnode *vp;
***************
*** 263,270 ****
               else if (prot & PROT_READ)
                       return (EACCES);
               if (flags & MAP_SHARED) {
!                       if (fp->f_flag & FWRITE)
!                               maxprot |= VM_PROT_WRITE;
                       else if (prot & PROT_WRITE)
                               return (EACCES);
               } else
--- 265,285 ----
               else if (prot & PROT_READ)
                       return (EACCES);
               if (flags & MAP_SHARED) {
!                       /*
!                        * if the file is writable, only add PROT_WRITE to
!                        * maxprot if the file is not immutable, append-only.
!                        * otherwise, if we have asked for PROT_WRITE, return
!                        * EPERM.
!                        */
!                       if (fp->f_flag & FWRITE) {
!                               if ((error =
!                                   VOP_GETATTR(vp, &va, p->p_ucred, p)))
!                                       return (error);
!                               if ((va.va_flags & (IMMUTABLE|APPEND)) == 0)
!                                       maxprot |= VM_PROT_WRITE;
!                               else if (prot & PROT_WRITE)
!                                       return (EPERM);
!                       }
                       else if (prot & PROT_WRITE)
                               return (EACCES);
               } else