diff mbox series

[v3,4/4] fzsync: Limit execution time to prevent test timeouts

Message ID 20180816120020.11042-4-rpalethorpe@suse.com
State Changes Requested
Headers show
Series [v3,1/4] lib: Allow user to easily get LTP_TIMEOUT_MUL value | expand

Commit Message

Richard Palethorpe Aug. 16, 2018, noon UTC
Use the tst_timer library to check how long the main test loop has been
running for and break the loop if it exceeds (60 * LTP_TIMEOUT_MUL)
seconds. This prevents an overall test timeout which is reported as a failure.

Signed-off-by: Richard Palethorpe <rpalethorpe@suse.com>
---
 include/tst_fuzzy_sync.h                      | 50 +++++++++++++------
 lib/newlib_tests/test16.c                     |  4 +-
 testcases/cve/cve-2014-0196.c                 |  4 +-
 testcases/cve/cve-2016-7117.c                 |  6 ++-
 testcases/cve/cve-2017-2671.c                 |  4 +-
 testcases/kernel/syscalls/inotify/inotify09.c |  5 +-
 6 files changed, 51 insertions(+), 22 deletions(-)

Comments

Li Wang Aug. 17, 2018, 7:43 a.m. UTC | #1
Richard Palethorpe <rpalethorpe@suse.com> wrote:
>
> ...
>
> @@ -99,6 +102,15 @@ struct tst_fzsync_pair {
>         .info_gap = 0x7FFFF     \
>  }
>
> +
> static void tst_fzsync_pair_reset(struct tst_fzsync_pair *pair)
> +{
> +       pair->timer.clock_id = CLOCK_MONOTONIC_RAW;
> +       pair->timer.limit.tv_sec = 60 * tst_timeout_mul();
> +       pair->timer.limit.tv_nsec = 0;
> +
> +       tst_timer_start_st(&pair->timer);
> +}
> +
>

There is a loop defect in this method as I commented in patch V2.

If we don't reset the pair->exit to 0 after one loop, it will be never run
into the second
fzsync function because the pair->exit has been set to 1 at the first
expired time.

something result like:
----------------------------
# ./cve-2016-7117 -i 3
tst_test.c:1022: INFO: Timeout per run is 0h 05m 00s
../../include/tst_fuzzy_sync.h:121: INFO: avg_diff = -216ns, avg_dev =
565ns, delay = 02474 loops
../../include/tst_fuzzy_sync.h:121: INFO: avg_diff = 12ns, avg_dev = 430ns,
delay = 02604 loops
../../include/tst_fuzzy_sync.h:330: INFO: Exceeded fuzzy sync time limit,
requesting exit
cve-2016-7117.c:161: PASS: Nothing happened after 1564741 attempts
cve-2016-7117.c:161: PASS: Nothing happened after 1 attempts
cve-2016-7117.c:161: PASS: Nothing happened after 1 attempts

Summary:
passed   3
failed   0
skipped  0
warnings 0

But, if we just reset the pair->exit to 0 in the new function
tst_fzsync_pair_reset(),
there still NOT fix the problem totally, because in the last test expired
time, all threads
created by setup() function have exited, and here we'll only loop
in tst_fzsync_wait_a()
and wait there forever. :(
Li Wang Aug. 17, 2018, 9:04 a.m. UTC | #2
Li Wang <liwang@redhat.com> wrote:

>
> Richard Palethorpe <rpalethorpe@suse.com> wrote:
>>
>> ...
>>
>> @@ -99,6 +102,15 @@ struct tst_fzsync_pair {
>>         .info_gap = 0x7FFFF     \
>>  }
>>
>> +
>> static void tst_fzsync_pair_reset(struct tst_fzsync_pair *pair)
>> +{
>> +       pair->timer.clock_id = CLOCK_MONOTONIC_RAW;
>> +       pair->timer.limit.tv_sec = 60 * tst_timeout_mul();
>> +       pair->timer.limit.tv_nsec = 0;
>> +
>> +       tst_timer_start_st(&pair->timer);
>> +}
>> +
>>
>
> There is a loop defect in this method as I commented in patch V2.
>
> If we don't reset the pair->exit to 0 after one loop, it will be never run
> into the second
> fzsync function because the pair->exit has been set to 1 at the first
> expired time.
>
> something result like:
> ----------------------------
> # ./cve-2016-7117 -i 3
> tst_test.c:1022: INFO: Timeout per run is 0h 05m 00s
> ../../include/tst_fuzzy_sync.h:121: INFO: avg_diff = -216ns, avg_dev =
> 565ns, delay = 02474 loops
> ../../include/tst_fuzzy_sync.h:121: INFO: avg_diff = 12ns, avg_dev =
> 430ns, delay = 02604 loops
> ../../include/tst_fuzzy_sync.h:330: INFO: Exceeded fuzzy sync time limit,
> requesting exit
> cve-2016-7117.c:161: PASS: Nothing happened after 1564741 attempts
> cve-2016-7117.c:161: PASS: Nothing happened after 1 attempts
> cve-2016-7117.c:161: PASS: Nothing happened after 1 attempts
>
> Summary:
> passed   3
> failed   0
> skipped  0
> warnings 0
>
> But, if we just reset the pair->exit to 0 in the new function
> tst_fzsync_pair_reset(),
> there still NOT fix the problem totally, because in the last test expired
> time, all threads
> created by setup() function have exited, and here we'll only loop
> in tst_fzsync_wait_a()
> and wait there forever. :(
>

I just come up with a stupid patch to fix that, but personally I insist
believe
that maybe we should not leave this kind of works to LTP user, we'd better
encapsulate that all in fuzzy_sync library.

Just FYI:

diff --git a/include/tst_fuzzy_sync.h b/include/tst_fuzzy_sync.h
index 5e0ff36..862ab7e 100644
--- a/include/tst_fuzzy_sync.h
+++ b/include/tst_fuzzy_sync.h
@@ -102,8 +102,14 @@ struct tst_fzsync_pair {
        .info_gap = 0x7FFFF     \
 }

-static void tst_fzsync_pair_reset(struct tst_fzsync_pair *pair)
+static void tst_fzsync_pair_init(struct tst_fzsync_pair *pair)
 {
+       pair->exit = 0;
+       pair->delay = 0;
+       pair->a_cntr = pair->b_cntr = 0;
+       pair->avg_dev = pair->avg_diff = 0;
+       pair->a.tv_sec = pair->a.tv_nsec = 0;
+       pair->b.tv_sec = pair->b.tv_nsec = 0;
        pair->timer.clock_id = CLOCK_MONOTONIC_RAW;
        pair->timer.limit.tv_sec = 60 * tst_timeout_mul();
        pair->timer.limit.tv_nsec = 0;
diff --git a/testcases/cve/cve-2016-7117.c b/testcases/cve/cve-2016-7117.c
index fecc588..f8993c7 100644
--- a/testcases/cve/cve-2016-7117.c
+++ b/testcases/cve/cve-2016-7117.c
@@ -136,7 +136,10 @@ static void run(void)

        msghdrs[0].msg_hdr.msg_iov->iov_base = (void *)&rbuf;

-       tst_fzsync_pair_reset(&fzsync_pair);
+       if (fzsync_pair.exit == 1)
+               setup();
+
+       tst_fzsync_pair_init(&fzsync_pair);
        for (i = 1; i < ATTEMPTS; i++) {
                if (socketpair(AF_LOCAL, SOCK_DGRAM, 0, (int *)socket_fds))
                        tst_brk(TBROK | TERRNO, "Socket creation failed");
diff mbox series

Patch

diff --git a/include/tst_fuzzy_sync.h b/include/tst_fuzzy_sync.h
index bcc625e24..5e0ff3602 100644
--- a/include/tst_fuzzy_sync.h
+++ b/include/tst_fuzzy_sync.h
@@ -42,6 +42,7 @@ 
 #include <time.h>
 #include <math.h>
 #include "tst_atomic.h"
+#include "tst_timer.h"
 
 #ifndef CLOCK_MONOTONIC_RAW
 # define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC
@@ -66,6 +67,7 @@ 
  * @a_cntr: Internal; Atomic counter used by fzsync_pair_wait()
  * @b_cntr: Internal; Atomic counter used by fzsync_pair_wait()
  * @exit: Internal; Used by tst_fzsync_pair_exit() and fzsync_pair_wait()
+ * @timer: Internal; Used to limit the execution time.
  *
  * This contains all the necessary state for synchronising two points A and
  * B. Where A is the time of an event in one process and B is the time of an
@@ -87,6 +89,7 @@  struct tst_fzsync_pair {
 	int a_cntr;
 	int b_cntr;
 	int exit;
+	struct tst_timer timer;
 };
 
 /**
@@ -99,6 +102,15 @@  struct tst_fzsync_pair {
 	.info_gap = 0x7FFFF     \
 }
 
+static void tst_fzsync_pair_reset(struct tst_fzsync_pair *pair)
+{
+	pair->timer.clock_id = CLOCK_MONOTONIC_RAW;
+	pair->timer.limit.tv_sec = 60 * tst_timeout_mul();
+	pair->timer.limit.tv_nsec = 0;
+
+	tst_timer_start_st(&pair->timer);
+}
+
 /**
  * tst_fzsync_pair_info - Print some synchronisation statistics
  */
@@ -265,9 +277,7 @@  static inline int tst_fzsync_pair_wait(struct tst_fzsync_pair *pair,
 			;
 	}
 
-	/* Only exit if we have done the same amount of work as the other thread */
-	return !tst_atomic_load(&pair->exit) ||
-	  tst_atomic_load(other_cntr) <= tst_atomic_load(our_cntr);
+	return !tst_atomic_load(&pair->exit);
 }
 
 static inline int tst_fzsync_wait_a(struct tst_fzsync_pair *pair)
@@ -280,6 +290,17 @@  static inline int tst_fzsync_wait_b(struct tst_fzsync_pair *pair)
 	return tst_fzsync_pair_wait(pair, &pair->b_cntr, &pair->a_cntr);
 }
 
+/**
+ * tst_fzsync_pair_exit - Signal that the other thread should exit
+ *
+ * Causes tst_fzsync_pair_wait() and tst_fzsync_pair_wait_update() to return
+ * 0.
+ */
+static inline void tst_fzsync_pair_exit(struct tst_fzsync_pair *pair)
+{
+	tst_atomic_store(1, &pair->exit);
+}
+
 /**
  * tst_fzsync_pair_wait_update_{a,b} - Wait and then recalculate
  *
@@ -303,8 +324,16 @@  static inline int tst_fzsync_wait_update_a(struct tst_fzsync_pair *pair)
 	static int loop_index;
 
 	tst_fzsync_pair_wait(pair, &pair->a_cntr, &pair->b_cntr);
-	loop_index++;
-	tst_fzsync_pair_update(loop_index, pair);
+
+	if (tst_timer_expired_st(&pair->timer)) {
+		tst_res(TINFO,
+			"Exceeded fuzzy sync time limit, requesting exit");
+		tst_fzsync_pair_exit(pair);
+	} else {
+		loop_index++;
+		tst_fzsync_pair_update(loop_index, pair);
+	}
+
 	return tst_fzsync_pair_wait(pair, &pair->a_cntr, &pair->b_cntr);
 }
 
@@ -313,14 +342,3 @@  static inline int tst_fzsync_wait_update_b(struct tst_fzsync_pair *pair)
 	tst_fzsync_pair_wait(pair, &pair->b_cntr, &pair->a_cntr);
 	return tst_fzsync_pair_wait(pair, &pair->b_cntr, &pair->a_cntr);
 }
-
-/**
- * tst_fzsync_pair_exit - Signal that the other thread should exit
- *
- * Causes tst_fzsync_pair_wait() and tst_fzsync_pair_wait_update() to return
- * 0.
- */
-static inline void tst_fzsync_pair_exit(struct tst_fzsync_pair *pair)
-{
-	tst_atomic_store(1, &pair->exit);
-}
diff --git a/lib/newlib_tests/test16.c b/lib/newlib_tests/test16.c
index d80bd5369..3447dbc5a 100644
--- a/lib/newlib_tests/test16.c
+++ b/lib/newlib_tests/test16.c
@@ -64,8 +64,10 @@  static void run(void)
 {
 	unsigned int i, j, fail = 0;
 
+	tst_fzsync_pair_reset(&pair);
 	for (i = 0; i < LOOPS; i++) {
-		tst_fzsync_wait_update_a(&pair);
+		if (!tst_fzsync_wait_update_a(&pair))
+			break;
 		tst_fzsync_delay_a(&pair);
 		seq[seq_n] = 'A';
 		seq_n = i * 2 + 1;
diff --git a/testcases/cve/cve-2014-0196.c b/testcases/cve/cve-2014-0196.c
index d18108897..4a3f24026 100644
--- a/testcases/cve/cve-2014-0196.c
+++ b/testcases/cve/cve-2014-0196.c
@@ -102,6 +102,7 @@  static void run(void)
 
 	tst_res(TINFO, "Attempting to overflow into a tty_struct...");
 
+	tst_fzsync_pair_reset(&fzsync_pair);
 	for (i = 0; i < ATTEMPTS; i++) {
 		create_pty((int *)&master_fd, (int *)&slave_fd);
 
@@ -118,7 +119,8 @@  static void run(void)
 		t.c_lflag |= ECHO;
 		tcsetattr(master_fd, TCSANOW, &t);
 
-		tst_fzsync_wait_update_a(&fzsync_pair);
+		if (!tst_fzsync_wait_update_a(&fzsync_pair))
+			break;
 
 		tst_fzsync_delay_a(&fzsync_pair);
 		tst_fzsync_time_a(&fzsync_pair);
diff --git a/testcases/cve/cve-2016-7117.c b/testcases/cve/cve-2016-7117.c
index 3cb7efcdf..fecc5889f 100644
--- a/testcases/cve/cve-2016-7117.c
+++ b/testcases/cve/cve-2016-7117.c
@@ -136,11 +136,13 @@  static void run(void)
 
 	msghdrs[0].msg_hdr.msg_iov->iov_base = (void *)&rbuf;
 
+	tst_fzsync_pair_reset(&fzsync_pair);
 	for (i = 1; i < ATTEMPTS; i++) {
 		if (socketpair(AF_LOCAL, SOCK_DGRAM, 0, (int *)socket_fds))
 			tst_brk(TBROK | TERRNO, "Socket creation failed");
 
-		tst_fzsync_wait_update_a(&fzsync_pair);
+		if (!tst_fzsync_wait_update_a(&fzsync_pair))
+			break;
 		tst_fzsync_delay_a(&fzsync_pair);
 
 		stat = tst_syscall(__NR_recvmmsg,
@@ -156,7 +158,7 @@  static void run(void)
 		tst_fzsync_wait_a(&fzsync_pair);
 	}
 
-	tst_res(TPASS, "Nothing happened after %d attempts", ATTEMPTS);
+	tst_res(TPASS, "Nothing happened after %d attempts", i);
 }
 
 static struct tst_test test = {
diff --git a/testcases/cve/cve-2017-2671.c b/testcases/cve/cve-2017-2671.c
index b0471bfff..ce3022ce2 100644
--- a/testcases/cve/cve-2017-2671.c
+++ b/testcases/cve/cve-2017-2671.c
@@ -111,11 +111,13 @@  static void run(void)
 {
 	int i;
 
+	tst_fzsync_pair_reset(&fzsync_pair);
 	for (i = 0; i < ATTEMPTS; i++) {
 		SAFE_CONNECT(sockfd,
 			     (struct sockaddr *)&iaddr, sizeof(iaddr));
 
-		tst_fzsync_wait_update_a(&fzsync_pair);
+		if (!tst_fzsync_wait_update_a(&fzsync_pair))
+			break;
 		tst_fzsync_delay_a(&fzsync_pair);
 		connect(sockfd, (struct sockaddr *)&uaddr, sizeof(uaddr));
 		tst_fzsync_time_a(&fzsync_pair);
diff --git a/testcases/kernel/syscalls/inotify/inotify09.c b/testcases/kernel/syscalls/inotify/inotify09.c
index 475411311..701ab1487 100644
--- a/testcases/kernel/syscalls/inotify/inotify09.c
+++ b/testcases/kernel/syscalls/inotify/inotify09.c
@@ -97,12 +97,15 @@  static void verify_inotify(void)
 	inotify_fd = myinotify_init1(0);
 	if (inotify_fd < 0)
 		tst_brk(TBROK | TERRNO, "inotify_init failed");
+
+	tst_fzsync_pair_reset(&fzsync_pair);
 	for (tests = 0; tests < TEARDOWNS; tests++) {
 		wd = myinotify_add_watch(inotify_fd, FNAME, IN_MODIFY);
 		if (wd < 0)
 			tst_brk(TBROK | TERRNO, "inotify_add_watch() failed.");
 
-		tst_fzsync_wait_update_a(&fzsync_pair);
+		if (!tst_fzsync_wait_update_a(&fzsync_pair))
+			break;
 		tst_fzsync_delay_a(&fzsync_pair);
 
 		wd = myinotify_rm_watch(inotify_fd, wd);