Add genfs_can_mount() and use it to prevent some more code duplication of

the security checks when mounting a device (VOP_ACCESS() + kauth(9) call)).

Proposed with no objections on tech-kern@:

	http://mail-index.netbsd.org/tech-kern/2009/04/20/msg004859.html

The vnode is always expected to be locked, so no locking is done outside
the file-system code.
This commit is contained in:
elad 2009-04-25 18:53:44 +00:00
parent bab57db991
commit 54bf8cc67a
5 changed files with 66 additions and 42 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: udf_vfsops.c,v 1.55 2009/02/08 19:04:41 reinoud Exp $ */
/* $NetBSD: udf_vfsops.c,v 1.56 2009/04/25 18:53:45 elad Exp $ */
/*
* Copyright (c) 2006, 2008 Reinoud Zandijk
@ -28,7 +28,7 @@
#include <sys/cdefs.h>
#ifndef lint
__KERNEL_RCSID(0, "$NetBSD: udf_vfsops.c,v 1.55 2009/02/08 19:04:41 reinoud Exp $");
__KERNEL_RCSID(0, "$NetBSD: udf_vfsops.c,v 1.56 2009/04/25 18:53:45 elad Exp $");
#endif /* not lint */
@ -378,17 +378,15 @@ udf_mount(struct mount *mp, const char *path,
* If mount by non-root, then verify that user has necessary
* permissions on the device.
*/
if (kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER, NULL)) {
accessmode = VREAD;
if ((mp->mnt_flag & MNT_RDONLY) == 0)
accessmode |= VWRITE;
vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
error = VOP_ACCESS(devvp, accessmode, l->l_cred);
VOP_UNLOCK(devvp, 0);
if (error) {
vrele(devvp);
return error;
}
accessmode = VREAD;
if ((mp->mnt_flag & MNT_RDONLY) == 0)
accessmode |= VWRITE;
vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
error = genfs_can_mount(devvp, accessmode, l->l_cred);
VOP_UNLOCK(devvp, 0);
if (error) {
vrele(devvp);
return error;
}
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: genfs.h,v 1.24 2009/04/22 22:57:08 elad Exp $ */
/* $NetBSD: genfs.h,v 1.25 2009/04/25 18:53:44 elad Exp $ */
#ifndef _MISCFS_GENFS_GENFS_H_
#define _MISCFS_GENFS_GENFS_H_
@ -38,5 +38,6 @@ void genfs_renamelock_exit(struct mount *);
int genfs_can_chmod(vnode_t *, kauth_cred_t, uid_t, gid_t, mode_t);
int genfs_can_chown(vnode_t *, kauth_cred_t, uid_t, gid_t, uid_t, gid_t);
int genfs_can_mount(vnode_t *, mode_t, kauth_cred_t);
#endif /* !_MISCFS_GENFS_GENFS_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: genfs_vnops.c,v 1.169 2009/04/22 22:57:08 elad Exp $ */
/* $NetBSD: genfs_vnops.c,v 1.170 2009/04/25 18:53:44 elad Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@ -57,7 +57,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: genfs_vnops.c,v 1.169 2009/04/22 22:57:08 elad Exp $");
__KERNEL_RCSID(0, "$NetBSD: genfs_vnops.c,v 1.170 2009/04/25 18:53:44 elad Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -642,3 +642,26 @@ genfs_can_chown(vnode_t *vp, kauth_cred_t cred, uid_t cur_uid,
return (0);
}
/*
* Common routine to check if the device can be mounted.
*
* devvp - the locked vnode of the device
* cred - credentials of the invoker
* accessmode - the accessmode (VREAD, VWRITE)
*
* Returns 0 if the mount is allowed, or an error value otherwise.
*/
int
genfs_can_mount(vnode_t *devvp, mode_t accessmode, kauth_cred_t cred)
{
int error;
/* Always allow for root. */
error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
if (!error)
return (0);
error = VOP_ACCESS(devvp, accessmode, cred);
return (error);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: ext2fs_vfsops.c,v 1.142 2009/03/01 15:59:57 christos Exp $ */
/* $NetBSD: ext2fs_vfsops.c,v 1.143 2009/04/25 18:53:45 elad Exp $ */
/*
* Copyright (c) 1989, 1991, 1993, 1994
@ -65,7 +65,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ext2fs_vfsops.c,v 1.142 2009/03/01 15:59:57 christos Exp $");
__KERNEL_RCSID(0, "$NetBSD: ext2fs_vfsops.c,v 1.143 2009/04/25 18:53:45 elad Exp $");
#if defined(_KERNEL_OPT)
#include "opt_compat_netbsd.h"
@ -380,18 +380,19 @@ ext2fs_mount(struct mount *mp, const char *path, void *data, size_t *data_len)
/*
* If mount by non-root, then verify that user has necessary
* permissions on the device.
*
* Permission to update a mount is checked higher, so here we presume
* updating the mount is okay (for example, as far as securelevel goes)
* which leaves us with the normal check.
*/
if (error == 0 && kauth_authorize_generic(l->l_cred,
KAUTH_GENERIC_ISSUSER, NULL) != 0) {
accessmode = VREAD;
if (update ?
(mp->mnt_iflag & IMNT_WANTRDWR) != 0 :
(mp->mnt_flag & MNT_RDONLY) == 0)
accessmode |= VWRITE;
vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
error = VOP_ACCESS(devvp, accessmode, l->l_cred);
VOP_UNLOCK(devvp, 0);
}
accessmode = VREAD;
if (update ?
(mp->mnt_iflag & IMNT_WANTRDWR) != 0 :
(mp->mnt_flag & MNT_RDONLY) == 0)
accessmode |= VWRITE;
vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
error = genfs_can_mount(devvp, accessmode, l->l_cred);
VOP_UNLOCK(devvp, 0);
if (error) {
vrele(devvp);

View File

@ -1,4 +1,4 @@
/* $NetBSD: ffs_vfsops.c,v 1.245 2009/03/29 10:29:00 ad Exp $ */
/* $NetBSD: ffs_vfsops.c,v 1.246 2009/04/25 18:53:45 elad Exp $ */
/*-
* Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@ -61,7 +61,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.245 2009/03/29 10:29:00 ad Exp $");
__KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.246 2009/04/25 18:53:45 elad Exp $");
#if defined(_KERNEL_OPT)
#include "opt_ffs.h"
@ -381,18 +381,19 @@ ffs_mount(struct mount *mp, const char *path, void *data, size_t *data_len)
/*
* If mount by non-root, then verify that user has necessary
* permissions on the device.
*
* Permission to update a mount is checked higher, so here we presume
* updating the mount is okay (for example, as far as securelevel goes)
* which leaves us with the normal check.
*/
if (error == 0 && kauth_authorize_generic(l->l_cred,
KAUTH_GENERIC_ISSUSER, NULL) != 0) {
accessmode = VREAD;
if (update ?
(mp->mnt_iflag & IMNT_WANTRDWR) != 0 :
(mp->mnt_flag & MNT_RDONLY) == 0)
accessmode |= VWRITE;
vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
error = VOP_ACCESS(devvp, accessmode, l->l_cred);
VOP_UNLOCK(devvp, 0);
}
accessmode = VREAD;
if (update ?
(mp->mnt_iflag & IMNT_WANTRDWR) != 0 :
(mp->mnt_flag & MNT_RDONLY) == 0)
accessmode |= VWRITE;
vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
error = genfs_can_mount(devvp, accessmode, l->l_cred);
VOP_UNLOCK(devvp, 0);
if (error) {
vrele(devvp);