lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <d5f8364b42f277daa9e235d23398e3dce5549e92.1724324945.git.petrm@nvidia.com>
Date: Thu, 22 Aug 2024 15:49:40 +0200
From: Petr Machata <petrm@...dia.com>
To: Shuah Khan <shuah@...nel.org>, <linux-kselftest@...r.kernel.org>,
	<netdev@...r.kernel.org>
CC: Jakub Kicinski <kuba@...nel.org>, Ido Schimmel <idosch@...dia.com>, "Petr
 Machata" <petrm@...dia.com>, Amit Cohen <amcohen@...dia.com>, Benjamin
 Poirier <bpoirier@...dia.com>, Hangbin Liu <liuhangbin@...il.com>, Vladimir
 Oltean <vladimir.oltean@....com>, <mlxsw@...dia.com>
Subject: [RFC PATCH net-next 1/5] selftests: forwarding: Introduce deferred commands

In commit 8510801a9dbd ("selftests: drv-net: add ability to schedule
cleanup with defer()"), a defer helper was added to Python selftests.
The idea is to keep cleanup commands close to their dirtying counterparts,
thereby making it more transparent what is cleaning up what, making it
harder to miss a cleanup, and make the whole cleanup business exception
safe. All these benefits are applicable to bash as well, exception safety
can be interpreted in terms of safety vs. a SIGINT.

This patch therefore introduces a framework of several helpers that serve
to schedule cleanups in bash selftests:

- defer_scope_push(), defer_scope_pop(): Deferred statements can be batched
  together in scopes. When a scope is popped, the deferred commands
  schoduled in that scope are executed in the order opposite to order of
  their scheduling.

- defer(): Schedules a defer to the most recently pushed scope (or the
  default scope if none was pushed.)

- defer_scopes_cleanup(): Pops any unpopped scopes, including the default
  one. The selftests that use defer should run this in their cleanup
  function. This is important to get cleanups of interrupted scripts.

  Consistent use of defers however obviates the need for a separate cleanup
  function -- everything is just taken care of in defers. So this patch
  actually introduces a cleanup() helper in the forwarding lib.sh, which
  calls just pre_cleanup() and defer_scopes_cleanup(). Selftests are
  obviously still free to override the function.

- defer_scoped_fn(): Sometimes a function would like to introduce a new
  defer scope, then run whatever it is that it wants to run, and then pop
  the scope to run the deferred cleanups. The helper defer_scoped_fn() can
  be used to derive from one function its wrapper that pushes a defer scope
  before the function is called, and pops it after it returns.

The following patches will convert several selftests to this new framework.

Signed-off-by: Petr Machata <petrm@...dia.com>
---
 tools/testing/selftests/net/forwarding/lib.sh | 83 +++++++++++++++++++
 1 file changed, 83 insertions(+)

diff --git a/tools/testing/selftests/net/forwarding/lib.sh b/tools/testing/selftests/net/forwarding/lib.sh
index 67f38dd1f36b..21cd6a2e3344 100644
--- a/tools/testing/selftests/net/forwarding/lib.sh
+++ b/tools/testing/selftests/net/forwarding/lib.sh
@@ -1369,6 +1369,12 @@ tests_run()
 	done
 }
 
+cleanup()
+{
+	pre_cleanup
+	defer_scopes_cleanup
+}
+
 multipath_eval()
 {
 	local desc="$1"
@@ -1423,6 +1429,83 @@ in_ns()
 	EOF
 }
 
+# map[(defer_scope,cleanup_id) -> cleanup_command]
+declare -A DEFERS
+# map[defer_scope -> # cleanup_commands]
+declare -a NDEFERS=(0)
+DEFER_SCOPE=0
+
+defer_scope_push()
+{
+	((DEFER_SCOPE++))
+	NDEFERS[${DEFER_SCOPE}]=0
+}
+
+defer_scope_pop()
+{
+	local defer_key
+	local defer_ix
+
+	for ((defer_ix=${NDEFERS[${DEFER_SCOPE}]}; defer_ix-->0; )); do
+		defer_key=${DEFER_SCOPE},$defer_ix
+		${DEFERS[$defer_key]}
+		unset DEFERS[$defer_key]
+	done
+
+	NDEFERS[${DEFER_SCOPE}]=0
+	((DEFER_SCOPE--))
+}
+
+defer()
+{
+	local defer_key=${DEFER_SCOPE},${NDEFERS[${DEFER_SCOPE}]}
+	local defer="$@"
+
+	DEFERS[$defer_key]="$defer"
+	NDEFERS[${DEFER_SCOPE}]=$((${NDEFERS[${DEFER_SCOPE}]} + 1))
+}
+
+defer_scopes_cleanup()
+{
+	while ((DEFER_SCOPE >= 0)); do
+		defer_scope_pop
+	done
+}
+
+defer_scoped_fn()
+{
+	local name=$1; shift;
+	local mangle=__defer_scoped__
+
+	declare -f $name >/dev/null
+	if (($?)); then
+		echo "Cannot make non-existent function '$name' defer-scoped" \
+			> /dev/stderr
+		exit 1
+	fi
+
+	declare -f $mangle$name
+	if ((! $?)); then
+		echo "The function '$name' appears to already be defer-scoped" \
+			> /dev/stderr
+		exit 1
+	fi
+
+	eval "$mangle$(declare -f $name)"
+	local body="
+		$name() {
+			local ret;
+			defer_scope_push;
+			$mangle$name \"\$@\";
+			ret=\$?;
+			defer_scope_pop;
+			return \$ret;
+		}
+	"
+	unset $name
+	eval "$body"
+}
+
 ##############################################################################
 # Tests
 
-- 
2.45.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ