Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mem: add mprotect tests #292

Merged
merged 1 commit into from
Feb 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Makefile.host
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
DEFAULT_COMPONENTS = $(filter test_meterfs_%,$(ALL_COMPONENTS))
DEFAULT_COMPONENTS += $(SAMPLE_TESTS)
DEFAULT_COMPONENTS += $(LIBC_UNIT_TESTS)
DEFAULT_COMPONENTS += test-mprotect
17 changes: 16 additions & 1 deletion mem/Makefile
Original file line number Diff line number Diff line change
@@ -1,10 +1,25 @@
#
# Makefile for libphoenix tests
# Makefile for mem tests
#
# Copyright 2019 Phoenix Systems
#
# %LICENSE%
#

# LEGACY
$(eval $(call add_test, test_mmap))
$(eval $(call add_test, test_malloc))

# UNITY

NAME := test-mprotect
LOCAL_SRCS := test_mprotect.c
DEP_LIBS := unity

include $(binary.mk)

NAME := test-mprotect-fault
LOCAL_SRCS := test_mprotect_fault.c
DEP_LIBS := unity

include $(binary.mk)
9 changes: 9 additions & 0 deletions mem/fault_harness.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from trunner.ctx import TestContext
from trunner.dut import Dut
from trunner.types import TestResult, Status


def harness(dut: Dut, ctx: TestContext, result: TestResult):
dut.expect("Exception", timeout=30)

return TestResult(status=Status.OK)
19 changes: 19 additions & 0 deletions mem/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
test:
tests:
- name: mprotect-fault
harness: fault_harness.py
execute: test-mprotect-fault
targets:
# mprotect: is noop on NOMMU architecture
exclude: [armv7m7-imxrt106x-evk, armv7m7-imxrt117x-evk, armv7m4-stm32l4x6-nucleo]

- name: mprotect
type: unity
execute: test-mprotect
# FIXME: this reboot is placed here as after mprotect-fault is run target need to be rebooter.
# Currently rebooting after the test is not implemented in the runner.
reboot: True
targets:
# mprotect: is noop on NOMMU architecture
exclude: [armv7m7-imxrt106x-evk, armv7m7-imxrt117x-evk, armv7m4-stm32l4x6-nucleo]

86 changes: 86 additions & 0 deletions mem/test_mprotect.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* Phoenix-RTOS
*
* phoenix-rtos-test
*
* mprotect syscall tests
*
* Copyright 2023 Phoenix Systems
* Author: Hubert Badocha
*
* This file is part of Phoenix-RTOS.
*
* %LICENSE%
*/

#include <sys/mman.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>

#include "unity_fixture.h"


#define PAGES 4


static long page_size;


TEST_GROUP(test_mprotect);


TEST_SETUP(test_mprotect)
{
page_size = sysconf(_SC_PAGESIZE);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could get it once - at the beginning of a test (for example in runner()), not before all test cases, or alternatively only within the test case body.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EDIT: I know that now we have only one test case, but when someone will add more of them it's easy to forget about it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moved to the body

}


TEST_TEAR_DOWN(test_mprotect)
{
}


TEST(test_mprotect, test_mprotect_singlecore)
{
unsigned char *area = mmap(NULL, page_size * PAGES, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it would be better to not set PROT_READ at the beginning to check whether read access protection has been set properly in the mprotect call.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't work then as we require that the protection required by the mrpotect has to be lesser or equal than the one established by mmap

TEST_ASSERT(area != MAP_FAILED);

for (int page = 0; page < PAGES; page++) {
area[page * page_size] = 0x42;
}

TEST_ASSERT_EQUAL(0, mprotect(area, page_size * PAGES, PROT_READ));

for (int page = 0; page < PAGES; page++) {
TEST_ASSERT_EQUAL(0x42, area[page * page_size]);
}

TEST_ASSERT_EQUAL(0, mprotect(area, page_size * PAGES, PROT_READ | PROT_WRITE));

for (int page = 0; page < PAGES; page++) {
area[(page * page_size) + 0x6] = 0x9;
TEST_ASSERT_EQUAL(0x9, area[(page * page_size) + 0x6]);
}

TEST_ASSERT_EQUAL(0, munmap(area, page_size * PAGES));
}

TEST_GROUP_RUNNER(test_mprotect)
{
RUN_TEST_CASE(test_mprotect, test_mprotect_singlecore);
}


static void runner(void)
{
RUN_TEST_GROUP(test_mprotect);
}


int main(int argc, char *argv[])
{
UnityMain(argc, (const char **)argv, runner);

return 0;
}
68 changes: 68 additions & 0 deletions mem/test_mprotect_fault.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Phoenix-RTOS
*
* phoenix-rtos-test
*
* mprotect syscall tests
*
* Copyright 2023 Phoenix Systems
* Author: Hubert Badocha
*
* This file is part of Phoenix-RTOS.
*
* %LICENSE%
*/

#include <sys/mman.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>

#include "unity_fixture.h"


TEST_GROUP(test_mprotect_fault);


TEST_SETUP(test_mprotect_fault)
{
}


TEST_TEAR_DOWN(test_mprotect_fault)
{
}


TEST(test_mprotect_fault, unit)
{
long pageSize = sysconf(_SC_PAGESIZE);
long totalSize = 4 * pageSize;
volatile unsigned char *area = mmap(NULL, totalSize, PROT_READ | PROT_WRITE, MAP_ANONYMOUS, -1, 0);
TEST_ASSERT(area != MAP_FAILED);

TEST_ASSERT_EQUAL(0, mprotect((void *)area, totalSize, PROT_READ));

area[0] = 0x42; /* Should generate fault. */
TEST_ASSERT_NOT_EQUAL(0x42, area[0]);
}


TEST_GROUP_RUNNER(test_mprotect_fault)
{
RUN_TEST_CASE(test_mprotect_fault, unit);
}


static void runner(void)
{
RUN_TEST_GROUP(test_mprotect_fault);
}


int main(int argc, char *argv[])
{
UnityMain(argc, (const char **)argv, runner);

return 0;
}
Loading