mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-08-22 01:57:43 +00:00
regression: add test for making O_TMPFILE followed by linkat
The unnamed nature of an O_TMPFILE, combined with the delayed linkage of linkat(2), creates a potential for a filesystem mediation bypass. Thus, add a test to verify whether or not such a bypass occurs. Signed-off-by: Ryan Lee <ryan.lee@canonical.com>
This commit is contained in:
parent
520db7a16c
commit
3e7ddc1ce5
1
.gitignore
vendored
1
.gitignore
vendored
@ -255,6 +255,7 @@ tests/regression/apparmor/introspect
|
||||
tests/regression/apparmor/io_uring
|
||||
tests/regression/apparmor/link
|
||||
tests/regression/apparmor/link_subset
|
||||
tests/regression/apparmor/linkat_tmpfile
|
||||
tests/regression/apparmor/mkdir
|
||||
tests/regression/apparmor/mmap
|
||||
tests/regression/apparmor/mount
|
||||
|
@ -144,6 +144,7 @@ SRC=access.c \
|
||||
getcon_verify.c \
|
||||
link.c \
|
||||
link_subset.c \
|
||||
linkat_tmpfile.c \
|
||||
mmap.c \
|
||||
mkdir.c \
|
||||
mount.c \
|
||||
@ -311,6 +312,7 @@ TESTS=aa_exec \
|
||||
i18n \
|
||||
link \
|
||||
link_subset \
|
||||
linkat_tmpfile \
|
||||
mkdir \
|
||||
mmap \
|
||||
mount \
|
||||
|
29
tests/regression/apparmor/linkat_tmpfile.c
Normal file
29
tests/regression/apparmor/linkat_tmpfile.c
Normal file
@ -0,0 +1,29 @@
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc != 2 && argc != 3) {
|
||||
fprintf(stderr, "FAIL: Usage: linkat tmpdir final_location\n");
|
||||
return 1;
|
||||
}
|
||||
int tmpfile_fd = open(argv[1], O_TMPFILE | O_WRONLY, S_IRUSR | S_IWUSR);
|
||||
if (tmpfile_fd == -1) {
|
||||
perror("FAIL: could not open tmpfile");
|
||||
return 1;
|
||||
}
|
||||
if (argc == 3) {
|
||||
int linkat_result = linkat(tmpfile_fd, "", AT_FDCWD, argv[2], AT_EMPTY_PATH);
|
||||
if (linkat_result == -1) {
|
||||
perror("FAIL: could not link tmpfile into final location");
|
||||
close(tmpfile_fd);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
close(tmpfile_fd);
|
||||
fprintf(stderr, "PASS\n");
|
||||
return 0;
|
||||
}
|
52
tests/regression/apparmor/linkat_tmpfile.sh
Normal file
52
tests/regression/apparmor/linkat_tmpfile.sh
Normal file
@ -0,0 +1,52 @@
|
||||
#! /bin/bash
|
||||
# Copyright (C) 2025 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 linkat
|
||||
#=DESCRIPTION
|
||||
# Verifies that file creation with O_TMPFILE and linkat(2) is mediated correctly
|
||||
#=END
|
||||
|
||||
pwd=`dirname $0`
|
||||
pwd=`cd $pwd ; /bin/pwd`
|
||||
|
||||
bin=$pwd
|
||||
|
||||
. "$bin/prologue.inc"
|
||||
|
||||
tmpdir_nested=$tmpdir/nested
|
||||
tmpdir_nested_file=$tmpdir_nested/file
|
||||
tmpfile=$tmpdir/file
|
||||
|
||||
mkdir $tmpdir_nested
|
||||
|
||||
genprofile cap:dac_read_search
|
||||
runchecktest "linkat O_TMPFILE noperms" fail $tmpdir_nested
|
||||
runchecktest "linkat O_TMPFILE noperms, link" fail $tmpdir_nested $tmpfile
|
||||
|
||||
# Denial log entry for tmpfile is /path/#[6digits]
|
||||
# Don't assume because O_TMPFILE fds should lack a name entirely
|
||||
genprofile cap:dac_read_search "${tmpdir_nested}/:w" "${tmpdir_nested}/*:w"
|
||||
runchecktest "linkat O_TMPFILE tmpdir only" pass $tmpdir_nested
|
||||
runchecktest "linkat O_TMPFILE tmpdir only, link" fail $tmpdir_nested $tmpfile
|
||||
|
||||
genprofile cap:dac_read_search "${tmpfile}:w"
|
||||
runchecktest "linkat O_TMPFILE tmpfile only" fail $tmpdir_nested
|
||||
runchecktest "linkat O_TMPFILE tmpfile only, link" fail $tmpdir_nested $tmpfile
|
||||
|
||||
genprofile cap:dac_read_search "${tmpdir_nested}/:w" "${tmpdir_nested}/*:w" "${tmpfile}:w"
|
||||
runchecktest "linkat O_TMPFILE tmpdir and tmpfile (w)" pass $tmpdir_nested
|
||||
# Even if semantically a (w)rite it gets logged as the (l)ink that it actually is
|
||||
runchecktest "linkat O_TMPFILE tmpdir and tmpfile (w), link" xpass $tmpdir_nested $tmpfile
|
||||
|
||||
genprofile cap:dac_read_search "${tmpdir_nested}/:w" "${tmpdir_nested}/*:w" "${tmpfile}:l"
|
||||
runchecktest "linkat O_TMPFILE tmpdir and tmpfile (l)" pass $tmpdir_nested
|
||||
# Even if semantically a (w)rite we want to test backwards compatibility with (l)ink as it is currently seen
|
||||
runchecktest "linkat O_TMPFILE tmpdir and tmpfile (l), link" pass $tmpdir_nested $tmpfile
|
||||
|
||||
rm $tmpfile
|
||||
rmdir $tmpdir_nested
|
Loading…
x
Reference in New Issue
Block a user