[prev in list] [next in list] [prev in thread] [next in thread] 

List:       apparmor-dev
Subject:    Re: [apparmor] [PATCH 3/5] Fix permission mapping for change_profile onexec
From:       Steve Beattie <steve () nxnw ! org>
Date:       2012-03-26 16:53:57
Message-ID: 20120326165357.GT3989 () nxnw ! org
[Download RAW message or body]

[Attachment #2 (multipart/signed)]


On Mon, Mar 26, 2012 at 06:03:55AM -0700, John Johansen wrote:
> The kernel has an extended test for change_profile when used with
> onexec, that allows it to only work against set executables.
> 
> The parser is not correctly mapping change_profile for this test
> update the mapping so change_onexec will work when confined.
> 
> Note: the parser does not currently support the extended syntax
> that the kernel test allows for, this just enables it to work
> for the generic case.
> 
> Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>

> ---
> parser/immunix.h                    |    1 +
> parser/parser_regex.c               |   27 ++++--
> tests/regression/apparmor/Makefile  |    2 +
> tests/regression/apparmor/onexec.c  |   58 +++++++++++
> tests/regression/apparmor/onexec.sh |  181 +++++++++++++++++++++++++++++++++++
> 5 files changed, 260 insertions(+), 9 deletions(-)
> create mode 100644 tests/regression/apparmor/onexec.c
> create mode 100755 tests/regression/apparmor/onexec.sh
> 
> diff --git a/parser/immunix.h b/parser/immunix.h
> index 8dc157a..ebb2d2e 100644
> --- a/parser/immunix.h
> +++ b/parser/immunix.h
> @@ -61,6 +61,7 @@
> #define AA_PTRACE_PERMS			(AA_USER_PTRACE | AA_OTHER_PTRACE)
> 
> #define AA_CHANGE_HAT			(1 << 30)
> +#define AA_ONEXEC			(1 << 30)
> #define AA_CHANGE_PROFILE		(1 << 31)
> #define AA_SHARED_PERMS			(AA_CHANGE_HAT | AA_CHANGE_PROFILE)
> 
> diff --git a/parser/parser_regex.c b/parser/parser_regex.c
> index 8c34799..c774372 100644
> --- a/parser/parser_regex.c
> +++ b/parser/parser_regex.c
> @@ -510,19 +510,28 @@ static int process_dfa_entry(aare_ruleset_t *dfarules, struct \
> cod_entry *entry)  return FALSE;
> 	}
> 	if (entry->mode & AA_CHANGE_PROFILE) {
> +		char *vec[3];
> +		char lbuf[PATH_MAX + 8];
> +		int index = 1;
> +
> +		/* allow change_profile for all execs */
> +		vec[0] = "/[^\\x00]*";
> +
> 		if (entry->namespace) {
> -			char *vec[2];
> -			char lbuf[PATH_MAX + 8];
> 			int pos;
> 			ptype = convert_aaregex_to_pcre(entry->namespace, 0, lbuf, PATH_MAX + 8, &pos);
> -			vec[0] = lbuf;
> -			vec[1] = tbuf;
> -			if (!aare_add_rule_vec(dfarules, 0, AA_CHANGE_PROFILE, 0, 2, vec, dfaflags))
> -			    return FALSE;
> -		} else {
> -		  if (!aare_add_rule(dfarules, tbuf, 0, AA_CHANGE_PROFILE, 0, dfaflags))
> -				return FALSE;
> +			vec[index++] = lbuf;
> 		}
> +		vec[index++] = tbuf;
> +
> +		/* regular change_profile rule */
> +		if (!aare_add_rule_vec(dfarules, 0, AA_CHANGE_PROFILE, 0, index - 1, &vec[1], \
> dfaflags)) +			return FALSE;
> +		/* onexec rules - both rules are needed for onexec */
> +		if (!aare_add_rule_vec(dfarules, 0, AA_ONEXEC, 0, 1, vec, dfaflags))
> +			return FALSE;
> +		if (!aare_add_rule_vec(dfarules, 0, AA_ONEXEC, 0, index, vec, dfaflags))
> +			return FALSE;
> 	}
> 	if (entry->mode & (AA_USER_PTRACE | AA_OTHER_PTRACE)) {
> 		int mode = entry->mode & (AA_USER_PTRACE | AA_OTHER_PTRACE);
> diff --git a/tests/regression/apparmor/Makefile \
> b/tests/regression/apparmor/Makefile index b288626..2021f51 100644
> --- a/tests/regression/apparmor/Makefile
> +++ b/tests/regression/apparmor/Makefile
> @@ -8,6 +8,7 @@
> SRC=access.c \
> introspect.c \
> changeprofile.c \
> +    onexec.c \
> changehat.c \
> changehat_fork.c \
> changehat_misc.c \
> @@ -110,6 +111,7 @@ TESTS=access \
> introspect \
> capabilities \
> changeprofile \
> +      onexec \
> changehat \
> changehat_fork \
> changehat_misc \
> diff --git a/tests/regression/apparmor/onexec.c \
> b/tests/regression/apparmor/onexec.c new file mode 100644
> index 0000000..bcb5258
> --- /dev/null
> +++ b/tests/regression/apparmor/onexec.c
> @@ -0,0 +1,58 @@
> +/*
> + *	Copyright (C) 2002-2005 Novell/SUSE
> + *
> + *	This program is free software; you can redistribute it and/or
> + *	modify it under the terms of the GNU General Public License as
> + *	published by the Free Software Foundation, version 2 of the
> + *	License.
> + */
> +
> +#include <stdio.h>
> +#include <unistd.h>
> +#include <errno.h>
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <fcntl.h>
> +#include <string.h>
> +#include <stdlib.h>
> +#include <signal.h>
> +#include <linux/unistd.h>
> +
> +#include <sys/apparmor.h>
> +#include "changehat.h"
> +
> +int main(int argc, char *argv[])
> +{
> +	int rc = 0;
> +
> +	extern char **environ;
> +
> +	if (argc < 3){
> +		fprintf(stderr, "usage: %s profile executable args\n",
> +			argv[0]);
> +		return 1;
> +	}
> +
> +	/* change profile if profile name != nochange */
> +	if (strcmp(argv[1], "nochange") != 0){
> +		rc = aa_change_onexec(argv[1]);
> +		if (rc == -1){
> +			fprintf(stderr, "FAIL: change_onexec %s failed - %s\n",
> +				argv[1], strerror(errno));
> +			exit(errno);
> +		}
> +	}
> +
> +	/* stop after onexec and wait to for continue before exec so
> +	 * caller can introspect task */
> +	(void)kill(getpid(), SIGSTOP);
> +
> +	(void)execve(argv[2], &argv[2], environ);
> +	/* exec failed, kill outselves to flag parent */
> +
> +	rc = errno;
> +
> +	fprintf(stderr, "FAIL: exec to '%s' failed\n", argv[2]);
> +
> +	return rc;
> +}
> diff --git a/tests/regression/apparmor/onexec.sh \
> b/tests/regression/apparmor/onexec.sh new file mode 100755
> index 0000000..38d4632
> --- /dev/null
> +++ b/tests/regression/apparmor/onexec.sh
> @@ -0,0 +1,181 @@
> +#! /bin/bash
> +#	Copyright (C) 2012 Canonical, Ltd.
> +#
> +#	This program is free software; you can redistribute it and/or
> +#	modify it under the terms of the GNU General Public License as
> +#	published by the Free Software Foundation, version 2 of the
> +#	License.
> +
> +#=NAME onexec
> +#=DESCRIPTION 
> +# Verifies basic file access permission checks for change_onexec
> +#=END
> +
> +pwd=`dirname $0`
> +pwd=`cd $pwd ; /bin/pwd`
> +
> +bin=$pwd
> +
> +. $bin/prologue.inc
> +
> +file=$tmpdir/file
> +subfile=$tmpdir/file2
> +okperm=rw
> +
> +othertest="$pwd/rename"
> +subtest="sub"
> +fqsubbase="$pwd/onexec"
> +fqsubtest="$fqsubbase//$subtest"
> +subtest2="$pwd//sub2"
> +subtest3="$pwd//sub3"
> +
> +onexec="/proc/*/attr/exec"
> +
> +touch $file $subfile
> +
> +check_exec()
> +{
> +    local rc
> +    local actual
> +    actual=`cat /proc/$1/attr/exec 2>/dev/null`
> +    rc=$?
> +
> +    # /proc/$1/attr/exec returns invalid argument if onexec has not been called
> +    if [ $rc -ne 0 ] ; then
> +	if [ "$2" == "nochange" ] ; then
> +	    return 0
> +	fi
> +	echo "ONEXEC - exec transition not set"
> +	return $rc
> +    fi
> +    if [ "${actual% (*)}" != "$2" ] ; then
> +	echo "ONEXEC - check exec '${actual% (*)}' != expected '$2'"
> +	return 1
> +    fi
> +
> +    return 0
> +}
> +
> +check_current()
> +{
> +    local rc
> +    local actual
> +    actual=`cat /proc/$1/attr/current 2>/dev/null`
> +    rc=$?
> +
> +    # /proc/$1/attr/current return enoent if the onexec process already exited due \
> to error +    if [ $rc -ne 0 ] ; then
> +	return $rc
> +    fi
> +
> +    if [ "${actual% (*)}" != "$2" ] ; then
> +	echo "ONEXEC - check current '${actual% (*)}' != expected '$2'"
> +	return 1
> +    fi
> +
> +    return 0
> +}
> +
> +do_test()
> +{
> +    local desc="$1"
> +    local prof="$2"
> +    local target_prof="$3"
> +    local res="$4"
> +    shift 4
> +
> +    #ignore prologue.inc error trapping that catches our subfn return values
> +
> +    runtestbg "ONEXEC $desc ($prof -> $target_prof)" $res $target_prof "$@"
> +    # check that transition does not happen before exec, and that transition
> +    # is set
> +    
> +    if ! check_current $_pid $prof ; then
> +	checktestfg
> +	return
> +    fi
> +
> +    if ! check_exec $_pid $target_prof ; then
> +	checktestfg
> +	return
> +    fi
> +
> +    kill -CONT $_pid
> +
> +    checktestbg
> +}
> +
> +
> +# ONEXEC from UNCONFINED - don't change profile
> +do_test "" unconfined nochange pass $bin/open $file
> +
> +# ONEXEC from UNCONFINED - target does NOT exist
> +genprofile image=$bin/rw $bin/open:rix $file:rw  -- image=$bin/open
> +do_test "" unconfined noexist fail $bin/open $file
> +
> +# ONEXEC from UNCONFINED - change to rw profile, no exec profile to override
> +genprofile image=$bin/rw $bin/open:rix $file:rw
> +do_test "no px profile" unconfined $bin/rw pass $bin/open $file
> +
> +# ONEXEC from UNCONFINED - don't change profile, make sure exec profile is applied
> +genprofile image=$bin/rw $bin/open:px $file:rw  -- image=$bin/open $file:rw
> +do_test "nochange px" unconfined nochange pass $bin/open $file
> +
> +# ONEXEC from UNCONFINED - change to rw profile, override regular exec profile, \
> exec profile doesn't have perms +genprofile image=$bin/rw $bin/open:px $file:rw  -- \
> image=$bin/open +do_test "override px" unconfined $bin/rw pass $bin/open $file
> +
> +#------
> +
> +# ONEXEC from CONFINED - don't change profile, open can't exec
> +genprofile 'change_profile->':$bin/rw $onexec:w
> +do_test "no px perm" $bin/onexec nochange fail $bin/open $file
> +
> +# ONEXEC from CONFINED - don't change profile, open is run unconfined
> +genprofile 'change_profile->':$bin/rw $bin/open:rux $onexec:w
> +do_test "nochange rux" $bin/onexec nochange pass $bin/open $file
> +
> +# ONEXEC from CONFINED - don't change profile, open is run confined without \
> necessary perms +genprofile 'change_profile->':$bin/rw $onexec:w -- image=$bin/open \
> $file:rw +do_test "nochange px - no px perm" $bin/onexec nochange fail $bin/open \
> $file +
> +# ONEXEC from CONFINED - don't change profile, open is run confined without \
> necessary perms +genprofile 'change_profile->':$bin/rw $bin/open:rpx $onexec:w -- \
> image=$bin/open +do_test "nochange px - no file perm" $bin/onexec nochange fail \
> $bin/open $file +
> +# ONEXEC from CONFINED - target does NOT exist
> +genprofile 'change_profile->':$bin/open $onexec:w -- image=$bin/rw $bin/open:rix \
> $file:rw  -- image=$bin/open +do_test "noexist px" $bin/onexec noexist fail \
> $bin/open $file +
> +# ONEXEC from CONFINED - change to rw profile, no exec profile to override
> +genprofile 'change_profile->':$bin/rw $onexec:w -- image=$bin/rw $bin/open:rix \
> $file:rw +do_test "change profile - override rix" $bin/onexec $bin/rw pass \
> $bin/open $file +
> +# ONEXEC from CONFINED - change to rw profile, no exec profile to override
> +genprofile 'change_profile->':$bin/rw -- image=$bin/rw $bin/open:rix $file:rw
> +do_test "change profile - no onexec:w" $bin/onexec $bin/rw fail $bin/open $file
> +
> +# ONEXEC from CONFINED - don't change profile, make sure exec profile is applied
> +genprofile 'change_profile->':$bin/rw $onexec:w $bin/open:rpx -- image=$bin/rw \
> $bin/open:rix $file:rw  -- image=$bin/open $file:rw +do_test "nochange px" \
> $bin/onexec nochange pass $bin/open $file +
> +# ONEXEC from CONFINED - change to rw profile, override regular exec profile, exec \
> profile doesn't have perms +genprofile 'change_profile->':$bin/rw $onexec:w -- \
> image=$bin/rw $bin/open:rix $file:rw  -- image=$bin/open +do_test "override px" \
> $bin/onexec $bin/rw pass $bin/open $file +
> +# ONEXEC from - change to rw profile, override regular exec profile, exec profile \
> has perms, rw doesn't +genprofile 'change_profile->':$bin/rw $onexec:w -- \
> image=$bin/rw $bin/open:rix  -- image=$bin/open $file:rw +do_test "override px" \
> $bin/onexec $bin/rw fail $bin/open $file +
> +# ONEXEC from COFINED - change to rw profile via glob rule, override exec profile, \
> exec profile doesn't have perms +genprofile 'change_profile->':/** $onexec:w -- \
> image=$bin/rw $bin/open:rix $file:rw  -- image=$bin/open +do_test "glob override \
> px" $bin/onexec $bin/rw pass $bin/open $file +
> +# ONEXEC from COFINED - change to exec profile via glob rule, override exec \
> profile, exec profile doesn't have perms +genprofile 'change_profile->':/** \
> $onexec:w -- image=$bin/rw $bin/open:rix $file:rw  -- image=$bin/open +do_test \
> "glob override px" $bin/onexec $bin/open fail $bin/open $file +
> +# ONEXEC from COFINED - change to exec profile via glob rule, override exec \
> profile, exec profile has perms +genprofile 'change_profile->':/** $onexec:w -- \
> image=$bin/rw $bin/open:rix $file:rw  -- image=$bin/open $file:rw +do_test "glob \
> override px" $bin/onexec $bin/rw pass $bin/open $file +
> -- 
> 1.7.9.1
> 
> 
> -- 
> AppArmor mailing list
> AppArmor@lists.ubuntu.com
> Modify settings or unsubscribe at: \
> https://lists.ubuntu.com/mailman/listinfo/apparmor

-- 
Steve Beattie
<sbeattie@ubuntu.com>
http://NxNW.org/~steve/


["signature.asc" (application/pgp-signature)]

-- 
AppArmor mailing list
AppArmor@lists.ubuntu.com
Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/apparmor


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic