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
This commit is contained in:
parent
f795ce9603
commit
b6a2964430
@ -59,14 +59,6 @@ Converts the internal representation of a rule
|
||||
into its text representation;
|
||||
see
|
||||
.Xr bsde_rule_to_string 3 .
|
||||
.It Fn bsde_parse_identity
|
||||
Parses the identity of a subject or object;
|
||||
see
|
||||
.Xr bsde_parse_identity 3 .
|
||||
.It Fn bsde_parse_mode
|
||||
Parses the access mode for a ugidfw rule;
|
||||
see
|
||||
.Xr bsde_parse_mode 3 .
|
||||
.It Fn bsde_parse_rule
|
||||
Parses an entire rule
|
||||
(in argument array form);
|
||||
@ -108,8 +100,6 @@ rule number; see
|
||||
.Xr bsde_get_rule 3 ,
|
||||
.Xr bsde_get_rule_count 3 ,
|
||||
.Xr bsde_get_rule_slots 3 ,
|
||||
.Xr bsde_parse_identity 3 ,
|
||||
.Xr bsde_parse_mode 3 ,
|
||||
.Xr bsde_parse_rule 3 ,
|
||||
.Xr bsde_parse_rule_string 3 ,
|
||||
.Xr bsde_rule_to_string 3 ,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -37,9 +37,6 @@
|
||||
__BEGIN_DECLS
|
||||
int bsde_rule_to_string(struct mac_bsdextended_rule *rule, char *buf,
|
||||
size_t buflen);
|
||||
int bsde_parse_identity(int argc, char *argv[],
|
||||
struct mac_bsdextended_identity *identity, size_t buflen,
|
||||
char *errstr);
|
||||
int bsde_parse_mode(int argc, char *argv[], mode_t *mode, size_t buflen,
|
||||
char *errstr);
|
||||
int bsde_parse_rule(int argc, char *argv[],
|
||||
|
@ -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.mbi_flags & MBI_NEGATED)
|
||||
if (rule->mbr_subject.mbs_neg & MBS_UID_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_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 (rule->mbr_subject.mbi_flags & MBI_NEGATED)
|
||||
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.mbs_flags & MBS_PRISON_DEFINED) {
|
||||
match = (cred->cr_prison != NULL &&
|
||||
cred->cr_prison->pr_id == rule->mbr_subject.mbs_prison);
|
||||
|
||||
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
|
||||
|
@ -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 */
|
||||
};
|
||||
|
||||
|
167
tools/regression/mac/mac_bsdextended/test_matches.sh
Normal file
167
tools/regression/mac/mac_bsdextended/test_matches.sh
Normal file
@ -0,0 +1,167 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
|
||||
uidrange="60000:100000"
|
||||
gidrange="60000:100000"
|
||||
uidinrange="nobody"
|
||||
uidoutrange="daemon"
|
||||
gidinrange="nobody" # We expect $uidinrange in this group
|
||||
gidoutrange="daemon" # We expect $uidinrange in this group
|
||||
|
||||
playground="/stuff/nobody/" # Must not be on root fs
|
||||
|
||||
#
|
||||
# Setup
|
||||
#
|
||||
rm -f $playground/test*
|
||||
ugidfw remove 1
|
||||
|
||||
file1=$playground/test-$uidinrange
|
||||
file2=$playground/test-$uidoutrange
|
||||
cat <<EOF> $playground/test-script.pl
|
||||
if (open(F, ">" . shift)) { exit 0; } else { exit 1; }
|
||||
EOF
|
||||
command1="perl $playground/test-script.pl $file1"
|
||||
command2="perl $playground/test-script.pl $file2"
|
||||
|
||||
echo -n "$uidinrange file: "
|
||||
su -m $uidinrange -c "$command1 && echo good"
|
||||
chown "$uidinrange":"$gidinrange" $file1
|
||||
chmod a+w $file1
|
||||
|
||||
echo -n "$uidoutrange file: "
|
||||
$command2 && echo good
|
||||
chown "$uidoutrange":"$gidoutrange" $file2
|
||||
chmod a+w $file2
|
||||
|
||||
#
|
||||
# No rules
|
||||
#
|
||||
echo -n "no rules $uidinrange: "
|
||||
su -fm $uidinrange -c "$command1 && echo good"
|
||||
echo -n "no rules $uidoutrange: "
|
||||
su -fm $uidoutrange -c "$command1 && echo good"
|
||||
|
||||
#
|
||||
# Subject Match on uid
|
||||
#
|
||||
ugidfw set 1 subject uid $uidrange object mode rasx
|
||||
echo -n "subject uid in range: "
|
||||
su -fm $uidinrange -c "$command1 || echo good"
|
||||
echo -n "subject uid out range: "
|
||||
su -fm $uidoutrange -c "$command1 && echo good"
|
||||
|
||||
#
|
||||
# Subject Match on gid
|
||||
#
|
||||
ugidfw set 1 subject gid $gidrange object mode rasx
|
||||
echo -n "subject gid in range: "
|
||||
su -fm $uidinrange -c "$command1 || echo good"
|
||||
echo -n "subject gid out range: "
|
||||
su -fm $uidoutrange -c "$command1 && echo good"
|
||||
|
||||
#
|
||||
# Subject Match on jail
|
||||
#
|
||||
echo -n "subject matching jailid: "
|
||||
rm -f $playground/test-jail
|
||||
jailid=`jail -i / localhost 127.0.0.1 /usr/sbin/daemon -f /bin/sh -c "(sleep 3; touch $playground/test-jail) &"`
|
||||
ugidfw set 1 subject jailid $jailid object mode rasx
|
||||
sleep 6
|
||||
if [ ! -f $playground/test-jail ] ; then echo good ; fi
|
||||
|
||||
echo -n "subject nonmatching jailid: "
|
||||
rm -f $playground/test-jail
|
||||
jailid=`jail -i / localhost 127.0.0.1 /usr/sbin/daemon -f /bin/sh -c "(sleep 3; touch $playground/test-jail) &"`
|
||||
sleep 6
|
||||
if [ -f $playground/test-jail ] ; then echo good ; fi
|
||||
|
||||
#
|
||||
# Object uid
|
||||
#
|
||||
ugidfw set 1 subject object uid $uidrange mode rasx
|
||||
echo -n "object uid in range: "
|
||||
su -fm $uidinrange -c "$command1 || echo good"
|
||||
echo -n "object uid out range: "
|
||||
su -fm $uidinrange -c "$command2 && echo good"
|
||||
ugidfw set 1 subject object uid $uidrange mode rasx
|
||||
echo -n "object uid in range (differennt subject): "
|
||||
su -fm $uidoutrange -c "$command1 || echo good"
|
||||
echo -n "object uid out range (differennt subject): "
|
||||
su -fm $uidoutrange -c "$command2 && echo good"
|
||||
|
||||
#
|
||||
# Object gid
|
||||
#
|
||||
ugidfw set 1 subject object gid $uidrange mode rasx
|
||||
echo -n "object gid in range: "
|
||||
su -fm $uidinrange -c "$command1 || echo good"
|
||||
echo -n "object gid out range: "
|
||||
su -fm $uidinrange -c "$command2 && echo good"
|
||||
echo -n "object gid in range (differennt subject): "
|
||||
su -fm $uidoutrange -c "$command1 || echo good"
|
||||
echo -n "object gid out range (differennt subject): "
|
||||
su -fm $uidoutrange -c "$command2 && echo good"
|
||||
|
||||
#
|
||||
# Object filesys
|
||||
#
|
||||
ugidfw set 1 subject uid $uidrange object filesys / mode rasx
|
||||
echo -n "object out of filesys: "
|
||||
su -fm $uidinrange -c "$command1 && echo good"
|
||||
ugidfw set 1 subject uid $uidrange object filesys $playground mode rasx
|
||||
echo -n "object in filesys: "
|
||||
su -fm $uidinrange -c "$command1 || echo good"
|
||||
|
||||
#
|
||||
# Object suid
|
||||
#
|
||||
ugidfw set 1 subject uid $uidrange object suid mode rasx
|
||||
echo -n "object notsuid: "
|
||||
su -fm $uidinrange -c "$command1 && echo good"
|
||||
chmod u+s $file1
|
||||
echo -n "object suid: "
|
||||
su -fm $uidinrange -c "$command1 || echo good"
|
||||
chmod u-s $file1
|
||||
|
||||
#
|
||||
# Object sgid
|
||||
#
|
||||
ugidfw set 1 subject uid $uidrange object sgid mode rasx
|
||||
echo -n "object notsgid: "
|
||||
su -fm $uidinrange -c "$command1 && echo good"
|
||||
chmod g+s $file1
|
||||
echo -n "object sgid: "
|
||||
su -fm $uidinrange -c "$command1 || echo good"
|
||||
chmod g-s $file1
|
||||
|
||||
#
|
||||
# Object uid matches subject
|
||||
#
|
||||
ugidfw set 1 subject uid $uidrange object uid_of_subject mode rasx
|
||||
echo -n "object uid notmatches subject: "
|
||||
su -fm $uidinrange -c "$command2 && echo good"
|
||||
echo -n "object uid matches subject: "
|
||||
su -fm $uidinrange -c "$command1 || echo good"
|
||||
|
||||
#
|
||||
# Object gid matches subject
|
||||
#
|
||||
ugidfw set 1 subject uid $uidrange object gid_of_subject mode rasx
|
||||
echo -n "object gid notmatches subject: "
|
||||
su -fm $uidinrange -c "$command2 && echo good"
|
||||
echo -n "object gid matches subject: "
|
||||
su -fm $uidinrange -c "$command1 || echo good"
|
||||
|
||||
#
|
||||
# Object type
|
||||
#
|
||||
ugidfw set 1 subject uid $uidrange object type dbclsp mode rasx
|
||||
echo -n "object not type: "
|
||||
su -fm $uidinrange -c "$command1 && echo good"
|
||||
ugidfw set 1 subject uid $uidrange object type r mode rasx
|
||||
echo -n "object type: "
|
||||
su -fm $uidinrange -c "$command1 || echo good"
|
||||
|
@ -26,8 +26,9 @@
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/mac.h>
|
||||
#include <sys/mount.h>
|
||||
|
||||
#include <security/mac_bsdextended/mac_bsdextended.h>
|
||||
|
||||
@ -104,6 +105,47 @@ static const char *test_strings[] = {
|
||||
"subject not uid operator object uid bin mode n",
|
||||
"subject uid bin object not uid operator mode n",
|
||||
"subject not uid daemon object not uid operator mode n",
|
||||
/* Ranges */
|
||||
"subject uid root:operator object gid wheel:bin mode n",
|
||||
/* Jail ID */
|
||||
"subject jailid 1 object uid root mode n",
|
||||
/* Filesys */
|
||||
"subject uid root object filesys / mode n",
|
||||
"subject uid root object filesys /dev mode n",
|
||||
/* S/UGID */
|
||||
"subject not uid root object sgid mode n",
|
||||
"subject not uid root object sgid mode n",
|
||||
/* Matching uid/gid */
|
||||
"subject not uid root:operator object not uid_of_subject mode n",
|
||||
"subject not gid wheel:bin object not gid_of_subject mode n",
|
||||
/* Object types */
|
||||
"subject uid root object type a mode a",
|
||||
"subject uid root object type r mode a",
|
||||
"subject uid root object type d mode a",
|
||||
"subject uid root object type b mode a",
|
||||
"subject uid root object type c mode a",
|
||||
"subject uid root object type l mode a",
|
||||
"subject uid root object type s mode a",
|
||||
"subject uid root object type rbc mode a",
|
||||
"subject uid root object type dls mode a",
|
||||
/* Empty rules always match */
|
||||
"subject object mode a",
|
||||
/* Partial negations */
|
||||
"subject ! uid root object mode n",
|
||||
"subject ! gid wheel object mode n",
|
||||
"subject ! jailid 2 object mode n",
|
||||
"subject object ! uid root mode n",
|
||||
"subject object ! gid wheel mode n",
|
||||
"subject object ! filesys / mode n",
|
||||
"subject object ! suid mode n",
|
||||
"subject object ! sgid mode n",
|
||||
"subject object ! uid_of_subject mode n",
|
||||
"subject object ! gid_of_subject mode n",
|
||||
"subject object ! type d mode n",
|
||||
/* All out nonsense */
|
||||
"subject uid root ! gid wheel:bin ! jailid 1 "
|
||||
"object ! uid root:daemon gid daemon filesys / suid sgid uid_of_subject gid_of_subject ! type r "
|
||||
"mode rsx",
|
||||
};
|
||||
static const int test_strings_len = sizeof(test_strings) / sizeof(char *);
|
||||
|
||||
@ -111,8 +153,8 @@ static void
|
||||
test_libugidfw_strings(void)
|
||||
{
|
||||
struct mac_bsdextended_rule rule;
|
||||
char errorstr[128];
|
||||
char rulestr[128];
|
||||
char errorstr[256];
|
||||
char rulestr[256];
|
||||
int i, error;
|
||||
|
||||
for (i = 0; i < test_users_len; i++) {
|
||||
@ -129,11 +171,11 @@ test_libugidfw_strings(void)
|
||||
|
||||
for (i = 0; i < test_strings_len; i++) {
|
||||
error = bsde_parse_rule_string(test_strings[i], &rule,
|
||||
128, errorstr);
|
||||
sizeof(errorstr), errorstr);
|
||||
if (error == -1)
|
||||
errx(-1, "bsde_parse_rule_string: '%s' (%d): %s",
|
||||
test_strings[i], i, errorstr);
|
||||
error = bsde_rule_to_string(&rule, rulestr, 128);
|
||||
error = bsde_rule_to_string(&rule, rulestr, sizeof(rulestr));
|
||||
if (error < 0)
|
||||
errx(-1, "bsde_rule_to_string: rule for '%s' "
|
||||
"returned %d", test_strings[i], error);
|
||||
@ -147,7 +189,7 @@ test_libugidfw_strings(void)
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
char errorstr[128];
|
||||
char errorstr[256];
|
||||
int count, slots;
|
||||
|
||||
if (argc != 1)
|
||||
@ -182,13 +224,13 @@ main(int argc, char *argv[])
|
||||
* starting, but "slots" is a property of prior runs and so we ignore
|
||||
* the return value.
|
||||
*/
|
||||
count = bsde_get_rule_count(128, errorstr);
|
||||
count = bsde_get_rule_count(sizeof(errorstr), errorstr);
|
||||
if (count == -1)
|
||||
errx(-1, "bsde_get_rule_count: %s", errorstr);
|
||||
if (count != 0)
|
||||
errx(-1, "bsde_get_rule_count: %d rules", count);
|
||||
|
||||
slots = bsde_get_rule_slots(128, errorstr);
|
||||
slots = bsde_get_rule_slots(sizeof(errorstr), errorstr);
|
||||
if (slots == -1)
|
||||
errx(-1, "bsde_get_rule_slots: %s", errorstr);
|
||||
|
||||
|
@ -41,12 +41,52 @@
|
||||
.Cm add
|
||||
.Cm subject
|
||||
.Op Cm not
|
||||
.Op Cm uid Ar uid
|
||||
.Op Cm gid Ar gid
|
||||
.Oo
|
||||
.Op Cm \&!
|
||||
.Cm uid Ar uid | minuid:maxuid
|
||||
.Oc
|
||||
.Oo
|
||||
.Op Cm \&!
|
||||
.Cm gid Ar gid | mingid:maxgid
|
||||
.Oc
|
||||
.Oo
|
||||
.Op Cm \&!
|
||||
.Cm jailid Ad jailid
|
||||
.Oc
|
||||
.Cm object
|
||||
.Op Cm not
|
||||
.Op Cm uid Ar uid
|
||||
.Op Cm gid Ar gid
|
||||
.Oo
|
||||
.Op Cm \&!
|
||||
.Cm uid Ar uid | minuid:maxuid
|
||||
.Oc
|
||||
.Oo
|
||||
.Op Cm \&!
|
||||
.Cm gid Ar gid | mingid:maxgid
|
||||
.Oc
|
||||
.Oo
|
||||
.Op Cm \&!
|
||||
.Cm filesys Ad path
|
||||
.Oc
|
||||
.Oo
|
||||
.Op Cm \&!
|
||||
.Cm suid
|
||||
.Oc
|
||||
.Oo
|
||||
.Op Cm \&!
|
||||
.Cm sgid
|
||||
.Oc
|
||||
.Oo
|
||||
.Op Cm \&!
|
||||
.Cm uid_of_subject
|
||||
.Oc
|
||||
.Oo
|
||||
.Op Cm \&!
|
||||
.Cm gid_of_subject
|
||||
.Oc
|
||||
.Oo
|
||||
.Op Cm \&!
|
||||
.Cm type Ar ardbclsp
|
||||
.Oc
|
||||
.Cm mode
|
||||
.Ar arswxn
|
||||
.Nm
|
||||
@ -56,12 +96,52 @@
|
||||
.Ar rulenum
|
||||
.Cm subject
|
||||
.Op Cm not
|
||||
.Op Cm uid Ar uid
|
||||
.Op Cm gid Ar gid
|
||||
.Oo
|
||||
.Op Cm \&!
|
||||
.Cm uid Ar uid | minuid:maxuid
|
||||
.Oc
|
||||
.Oo
|
||||
.Op Cm \&!
|
||||
.Cm gid Ar gid | mingid:maxgid
|
||||
.Oc
|
||||
.Oo
|
||||
.Op Cm \&!
|
||||
.Cm jailid Ad jailid
|
||||
.Oc
|
||||
.Cm object
|
||||
.Op Cm not
|
||||
.Op Cm uid Ar uid
|
||||
.Op Cm gid Ar gid
|
||||
.Oo
|
||||
.Op Cm \&!
|
||||
.Cm uid Ar uid | minuid:maxuid
|
||||
.Oc
|
||||
.Oo
|
||||
.Op Cm \&!
|
||||
.Cm gid Ar gid | mingid:maxgid
|
||||
.Oc
|
||||
.Oo
|
||||
.Op Cm \&!
|
||||
.Cm filesys Ad path
|
||||
.Oc
|
||||
.Oo
|
||||
.Op Cm \&!
|
||||
.Cm suid
|
||||
.Oc
|
||||
.Oo
|
||||
.Op Cm \&!
|
||||
.Cm sgid
|
||||
.Oc
|
||||
.Oo
|
||||
.Op Cm \&!
|
||||
.Cm uid_of_subject
|
||||
.Oc
|
||||
.Oo
|
||||
.Op Cm \&!
|
||||
.Cm gid_of_subject
|
||||
.Oc
|
||||
.Oo
|
||||
.Op Cm \&!
|
||||
.Cm type Ar ardbclsp
|
||||
.Oc
|
||||
.Cm mode
|
||||
.Ar arswxn
|
||||
.Nm
|
||||
@ -80,20 +160,12 @@ policy.
|
||||
.Pp
|
||||
The arguments are as follows:
|
||||
.Bl -tag -width indent -offset indent
|
||||
.It Cm add
|
||||
Add a new
|
||||
.Nm
|
||||
rule.
|
||||
.It Xo
|
||||
.Cm add
|
||||
.Cm subject
|
||||
.Op Cm not
|
||||
.Op Cm uid Ar uid
|
||||
.Op Cm gid Ar gid
|
||||
.Ar ...
|
||||
.Cm object
|
||||
.Op Cm not
|
||||
.Op Cm uid Ar uid
|
||||
.Op Cm gid Ar gid
|
||||
.Ar ...
|
||||
.Cm mode
|
||||
.Ar arswxn
|
||||
.Xc
|
||||
@ -108,13 +180,9 @@ rules in the system.
|
||||
.It Xo
|
||||
.Cm set Ar rulenum
|
||||
.Cm subject
|
||||
.Op Cm not
|
||||
.Op Cm uid Ar uid
|
||||
.Op Cm gid Ar gid
|
||||
.Ar ...
|
||||
.Cm object
|
||||
.Op Cm not
|
||||
.Op Cm uid Ar uid
|
||||
.Op Cm gid Ar gid
|
||||
.Ar ...
|
||||
.Cm mode
|
||||
.Ar arswxn
|
||||
.Xc
|
||||
@ -131,37 +199,120 @@ will yield a slight performance increase.
|
||||
.It Xo
|
||||
.Cm subject
|
||||
.Op Cm not
|
||||
.Op Cm uid Ar uid
|
||||
.Op Cm gid Ar gid
|
||||
.Oo
|
||||
.Op Cm \&!
|
||||
.Cm uid Ar uid | minuid:maxuid
|
||||
.Oc
|
||||
.Oo
|
||||
.Op Cm \&!
|
||||
.Cm gid Ar gid | mingid:maxgid
|
||||
.Oc
|
||||
.Oo
|
||||
.Op Cm \&!
|
||||
.Cm jailid Ad jailid
|
||||
.Oc
|
||||
.Xc
|
||||
Subjects performing an operation must match
|
||||
(or, if
|
||||
Subjects performing an operation must match all the conditions given.
|
||||
A leading
|
||||
.Cm not
|
||||
is specified, must
|
||||
.Em not
|
||||
match)
|
||||
the user and group specified by
|
||||
means that the subject should not match the remainder of the specification.
|
||||
A condition may be prefixed by
|
||||
.Cm \&!
|
||||
to indicate that particular condition must not match the subject.
|
||||
The subject can be required to have a particular
|
||||
.Ar uid
|
||||
and/or
|
||||
.Ar gid
|
||||
for the rule to be applied.
|
||||
.Ar gid .
|
||||
A range of uids/gids can be specified,
|
||||
seperated by a colon.
|
||||
The subject can be required to be in a particular jail with the
|
||||
.Ar jailid .
|
||||
.It Xo
|
||||
.Cm object
|
||||
.Op Cm not
|
||||
.Op Cm uid Ar uid
|
||||
.Op Cm gid Ar gid
|
||||
.Oo
|
||||
.Op Cm \&!
|
||||
.Cm uid Ar uid | minuid:maxuid
|
||||
.Oc
|
||||
.Oo
|
||||
.Op Cm \&!
|
||||
.Cm gid Ar gid | mingid:maxgid
|
||||
.Oc
|
||||
.Oo
|
||||
.Op Cm \&!
|
||||
.Cm filesys Ad path
|
||||
.Oc
|
||||
.Oo
|
||||
.Op Cm \&!
|
||||
.Cm suid
|
||||
.Oc
|
||||
.Oo
|
||||
.Op Cm \&!
|
||||
.Cm sgid
|
||||
.Oc
|
||||
.Oo
|
||||
.Op Cm \&!
|
||||
.Cm uid_of_subject
|
||||
.Oc
|
||||
.Oo
|
||||
.Op Cm \&!
|
||||
.Cm gid_of_subject
|
||||
.Oc
|
||||
.Oo
|
||||
.Op Cm \&!
|
||||
.Cm type Ar ardbclsp
|
||||
.Oc
|
||||
.Xc
|
||||
Objects must be owned by
|
||||
(or, if
|
||||
The rule will apply only to objects matching all the specified conditions.
|
||||
A leading
|
||||
.Cm not
|
||||
is specified, must
|
||||
.Em not
|
||||
be owned by)
|
||||
the user and/or group specified by
|
||||
means that the object should not match all the remaining conditions.
|
||||
A condition may be prefixed by
|
||||
.Cm \&!
|
||||
to indicate that particular condition must not match the object.
|
||||
Objects can be required to be owned by the user and/or group specified by
|
||||
.Ar uid
|
||||
and/or
|
||||
.Ar gid
|
||||
for the rule to be applied.
|
||||
.Ar gid .
|
||||
A range of uids/gids can be specified, seperated by a colon.
|
||||
The object can be required to be in a particular filesystem by
|
||||
specifing the filesystem using
|
||||
.Cm filesys .
|
||||
Note,
|
||||
if the filesystem is unmounted and remounted,
|
||||
then the rule may need to be reapplied to ensure the correct filesystem
|
||||
id is used.
|
||||
The object can be required to have the
|
||||
.Cm suid
|
||||
or
|
||||
.Cm sgid
|
||||
bits set.
|
||||
The owner of the object can be required to match the
|
||||
.Cm uid_of_subject
|
||||
or the
|
||||
.Cm gid_of_subject
|
||||
attempting the operation.
|
||||
The type of the object can be restricted to a subset of
|
||||
the following types.
|
||||
.Pp
|
||||
.Bl -tag -width ".Cm w" -compact -offset indent
|
||||
.It Cm a
|
||||
any file type
|
||||
.It Cm r
|
||||
a regular file
|
||||
.It Cm d
|
||||
a directory
|
||||
.It Cm b
|
||||
a block special device
|
||||
.It Cm c
|
||||
a character special device
|
||||
.It Cm l
|
||||
a symbolic link
|
||||
.It Cm s
|
||||
a unix domain socket
|
||||
.It Cm p
|
||||
a named pipe (FIFO)
|
||||
.El
|
||||
.It Cm mode Ar arswxn
|
||||
Similar to
|
||||
.Xr chmod 1 ,
|
||||
|
@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user