[RFC PATCH v2 19/29] selftests: ntsync: Add some tests for NTSYNC_IOC_WAIT_ANY.

Elizabeth Figura posted 29 patches 1 year, 10 months ago
There is a newer version of this series
[RFC PATCH v2 19/29] selftests: ntsync: Add some tests for NTSYNC_IOC_WAIT_ANY.
Posted by Elizabeth Figura 1 year, 10 months ago
Test basic synchronous functionality of NTSYNC_IOC_WAIT_ANY, when objects are
considered signaled or not signaled, and how they are affected by a successful
wait.

Signed-off-by: Elizabeth Figura <zfigura@codeweavers.com>
---
 .../testing/selftests/drivers/ntsync/ntsync.c | 105 ++++++++++++++++++
 1 file changed, 105 insertions(+)

diff --git a/tools/testing/selftests/drivers/ntsync/ntsync.c b/tools/testing/selftests/drivers/ntsync/ntsync.c
index 80c8bd409d68..13e7c9d7441e 100644
--- a/tools/testing/selftests/drivers/ntsync/ntsync.c
+++ b/tools/testing/selftests/drivers/ntsync/ntsync.c
@@ -321,4 +321,109 @@ TEST(mutex_state)
 	close(fd);
 }
 
+TEST(test_wait_any)
+{
+	struct ntsync_mutex_args mutex_args = {0};
+	struct ntsync_wait_args wait_args = {0};
+	struct ntsync_sem_args sem_args = {0};
+	__u32 owner, index, count;
+	struct timespec timeout;
+	int objs[2], fd, ret;
+
+	clock_gettime(CLOCK_MONOTONIC, &timeout);
+
+	fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY);
+	ASSERT_LE(0, fd);
+
+	sem_args.count = 2;
+	sem_args.max = 3;
+	sem_args.sem = 0xdeadbeef;
+	ret = ioctl(fd, NTSYNC_IOC_CREATE_SEM, &sem_args);
+	EXPECT_EQ(0, ret);
+	EXPECT_NE(0xdeadbeef, sem_args.sem);
+
+	mutex_args.owner = 0;
+	mutex_args.count = 0;
+	mutex_args.mutex = 0xdeadbeef;
+	ret = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args);
+	EXPECT_EQ(0, ret);
+	EXPECT_NE(0xdeadbeef, mutex_args.mutex);
+
+	objs[0] = sem_args.sem;
+	objs[1] = mutex_args.mutex;
+
+	ret = wait_any(fd, 2, objs, 123, &index);
+	EXPECT_EQ(0, ret);
+	EXPECT_EQ(0, index);
+	check_sem_state(sem_args.sem, 1, 3);
+	check_mutex_state(mutex_args.mutex, 0, 0);
+
+	ret = wait_any(fd, 2, objs, 123, &index);
+	EXPECT_EQ(0, ret);
+	EXPECT_EQ(0, index);
+	check_sem_state(sem_args.sem, 0, 3);
+	check_mutex_state(mutex_args.mutex, 0, 0);
+
+	ret = wait_any(fd, 2, objs, 123, &index);
+	EXPECT_EQ(0, ret);
+	EXPECT_EQ(1, index);
+	check_sem_state(sem_args.sem, 0, 3);
+	check_mutex_state(mutex_args.mutex, 1, 123);
+
+	count = 1;
+	ret = post_sem(sem_args.sem, &count);
+	EXPECT_EQ(0, ret);
+	EXPECT_EQ(0, count);
+
+	ret = wait_any(fd, 2, objs, 123, &index);
+	EXPECT_EQ(0, ret);
+	EXPECT_EQ(0, index);
+	check_sem_state(sem_args.sem, 0, 3);
+	check_mutex_state(mutex_args.mutex, 1, 123);
+
+	ret = wait_any(fd, 2, objs, 123, &index);
+	EXPECT_EQ(0, ret);
+	EXPECT_EQ(1, index);
+	check_sem_state(sem_args.sem, 0, 3);
+	check_mutex_state(mutex_args.mutex, 2, 123);
+
+	ret = wait_any(fd, 2, objs, 456, &index);
+	EXPECT_EQ(-1, ret);
+	EXPECT_EQ(ETIMEDOUT, errno);
+
+	owner = 123;
+	ret = ioctl(mutex_args.mutex, NTSYNC_IOC_MUTEX_KILL, &owner);
+	EXPECT_EQ(0, ret);
+
+	ret = wait_any(fd, 2, objs, 456, &index);
+	EXPECT_EQ(-1, ret);
+	EXPECT_EQ(EOWNERDEAD, errno);
+	EXPECT_EQ(1, index);
+
+	ret = wait_any(fd, 2, objs, 456, &index);
+	EXPECT_EQ(0, ret);
+	EXPECT_EQ(1, index);
+
+	/* test waiting on the same object twice */
+	count = 2;
+	ret = post_sem(sem_args.sem, &count);
+	EXPECT_EQ(0, ret);
+	EXPECT_EQ(0, count);
+
+	objs[0] = objs[1] = sem_args.sem;
+	ret = wait_any(fd, 2, objs, 456, &index);
+	EXPECT_EQ(0, ret);
+	EXPECT_EQ(0, wait_args.index);
+	check_sem_state(sem_args.sem, 1, 3);
+
+	ret = wait_any(fd, 0, NULL, 456, &index);
+	EXPECT_EQ(-1, ret);
+	EXPECT_EQ(ETIMEDOUT, errno);
+
+	close(sem_args.sem);
+	close(mutex_args.mutex);
+
+	close(fd);
+}
+
 TEST_HARNESS_MAIN
-- 
2.43.0
Re: [RFC PATCH v2 19/29] selftests: ntsync: Add some tests for NTSYNC_IOC_WAIT_ANY.
Posted by Andi Kleen 1 year, 10 months ago
Elizabeth Figura <zfigura@codeweavers.com> writes:

> +TEST(test_wait_any)
> +{
> +	struct ntsync_mutex_args mutex_args = {0};
> +	struct ntsync_wait_args wait_args = {0};
> +	struct ntsync_sem_args sem_args = {0};
> +	__u32 owner, index, count;
> +	struct timespec timeout;
> +	int objs[2], fd, ret;
> +
> +	clock_gettime(CLOCK_MONOTONIC, &timeout);
> +
> +	fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY);
> +	ASSERT_LE(0, fd);
> +
> +	sem_args.count = 2;
> +	sem_args.max = 3;
> +	sem_args.sem = 0xdeadbeef;
> +	ret = ioctl(fd, NTSYNC_IOC_CREATE_SEM, &sem_args);
> +	EXPECT_EQ(0, ret);
> +	EXPECT_NE(0xdeadbeef, sem_args.sem);
> +
> +	mutex_args.owner = 0;
> +	mutex_args.count = 0;
> +	mutex_args.mutex = 0xdeadbeef;
> +	ret = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args);
> +	EXPECT_EQ(0, ret);
> +	EXPECT_NE(0xdeadbeef, mutex_args.mutex);

It seems your tests are missing test cases for exceeding any limits,
especially overflow/underflow cases. Since these are the most likely
for any security problems it would be good to have extra coverage here.
The fuzzers will hopefully hit it too.

Also some stress testing with multiple threads would be useful.

-Andi
Re: [RFC PATCH v2 19/29] selftests: ntsync: Add some tests for NTSYNC_IOC_WAIT_ANY.
Posted by Elizabeth Figura 1 year, 10 months ago
On Wednesday, 31 January 2024 02:52:11 CST Andi Kleen wrote:
> Elizabeth Figura <zfigura@codeweavers.com> writes:
> 
> > +TEST(test_wait_any)
> > +{
> > +	struct ntsync_mutex_args mutex_args = {0};
> > +	struct ntsync_wait_args wait_args = {0};
> > +	struct ntsync_sem_args sem_args = {0};
> > +	__u32 owner, index, count;
> > +	struct timespec timeout;
> > +	int objs[2], fd, ret;
> > +
> > +	clock_gettime(CLOCK_MONOTONIC, &timeout);
> > +
> > +	fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY);
> > +	ASSERT_LE(0, fd);
> > +
> > +	sem_args.count = 2;
> > +	sem_args.max = 3;
> > +	sem_args.sem = 0xdeadbeef;
> > +	ret = ioctl(fd, NTSYNC_IOC_CREATE_SEM, &sem_args);
> > +	EXPECT_EQ(0, ret);
> > +	EXPECT_NE(0xdeadbeef, sem_args.sem);
> > +
> > +	mutex_args.owner = 0;
> > +	mutex_args.count = 0;
> > +	mutex_args.mutex = 0xdeadbeef;
> > +	ret = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args);
> > +	EXPECT_EQ(0, ret);
> > +	EXPECT_NE(0xdeadbeef, mutex_args.mutex);
> 
> It seems your tests are missing test cases for exceeding any limits,
> especially overflow/underflow cases. Since these are the most likely
> for any security problems it would be good to have extra coverage here.
> The fuzzers will hopefully hit it too.
> 
> Also some stress testing with multiple threads would be useful.

Thanks, I'll add these.