diff options
author | dwmalone <dwmalone@FreeBSD.org> | 2006-04-23 17:06:18 +0000 |
---|---|---|
committer | dwmalone <dwmalone@FreeBSD.org> | 2006-04-23 17:06:18 +0000 |
commit | b6a29644300546ce70b02879a2c08ac130791d36 (patch) | |
tree | 27f43660d8de323a7adc792ac8d26a820c3b6015 /sys/security/mac_bsdextended/mac_bsdextended.c | |
parent | f795ce96032ed06ead12a69167377795ea4364ee (diff) | |
download | FreeBSD-src-b6a29644300546ce70b02879a2c08ac130791d36.zip FreeBSD-src-b6a29644300546ce70b02879a2c08ac130791d36.tar.gz |
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
Diffstat (limited to 'sys/security/mac_bsdextended/mac_bsdextended.c')
-rw-r--r-- | sys/security/mac_bsdextended/mac_bsdextended.c | 183 |
1 files changed, 158 insertions, 25 deletions
diff --git a/sys/security/mac_bsdextended/mac_bsdextended.c b/sys/security/mac_bsdextended/mac_bsdextended.c index 5dd69b1..7dec0d1 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 |