KasperskyOS Community Edition

Creating and performing tests for a KasperskyOS-based solution security policy

May 21, 2024

ID ssp_descr_psl_syntax_testing

A solution security policy is tested to verify whether or not the policy actually allows what should be allowed and denies what should be denied.

To create a set of tests for a solution security policy, use the following declaration:

assert ["name of test set"] {

// Constructs in PAL (Policy Assertion Language)

[setup {<initial part of tests>}]

sequence ["test name"] {<main part of test>}

[...]

[finally {<final part of tests>}]

}

You can create multiple sets of tests by using several of these declarations.

A set of tests can optionally include the initial part of the tests and/or the final part of the tests. The execution of each test from the set begins with whatever is described in the initial part of the test and ends with whatever is described in the final part of the test. This lets you describe the repeated initial and/or final parts of tests in each test.

After completing each test, all modifications in the Kaspersky Security Module related to the execution of this test are rolled back.

Each test includes one or more test cases.

Test cases

A test case associates a security event description and values of interface method parameters with an expected decision of the Kaspersky Security Module. If the actual security module decision matches the expected decision, the test case passes. Otherwise it fails.

When a test is run, the test cases are executed in the same sequence in which they are described. In other words, the test demonstrates how the security module handles a sequence of security events.

If all test cases within a test pass, the test passes. If even one test case fails to pass, the test fails. A test is terminated on the first failing test case. Each test from the set is run regardless of whether the previous test passed or failed.

A test case description in the PAL language is comprised of the following construct:

[<expected decision of security module> ["test case name"]] <security event type> <security event selectors> [{interface method parameter values}]

The expected decision of the security module can be indicated as grant ("granted"), deny ("denied") or any ("any decision"). You are not required to indicate the expected decision of the security module. The "granted" decision is expected by default. If the any value is specified, the security module decision does not have any influence on whether or not the test case passes. In this case, the test case may fail due to errors that occur when the security module processes an IPC message (for example, when the IPC message has an invalid structure).

The name of the test case can be specified if only the expected decision of the security module is specified.

For information about the types and selectors of security events, and about the limitations when using selectors, see Binding methods of security models to security events. Selectors must ensure that the security event description corresponds to IPC messages of the same type. (When security model methods are bound to security events, selectors may not ensure this.)

In security event descriptions, you need to specify the SID instead of the process class name (and the KasperskyOS kernel). However, this requirement does not apply to execute events for which the SID of the started process (or kernel) is unknown. To save the SID of the process or kernel to a variable, you need to use the <- operator in the test case description in the following format:

<variable name> <- execute dst=<kernel/process class name> ...

The SID value will be assigned to the variable even if startup of the process of the defined class (or kernel) is denied by the tested policy but the "denied" decision is expected.

The PAL language supports abbreviated forms of security event descriptions:

  • security: <Process SID> ! <qualified name of security interface method> corresponds to security src=<process SID> method=<qualified name of security interface method>.
  • request: <client SID> ~> <kernel/server SID> : <qualified name of endpoint.method name> corresponds to request src=<client SID> dst=<kernel/server SID> endpoint=<qualified name of endpoint> method=<method name>.
  • response: <client SID> <~ <kernel/server SID> : <qualified name of endpoint.method name> corresponds to response src=<kernel/server SID> dst=<client SID> endpoint=<qualified name of endpoint> method=<method name>.

The values of interface method parameters must be defined for all types of security events except execute. If the interface method has no parameters, specify {}. You cannot specify {} for security events of the execute type.

Interface method parameters and their values must be defined by comma-separated constructs that look as follows:

<parameter name> : <value>

The names and types of parameters must comply with the IDL description. The sequence order of parameters is not important.

Example definition of parameter values:

{ param1 : 23, param2 : "bar", param3 : { collection : [5,7,12], filehandle : 15 }, param4 : { name : ["foo", "baz" } }

In this example, the number is passed through the param1 parameter. The string buffer is passed through the param2 parameter. A structure consisting of two fields is passed through the param3 parameter. The collection field contains an array or sequence of three numeric elements. The filehandle field contains the SID. A union or structure containing one field is passed through the param4 parameter. The name field contains an array or sequence of two string buffers.

Currently, only an SID can be indicated as the value of a Handle parameter, and there is no capability to indicate the SID together with a handle permissions mask. For this reason, it is not possible to properly test a solution security policy when the permissions masks of handles influence the security module decisions.

The values of parameters (or elements of parameters) do not have to be specified. If they are not specified, the system automatically applies the default values corresponding to the IDL types of parameters (and elements of parameters):

  • The default values for numerical types and the Handle type are zero.
  • A zero-sized byte- or string buffer is the default value for byte- or string buffers.
  • The default value for sequences is a sequence with zero elements.
  • The default value for arrays is an array of elements with the default values.
  • The default value for structures is a structure consisting of fields with the default values.
  • For unions, the default value of the first member of the union is applied by default.

Example of applying the default value for a parameter and parameter element:

/* Parameter is specified. */

request src=x dst=y endpoint=e method=m { name : { firstname: "a", lastname: "b" } }

/* Parameter is not specified. The applied value of the name parameter will be a structure

* consisting of two zero-sized string buffers.*/

request src=x dst=y endpoint=e method=m {}

/* Parameter element is not specified. The applied value of the lastname parameter element will be

* a zero-sized string buffer.*/

request src=x dst=y endpoint=e method=m { name : { firstname: "a"} }

Example tests

See "Examples of tests for KasperskyOS-based solution security policies".

Test procedure

The test procedure includes the following steps:

  1. Save the tests in one or multiple PSL files (*.psl or *.psl.in).
  2. Add the CMake command add_kss_pal_qemu_tests() to one of the CMakeLists.txt files of the project.

    Use the PSL_FILES parameter to define the paths to PSL files containing tests. Use the DEPENDS parameter to define the CMake targets whose execution will cause the PSL file-dependent IDL, CDL, and EDL files to be put into the directories where the nk-psl-gen-c compiler can find them. If *.psl.in files are utilized, use the ENTITIES parameter to define the names of process classes of system programs. (These system programs are included in a KasperskyOS-based solution that requires security policy testing.)

    Example use of the CMake command add_kss_pal_qemu_tests() in the file einit/CMakeLists.txt:

    add_kss_pal_qemu_tests (

    PSL_FILES src/security.psl.in

    DEPENDS kos-qemu-image

    ENTITIES ${ENTITIES})

  3. Build and run the tests.

    You must run the Bash build script cross-build.sh with the parameter --target pal-test<N> (N is the index of the PSL file in the list of PSL files defined through the PSL_FILES parameter of the CMake command add_kss_pal_qemu_tests() at step 2. For example, --target pal-test0 will create a KasperskyOS-based solution image corresponding to the first PSL file defined through the PSL_FILES parameter of the CMake command add_kss_pal_qemu_tests() and then run that image in QEMU. (Instead of applications and system programs, this solution will contain the program that runs tests.)

    Example:

    ./cross-build.sh --target pal-test0

Example test results:

[==========] Running 4 tests from 1 test suite.

[----------] Global test environment set-up.

[----------] 4 tests from KSS

[ RUN ] KSS.KssUnitTest_flow_normal

[ OK ] KSS.KssUnitTest_flow_normal (6 ms)

[ RUN ] KSS.KssUnitTest_flow_ping_must_be_first

/home/work/build/stat/build/install/examples/ping/build/einit/

pal-test/gen_security.psl.test.c:9742: Failure

Expected equality of these values:

rc

Which is: -1

NK_EOK

Which is: 0

gen_security.psl:116: expect grant

[ FAILED ] KSS.KssUnitTest_flow_ping_must_be_first (8 ms)

[ RUN ] KSS.KssUnitTest_flow_ping_ping_is_deny

[ OK ] KSS.KssUnitTest_flow_ping_ping_is_deny (4 ms)

[ RUN ] KSS.KssUnitTest_flow_test_deny

[ OK ] KSS.KssUnitTest_flow_test_deny (1 ms)

[----------] 4 tests from KSS (29 ms total)

[----------] Global test environment tear-down

[==========] 4 tests from 1 test suite ran. (42 ms total)

[ PASSED ] 3 tests.

[ FAILED ] KSS.KssUnitTest_flow_ping_must_be_first (8 ms)

The test results contain information about whether or not each test passed or failed. If a test failed, information indicating the location of the description of the failed test example will be displayed in the PSL file.

Did you find this article helpful?
What can we do better?
Thank you for your feedback! You're helping us improve.
Thank you for your feedback! You're helping us improve.