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
This commit is contained in:
parent
788a8001cc
commit
7af111191c
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user