diff options
author | rwatson <rwatson@FreeBSD.org> | 2006-11-06 13:42:10 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2006-11-06 13:42:10 +0000 |
commit | 10d0d9cf473dc5f0ce1bf263ead445ffe7819154 (patch) | |
tree | b9dd284620eeaddbff089cef10e4b1afb7918279 /sys/ufs | |
parent | 7288104e2094825a9c98b9923f039817a76e2983 (diff) | |
download | FreeBSD-src-10d0d9cf473dc5f0ce1bf263ead445ffe7819154.zip FreeBSD-src-10d0d9cf473dc5f0ce1bf263ead445ffe7819154.tar.gz |
Sweep kernel replacing suser(9) calls with priv(9) calls, assigning
specific privilege names to a broad range of privileges. These may
require some future tweaking.
Sponsored by: nCircle Network Security, Inc.
Obtained from: TrustedBSD Project
Discussed on: arch@
Reviewed (at least in part) by: mlaier, jmg, pjd, bde, ceri,
Alex Lyashkov <umka at sevcity dot net>,
Skip Ford <skip dot ford at verizon dot net>,
Antoine Brodin <antoine dot brodin at laposte dot net>
Diffstat (limited to 'sys/ufs')
-rw-r--r-- | sys/ufs/ffs/ffs_alloc.c | 5 | ||||
-rw-r--r-- | sys/ufs/ffs/ffs_vfsops.c | 33 | ||||
-rw-r--r-- | sys/ufs/ffs/ffs_vnops.c | 6 | ||||
-rw-r--r-- | sys/ufs/ufs/ufs_extattr.c | 4 | ||||
-rw-r--r-- | sys/ufs/ufs/ufs_quota.c | 34 | ||||
-rw-r--r-- | sys/ufs/ufs/ufs_vnops.c | 45 |
6 files changed, 84 insertions, 43 deletions
diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c index bc92afe..b7e7fda 100644 --- a/sys/ufs/ffs/ffs_alloc.c +++ b/sys/ufs/ffs/ffs_alloc.c @@ -71,6 +71,7 @@ __FBSDID("$FreeBSD$"); #include <sys/conf.h> #include <sys/file.h> #include <sys/filedesc.h> +#include <sys/priv.h> #include <sys/proc.h> #include <sys/vnode.h> #include <sys/mount.h> @@ -171,7 +172,7 @@ retry: #endif if (size == fs->fs_bsize && fs->fs_cstotal.cs_nbfree == 0) goto nospace; - if (suser_cred(cred, SUSER_ALLOWJAIL) && + if (priv_check_cred(cred, PRIV_VFS_BLOCKRESERVE, SUSER_ALLOWJAIL) && freespace(fs, fs->fs_minfree) - numfrags(fs, size) < 0) goto nospace; if (bpref >= fs->fs_size) @@ -259,7 +260,7 @@ ffs_realloccg(ip, lbprev, bprev, bpref, osize, nsize, cred, bpp) #endif /* DIAGNOSTIC */ reclaimed = 0; retry: - if (suser_cred(cred, SUSER_ALLOWJAIL) && + if (priv_check_cred(cred, PRIV_VFS_BLOCKRESERVE, SUSER_ALLOWJAIL) && freespace(fs, fs->fs_minfree) - numfrags(fs, nsize - osize) < 0) { goto nospace; } diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c index b9ccf3a..a2591bc 100644 --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/systm.h> #include <sys/namei.h> +#include <sys/priv.h> #include <sys/proc.h> #include <sys/kernel.h> #include <sys/vnode.h> @@ -257,15 +258,16 @@ ffs_mount(struct mount *mp, struct thread *td) * If upgrade to read-write by non-root, then verify * that user has necessary permissions on the device. */ - if (suser(td)) { - vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td); - if ((error = VOP_ACCESS(devvp, VREAD | VWRITE, - td->td_ucred, td)) != 0) { - VOP_UNLOCK(devvp, 0, td); - return (error); - } + vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td); + error = VOP_ACCESS(devvp, VREAD | VWRITE, + td->td_ucred, td); + if (error) + error = priv_check(td, PRIV_VFS_MOUNT_PERM); + if (error) { VOP_UNLOCK(devvp, 0, td); + return (error); } + VOP_UNLOCK(devvp, 0, td); fs->fs_flags &= ~FS_UNCLEAN; if (fs->fs_clean == 0) { fs->fs_flags |= FS_UNCLEAN; @@ -364,14 +366,15 @@ ffs_mount(struct mount *mp, struct thread *td) * If mount by non-root, then verify that user has necessary * permissions on the device. */ - if (suser(td)) { - accessmode = VREAD; - if ((mp->mnt_flag & MNT_RDONLY) == 0) - accessmode |= VWRITE; - if ((error = VOP_ACCESS(devvp, accessmode, td->td_ucred, td))!= 0){ - vput(devvp); - return (error); - } + accessmode = VREAD; + if ((mp->mnt_flag & MNT_RDONLY) == 0) + accessmode |= VWRITE; + error = VOP_ACCESS(devvp, accessmode, td->td_ucred, td); + if (error) + error = priv_check(td, PRIV_VFS_MOUNT_PERM); + if (error) { + vput(devvp); + return (error); } if (mp->mnt_flag & MNT_UPDATE) { diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c index 4d8d9ef..5ffedd7 100644 --- a/sys/ufs/ffs/ffs_vnops.c +++ b/sys/ufs/ffs/ffs_vnops.c @@ -74,6 +74,7 @@ __FBSDID("$FreeBSD$"); #include <sys/limits.h> #include <sys/malloc.h> #include <sys/mount.h> +#include <sys/priv.h> #include <sys/proc.h> #include <sys/resourcevar.h> #include <sys/signalvar.h> @@ -781,7 +782,8 @@ ffs_write(ap) * tampering. */ if (resid > uio->uio_resid && ap->a_cred && - suser_cred(ap->a_cred, SUSER_ALLOWJAIL)) { + priv_check_cred(ap->a_cred, PRIV_VFS_CLEARSUGID, + SUSER_ALLOWJAIL)) { ip->i_mode &= ~(ISUID | ISGID); DIP_SET(ip, i_mode, ip->i_mode); } @@ -1107,7 +1109,7 @@ ffs_extwrite(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *ucred) * tampering. */ if (resid > uio->uio_resid && ucred && - suser_cred(ucred, SUSER_ALLOWJAIL)) { + priv_check_cred(ucred, PRIV_VFS_CLEARSUGID, SUSER_ALLOWJAIL)) { ip->i_mode &= ~(ISUID | ISGID); dp->di_mode = ip->i_mode; } diff --git a/sys/ufs/ufs/ufs_extattr.c b/sys/ufs/ufs/ufs_extattr.c index e6153f3..f49f988 100644 --- a/sys/ufs/ufs/ufs_extattr.c +++ b/sys/ufs/ufs/ufs_extattr.c @@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$"); #include <sys/namei.h> #include <sys/malloc.h> #include <sys/fcntl.h> +#include <sys/priv.h> #include <sys/proc.h> #include <sys/vnode.h> #include <sys/mount.h> @@ -699,7 +700,8 @@ ufs_extattrctl(struct mount *mp, int cmd, struct vnode *filename_vp, * Processes with privilege, but in jail, are not allowed to * configure extended attributes. */ - if ((error = suser(td))) { + error = priv_check(td, PRIV_UFS_EXTATTRCTL); + if (error) { if (filename_vp != NULL) VOP_UNLOCK(filename_vp, 0, td); return (error); diff --git a/sys/ufs/ufs/ufs_quota.c b/sys/ufs/ufs/ufs_quota.c index 81a1d0d..c4a93cd 100644 --- a/sys/ufs/ufs/ufs_quota.c +++ b/sys/ufs/ufs/ufs_quota.c @@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$"); #include <sys/mount.h> #include <sys/mutex.h> #include <sys/namei.h> +#include <sys/priv.h> #include <sys/proc.h> #include <sys/socket.h> #include <sys/stat.h> @@ -165,7 +166,8 @@ chkdq(ip, change, cred, flags) } return (0); } - if ((flags & FORCE) == 0 && suser_cred(cred, 0)) { + if ((flags & FORCE) == 0 && priv_check_cred(cred, + PRIV_UFS_EXCEEDQUOTA, 0)) { for (i = 0; i < MAXQUOTAS; i++) { if ((dq = ip->i_dquot[i]) == NODQUOT) continue; @@ -288,7 +290,8 @@ chkiq(ip, change, cred, flags) } return (0); } - if ((flags & FORCE) == 0 && suser_cred(cred, 0)) { + if ((flags & FORCE) == 0 && priv_check_cred(cred, + PRIV_UFS_EXCEEDQUOTA, 0)) { for (i = 0; i < MAXQUOTAS; i++) { if ((dq = ip->i_dquot[i]) == NODQUOT) continue; @@ -423,7 +426,11 @@ quotaon(td, mp, type, fname) int error, flags; struct nameidata nd; - error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL); + /* + * XXXRW: Can this be right? Jail is allowed to do this? + */ + error = priv_check_cred(td->td_ucred, PRIV_UFS_QUOTAON, + SUSER_ALLOWJAIL); if (error) return (error); @@ -517,7 +524,11 @@ quotaoff(td, mp, type) struct inode *ip; int error; - error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL); + /* + * XXXRW: This also seems wrong to allow in a jail? + */ + error = priv_check_cred(td->td_ucred, PRIV_UFS_QUOTAOFF, + SUSER_ALLOWJAIL); if (error) return (error); @@ -589,15 +600,18 @@ getquota(td, mp, id, type, addr) switch (type) { case USRQUOTA: if ((td->td_ucred->cr_uid != id) && !unprivileged_get_quota) { - error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL); + error = priv_check_cred(td->td_ucred, + PRIV_UFS_GETQUOTA, SUSER_ALLOWJAIL); if (error) return (error); } break; case GRPQUOTA: - if (!groupmember(id, td->td_ucred) && !unprivileged_get_quota) { - error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL); + if (!groupmember(id, td->td_ucred) && + !unprivileged_get_quota) { + error = priv_check_cred(td->td_ucred, + PRIV_UFS_GETQUOTA, SUSER_ALLOWJAIL); if (error) return (error); } @@ -632,7 +646,8 @@ setquota(td, mp, id, type, addr) struct dqblk newlim; int error; - error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL); + error = priv_check_cred(td->td_ucred, PRIV_UFS_SETQUOTA, + SUSER_ALLOWJAIL); if (error) return (error); @@ -698,7 +713,8 @@ setuse(td, mp, id, type, addr) struct dqblk usage; int error; - error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL); + error = priv_check_cred(td->td_ucred, PRIV_UFS_SETUSE, + SUSER_ALLOWJAIL); if (error) return (error); diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c index 4f96449..4fcadd0 100644 --- a/sys/ufs/ufs/ufs_vnops.c +++ b/sys/ufs/ufs/ufs_vnops.c @@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$"); #include <sys/bio.h> #include <sys/buf.h> #include <sys/mount.h> +#include <sys/priv.h> #include <sys/refcount.h> #include <sys/unistd.h> #include <sys/vnode.h> @@ -493,8 +494,11 @@ ufs_setattr(ap) * processes if the security.jail.chflags_allowed sysctl is * is non-zero; otherwise, they behave like unprivileged * processes. + * + * XXXRW: Move implementation of jail_chflags_allowed to + * kern_jail.c. */ - if (!suser_cred(cred, + if (!priv_check_cred(cred, PRIV_VFS_SYSFLAGS, jail_chflags_allowed ? SUSER_ALLOWJAIL : 0)) { if (ip->i_flags & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND)) { @@ -585,10 +589,19 @@ ufs_setattr(ap) * super-user. * If times is non-NULL, ... The caller must be the owner of * the file or be the super-user. + * + * Possibly for historical reasons, try to use VADMIN in + * preference to VADMIN for a NULL timestamp. This means we + * will return EACCES in preference to EPERM if neither + * check succeeds. */ - if ((error = VOP_ACCESS(vp, VADMIN, cred, td)) && - ((vap->va_vaflags & VA_UTIMES_NULL) == 0 || - (error = VOP_ACCESS(vp, VWRITE, cred, td)))) + if (vap->va_vaflags & VA_UTIMES_NULL) { + error = VOP_ACCESS(vp, VADMIN, cred, td); + if (error) + error = VOP_ACCESS(vp, VWRITE, cred, td); + } else + error = VOP_ACCESS(vp, VADMIN, cred, td); + if (error) return (error); if (vap->va_atime.tv_sec != VNOVAL) ip->i_flag |= IN_ACCESS; @@ -654,11 +667,13 @@ ufs_chmod(vp, mode, cred, td) * jail(8). */ if (vp->v_type != VDIR && (mode & S_ISTXT)) { - if (suser_cred(cred, SUSER_ALLOWJAIL)) + if (priv_check_cred(cred, PRIV_VFS_STICKYFILE, + SUSER_ALLOWJAIL)) return (EFTYPE); } if (!groupmember(ip->i_gid, cred) && (mode & ISGID)) { - error = suser_cred(cred, SUSER_ALLOWJAIL); + error = priv_check_cred(cred, PRIV_VFS_SETGID, + SUSER_ALLOWJAIL); if (error) return (error); } @@ -695,19 +710,19 @@ ufs_chown(vp, uid, gid, cred, td) if (gid == (gid_t)VNOVAL) gid = ip->i_gid; /* - * To modify the ownership of a file, must possess VADMIN - * for that file. + * To modify the ownership of a file, must possess VADMIN for that + * file. */ if ((error = VOP_ACCESS(vp, VADMIN, cred, td))) return (error); /* - * To change the owner of a file, or change the group of a file - * to a group of which we are not a member, the caller must - * have privilege. + * To change the owner of a file, or change the group of a file to a + * group of which we are not a member, the caller must have + * privilege. */ if ((uid != ip->i_uid || (gid != ip->i_gid && !groupmember(gid, cred))) && - (error = suser_cred(cred, SUSER_ALLOWJAIL))) + (error = priv_check_cred(cred, PRIV_VFS_CHOWN, SUSER_ALLOWJAIL))) return (error); ogid = ip->i_gid; ouid = ip->i_uid; @@ -778,7 +793,8 @@ good: panic("ufs_chown: lost quota"); #endif /* QUOTA */ ip->i_flag |= IN_CHANGE; - if (suser_cred(cred, SUSER_ALLOWJAIL) && (ouid != uid || ogid != gid)) { + if (priv_check_cred(cred, PRIV_VFS_CLEARSUGID, SUSER_ALLOWJAIL) && + (ouid != uid || ogid != gid)) { ip->i_mode &= ~(ISUID | ISGID); DIP_SET(ip, i_mode, ip->i_mode); } @@ -2357,7 +2373,8 @@ ufs_makeinode(mode, dvp, vpp, cnp) if (DOINGSOFTDEP(tvp)) softdep_change_linkcnt(ip); if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, cnp->cn_cred) && - suser_cred(cnp->cn_cred, SUSER_ALLOWJAIL)) { + priv_check_cred(cnp->cn_cred, PRIV_VFS_SETGID, + SUSER_ALLOWJAIL)) { ip->i_mode &= ~ISGID; DIP_SET(ip, i_mode, ip->i_mode); } |