aboutsummaryrefslogtreecommitdiff
path: root/sys/security/mac_bsdextended
diff options
context:
space:
mode:
authorDavid Malone <dwmalone@FreeBSD.org>2006-04-23 17:06:18 +0000
committerDavid Malone <dwmalone@FreeBSD.org>2006-04-23 17:06:18 +0000
commit89ddbd45e5e8e521f98c3e4a42fe969499f1a70c (patch)
tree27f43660d8de323a7adc792ac8d26a820c3b6015 /sys/security/mac_bsdextended
parent19af5f6b1785009364113fc543433f41fa8f8219 (diff)
downloadsrc-89ddbd45e5e8e521f98c3e4a42fe969499f1a70c.tar.gz
src-89ddbd45e5e8e521f98c3e4a42fe969499f1a70c.zip
Add some new options to mac_bsdestended. We can now match on:
subject: ranges of uid, ranges of gid, jail id objects: ranges of uid, ranges of gid, filesystem, object is suid, object is sgid, object matches subject uid/gid object type We can also negate individual conditions. The ruleset language is a superset of the previous language, so old rules should continue to work. These changes require a change to the API between libugidfw and the mac_bsdextended module. Add a version number, so we can tell if we're running mismatched versions. Update man pages to reflect changes, add extra test cases to test_ugidfw.c and add a shell script that checks that the the module seems to do what we expect. Suggestions from: rwatson, trhodes Reviewed by: trhodes MFC after: 2 months
Notes
Notes: svn path=/head/; revision=157986
Diffstat (limited to 'sys/security/mac_bsdextended')
-rw-r--r--sys/security/mac_bsdextended/mac_bsdextended.c183
-rw-r--r--sys/security/mac_bsdextended/mac_bsdextended.h62
2 files changed, 210 insertions, 35 deletions
diff --git a/sys/security/mac_bsdextended/mac_bsdextended.c b/sys/security/mac_bsdextended/mac_bsdextended.c
index 5dd69b148869..7dec0d16d3c9 100644
--- a/sys/security/mac_bsdextended/mac_bsdextended.c
+++ b/sys/security/mac_bsdextended/mac_bsdextended.c
@@ -47,6 +47,7 @@
#include <sys/acl.h>
#include <sys/conf.h>
#include <sys/kernel.h>
+#include <sys/jail.h>
#include <sys/lock.h>
#include <sys/mac.h>
#include <sys/malloc.h>
@@ -62,6 +63,7 @@
#include <sys/socketvar.h>
#include <sys/sysctl.h>
#include <sys/syslog.h>
+#include <sys/ucred.h>
#include <net/bpfdesc.h>
#include <net/if.h>
@@ -92,11 +94,14 @@ MALLOC_DEFINE(M_MACBSDEXTENDED, "mac_bsdextended", "BSD Extended MAC rule");
static struct mac_bsdextended_rule *rules[MAC_BSDEXTENDED_MAXRULES];
static int rule_count = 0;
static int rule_slots = 0;
+static int rule_version = MB_VERSION;
SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_count, CTLFLAG_RD,
&rule_count, 0, "Number of defined rules\n");
SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_slots, CTLFLAG_RD,
&rule_slots, 0, "Number of used rule slots\n");
+SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_version, CTLFLAG_RD,
+ &rule_version, 0, "Version number for API\n");
/*
* This is just used for logging purposes, eventually we would like
@@ -121,10 +126,20 @@ static int
mac_bsdextended_rule_valid(struct mac_bsdextended_rule *rule)
{
- if ((rule->mbr_subject.mbi_flags | MBI_BITS) != MBI_BITS)
+ if ((rule->mbr_subject.mbs_flags | MBS_ALL_FLAGS) != MBS_ALL_FLAGS)
return (EINVAL);
- if ((rule->mbr_object.mbi_flags | MBI_BITS) != MBI_BITS)
+ if ((rule->mbr_subject.mbs_neg | MBS_ALL_FLAGS) != MBS_ALL_FLAGS)
+ return (EINVAL);
+
+ if ((rule->mbr_object.mbo_flags | MBO_ALL_FLAGS) != MBO_ALL_FLAGS)
+ return (EINVAL);
+
+ if ((rule->mbr_object.mbo_neg | MBO_ALL_FLAGS) != MBO_ALL_FLAGS)
+ return (EINVAL);
+
+ if ((rule->mbr_object.mbo_neg | MBO_TYPE_DEFINED) &&
+ (rule->mbr_object.mbo_type | MBO_ALL_TYPE) != MBO_ALL_TYPE)
return (EINVAL);
if ((rule->mbr_mode | MBI_ALLPERM) != MBI_ALLPERM)
@@ -240,32 +255,59 @@ mac_bsdextended_destroy(struct mac_policy_conf *mpc)
static int
mac_bsdextended_rulecheck(struct mac_bsdextended_rule *rule,
- struct ucred *cred, uid_t object_uid, gid_t object_gid, int acc_mode)
+ struct ucred *cred, struct vnode *vp, struct vattr *vap, int acc_mode)
{
int match;
+ int i;
/*
* Is there a subject match?
*/
mtx_assert(&mac_bsdextended_mtx, MA_OWNED);
- if (rule->mbr_subject.mbi_flags & MBI_UID_DEFINED) {
- match = (rule->mbr_subject.mbi_uid == cred->cr_uid ||
- rule->mbr_subject.mbi_uid == cred->cr_ruid ||
- rule->mbr_subject.mbi_uid == cred->cr_svuid);
+ if (rule->mbr_subject.mbs_flags & MBS_UID_DEFINED) {
+ match = ((cred->cr_uid <= rule->mbr_subject.mbs_uid_max &&
+ cred->cr_uid >= rule->mbr_subject.mbs_uid_min) ||
+ (cred->cr_ruid <= rule->mbr_subject.mbs_uid_max &&
+ cred->cr_ruid >= rule->mbr_subject.mbs_uid_min) ||
+ (cred->cr_svuid <= rule->mbr_subject.mbs_uid_max &&
+ cred->cr_svuid >= rule->mbr_subject.mbs_uid_min));
+
+ if (rule->mbr_subject.mbs_neg & MBS_UID_DEFINED)
+ match = !match;
- if (rule->mbr_subject.mbi_flags & MBI_NEGATED)
+ if (!match)
+ return (0);
+ }
+
+ if (rule->mbr_subject.mbs_flags & MBS_GID_DEFINED) {
+ match = ((cred->cr_rgid <= rule->mbr_subject.mbs_gid_max &&
+ cred->cr_rgid >= rule->mbr_subject.mbs_gid_min) ||
+ (cred->cr_svgid <= rule->mbr_subject.mbs_gid_max &&
+ cred->cr_svgid >= rule->mbr_subject.mbs_gid_min));
+
+ if (!match) {
+ for (i = 0; i < cred->cr_ngroups; i++)
+ if (cred->cr_groups[i]
+ <= rule->mbr_subject.mbs_gid_max &&
+ cred->cr_groups[i]
+ >= rule->mbr_subject.mbs_gid_min) {
+ match = 1;
+ break;
+ }
+ }
+
+ if (rule->mbr_subject.mbs_neg & MBS_GID_DEFINED)
match = !match;
if (!match)
return (0);
}
- if (rule->mbr_subject.mbi_flags & MBI_GID_DEFINED) {
- match = (groupmember(rule->mbr_subject.mbi_gid, cred) ||
- rule->mbr_subject.mbi_gid == cred->cr_rgid ||
- rule->mbr_subject.mbi_gid == cred->cr_svgid);
+ if (rule->mbr_subject.mbs_flags & MBS_PRISON_DEFINED) {
+ match = (cred->cr_prison != NULL &&
+ cred->cr_prison->pr_id == rule->mbr_subject.mbs_prison);
- if (rule->mbr_subject.mbi_flags & MBI_NEGATED)
+ if (rule->mbr_subject.mbs_neg & MBS_PRISON_DEFINED)
match = !match;
if (!match)
@@ -275,26 +317,118 @@ mac_bsdextended_rulecheck(struct mac_bsdextended_rule *rule,
/*
* Is there an object match?
*/
- if (rule->mbr_object.mbi_flags & MBI_UID_DEFINED) {
- match = (rule->mbr_object.mbi_uid == object_uid);
+ if (rule->mbr_object.mbo_flags & MBO_UID_DEFINED) {
+ match = (vap->va_uid <= rule->mbr_object.mbo_uid_max &&
+ vap->va_uid >= rule->mbr_object.mbo_uid_min);
- if (rule->mbr_object.mbi_flags & MBI_NEGATED)
+ if (rule->mbr_object.mbo_neg & MBO_UID_DEFINED)
match = !match;
if (!match)
return (0);
}
- if (rule->mbr_object.mbi_flags & MBI_GID_DEFINED) {
- match = (rule->mbr_object.mbi_gid == object_gid);
+ if (rule->mbr_object.mbo_flags & MBO_GID_DEFINED) {
+ match = (vap->va_gid <= rule->mbr_object.mbo_gid_max &&
+ vap->va_gid >= rule->mbr_object.mbo_gid_min);
- if (rule->mbr_object.mbi_flags & MBI_NEGATED)
+ if (rule->mbr_object.mbo_neg & MBO_GID_DEFINED)
match = !match;
if (!match)
return (0);
}
+ if (rule->mbr_object.mbo_flags & MBO_FSID_DEFINED) {
+ match = (bcmp(&(vp->v_mount->mnt_stat.f_fsid),
+ &(rule->mbr_object.mbo_fsid),
+ sizeof(rule->mbr_object.mbo_fsid)) == 0);
+
+ if (rule->mbr_object.mbo_neg & MBO_FSID_DEFINED)
+ match = !match;
+
+ if (!match)
+ return 0;
+ }
+
+ if (rule->mbr_object.mbo_flags & MBO_SUID) {
+ match = (vap->va_mode & VSUID);
+
+ if (rule->mbr_object.mbo_neg & MBO_SUID)
+ match = !match;
+
+ if (!match)
+ return 0;
+ }
+
+ if (rule->mbr_object.mbo_flags & MBO_SGID) {
+ match = (vap->va_mode & VSGID);
+
+ if (rule->mbr_object.mbo_neg & MBO_SGID)
+ match = !match;
+
+ if (!match)
+ return 0;
+ }
+
+ if (rule->mbr_object.mbo_flags & MBO_UID_SUBJECT) {
+ match = (vap->va_uid == cred->cr_uid ||
+ vap->va_uid == cred->cr_ruid ||
+ vap->va_uid == cred->cr_svuid);
+
+ if (rule->mbr_object.mbo_neg & MBO_UID_SUBJECT)
+ match = !match;
+
+ if (!match)
+ return 0;
+ }
+
+ if (rule->mbr_object.mbo_flags & MBO_GID_SUBJECT) {
+ match = (groupmember(vap->va_gid, cred) ||
+ vap->va_gid == cred->cr_rgid ||
+ vap->va_gid == cred->cr_svgid);
+
+ if (rule->mbr_object.mbo_neg & MBO_GID_SUBJECT)
+ match = !match;
+
+ if (!match)
+ return 0;
+ }
+
+ if (rule->mbr_object.mbo_flags & MBO_TYPE_DEFINED) {
+ switch (vap->va_type) {
+ case VREG:
+ match = (rule->mbr_object.mbo_type & MBO_TYPE_REG);
+ break;
+ case VDIR:
+ match = (rule->mbr_object.mbo_type & MBO_TYPE_DIR);
+ break;
+ case VBLK:
+ match = (rule->mbr_object.mbo_type & MBO_TYPE_BLK);
+ break;
+ case VCHR:
+ match = (rule->mbr_object.mbo_type & MBO_TYPE_CHR);
+ break;
+ case VLNK:
+ match = (rule->mbr_object.mbo_type & MBO_TYPE_LNK);
+ break;
+ case VSOCK:
+ match = (rule->mbr_object.mbo_type & MBO_TYPE_SOCK);
+ break;
+ case VFIFO:
+ match = (rule->mbr_object.mbo_type & MBO_TYPE_FIFO);
+ break;
+ default:
+ match = 0;
+ }
+
+ if (rule->mbr_object.mbo_neg & MBO_TYPE_DEFINED)
+ match = !match;
+
+ if (!match)
+ return 0;
+ }
+
/*
* Is the access permitted?
*/
@@ -302,7 +436,7 @@ mac_bsdextended_rulecheck(struct mac_bsdextended_rule *rule,
if (mac_bsdextended_logging)
log(LOG_AUTHPRIV, "mac_bsdextended: %d:%d request %d"
" on %d:%d failed. \n", cred->cr_ruid,
- cred->cr_rgid, acc_mode, object_uid, object_gid);
+ cred->cr_rgid, acc_mode, vap->va_uid, vap->va_gid);
return (EACCES); /* Matching rule denies access */
}
@@ -317,7 +451,7 @@ mac_bsdextended_rulecheck(struct mac_bsdextended_rule *rule,
}
static int
-mac_bsdextended_check(struct ucred *cred, uid_t object_uid, gid_t object_gid,
+mac_bsdextended_check(struct ucred *cred, struct vnode *vp, struct vattr *vap,
int acc_mode)
{
int error, i;
@@ -339,8 +473,8 @@ mac_bsdextended_check(struct ucred *cred, uid_t object_uid, gid_t object_gid,
acc_mode |= MBI_WRITE;
}
- error = mac_bsdextended_rulecheck(rules[i], cred, object_uid,
- object_gid, acc_mode);
+ error = mac_bsdextended_rulecheck(rules[i], cred,
+ vp, vap, acc_mode);
if (error == EJUSTRETURN)
break;
if (error) {
@@ -365,8 +499,7 @@ mac_bsdextended_check_vp(struct ucred *cred, struct vnode *vp, int acc_mode)
if (error)
return (error);
- return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
- acc_mode));
+ return (mac_bsdextended_check(cred, vp, &vap, acc_mode));
}
static int
diff --git a/sys/security/mac_bsdextended/mac_bsdextended.h b/sys/security/mac_bsdextended/mac_bsdextended.h
index 4ddc21e15b29..af3ae8f78fb5 100644
--- a/sys/security/mac_bsdextended/mac_bsdextended.h
+++ b/sys/security/mac_bsdextended/mac_bsdextended.h
@@ -37,10 +37,7 @@
#ifndef _SYS_SECURITY_MAC_BSDEXTENDED_H
#define _SYS_SECURITY_MAC_BSDEXTENDED_H
-#define MBI_UID_DEFINED 0x00000001 /* uid field should be used */
-#define MBI_GID_DEFINED 0x00000002 /* gid field should be used */
-#define MBI_NEGATED 0x00000004 /* negate uid/gid matches */
-#define MBI_BITS (MBI_UID_DEFINED | MBI_GID_DEFINED | MBI_NEGATED)
+#define MB_VERSION 2 /* Used to check library and kernel are the same. */
/*
* Rights that can be represented in mbr_mode. These have the same values
@@ -57,15 +54,60 @@
#define MBI_ALLPERM (MBI_EXEC | MBI_WRITE | MBI_READ | MBI_ADMIN | \
MBI_STAT | MBI_APPEND)
-struct mac_bsdextended_identity {
- int mbi_flags;
- uid_t mbi_uid;
- gid_t mbi_gid;
+#define MBS_UID_DEFINED 0x00000001 /* uid field should be matched */
+#define MBS_GID_DEFINED 0x00000002 /* gid field should be matched */
+#define MBS_PRISON_DEFINED 0x00000004 /* prison field should be matched */
+
+#define MBS_ALL_FLAGS (MBS_UID_DEFINED | MBS_GID_DEFINED | MBS_PRISON_DEFINED)
+
+struct mac_bsdextended_subject {
+ int mbs_flags;
+ int mbs_neg;
+ uid_t mbs_uid_min;
+ uid_t mbs_uid_max;
+ gid_t mbs_gid_min;
+ gid_t mbs_gid_max;
+ int mbs_prison;
+};
+
+#define MBO_UID_DEFINED 0x00000001 /* uid field should be matched */
+#define MBO_GID_DEFINED 0x00000002 /* gid field should be matched */
+#define MBO_FSID_DEFINED 0x00000004 /* fsid field should be matched */
+#define MBO_SUID 0x00000008 /* object must be suid */
+#define MBO_SGID 0x00000010 /* object must be sgid */
+#define MBO_UID_SUBJECT 0x00000020 /* uid must match subject */
+#define MBO_GID_SUBJECT 0x00000040 /* gid must match subject */
+#define MBO_TYPE_DEFINED 0x00000080 /* object type should be matched */
+
+#define MBO_ALL_FLAGS (MBO_UID_DEFINED | MBO_GID_DEFINED | MBO_FSID_DEFINED | \
+ MBO_SUID | MBO_SGID | MBO_UID_SUBJECT | MBO_GID_SUBJECT | \
+ MBO_TYPE_DEFINED)
+
+#define MBO_TYPE_REG 0x00000001
+#define MBO_TYPE_DIR 0x00000002
+#define MBO_TYPE_BLK 0x00000004
+#define MBO_TYPE_CHR 0x00000008
+#define MBO_TYPE_LNK 0x00000010
+#define MBO_TYPE_SOCK 0x00000020
+#define MBO_TYPE_FIFO 0x00000040
+
+#define MBO_ALL_TYPE (MBO_TYPE_REG | MBO_TYPE_DIR | MBO_TYPE_BLK | \
+ MBO_TYPE_CHR | MBO_TYPE_LNK | MBO_TYPE_SOCK | MBO_TYPE_FIFO)
+
+struct mac_bsdextended_object {
+ int mbo_flags;
+ int mbo_neg;
+ uid_t mbo_uid_min;
+ uid_t mbo_uid_max;
+ gid_t mbo_gid_min;
+ gid_t mbo_gid_max;
+ struct fsid mbo_fsid;
+ int mbo_type;
};
struct mac_bsdextended_rule {
- struct mac_bsdextended_identity mbr_subject;
- struct mac_bsdextended_identity mbr_object;
+ struct mac_bsdextended_subject mbr_subject;
+ struct mac_bsdextended_object mbr_object;
mode_t mbr_mode; /* maximum access */
};