Introduce several actions/requests for authorizing file-system related

operations, specifically quota and block allocation from reserved space.

Modify ufs_quotactl() to accomodate passing "mp" earlier by vfs_busy()ing
it a little bit higher.

Mailing list reference:

	http://mail-index.netbsd.org/tech-kern/2009/04/26/msg004936.html

Note that the umapfs request mentioned in this thread was NOT added as
there is still on-going discussion regarding the proper implementation.
This commit is contained in:
elad 2009-05-07 19:26:08 +00:00
parent 8650959ae7
commit 9e9887cc59
7 changed files with 121 additions and 28 deletions

View File

@ -1,4 +1,4 @@
.\" $NetBSD: kauth.9,v 1.82 2009/05/07 18:01:56 elad Exp $
.\" $NetBSD: kauth.9,v 1.83 2009/05/07 19:26:08 elad Exp $
.\"
.\" Copyright (c) 2005, 2006 Elad Efrat <elad@NetBSD.org>
.\" All rights reserved.
@ -203,6 +203,37 @@ is allowed.
.El
.It Dv KAUTH_SYSTEM_FILEHANDLE
Check if filehandle operations allowed.
.It Dv KAUTH_SYSTEM_FS_QUOTA
Check if file-system quota operations are allowed.
.Pp
.Ar arg1
is a
.Ft struct mount *
describing the file-system mount in question.
.Ar req
can be one of the following:
.Bl -tag -width compact
.It Dv KAUTH_REQ_SYSTEM_FS_QUOTA_GET
Check if retrieving quota information is allowed.
.Pp
.Ar arg2
is a
.Ft uid_t
with the user-id of the user whose quota information is to be retrieved.
.It Dv KAUTH_REQ_SYSTEM_FS_QUOTA_ONOFF
Check if turning quota on/off is allowed.
.It Dv KAUTH_REQ_SYSTEM_FS_QUOTA_MANAGE
Check if managing the quota by setting the quota/quota use is allowed.
.Pp
.Ar arg2
is a
.Ft uid_t
with the user-id of the user whose quota/quota use is to be set.
.It Dv KAUTH_REQ_SYSTEM_FS_QUOTA_NOLIMIT
Check if bypassing the quota (not enforcing it) is allwoed.
.El
.It Dv KAUTH_SYSTEM_FS_RESERVEDSPACE
Check if using the file-system reserved space is allowed.
.It Dv KAUTH_SYSTEM_MODULE
Check if a module request is allowed.
.Pp

View File

@ -1,4 +1,4 @@
/* $NetBSD: secmodel_bsd44_suser.c,v 1.65 2009/05/07 18:01:56 elad Exp $ */
/* $NetBSD: secmodel_bsd44_suser.c,v 1.66 2009/05/07 19:26:09 elad Exp $ */
/*-
* Copyright (c) 2006 Elad Efrat <elad@NetBSD.org>
* All rights reserved.
@ -38,7 +38,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: secmodel_bsd44_suser.c,v 1.65 2009/05/07 18:01:56 elad Exp $");
__KERNEL_RCSID(0, "$NetBSD: secmodel_bsd44_suser.c,v 1.66 2009/05/07 19:26:09 elad Exp $");
#include <sys/types.h>
#include <sys/param.h>
@ -172,6 +172,27 @@ secmodel_bsd44_suser_system_cb(kauth_cred_t cred, kauth_action_t action,
break;
case KAUTH_SYSTEM_FS_QUOTA:
switch (req) {
case KAUTH_REQ_SYSTEM_FS_QUOTA_GET:
case KAUTH_REQ_SYSTEM_FS_QUOTA_ONOFF:
case KAUTH_REQ_SYSTEM_FS_QUOTA_MANAGE:
case KAUTH_REQ_SYSTEM_FS_QUOTA_NOLIMIT:
if (isroot)
result = KAUTH_RESULT_ALLOW;
break;
default:
break;
}
break;
case KAUTH_SYSTEM_FS_RESERVEDSPACE:
if (isroot)
result = KAUTH_RESULT_ALLOW;
break;
case KAUTH_SYSTEM_MOUNT:
switch (req) {
case KAUTH_REQ_SYSTEM_MOUNT_GET:

View File

@ -1,4 +1,4 @@
/* $NetBSD: kauth.h,v 1.57 2009/05/07 18:01:56 elad Exp $ */
/* $NetBSD: kauth.h,v 1.58 2009/05/07 19:26:08 elad Exp $ */
/*-
* Copyright (c) 2005, 2006 Elad Efrat <elad@NetBSD.org>
@ -94,7 +94,9 @@ enum {
KAUTH_SYSTEM_SWAPCTL,
KAUTH_SYSTEM_SYSCTL,
KAUTH_SYSTEM_TIME,
KAUTH_SYSTEM_MODULE
KAUTH_SYSTEM_MODULE,
KAUTH_SYSTEM_FS_RESERVEDSPACE,
KAUTH_SYSTEM_FS_QUOTA,
};
/*
@ -122,7 +124,11 @@ enum kauth_system_req {
KAUTH_REQ_SYSTEM_TIME_NTPADJTIME,
KAUTH_REQ_SYSTEM_TIME_RTCOFFSET,
KAUTH_REQ_SYSTEM_TIME_SYSTEM,
KAUTH_REQ_SYSTEM_TIME_TIMECOUNTERS
KAUTH_REQ_SYSTEM_TIME_TIMECOUNTERS,
KAUTH_REQ_SYSTEM_FS_QUOTA_GET,
KAUTH_REQ_SYSTEM_FS_QUOTA_MANAGE,
KAUTH_REQ_SYSTEM_FS_QUOTA_NOLIMIT,
KAUTH_REQ_SYSTEM_FS_QUOTA_ONOFF,
};
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: ext2fs_alloc.c,v 1.38 2009/01/11 02:45:56 christos Exp $ */
/* $NetBSD: ext2fs_alloc.c,v 1.39 2009/05/07 19:26:08 elad Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1993
@ -65,7 +65,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ext2fs_alloc.c,v 1.38 2009/01/11 02:45:56 christos Exp $");
__KERNEL_RCSID(0, "$NetBSD: ext2fs_alloc.c,v 1.39 2009/05/07 19:26:08 elad Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -128,7 +128,8 @@ ext2fs_alloc(struct inode *ip, daddr_t lbn, daddr_t bpref,
#endif /* DIAGNOSTIC */
if (fs->e2fs.e2fs_fbcount == 0)
goto nospace;
if (kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL) != 0 &&
if (kauth_authorize_system(cred, KAUTH_SYSTEM_FS_RESERVEDSPACE, 0, NULL,
NULL, NULL) != 0 &&
freespace(fs) <= 0)
goto nospace;
if (bpref >= fs->e2fs.e2fs_bcount)

View File

@ -1,4 +1,4 @@
/* $NetBSD: ffs_alloc.c,v 1.123 2009/04/25 08:32:32 sborrill Exp $ */
/* $NetBSD: ffs_alloc.c,v 1.124 2009/05/07 19:26:09 elad Exp $ */
/*-
* Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@ -70,7 +70,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ffs_alloc.c,v 1.123 2009/04/25 08:32:32 sborrill Exp $");
__KERNEL_RCSID(0, "$NetBSD: ffs_alloc.c,v 1.124 2009/05/07 19:26:09 elad Exp $");
#if defined(_KERNEL_OPT)
#include "opt_ffs.h"
@ -216,7 +216,8 @@ ffs_alloc(struct inode *ip, daddr_t lbn, daddr_t bpref, int size, int flags,
if (size == fs->fs_bsize && fs->fs_cstotal.cs_nbfree == 0)
goto nospace;
if (freespace(fs, fs->fs_minfree) <= 0 &&
kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL) != 0)
kauth_authorize_system(cred, KAUTH_SYSTEM_FS_RESERVEDSPACE, 0, NULL,
NULL, NULL) != 0)
goto nospace;
#ifdef QUOTA
mutex_exit(&ump->um_lock);
@ -323,7 +324,8 @@ ffs_realloccg(struct inode *ip, daddr_t lbprev, daddr_t bpref, int osize,
panic("ffs_realloccg: missing credential");
#endif /* DIAGNOSTIC */
if (freespace(fs, fs->fs_minfree) <= 0 &&
kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL) != 0) {
kauth_authorize_system(cred, KAUTH_SYSTEM_FS_RESERVEDSPACE, 0, NULL,
NULL, NULL) != 0) {
mutex_exit(&ump->um_lock);
goto nospace;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: ufs_quota.c,v 1.61 2008/12/21 10:48:10 ad Exp $ */
/* $NetBSD: ufs_quota.c,v 1.62 2009/05/07 19:26:09 elad Exp $ */
/*
* Copyright (c) 1982, 1986, 1990, 1993, 1995
@ -35,7 +35,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ufs_quota.c,v 1.61 2008/12/21 10:48:10 ad Exp $");
__KERNEL_RCSID(0, "$NetBSD: ufs_quota.c,v 1.62 2009/05/07 19:26:09 elad Exp $");
#include <sys/param.h>
#include <sys/kernel.h>
@ -221,7 +221,8 @@ chkdq(struct inode *ip, int64_t change, kauth_cred_t cred, int flags)
return (0);
}
if ((flags & FORCE) == 0 &&
kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL) != 0) {
kauth_authorize_system(cred, KAUTH_SYSTEM_FS_QUOTA,
KAUTH_REQ_SYSTEM_FS_QUOTA_NOLIMIT, NULL, NULL, NULL) != 0) {
for (i = 0; i < MAXQUOTAS; i++) {
if ((dq = ip->i_dquot[i]) == NODQUOT)
continue;
@ -325,8 +326,9 @@ chkiq(struct inode *ip, int32_t change, kauth_cred_t cred, int flags)
}
return (0);
}
if ((flags & FORCE) == 0 && kauth_authorize_generic(cred,
KAUTH_GENERIC_ISSUSER, NULL) != 0) {
if ((flags & FORCE) == 0 && kauth_authorize_system(cred,
KAUTH_SYSTEM_FS_QUOTA, KAUTH_REQ_SYSTEM_FS_QUOTA_NOLIMIT, NULL,
NULL, NULL) != 0) {
for (i = 0; i < MAXQUOTAS; i++) {
if ((dq = ip->i_dquot[i]) == NODQUOT)
continue;

View File

@ -1,4 +1,4 @@
/* $NetBSD: ufs_vfsops.c,v 1.39 2008/05/06 18:43:45 ad Exp $ */
/* $NetBSD: ufs_vfsops.c,v 1.40 2009/05/07 19:26:09 elad Exp $ */
/*
* Copyright (c) 1991, 1993, 1994
@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ufs_vfsops.c,v 1.39 2008/05/06 18:43:45 ad Exp $");
__KERNEL_RCSID(0, "$NetBSD: ufs_vfsops.c,v 1.40 2009/05/07 19:26:09 elad Exp $");
#if defined(_KERNEL_OPT)
#include "opt_ffs.h"
@ -117,25 +117,55 @@ ufs_quotactl(struct mount *mp, int cmds, uid_t uid, void *arg)
uid = kauth_cred_getuid(l->l_cred);
cmd = cmds >> SUBCMDSHIFT;
/* Mark the mount busy, as we're passing it to kauth(9). */
error = vfs_busy(mp, NULL);
if (error)
return (error);
switch (cmd) {
case Q_SYNC:
break;
case Q_GETQUOTA:
/* The user can always query about his own quota. */
if (uid == kauth_cred_getuid(l->l_cred))
break;
/* fall through */
error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA,
KAUTH_REQ_SYSTEM_FS_QUOTA_GET, mp, KAUTH_ARG(uid), NULL);
break;
case Q_QUOTAON:
case Q_QUOTAOFF:
error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA,
KAUTH_REQ_SYSTEM_FS_QUOTA_ONOFF, mp, NULL, NULL);
break;
case Q_SETQUOTA:
case Q_SETUSE:
error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA,
KAUTH_REQ_SYSTEM_FS_QUOTA_MANAGE, mp, KAUTH_ARG(uid), NULL);
break;
default:
if ((error = kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER,
NULL)) != 0)
return (error);
error = EINVAL;
break;
}
type = cmds & SUBCMDMASK;
if ((u_int)type >= MAXQUOTAS)
return (EINVAL);
error = vfs_busy(mp, NULL);
if (error != 0)
if (!error) {
/* Only check if there was no error above. */
if ((u_int)type >= MAXQUOTAS)
error = EINVAL;
}
if (error) {
vfs_unbusy(mp, false, NULL);
return (error);
}
mutex_enter(&mp->mnt_updating);
switch (cmd) {