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: <20220331190612.22162-2-mat.jonczyk@o2.pl>
Date:   Thu, 31 Mar 2022 21:06:12 +0200
From:   Mateusz Jończyk <mat.jonczyk@...pl>
To:     linux-kernel@...r.kernel.org, linux-rtc@...r.kernel.org,
        linux-kselftest@...r.kernel.org
Cc:     Mateusz Jończyk <mat.jonczyk@...pl>,
        Alessandro Zummo <a.zummo@...ertech.it>,
        Alexandre Belloni <alexandre.belloni@...tlin.com>,
        Shuah Khan <shuah@...nel.org>
Subject: [PATCH 2/2] [RFC] selftests/rtc: read RTC alarm time many times in a row

This is the userspace part of the test unit.

This patch depends on
commit 2aaa36e95ea5 ("selftests/rtc: continuously read RTC in a loop for 30s")

Existing code casts "struct rtc_time *" to "struct tm *", like so:

	gmtime_r(&secs, (struct tm *)&tm);

This is incorrect, because sizeof(struct tm) > sizeof(struct rtc_time)
(on Ubuntu 20.04 at least) and gmtime_r overwrites part of the stack.
I'll submit a fix for this in mainline soon, but for now I'm defining
timestamp_to_rtc_time() here.

TODO:
- some logic improvements, without much impact on the core algorithm.

Signed-off-by: Mateusz Jończyk <mat.jonczyk@...pl>
Cc: Alessandro Zummo <a.zummo@...ertech.it>
Cc: Alexandre Belloni <alexandre.belloni@...tlin.com>
Cc: Shuah Khan <shuah@...nel.org>
---
 tools/testing/selftests/rtc/rtctest.c | 81 ++++++++++++++++++++++++++-
 tools/testing/selftests/rtc/settings  |  2 +-
 2 files changed, 81 insertions(+), 2 deletions(-)

diff --git a/tools/testing/selftests/rtc/rtctest.c b/tools/testing/selftests/rtc/rtctest.c
index 2b9d929a24ed..7e5f2f1c00ef 100644
--- a/tools/testing/selftests/rtc/rtctest.c
+++ b/tools/testing/selftests/rtc/rtctest.c
@@ -62,7 +62,21 @@ static time_t rtc_time_to_timestamp(struct rtc_time *rtc_time)
 	       .tm_year = rtc_time->tm_year,
 	};
 
-	return mktime(&tm_time);
+	return timegm(&tm_time);
+}
+
+static void timestamp_to_rtc_time(time_t timestamp, struct rtc_time *rtc_time)
+{
+	struct tm tm_time;
+
+	gmtime_r(&timestamp, &tm_time);
+
+	rtc_time->tm_sec = tm_time.tm_sec;
+	rtc_time->tm_min = tm_time.tm_min;
+	rtc_time->tm_hour = tm_time.tm_hour;
+	rtc_time->tm_mday = tm_time.tm_mday;
+	rtc_time->tm_mon = tm_time.tm_mon;
+	rtc_time->tm_year = tm_time.tm_year;
 }
 
 static void nanosleep_with_retries(long ns)
@@ -228,6 +242,71 @@ TEST_F(rtc, alarm_alm_set) {
 	ASSERT_EQ(new, secs);
 }
 
+TEST_F_TIMEOUT(rtc, alarm_read_loop, READ_LOOP_DURATION_SEC + 2) {
+	int rc;
+	long iter_count = 0;
+	struct rtc_time tm;
+	struct timeval start, curr;
+	time_t secs;
+
+	rc = ioctl(self->fd, RTC_RD_TIME, &tm);
+	ASSERT_NE(-1, rc);
+
+	// 60s is for clocks that only support minute resolution of RTC alarm
+	secs = rtc_time_to_timestamp(&tm) + READ_LOOP_DURATION_SEC + 60 + 2;
+	timestamp_to_rtc_time(secs, &tm);
+
+	rc = ioctl(self->fd, RTC_ALM_SET, &tm);
+	if (rc == -1) {
+		ASSERT_EQ(EINVAL, errno);
+		TH_LOG("skip alarms are not supported.");
+		return;
+	}
+
+	rc = ioctl(self->fd, RTC_AIE_ON, NULL);
+	ASSERT_NE(-1, rc);
+
+	TH_LOG("Continuously reading RTC alarm time for %ds (with %dms breaks after every read).",
+	       READ_LOOP_DURATION_SEC, READ_LOOP_SLEEP_MS);
+
+	gettimeofday(&start, NULL);
+
+	secs = 0;
+
+	do {
+		// TODO: use appropriate directory
+		// TODO: fail gracefully if the kernel support does not exist
+		FILE *wkalarm_file = fopen("/sys/kernel/debug/rtc/rtc0/wakealarm_raw", "r");
+		long long wkalarm_time;
+
+		ASSERT_NE(wkalarm_file, NULL);
+
+		rc = fscanf(wkalarm_file, "%lld", &wkalarm_time);
+		fclose(wkalarm_file);
+
+		ASSERT_EQ(rc, 1);
+		ASSERT_NE(secs, -1);
+		// TODO: use another value as placeholder,
+		// TODO: check if wkalarm_time matches alarm time we set
+		// previously
+		if (secs == 0)
+			secs = wkalarm_time;
+
+		ASSERT_EQ(wkalarm_time, secs);
+
+		// Sleep 11ms to avoid killing / overheating the RTC
+		nanosleep_with_retries(READ_LOOP_SLEEP_MS * 1000000);
+
+		gettimeofday(&curr, NULL);
+		iter_count++;
+	} while (curr.tv_sec <= start.tv_sec + READ_LOOP_DURATION_SEC);
+
+	TH_LOG("Performed %ld RTC alarm time reads.", iter_count);
+
+	rc = ioctl(self->fd, RTC_AIE_OFF, NULL);
+	ASSERT_NE(-1, rc);
+}
+
 TEST_F(rtc, alarm_wkalm_set) {
 	struct timeval tv = { .tv_sec = ALARM_DELTA + 2 };
 	struct rtc_wkalrm alarm = { 0 };
diff --git a/tools/testing/selftests/rtc/settings b/tools/testing/selftests/rtc/settings
index 0c1a2075d5f3..b478e684846a 100644
--- a/tools/testing/selftests/rtc/settings
+++ b/tools/testing/selftests/rtc/settings
@@ -1 +1 @@
-timeout=210
+timeout=240
-- 
2.25.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ