[apparmor] [patch] regression tests: make sysctl(2) test a bit more resiliant

Steve Beattie steve at nxnw.org
Thu Jul 23 08:45:35 UTC 2015


Hello,

In testing against the 4.1 kernel, the syscall_sysctl testcase started
failing even in the unconfined case. What the test program does is
attempt to adjust the kernel.threads-max sysctl to be slightly larger
and see if the operation succeeds by reading the value back out. It
also attempts to save the original value and restore it. The test
was failing because (in VMs at least) the default value chosen by
the kernel for the kernel.threads-max setting was high enough that
attempts to increase it would be ignored (likely to prevent too much
use of kernel memory by threads), helpfully without any message being
report to dmesg. Thus, the initial read of the current value would
succeed, the write of that value + 1024 would appear to succeed,
but then reading the value back out and comparing it to the expected
value would fail, as it would still be the original value, not the
expected new value.

This patch attempts to address this by first attempting to raise
the value, and if that does not appear to work, to then attempt
to lower it.  It also refactors the code a bit by creating helper
functions to perform the actual sysctl(2) calls to make the code a
bit easier to read.

Nominated for 2.10 and 2.9.
---
 tests/regression/apparmor/syscall_sysctl.c |   76 +++++++++++++++++++----------
 1 file changed, 51 insertions(+), 25 deletions(-)

Index: b/tests/regression/apparmor/syscall_sysctl.c
===================================================================
--- a/tests/regression/apparmor/syscall_sysctl.c
+++ b/tests/regression/apparmor/syscall_sysctl.c
@@ -16,21 +16,44 @@
 #include <string.h>
 
 #define BUFSIZE 4096
+
+static int name[] = {CTL_KERN, KERN_MAX_THREADS};
+
+int read_max_threads(int *max_threads)
+{
+	size_t save_sz = sizeof(*max_threads);
+
+	if (sysctl(name, sizeof(name), max_threads, &save_sz, NULL, 0) == -1){
+		fprintf(stderr, "FAIL: sysctl read failed - %s\n",
+			strerror(errno));
+		return 1;
+	}
+	return 0;
+}
+
+int write_max_threads(int new_max_threads)
+{
+	size_t save_sz = sizeof(new_max_threads);
+
+	if (sysctl(name, sizeof(name), NULL, 0, &new_max_threads, save_sz) == -1){
+		fprintf(stderr, "FAIL: sysctl write failed - %s\n",
+			strerror(errno));
+		return 1;
+	}
+
+	return 0;
+}
+
 int main(int argc, char *argv[])
 {
 	int save_max_threads, new_max_threads, read_new_max_threads;
-	size_t save_sz = sizeof(save_max_threads);
-	int name[] = {CTL_KERN, KERN_MAX_THREADS};
 	int readonly = 0;
 	
-	if ((argc > 1) && strcmp(argv[1],"ro") == 0) 
+	if ((argc > 1) && strcmp(argv[1],"ro") == 0)
 		readonly = 1;
 
-	if (sysctl(name, sizeof(name), &save_max_threads, &save_sz, NULL, 0) == -1){
-		fprintf(stderr, "FAIL: sysctl read failed - %s\n",
-			strerror(errno));
+	if (read_max_threads(&save_max_threads) != 0)
 		return 1;
-	}
 
 	/* printf("Kernel max threads (saved) is %d\n", save_max_threads); */
 
@@ -41,36 +64,39 @@ int main(int argc, char *argv[])
 
 	new_max_threads = save_max_threads + 1024;
 
-	if (sysctl(name, sizeof(name), NULL, 0, &new_max_threads, save_sz) == -1){
-		fprintf(stderr, "FAIL: sysctl write failed - %s\n",
-			strerror(errno));
+	if (write_max_threads(new_max_threads) != 0)
 		return 1;
-	}
 
-	if (sysctl(name, sizeof(name), &read_new_max_threads, &save_sz, NULL, 0) == -1){
-		fprintf(stderr, "FAIL: sysctl read failed - %s\n",
-			strerror(errno));
+	if (read_max_threads(&read_new_max_threads) != 0)
 		return 1;
-	}
 
 	/* printf("Kernel max threads (new) is %d\n", read_new_max_threads); */
 
 	if (read_new_max_threads != new_max_threads) {
-		fprintf(stderr, "FAIL: read value does not match written values\n");
-		return 1;
+		/* the kernel possibly rejected our updated max threads
+		 * as being too large; try decreasing max threads. */
+
+		new_max_threads = save_max_threads - 1024;
+
+		if (write_max_threads(new_max_threads) != 0)
+			return 1;
+
+		if (read_max_threads(&read_new_max_threads) != 0)
+			return 1;
+
+		/* printf("Kernel max threads (new, 2nd attempt) is %d\n", read_new_max_threads); */
+
+		if (read_new_max_threads != new_max_threads) {
+			fprintf(stderr, "FAIL: read value does not match written values\n");
+			return 1;
+		}
 	}
 
-	if (sysctl(name, sizeof(name), NULL, 0, &save_max_threads, save_sz) == -1){
-		fprintf(stderr, "FAIL: sysctl write failed - %s\n",
-			strerror(errno));
+	if (write_max_threads(save_max_threads) != 0)
 		return 1;
-	}
 
-	if (sysctl(name, sizeof(name), &read_new_max_threads, &save_sz, NULL, 0) == -1){
-		fprintf(stderr, "FAIL: sysctl read failed - %s\n",
-			strerror(errno));
+	if (read_max_threads(&read_new_max_threads) != 0)
 		return 1;
-	}
 
 	/* printf("Kernel max threads (saved) is %d\n", read_new_max_threads);*/
 
-- 
Steve Beattie
<sbeattie at ubuntu.com>
http://NxNW.org/~steve/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <https://lists.ubuntu.com/archives/apparmor/attachments/20150723/bc210847/attachment.pgp>


More information about the AppArmor mailing list