diff options
author | David Malone <dwmalone@FreeBSD.org> | 2006-04-23 17:06:18 +0000 |
---|---|---|
committer | David Malone <dwmalone@FreeBSD.org> | 2006-04-23 17:06:18 +0000 |
commit | 89ddbd45e5e8e521f98c3e4a42fe969499f1a70c (patch) | |
tree | 27f43660d8de323a7adc792ac8d26a820c3b6015 /sys/security | |
parent | 19af5f6b1785009364113fc543433f41fa8f8219 (diff) | |
download | src-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')
-rw-r--r-- | sys/security/mac_bsdextended/mac_bsdextended.c | 183 | ||||
-rw-r--r-- | sys/security/mac_bsdextended/mac_bsdextended.h | 62 |
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 */ }; |