summaryrefslogtreecommitdiffstats
path: root/sys/ufs
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2006-11-06 13:42:10 +0000
committerrwatson <rwatson@FreeBSD.org>2006-11-06 13:42:10 +0000
commit10d0d9cf473dc5f0ce1bf263ead445ffe7819154 (patch)
treeb9dd284620eeaddbff089cef10e4b1afb7918279 /sys/ufs
parent7288104e2094825a9c98b9923f039817a76e2983 (diff)
downloadFreeBSD-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.c5
-rw-r--r--sys/ufs/ffs/ffs_vfsops.c33
-rw-r--r--sys/ufs/ffs/ffs_vnops.c6
-rw-r--r--sys/ufs/ufs/ufs_extattr.c4
-rw-r--r--sys/ufs/ufs/ufs_quota.c34
-rw-r--r--sys/ufs/ufs/ufs_vnops.c45
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);
}
OpenPOWER on IntegriCloud