Skip to content

Commit 48f92e5

Browse files
tweksteenstephensmalley
authored andcommitted
policy,tests: add tests for memfd_file class
A new class "memfd_file" is introduced to the kernel in [1]. This class is only used when the policy capability "memfd_class" is set. Add tests to validate this new class: 1. Validate that memfd_create() requires the "create" permission. 2. Validate that fexecve() on a memfd requires the "execute_no_trans" permission. This can be tested by modifying the policy with: semodule -c -E base sed -i \ -e 's/\((class user_namespace (create ))\)/\1\n(class memfd_file (execute_no_trans entrypoint ))\n(classcommon memfd_file file)/' \ -e 's/\(anon_inode socket\)/memfd_file \1/' \ base.cil echo "(policycap memfd_class)" > memfdclass.cil semodule -i base.cil memfdclass.cil rm -f base.cil sed -i.orig \ -e 's/\(define(`all_file_perms'\'',\)\(.*\)$/\1\2\ndefine(`all_memfd_file_perms'\'',\2/' \ -e 's/\(class file all_file_perms;\)/\1\nclass memfd_file all_memfd_file_perms;/' \ /usr/share/selinux/devel/include/support/all_perms.spt Then, after running the tests, undo these changes as follows: semodule -r base memfdclass mv /usr/share/selinux/devel/include/support/all_perms.spt.orig \ /usr/share/selinux/deve/include/support/all_perms.spt [1] https://lore.kernel.org/selinux/[email protected]/ Signed-off-by: Thiébaud Weksteen <[email protected]> Reviewed-by: Stephen Smalley <[email protected]> Tested-by: Stephen Smalley <[email protected]>
1 parent 72e60b6 commit 48f92e5

File tree

8 files changed

+164
-0
lines changed

8 files changed

+164
-0
lines changed

policy/Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,11 @@ ifeq ($(shell [ $(MOD_POL_VERS) -ge 18 -a $(MAX_KERNEL_POLICY) -ge 30 ] && [ -f
163163
TARGETS += test_nlmsg.te
164164
endif
165165

166+
# memfd_file test dependencies: memfd_file class, memfd_class capability
167+
ifeq ($(shell [ -d /sys/fs/selinux/class/memfd_file ] && grep -q 1 $(SELINUXFS)/policy_capabilities/memfd_class && echo true),true)
168+
TARGETS += test_memfd.te
169+
endif
170+
166171
ifeq (x$(DISTRO),$(filter x$(DISTRO),xRHEL4 xRHEL5 xRHEL6))
167172
TARGETS:=$(filter-out test_overlayfs.te test_mqueue.te test_ibpkey.te, $(TARGETS))
168173
endif

policy/test_memfd.te

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
########################################
2+
#
3+
# Policy for testing memfd_file.
4+
5+
attribute memfdtestdomain;
6+
7+
type test_memfd_t;
8+
typeattribute test_memfd_t memfdtestdomain;
9+
testsuite_domain_type(test_memfd_t);
10+
allow test_memfd_t self:memfd_file { create mmap_rw_file_perms };
11+
12+
type test_memfd_nocreate_t;
13+
typeattribute test_memfd_nocreate_t memfdtestdomain;
14+
testsuite_domain_type(test_memfd_nocreate_t);
15+
allow test_memfd_nocreate_t self:memfd_file mmap_rw_file_perms;
16+
17+
type test_memfd_with_exec_t;
18+
typeattribute test_memfd_with_exec_t memfdtestdomain;
19+
testsuite_domain_type(test_memfd_with_exec_t);
20+
allow test_memfd_with_exec_t self:memfd_file { create mmap_rw_file_perms execute execute_no_trans };
21+
22+
type test_memfd_with_noexec_t;
23+
typeattribute test_memfd_with_noexec_t memfdtestdomain;
24+
testsuite_domain_type(test_memfd_with_noexec_t);
25+
allow test_memfd_with_noexec_t self:memfd_file { create mmap_rw_file_perms execute };

tests/Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,11 @@ ifeq ($(shell [ $(MOD_POL_VERS) -ge 18 -a $(MAX_KERNEL_POLICY) -ge 30 ] && [ -f
158158
SUBDIRS += nlmsg
159159
endif
160160

161+
# memfd_file test dependencies: memfd_file class, memfd_class capability
162+
ifeq ($(shell [ -d /sys/fs/selinux/class/memfd_file ] && grep -q 1 $(SELINUXFS)/policy_capabilities/memfd_class && echo true),true)
163+
SUBDIRS += memfd
164+
endif
165+
161166
ifeq ($(DISTRO),RHEL4)
162167
SUBDIRS:=$(filter-out bounds dyntrace dyntrans inet_socket mmap nnp_nosuid overlay unix_socket, $(SUBDIRS))
163168
endif

tests/memfd/Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
TARGETS=memfd nothing memfd_fexecve
2+
3+
all: $(TARGETS)
4+
clean:
5+
rm -f $(TARGETS)

tests/memfd/memfd.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#ifndef _GNU_SOURCE
2+
#define _GNU_SOURCE
3+
#endif
4+
#include <stdlib.h>
5+
#include <stdio.h>
6+
#include <string.h>
7+
#include <errno.h>
8+
#include <sys/mman.h>
9+
#include <unistd.h>
10+
11+
int main(int argc, char *argv[])
12+
{
13+
int fd;
14+
char *name = "mymemfd";
15+
16+
fd = memfd_create(name, 0);
17+
if (fd < 0) {
18+
perror("memfd_create");
19+
exit(-1);
20+
}
21+
22+
close(fd);
23+
exit(0);
24+
}

tests/memfd/memfd_fexecve.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#ifndef _GNU_SOURCE
2+
#define _GNU_SOURCE
3+
#endif
4+
#include <errno.h>
5+
#include <fcntl.h>
6+
#include <stdint.h>
7+
#include <stdio.h>
8+
#include <stdlib.h>
9+
#include <string.h>
10+
#include <sys/mman.h>
11+
#include <unistd.h>
12+
13+
int main(int argc, char *argv[])
14+
{
15+
int memfd_fd, exec_fd;
16+
int len, written, rc;
17+
char *name = "mymemfd";
18+
19+
if (argc != 2) {
20+
printf("Usage: %s <fexec_binary>\n", argv[0]);
21+
exit(-1);
22+
}
23+
24+
memfd_fd = memfd_create(name, 0);
25+
if (memfd_fd < 0) {
26+
perror("memfd_create");
27+
exit(-1);
28+
}
29+
30+
exec_fd = open(argv[1], O_RDONLY);
31+
if (exec_fd < 0) {
32+
perror("open");
33+
exit(-1);
34+
}
35+
36+
char buf[8192];
37+
while ((len = read(exec_fd, buf, sizeof(buf))) > 0) {
38+
written = write(memfd_fd, buf, len);
39+
if (len != written) {
40+
perror("read/write");
41+
exit(-1);
42+
}
43+
}
44+
close(exec_fd);
45+
46+
char *empty_env[] = {NULL};
47+
char *nothing_argv[] = {argv[1], NULL};
48+
49+
rc = fexecve(memfd_fd, nothing_argv, empty_env);
50+
51+
perror("fexecve");
52+
exit(rc);
53+
}

tests/memfd/nothing.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#include <stdlib.h>
2+
3+
int main(int argc, char *argv[])
4+
{
5+
return 0;
6+
}

tests/memfd/test

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#!/usr/bin/perl
2+
#
3+
# This test exercises the memfd_class support
4+
#
5+
6+
use Test;
7+
8+
BEGIN {
9+
$test_count = 4;
10+
plan tests => $test_count;
11+
}
12+
13+
$basedir = $0;
14+
$basedir =~ s|(.*)/[^/]*|$1|;
15+
16+
#
17+
# Attempt to call memfd_create() from the allowed domain.
18+
#
19+
$result = system "runcon -t test_memfd_t -- $basedir/memfd 2>&1";
20+
ok( $result, 0 );
21+
22+
#
23+
# Attempt to call memfd_create() from the not-allowed domain.
24+
#
25+
$result = system "runcon -t test_memfd_nocreate_t -- $basedir/memfd 2>&1";
26+
ok($result);
27+
28+
#
29+
# Attempt to fexecve() on a memfd_create() fd from the allowed domain.
30+
#
31+
$result = system
32+
"runcon -t test_memfd_with_exec_t -- $basedir/memfd_fexecve $basedir/nothing 2>&1";
33+
ok( $result, 0 );
34+
35+
#
36+
# Attempt to fexecve() on a memfd_create() fd from the not-allowed domain.
37+
#
38+
$result = system
39+
"runcon -t test_memfd_with_noexec_t -- $basedir/memfd_fexecve $basedir/nothing 2>&1";
40+
ok($result);
41+
exit;

0 commit comments

Comments
 (0)