mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-08-22 10:07:12 +00:00
Fix permission mapping for change_profile onexec
Bug #963756 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>
This commit is contained in:
parent
5c09f44f8b
commit
c1722cdfdb
@ -61,6 +61,7 @@
|
|||||||
#define AA_PTRACE_PERMS (AA_USER_PTRACE | AA_OTHER_PTRACE)
|
#define AA_PTRACE_PERMS (AA_USER_PTRACE | AA_OTHER_PTRACE)
|
||||||
|
|
||||||
#define AA_CHANGE_HAT (1 << 30)
|
#define AA_CHANGE_HAT (1 << 30)
|
||||||
|
#define AA_ONEXEC (1 << 30)
|
||||||
#define AA_CHANGE_PROFILE (1 << 31)
|
#define AA_CHANGE_PROFILE (1 << 31)
|
||||||
#define AA_SHARED_PERMS (AA_CHANGE_HAT | AA_CHANGE_PROFILE)
|
#define AA_SHARED_PERMS (AA_CHANGE_HAT | AA_CHANGE_PROFILE)
|
||||||
|
|
||||||
|
@ -510,19 +510,28 @@ static int process_dfa_entry(aare_ruleset_t *dfarules, struct cod_entry *entry)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (entry->mode & AA_CHANGE_PROFILE) {
|
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) {
|
if (entry->namespace) {
|
||||||
char *vec[2];
|
|
||||||
char lbuf[PATH_MAX + 8];
|
|
||||||
int pos;
|
int pos;
|
||||||
ptype = convert_aaregex_to_pcre(entry->namespace, 0, lbuf, PATH_MAX + 8, &pos);
|
ptype = convert_aaregex_to_pcre(entry->namespace, 0, lbuf, PATH_MAX + 8, &pos);
|
||||||
vec[0] = lbuf;
|
vec[index++] = 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++] = 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)) {
|
if (entry->mode & (AA_USER_PTRACE | AA_OTHER_PTRACE)) {
|
||||||
int mode = entry->mode & (AA_USER_PTRACE | AA_OTHER_PTRACE);
|
int mode = entry->mode & (AA_USER_PTRACE | AA_OTHER_PTRACE);
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
SRC=access.c \
|
SRC=access.c \
|
||||||
introspect.c \
|
introspect.c \
|
||||||
changeprofile.c \
|
changeprofile.c \
|
||||||
|
onexec.c \
|
||||||
changehat.c \
|
changehat.c \
|
||||||
changehat_fork.c \
|
changehat_fork.c \
|
||||||
changehat_misc.c \
|
changehat_misc.c \
|
||||||
@ -110,6 +111,7 @@ TESTS=access \
|
|||||||
introspect \
|
introspect \
|
||||||
capabilities \
|
capabilities \
|
||||||
changeprofile \
|
changeprofile \
|
||||||
|
onexec \
|
||||||
changehat \
|
changehat \
|
||||||
changehat_fork \
|
changehat_fork \
|
||||||
changehat_misc \
|
changehat_misc \
|
||||||
|
58
tests/regression/apparmor/onexec.c
Normal file
58
tests/regression/apparmor/onexec.c
Normal file
@ -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;
|
||||||
|
}
|
181
tests/regression/apparmor/onexec.sh
Normal file
181
tests/regression/apparmor/onexec.sh
Normal file
@ -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
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user