-
Notifications
You must be signed in to change notification settings - Fork 6.8k
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
[RFC] samples: Add a self-protection test suite #493
Conversation
samples/prot_test/README.rst
Outdated
|
||
Overview | ||
******** | ||
This test provides a set of shell commands to test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your commit message asked whether this would be better placed in "tests" rather than "samples" -- I think it would be better in "tests" since this isn't really an example of how to do something useful.
samples/prot_test/README.rst
Outdated
* Execute from stack. | ||
* Execute from heap. | ||
|
||
Messages that begin with FAIL: are indicative of a lack of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@inakypg Should this be in a form that would make this test fit into the TCF infrastructure?
samples/prot_test/README.rst
Outdated
* Execute from stack. | ||
* Execute from heap. | ||
|
||
Messages that begin with FAIL: are indicative of a lack of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can/should there be a SUCCESS: message too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some questions
I also notice this test/sample samples/mpu_stack_guard_test/src/main.c that might have some overlap? |
Moved from samples/ to tests/. |
tests/kernel/protection/src/main.c
Outdated
*/ | ||
|
||
#include <zephyr.h> | ||
#include <tc_util.h> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tc_util is still being in use?
I thought ztest.h was superseding it. It's nicer and easier to use. Could you move towards that one instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I followed the example of tests/kernel/fatal. If ztest is preferred, I can move to it, but is it suitable for this kind of testing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rewrote it to use ztest.
@MaureenHelm @galak please review, these are the tests that detected the recent NXP MPU driver bug. |
tests/kernel/protection/src/main.c
Outdated
f, NULL, NULL, NULL, | ||
K_PRIO_COOP(PRIORITY), 0, | ||
K_NO_WAIT); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since ztest creates threads internally for each test, we could avoid the need to create this separate thread if ztest provided a ztest_test_pass() analogous to its ztest_test_fail() function, i.e. one that sets test_result = 0 and calls k_sem_give(&test_end_signal). Then we could call that from _SysFatalErrorHandler() upon the MPU fault. Otherwise, we end up hanging on the k_sem_take(&test_end_signal, K_FOREVER) cal in run_test(). If desired, I could add that and include it as part of this commit.
Revised to add a ztest_test_pass() interface to ztest, and then rewrote protection tests to use it. |
ztest provides a ztest_test_fail() interface to fail the currently running test, but does not provide an equivalent ztest_test_pass(). Normally a test passes just by returning without an assertion failure or other call to ztest_test_fail(). However, if the correct behavior for a test is to trigger a fatal fault (as with tests/kernel/fatal or protection or MPU tests), then we need a way for the test to pass the currently running test before aborting the current thread. Otherwise, ztest hangs forever in run_test() on the k_sem_take(&test_end_signal, K_FOREVER) call. Add a ztest_test_pass() interface and implement it for kernel and userspace variants of ztest. This interface will be used in the protection tests. Signed-off-by: Stephen Smalley <[email protected]>
tests/kernel/protection/README.rst
Outdated
@@ -0,0 +1,84 @@ | |||
.. protection |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
needs a trailing colon, and would be better as:
.. protection_tests:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
one little tweak, and LGTM
@stephensmalley As you correctly analyzed in your RFC description mpu_test and mpu_stack_guard_test are simple example meant to help the development and the integration of the MPU on various platforms and to test the basic functionalities hence are categorized as samples. What you are proposing here (and I am happy you are doing that 👍, because I had it in mind but due to a work change I am not able to work on Zephyr with continuity anymore...) is an extensible "high level" test suite that verifies the behavior of the MPU independently from the platform of choice. I agree with the choice of putting it in tests and modelling it following what it has been done in the fatal test. In the next few days I will look into the patch more in detail and if required I will provide more comments. |
Thank you very much! And thanks for the MPU driver implementation for Zephyr - it is definitely a big step forward for Zephyr security. |
@AdithyaBaglody This might be helpful for MMU support testing. |
Yes, we can definitely use this to test memory protection support on x86 or really any architecture that has an MMU or MPU. |
tests/kernel/protection/README.rst
Outdated
@@ -0,0 +1,84 @@ | |||
.. protection_tests: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I missed that it also needs a leading underscore: .. _protection_tests:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Is there an equivalent to checkpatch.pl checks for the .rst files?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry, one more little tweak to that first label I missed in my earlier comment
Add a self-protection test suite with a set of tests to check whether one can overwrite read-only data and text, and whether one can execute from data, stack, or heap buffers. These tests are modeled after a subset of the lkdtm tests in the Linux kernel. These tests have twice caught bugs in the Zephyr NXP MPU driver, once during initial testing/review of the code (in its earliest forms on gerrit, reported to the original author there) and most recently the regression introduced by commit bacbea6 ("arm: nxp: mpu: Rework handling of region descriptor 0"), which was fixed by commit a8aa9d4 ("arm: nxp: mpu: Fix region descriptor 0 attributes") after being reported. This is intended to be a testsuite of self-protection features rather than just a test of MPU functionality. It is envisioned that these tests will be expanded to cover a wider range of protection features beyond just memory protection, and the current tests are independent of any particular enforcement mechanism (e.g. MPU, MMU, or other). The tests are intended to be cross-platform, and have been built and run on both x86- and ARM-based boards. The tests currently fail on x86-based boards, but this is an accurate reflection of current protections and should change as MMU support arrives. The tests leverage the ztest framework, making them suitable for incorporation into automated regression testing for Zephyr. Signed-off-by: Stephen Smalley <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks!
Sadly, no. We don't have a checkpatch equivalent for .rst files. Generally .rst errors are caught by the doc generation process itself (and included in the test run). But there are some .rst errors that go unnoticed because, for example, directives (lines starting with ..
) with unknown names are treated as comments. I'll see what I can do.
@stephensmalley Agreed, this would help out with all memory protection testing. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If preferred, I could submit the ztest_test_pass() commit as a separate pull request (it is already a separate commit, but part of this pull request at the moment).
I don't see a need for a separate pull request as long as @inakypg +1's this one.
I said earlier that this test could be merged with mpu_test, but you make a good argument to keep separate given it can be used for other non-mpu protection mechanisms. The implementation LGTM. Thanks for contributing the test!
* Parts derived from tests/kernel/fatal/src/main.c, which has the | ||
* following copyright and license: | ||
* | ||
* Copyright (c) 2017 Intel Corporation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use your own copyright
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only relevant copyright is that of tests/kernel/fatal/src/main.c, from which I copied the _SysFatalErrorHandler() definition (and originally a few other bits, but those got replaced in converting to using ztest). No copyright for anything I wrote, since USG works are public domain by statute.
Right, but we do run those test on hardware using the same files, so that is all fine, at some point we need to look how to enable this type of tests in qemu as well. |
…ect-rtos#493) * [scripts] New script 'trlite' to run Travis tests locally With no args, runs all the tests. "trlite zephyr" runs just the VM zephyrproject-rtos#1 "zephyr" tests. "trlite linux" runs just the VM zephyrproject-rtos#2 "linux" tests. "trlite ashell" runs just the VM zephyrproject-rtos#3 "ashell" tests. You can also just pass the VM# instead (1, 2, or 3). Signed-off-by: Geoff Gustafson <[email protected]> * [trlite] Add -v flag for verbose output, change to off by default Signed-off-by: Geoff Gustafson <[email protected]>
Add a self-protection test suite with a set of options
to check whether one can overwrite read-only data
and text, and whether one can execute from data,
stack, or heap buffers. These tests are modeled after
a subset of the lkdtm tests in the Linux kernel.
On boards with MPU support, the disable_mpu and enable_mpu
commands allow one to enable and disable the MPU around other
commands, so that one can see how disabling the MPU affects the tests.
These tests are intentionally separate from mpu_test for the
following reasons:
This is intended to be a testsuite of self-protection features
rather than just a test of MPU functionality. It is envisioned that
these tests will be expanded to cover a wider range of protection
features beyond just memory protection, and the current tests
are independent of any particular enforcement mechanism (e.g.
they can just as easily be enforced by a MMU or other means).
The current tests also operate at a higher level of abstraction
than mpu_test, e.g. testing accessibility of rodata, text, stack,
heap, and data sections.
These tests are intended to be cross-platform. The tests have been
built and run on both x86-based and ARM-based boards. Obviously they
all fail on x86-based ones currently, but this is an accurate
reflection of current protections there and will hopefully change as
MMU support arrives. The mpu_test only builds on ARM-based boards and
embeds various architecture- and board-specific assumptions.
These tests provide clearly different results for success (bus fault
on NXP MPU, MPU fault with ARM MPU) versus failure (FAIL messages),
whereas the mpu_test tests generally fault regardless of success/fail,
only the nature of the fault changes (and sometimes even that is unchanged,
e.g. NXP MPU generates bus faults on read/write failures so you can't always
distinguish from a bus fault due to cause other than MPU).
That said, if the consensus is that these should be merged into
mpu_test, I can do that, but would appreciate guidance on how
much I should change mpu_test along the lines above.
My other open questions are as follows:
go somewhere else like tests/kernel?
mpu_test). Is that reasonable or should it be replaced/augmented with
a more automated test execution framework?
Signed-off-by: Stephen Smalley [email protected]