Subject: mount(2) on kauth(9)
To: None <tech-kern@NetBSD.org>
From: Elad Efrat <elad@NetBSD.org>
List: tech-kern
Date: 12/28/2006 18:04:49
This is a multi-part message in MIME format.
--------------000606070401000105060001
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit
hi,
attached diff makes mount(2) use kauth(9) to do some stuff previously
done by checking securelevel/euid.
if there are no objections, I'll commit.
-e.
--------------000606070401000105060001
Content-Type: text/plain;
name="mount.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="mount.diff"
Index: sys/kauth.h
===================================================================
RCS file: /usr/cvs/src/sys/sys/kauth.h,v
retrieving revision 1.29
diff -u -p -r1.29 kauth.h
--- sys/kauth.h 26 Dec 2006 10:43:44 -0000 1.29
+++ sys/kauth.h 27 Dec 2006 13:58:15 -0000
@@ -87,6 +87,7 @@ enum {
KAUTH_SYSTEM_FILEHANDLE,
KAUTH_SYSTEM_LKM,
KAUTH_SYSTEM_MKNOD,
+ KAUTH_SYSTEM_MOUNT,
KAUTH_SYSTEM_REBOOT,
KAUTH_SYSTEM_SETIDCORE,
KAUTH_SYSTEM_SWAPCTL,
@@ -101,6 +102,9 @@ enum kauth_system_req {
KAUTH_REQ_SYSTEM_CHROOT_CHROOT=1,
KAUTH_REQ_SYSTEM_CHROOT_FCHROOT,
KAUTH_REQ_SYSTEM_DEBUG_IPKDB,
+ KAUTH_REQ_SYSTEM_MOUNT_GET,
+ KAUTH_REQ_SYSTEM_MOUNT_NEW,
+ KAUTH_REQ_SYSTEM_MOUNT_UPDATE,
KAUTH_REQ_SYSTEM_SYSCTL_ADD,
KAUTH_REQ_SYSTEM_SYSCTL_DELETE,
KAUTH_REQ_SYSTEM_SYSCTL_DESC,
Index: kern/vfs_syscalls.c
===================================================================
RCS file: /usr/cvs/src/sys/kern/vfs_syscalls.c,v
retrieving revision 1.288
diff -u -p -r1.288 vfs_syscalls.c
--- kern/vfs_syscalls.c 28 Dec 2006 14:33:41 -0000 1.288
+++ kern/vfs_syscalls.c 27 Dec 2006 14:43:09 -0000
@@ -170,39 +170,23 @@ mount_update(struct lwp *l, struct vnode
error = EOPNOTSUPP; /* Needs translation */
goto out;
}
- /*
- * In "highly secure" mode, don't let the caller do anything
- * but downgrade a filesystem from read-write to read-only.
- */
- if (securelevel >= 2 &&
- flags !=
- (mp->mnt_flag | MNT_RDONLY | MNT_RELOAD | MNT_FORCE | MNT_UPDATE)) {
- error = EPERM;
+
+ error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT,
+ KAUTH_REQ_SYSTEM_MOUNT_UPDATE, mp, &flags, data);
+ if (error)
goto out;
- }
+
/*
* Only root, or the user that did the original mount is
* permitted to update it.
+ *
+ * XXX: kauth(9) vnode scope.
*/
if (mp->mnt_stat.f_owner != kauth_cred_geteuid(l->l_cred) &&
(error = kauth_authorize_generic(l->l_cred,
KAUTH_GENERIC_ISSUSER, NULL)) != 0) {
goto out;
}
- /*
- * Do not allow NFS export by non-root users. For non-root
- * users, silently enforce MNT_NOSUID and MNT_NODEV, and
- * MNT_NOEXEC if mount point is already MNT_NOEXEC.
- */
- if (kauth_cred_geteuid(l->l_cred) != 0) {
- if (flags & MNT_EXPORTED) {
- error = EPERM;
- goto out;
- }
- flags |= MNT_NOSUID | MNT_NODEV;
- if (saved_flags & MNT_NOEXEC)
- flags |= MNT_NOEXEC;
- }
if (vfs_busy(mp, LK_NOWAIT, 0)) {
error = EPERM;
goto out;
@@ -273,16 +257,15 @@ mount_domount(struct lwp *l, struct vnod
char fstypename[MFSNAMELEN];
int error;
- /* XXX secmodel stuff. */
- if (securelevel >= 2) {
- error = EPERM;
+ /* Can't make a non-dir a mount-point (from here anyway). */
+ if (vp->v_type != VDIR) {
+ error = ENOTDIR;
vput(vp);
goto out;
}
- /* Can't make a non-dir a mount-point (from here anyway). */
- if (vp->v_type != VDIR) {
- error = ENOTDIR;
+ if (flags & MNT_EXPORTED) {
+ error = EINVAL;
vput(vp);
goto out;
}
@@ -290,6 +273,8 @@ mount_domount(struct lwp *l, struct vnod
/*
* If the user is not root, ensure that they own the directory
* onto which we are attempting to mount.
+ *
+ * XXX: kauth(9) vnode scope.
*/
if ((error = VOP_GETATTR(vp, &va, l->l_cred, l)) != 0 ||
(va.va_uid != kauth_cred_geteuid(l->l_cred) &&
@@ -299,19 +284,6 @@ mount_domount(struct lwp *l, struct vnod
goto out;
}
- if (flags & MNT_EXPORTED) {
- error = EINVAL;
- vput(vp);
- goto out;
- }
-
- /*
- * For non-root users, silently enforce MNT_NOSUID and MNT_NODEV.
- */
- if (kauth_cred_geteuid(l->l_cred) != 0) {
- flags |= MNT_NOSUID | MNT_NODEV;
- }
-
/*
* Copy file-system type from userspace.
*/
@@ -344,6 +316,13 @@ mount_domount(struct lwp *l, struct vnod
strlcpy(fstypename, "ffs", sizeof(fstypename));
#endif
+ error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT,
+ KAUTH_REQ_SYSTEM_MOUNT_NEW, vp, &flags, data);
+ if (error) {
+ vput(vp);
+ goto out;
+ }
+
if ((error = vinvalbuf(vp, V_SAVE, l->l_cred, l, 0, 0)) != 0) {
vput(vp);
goto out;
@@ -438,6 +417,12 @@ mount_getargs(struct lwp *l, struct vnod
goto out;
}
+ /* XXX: probably some notion of "can see" here if we want isolation. */
+ error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT,
+ KAUTH_REQ_SYSTEM_MOUNT_GET, mp, data, NULL);
+ if (error)
+ goto out;
+
if (vfs_busy(mp, LK_NOWAIT, 0)) {
error = EPERM;
goto out;
@@ -475,17 +460,10 @@ sys_mount(struct lwp *l, void *v, regist
return EINVAL;
}
- /* XXX secmodel stuff. */
- if (dovfsusermount == 0 && (SCARG(uap, flags) & MNT_GETARGS) == 0 &&
- (error = kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER,
- &l->l_acflag)))
- return (error);
-
/*
* Get vnode to be covered
*/
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE,
- SCARG(uap, path), l);
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), l);
if ((error = namei(&nd)) != 0)
return (error);
vp = nd.ni_vp;
Index: secmodel/bsd44/secmodel_bsd44_suser.c
===================================================================
RCS file: /usr/cvs/src/sys/secmodel/bsd44/secmodel_bsd44_suser.c,v
retrieving revision 1.23
diff -u -p -r1.23 secmodel_bsd44_suser.c
--- secmodel/bsd44/secmodel_bsd44_suser.c 27 Dec 2006 10:02:46 -0000 1.23
+++ secmodel/bsd44/secmodel_bsd44_suser.c 27 Dec 2006 14:04:36 -0000
@@ -60,6 +60,8 @@ __KERNEL_RCSID(0, "$NetBSD: secmodel_bsd
#include <secmodel/bsd44/suser.h>
+extern int dovfsusermount;
+
void
secmodel_bsd44_suser_start(void)
{
@@ -138,6 +140,54 @@ secmodel_bsd44_suser_system_cb(kauth_cre
req = (enum kauth_system_req)arg0;
switch (action) {
+ case KAUTH_SYSTEM_MOUNT:
+ switch (req) {
+ case KAUTH_REQ_SYSTEM_MOUNT_GET:
+ result = KAUTH_RESULT_ALLOW;
+ break;
+
+ case KAUTH_REQ_SYSTEM_MOUNT_NEW:
+ if (isroot) {
+ result = KAUTH_RESULT_ALLOW;
+ } else if (dovfsusermount) {
+ int *flags = arg2;
+
+ /* Enforce 'nodev', 'nosuid', for non-root */
+ *flags |= MNT_NODEV | MNT_NOSUID;
+
+ result = KAUTH_RESULT_ALLOW;
+ }
+
+ break;
+
+ case KAUTH_REQ_SYSTEM_MOUNT_UPDATE:
+ if (isroot) {
+ result = KAUTH_RESULT_ALLOW;
+ } else if (dovfsusermount) {
+ struct mount *mp = arg1;
+ int *flags = arg2;
+
+ /* No exporting for non-root. */
+ if (*flags & MNT_EXPORTED)
+ break;
+
+ /* Enforce 'nodev', 'nosuid', for non-root */
+ *flags |= MNT_NODEV | MNT_NOSUID;
+
+ /* Retain 'noexec'. */
+ if (mp->mnt_flag & MNT_NOEXEC)
+ *flags |= MNT_NOEXEC;
+
+ result = KAUTH_RESULT_ALLOW;
+ }
+
+ break;
+
+ default:
+ result = KAUTH_RESULT_DEFER;
+ break;
+ }
+
case KAUTH_SYSTEM_TIME:
switch (req) {
case KAUTH_REQ_SYSTEM_TIME_ADJTIME:
Index: secmodel/bsd44/secmodel_bsd44_securelevel.c
===================================================================
RCS file: /usr/cvs/src/sys/secmodel/bsd44/secmodel_bsd44_securelevel.c,v
retrieving revision 1.20
diff -u -p -r1.20 secmodel_bsd44_securelevel.c
--- secmodel/bsd44/secmodel_bsd44_securelevel.c 26 Dec 2006 10:43:44 -0000 1.20
+++ secmodel/bsd44/secmodel_bsd44_securelevel.c 27 Dec 2006 14:33:25 -0000
@@ -174,6 +174,37 @@ secmodel_bsd44_securelevel_system_cb(kau
result = KAUTH_RESULT_ALLOW;
break;
+ case KAUTH_SYSTEM_MOUNT:
+ switch (req) {
+ case KAUTH_REQ_SYSTEM_MOUNT_NEW:
+ if (securelevel > 1)
+ break;
+
+ result = KAUTH_RESULT_ALLOW;
+ break;
+
+ case KAUTH_REQ_SYSTEM_MOUNT_UPDATE:
+ if (securelevel > 1) {
+ struct mount *mp = arg1;
+ int *flags = arg2;
+
+ /* Can only degrade from read/write to read-only. */
+ if (*flags != (mp->mnt_flag | MNT_RDONLY | MNT_RELOAD |
+ MNT_FORCE | MNT_UPDATE))
+ break;
+ }
+
+ result = KAUTH_RESULT_ALLOW;
+
+ break;
+
+ default:
+ result = KAUTH_RESULT_DEFER;
+ break;
+ }
+
+ break;
+
case KAUTH_SYSTEM_SYSCTL:
switch (req) {
case KAUTH_REQ_SYSTEM_SYSCTL_ADD:
--------------000606070401000105060001--