From: Deven Bowers <deven.de...@linux.microsoft.com>

Add various happy/unhappy unit tests for both IPE's parser.

Signed-off-by: Deven Bowers <deven.de...@linux.microsoft.com>
Signed-off-by: Fan Wu <wu...@linux.microsoft.com>

---
v1-v6:
  + Not present

v7:
  Introduced

v8:
  + Remove the kunit tests with respect to the fsverity digest, as these
    require significant changes to work with the new method of acquiring
    the digest at runtime.

v9:
  + Remove the kunit tests related to ipe_context
---
 security/ipe/Kconfig        |  17 +++
 security/ipe/Makefile       |   3 +
 security/ipe/policy_tests.c | 294 ++++++++++++++++++++++++++++++++++++
 3 files changed, 314 insertions(+)
 create mode 100644 security/ipe/policy_tests.c

diff --git a/security/ipe/Kconfig b/security/ipe/Kconfig
index 691fdb9ae60e..79e4fd677c19 100644
--- a/security/ipe/Kconfig
+++ b/security/ipe/Kconfig
@@ -55,4 +55,21 @@ config IPE_PROP_FS_VERITY
 
 endmenu
 
+config SECURITY_IPE_KUNIT_TEST
+       bool "Build KUnit tests for IPE" if !KUNIT_ALL_TESTS
+       depends on KUNIT=y
+       default KUNIT_ALL_TESTS
+       help
+         This builds the IPE KUnit tests.
+
+         KUnit tests run during boot and output the results to the debug log
+         in TAP format (https://testanything.org/). Only useful for kernel devs
+         running KUnit test harness and are not for inclusion into a
+         production build.
+
+         For more information on KUnit and unit tests in general please refer
+         to the KUnit documentation in Documentation/dev-tools/kunit/.
+
+         If unsure, say N.
+
 endif
diff --git a/security/ipe/Makefile b/security/ipe/Makefile
index e6d5176bc20b..285e0949db25 100644
--- a/security/ipe/Makefile
+++ b/security/ipe/Makefile
@@ -27,3 +27,6 @@ obj-$(CONFIG_SECURITY_IPE) += \
        audit.o \
 
 clean-files := boot-policy.c \
+
+obj-$(CONFIG_SECURITY_IPE_KUNIT_TEST) += \
+       policy_tests.o \
diff --git a/security/ipe/policy_tests.c b/security/ipe/policy_tests.c
new file mode 100644
index 000000000000..d09a1aca863d
--- /dev/null
+++ b/security/ipe/policy_tests.c
@@ -0,0 +1,294 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) Microsoft Corporation. All rights reserved.
+ */
+
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <kunit/test.h>
+#include "policy.h"
+struct policy_case {
+       const char *const policy;
+       int        errno;
+       const char *const desc;
+};
+
+static const struct policy_case policy_cases[] = {
+       {
+               "policy_name=allowall policy_version=0.0.0\n"
+               "DEFAULT action=ALLOW",
+               0,
+               "basic",
+       },
+       {
+               "policy_name=trailing_comment policy_version=152.0.0 #This is 
comment\n"
+               "DEFAULT action=ALLOW",
+               0,
+               "trailing comment",
+       },
+       {
+               "policy_name=allowallnewline policy_version=0.2.0\n"
+               "DEFAULT action=ALLOW\n"
+               "\n",
+               0,
+               "trailing newline",
+       },
+       {
+               "policy_name=carriagereturnlinefeed policy_version=0.0.1\n"
+               "DEFAULT action=ALLOW\n"
+               "\r\n",
+               0,
+               "clrf newline",
+       },
+       {
+               "policy_name=whitespace policy_version=0.0.0\n"
+               "DEFAULT\taction=ALLOW\n"
+               "     \t     DEFAULT \t    op=EXECUTE      action=DENY\n"
+               "op=EXECUTE boot_verified=TRUE action=ALLOW\n"
+               "# this is a\tcomment\t\t\t\t\n"
+               "DEFAULT \t op=KMODULE\t\t\t  action=DENY\r\n"
+               "op=KMODULE boot_verified=TRUE action=ALLOW\n",
+               0,
+               "various whitespaces and nested default",
+       },
+       {
+               "policy_name=boot_verified policy_version=-1236.0.0\n"
+               "DEFAULT\taction=ALLOW\n",
+               -EINVAL,
+               "negative version",
+       },
+       {
+               "policy_name=$@!*&^%%\\:;{}() policy_version=0.0.0\n"
+               "DEFAULT action=ALLOW",
+               0,
+               "special characters",
+       },
+       {
+               "policy_name=test policy_version=999999.0.0\n"
+               "DEFAULT action=ALLOW",
+               -ERANGE,
+               "overflow version",
+       },
+       {
+               "policy_name=test policy_version=255.0\n"
+               "DEFAULT action=ALLOW",
+               -EBADMSG,
+               "incomplete version",
+       },
+       {
+               "policy_name=test policy_version=111.0.0.0\n"
+               "DEFAULT action=ALLOW",
+               -EBADMSG,
+               "extra version",
+       },
+       {
+               "",
+               -EBADMSG,
+               "0-length policy",
+       },
+       {
+               "policy_name=test\0policy_version=0.0.0\n"
+               "DEFAULT action=ALLOW",
+               -EBADMSG,
+               "random null in header",
+       },
+       {
+               "policy_name=test policy_version=0.0.0\n"
+               "\0DEFAULT action=ALLOW",
+               -EBADMSG,
+               "incomplete policy from NULL",
+       },
+       {
+               "policy_name=test policy_version=0.0.0\n"
+               "DEFAULT action=DENY\n\0"
+               "op=EXECUTE dmverity_signature=TRUE action=ALLOW\n",
+               0,
+               "NULL truncates policy",
+       },
+       {
+               "policy_name=test policy_version=0.0.0\n"
+               "DEFAULT action=ALLOW\n"
+               "op=EXECUTE dmverity_signature=abc action=ALLOW",
+               -EBADMSG,
+               "invalid property type",
+       },
+       {
+               "DEFAULT action=ALLOW",
+               -EBADMSG,
+               "missing policy header",
+       },
+       {
+               "policy_name=test policy_version=0.0.0\n",
+               -EBADMSG,
+               "missing default definition",
+       },
+       {
+               "policy_name=test policy_version=0.0.0\n"
+               "DEFAULT action=ALLOW\n"
+               "dmverity_signature=TRUE op=EXECUTE action=ALLOW",
+               -EBADMSG,
+               "invalid rule ordering"
+       },
+       {
+               "policy_name=test policy_version=0.0.0\n"
+               "DEFAULT action=ALLOW\n"
+               "action=ALLOW op=EXECUTE dmverity_signature=TRUE",
+               -EBADMSG,
+               "invalid rule ordering (2)",
+       },
+       {
+               "policy_name=test policy_version=0.0\n"
+               "DEFAULT action=ALLOW\n"
+               "op=EXECUTE dmverity_signature=TRUE action=ALLOW",
+               -EBADMSG,
+               "invalid version",
+       },
+       {
+               "policy_name=test policy_version=0.0.0\n"
+               "DEFAULT action=ALLOW\n"
+               "op=UNKNOWN dmverity_signature=TRUE action=ALLOW",
+               -EBADMSG,
+               "unknown operation",
+       },
+       {
+               "policy_name=asdvpolicy_version=0.0.0\n"
+               "DEFAULT action=ALLOW\n",
+               -EBADMSG,
+               "missing space after policy name",
+       },
+       {
+               "policy_name=test\xFF\xEF policy_version=0.0.0\n"
+               "DEFAULT action=ALLOW\n"
+               "op=EXECUTE dmverity_signature=TRUE action=ALLOW",
+               0,
+               "expanded ascii",
+       },
+       {
+               "policy_name=test\xFF\xEF policy_version=0.0.0\n"
+               "DEFAULT action=ALLOW\n"
+               "op=EXECUTE dmverity_roothash=GOOD_DOG action=ALLOW",
+               -EBADMSG,
+               "invalid property value (2)",
+       },
+       {
+               "policy_name=test policy_version=0.0.0\n"
+               "policy_name=test policy_version=0.1.0\n"
+               "DEFAULT action=ALLOW",
+               -EBADMSG,
+               "double header"
+       },
+       {
+               "policy_name=test policy_version=0.0.0\n"
+               "DEFAULT action=ALLOW\n"
+               "DEFAULT action=ALLOW\n",
+               -EBADMSG,
+               "double default"
+       },
+       {
+               "policy_name=test policy_version=0.0.0\n"
+               "DEFAULT action=ALLOW\n"
+               "DEFAULT op=EXECUTE action=DENY\n"
+               "DEFAULT op=EXECUTE action=ALLOW\n",
+               -EBADMSG,
+               "double operation default"
+       },
+       {
+               "policy_name=test policy_version=0.0.0\n"
+               "DEFAULT action=ALLOW\n"
+               "DEFAULT op=EXECUTE action=DEN\n",
+               -EBADMSG,
+               "invalid action value"
+       },
+       {
+               "policy_name=test policy_version=0.0.0\n"
+               "DEFAULT action=ALLOW\n"
+               "DEFAULT op=EXECUTE action\n",
+               -EBADMSG,
+               "invalid action value (2)"
+       },
+       {
+               "policy_name=test policy_version=0.0.0\n"
+               "DEFAULT action=ALLOW\n"
+               "UNKNOWN value=true\n",
+               -EBADMSG,
+               "unrecognized statement"
+       },
+       {
+               "policy_name=test policy_version=0.0.0\n"
+               "DEFAULT action=ALLOW\n"
+               "op=EXECUTE 
dmverity_roothash=1c0d7ee1f8343b7fbe418378e8eb22c061d7dec7 action=DENY\n",
+               -EBADMSG,
+               "old-style digest"
+       },
+       {
+               "policy_name=test policy_version=0.0.0\n"
+               "DEFAULT action=ALLOW\n"
+               "op=EXECUTE 
fsverity_digest=1c0d7ee1f8343b7fbe418378e8eb22c061d7dec7 action=DENY\n",
+               -EBADMSG,
+               "old-style digest"
+       }
+};
+
+static void pol_to_desc(const struct policy_case *c, char *desc)
+{
+       strncpy(desc, c->desc, KUNIT_PARAM_DESC_SIZE);
+}
+
+KUNIT_ARRAY_PARAM(ipe_policies, policy_cases, pol_to_desc);
+
+/**
+ * ipe_parser_unsigned_test - Test the paser by passing unsigned policies.
+ * @test: Supplies a pointer to a kunit structure.
+ *
+ * This is called by the kunit harness. This test does not check the 
correctness
+ * of the policy, but ensures that errors are handled correctly.
+ */
+static void ipe_parser_unsigned_test(struct kunit *test)
+{
+       const struct policy_case *p = test->param_value;
+       struct ipe_policy *pol = ipe_new_policy(p->policy, strlen(p->policy), 
NULL, 0);
+
+       if (p->errno) {
+               KUNIT_EXPECT_EQ(test, PTR_ERR(pol), p->errno);
+               return;
+       }
+
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pol);
+       KUNIT_EXPECT_NOT_ERR_OR_NULL(test, pol->parsed);
+       KUNIT_EXPECT_STREQ(test, pol->text, p->policy);
+       KUNIT_EXPECT_PTR_EQ(test, NULL, pol->pkcs7);
+       KUNIT_EXPECT_EQ(test, 0, pol->pkcs7len);
+
+       ipe_free_policy(pol);
+}
+
+/**
+ * ipe_parser_widestring_test - Ensure parser fail on a wide string policy.
+ * @test: Supplies a pointer to a kunit structure.
+ *
+ * This is called by the kunit harness.
+ */
+static void ipe_parser_widestring_test(struct kunit *test)
+{
+       struct ipe_policy *pol = NULL;
+       const unsigned short policy[] = L"policy_name=Test 
policy_version=0.0.0\n"
+                                       L"DEFAULT action=ALLOW";
+
+       pol = ipe_new_policy((const char *)policy, (ARRAY_SIZE(policy) - 1) * 
2, NULL, 0);
+       KUNIT_EXPECT_TRUE(test, IS_ERR_OR_NULL(pol));
+
+       ipe_free_policy(pol);
+}
+
+static struct kunit_case ipe_parser_test_cases[] = {
+       KUNIT_CASE_PARAM(ipe_parser_unsigned_test, ipe_policies_gen_params),
+       KUNIT_CASE(ipe_parser_widestring_test),
+};
+
+static struct kunit_suite ipe_parser_test_suite = {
+       .name = "ipe-parser",
+       .test_cases = ipe_parser_test_cases,
+};
+
+kunit_test_suite(ipe_parser_test_suite);
-- 
2.39.0

--
dm-devel mailing list
dm-devel@redhat.com
https://listman.redhat.com/mailman/listinfo/dm-devel

Reply via email to