aboutsummaryrefslogtreecommitdiff
path: root/testcases/lib
diff options
context:
space:
mode:
Diffstat (limited to 'testcases/lib')
-rw-r--r--testcases/lib/.gitignore8
-rw-r--r--testcases/lib/Makefile3
-rw-r--r--testcases/lib/tst_fsfreeze.c38
-rw-r--r--testcases/lib/tst_get_free_pids.c2
-rw-r--r--testcases/lib/tst_kvcmp.c2
-rw-r--r--testcases/lib/tst_lockdown_enabled.c12
-rw-r--r--testcases/lib/tst_net.sh228
-rw-r--r--testcases/lib/tst_ns_common.h42
-rw-r--r--testcases/lib/tst_ns_create.c92
-rw-r--r--testcases/lib/tst_ns_exec.c115
-rw-r--r--testcases/lib/tst_ns_ifmove.c92
-rw-r--r--testcases/lib/tst_secureboot_enabled.c12
-rw-r--r--testcases/lib/tst_test.sh14
13 files changed, 570 insertions, 90 deletions
diff --git a/testcases/lib/.gitignore b/testcases/lib/.gitignore
index 34dea272d..e8afd06f3 100644
--- a/testcases/lib/.gitignore
+++ b/testcases/lib/.gitignore
@@ -3,17 +3,23 @@
/tst_check_kconfigs
/tst_checkpoint
/tst_device
+/tst_fsfreeze
/tst_getconf
/tst_get_free_pids
/tst_get_median
/tst_get_unused_port
+/tst_hexdump
/tst_kvcmp
+/tst_lockdown_enabled
/tst_net_iface_prefix
/tst_net_ip_prefix
/tst_net_vars
+/tst_ns_create
+/tst_ns_exec
+/tst_ns_ifmove
/tst_random
/tst_rod
+/tst_secureboot_enabled
/tst_sleep
/tst_supported_fs
-/tst_hexdump
/tst_timeout_kill
diff --git a/testcases/lib/Makefile b/testcases/lib/Makefile
index f4f8c8524..990b46089 100644
--- a/testcases/lib/Makefile
+++ b/testcases/lib/Makefile
@@ -12,6 +12,7 @@ MAKE_TARGETS := tst_sleep tst_random tst_checkpoint tst_rod tst_kvcmp\
tst_device tst_net_iface_prefix tst_net_ip_prefix tst_net_vars\
tst_getconf tst_supported_fs tst_check_drivers tst_get_unused_port\
tst_get_median tst_hexdump tst_get_free_pids tst_timeout_kill\
- tst_check_kconfigs tst_cgctl
+ tst_check_kconfigs tst_cgctl tst_fsfreeze tst_ns_create tst_ns_exec\
+ tst_ns_ifmove tst_lockdown_enabled tst_secureboot_enabled
include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/lib/tst_fsfreeze.c b/testcases/lib/tst_fsfreeze.c
new file mode 100644
index 000000000..4b0b12cba
--- /dev/null
+++ b/testcases/lib/tst_fsfreeze.c
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2010 Hajime Taira <htaira@redhat.com>
+ * Masatake Yamato <yamato@redhat.com>
+ * Copyright (c) 2023 Petr Vorel <pvorel@suse.cz>
+ *
+ * Based on fsfreeze from util-linux.
+ */
+
+#include <linux/fs.h>
+#include <stdio.h>
+
+#define TST_NO_DEFAULT_MAIN
+#include "tst_test.h"
+#include "tst_safe_macros.h"
+
+static void help(void)
+{
+ printf("Freeze and unfreeze the device.\n");
+ printf("Usage: tst_fsfreeze device\n");
+}
+
+int main(int argc, char *argv[])
+{
+ int fd;
+
+ if (argc < 2) {
+ help();
+ return 1;
+ }
+
+ fd = SAFE_OPEN(argv[1], O_RDONLY);
+ SAFE_IOCTL(fd, FIFREEZE, 0);
+ SAFE_IOCTL(fd, FITHAW, 0);
+ SAFE_CLOSE(fd);
+
+ return 0;
+}
diff --git a/testcases/lib/tst_get_free_pids.c b/testcases/lib/tst_get_free_pids.c
index d7b68c620..370ec3e26 100644
--- a/testcases/lib/tst_get_free_pids.c
+++ b/testcases/lib/tst_get_free_pids.c
@@ -2,7 +2,7 @@
#define TST_NO_DEFAULT_MAIN
#include <stdio.h>
-#include <tst_test.h>
+#include "tst_test.h"
extern struct tst_test *tst_test;
diff --git a/testcases/lib/tst_kvcmp.c b/testcases/lib/tst_kvcmp.c
index 0f5793ef1..afc4b5ce3 100644
--- a/testcases/lib/tst_kvcmp.c
+++ b/testcases/lib/tst_kvcmp.c
@@ -7,7 +7,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/utsname.h>
-#include <tst_test.h>
+#include "tst_test.h"
enum op {
EQ,
diff --git a/testcases/lib/tst_lockdown_enabled.c b/testcases/lib/tst_lockdown_enabled.c
new file mode 100644
index 000000000..30abe3e5e
--- /dev/null
+++ b/testcases/lib/tst_lockdown_enabled.c
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2023 Petr Vorel <pvorel@suse.cz>
+ */
+
+#define TST_NO_DEFAULT_MAIN
+#include "tst_test.h"
+
+int main(void)
+{
+ return tst_lockdown_enabled() <= 0;
+}
diff --git a/testcases/lib/tst_net.sh b/testcases/lib/tst_net.sh
index e6bb09d81..6168db86b 100644
--- a/testcases/lib/tst_net.sh
+++ b/testcases/lib/tst_net.sh
@@ -1,7 +1,7 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) 2014-2017 Oracle and/or its affiliates. All Rights Reserved.
-# Copyright (c) 2016-2022 Petr Vorel <pvorel@suse.cz>
+# Copyright (c) 2016-2023 Petr Vorel <pvorel@suse.cz>
# Author: Alexey Kodanev <alexey.kodanev@oracle.com>
[ -n "$TST_LIB_NET_LOADED" ] && return 0
@@ -59,7 +59,7 @@ tst_net_remote_tmpdir()
tst_net_setup()
{
- [ "$TST_IPVER" = 6 ] && tst_net_require_ipv6
+ [ "$TST_IPV6" ] && tst_net_require_ipv6
tst_net_remote_tmpdir
[ -n "$TST_SETUP_CALLER" ] && $TST_SETUP_CALLER
@@ -73,52 +73,93 @@ tst_net_setup()
fi
}
-if [ "$TST_PARSE_ARGS_CALLER" = "$TST_PARSE_ARGS" ]; then
- tst_res TWARN "TST_PARSE_ARGS_CALLER same as TST_PARSE_ARGS, unset it ($TST_PARSE_ARGS)"
- unset TST_PARSE_ARGS_CALLER
-fi
-if [ "$TST_SETUP_CALLER" = "$TST_SETUP" ]; then
- tst_res TWARN "TST_SETUP_CALLER same as TST_SETUP, unset it ($TST_SETUP)"
- unset TST_SETUP_CALLER
-fi
-if [ "$TST_USAGE_CALLER" = "$TST_USAGE" ]; then
- tst_res TWARN "TST_USAGE_CALLER same as TST_USAGE, unset it ($TST_USAGE)"
- unset TST_USAGE_CALLER
-fi
-
-if [ -n "$TST_USE_LEGACY_API" ]; then
- tst_net_read_opts "$@"
-fi
-
# old vs. new API compatibility layer
tst_res_()
{
[ -z "$TST_USE_LEGACY_API" ] && tst_res $@ || tst_resm $@
}
+
tst_brk_()
{
[ -z "$TST_USE_LEGACY_API" ] && tst_brk $@ || tst_brkm $@
}
+# Detect IPv6 disabled via 1) CONFIG_IPV6=n or 2) ipv6.disable=1 kernel cmdline
+# parameter or 3) sysctl net.ipv6.conf.all.disable_ipv6=1 (disables IPv6 on all
+# interfaces (including both already created and later created).
+# $TST_NET_IPV6_ENABLED: 1 on IPv6 enabled, 0 on IPv6 disabled.
tst_net_detect_ipv6()
{
local type="${1:-lhost}"
local cmd='[ -f /proc/net/if_inet6 ]'
- local ret
+ local disabled iface ret
if [ "$type" = "lhost" ]; then
$cmd
else
tst_rhost_run -c "$cmd"
fi
- ret=$?
- if [ $ret -eq 0 ]; then
- TST_NET_IPV6_ENABLED=1
+ if [ $? -ne 0 ]; then
+ TST_NET_IPV6_ENABLED=0
+ tst_res_ TINFO "IPv6 disabled on $type via kernel command line or not compiled in"
+ return
+ fi
+
+ cmd='cat /proc/sys/net/ipv6/conf/all/disable_ipv6'
+ if [ "$type" = "lhost" ]; then
+ disabled=$($cmd)
+ else
+ disabled=$(tst_rhost_run -c "$cmd")
+ fi
+ if [ $disabled = 1 ]; then
+ tst_res_ TINFO "IPv6 disabled on $type net.ipv6.conf.all.disable_ipv6=1"
+ TST_NET_IPV6_ENABLED=0
+ return
+ fi
+
+ TST_NET_IPV6_ENABLED=1
+}
+
+# Detect IPv6 disabled on interface via sysctl
+# net.ipv6.conf.$iface.disable_ipv6=1.
+# $TST_NET_IPV6_ENABLED: 1 on IPv6 enabled, 0 on IPv6 disabled.
+# return: 0 on IPv6 enabled, 1 on IPv6 disabled.
+tst_net_detect_ipv6_iface()
+{
+ [ "$TST_NET_IPV6_ENABLED" = 1 ] || return 1
+
+ local iface="$1"
+ local type="${2:-lhost}"
+ local check="cat /proc/sys/net/ipv6/conf/$iface/disable_ipv6"
+ local disabled
+
+ if [ "$type" = "lhost" ]; then
+ disabled=$($check)
else
+ disabled=$(tst_rhost_run -c "$check")
+ fi
+ if [ $disabled = 1 ]; then
+ tst_res_ TINFO "IPv6 disabled on $type on $iface"
TST_NET_IPV6_ENABLED=0
- tst_res TINFO "IPv6 disabled on $type"
+ return 1
fi
+
+ return 0
+}
+
+# Detect IPv6 disabled on used interfaces.
+tst_net_check_ifaces_ipv6()
+{
+ local iface
+
+ for iface in $(tst_get_ifaces); do
+ tst_net_detect_ipv6_iface $iface || return
+ done
+
+ for iface in $(tst_get_ifaces rhost); do
+ tst_net_detect_ipv6_iface $iface rhost || return
+ done
}
tst_net_require_ipv6()
@@ -131,18 +172,18 @@ init_ltp_netspace()
local pid
if [ ! -f /var/run/netns/ltp_ns -a -z "$LTP_NETNS" ]; then
- tst_require_cmds ip ns_create ns_exec ns_ifmove
+ tst_require_cmds ip tst_ns_create tst_ns_exec tst_ns_ifmove
tst_require_root
tst_require_drivers veth
ROD ip link add name ltp_ns_veth1 type veth peer name ltp_ns_veth2
- pid="$(ROD ns_create net,mnt)"
+ pid="$(ROD tst_ns_create net,mnt)"
mkdir -p /var/run/netns
ROD ln -s /proc/$pid/ns/net /var/run/netns/ltp_ns
- ROD ns_exec $pid net,mnt mount --make-rprivate /sys
- ROD ns_exec $pid net,mnt mount -t sysfs none /sys
- ROD ns_ifmove ltp_ns_veth1 $pid
- ROD ns_exec $pid net,mnt ip link set lo up
+ ROD tst_ns_exec $pid net,mnt mount --make-rprivate /sys
+ ROD tst_ns_exec $pid net,mnt mount -t sysfs none /sys
+ ROD tst_ns_ifmove ltp_ns_veth1 $pid
+ ROD tst_ns_exec $pid net,mnt ip link set lo up
elif [ -n "$LTP_NETNS" ]; then
tst_res_ TINFO "using not default LTP netns: '$LTP_NETNS'"
fi
@@ -150,10 +191,8 @@ init_ltp_netspace()
LHOST_IFACES="${LHOST_IFACES:-ltp_ns_veth2}"
RHOST_IFACES="${RHOST_IFACES:-ltp_ns_veth1}"
- export TST_INIT_NETNS="no"
-
pid="$(echo $(readlink /var/run/netns/ltp_ns) | cut -f3 -d'/')"
- export LTP_NETNS="${LTP_NETNS:-ns_exec $pid net,mnt}"
+ export LTP_NETNS="${LTP_NETNS:-tst_ns_exec $pid net,mnt}"
tst_restore_ipaddr
tst_restore_ipaddr rhost
@@ -460,7 +499,7 @@ tst_ipaddr_un()
;;
m)
! tst_is_int "$OPTARG" || [ "$OPTARG" -lt 0 ]|| [ "$OPTARG" -gt $max_net_id ] && \
- tst_brk TBROK "tst_ipaddr_un: -m must be integer <0,$max_net_id> ($OPTARG)"
+ tst_brk_ TBROK "tst_ipaddr_un: -m must be integer <0,$max_net_id> ($OPTARG)"
[ "$OPTARG" -gt $max_net_id ] && \
tst_brk_ TBROK "tst_ipaddr_un: -m cannot be higher than $max_net_id ($OPTARG)"
max_host_id="$OPTARG"
@@ -481,16 +520,16 @@ tst_ipaddr_un()
! tst_is_int "$min_host_id" || ! tst_is_int "$max_host_id" || \
[ $min_host_id -lt 0 -o $min_host_id -gt $default_max ] || \
[ $max_host_id -lt 0 -o $max_host_id -gt $default_max ] && \
- tst_brk TBROK "tst_ipaddr_un: HOST_ID must be int in range <0,$default_max> ($min_host_id,$max_host_id)"
+ tst_brk_ TBROK "tst_ipaddr_un: HOST_ID must be int in range <0,$default_max> ($min_host_id,$max_host_id)"
! tst_is_int "$min_net_id" || ! tst_is_int "$max_net_id" || \
[ $min_net_id -lt 0 -o $min_net_id -gt $default_max ] || \
[ $max_net_id -lt 0 -o $max_net_id -gt $default_max ] && \
- tst_brk TBROK "tst_ipaddr_un: NET_ID must be int in range <0,$default_max> ($min_net_id,$max_net_id)"
+ tst_brk_ TBROK "tst_ipaddr_un: NET_ID must be int in range <0,$default_max> ($min_net_id,$max_net_id)"
[ $min_host_id -gt $max_host_id ] && \
- tst_brk TBROK "tst_ipaddr_un: max HOST_ID ($max_host_id) must be >= min HOST_ID ($min_host_id)"
+ tst_brk_ TBROK "tst_ipaddr_un: max HOST_ID ($max_host_id) must be >= min HOST_ID ($min_host_id)"
[ $min_net_id -gt $max_net_id ] && \
- tst_brk TBROK "tst_ipaddr_un: max NET_ID ($max_net_id) must be >= min NET_ID ($min_net_id)"
+ tst_brk_ TBROK "tst_ipaddr_un: max NET_ID ($max_net_id) must be >= min NET_ID ($min_net_id)"
# counter
host_range=$((max_host_id - min_host_id + 1))
@@ -533,7 +572,9 @@ tst_init_iface()
local type="${1:-lhost}"
local link_num="${2:-0}"
local iface="$(tst_iface $type $link_num)"
+
tst_res_ TINFO "initialize '$type' '$iface' interface"
+ tst_net_detect_ipv6_iface $iface $type
if [ "$type" = "lhost" ]; then
if ip xfrm state 1>/dev/null 2>&1; then
@@ -584,7 +625,7 @@ tst_add_ipaddr()
d) action="del" ;;
q) quiet=1 ;;
s) lsafe="ROD"; rsafe="-s" ;;
- *) tst_brk TBROK "tst_add_ipaddr: unknown option: $OPTARG" ;;
+ *) tst_brk_ TBROK "tst_add_ipaddr: unknown option: $OPTARG" ;;
esac
done
shift $((OPTIND - 1))
@@ -593,6 +634,8 @@ tst_add_ipaddr()
local link_num="${2:-0}"
local iface=$(tst_iface $type $link_num)
+ tst_net_detect_ipv6_iface $iface $type
+
if [ "$TST_IPV6" ]; then
dad="nodad"
[ "$type" = "lhost" ] && mask=$IPV6_LPREFIX || mask=$IPV6_RPREFIX
@@ -969,43 +1012,25 @@ tst_default_max_pkt()
echo "$((mtu + mtu / 10))"
}
-[ -n "$TST_USE_LEGACY_API" ] && . test.sh || . tst_test.sh
-
-# detect IPv6 support on lhost for tests which don't use test links
-tst_net_detect_ipv6
-
-[ -n "$TST_NET_SKIP_VARIABLE_INIT" ] && return 0
-
-# Management Link
-[ -z "$RHOST" ] && TST_USE_NETNS="yes"
-export RHOST="$RHOST"
-export PASSWD="${PASSWD:-}"
-# Don't use it in new tests, use tst_rhost_run() from tst_net.sh instead.
-export LTP_RSH="${LTP_RSH:-ssh -nq}"
-
-# Test Links
-# IPV{4,6}_{L,R}HOST can be set with or without prefix (e.g. IP or IP/prefix),
-# but if you use IP/prefix form, /prefix will be removed by tst_net_vars.
-IPV4_LHOST="${IPV4_LHOST:-10.0.0.2/24}"
-IPV4_RHOST="${IPV4_RHOST:-10.0.0.1/24}"
-IPV6_LHOST="${IPV6_LHOST:-fd00:1:1:1::2/64}"
-IPV6_RHOST="${IPV6_RHOST:-fd00:1:1:1::1/64}"
-
-# tst_net_ip_prefix
+# Setup LTP network.
+#
+# Used tools:
+# * tst_net_ip_prefix
# Strip prefix from IP address and save both If no prefix found sets
# default prefix.
-#
-# tst_net_iface_prefix reads prefix and interface from rtnetlink.
+# * tst_net_iface_prefix reads prefix and interface from rtnetlink.
# If nothing found sets default prefix value.
-#
-# tst_net_vars exports environment variables related to test links and
+# * tst_net_vars exports environment variables related to test links and
# networks that aren't reachable through the test links.
#
# For full list of exported environment variables see:
# tst_net_ip_prefix -h
# tst_net_iface_prefix -h
# tst_net_vars -h
-if [ -z "$_tst_net_parse_variables" ]; then
+tst_net_setup_network()
+{
+ tst_require_cmds tst_net_iface_prefix tst_net_ip_prefix tst_net_vars
+
eval $(tst_net_ip_prefix $IPV4_LHOST || echo "exit $?")
eval $(tst_net_ip_prefix -r $IPV4_RHOST || echo "exit $?")
@@ -1015,25 +1040,20 @@ if [ -z "$_tst_net_parse_variables" ]; then
eval $(tst_net_ip_prefix $IPV6_LHOST || echo "exit $?")
eval $(tst_net_ip_prefix -r $IPV6_RHOST || echo "exit $?")
fi
-fi
-[ -n "$TST_USE_NETNS" -a "$TST_INIT_NETNS" != "no" ] && init_ltp_netspace
+ tst_net_use_netns && init_ltp_netspace
-if [ -z "$_tst_net_parse_variables" ]; then
eval $(tst_net_iface_prefix $IPV4_LHOST || echo "exit $?")
eval $(tst_rhost_run -c 'tst_net_iface_prefix -r '$IPV4_RHOST \
|| echo "exit $?")
+ eval $(tst_net_vars $IPV4_LHOST/$IPV4_LPREFIX \
+ $IPV4_RHOST/$IPV4_RPREFIX || echo "exit $?")
if [ "$TST_NET_IPV6_ENABLED" = 1 ]; then
+ tst_net_check_ifaces_ipv6
eval $(tst_net_iface_prefix $IPV6_LHOST || echo "exit $?")
eval $(tst_rhost_run -c 'tst_net_iface_prefix -r '$IPV6_RHOST \
|| echo "exit $?")
- fi
-
- eval $(tst_net_vars $IPV4_LHOST/$IPV4_LPREFIX \
- $IPV4_RHOST/$IPV4_RPREFIX || echo "exit $?")
-
- if [ "$TST_NET_IPV6_ENABLED" = 1 ]; then
eval $(tst_net_vars $IPV6_LHOST/$IPV6_LPREFIX \
$IPV6_RHOST/$IPV6_RPREFIX || echo "exit $?")
fi
@@ -1043,9 +1063,56 @@ if [ -z "$_tst_net_parse_variables" ]; then
tst_res_ TINFO "$IPV4_LHOST/$IPV4_LPREFIX -- $IPV4_RHOST/$IPV4_RPREFIX"
tst_res_ TINFO "$IPV6_LHOST/$IPV6_LPREFIX -- $IPV6_RHOST/$IPV6_RPREFIX"
- export _tst_net_parse_variables="yes"
+ if [ -n "$TST_USE_LEGACY_API" ]; then
+ [ "$TST_IPV6" ] && tst_net_require_ipv6
+ tst_net_remote_tmpdir
+ fi
+}
+
+[ -n "$TST_USE_LEGACY_API" ] && . test.sh || . tst_test.sh
+
+if [ -n "$TST_USE_LEGACY_API" ]; then
+ tst_net_read_opts "$@"
+else
+ if [ "$TST_PARSE_ARGS_CALLER" = "$TST_PARSE_ARGS" ]; then
+ tst_res_ TWARN "TST_PARSE_ARGS_CALLER same as TST_PARSE_ARGS, unset it ($TST_PARSE_ARGS)"
+ unset TST_PARSE_ARGS_CALLER
+ fi
+ if [ "$TST_SETUP_CALLER" = "$TST_SETUP" ]; then
+ tst_res_ TWARN "TST_SETUP_CALLER same as TST_SETUP, unset it ($TST_SETUP)"
+ unset TST_SETUP_CALLER
+ fi
+ if [ "$TST_USAGE_CALLER" = "$TST_USAGE" ]; then
+ tst_res_ TWARN "TST_USAGE_CALLER same as TST_USAGE, unset it ($TST_USAGE)"
+ unset TST_USAGE_CALLER
+ fi
fi
+# detect IPv6 support on lhost for tests which don't use test links
+tst_net_detect_ipv6
+
+[ -n "$TST_NET_SKIP_VARIABLE_INIT" ] && return 0
+
+# Management Link
+[ -z "$RHOST" ] && TST_USE_NETNS="yes"
+export RHOST="$RHOST"
+export PASSWD="${PASSWD:-}"
+# Don't use it in new tests, use tst_rhost_run() from tst_net.sh instead.
+export LTP_RSH="${LTP_RSH:-ssh -nq}"
+
+# Test Links
+# IPV{4,6}_{L,R}HOST can be set with or without prefix (e.g. IP or IP/prefix),
+# but if you use IP/prefix form, /prefix will be removed by tst_net_vars.
+IPV4_LHOST="${IPV4_LHOST:-10.0.0.2/24}"
+IPV4_RHOST="${IPV4_RHOST:-10.0.0.1/24}"
+IPV6_LHOST="${IPV6_LHOST:-fd00:1:1:1::2/64}"
+IPV6_RHOST="${IPV6_RHOST:-fd00:1:1:1::1/64}"
+
+tst_net_setup_network
+
+# More information about network parameters can be found
+# in the following document: testcases/network/stress/README
+
export TST_NET_DATAROOT="$LTPROOT/testcases/bin/datafiles"
export TST_NETLOAD_CLN_REQUESTS="${TST_NETLOAD_CLN_REQUESTS:-10000}"
@@ -1090,13 +1157,6 @@ export RHOST_HWADDRS="${RHOST_HWADDRS:-$(tst_get_hwaddrs rhost)}"
export NS_ICMPV4_SENDER_DATA_MAXSIZE=1472
export NS_ICMPV6_SENDER_DATA_MAXSIZE=1452
-# More information about network parameters can be found
-# in the following document: testcases/network/stress/README
-
-if [ -n "$TST_USE_LEGACY_API" ]; then
- tst_net_remote_tmpdir
-fi
-
if [ -z "$TST_USE_LEGACY_API" ] && ! tst_cmd_available ping6; then
ping6()
{
diff --git a/testcases/lib/tst_ns_common.h b/testcases/lib/tst_ns_common.h
new file mode 100644
index 000000000..358db5141
--- /dev/null
+++ b/testcases/lib/tst_ns_common.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (c) 2015 Red Hat, Inc.
+ * Copyright (c) Linux Test Project, 2015-2023
+ */
+
+#ifndef TST_NS_COMMON_H__
+#define TST_NS_COMMON_H__
+#include <sched.h>
+#include "lapi/sched.h"
+
+#define PROC_PATH "/proc"
+
+struct param {
+ const char *name;
+ int flag;
+};
+
+static struct param params[] = {
+ {"ipc", CLONE_NEWIPC},
+ {"mnt", CLONE_NEWNS},
+ {"net", CLONE_NEWNET},
+ {"pid", CLONE_NEWPID},
+ {"user", CLONE_NEWUSER},
+ {"uts", CLONE_NEWUTS},
+ {NULL, 0}
+};
+
+#define NS_TOTAL (ARRAY_SIZE(params) - 1)
+
+static struct param *get_param(const char *name)
+{
+ int i;
+
+ for (i = 0; params[i].name; i++) {
+ if (!strcasecmp(params[i].name, name))
+ return params + i;
+ }
+
+ return NULL;
+}
+
+#endif /* TST_NS_COMMON_H__ */
diff --git a/testcases/lib/tst_ns_create.c b/testcases/lib/tst_ns_create.c
new file mode 100644
index 000000000..1c6258cd1
--- /dev/null
+++ b/testcases/lib/tst_ns_create.c
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2015 Red Hat, Inc.
+ * Matus Marhefka <mmarhefk@redhat.com>
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ * Copyright (c) Linux Test Project, 2020-2023
+ */
+
+/*\
+ * [Description]
+ *
+ * Creates a child process in the new specified namespace(s), child is then
+ * daemonized and is running in the background. PID of the daemonized child
+ * process is printed on the stdout. As the new namespace(s) is(are) maintained
+ * by the daemonized child process it(they) can be removed by killing this
+ * process.
+ */
+
+#define TST_NO_DEFAULT_MAIN
+
+#include <stdio.h>
+#include <string.h>
+#include "tst_test.h"
+#include "tst_ns_common.h"
+
+extern struct tst_test *tst_test;
+
+static struct tst_test test = {
+ .forks_child = 1, /* Needed by SAFE_CLONE */
+};
+
+static void print_help(void)
+{
+ int i;
+
+ printf("usage: tst_ns_create <%s", params[0].name);
+
+ for (i = 1; params[i].name; i++)
+ printf("|,%s", params[i].name);
+
+ printf(">\n");
+}
+
+static void child_fn(void)
+{
+ int i;
+
+ SAFE_SETSID();
+ SAFE_CHDIR("/");
+
+ for (i = 0; i < SAFE_SYSCONF(_SC_OPEN_MAX); i++)
+ close(i);
+
+ printf("pausing child\n");
+ pause();
+}
+
+int main(int argc, char *argv[])
+{
+ struct tst_clone_args args = { 0, SIGCHLD };
+ char *token;
+ int pid;
+
+ if (argc < 2) {
+ print_help();
+ return 1;
+ }
+
+ tst_test = &test;
+
+ while ((token = strsep(&argv[1], ","))) {
+ struct param *p = get_param(token);
+
+ if (!p) {
+ printf("Unknown namespace: %s\n", token);
+ print_help();
+ return 1;
+ }
+
+ args.flags |= p->flag;
+ }
+
+ pid = SAFE_CLONE(&args);
+ if (!pid) {
+ child_fn();
+ return 0;
+ }
+
+ printf("%d", pid);
+
+ return 0;
+}
diff --git a/testcases/lib/tst_ns_exec.c b/testcases/lib/tst_ns_exec.c
new file mode 100644
index 000000000..66a4e69d3
--- /dev/null
+++ b/testcases/lib/tst_ns_exec.c
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2015 Red Hat, Inc.
+ * Matus Marhefka <mmarhefk@redhat.com>
+ * Copyright (c) Linux Test Project, 2015-2023
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * Enters the namespace(s) of a process specified by a PID and then executes
+ * the indicated program inside that namespace(s).
+ */
+
+#define TST_NO_DEFAULT_MAIN
+
+#include <stdio.h>
+#include <sys/wait.h>
+#include "tst_test.h"
+#include "tst_ns_common.h"
+
+extern struct tst_test *tst_test;
+
+static struct tst_test test = {
+ .forks_child = 1, /* Needed by SAFE_CLONE */
+};
+
+static int ns_fd[NS_TOTAL];
+static int ns_fds;
+
+static void print_help(void)
+{
+ int i;
+
+ printf("usage: tst_ns_exec <NS_PID> <%s", params[0].name);
+
+ for (i = 1; params[i].name; i++)
+ printf("|,%s", params[i].name);
+
+ printf("> <PROGRAM> [ARGS]\nSecond argument indicates the types"
+ " of a namespaces maintained by NS_PID\nand is specified"
+ " as a comma separated list.\n"
+ "Example: tst_ns_exec 1234 net,ipc ip a\n");
+}
+
+static void open_ns_fd(const char *pid, const char *ns)
+{
+ int fd;
+ char file_buf[64];
+
+ sprintf(file_buf, "%s/%s/ns/%s", PROC_PATH, pid, ns);
+
+ fd = SAFE_OPEN(file_buf, O_RDONLY);
+ ns_fd[ns_fds] = fd;
+
+ ++ns_fds;
+}
+
+static void close_ns_fd(void)
+{
+ int i;
+
+ for (i = 0; i < ns_fds; i++)
+ SAFE_CLOSE(ns_fd[i]);
+}
+
+int main(int argc, char *argv[])
+{
+ struct tst_clone_args args = { 0, SIGCHLD };
+ int i, status, pid;
+ char *token;
+
+ tst_test = &test;
+
+ if (argc < 4) {
+ print_help();
+ return 1;
+ }
+
+ memset(ns_fd, 0, sizeof(ns_fd));
+
+ while ((token = strsep(&argv[2], ","))) {
+ struct param *p = get_param(token);
+
+ if (!p) {
+ printf("Unknown namespace: %s\n", token);
+ print_help();
+ return 1;
+ }
+
+ open_ns_fd(argv[1], token);
+ }
+
+ if (!ns_fds) {
+ printf("no namespace entries in /proc/%s/ns/\n", argv[1]);
+ return 1;
+ }
+
+ for (i = 0; i < ns_fds; i++)
+ SAFE_SETNS(ns_fd[i], 0);
+
+ pid = SAFE_CLONE(&args);
+ if (!pid)
+ SAFE_EXECVP(argv[3], argv+3);
+
+ SAFE_WAITPID(pid, &status, 0);
+
+ close_ns_fd();
+
+ if (WIFEXITED(status))
+ return WEXITSTATUS(status);
+
+ return 0;
+}
diff --git a/testcases/lib/tst_ns_ifmove.c b/testcases/lib/tst_ns_ifmove.c
new file mode 100644
index 000000000..03531fc9b
--- /dev/null
+++ b/testcases/lib/tst_ns_ifmove.c
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* Copyright (c) 2015 Red Hat, Inc.
+ * Copyright (c) Linux Test Project, 2015-2022
+ * Copyright (c) 2023 Petr Vorel <pvorel@suse.cz>
+ * Written by Matus Marhefka <mmarhefk@redhat.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * Moves a network interface to the namespace of a process specified by a PID.
+ */
+
+#include "config.h"
+
+#define TST_NO_DEFAULT_MAIN
+#include "tst_test.h"
+#include "tst_safe_macros.h"
+#include "tst_safe_net.h"
+
+#include <linux/if.h>
+#include <linux/rtnetlink.h>
+#include <net/ethernet.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_DECL_IFLA_NET_NS_PID
+
+static struct {
+ struct nlmsghdr nh;
+ struct ifinfomsg ifi;
+ char attrbuf[512];
+} req;
+
+
+static int get_intf_index_from_name(const char *intf_name)
+{
+ struct ifreq ifr;
+ int sock_fd;
+
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, intf_name, sizeof(ifr.ifr_name) - 1);
+ ifr.ifr_name[sizeof(ifr.ifr_name)-1] = '\0';
+
+ sock_fd = SAFE_SOCKET(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+
+ /* interface index */
+ SAFE_IOCTL(sock_fd, SIOCGIFINDEX, &ifr);
+ SAFE_CLOSE(sock_fd);
+
+ return ifr.ifr_ifindex;
+}
+
+int main(int argc, char **argv)
+{
+ struct rtattr *rta;
+ int intf_index, pid, rtnetlink_socket;
+
+ if (argc != 3) {
+ printf("tst_ns_ifmove <INTERFACE_NAME> <NAMESPACE_PID>\n");
+ return 1;
+ }
+
+ intf_index = get_intf_index_from_name(argv[1]);
+ pid = atoi(argv[2]);
+ rtnetlink_socket = SAFE_SOCKET(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
+
+ memset(&req, 0, sizeof(req));
+ req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
+ req.nh.nlmsg_flags = NLM_F_REQUEST;
+ req.nh.nlmsg_type = RTM_NEWLINK;
+ req.ifi.ifi_family = AF_UNSPEC;
+ req.ifi.ifi_index = intf_index;
+ req.ifi.ifi_change = 0xffffffff;
+ rta = (struct rtattr *)(((char *) &req) +
+ NLMSG_ALIGN(req.nh.nlmsg_len));
+ rta->rta_type = IFLA_NET_NS_PID;
+ rta->rta_len = RTA_LENGTH(sizeof(int));
+ req.nh.nlmsg_len = NLMSG_ALIGN(req.nh.nlmsg_len) +
+ RTA_LENGTH(sizeof(pid));
+ memcpy(RTA_DATA(rta), &pid, sizeof(pid));
+
+ SAFE_SEND(1, rtnetlink_socket, &req, req.nh.nlmsg_len, 0);
+ SAFE_CLOSE(rtnetlink_socket);
+
+ return 0;
+}
+
+#else
+ TST_TEST_TCONF("IFLA_NET_NS_PID not defined in linux/if_link.h");
+#endif
diff --git a/testcases/lib/tst_secureboot_enabled.c b/testcases/lib/tst_secureboot_enabled.c
new file mode 100644
index 000000000..dadc0413c
--- /dev/null
+++ b/testcases/lib/tst_secureboot_enabled.c
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2023 Petr Vorel <pvorel@suse.cz>
+ */
+
+#define TST_NO_DEFAULT_MAIN
+#include "tst_test.h"
+
+int main(void)
+{
+ return tst_secureboot_enabled() <= 0;
+}
diff --git a/testcases/lib/tst_test.sh b/testcases/lib/tst_test.sh
index 3bd68a63a..b3f451a21 100644
--- a/testcases/lib/tst_test.sh
+++ b/testcases/lib/tst_test.sh
@@ -532,7 +532,7 @@ _tst_cleanup_timer()
{
if [ -n "$_tst_setup_timer_pid" ]; then
kill -TERM $_tst_setup_timer_pid 2>/dev/null
- # kill is succesful only on test timeout
+ # kill is successful only on test timeout
wait $_tst_setup_timer_pid 2>/dev/null || true
fi
}
@@ -682,7 +682,7 @@ tst_run()
CHECKPOINT_WAIT|CHECKPOINT_WAKE);;
CHECKPOINT_WAKE2|CHECKPOINT_WAKE_AND_WAIT);;
DEV_EXTRA_OPTS|DEV_FS_OPTS|FORMAT_DEVICE|MOUNT_DEVICE);;
- SKIP_FILESYSTEMS);;
+ SKIP_FILESYSTEMS|SKIP_IN_LOCKDOWN|SKIP_IN_SECUREBOOT);;
*) tst_res TWARN "Reserved variable TST_$_tst_i used!";;
esac
done
@@ -702,6 +702,14 @@ tst_run()
[ "$TST_NEEDS_ROOT" = 1 ] && tst_require_root
+ if [ "$TST_SKIP_IN_SECUREBOOT" = 1 ] && tst_secureboot_enabled; then
+ tst_brk TCONF "SecureBoot enabled, skipping test"
+ fi
+
+ if [ "$TST_SKIP_IN_LOCKDOWN" = 1 ] && tst_lockdown_enabled; then
+ tst_brk TCONF "Kernel is locked down, skipping test"
+ fi
+
[ "$TST_DISABLE_APPARMOR" = 1 ] && tst_disable_apparmor
[ "$TST_DISABLE_SELINUX" = 1 ] && tst_disable_selinux
@@ -726,6 +734,8 @@ tst_run()
fi
TST_TMPDIR=$(mktemp -d "$TMPDIR/LTP_$TST_ID.XXXXXXXXXX")
+ # remove possible trailing slash or double slashes from TMPDIR
+ TST_TMPDIR=$(echo "$TST_TMPDIR" | sed 's~/\+~/~g')
chmod 777 "$TST_TMPDIR"