[LTP] [PATCH v4] thp01: Find largest arguments size
Richard Palethorpe
rpalethorpe@suse.com
Fri Sep 22 11:28:02 CEST 2017
Because of kernel commit da029c11e6b1 the arguments size for exec has been
reduced considerably. This causes exec to fail with E2BIG, so we call it
repeatedly with a decreasing number of arguments until it is successful.
As far as I know, there is no other reliable and easy way to determine the
maximum argument length.
Signed-off-by: Richard Palethorpe <rpalethorpe@suse.com>
---
V4 - Change the binary search implementation and add some comments.
testcases/kernel/mem/thp/thp01.c | 116 ++++++++++++++++++++++++++++-----------
1 file changed, 84 insertions(+), 32 deletions(-)
diff --git a/testcases/kernel/mem/thp/thp01.c b/testcases/kernel/mem/thp/thp01.c
index 101a9b5c8..be114e0bf 100644
--- a/testcases/kernel/mem/thp/thp01.c
+++ b/testcases/kernel/mem/thp/thp01.c
@@ -28,8 +28,15 @@
* invalid opcode: 0000 [#1] SMP
* last sysfs file: /sys/devices/system/cpu/cpu23/cache/index2/shared_cpu_map
* ....
+ *
+ * Due to commit da029c11e6b1 which reduced the stack size considerably, we
+ * now perform a binary search to find the largest possible argument we can
+ * use. Only the first iteration of the test performs the search; subsequent
+ * iterations use the result of the search which is stored in some shared
+ * memory.
*/
+#include <errno.h>
#include <sys/types.h>
#include <sys/resource.h>
#include <sys/wait.h>
@@ -37,57 +44,102 @@
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
+#include "tst_test.h"
#include "mem.h"
+#include "tst_minmax.h"
+
+#define ARGS_SZ (256 * 32)
-#define ARRAY_SZ 256
+static struct bisection {
+ long left;
+ long right;
+ long mid;
+} *bst;
-static int ps;
-static long length;
-static char *array[ARRAY_SZ];
+static char *args[ARGS_SZ];
static char *arg;
-static struct rlimit rl = {
- .rlim_cur = RLIM_INFINITY,
- .rlim_max = RLIM_INFINITY,
-};
static void thp_test(void)
{
- int i;
- pid_t pid;
-
- switch (pid = SAFE_FORK()) {
- case 0:
- memset(arg, 'c', length - 1);
- arg[length - 1] = '\0';
- array[0] = "true";
- for (i = 1; i < ARRAY_SZ - 1; i++)
- array[i] = arg;
- array[ARRAY_SZ - 1] = NULL;
- if (setrlimit(RLIMIT_STACK, &rl) == -1) {
- perror("setrlimit");
- exit(1);
- }
- if (execvp("true", array) == -1) {
- perror("execvp");
- exit(1);
+ long prev_left;
+ int pid;
+
+ while (bst->right - bst->left > 1) {
+ pid_t pid = SAFE_FORK();
+
+ if (!pid) {
+ /* We set mid to left assuming exec will succeed. If
+ * exec fails with E2BIG (and thus returns) then we
+ * restore left and set right to mid instead.
+ */
+ prev_left = bst->left;
+ bst->mid = (bst->left + bst->right) / 2;
+ bst->left = bst->mid;
+ args[bst->mid] = NULL;
+
+ TEST(execvp("true", args));
+ if (TEST_ERRNO != E2BIG)
+ tst_brk(TBROK | TTERRNO, "execvp(\"true\", ...)");
+ bst->left = prev_left;
+ bst->right = bst->mid;
+ exit(0);
}
- default:
+
tst_reap_children();
+ tst_res(TINFO, "left: %ld, right: %ld, mid: %ld",
+ bst->left, bst->right, bst->mid);
+ }
+
+ /* We end with mid == right or mid == left where right - left =
+ * 1. Regardless we must use left because right is only set to values
+ * which are too large.
+ */
+ pid = SAFE_FORK();
+ if (pid == 0) {
+ args[bst->left] = NULL;
+ TEST(execvp("true", args));
+ if (TEST_ERRNO != E2BIG)
+ tst_brk(TBROK | TTERRNO, "execvp(\"true\", ...)");
+ exit(0);
}
+ tst_reap_children();
- tst_res(TPASS, "system didn't crash, pass.");
+ tst_res(TPASS, "system didn't crash.");
}
static void setup(void)
{
- ps = sysconf(_SC_PAGESIZE);
- length = 32 * ps;
- arg = SAFE_MALLOC(length);
+ struct rlimit rl = {
+ .rlim_cur = RLIM_INFINITY,
+ .rlim_max = RLIM_INFINITY,
+ };
+ int i;
+ long arg_len, arg_count;
+
+ bst = SAFE_MMAP(NULL, sizeof(*bst),
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+ bst->left = 0;
+ bst->right = ARGS_SZ;
+
+ arg_len = sysconf(_SC_PAGESIZE);
+ arg = SAFE_MALLOC(arg_len);
+ memset(arg, 'c', arg_len - 1);
+ arg[arg_len - 1] = '\0';
+
+ args[0] = "true";
+ arg_count = ARGS_SZ;
+ tst_res(TINFO, "Using %ld args of size %ld", arg_count, arg_len);
+ for (i = 1; i < arg_count; i++)
+ args[i] = arg;
+
+ SAFE_SETRLIMIT(RLIMIT_STACK, &rl);
}
static void cleanup(void)
{
- free(arg);
+ if (arg)
+ free(arg);
}
static struct tst_test test = {
--
2.14.1
More information about the ltp
mailing list