--- share/man/man4/mac_portacl.4.orig +++ share/man/man4/mac_portacl.4 @@ -109,7 +109,7 @@ .Xr sysctl 8 variable .Va security.mac.portacl.suser_exempt -is set to a non-zero value. +is set to 1 (only unjailed superusers) or 2 (unjailed and jailed superusers). .Ss Runtime Configuration The following .Xr sysctl 8 @@ -145,11 +145,13 @@ Describes the type of subject match to be performed. Either .Li uid -for user ID matching, or +for user ID matching, .Li gid -for group ID matching. +for group ID matching, or +.Li jail +for jail name matching. .It Ar id -The user or group ID (depending on +The user ID, group ID or jail name (depending on .Ar idtype ) allowed to bind to the specified port. .Bf -emphasis @@ -174,15 +176,17 @@ If the specified port falls within the range specified, the .Nm entry will not function -(i.e., even the specified user/group may not be able to bind to the specified -port). +(i.e., even the specified user/group/jail may not be able to bind to the +specified port). .El .It Va security.mac.portacl.suser_exempt Allow superuser (i.e., root) to bind to all .Nm protected ports, even if the port access control list does not explicitly allow this. -(Default: 1). +Set to 1 to allow only unjailed superusers, set to 2 to allow any superuser +(jailed and unjailed) or set to 0 to turn off exemptions. +(Default: 2). .It Va security.mac.portacl.autoport_exempt Allow applications to use automatic binding to port 0. Applications use port 0 as a request for automatic port allocation when @@ -216,3 +220,5 @@ Inc.\& under DARPA/SPAWAR contract N66001-01-C-8035 .Pq Dq CBOSS , as part of the DARPA CHATS research program. +The jail support was implemented by +.An Pawel Jakub Dawidek Aq pjd@FreeBSD.org . --- sys/security/mac_portacl/mac_portacl.c.orig +++ sys/security/mac_portacl/mac_portacl.c @@ -32,7 +32,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/sys/security/mac_portacl/mac_portacl.c,v 1.21 2009/03/14 20:40:06 pjd Exp $ + * $FreeBSD: src/sys/security/mac_portacl/mac_portacl.c,v 1.20 2009/01/10 10:58:41 rwatson Exp $ */ /* @@ -61,15 +61,16 @@ #include #include +#include #include #include #include #include -#include #include #include #include #include +#include #include #include #include @@ -91,18 +92,21 @@ &portacl_enabled, 0, "Enforce portacl policy"); TUNABLE_INT("security.mac.portacl.enabled", &portacl_enabled); -static int portacl_suser_exempt = 1; +/* + * 0 - No exemptions. + * 1 - Exempt unjailed processes that hold PRIV_NETINET_RESERVEDPORT privilege. + * 2 - Exempt any process that holds PRIV_NETINET_RESERVEDPORT privilege. + */ +static int portacl_suser_exempt = 2; SYSCTL_INT(_security_mac_portacl, OID_AUTO, suser_exempt, CTLFLAG_RW, &portacl_suser_exempt, 0, "Privilege permits binding of any port"); -TUNABLE_INT("security.mac.portacl.suser_exempt", - &portacl_suser_exempt); +TUNABLE_INT("security.mac.portacl.suser_exempt", &portacl_suser_exempt); static int portacl_autoport_exempt = 1; SYSCTL_INT(_security_mac_portacl, OID_AUTO, autoport_exempt, CTLFLAG_RW, &portacl_autoport_exempt, 0, "Allow automatic allocation through " "binding port 0 if not IP_PORTRANGELOW"); -TUNABLE_INT("security.mac.portacl.autoport_exempt", - &portacl_autoport_exempt); +TUNABLE_INT("security.mac.portacl.autoport_exempt", &portacl_autoport_exempt); static int portacl_port_high = 1023; SYSCTL_INT(_security_mac_portacl, OID_AUTO, port_high, CTLFLAG_RW, @@ -111,24 +115,33 @@ MALLOC_DEFINE(M_PORTACL, "portacl_rule", "Rules for mac_portacl"); -#define MAC_RULE_STRING_LEN 1024 +#define MAC_RULE_STRING_LEN 16384 #define RULE_GID 1 #define RULE_UID 2 +#define RULE_JAIL 3 + #define RULE_PROTO_TCP 1 #define RULE_PROTO_UDP 2 + struct rule { - id_t r_id; + union { + id_t ur_numid; + char ur_strid[MAXHOSTNAMELEN]; + } __rule_id; int r_idtype; u_int16_t r_port; int r_protocol; TAILQ_ENTRY(rule) r_entries; }; +#define r_numid __rule_id.ur_numid +#define r_strid __rule_id.ur_strid #define GID_STRING "gid" +#define UID_STRING "uid" +#define JAIL_STRING "jail" #define TCP_STRING "tcp" -#define UID_STRING "uid" #define UDP_STRING "udp" /* @@ -138,7 +151,7 @@ * for the specified binding. */ -static struct mtx rule_mtx; +static struct rmlock rule_lock; static TAILQ_HEAD(rulehead, rule) rule_head; static char rule_string[MAC_RULE_STRING_LEN]; @@ -161,7 +174,7 @@ destroy(struct mac_policy_conf *mpc) { - mtx_destroy(&rule_mtx); + rm_destroy(&rule_lock); toast_rules(&rule_head); } @@ -169,7 +182,7 @@ init(struct mac_policy_conf *mpc) { - mtx_init(&rule_mtx, "rule_mtx", NULL, MTX_DEF); + rm_init(&rule_lock, "rule_lock", 0); TAILQ_INIT(&rule_head); } @@ -191,23 +204,30 @@ error = EINVAL; goto out; } - id = strsep(&element, ":"); - if (id == NULL) { + if (strcmp(idtype, UID_STRING) == 0) + new->r_idtype = RULE_UID; + else if (strcmp(idtype, GID_STRING) == 0) + new->r_idtype = RULE_GID; + else if (strcmp(idtype, JAIL_STRING) == 0) + new->r_idtype = RULE_JAIL; + else { error = EINVAL; goto out; } - new->r_id = strtol(id, &p, 10); - if (*p != '\0') { + + id = strsep(&element, ":"); + if (id == NULL) { error = EINVAL; goto out; } - if (strcmp(idtype, UID_STRING) == 0) - new->r_idtype = RULE_UID; - else if (strcmp(idtype, GID_STRING) == 0) - new->r_idtype = RULE_GID; + if (new->r_idtype == RULE_JAIL) + strlcpy(new->r_strid, id, sizeof(new->r_strid)); else { - error = EINVAL; - goto out; + new->r_numid = strtol(id, &p, 10); + if (*p != '\0') { + error = EINVAL; + goto out; + } } protocol = strsep(&element, ":"); if (protocol == NULL) { @@ -283,6 +303,9 @@ case RULE_UID: idtype = UID_STRING; break; + case RULE_JAIL: + idtype = JAIL_STRING; + break; default: panic("rule_printf: unknown idtype (%d)\n", rule->r_idtype); } @@ -298,13 +321,20 @@ panic("rule_printf: unknown protocol (%d)\n", rule->r_protocol); } - sbuf_printf(sb, "%s:%jd:%s:%d", idtype, (intmax_t)rule->r_id, - protocol, rule->r_port); + + if (rule->r_idtype == RULE_JAIL) { + sbuf_printf(sb, "%s:%s:%s:%u", idtype, rule->r_strid, protocol, + (u_int)rule->r_port); + } else { + sbuf_printf(sb, "%s:%jd:%s:%u", idtype, (intmax_t)rule->r_numid, + protocol, (u_int)rule->r_port); + } } static char * rules_to_string(void) { + struct rm_priotracker prtr; struct rule *rule; struct sbuf *sb; int needcomma; @@ -312,16 +342,15 @@ sb = sbuf_new_auto(); needcomma = 0; - mtx_lock(&rule_mtx); - for (rule = TAILQ_FIRST(&rule_head); rule != NULL; - rule = TAILQ_NEXT(rule, r_entries)) { + rm_rlock(&rule_lock, &prtr); + TAILQ_FOREACH(rule, &rule_head, r_entries) { if (!needcomma) needcomma = 1; else sbuf_printf(sb, ","); rule_printf(sb, rule); } - mtx_unlock(&rule_mtx); + rm_runlock(&rule_lock, &prtr); sbuf_finish(sb); temp = strdup(sbuf_data(sb), M_PORTACL); sbuf_delete(sb); @@ -338,15 +367,16 @@ { char *string, *copy_string, *new_string; struct rulehead head, save_head; + struct rm_priotracker prtr; int error; new_string = NULL; if (req->newptr != NULL) { new_string = malloc(MAC_RULE_STRING_LEN, M_PORTACL, M_WAITOK | M_ZERO); - mtx_lock(&rule_mtx); + rm_rlock(&rule_lock, &prtr); strcpy(new_string, rule_string); - mtx_unlock(&rule_mtx); + rm_runlock(&rule_lock, &prtr); string = new_string; } else string = rule_string; @@ -364,11 +394,11 @@ goto out; TAILQ_INIT(&save_head); - mtx_lock(&rule_mtx); + rm_wlock(&rule_lock); TAILQ_CONCAT(&save_head, &rule_head, r_entries); TAILQ_CONCAT(&rule_head, &head, r_entries); strcpy(rule_string, string); - mtx_unlock(&rule_mtx); + rm_wunlock(&rule_lock); toast_rules(&save_head); } out: @@ -378,11 +408,12 @@ } SYSCTL_PROC(_security_mac_portacl, OID_AUTO, rules, - CTLTYPE_STRING|CTLFLAG_RW, 0, 0, sysctl_rules, "A", "Rules"); + CTLTYPE_STRING|CTLFLAG_RW, 0, 0, sysctl_rules, "A", "Rules"); static int rules_check(struct ucred *cred, int family, int type, u_int16_t port) { + struct rm_priotracker prtr; struct rule *rule; int error; @@ -395,37 +426,46 @@ return (0); error = EPERM; - mtx_lock(&rule_mtx); - for (rule = TAILQ_FIRST(&rule_head); - rule != NULL; - rule = TAILQ_NEXT(rule, r_entries)) { + rm_rlock(&rule_lock, &prtr); + TAILQ_FOREACH(rule, &rule_head, r_entries) { if (type == SOCK_DGRAM && rule->r_protocol != RULE_PROTO_UDP) continue; if (type == SOCK_STREAM && rule->r_protocol != RULE_PROTO_TCP) continue; if (port != rule->r_port) continue; - if (rule->r_idtype == RULE_UID) { - if (cred->cr_uid == rule->r_id) { + switch (rule->r_idtype) { + case RULE_UID: + if (cred->cr_uid == rule->r_numid) + error = 0; + break; + case RULE_GID: + if (cred->cr_gid == rule->r_numid) error = 0; - break; - } - } else if (rule->r_idtype == RULE_GID) { - if (cred->cr_gid == rule->r_id) { + else if (groupmember(rule->r_numid, cred)) error = 0; - break; - } else if (groupmember(rule->r_id, cred)) { + break; + case RULE_JAIL: + if (jailed(cred) && + strcmp(cred->cr_prison->pr_name, rule->r_strid) == 0) error = 0; - break; - } - } else + break; + default: panic("rules_check: unknown rule type %d", rule->r_idtype); + } + if (error == 0) + break; } - mtx_unlock(&rule_mtx); + rm_runlock(&rule_lock, &prtr); + + if (error == 0 || portacl_suser_exempt == 0) + return (error); - if (error != 0 && portacl_suser_exempt != 0) + if (portacl_suser_exempt == 2 || + (portacl_suser_exempt == 1 && !jailed(cred))) { error = priv_check_cred(cred, PRIV_NETINET_RESERVEDPORT, 0); + } return (error); } @@ -436,7 +476,7 @@ * the source port is left up to the IP stack to determine automatically. */ static int -socket_check_bind(struct ucred *cred, struct socket *so, +portacl_socket_check_bind(struct ucred *cred, struct socket *so, struct label *solabel, struct sockaddr *sa) { struct sockaddr_in *sin; @@ -488,7 +528,7 @@ { .mpo_destroy = destroy, .mpo_init = init, - .mpo_socket_check_bind = socket_check_bind, + .mpo_socket_check_bind = portacl_socket_check_bind, }; MAC_POLICY_SET(&portacl_ops, mac_portacl, "TrustedBSD MAC/portacl", --- tools/regression/mac/mac_portacl/LICENSE.orig +++ tools/regression/mac/mac_portacl/LICENSE @@ -1,4 +1,4 @@ -$FreeBSD: src/tools/regression/mac/mac_portacl/LICENSE,v 1.2 2009/03/14 21:59:12 pjd Exp $ +$FreeBSD$ License for all mac_portacl regression tests: --- /dev/null 2009-05-23 21:30:12.000000000 +0200 +++ tools/regression/mac/mac_portacl/Makefile 2009-05-23 21:30:13.372894117 +0200 @@ -0,0 +1,8 @@ +# $FreeBSD$ + +PROG= sobind +SRCS= sobind.c +CFLAGS+=-Wall +NO_MAN= + +.include --- /dev/null 2009-05-23 21:30:12.000000000 +0200 +++ tools/regression/mac/mac_portacl/autoport_exempt.t 2009-05-23 21:30:14.672894816 +0200 @@ -0,0 +1,100 @@ +#!/bin/sh + +dir=`dirname $0` +. ${dir}/misc.sh + +echo "1..48" + +# Check if security.mac.portacl.autoport_exempt works properly. + +sysctl security.mac.portacl.suser_exempt=0 >/dev/null + +sysctl security.mac.portacl.autoport_exempt=1 >/dev/null + +expect_ok sobind -u 0 tcp 0 +expect_ok sobind -u 0 udp 0 + +expect_ok sobind -j sobind_test -u 0 tcp 0 +expect_ok sobind -j sobind_test -u 0 udp 0 + +expect_ok sobind -u 65535 tcp 0 +expect_ok sobind -u 65535 udp 0 + +expect_ok sobind -j sobind_test -u 65535 tcp 0 +expect_ok sobind -j sobind_test -u 65535 udp 0 + +sysctl security.mac.portacl.autoport_exempt=0 >/dev/null + +expect_fl sobind -u 0 tcp 0 +expect_fl sobind -u 0 udp 0 + +expect_fl sobind -j sobind_test -u 0 tcp 0 +expect_fl sobind -j sobind_test -u 0 udp 0 + +expect_fl sobind -u 65535 tcp 0 +expect_fl sobind -u 65535 udp 0 + +expect_fl sobind -j sobind_test -u 65535 tcp 0 +expect_fl sobind -j sobind_test -u 65535 udp 0 + +sysctl security.mac.portacl.suser_exempt=1 >/dev/null + +sysctl security.mac.portacl.autoport_exempt=1 >/dev/null + +expect_ok sobind -u 0 tcp 0 +expect_ok sobind -u 0 udp 0 + +expect_ok sobind -j sobind_test -u 0 tcp 0 +expect_ok sobind -j sobind_test -u 0 udp 0 + +expect_ok sobind -u 65535 tcp 0 +expect_ok sobind -u 65535 udp 0 + +expect_ok sobind -j sobind_test -u 65535 tcp 0 +expect_ok sobind -j sobind_test -u 65535 udp 0 + +sysctl security.mac.portacl.autoport_exempt=0 >/dev/null + +expect_ok sobind -u 0 tcp 0 +expect_ok sobind -u 0 udp 0 + +expect_fl sobind -j sobind_test -u 0 tcp 0 +expect_fl sobind -j sobind_test -u 0 udp 0 + +expect_fl sobind -u 65535 tcp 0 +expect_fl sobind -u 65535 udp 0 + +expect_fl sobind -j sobind_test -u 65535 tcp 0 +expect_fl sobind -j sobind_test -u 65535 udp 0 + +sysctl security.mac.portacl.suser_exempt=2 >/dev/null + +sysctl security.mac.portacl.autoport_exempt=1 >/dev/null + +expect_ok sobind -u 0 tcp 0 +expect_ok sobind -u 0 udp 0 + +expect_ok sobind -j sobind_test -u 0 tcp 0 +expect_ok sobind -j sobind_test -u 0 udp 0 + +expect_ok sobind -u 65535 tcp 0 +expect_ok sobind -u 65535 udp 0 + +expect_ok sobind -j sobind_test -u 65535 tcp 0 +expect_ok sobind -j sobind_test -u 65535 udp 0 + +sysctl security.mac.portacl.autoport_exempt=0 >/dev/null + +expect_ok sobind -u 0 tcp 0 +expect_ok sobind -u 0 udp 0 + +expect_ok sobind -j sobind_test -u 0 tcp 0 +expect_ok sobind -j sobind_test -u 0 udp 0 + +expect_fl sobind -u 65535 tcp 0 +expect_fl sobind -u 65535 udp 0 + +expect_fl sobind -j sobind_test -u 65535 tcp 0 +expect_fl sobind -j sobind_test -u 65535 udp 0 + +restore_settings --- /dev/null 2009-05-23 21:30:12.000000000 +0200 +++ tools/regression/mac/mac_portacl/gid.t 2009-05-23 21:30:16.000894603 +0200 @@ -0,0 +1,32 @@ +#!/bin/sh + +dir=`dirname $0` +. ${dir}/misc.sh + +echo "1..32" + +sysctl security.mac.portacl.suser_exempt=0 >/dev/null +sysctl net.inet.ip.portrange.reservedhigh=0 >/dev/null +sysctl security.mac.portacl.port_high=1023 >/dev/null + +bind_test fl ok gid 0 tcp 777 +bind_test ok ok gid 0 tcp 7777 +bind_test fl fl gid 0 tcp 777 778 +bind_test ok ok gid 0 tcp 7777 7778 + +bind_test fl ok gid 65535 tcp 777 +bind_test ok ok gid 65535 tcp 7777 +bind_test fl fl gid 65535 tcp 777 778 +bind_test ok ok gid 65535 tcp 7777 7778 + +bind_test fl ok gid 0 udp 777 +bind_test ok ok gid 0 udp 7777 +bind_test fl fl gid 0 udp 777 778 +bind_test ok ok gid 0 udp 7777 7778 + +bind_test fl ok gid 65535 udp 777 +bind_test ok ok gid 65535 udp 7777 +bind_test fl fl gid 65535 udp 777 778 +bind_test ok ok gid 65535 udp 7777 7778 + +restore_settings --- /dev/null 2009-05-23 21:30:17.000000000 +0200 +++ tools/regression/mac/mac_portacl/jail.t 2009-05-23 21:30:17.343894622 +0200 @@ -0,0 +1,32 @@ +#!/bin/sh + +dir=`dirname $0` +. ${dir}/misc.sh + +echo "1..32" + +sysctl security.mac.portacl.suser_exempt=0 >/dev/null +sysctl net.inet.ip.portrange.reservedhigh=0 >/dev/null +sysctl security.mac.portacl.port_high=1023 >/dev/null + +bind_test fl ok jail sobind tcp 777 +bind_test ok ok jail sobind tcp 7777 +bind_test fl fl jail sobind tcp 777 778 +bind_test ok ok jail sobind tcp 7777 7778 + +bind_test fl ok jail sobind tcp 777 +bind_test ok ok jail sobind tcp 7777 +bind_test fl fl jail sobind tcp 777 778 +bind_test ok ok jail sobind tcp 7777 7778 + +bind_test fl ok jail sobind udp 777 +bind_test ok ok jail sobind udp 7777 +bind_test fl fl jail sobind udp 777 778 +bind_test ok ok jail sobind udp 7777 7778 + +bind_test fl ok jail sobind udp 777 +bind_test ok ok jail sobind udp 7777 +bind_test fl fl jail sobind udp 777 778 +bind_test ok ok jail sobind udp 7777 7778 + +restore_settings --- tools/regression/mac/mac_portacl/misc.sh.orig +++ tools/regression/mac/mac_portacl/misc.sh @@ -1,5 +1,4 @@ #!/bin/sh -# $FreeBSD: src/tools/regression/mac/mac_portacl/misc.sh,v 1.1 2009/03/14 21:54:19 pjd Exp $ sysctl security.mac.portacl >/dev/null 2>&1 if [ $? -ne 0 ]; then @@ -7,83 +6,104 @@ echo "not ok 1 # MAC_PORTACL is unavailable." exit 0 fi +export PATH=${PATH}:${dir} ntest=1 -check_bind() { - idtype=${1} - name=${2} - proto=${3} - port=${4} +isnumber() { + echo ${1} | egrep -q '^[0-9]+$' + return $? +} - [ "${proto}" = "udp" ] && udpflag="-u" +bind_test() { + expect_without_rule=${1} + expect_with_rule=${2} + idtype=${3} + idstr=${4} + proto=${5} + ruleport=${6} + bindport=${7} + if [ -z "${bindport}" ]; then + bindport=${ruleport} + fi - out=`( - case "${idtype}" in - uid|gid) - ( echo -n | su -m ${name} -c "nc ${udpflag} -o -l 127.0.0.1 $port" 2>&1 ) & - ;; - jail) - kill $$ - ;; - *) - kill $$ - esac - sleep 0.3 - echo | nc ${udpflag} -o 127.0.0.1 $port >/dev/null 2>&1 - wait - )` - case "${out}" in - "nc: Permission denied"*|"nc: Operation not permitted"*) - echo fl + case "${idtype}" in + uid) + flag="-u" + if ! isnumber ${idstr}; then + idstr=`id -u ${idstr}` + fi + ;; + gid) + flag="-g" + if ! isnumber ${idstr}; then + idstr=`id -g ${idstr}` + fi ;; - "") - echo ok + jail) + flag="-j" ;; *) - echo ${out} + echo "Invalid idtype: ${idtype}" >/dev/stderr + exit 1 ;; esac -} -bind_test() { - expect_without_rule=${1} - expect_with_rule=${2} - idtype=${3} - name=${4} - proto=${5} - port=${6} + sysctl security.mac.portacl.rules= >/dev/null - sysctl security.mac.portacl.rules= >/dev/null - out=`check_bind ${idtype} ${name} ${proto} ${port}` - if [ "${out}" = "${expect_without_rule}" ]; then + out=`sobind ${flag} ${idstr} ${proto} ${bindport} 2>&1` + ec=$? + if [ "${expect_without_rule}" = "ok" -a $ec -eq 0 ]; then + echo "ok ${ntest}" + elif [ "${expect_without_rule}" = "fl" -a $ec -ne 0 ]; then echo "ok ${ntest}" - elif [ "${out}" = "ok" -o "${out}" = "fl" ]; then + elif [ "${expect_without_rule}" = "ok" ]; then + echo "not ok ${ntest} ${out}" + else echo "not ok ${ntest}" + fi + ntest=$((ntest+1)) + + sysctl security.mac.portacl.rules=${idtype}:${idstr}:${proto}:${ruleport} >/dev/null + + out=`sobind ${flag} ${idstr} ${proto} ${bindport} 2>&1` + ec=$? + if [ "${expect_with_rule}" = "ok" -a $ec -eq 0 ]; then + echo "ok ${ntest}" + elif [ "${expect_with_rule}" = "fl" -a $ec -ne 0 ]; then + echo "ok ${ntest}" + elif [ "${expect_with_rule}" = "ok" ]; then + echo "not ok ${ntest} ${out}" else - echo "not ok ${ntest} # ${out}" + echo "not ok ${ntest}" fi ntest=$((ntest+1)) - if [ "${idtype}" = "uid" ]; then - idstr=`id -u ${name}` - elif [ "${idtype}" = "gid" ]; then - idstr=`id -g ${name}` + sysctl security.mac.portacl.rules= >/dev/null +} + +expect_ok() +{ + out=`$* 2>&1` + ec=$? + if [ $ec -eq 0 ]; then + echo "ok ${ntest}" else - idstr=${name} + echo "not ok ${ntest} ${out}" fi - sysctl security.mac.portacl.rules=${idtype}:${idstr}:${proto}:${port} >/dev/null - out=`check_bind ${idtype} ${name} ${proto} ${port}` - if [ "${out}" = "${expect_with_rule}" ]; then + ntest=$((ntest+1)) +} + +expect_fl() +{ + out=`$* 2>&1` + ec=$? + if [ $ec -ne 0 ]; then echo "ok ${ntest}" - elif [ "${out}" = "ok" -o "${out}" = "fl" ]; then + else echo "not ok ${ntest}" - else - echo "not ok ${ntest} # ${out}" fi ntest=$((ntest+1)) - - sysctl security.mac.portacl.rules= >/dev/null } reserved_high=`sysctl -n net.inet.ip.portrange.reservedhigh` --- tools/regression/mac/mac_portacl/nobody.t 2009-05-23 21:30:18.760895106 +0200 +++ /dev/null 2009-05-23 21:30:17.000000000 +0200 @@ -1,67 +0,0 @@ -#!/bin/sh -# $FreeBSD: src/tools/regression/mac/mac_portacl/nobody.t,v 1.1 2009/03/14 21:54:19 pjd Exp $ - -dir=`dirname $0` -. ${dir}/misc.sh - -echo "1..64" - -# security.mac.portacl.suser_exempt value doesn't affect unprivileged users -# behaviour. -# mac_portacl has no impact on ports <= net.inet.ip.portrange.reservedhigh. - -sysctl security.mac.portacl.suser_exempt=1 >/dev/null -sysctl net.inet.ip.portrange.reservedhigh=78 >/dev/null - -bind_test fl fl uid nobody tcp 77 -bind_test ok ok uid nobody tcp 7777 -bind_test fl fl uid nobody udp 77 -bind_test ok ok uid nobody udp 7777 - -bind_test fl fl gid nobody tcp 77 -bind_test ok ok gid nobody tcp 7777 -bind_test fl fl gid nobody udp 77 -bind_test ok ok gid nobody udp 7777 - -sysctl security.mac.portacl.suser_exempt=0 >/dev/null - -bind_test fl fl uid nobody tcp 77 -bind_test ok ok uid nobody tcp 7777 -bind_test fl fl uid nobody udp 77 -bind_test ok ok uid nobody udp 7777 - -bind_test fl fl gid nobody tcp 77 -bind_test ok ok gid nobody tcp 7777 -bind_test fl fl gid nobody udp 77 -bind_test ok ok gid nobody udp 7777 - -# Verify if security.mac.portacl.port_high works. - -sysctl security.mac.portacl.port_high=7778 >/dev/null - -bind_test fl fl uid nobody tcp 77 -bind_test fl ok uid nobody tcp 7777 -bind_test fl fl uid nobody udp 77 -bind_test fl ok uid nobody udp 7777 - -bind_test fl fl gid nobody tcp 77 -bind_test fl ok gid nobody tcp 7777 -bind_test fl fl gid nobody udp 77 -bind_test fl ok gid nobody udp 7777 - -# Verify if mac_portacl rules work. - -sysctl net.inet.ip.portrange.reservedhigh=76 >/dev/null -sysctl security.mac.portacl.port_high=7776 >/dev/null - -bind_test fl ok uid nobody tcp 77 -bind_test ok ok uid nobody tcp 7777 -bind_test fl ok uid nobody udp 77 -bind_test ok ok uid nobody udp 7777 - -bind_test fl ok gid nobody tcp 77 -bind_test ok ok gid nobody tcp 7777 -bind_test fl ok gid nobody udp 77 -bind_test ok ok gid nobody udp 7777 - -restore_settings --- /dev/null 2009-05-23 21:30:17.000000000 +0200 +++ tools/regression/mac/mac_portacl/port_high.t 2009-05-23 21:30:20.152895486 +0200 @@ -0,0 +1,97 @@ +#!/bin/sh + +dir=`dirname $0` +. ${dir}/misc.sh + +echo "1..64" + +# Check if security.mac.portacl.port_high works properly. + +sysctl security.mac.portacl.suser_exempt=0 >/dev/null + +sysctl net.inet.ip.portrange.reservedhigh=77 >/dev/null +sysctl security.mac.portacl.port_high=77 >/dev/null + +expect_fl sobind -u 0 tcp 76 +expect_ok sobind -u 0 tcp 78 +expect_fl sobind -u 0 udp 76 +expect_ok sobind -u 0 udp 78 + +expect_fl sobind -j sobind_test -u 0 tcp 76 +expect_ok sobind -j sobind_test -u 0 tcp 78 +expect_fl sobind -j sobind_test -u 0 udp 76 +expect_ok sobind -j sobind_test -u 0 udp 78 + +expect_fl sobind -u 65535 tcp 76 +expect_ok sobind -u 65535 tcp 78 +expect_fl sobind -u 65535 udp 76 +expect_ok sobind -u 65535 udp 78 + +expect_fl sobind -j sobind_test -u 65535 tcp 76 +expect_ok sobind -j sobind_test -u 65535 tcp 78 +expect_fl sobind -j sobind_test -u 65535 udp 76 +expect_ok sobind -j sobind_test -u 65535 udp 78 + +sysctl net.inet.ip.portrange.reservedhigh=77 >/dev/null +sysctl security.mac.portacl.port_high=75 >/dev/null + +expect_fl sobind -u 0 tcp 74 +expect_ok sobind -u 0 tcp 76 +expect_ok sobind -u 0 tcp 78 +expect_fl sobind -u 0 udp 74 +expect_ok sobind -u 0 udp 76 +expect_ok sobind -u 0 udp 78 + +expect_fl sobind -j sobind_test -u 0 tcp 74 +expect_ok sobind -j sobind_test -u 0 tcp 76 +expect_ok sobind -j sobind_test -u 0 tcp 78 +expect_fl sobind -j sobind_test -u 0 udp 74 +expect_ok sobind -j sobind_test -u 0 udp 76 +expect_ok sobind -j sobind_test -u 0 udp 78 + +expect_fl sobind -u 65535 tcp 74 +expect_fl sobind -u 65535 tcp 76 +expect_ok sobind -u 65535 tcp 78 +expect_fl sobind -u 65535 udp 74 +expect_fl sobind -u 65535 udp 76 +expect_ok sobind -u 65535 udp 78 + +expect_fl sobind -j sobind_test -u 65535 tcp 74 +expect_fl sobind -j sobind_test -u 65535 tcp 76 +expect_ok sobind -j sobind_test -u 65535 tcp 78 +expect_fl sobind -j sobind_test -u 65535 udp 74 +expect_fl sobind -j sobind_test -u 65535 udp 76 +expect_ok sobind -j sobind_test -u 65535 udp 78 + +sysctl net.inet.ip.portrange.reservedhigh=75 >/dev/null +sysctl security.mac.portacl.port_high=77 >/dev/null + +expect_fl sobind -u 0 tcp 74 +expect_fl sobind -u 0 tcp 76 +expect_ok sobind -u 0 tcp 78 +expect_fl sobind -u 0 udp 74 +expect_fl sobind -u 0 udp 76 +expect_ok sobind -u 0 udp 78 + +expect_fl sobind -j sobind_test -u 0 tcp 74 +expect_fl sobind -j sobind_test -u 0 tcp 76 +expect_ok sobind -j sobind_test -u 0 tcp 78 +expect_fl sobind -j sobind_test -u 0 udp 74 +expect_fl sobind -j sobind_test -u 0 udp 76 +expect_ok sobind -j sobind_test -u 0 udp 78 + +expect_fl sobind -u 65535 tcp 74 +expect_fl sobind -u 65535 tcp 76 +expect_ok sobind -u 65535 tcp 78 +expect_fl sobind -u 65535 udp 74 +expect_fl sobind -u 65535 udp 76 +expect_ok sobind -u 65535 udp 78 + +expect_fl sobind -j sobind_test -u 65535 tcp 74 +expect_fl sobind -j sobind_test -u 65535 tcp 76 +expect_ok sobind -j sobind_test -u 65535 tcp 78 +expect_fl sobind -j sobind_test -u 65535 udp 74 +expect_fl sobind -j sobind_test -u 65535 udp 76 +expect_ok sobind -j sobind_test -u 65535 udp 78 + +restore_settings --- tools/regression/mac/mac_portacl/root.t 2009-05-23 21:30:21.459895677 +0200 +++ /dev/null 2009-05-23 21:30:17.000000000 +0200 @@ -1,51 +0,0 @@ -#!/bin/sh -# $FreeBSD: src/tools/regression/mac/mac_portacl/root.t,v 1.1 2009/03/14 21:54:19 pjd Exp $ - -dir=`dirname $0` -. ${dir}/misc.sh - -echo "1..48" - -# Verify if security.mac.portacl.suser_exempt=1 really exempts super-user. - -sysctl security.mac.portacl.suser_exempt=1 >/dev/null - -bind_test ok ok uid root tcp 77 -bind_test ok ok uid root tcp 7777 -bind_test ok ok uid root udp 77 -bind_test ok ok uid root udp 7777 - -bind_test ok ok gid root tcp 77 -bind_test ok ok gid root tcp 7777 -bind_test ok ok gid root udp 77 -bind_test ok ok gid root udp 7777 - -# Verify if security.mac.portacl.suser_exempt=0 really doesn't exempt super-user. - -sysctl security.mac.portacl.suser_exempt=0 >/dev/null - -bind_test fl ok uid root tcp 77 -bind_test ok ok uid root tcp 7777 -bind_test fl ok uid root udp 77 -bind_test ok ok uid root udp 7777 - -bind_test fl ok gid root tcp 77 -bind_test ok ok gid root tcp 7777 -bind_test fl ok gid root udp 77 -bind_test ok ok gid root udp 7777 - -# Verify if security.mac.portacl.port_high works for super-user. - -sysctl security.mac.portacl.port_high=7778 >/dev/null - -bind_test fl ok uid root tcp 77 -bind_test fl ok uid root tcp 7777 -bind_test fl ok uid root udp 77 -bind_test fl ok uid root udp 7777 - -bind_test fl ok gid root tcp 77 -bind_test fl ok gid root tcp 7777 -bind_test fl ok gid root udp 77 -bind_test fl ok gid root udp 7777 - -restore_settings --- /dev/null 2009-05-23 21:30:17.000000000 +0200 +++ tools/regression/mac/mac_portacl/sobind.c 2009-05-23 21:30:23.111896700 +0200 @@ -0,0 +1,190 @@ +/*- + * Copyright (c) 2009 Pawel Jakub Dawidek + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#define PROTO_TCP 0 +#define PROTO_UDP 1 + +static void +usage(void) +{ + + errx(1, "usage: %s [-j jailname] [-u uid] [-g gid1[,gid2[...]]] ", + getprogname()); +} + +static void +jailme(char *jname) +{ + struct in_addr addr; + struct jail j; + + bzero(&j, sizeof(j)); + j.version = JAIL_API_VERSION; + j.path = "/"; + j.hostname = "sobind_test"; + j.jailname = jname; + j.ip4s = 1; + addr.s_addr = htonl(INADDR_LOOPBACK); + j.ip4 = &addr; + + if (jail(&j) < 0) + err(1, "jail() failed"); +} + +static void +set_gids(char *gids) +{ + gid_t *gidset; + long ngroups; + char *g, *endp; + unsigned i; + + ngroups = sysconf(_SC_NGROUPS_MAX); + assert(ngroups > 0); + gidset = malloc(sizeof(*gidset) * ngroups); + assert(gidset != NULL); + for (i = 0, g = strtok(gids, ","); g != NULL; g = strtok(NULL, ","), i++) { + if (i >= ngroups) + errx(1, "too many gids"); + gidset[i] = strtol(g, &endp, 0); + if (*endp != '\0' && !isspace((unsigned char)*endp)) + errx(1, "invalid gid '%s' - number expected\n", g); + } + if (setgroups(i, gidset) < 0) + err(1, "cannot change groups"); + if (setegid(gidset[0]) < 0) + err(1, "cannot change effective gid"); + free(gidset); +} + +static int +sobind(int proto, int port) +{ + struct sockaddr_in sin; + int sock; + + switch (proto) { + case PROTO_TCP: + sock = socket(AF_INET, SOCK_STREAM, 0); + break; + case PROTO_UDP: + sock = socket(AF_INET, SOCK_DGRAM, 0); + break; + default: + sock = -1; /* keep gcc happy */ + assert(!"unexpected protocol"); + } + if (sock < 0) + err(1, "socket() failed"); + + bzero(&sin, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + sin.sin_port = htons(port); + + if (bind(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) + err(1, "bind() failed"); + + exit(0); +} + +int +main(int argc, char *argv[]) +{ + int ch, uid, port, proto; + char *endp, *gids, *jname; + + uid = -1; + gids = NULL; + jname = NULL; + + while ((ch = getopt(argc, argv, "g:j:u:")) != -1) { + switch(ch) { + case 'g': + gids = optarg; + break; + case 'j': + jname = optarg; + break; + case 'u': + uid = (int)strtol(optarg, &endp, 0); + if (*endp != '\0' && !isspace((unsigned char)*endp)) { + errx(1, "invalid uid '%s' - number expected", + optarg); + } + break; + default: + usage(); + } + } + argc -= optind; + argv += optind; + + if (argc != 2) { + fprintf(stderr, "too few arguments\n"); + usage(); + } + + if (jname != NULL) + jailme(jname); + if (gids != NULL) + set_gids(gids); + if (uid != -1) { + if (setuid(uid) < 0) + err(1, "cannot change uid"); + } + + if (strcasecmp(argv[0], "tcp") == 0) + proto = PROTO_TCP; + else if (strcasecmp(argv[0], "udp") == 0) + proto = PROTO_UDP; + else + errx(1, "invalid protocal '%s', expected tcp or udp", argv[0]); + + port = (int)strtol(argv[1], &endp, 0); + if (*endp != '\0' && !isspace((unsigned char)*endp)) + errx(1, "invalid uid '%s' - number expected", argv[1]); + + sobind(proto, port); + /* NOTREACHED */ + exit(255); /* keep gcc happy */ +} --- /dev/null 2009-05-23 21:30:17.000000000 +0200 +++ tools/regression/mac/mac_portacl/suser_exempt.t 2009-05-23 21:30:24.419895622 +0200 @@ -0,0 +1,78 @@ +#!/bin/sh + +dir=`dirname $0` +. ${dir}/misc.sh + +echo "1..48" + +# Check if security.mac.portacl.suser_exempt works properly. + +sysctl net.inet.ip.portrange.reservedhigh=78 >/dev/null + +sysctl security.mac.portacl.suser_exempt=2 >/dev/null + +expect_ok sobind -u 0 tcp 77 +expect_ok sobind -u 0 tcp 7777 +expect_ok sobind -u 0 udp 77 +expect_ok sobind -u 0 udp 7777 + +expect_ok sobind -j sobind_test -u 0 tcp 77 +expect_ok sobind -j sobind_test -u 0 tcp 7777 +expect_ok sobind -j sobind_test -u 0 udp 77 +expect_ok sobind -j sobind_test -u 0 udp 7777 + +expect_fl sobind -u 65535 tcp 77 +expect_ok sobind -u 65535 tcp 7777 +expect_fl sobind -u 65535 udp 77 +expect_ok sobind -u 65535 udp 7777 + +expect_fl sobind -j sobind_test -u 65535 tcp 77 +expect_ok sobind -j sobind_test -u 65535 tcp 7777 +expect_fl sobind -j sobind_test -u 65535 udp 77 +expect_ok sobind -j sobind_test -u 65535 udp 7777 + +sysctl security.mac.portacl.suser_exempt=1 >/dev/null + +expect_ok sobind -u 0 tcp 77 +expect_ok sobind -u 0 tcp 7777 +expect_ok sobind -u 0 udp 77 +expect_ok sobind -u 0 udp 7777 + +expect_fl sobind -j sobind_test -u 0 tcp 77 +expect_ok sobind -j sobind_test -u 0 tcp 7777 +expect_fl sobind -j sobind_test -u 0 udp 77 +expect_ok sobind -j sobind_test -u 0 udp 7777 + +expect_fl sobind -u 65535 tcp 77 +expect_ok sobind -u 65535 tcp 7777 +expect_fl sobind -u 65535 udp 77 +expect_ok sobind -u 65535 udp 7777 + +expect_fl sobind -j sobind_test -u 65535 tcp 77 +expect_ok sobind -j sobind_test -u 65535 tcp 7777 +expect_fl sobind -j sobind_test -u 65535 udp 77 +expect_ok sobind -j sobind_test -u 65535 udp 7777 + +sysctl security.mac.portacl.suser_exempt=0 >/dev/null + +expect_fl sobind -u 0 tcp 77 +expect_ok sobind -u 0 tcp 7777 +expect_fl sobind -u 0 udp 77 +expect_ok sobind -u 0 udp 7777 + +expect_fl sobind -j sobind_test -u 0 tcp 77 +expect_ok sobind -j sobind_test -u 0 tcp 7777 +expect_fl sobind -j sobind_test -u 0 udp 77 +expect_ok sobind -j sobind_test -u 0 udp 7777 + +expect_fl sobind -u 65535 tcp 77 +expect_ok sobind -u 65535 tcp 7777 +expect_fl sobind -u 65535 udp 77 +expect_ok sobind -u 65535 udp 7777 + +expect_fl sobind -j sobind_test -u 65535 tcp 77 +expect_ok sobind -j sobind_test -u 65535 tcp 7777 +expect_fl sobind -j sobind_test -u 65535 udp 77 +expect_ok sobind -j sobind_test -u 65535 udp 7777 + +restore_settings --- /dev/null 2009-05-23 21:30:17.000000000 +0200 +++ tools/regression/mac/mac_portacl/uid.t 2009-05-23 21:30:25.723897108 +0200 @@ -0,0 +1,32 @@ +#!/bin/sh + +dir=`dirname $0` +. ${dir}/misc.sh + +echo "1..32" + +sysctl security.mac.portacl.suser_exempt=0 >/dev/null +sysctl net.inet.ip.portrange.reservedhigh=0 >/dev/null +sysctl security.mac.portacl.port_high=1023 >/dev/null + +bind_test fl ok uid 0 tcp 777 +bind_test ok ok uid 0 tcp 7777 +bind_test fl fl uid 0 tcp 777 778 +bind_test ok ok uid 0 tcp 7777 7778 + +bind_test fl ok uid 65535 tcp 777 +bind_test ok ok uid 65535 tcp 7777 +bind_test fl fl uid 65535 tcp 777 778 +bind_test ok ok uid 65535 tcp 7777 7778 + +bind_test fl ok uid 0 udp 777 +bind_test ok ok uid 0 udp 7777 +bind_test fl fl uid 0 udp 777 778 +bind_test ok ok uid 0 udp 7777 7778 + +bind_test fl ok uid 65535 udp 777 +bind_test ok ok uid 65535 udp 7777 +bind_test fl fl uid 65535 udp 777 778 +bind_test ok ok uid 65535 udp 7777 7778 + +restore_settings