diff options
author | rwatson <rwatson@FreeBSD.org> | 2002-08-01 15:37:12 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2002-08-01 15:37:12 +0000 |
commit | 7af111191c599878545a46db61bc2ce941a6db99 (patch) | |
tree | 2623052f2ac865b58a0c903ad64a3abea0b1b692 /sys/kern | |
parent | 788a8001cc095577779652d0f77dddb2739e4bf6 (diff) | |
download | FreeBSD-src-7af111191c599878545a46db61bc2ce941a6db99.zip FreeBSD-src-7af111191c599878545a46db61bc2ce941a6db99.tar.gz |
Introduce support for Mandatory Access Control and extensible
kernel access control.
Invoke appropriate MAC entry points to authorize the following
operations:
truncate on open() (write)
access() (access)
readlink() (readlink)
chflags(), lchflags(), fchflags() (setflag)
chmod(), fchmod(), lchmod() (setmode)
chown(), fchown(), lchown() (setowner)
utimes(), lutimes(), futimes() (setutimes)
truncate(), ftrunfcate() (write)
revoke() (revoke)
fhopen() (open)
truncate on fhopen() (write)
extattr_set_fd, extattr_set_file() (setextattr)
extattr_get_fd, extattr_get_file() (getextattr)
extattr_delete_fd(), extattr_delete_file() (setextattr)
These entry points permit MAC policies to enforce a variety of
protections on vnodes. More vnode checks to come, especially in
non-native ABIs.
Obtained from: TrustedBSD Project
Sponsored by: DARPA, NAI Labs
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/vfs_extattr.c | 105 | ||||
-rw-r--r-- | sys/kern/vfs_syscalls.c | 105 |
2 files changed, 190 insertions, 20 deletions
diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c index bf43908..8d4c9b4 100644 --- a/sys/kern/vfs_extattr.c +++ b/sys/kern/vfs_extattr.c @@ -733,7 +733,12 @@ open(td, uap) VATTR_NULL(&vat); vat.va_size = 0; vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); - error = VOP_SETATTR(vp, &vat, td->td_ucred, td); +#ifdef MAC + error = mac_check_vnode_op(td->td_ucred, vp, + MAC_OP_VNODE_WRITE); + if (error == 0) +#endif + error = VOP_SETATTR(vp, &vat, td->td_ucred, td); VOP_UNLOCK(vp, 0, td); vn_finished_write(mp); if (error) @@ -1305,6 +1310,11 @@ vn_access(vp, user_flags, cred, td) flags |= VWRITE; if (user_flags & X_OK) flags |= VEXEC; +#ifdef MAC + error = mac_check_vnode_access(cred, vp, flags); + if (error) + return (error); +#endif if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0) error = VOP_ACCESS(vp, flags, cred, td); } @@ -1746,6 +1756,13 @@ readlink(td, uap) return (error); NDFREE(&nd, NDF_ONLY_PNBUF); vp = nd.ni_vp; +#ifdef MAC + error = mac_check_vnode_readlink(td->td_ucred, vp); + if (error) { + vput(vp); + return (error); + } +#endif if (vp->v_type != VLNK) error = EINVAL; else { @@ -1794,9 +1811,16 @@ setfflags(td, vp, flags) return (error); VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); - VATTR_NULL(&vattr); - vattr.va_flags = flags; - error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); +#ifdef MAC + error = mac_check_vnode_setflags(td->td_ucred, vp, vattr.va_flags); + if (error == 0) { +#endif + VATTR_NULL(&vattr); + vattr.va_flags = flags; + error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); +#ifdef MAC + } +#endif VOP_UNLOCK(vp, 0, td); vn_finished_write(mp); return (error); @@ -1902,7 +1926,11 @@ setfmode(td, vp, mode) vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); VATTR_NULL(&vattr); vattr.va_mode = mode & ALLPERMS; - error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); +#ifdef MAC + error = mac_check_vnode_setmode(td->td_ucred, vp, vattr.va_mode); + if (error == 0) +#endif + error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); VOP_UNLOCK(vp, 0, td); vn_finished_write(mp); return error; @@ -2019,7 +2047,12 @@ setfown(td, vp, uid, gid) VATTR_NULL(&vattr); vattr.va_uid = uid; vattr.va_gid = gid; - error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); +#ifdef MAC + error = mac_check_vnode_setowner(td->td_ucred, vp, vattr.va_uid, + vattr.va_gid); + if (error == 0) +#endif + error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); VOP_UNLOCK(vp, 0, td); vn_finished_write(mp); return error; @@ -2178,7 +2211,12 @@ setutimes(td, vp, ts, numtimes, nullflag) vattr.va_birthtime = ts[2]; if (nullflag) vattr.va_vaflags |= VA_UTIMES_NULL; - error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); +#ifdef MAC + error = mac_check_vnode_setutimes(td->td_ucred, vp, vattr.va_atime, + vattr.va_mtime); + if (error == 0) +#endif + error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); VOP_UNLOCK(vp, 0, td); vn_finished_write(mp); return error; @@ -2328,6 +2366,10 @@ truncate(td, uap) vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); if (vp->v_type == VDIR) error = EISDIR; +#ifdef MAC + else if ((error = mac_check_vnode_op(td->td_ucred, vp, + MAC_OP_VNODE_WRITE))) {} +#endif else if ((error = vn_writechk(vp)) == 0 && (error = VOP_ACCESS(vp, VWRITE, td->td_ucred, td)) == 0) { VATTR_NULL(&vattr); @@ -2382,6 +2424,10 @@ ftruncate(td, uap) vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); if (vp->v_type == VDIR) error = EISDIR; +#ifdef MAC + else if ((error = mac_check_vnode_op(td->td_ucred, vp, + MAC_OP_VNODE_WRITE))) {} +#endif else if ((error = vn_writechk(vp)) == 0) { VATTR_NULL(&vattr); vattr.va_size = SCARG(uap, length); @@ -3073,6 +3119,13 @@ revoke(td, uap) vput(vp); return (EINVAL); } +#ifdef MAC + error = mac_check_vnode_revoke(td->td_ucred, vp); + if (error) { + vput(vp); + return (error); + } +#endif error = VOP_GETATTR(vp, &vattr, td->td_ucred, td); if (error) { vput(vp); @@ -3257,6 +3310,11 @@ fhopen(td, uap) mode |= VREAD; if (fmode & O_APPEND) mode |= VAPPEND; +#ifdef MAC + error = mac_check_vnode_open(td->td_ucred, vp, mode); + if (error) + goto bad; +#endif if (mode) { error = VOP_ACCESS(vp, mode, td->td_ucred, td); if (error) @@ -3270,9 +3328,17 @@ fhopen(td, uap) } VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); /* XXX */ - VATTR_NULL(vap); - vap->va_size = 0; - error = VOP_SETATTR(vp, vap, td->td_ucred, td); +#ifdef MAC + error = mac_check_vnode_op(td->td_ucred, vp, + MAC_OP_VNODE_WRITE); + if (error == 0) { +#endif + VATTR_NULL(vap); + vap->va_size = 0; + error = VOP_SETATTR(vp, vap, td->td_ucred, td); +#ifdef MAC + } +#endif vn_finished_write(mp); if (error) goto bad; @@ -3584,6 +3650,13 @@ extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname, auio.uio_td = td; cnt = nbytes; +#ifdef MAC + error = mac_check_vnode_setextattr(td->td_ucred, vp, attrnamespace, + attrname, &auio); + if (error) + goto done; +#endif + error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio, td->td_ucred, td); cnt -= auio.uio_resid; @@ -3704,6 +3777,13 @@ extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname, } else sizep = &size; +#ifdef MAC + error = mac_check_vnode_getextattr(td->td_ucred, vp, attrnamespace, + attrname, &auio); + if (error) + goto done; +#endif + error = VOP_GETEXTATTR(vp, attrnamespace, attrname, auiop, sizep, td->td_ucred, td); @@ -3800,6 +3880,11 @@ extattr_delete_vp(struct vnode *vp, int attrnamespace, const char *attrname, VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); +#ifdef MAC + error = mac_check_vnode_setextattr(td->td_ucred, vp, attrnamespace, + attrname, NULL); +#endif + error = VOP_SETEXTATTR(vp, attrnamespace, attrname, NULL, td->td_ucred, td); diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index bf43908..8d4c9b4 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -733,7 +733,12 @@ open(td, uap) VATTR_NULL(&vat); vat.va_size = 0; vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); - error = VOP_SETATTR(vp, &vat, td->td_ucred, td); +#ifdef MAC + error = mac_check_vnode_op(td->td_ucred, vp, + MAC_OP_VNODE_WRITE); + if (error == 0) +#endif + error = VOP_SETATTR(vp, &vat, td->td_ucred, td); VOP_UNLOCK(vp, 0, td); vn_finished_write(mp); if (error) @@ -1305,6 +1310,11 @@ vn_access(vp, user_flags, cred, td) flags |= VWRITE; if (user_flags & X_OK) flags |= VEXEC; +#ifdef MAC + error = mac_check_vnode_access(cred, vp, flags); + if (error) + return (error); +#endif if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0) error = VOP_ACCESS(vp, flags, cred, td); } @@ -1746,6 +1756,13 @@ readlink(td, uap) return (error); NDFREE(&nd, NDF_ONLY_PNBUF); vp = nd.ni_vp; +#ifdef MAC + error = mac_check_vnode_readlink(td->td_ucred, vp); + if (error) { + vput(vp); + return (error); + } +#endif if (vp->v_type != VLNK) error = EINVAL; else { @@ -1794,9 +1811,16 @@ setfflags(td, vp, flags) return (error); VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); - VATTR_NULL(&vattr); - vattr.va_flags = flags; - error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); +#ifdef MAC + error = mac_check_vnode_setflags(td->td_ucred, vp, vattr.va_flags); + if (error == 0) { +#endif + VATTR_NULL(&vattr); + vattr.va_flags = flags; + error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); +#ifdef MAC + } +#endif VOP_UNLOCK(vp, 0, td); vn_finished_write(mp); return (error); @@ -1902,7 +1926,11 @@ setfmode(td, vp, mode) vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); VATTR_NULL(&vattr); vattr.va_mode = mode & ALLPERMS; - error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); +#ifdef MAC + error = mac_check_vnode_setmode(td->td_ucred, vp, vattr.va_mode); + if (error == 0) +#endif + error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); VOP_UNLOCK(vp, 0, td); vn_finished_write(mp); return error; @@ -2019,7 +2047,12 @@ setfown(td, vp, uid, gid) VATTR_NULL(&vattr); vattr.va_uid = uid; vattr.va_gid = gid; - error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); +#ifdef MAC + error = mac_check_vnode_setowner(td->td_ucred, vp, vattr.va_uid, + vattr.va_gid); + if (error == 0) +#endif + error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); VOP_UNLOCK(vp, 0, td); vn_finished_write(mp); return error; @@ -2178,7 +2211,12 @@ setutimes(td, vp, ts, numtimes, nullflag) vattr.va_birthtime = ts[2]; if (nullflag) vattr.va_vaflags |= VA_UTIMES_NULL; - error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); +#ifdef MAC + error = mac_check_vnode_setutimes(td->td_ucred, vp, vattr.va_atime, + vattr.va_mtime); + if (error == 0) +#endif + error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); VOP_UNLOCK(vp, 0, td); vn_finished_write(mp); return error; @@ -2328,6 +2366,10 @@ truncate(td, uap) vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); if (vp->v_type == VDIR) error = EISDIR; +#ifdef MAC + else if ((error = mac_check_vnode_op(td->td_ucred, vp, + MAC_OP_VNODE_WRITE))) {} +#endif else if ((error = vn_writechk(vp)) == 0 && (error = VOP_ACCESS(vp, VWRITE, td->td_ucred, td)) == 0) { VATTR_NULL(&vattr); @@ -2382,6 +2424,10 @@ ftruncate(td, uap) vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); if (vp->v_type == VDIR) error = EISDIR; +#ifdef MAC + else if ((error = mac_check_vnode_op(td->td_ucred, vp, + MAC_OP_VNODE_WRITE))) {} +#endif else if ((error = vn_writechk(vp)) == 0) { VATTR_NULL(&vattr); vattr.va_size = SCARG(uap, length); @@ -3073,6 +3119,13 @@ revoke(td, uap) vput(vp); return (EINVAL); } +#ifdef MAC + error = mac_check_vnode_revoke(td->td_ucred, vp); + if (error) { + vput(vp); + return (error); + } +#endif error = VOP_GETATTR(vp, &vattr, td->td_ucred, td); if (error) { vput(vp); @@ -3257,6 +3310,11 @@ fhopen(td, uap) mode |= VREAD; if (fmode & O_APPEND) mode |= VAPPEND; +#ifdef MAC + error = mac_check_vnode_open(td->td_ucred, vp, mode); + if (error) + goto bad; +#endif if (mode) { error = VOP_ACCESS(vp, mode, td->td_ucred, td); if (error) @@ -3270,9 +3328,17 @@ fhopen(td, uap) } VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); /* XXX */ - VATTR_NULL(vap); - vap->va_size = 0; - error = VOP_SETATTR(vp, vap, td->td_ucred, td); +#ifdef MAC + error = mac_check_vnode_op(td->td_ucred, vp, + MAC_OP_VNODE_WRITE); + if (error == 0) { +#endif + VATTR_NULL(vap); + vap->va_size = 0; + error = VOP_SETATTR(vp, vap, td->td_ucred, td); +#ifdef MAC + } +#endif vn_finished_write(mp); if (error) goto bad; @@ -3584,6 +3650,13 @@ extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname, auio.uio_td = td; cnt = nbytes; +#ifdef MAC + error = mac_check_vnode_setextattr(td->td_ucred, vp, attrnamespace, + attrname, &auio); + if (error) + goto done; +#endif + error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio, td->td_ucred, td); cnt -= auio.uio_resid; @@ -3704,6 +3777,13 @@ extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname, } else sizep = &size; +#ifdef MAC + error = mac_check_vnode_getextattr(td->td_ucred, vp, attrnamespace, + attrname, &auio); + if (error) + goto done; +#endif + error = VOP_GETEXTATTR(vp, attrnamespace, attrname, auiop, sizep, td->td_ucred, td); @@ -3800,6 +3880,11 @@ extattr_delete_vp(struct vnode *vp, int attrnamespace, const char *attrname, VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); +#ifdef MAC + error = mac_check_vnode_setextattr(td->td_ucred, vp, attrnamespace, + attrname, NULL); +#endif + error = VOP_SETEXTATTR(vp, attrnamespace, attrname, NULL, td->td_ucred, td); |