tests: add userns regression tests

Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>
This commit is contained in:
Georgia Garcia 2022-11-04 08:29:45 +00:00
parent ffd74aadb1
commit 0727da47b3
5 changed files with 192 additions and 0 deletions

1
.gitignore vendored
View file

@ -295,6 +295,7 @@ tests/regression/apparmor/unix_fd_server
tests/regression/apparmor/unix_socket
tests/regression/apparmor/unix_socket_client
tests/regression/apparmor/unlink
tests/regression/apparmor/userns
tests/regression/apparmor/uservars.inc
tests/regression/apparmor/xattrs
tests/regression/apparmor/xattrs_profile

View file

@ -142,6 +142,7 @@ SRC=access.c \
unix_socket.c \
unix_socket_client.c \
unlink.c \
userns.c \
xattrs.c \
xattrs_profile.c
@ -255,6 +256,7 @@ TESTS=aa_exec \
unix_socket_unnamed \
unix_socket_autobind \
unlink\
userns\
xattrs\
xattrs_profile\
longpath \

View file

@ -309,6 +309,20 @@ sub gen_pivot_root($) {
}
}
sub gen_userns($) {
my $rule = shift;
my @rules = split (/:/, $rule);
if (@rules == 2) {
if ($rules[1] =~ /^ALL$/) {
push (@{$output_rules{$hat}}, " userns,\n");
} else {
push (@{$output_rules{$hat}}, " userns $rules[1],\n");
}
} else {
(!$nowarn) && print STDERR "Warning: invalid userns description '$rule', ignored\n";
}
}
sub gen_file($) {
my $rule = shift;
my @rules = split (/:/, $rule);
@ -450,6 +464,8 @@ sub gen_from_args() {
gen_umount($rule);
} elsif ($rule =~ /^pivot_root:/) {
gen_pivot_root($rule);
} elsif ($rule =~ /^userns:/) {
gen_userns($rule)
} elsif ($rule =~ /^flag:/) {
gen_flag($rule);
} elsif ($rule =~ /^hat:/) {

View file

@ -0,0 +1,59 @@
/*
* Copyright (C) 2022 Canonical, Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, contact Canonical Ltd.
*/
#define _GNU_SOURCE
#include <sched.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
static int child(void *arg)
{
printf("PASS\n");
return EXIT_SUCCESS;
}
#define STACK_SIZE (1024 * 1024)
static char child_stack[STACK_SIZE];
int main(int argc, char *argv[])
{
pid_t child_pid;
int child_exit;
child_pid = clone(child, child_stack + STACK_SIZE,
CLONE_NEWUSER | SIGCHLD, NULL);
if (child_pid == -1) {
perror("FAIL - clone");
return EXIT_FAILURE;
}
if (waitpid(child_pid, &child_exit, 0) == -1) {
perror("FAIL - waitpid");
return EXIT_FAILURE;
}
if (WIFEXITED(child_exit)) {
if (WEXITSTATUS(child_exit) != EXIT_SUCCESS) {
fprintf(stderr, "FAIL - child ended with failure %d\n", child_exit);
return EXIT_FAILURE;
}
}
printf("PASS\n");
return EXIT_SUCCESS;
}

View file

@ -0,0 +1,114 @@
#! /bin/bash
#Copyright (C) 2022 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 userns
#=DESCRIPTION
# This test verifies if mediation of user namespaces is working
#=END
pwd=`dirname $0`
pwd=`cd $pwd ; /bin/pwd`
bin=$pwd
. $bin/prologue.inc
requires_kernel_features namespaces/mask/userns_create
requires_parser_support "userns,"
apparmor_restrict_unprivileged_userns_path=/proc/sys/kernel/apparmor_restrict_unprivileged_userns
if [ ! -e $apparmor_restrict_unprivileged_userns_path ]; then
echo "$apparmor_restrict_unprivileged_userns_path not available. Skipping tests ..."
exit 0
fi
apparmor_restrict_unprivileged_userns=$(cat $apparmor_restrict_unprivileged_userns_path)
unprivileged_userns_clone_path=/proc/sys/kernel/unprivileged_userns_clone
if [ -e $unprivileged_userns_clone_path ]; then
unprivileged_userns_clone=$(cat $unprivileged_userns_clone_path)
fi
restore_userns()
{
echo $apparmor_restrict_unprivileged_userns > $apparmor_restrict_unprivileged_userns_path
}
do_onexit="restore_userns"
do_test()
{
local desc="USERNS ($1)"
expect_root=$2
expect_user=$3
generate_profile=$4
settest userns
$generate_profile # settest removes the profile, so load it here
runchecktest "$desc - root" $expect_root
settest -u "foo" userns # run tests as user foo
$generate_profile # settest removes the profile, so load it here
runchecktest "$desc - user" $expect_user
}
if [ $unprivileged_userns_clone -eq 0 ]; then
echo "WARN: unprivileged_userns_clone is enabled. Both confined and unconfined unprivileged user namespaces are not allowed"
detail="unprivileged_userns_clone disabled"
do_test "unconfined - $detail" pass fail
generate_profile="genprofile userns cap:sys_admin"
do_test "confined all perms $detail" pass fail "$generate_profile"
generate_profile="genprofile cap:sys_admin"
do_test "confined no perms $detail" fail fail "$generate_profile"
generate_profile="genprofile userns:create cap:sys_admin"
do_test "confined specific perms $detail" pass fail "$generate_profile"
exit 0
fi
# confined tests should have the same results if apparmor_restrict_unprivileged_userns is enabled or not
run_confined_tests()
{
generate_profile="genprofile userns"
do_test "confined all perms $1" pass pass "$generate_profile"
generate_profile="genprofile"
do_test "confined no perms $1" fail fail "$generate_profile"
generate_profile="genprofile userns:create"
do_test "confined specific perms $1" pass pass "$generate_profile"
}
# ----------------------------------------------------
# disable restrictions on unprivileged user namespaces
echo 0 > $apparmor_restrict_unprivileged_userns_path
detail="apparmor_restrict_unprivileged_userns disabled"
do_test "unconfined - $detail" pass pass
run_confined_tests "$detail"
# ----------------------------------------------------
# enable restrictions on unprivileged user namespaces
echo 1 > $apparmor_restrict_unprivileged_userns_path
detail="apparmor_restrict_unprivileged_userns enabled"
# user cannot create user namespace unless cap_sys_admin
do_test "unconfined $detail" pass fail
# it should work when running as user with cap_sys_admin
setcap cap_sys_admin+pie $bin/userns
do_test "unconfined cap_sys_admin $detail" pass pass
# remove cap_sys_admin from binary
setcap cap_sys_admin= $bin/userns
run_confined_tests "$detail"