diff options
author | David Greenman <dg@FreeBSD.org> | 1995-10-22 09:32:48 +0000 |
---|---|---|
committer | David Greenman <dg@FreeBSD.org> | 1995-10-22 09:32:48 +0000 |
commit | d68a41903e7e98eb36b24c2678dd1552fabd047a (patch) | |
tree | 67d743dd75dac0605db551f3d4f64632e50167ea | |
parent | 6928ec333033faf66d7249b94e941df99e28f031 (diff) | |
download | src-d68a41903e7e98eb36b24c2678dd1552fabd047a.tar.gz src-d68a41903e7e98eb36b24c2678dd1552fabd047a.zip |
Moved the filesystem read-only check out of the syscalls and into the
filesystem layer, as was done in lite-2. Merged in some other cosmetic
changes while I was at it. Rewrote most of msdosfs_access() to be more
like ufs_access() and to include the FS read-only check.
Obtained from: partially from 4.4BSD-lite2
Notes
Notes:
svn path=/head/; revision=11644
-rw-r--r-- | sys/fs/cd9660/cd9660_lookup.c | 5 | ||||
-rw-r--r-- | sys/fs/msdosfs/msdosfs_vnops.c | 209 | ||||
-rw-r--r-- | sys/isofs/cd9660/cd9660_lookup.c | 5 | ||||
-rw-r--r-- | sys/kern/vfs_extattr.c | 80 | ||||
-rw-r--r-- | sys/kern/vfs_lookup.c | 40 | ||||
-rw-r--r-- | sys/kern/vfs_syscalls.c | 80 | ||||
-rw-r--r-- | sys/kern/vfs_vnops.c | 15 | ||||
-rw-r--r-- | sys/msdosfs/msdosfs_vnops.c | 209 | ||||
-rw-r--r-- | sys/nfs/nfs_vnops.c | 49 | ||||
-rw-r--r-- | sys/nfsclient/nfs_vnops.c | 49 | ||||
-rw-r--r-- | sys/ufs/ufs/ufs_lookup.c | 5 | ||||
-rw-r--r-- | sys/ufs/ufs/ufs_vnops.c | 104 |
12 files changed, 446 insertions, 404 deletions
diff --git a/sys/fs/cd9660/cd9660_lookup.c b/sys/fs/cd9660/cd9660_lookup.c index e035ce03a23b..9c359d13403f 100644 --- a/sys/fs/cd9660/cd9660_lookup.c +++ b/sys/fs/cd9660/cd9660_lookup.c @@ -38,7 +38,7 @@ * from: @(#)ufs_lookup.c 7.33 (Berkeley) 5/19/91 * * @(#)cd9660_lookup.c 8.2 (Berkeley) 1/23/94 - * $Id: cd9660_lookup.c,v 1.6 1995/01/16 17:03:23 joerg Exp $ + * $Id: cd9660_lookup.c,v 1.7 1995/05/30 08:04:57 rgrimes Exp $ */ #include <sys/param.h> @@ -142,6 +142,9 @@ cd9660_lookup(ap) return (ENOTDIR); if ((error = VOP_ACCESS(vdp, VEXEC, cred, cnp->cn_proc))) return (error); + if ((flags & ISLASTCN) && (vdp->v_mount->mnt_flag & MNT_RDONLY) && + (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) + return (EROFS); /* * We now have a segment name to search for, and a directory to search. diff --git a/sys/fs/msdosfs/msdosfs_vnops.c b/sys/fs/msdosfs/msdosfs_vnops.c index e3b4a5c63493..3521f3c6bcee 100644 --- a/sys/fs/msdosfs/msdosfs_vnops.c +++ b/sys/fs/msdosfs/msdosfs_vnops.c @@ -1,4 +1,4 @@ -/* $Id: msdosfs_vnops.c,v 1.23 1995/09/04 00:20:45 dyson Exp $ */ +/* $Id: msdosfs_vnops.c,v 1.24 1995/10/07 10:14:12 bde Exp $ */ /* $NetBSD: msdosfs_vnops.c,v 1.20 1994/08/21 18:44:13 ws Exp $ */ /*- @@ -204,24 +204,42 @@ msdosfs_close(ap) return 0; } -/* - * This routine will go into sys/kern/vfs_subr.c one day! - * - * Do the usual access checking. - * file_node, uid and gid are from the vnode in question, - * while acc_mode and cred are from the VOP_ACCESS parameter list. - */ -static int -vaccess(file_mode, uid, gid, acc_mode, cred) - mode_t file_mode; - uid_t uid; - gid_t gid; - mode_t acc_mode; - struct ucred *cred; +int +msdosfs_access(ap) + struct vop_access_args /* { + struct vnode *a_vp; + int a_mode; + struct ucred *a_cred; + struct proc *a_p; + } */ *ap; { - mode_t mask; - int i; + struct vnode *vp = ap->a_vp; + struct denode *dep = VTODE(ap->a_vp); + struct msdosfsmount *pmp = dep->de_pmp; + struct ucred *cred = ap->a_cred; + mode_t mask, file_mode, mode = ap->a_mode; register gid_t *gp; + int i; + + file_mode = (S_IXUSR|S_IXGRP|S_IXOTH) | (S_IRUSR|S_IRGRP|S_IROTH) | + ((dep->de_Attributes & ATTR_READONLY) ? 0 : (S_IWUSR|S_IWGRP|S_IWOTH)); + file_mode &= pmp->pm_mask; + + /* + * Disallow write attempts on read-only file systems; + * unless the file is a socket, fifo, or a block or + * character device resident on the file system. + */ + if (mode & VWRITE) { + switch (vp->v_type) { + case VDIR: + case VLNK: + case VREG: + if (vp->v_mount->mnt_flag & MNT_RDONLY) + return (EROFS); + break; + } + } /* User id 0 always gets access. */ if (cred->cr_uid == 0) @@ -230,59 +248,39 @@ vaccess(file_mode, uid, gid, acc_mode, cred) mask = 0; /* Otherwise, check the owner. */ - if (cred->cr_uid == uid) { - if (acc_mode & VEXEC) + if (cred->cr_uid == pmp->pm_uid) { + if (mode & VEXEC) mask |= S_IXUSR; - if (acc_mode & VREAD) + if (mode & VREAD) mask |= S_IRUSR; - if (acc_mode & VWRITE) + if (mode & VWRITE) mask |= S_IWUSR; return (file_mode & mask) == mask ? 0 : EACCES; } /* Otherwise, check the groups. */ for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++) - if (gid == *gp) { - if (acc_mode & VEXEC) + if (pmp->pm_gid == *gp) { + if (mode & VEXEC) mask |= S_IXGRP; - if (acc_mode & VREAD) + if (mode & VREAD) mask |= S_IRGRP; - if (acc_mode & VWRITE) + if (mode & VWRITE) mask |= S_IWGRP; return (file_mode & mask) == mask ? 0 : EACCES; } /* Otherwise, check everyone else. */ - if (acc_mode & VEXEC) + if (mode & VEXEC) mask |= S_IXOTH; - if (acc_mode & VREAD) + if (mode & VREAD) mask |= S_IROTH; - if (acc_mode & VWRITE) + if (mode & VWRITE) mask |= S_IWOTH; return (file_mode & mask) == mask ? 0 : EACCES; } int -msdosfs_access(ap) - struct vop_access_args /* { - struct vnode *a_vp; - int a_mode; - struct ucred *a_cred; - struct proc *a_p; - } */ *ap; -{ - mode_t dosmode; - struct denode *dep = VTODE(ap->a_vp); - struct msdosfsmount *pmp = dep->de_pmp; - - dosmode = (S_IXUSR|S_IXGRP|S_IXOTH) | (S_IRUSR|S_IRGRP|S_IROTH) | - ((dep->de_Attributes & ATTR_READONLY) ? 0 : (S_IWUSR|S_IWGRP|S_IWOTH)); - dosmode &= pmp->pm_mask; - - return vaccess(dosmode, pmp->pm_uid, pmp->pm_gid, ap->a_mode, ap->a_cred); -} - -int msdosfs_getattr(ap) struct vop_getattr_args /* { struct vnode *a_vp; @@ -349,34 +347,55 @@ msdosfs_setattr(ap) struct proc *a_p; } */ *ap; { - int error = 0; + struct vnode *vp = ap->a_vp; struct denode *dep = VTODE(ap->a_vp); struct vattr *vap = ap->a_vap; struct ucred *cred = ap->a_cred; + int error = 0; -#ifdef MSDOSFS_DEBUG - printf("msdosfs_setattr(): vp %08x, vap %08x, cred %08x, p %08x\n", - ap->a_vp, vap, cred, ap->a_p); -#endif - if ((vap->va_type != VNON) || - (vap->va_nlink != VNOVAL) || - (vap->va_fsid != VNOVAL) || - (vap->va_fileid != VNOVAL) || - (vap->va_blocksize != VNOVAL) || - (vap->va_rdev != VNOVAL) || - (vap->va_bytes != VNOVAL) || - (vap->va_gen != VNOVAL)) { -#ifdef MSDOSFS_DEBUG - printf("msdosfs_setattr(): returning EINVAL\n"); - printf(" va_type %d, va_nlink %x, va_fsid %x, va_fileid %x\n", - vap->va_type, vap->va_nlink, vap->va_fsid, vap->va_fileid); - printf(" va_blocksize %x, va_rdev %x, va_bytes %x, va_gen %x\n", - vap->va_blocksize, vap->va_rdev, vap->va_bytes, vap->va_gen); -#endif - return EINVAL; + /* + * Check for unsettable attributes. + */ + if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) || + (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) || + (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) || + (vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) { + return (EINVAL); + } + if (vap->va_flags != VNOVAL) { + if (vp->v_mount->mnt_flag & MNT_RDONLY) + return (EROFS); + if (cred->cr_uid != dep->de_pmp->pm_uid && + (error = suser(cred, &ap->a_p->p_acflag))) + return (error); + /* + * We are very inconsistent about handling unsupported + * attributes. We ignored the the access time and the + * read and execute bits. We were strict for the other + * attributes. + * + * Here we are strict, stricter than ufs in not allowing + * users to attempt to set SF_SETTABLE bits or anyone to + * set unsupported bits. However, we ignore attempts to + * set ATTR_ARCHIVE for directories `cp -pr' from a more + * sensible file system attempts it a lot. + */ + if (cred->cr_uid != 0) { + if (vap->va_flags & SF_SETTABLE) + return EPERM; + } + if (vap->va_flags & ~SF_ARCHIVED) + return EINVAL; + if (vap->va_flags & SF_ARCHIVED) + dep->de_Attributes &= ~ATTR_ARCHIVE; + else if (!(dep->de_Attributes & ATTR_DIRECTORY)) + dep->de_Attributes |= ATTR_ARCHIVE; + dep->de_flag |= DE_MODIFIED; } if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (uid_t)VNOVAL) { + if (vp->v_mount->mnt_flag & MNT_RDONLY) + return (EROFS); if ((cred->cr_uid != dep->de_pmp->pm_uid || vap->va_uid != dep->de_pmp->pm_uid || (vap->va_gid != dep->de_pmp->pm_gid && @@ -388,17 +407,31 @@ msdosfs_setattr(ap) return EINVAL; } if (vap->va_size != VNOVAL) { - if (ap->a_vp->v_type == VDIR) - return EISDIR; + /* + * Disallow write attempts on read-only file systems; + * unless the file is a socket, fifo, or a block or + * character device resident on the file system. + */ + switch (vp->v_type) { + case VDIR: + return (EISDIR); + case VLNK: + case VREG: + if (vp->v_mount->mnt_flag & MNT_RDONLY) + return (EROFS); + break; + } error = detrunc(dep, vap->va_size, 0, cred, ap->a_p); if (error) return error; } if (vap->va_mtime.ts_sec != VNOVAL) { + if (vp->v_mount->mnt_flag & MNT_RDONLY) + return (EROFS); if (cred->cr_uid != dep->de_pmp->pm_uid && (error = suser(cred, &ap->a_p->p_acflag)) && ((vap->va_vaflags & VA_UTIMES_NULL) == 0 || - (error = VOP_ACCESS(ap->a_vp, VWRITE, cred, ap->a_p)))) + (error = VOP_ACCESS(vp, VWRITE, cred, ap->a_p)))) return error; dep->de_flag |= DE_UPDATE; error = deupdat(dep, &vap->va_mtime, 1); @@ -411,7 +444,10 @@ msdosfs_setattr(ap) * attribute set, so we use the owner write bit to set the readonly * attribute. */ + error = 0; if (vap->va_mode != (u_short) VNOVAL) { + if (vp->v_mount->mnt_flag & MNT_RDONLY) + return (EROFS); if (cred->cr_uid != dep->de_pmp->pm_uid && (error = suser(cred, &ap->a_p->p_acflag))) return error; @@ -423,35 +459,6 @@ msdosfs_setattr(ap) dep->de_Attributes |= ATTR_READONLY; dep->de_flag |= DE_MODIFIED; } - - if (vap->va_flags != VNOVAL) { - if (cred->cr_uid != dep->de_pmp->pm_uid && - (error = suser(cred, &ap->a_p->p_acflag))) - return error; - /* - * We are very inconsistent about handling unsupported - * attributes. We ignored the the access time and the - * read and execute bits. We were strict for the other - * attributes. - * - * Here we are strict, stricter than ufs in not allowing - * users to attempt to set SF_SETTABLE bits or anyone to - * set unsupported bits. However, we ignore attempts to - * set ATTR_ARCHIVE for directories `cp -pr' from a more - * sensible file system attempts it a lot. - */ - if (cred->cr_uid != 0) { - if (vap->va_flags & SF_SETTABLE) - return EPERM; - } - if (vap->va_flags & ~SF_ARCHIVED) - return EINVAL; - if (vap->va_flags & SF_ARCHIVED) - dep->de_Attributes &= ~ATTR_ARCHIVE; - else if (!(dep->de_Attributes & ATTR_DIRECTORY)) - dep->de_Attributes |= ATTR_ARCHIVE; - dep->de_flag |= DE_MODIFIED; - } return error; } diff --git a/sys/isofs/cd9660/cd9660_lookup.c b/sys/isofs/cd9660/cd9660_lookup.c index e035ce03a23b..9c359d13403f 100644 --- a/sys/isofs/cd9660/cd9660_lookup.c +++ b/sys/isofs/cd9660/cd9660_lookup.c @@ -38,7 +38,7 @@ * from: @(#)ufs_lookup.c 7.33 (Berkeley) 5/19/91 * * @(#)cd9660_lookup.c 8.2 (Berkeley) 1/23/94 - * $Id: cd9660_lookup.c,v 1.6 1995/01/16 17:03:23 joerg Exp $ + * $Id: cd9660_lookup.c,v 1.7 1995/05/30 08:04:57 rgrimes Exp $ */ #include <sys/param.h> @@ -142,6 +142,9 @@ cd9660_lookup(ap) return (ENOTDIR); if ((error = VOP_ACCESS(vdp, VEXEC, cred, cnp->cn_proc))) return (error); + if ((flags & ISLASTCN) && (vdp->v_mount->mnt_flag & MNT_RDONLY) && + (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) + return (EROFS); /* * We now have a segment name to search for, and a directory to search. diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c index ffee2d650499..b0cf35c39afc 100644 --- a/sys/kern/vfs_extattr.c +++ b/sys/kern/vfs_extattr.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)vfs_syscalls.c 8.13 (Berkeley) 4/15/94 - * $Id: vfs_syscalls.c,v 1.33 1995/08/28 09:18:56 julian Exp $ + * $Id: vfs_syscalls.c,v 1.34 1995/10/08 00:06:10 swallace Exp $ */ #include <sys/param.h> @@ -1395,13 +1395,9 @@ chflags(p, uap, retval) vp = nd.ni_vp; LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); VOP_LOCK(vp); - if (vp->v_mount->mnt_flag & MNT_RDONLY) - error = EROFS; - else { - VATTR_NULL(&vattr); - vattr.va_flags = uap->flags; - error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); - } + VATTR_NULL(&vattr); + vattr.va_flags = uap->flags; + error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); vput(vp); return (error); } @@ -1431,13 +1427,9 @@ fchflags(p, uap, retval) vp = (struct vnode *)fp->f_data; LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); VOP_LOCK(vp); - if (vp->v_mount->mnt_flag & MNT_RDONLY) - error = EROFS; - else { - VATTR_NULL(&vattr); - vattr.va_flags = uap->flags; - error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); - } + VATTR_NULL(&vattr); + vattr.va_flags = uap->flags; + error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); VOP_UNLOCK(vp); return (error); } @@ -1468,13 +1460,9 @@ chmod(p, uap, retval) vp = nd.ni_vp; LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); VOP_LOCK(vp); - if (vp->v_mount->mnt_flag & MNT_RDONLY) - error = EROFS; - else { - VATTR_NULL(&vattr); - vattr.va_mode = uap->mode & ALLPERMS; - error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); - } + VATTR_NULL(&vattr); + vattr.va_mode = uap->mode & ALLPERMS; + error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); vput(vp); return (error); } @@ -1504,13 +1492,9 @@ fchmod(p, uap, retval) vp = (struct vnode *)fp->f_data; LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); VOP_LOCK(vp); - if (vp->v_mount->mnt_flag & MNT_RDONLY) - error = EROFS; - else { - VATTR_NULL(&vattr); - vattr.va_mode = uap->mode & ALLPERMS; - error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); - } + VATTR_NULL(&vattr); + vattr.va_mode = uap->mode & ALLPERMS; + error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); VOP_UNLOCK(vp); return (error); } @@ -1542,14 +1526,10 @@ chown(p, uap, retval) vp = nd.ni_vp; LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); VOP_LOCK(vp); - if (vp->v_mount->mnt_flag & MNT_RDONLY) - error = EROFS; - else { - VATTR_NULL(&vattr); - vattr.va_uid = uap->uid; - vattr.va_gid = uap->gid; - error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); - } + VATTR_NULL(&vattr); + vattr.va_uid = uap->uid; + vattr.va_gid = uap->gid; + error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); vput(vp); return (error); } @@ -1580,14 +1560,10 @@ fchown(p, uap, retval) vp = (struct vnode *)fp->f_data; LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); VOP_LOCK(vp); - if (vp->v_mount->mnt_flag & MNT_RDONLY) - error = EROFS; - else { - VATTR_NULL(&vattr); - vattr.va_uid = uap->uid; - vattr.va_gid = uap->gid; - error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); - } + VATTR_NULL(&vattr); + vattr.va_uid = uap->uid; + vattr.va_gid = uap->gid; + error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); VOP_UNLOCK(vp); return (error); } @@ -1629,15 +1605,11 @@ utimes(p, uap, retval) vp = nd.ni_vp; LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); VOP_LOCK(vp); - if (vp->v_mount->mnt_flag & MNT_RDONLY) - error = EROFS; - else { - vattr.va_atime.ts_sec = tv[0].tv_sec; - vattr.va_atime.ts_nsec = tv[0].tv_usec * 1000; - vattr.va_mtime.ts_sec = tv[1].tv_sec; - vattr.va_mtime.ts_nsec = tv[1].tv_usec * 1000; - error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); - } + vattr.va_atime.ts_sec = tv[0].tv_sec; + vattr.va_atime.ts_nsec = tv[0].tv_usec * 1000; + vattr.va_mtime.ts_sec = tv[1].tv_sec; + vattr.va_mtime.ts_nsec = tv[1].tv_usec * 1000; + error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); vput(vp); return (error); } diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index 35a7a691d184..0194dd93156a 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)vfs_lookup.c 8.4 (Berkeley) 2/16/94 - * $Id: vfs_lookup.c,v 1.8 1995/07/31 00:35:46 bde Exp $ + * $Id: vfs_lookup.c,v 1.9 1995/08/24 10:16:59 dfr Exp $ */ #include <sys/param.h> @@ -422,7 +422,7 @@ unionlookup: * If creating and at end of pathname, then can consider * allowing file to be created. */ - if (rdonly || (ndp->ni_dvp->v_mount->mnt_flag & MNT_RDONLY)) { + if (rdonly) { error = EROFS; goto bad; } @@ -510,19 +510,12 @@ nextname: goto dirloop; } /* - * Check for read-only file systems. + * Disallow directory write attempts on read-only file systems. */ - if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) { - /* - * Disallow directory write attempts on read-only - * file systems. - */ - if (rdonly || (dp->v_mount->mnt_flag & MNT_RDONLY) || - (wantparent && - (ndp->ni_dvp->v_mount->mnt_flag & MNT_RDONLY))) { - error = EROFS; - goto bad2; - } + if (rdonly && + (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) { + error = EROFS; + goto bad2; } if (cnp->cn_flags & SAVESTART) { ndp->ni_startdir = ndp->ni_dvp; @@ -638,7 +631,7 @@ relookup(dvp, vpp, cnp) * If creating and at end of pathname, then can consider * allowing file to be created. */ - if (rdonly || (dvp->v_mount->mnt_flag & MNT_RDONLY)) { + if (rdonly) { error = EROFS; goto bad; } @@ -663,19 +656,12 @@ relookup(dvp, vpp, cnp) #endif /* - * Check for read-only file systems. + * Disallow directory write attempts on read-only file systems. */ - if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) { - /* - * Disallow directory write attempts on read-only - * file systems. - */ - if (rdonly || (dp->v_mount->mnt_flag & MNT_RDONLY) || - (wantparent && - (dvp->v_mount->mnt_flag & MNT_RDONLY))) { - error = EROFS; - goto bad2; - } + if (rdonly && + (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) { + error = EROFS; + goto bad2; } /* ASSERT(dvp == ndp->ni_startdir) */ if (cnp->cn_flags & SAVESTART) diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index ffee2d650499..b0cf35c39afc 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)vfs_syscalls.c 8.13 (Berkeley) 4/15/94 - * $Id: vfs_syscalls.c,v 1.33 1995/08/28 09:18:56 julian Exp $ + * $Id: vfs_syscalls.c,v 1.34 1995/10/08 00:06:10 swallace Exp $ */ #include <sys/param.h> @@ -1395,13 +1395,9 @@ chflags(p, uap, retval) vp = nd.ni_vp; LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); VOP_LOCK(vp); - if (vp->v_mount->mnt_flag & MNT_RDONLY) - error = EROFS; - else { - VATTR_NULL(&vattr); - vattr.va_flags = uap->flags; - error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); - } + VATTR_NULL(&vattr); + vattr.va_flags = uap->flags; + error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); vput(vp); return (error); } @@ -1431,13 +1427,9 @@ fchflags(p, uap, retval) vp = (struct vnode *)fp->f_data; LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); VOP_LOCK(vp); - if (vp->v_mount->mnt_flag & MNT_RDONLY) - error = EROFS; - else { - VATTR_NULL(&vattr); - vattr.va_flags = uap->flags; - error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); - } + VATTR_NULL(&vattr); + vattr.va_flags = uap->flags; + error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); VOP_UNLOCK(vp); return (error); } @@ -1468,13 +1460,9 @@ chmod(p, uap, retval) vp = nd.ni_vp; LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); VOP_LOCK(vp); - if (vp->v_mount->mnt_flag & MNT_RDONLY) - error = EROFS; - else { - VATTR_NULL(&vattr); - vattr.va_mode = uap->mode & ALLPERMS; - error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); - } + VATTR_NULL(&vattr); + vattr.va_mode = uap->mode & ALLPERMS; + error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); vput(vp); return (error); } @@ -1504,13 +1492,9 @@ fchmod(p, uap, retval) vp = (struct vnode *)fp->f_data; LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); VOP_LOCK(vp); - if (vp->v_mount->mnt_flag & MNT_RDONLY) - error = EROFS; - else { - VATTR_NULL(&vattr); - vattr.va_mode = uap->mode & ALLPERMS; - error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); - } + VATTR_NULL(&vattr); + vattr.va_mode = uap->mode & ALLPERMS; + error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); VOP_UNLOCK(vp); return (error); } @@ -1542,14 +1526,10 @@ chown(p, uap, retval) vp = nd.ni_vp; LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); VOP_LOCK(vp); - if (vp->v_mount->mnt_flag & MNT_RDONLY) - error = EROFS; - else { - VATTR_NULL(&vattr); - vattr.va_uid = uap->uid; - vattr.va_gid = uap->gid; - error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); - } + VATTR_NULL(&vattr); + vattr.va_uid = uap->uid; + vattr.va_gid = uap->gid; + error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); vput(vp); return (error); } @@ -1580,14 +1560,10 @@ fchown(p, uap, retval) vp = (struct vnode *)fp->f_data; LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); VOP_LOCK(vp); - if (vp->v_mount->mnt_flag & MNT_RDONLY) - error = EROFS; - else { - VATTR_NULL(&vattr); - vattr.va_uid = uap->uid; - vattr.va_gid = uap->gid; - error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); - } + VATTR_NULL(&vattr); + vattr.va_uid = uap->uid; + vattr.va_gid = uap->gid; + error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); VOP_UNLOCK(vp); return (error); } @@ -1629,15 +1605,11 @@ utimes(p, uap, retval) vp = nd.ni_vp; LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); VOP_LOCK(vp); - if (vp->v_mount->mnt_flag & MNT_RDONLY) - error = EROFS; - else { - vattr.va_atime.ts_sec = tv[0].tv_sec; - vattr.va_atime.ts_nsec = tv[0].tv_usec * 1000; - vattr.va_mtime.ts_sec = tv[1].tv_sec; - vattr.va_mtime.ts_nsec = tv[1].tv_usec * 1000; - error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); - } + vattr.va_atime.ts_sec = tv[0].tv_sec; + vattr.va_atime.ts_nsec = tv[0].tv_usec * 1000; + vattr.va_mtime.ts_sec = tv[1].tv_sec; + vattr.va_mtime.ts_nsec = tv[1].tv_usec * 1000; + error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); vput(vp); return (error); } diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index a2cc2f714d41..46e897f70092 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)vfs_vnops.c 8.2 (Berkeley) 1/21/94 - * $Id: vfs_vnops.c,v 1.17 1995/07/20 09:43:04 davidg Exp $ + * $Id: vfs_vnops.c,v 1.18 1995/10/06 09:43:32 phk Exp $ */ #include <sys/param.h> @@ -194,19 +194,6 @@ vn_writechk(vp) { /* - * Disallow write attempts on read-only file systems; - * unless the file is a socket or a block or character - * device resident on the file system. - */ - if (vp->v_mount->mnt_flag & MNT_RDONLY) { - switch (vp->v_type) { - case VREG: case VDIR: case VLNK: - return (EROFS); - default: - break; - } - } - /* * If there's shared text associated with * the vnode, try to free it up once. If * we fail, we can't allow writing. diff --git a/sys/msdosfs/msdosfs_vnops.c b/sys/msdosfs/msdosfs_vnops.c index e3b4a5c63493..3521f3c6bcee 100644 --- a/sys/msdosfs/msdosfs_vnops.c +++ b/sys/msdosfs/msdosfs_vnops.c @@ -1,4 +1,4 @@ -/* $Id: msdosfs_vnops.c,v 1.23 1995/09/04 00:20:45 dyson Exp $ */ +/* $Id: msdosfs_vnops.c,v 1.24 1995/10/07 10:14:12 bde Exp $ */ /* $NetBSD: msdosfs_vnops.c,v 1.20 1994/08/21 18:44:13 ws Exp $ */ /*- @@ -204,24 +204,42 @@ msdosfs_close(ap) return 0; } -/* - * This routine will go into sys/kern/vfs_subr.c one day! - * - * Do the usual access checking. - * file_node, uid and gid are from the vnode in question, - * while acc_mode and cred are from the VOP_ACCESS parameter list. - */ -static int -vaccess(file_mode, uid, gid, acc_mode, cred) - mode_t file_mode; - uid_t uid; - gid_t gid; - mode_t acc_mode; - struct ucred *cred; +int +msdosfs_access(ap) + struct vop_access_args /* { + struct vnode *a_vp; + int a_mode; + struct ucred *a_cred; + struct proc *a_p; + } */ *ap; { - mode_t mask; - int i; + struct vnode *vp = ap->a_vp; + struct denode *dep = VTODE(ap->a_vp); + struct msdosfsmount *pmp = dep->de_pmp; + struct ucred *cred = ap->a_cred; + mode_t mask, file_mode, mode = ap->a_mode; register gid_t *gp; + int i; + + file_mode = (S_IXUSR|S_IXGRP|S_IXOTH) | (S_IRUSR|S_IRGRP|S_IROTH) | + ((dep->de_Attributes & ATTR_READONLY) ? 0 : (S_IWUSR|S_IWGRP|S_IWOTH)); + file_mode &= pmp->pm_mask; + + /* + * Disallow write attempts on read-only file systems; + * unless the file is a socket, fifo, or a block or + * character device resident on the file system. + */ + if (mode & VWRITE) { + switch (vp->v_type) { + case VDIR: + case VLNK: + case VREG: + if (vp->v_mount->mnt_flag & MNT_RDONLY) + return (EROFS); + break; + } + } /* User id 0 always gets access. */ if (cred->cr_uid == 0) @@ -230,59 +248,39 @@ vaccess(file_mode, uid, gid, acc_mode, cred) mask = 0; /* Otherwise, check the owner. */ - if (cred->cr_uid == uid) { - if (acc_mode & VEXEC) + if (cred->cr_uid == pmp->pm_uid) { + if (mode & VEXEC) mask |= S_IXUSR; - if (acc_mode & VREAD) + if (mode & VREAD) mask |= S_IRUSR; - if (acc_mode & VWRITE) + if (mode & VWRITE) mask |= S_IWUSR; return (file_mode & mask) == mask ? 0 : EACCES; } /* Otherwise, check the groups. */ for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++) - if (gid == *gp) { - if (acc_mode & VEXEC) + if (pmp->pm_gid == *gp) { + if (mode & VEXEC) mask |= S_IXGRP; - if (acc_mode & VREAD) + if (mode & VREAD) mask |= S_IRGRP; - if (acc_mode & VWRITE) + if (mode & VWRITE) mask |= S_IWGRP; return (file_mode & mask) == mask ? 0 : EACCES; } /* Otherwise, check everyone else. */ - if (acc_mode & VEXEC) + if (mode & VEXEC) mask |= S_IXOTH; - if (acc_mode & VREAD) + if (mode & VREAD) mask |= S_IROTH; - if (acc_mode & VWRITE) + if (mode & VWRITE) mask |= S_IWOTH; return (file_mode & mask) == mask ? 0 : EACCES; } int -msdosfs_access(ap) - struct vop_access_args /* { - struct vnode *a_vp; - int a_mode; - struct ucred *a_cred; - struct proc *a_p; - } */ *ap; -{ - mode_t dosmode; - struct denode *dep = VTODE(ap->a_vp); - struct msdosfsmount *pmp = dep->de_pmp; - - dosmode = (S_IXUSR|S_IXGRP|S_IXOTH) | (S_IRUSR|S_IRGRP|S_IROTH) | - ((dep->de_Attributes & ATTR_READONLY) ? 0 : (S_IWUSR|S_IWGRP|S_IWOTH)); - dosmode &= pmp->pm_mask; - - return vaccess(dosmode, pmp->pm_uid, pmp->pm_gid, ap->a_mode, ap->a_cred); -} - -int msdosfs_getattr(ap) struct vop_getattr_args /* { struct vnode *a_vp; @@ -349,34 +347,55 @@ msdosfs_setattr(ap) struct proc *a_p; } */ *ap; { - int error = 0; + struct vnode *vp = ap->a_vp; struct denode *dep = VTODE(ap->a_vp); struct vattr *vap = ap->a_vap; struct ucred *cred = ap->a_cred; + int error = 0; -#ifdef MSDOSFS_DEBUG - printf("msdosfs_setattr(): vp %08x, vap %08x, cred %08x, p %08x\n", - ap->a_vp, vap, cred, ap->a_p); -#endif - if ((vap->va_type != VNON) || - (vap->va_nlink != VNOVAL) || - (vap->va_fsid != VNOVAL) || - (vap->va_fileid != VNOVAL) || - (vap->va_blocksize != VNOVAL) || - (vap->va_rdev != VNOVAL) || - (vap->va_bytes != VNOVAL) || - (vap->va_gen != VNOVAL)) { -#ifdef MSDOSFS_DEBUG - printf("msdosfs_setattr(): returning EINVAL\n"); - printf(" va_type %d, va_nlink %x, va_fsid %x, va_fileid %x\n", - vap->va_type, vap->va_nlink, vap->va_fsid, vap->va_fileid); - printf(" va_blocksize %x, va_rdev %x, va_bytes %x, va_gen %x\n", - vap->va_blocksize, vap->va_rdev, vap->va_bytes, vap->va_gen); -#endif - return EINVAL; + /* + * Check for unsettable attributes. + */ + if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) || + (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) || + (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) || + (vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) { + return (EINVAL); + } + if (vap->va_flags != VNOVAL) { + if (vp->v_mount->mnt_flag & MNT_RDONLY) + return (EROFS); + if (cred->cr_uid != dep->de_pmp->pm_uid && + (error = suser(cred, &ap->a_p->p_acflag))) + return (error); + /* + * We are very inconsistent about handling unsupported + * attributes. We ignored the the access time and the + * read and execute bits. We were strict for the other + * attributes. + * + * Here we are strict, stricter than ufs in not allowing + * users to attempt to set SF_SETTABLE bits or anyone to + * set unsupported bits. However, we ignore attempts to + * set ATTR_ARCHIVE for directories `cp -pr' from a more + * sensible file system attempts it a lot. + */ + if (cred->cr_uid != 0) { + if (vap->va_flags & SF_SETTABLE) + return EPERM; + } + if (vap->va_flags & ~SF_ARCHIVED) + return EINVAL; + if (vap->va_flags & SF_ARCHIVED) + dep->de_Attributes &= ~ATTR_ARCHIVE; + else if (!(dep->de_Attributes & ATTR_DIRECTORY)) + dep->de_Attributes |= ATTR_ARCHIVE; + dep->de_flag |= DE_MODIFIED; } if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (uid_t)VNOVAL) { + if (vp->v_mount->mnt_flag & MNT_RDONLY) + return (EROFS); if ((cred->cr_uid != dep->de_pmp->pm_uid || vap->va_uid != dep->de_pmp->pm_uid || (vap->va_gid != dep->de_pmp->pm_gid && @@ -388,17 +407,31 @@ msdosfs_setattr(ap) return EINVAL; } if (vap->va_size != VNOVAL) { - if (ap->a_vp->v_type == VDIR) - return EISDIR; + /* + * Disallow write attempts on read-only file systems; + * unless the file is a socket, fifo, or a block or + * character device resident on the file system. + */ + switch (vp->v_type) { + case VDIR: + return (EISDIR); + case VLNK: + case VREG: + if (vp->v_mount->mnt_flag & MNT_RDONLY) + return (EROFS); + break; + } error = detrunc(dep, vap->va_size, 0, cred, ap->a_p); if (error) return error; } if (vap->va_mtime.ts_sec != VNOVAL) { + if (vp->v_mount->mnt_flag & MNT_RDONLY) + return (EROFS); if (cred->cr_uid != dep->de_pmp->pm_uid && (error = suser(cred, &ap->a_p->p_acflag)) && ((vap->va_vaflags & VA_UTIMES_NULL) == 0 || - (error = VOP_ACCESS(ap->a_vp, VWRITE, cred, ap->a_p)))) + (error = VOP_ACCESS(vp, VWRITE, cred, ap->a_p)))) return error; dep->de_flag |= DE_UPDATE; error = deupdat(dep, &vap->va_mtime, 1); @@ -411,7 +444,10 @@ msdosfs_setattr(ap) * attribute set, so we use the owner write bit to set the readonly * attribute. */ + error = 0; if (vap->va_mode != (u_short) VNOVAL) { + if (vp->v_mount->mnt_flag & MNT_RDONLY) + return (EROFS); if (cred->cr_uid != dep->de_pmp->pm_uid && (error = suser(cred, &ap->a_p->p_acflag))) return error; @@ -423,35 +459,6 @@ msdosfs_setattr(ap) dep->de_Attributes |= ATTR_READONLY; dep->de_flag |= DE_MODIFIED; } - - if (vap->va_flags != VNOVAL) { - if (cred->cr_uid != dep->de_pmp->pm_uid && - (error = suser(cred, &ap->a_p->p_acflag))) - return error; - /* - * We are very inconsistent about handling unsupported - * attributes. We ignored the the access time and the - * read and execute bits. We were strict for the other - * attributes. - * - * Here we are strict, stricter than ufs in not allowing - * users to attempt to set SF_SETTABLE bits or anyone to - * set unsupported bits. However, we ignore attempts to - * set ATTR_ARCHIVE for directories `cp -pr' from a more - * sensible file system attempts it a lot. - */ - if (cred->cr_uid != 0) { - if (vap->va_flags & SF_SETTABLE) - return EPERM; - } - if (vap->va_flags & ~SF_ARCHIVED) - return EINVAL; - if (vap->va_flags & SF_ARCHIVED) - dep->de_Attributes &= ~ATTR_ARCHIVE; - else if (!(dep->de_Attributes & ATTR_DIRECTORY)) - dep->de_Attributes |= ATTR_ARCHIVE; - dep->de_flag |= DE_MODIFIED; - } return error; } diff --git a/sys/nfs/nfs_vnops.c b/sys/nfs/nfs_vnops.c index 5b25d3088193..41f27fb73ea1 100644 --- a/sys/nfs/nfs_vnops.c +++ b/sys/nfs/nfs_vnops.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * @(#)nfs_vnops.c 8.5 (Berkeley) 2/13/94 - * $Id: nfs_vnops.c,v 1.23 1995/08/01 18:50:59 davidg Exp $ + * $Id: nfs_vnops.c,v 1.24 1995/09/04 00:20:50 dyson Exp $ */ /* @@ -330,6 +330,17 @@ nfs_access(ap) int v3 = NFS_ISV3(vp); /* + * Disallow write attempts on filesystems mounted read-only; + * unless the file is a socket, fifo, or a block or character + * device resident on the filesystem. + */ + if ((ap->a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) { + switch (vp->v_type) { + case VREG: case VDIR: case VLNK: + return (EROFS); + } + } + /* * For nfs v3, do an access rpc, otherwise you are stuck emulating * ufs_access() locally using the vattr. This may not be correct, * since the server may apply other access criteria such as @@ -430,7 +441,6 @@ nfs_open(ap) if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 1)) == EINTR) return (error); - /* (void) vnode_pager_uncache(vp); */ np->n_attrstamp = 0; if (vp->v_type == VDIR) np->n_direofoffset = 0; @@ -448,7 +458,6 @@ nfs_open(ap) if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 1)) == EINTR) return (error); - /* (void) vnode_pager_uncache(vp); */ np->n_mtime = vattr.va_mtime.ts_sec; } } @@ -585,6 +594,14 @@ nfs_setattr(ap) #ifndef nolint tsize = (u_quad_t)0; #endif + /* + * Disallow write attempts if the filesystem is mounted read-only. + */ + if ((vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL || + vap->va_gid != (gid_t)VNOVAL || vap->va_atime.ts_sec != VNOVAL || + vap->va_mtime.ts_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) && + (vp->v_mount->mnt_flag & MNT_RDONLY)) + return (EROFS); if (vap->va_size != VNOVAL) { switch (vp->v_type) { case VDIR: @@ -600,6 +617,12 @@ nfs_setattr(ap) vap->va_size = VNOVAL; break; default: + /* + * Disallow write attempts if the filesystem is + * mounted read-only. + */ + if (vp->v_mount->mnt_flag & MNT_RDONLY) + return (EROFS); if (vap->va_size == 0) error = nfs_vinvalbuf(vp, 0, ap->a_cred, ap->a_p, 1); @@ -768,6 +791,9 @@ nfs_lookup(ap) int lockparent, wantparent, error = 0, attrflag, fhsize; int v3 = NFS_ISV3(dvp); + if ((flags & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) && + (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) + return (EROFS); *vpp = NULLVP; if (dvp->v_type != VDIR) return (ENOTDIR); @@ -908,7 +934,10 @@ nfs_lookup(ap) (flags & ISLASTCN) && error == ENOENT) { if (!lockparent) VOP_UNLOCK(dvp); - error = EJUSTRETURN; + if (dvp->v_mount->mnt_flag & MNT_RDONLY) + error = EROFS; + else + error = EJUSTRETURN; } if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) cnp->cn_flags |= SAVENAME; @@ -3131,12 +3160,24 @@ nfsspec_access(ap) register struct vattr *vap; register gid_t *gp; register struct ucred *cred = ap->a_cred; + struct vnode *vp = ap->a_vp; mode_t mode = ap->a_mode; struct vattr vattr; register int i; int error; /* + * Disallow write attempts on filesystems mounted read-only; + * unless the file is a socket, fifo, or a block or character + * device resident on the filesystem. + */ + if ((mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) { + switch (vp->v_type) { + case VREG: case VDIR: case VLNK: + return (EROFS); + } + } + /* * If you're the super-user, * you always get access. */ diff --git a/sys/nfsclient/nfs_vnops.c b/sys/nfsclient/nfs_vnops.c index 5b25d3088193..41f27fb73ea1 100644 --- a/sys/nfsclient/nfs_vnops.c +++ b/sys/nfsclient/nfs_vnops.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * @(#)nfs_vnops.c 8.5 (Berkeley) 2/13/94 - * $Id: nfs_vnops.c,v 1.23 1995/08/01 18:50:59 davidg Exp $ + * $Id: nfs_vnops.c,v 1.24 1995/09/04 00:20:50 dyson Exp $ */ /* @@ -330,6 +330,17 @@ nfs_access(ap) int v3 = NFS_ISV3(vp); /* + * Disallow write attempts on filesystems mounted read-only; + * unless the file is a socket, fifo, or a block or character + * device resident on the filesystem. + */ + if ((ap->a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) { + switch (vp->v_type) { + case VREG: case VDIR: case VLNK: + return (EROFS); + } + } + /* * For nfs v3, do an access rpc, otherwise you are stuck emulating * ufs_access() locally using the vattr. This may not be correct, * since the server may apply other access criteria such as @@ -430,7 +441,6 @@ nfs_open(ap) if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 1)) == EINTR) return (error); - /* (void) vnode_pager_uncache(vp); */ np->n_attrstamp = 0; if (vp->v_type == VDIR) np->n_direofoffset = 0; @@ -448,7 +458,6 @@ nfs_open(ap) if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 1)) == EINTR) return (error); - /* (void) vnode_pager_uncache(vp); */ np->n_mtime = vattr.va_mtime.ts_sec; } } @@ -585,6 +594,14 @@ nfs_setattr(ap) #ifndef nolint tsize = (u_quad_t)0; #endif + /* + * Disallow write attempts if the filesystem is mounted read-only. + */ + if ((vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL || + vap->va_gid != (gid_t)VNOVAL || vap->va_atime.ts_sec != VNOVAL || + vap->va_mtime.ts_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) && + (vp->v_mount->mnt_flag & MNT_RDONLY)) + return (EROFS); if (vap->va_size != VNOVAL) { switch (vp->v_type) { case VDIR: @@ -600,6 +617,12 @@ nfs_setattr(ap) vap->va_size = VNOVAL; break; default: + /* + * Disallow write attempts if the filesystem is + * mounted read-only. + */ + if (vp->v_mount->mnt_flag & MNT_RDONLY) + return (EROFS); if (vap->va_size == 0) error = nfs_vinvalbuf(vp, 0, ap->a_cred, ap->a_p, 1); @@ -768,6 +791,9 @@ nfs_lookup(ap) int lockparent, wantparent, error = 0, attrflag, fhsize; int v3 = NFS_ISV3(dvp); + if ((flags & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) && + (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) + return (EROFS); *vpp = NULLVP; if (dvp->v_type != VDIR) return (ENOTDIR); @@ -908,7 +934,10 @@ nfs_lookup(ap) (flags & ISLASTCN) && error == ENOENT) { if (!lockparent) VOP_UNLOCK(dvp); - error = EJUSTRETURN; + if (dvp->v_mount->mnt_flag & MNT_RDONLY) + error = EROFS; + else + error = EJUSTRETURN; } if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) cnp->cn_flags |= SAVENAME; @@ -3131,12 +3160,24 @@ nfsspec_access(ap) register struct vattr *vap; register gid_t *gp; register struct ucred *cred = ap->a_cred; + struct vnode *vp = ap->a_vp; mode_t mode = ap->a_mode; struct vattr vattr; register int i; int error; /* + * Disallow write attempts on filesystems mounted read-only; + * unless the file is a socket, fifo, or a block or character + * device resident on the filesystem. + */ + if ((mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) { + switch (vp->v_type) { + case VREG: case VDIR: case VLNK: + return (EROFS); + } + } + /* * If you're the super-user, * you always get access. */ diff --git a/sys/ufs/ufs/ufs_lookup.c b/sys/ufs/ufs/ufs_lookup.c index f8e943607d2c..9020e47e9674 100644 --- a/sys/ufs/ufs/ufs_lookup.c +++ b/sys/ufs/ufs/ufs_lookup.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)ufs_lookup.c 8.6 (Berkeley) 4/1/94 - * $Id: ufs_lookup.c,v 1.5 1995/08/28 09:19:16 julian Exp $ + * $Id: ufs_lookup.c,v 1.6 1995/10/06 09:56:51 phk Exp $ */ #include <sys/param.h> @@ -145,6 +145,9 @@ ufs_lookup(ap) error = VOP_ACCESS(vdp, VEXEC, cred, cnp->cn_proc); if (error) return (error); + if ((flags & ISLASTCN) && (vdp->v_mount->mnt_flag & MNT_RDONLY) && + (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) + return (EROFS); /* * We now have a segment name to search for, and a directory to search. diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c index 958fdd1f1a95..ae3cb2fd329b 100644 --- a/sys/ufs/ufs/ufs_vnops.c +++ b/sys/ufs/ufs/ufs_vnops.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)ufs_vnops.c 8.10 (Berkeley) 4/1/94 - * $Id: ufs_vnops.c,v 1.29 1995/09/09 01:43:49 julian Exp $ + * $Id: ufs_vnops.c,v 1.30 1995/10/07 10:13:41 bde Exp $ */ #include <sys/param.h> @@ -122,9 +122,9 @@ ufs_mknod(ap) struct vattr *a_vap; } */ *ap; { - register struct vattr *vap = ap->a_vap; - register struct vnode **vpp = ap->a_vpp; - register struct inode *ip; + struct vattr *vap = ap->a_vap; + struct vnode **vpp = ap->a_vpp; + struct inode *ip; int error; error = ufs_makeinode(MAKEIMODE(vap->va_type, vap->va_mode), @@ -209,33 +209,32 @@ ufs_access(ap) struct proc *a_p; } */ *ap; { - register struct vnode *vp = ap->a_vp; - register struct inode *ip = VTOI(vp); - register struct ucred *cred = ap->a_cred; + struct vnode *vp = ap->a_vp; + struct inode *ip = VTOI(vp); + struct ucred *cred = ap->a_cred; mode_t mask, mode = ap->a_mode; register gid_t *gp; - int i; -#ifdef QUOTA - int error; -#endif + int i, error; -#ifdef DIAGNOSTIC - if (!VOP_ISLOCKED(vp)) { - vprint("ufs_access: not locked", vp); - panic("ufs_access: not locked"); - } -#endif -#ifdef QUOTA - if (mode & VWRITE) + /* + * Disallow write attempts on read-only file systems; + * unless the file is a socket, fifo, or a block or + * character device resident on the file system. + */ + if (mode & VWRITE) { switch (vp->v_type) { case VDIR: case VLNK: case VREG: + if (vp->v_mount->mnt_flag & MNT_RDONLY) + return (EROFS); +#ifdef QUOTA if (error = getinoquota(ip)) return (error); +#endif break; } -#endif + } /* If immutable bit set, nobody gets to write it. */ if ((mode & VWRITE) && (ip->i_flags & IMMUTABLE)) @@ -336,11 +335,11 @@ ufs_setattr(ap) struct proc *a_p; } */ *ap; { - register struct vattr *vap = ap->a_vap; - register struct vnode *vp = ap->a_vp; - register struct inode *ip = VTOI(vp); - register struct ucred *cred = ap->a_cred; - register struct proc *p = ap->a_p; + struct vattr *vap = ap->a_vap; + struct vnode *vp = ap->a_vp; + struct inode *ip = VTOI(vp); + struct ucred *cred = ap->a_cred; + struct proc *p = ap->a_p; struct timeval atimeval, mtimeval; int error; @@ -354,6 +353,8 @@ ufs_setattr(ap) return (EINVAL); } if (vap->va_flags != VNOVAL) { + if (vp->v_mount->mnt_flag & MNT_RDONLY) + return (EROFS); if (cred->cr_uid != ip->i_uid && (error = suser(cred, &p->p_acflag))) return (error); @@ -378,19 +379,35 @@ ufs_setattr(ap) * Go through the fields and update iff not VNOVAL. */ if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) { + if (vp->v_mount->mnt_flag & MNT_RDONLY) + return (EROFS); error = ufs_chown(vp, vap->va_uid, vap->va_gid, cred, p); if (error) return (error); } if (vap->va_size != VNOVAL) { - if (vp->v_type == VDIR) + /* + * Disallow write attempts on read-only file systems; + * unless the file is a socket, fifo, or a block or + * character device resident on the file system. + */ + switch (vp->v_type) { + case VDIR: return (EISDIR); + case VLNK: + case VREG: + if (vp->v_mount->mnt_flag & MNT_RDONLY) + return (EROFS); + break; + } error = VOP_TRUNCATE(vp, vap->va_size, 0, cred, p); if (error) return (error); } ip = VTOI(vp); if (vap->va_atime.ts_sec != VNOVAL || vap->va_mtime.ts_sec != VNOVAL) { + if (vp->v_mount->mnt_flag & MNT_RDONLY) + return (EROFS); if (cred->cr_uid != ip->i_uid && (error = suser(cred, &p->p_acflag)) && ((vap->va_vaflags & VA_UTIMES_NULL) == 0 || @@ -409,8 +426,11 @@ ufs_setattr(ap) return (error); } error = 0; - if (vap->va_mode != (mode_t)VNOVAL) + if (vap->va_mode != (mode_t)VNOVAL) { + if (vp->v_mount->mnt_flag & MNT_RDONLY) + return (EROFS); error = ufs_chmod(vp, (int)vap->va_mode, cred, p); + } return (error); } @@ -636,9 +656,9 @@ ufs_remove(ap) struct componentname *a_cnp; } */ *ap; { - register struct inode *ip; - register struct vnode *vp = ap->a_vp; - register struct vnode *dvp = ap->a_dvp; + struct inode *ip; + struct vnode *vp = ap->a_vp; + struct vnode *dvp = ap->a_dvp; int error; ip = VTOI(vp); @@ -671,10 +691,10 @@ ufs_link(ap) struct componentname *a_cnp; } */ *ap; { - register struct vnode *vp = ap->a_vp; - register struct vnode *tdvp = ap->a_tdvp; - register struct componentname *cnp = ap->a_cnp; - register struct inode *ip; + struct vnode *vp = ap->a_vp; + struct vnode *tdvp = ap->a_tdvp; + struct componentname *cnp = ap->a_cnp; + struct inode *ip; struct timeval tv; int error; @@ -760,10 +780,10 @@ ufs_rename(ap) struct vnode *tvp = ap->a_tvp; register struct vnode *tdvp = ap->a_tdvp; struct vnode *fvp = ap->a_fvp; - register struct vnode *fdvp = ap->a_fdvp; - register struct componentname *tcnp = ap->a_tcnp; - register struct componentname *fcnp = ap->a_fcnp; - register struct inode *ip, *xp, *dp; + struct vnode *fdvp = ap->a_fdvp; + struct componentname *tcnp = ap->a_tcnp; + struct componentname *fcnp = ap->a_fcnp; + struct inode *ip, *xp, *dp; struct dirtemplate dirbuf; struct timeval tv; int doingdirectory = 0, oldparent = 0, newparent = 0; @@ -1264,10 +1284,10 @@ ufs_rmdir(ap) struct componentname *a_cnp; } */ *ap; { - register struct vnode *vp = ap->a_vp; - register struct vnode *dvp = ap->a_dvp; - register struct componentname *cnp = ap->a_cnp; - register struct inode *ip, *dp; + struct vnode *vp = ap->a_vp; + struct vnode *dvp = ap->a_dvp; + struct componentname *cnp = ap->a_cnp; + struct inode *ip, *dp; int error; ip = VTOI(vp); |