[PATCH v2 2/3] lockdown/kunit: Introduce kunit tests

Nikolay Borisov posted 3 patches 2 months, 1 week ago
[PATCH v2 2/3] lockdown/kunit: Introduce kunit tests
Posted by Nikolay Borisov 2 months, 1 week ago
Add a bunch of tests to ensure lockdown's conversion to bitmap hasn't
regressed it.

Signed-off-by: Nikolay Borisov <nik.borisov@suse.com>
---
 security/lockdown/Kconfig         |  5 +++
 security/lockdown/Makefile        |  1 +
 security/lockdown/lockdown.c      |  5 ++-
 security/lockdown/lockdown_test.c | 54 +++++++++++++++++++++++++++++++
 4 files changed, 64 insertions(+), 1 deletion(-)
 create mode 100644 security/lockdown/lockdown_test.c

diff --git a/security/lockdown/Kconfig b/security/lockdown/Kconfig
index e84ddf484010..5fb750da1f8c 100644
--- a/security/lockdown/Kconfig
+++ b/security/lockdown/Kconfig
@@ -6,6 +6,11 @@ config SECURITY_LOCKDOWN_LSM
 	  Build support for an LSM that enforces a coarse kernel lockdown
 	  behaviour.
 
+config SECURITY_LOCKDOWN_LSM_TEST
+	tristate "Test lockdown functionality" if !KUNIT_ALL_TESTS
+	depends on SECURITY_LOCKDOWN_LSM && KUNIT
+	default KUNIT_ALL_TESTS
+
 config SECURITY_LOCKDOWN_LSM_EARLY
 	bool "Enable lockdown LSM early in init"
 	depends on SECURITY_LOCKDOWN_LSM
diff --git a/security/lockdown/Makefile b/security/lockdown/Makefile
index e3634b9017e7..f35d90e39f1c 100644
--- a/security/lockdown/Makefile
+++ b/security/lockdown/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_SECURITY_LOCKDOWN_LSM) += lockdown.o
+obj-$(CONFIG_SECURITY_LOCKDOWN_LSM_TEST) += lockdown_test.o
diff --git a/security/lockdown/lockdown.c b/security/lockdown/lockdown.c
index 5014d18c423f..412184121279 100644
--- a/security/lockdown/lockdown.c
+++ b/security/lockdown/lockdown.c
@@ -25,7 +25,10 @@ static const enum lockdown_reason lockdown_levels[] = {LOCKDOWN_NONE,
 /*
  * Put the kernel into lock-down mode.
  */
-static int lock_kernel_down(const char *where, enum lockdown_reason level)
+#if !IS_ENABLED(CONFIG_KUNIT)
+static
+#endif
+int lock_kernel_down(const char *where, enum lockdown_reason level)
 {
 
 	if (level > LOCKDOWN_CONFIDENTIALITY_MAX)
diff --git a/security/lockdown/lockdown_test.c b/security/lockdown/lockdown_test.c
new file mode 100644
index 000000000000..3a3c6db5b470
--- /dev/null
+++ b/security/lockdown/lockdown_test.c
@@ -0,0 +1,54 @@
+#include <linux/security.h>
+#include <kunit/test.h>
+
+int lock_kernel_down(const char *where, enum lockdown_reason level);
+
+static void lockdown_test_invalid_level(struct kunit *test)
+{
+	KUNIT_EXPECT_EQ(test, -EINVAL, lock_kernel_down("TEST", LOCKDOWN_CONFIDENTIALITY_MAX+1));
+}
+
+static void lockdown_test_depth_locking(struct kunit *test)
+{
+	KUNIT_EXPECT_EQ(test, 0, lock_kernel_down("TEST", LOCKDOWN_INTEGRITY_MAX));
+	for (int i = 1; i < LOCKDOWN_INTEGRITY_MAX; i++)
+		KUNIT_EXPECT_EQ_MSG(test, -EPERM, security_locked_down(i), "at i=%d", i);
+
+	KUNIT_EXPECT_EQ(test, -EPERM, security_locked_down(LOCKDOWN_INTEGRITY_MAX));
+}
+
+static void lockdown_test_individual_level(struct kunit *test)
+{
+	KUNIT_EXPECT_EQ(test, 0, lock_kernel_down("TEST", LOCKDOWN_PERF));
+	KUNIT_EXPECT_EQ(test, -EPERM, security_locked_down(LOCKDOWN_PERF));
+	/* Ensure adjacent levels are untouched */
+	KUNIT_EXPECT_EQ(test, 0, security_locked_down(LOCKDOWN_TRACEFS));
+	KUNIT_EXPECT_EQ(test, 0, security_locked_down(LOCKDOWN_DBG_READ_KERNEL));
+}
+
+static void lockdown_test_no_downgrade(struct kunit *test)
+{
+	KUNIT_EXPECT_EQ(test, 0, lock_kernel_down("TEST", LOCKDOWN_CONFIDENTIALITY_MAX));
+	KUNIT_EXPECT_EQ(test, 0, lock_kernel_down("TEST", LOCKDOWN_INTEGRITY_MAX));
+	/*
+	 * Ensure having locked down to a lower leve after a higher level
+	 * lockdown nothing is lost
+	 */
+	KUNIT_EXPECT_EQ(test, -EPERM, security_locked_down(LOCKDOWN_TRACEFS));
+}
+
+static struct kunit_case lockdown_tests[] = {
+	KUNIT_CASE(lockdown_test_invalid_level),
+	KUNIT_CASE(lockdown_test_depth_locking),
+	KUNIT_CASE(lockdown_test_individual_level),
+	KUNIT_CASE(lockdown_test_no_downgrade),
+	{}
+};
+
+static struct kunit_suite lockdown_test_suite = {
+	.name = "lockdown test",
+	.test_cases = lockdown_tests,
+};
+kunit_test_suite(lockdown_test_suite);
+
+MODULE_LICENSE("GPL");
-- 
2.34.1
Re: [PATCH v2 2/3] lockdown/kunit: Introduce kunit tests
Posted by kernel test robot 2 months, 1 week ago
Hi Nikolay,

kernel test robot noticed the following build errors:

[auto build test ERROR on linus/master]
[also build test ERROR on v6.16 next-20250728]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Nikolay-Borisov/lockdown-Switch-implementation-to-using-bitmap/20250728-191807
base:   linus/master
patch link:    https://lore.kernel.org/r/20250728111517.134116-3-nik.borisov%40suse.com
patch subject: [PATCH v2 2/3] lockdown/kunit: Introduce kunit tests
config: i386-randconfig-004-20250729 (https://download.01.org/0day-ci/archive/20250729/202507291419.PQ4uKtRo-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14+deb12u1) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250729/202507291419.PQ4uKtRo-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202507291419.PQ4uKtRo-lkp@intel.com/

All errors (new ones prefixed by >>, old ones prefixed by <<):

WARNING: modpost: missing MODULE_DESCRIPTION() in security/lockdown/lockdown_test.o
>> ERROR: modpost: "lock_kernel_down" [security/lockdown/lockdown_test.ko] undefined!

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Re: [PATCH v2 2/3] lockdown/kunit: Introduce kunit tests
Posted by kernel test robot 2 months, 1 week ago
Hi Nikolay,

kernel test robot noticed the following build warnings:

[auto build test WARNING on linus/master]
[also build test WARNING on v6.16 next-20250728]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Nikolay-Borisov/lockdown-Switch-implementation-to-using-bitmap/20250728-191807
base:   linus/master
patch link:    https://lore.kernel.org/r/20250728111517.134116-3-nik.borisov%40suse.com
patch subject: [PATCH v2 2/3] lockdown/kunit: Introduce kunit tests
config: arm-randconfig-004-20250729 (https://download.01.org/0day-ci/archive/20250729/202507290540.9IANrMED-lkp@intel.com/config)
compiler: clang version 22.0.0git (https://github.com/llvm/llvm-project 1b4db78d2eaa070b3f364a2d2b2b826a5439b892)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250729/202507290540.9IANrMED-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202507290540.9IANrMED-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> security/lockdown/lockdown.c:31:5: warning: no previous prototype for function 'lock_kernel_down' [-Wmissing-prototypes]
      31 | int lock_kernel_down(const char *where, enum lockdown_reason level)
         |     ^
   security/lockdown/lockdown.c:31:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
      31 | int lock_kernel_down(const char *where, enum lockdown_reason level)
         | ^
         | static 
   1 warning generated.


vim +/lock_kernel_down +31 security/lockdown/lockdown.c

    20	
    21	static const enum lockdown_reason lockdown_levels[] = {LOCKDOWN_NONE,
    22							 LOCKDOWN_INTEGRITY_MAX,
    23							 LOCKDOWN_CONFIDENTIALITY_MAX};
    24	
    25	/*
    26	 * Put the kernel into lock-down mode.
    27	 */
    28	#if !IS_ENABLED(CONFIG_KUNIT)
    29	static
    30	#endif
  > 31	int lock_kernel_down(const char *where, enum lockdown_reason level)
    32	{
    33	
    34		if (level > LOCKDOWN_CONFIDENTIALITY_MAX)
    35			return -EINVAL;
    36	
    37		if (level == LOCKDOWN_INTEGRITY_MAX || level == LOCKDOWN_CONFIDENTIALITY_MAX)
    38			bitmap_set(kernel_locked_down, 1, level);
    39		else
    40			bitmap_set(kernel_locked_down, level, 1);
    41	
    42		pr_notice("Kernel is locked down from %s; see man kernel_lockdown.7\n",
    43			  where);
    44		return 0;
    45	}
    46	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Re: [PATCH v2 2/3] lockdown/kunit: Introduce kunit tests
Posted by Nikolay Borisov 2 months, 1 week ago

On 29.07.25 г. 1:04 ч., kernel test robot wrote:
> Hi Nikolay,
> 
> kernel test robot noticed the following build warnings:
> 
> [auto build test WARNING on linus/master]
> [also build test WARNING on v6.16 next-20250728]
> [If your patch is applied to the wrong git tree, kindly drop us a note.
> And when submitting patch, we suggest to use '--base' as documented in
> https://git-scm.com/docs/git-format-patch#_base_tree_information]
> 
> url:    https://github.com/intel-lab-lkp/linux/commits/Nikolay-Borisov/lockdown-Switch-implementation-to-using-bitmap/20250728-191807
> base:   linus/master
> patch link:    https://lore.kernel.org/r/20250728111517.134116-3-nik.borisov%40suse.com
> patch subject: [PATCH v2 2/3] lockdown/kunit: Introduce kunit tests
> config: arm-randconfig-004-20250729 (https://download.01.org/0day-ci/archive/20250729/202507290540.9IANrMED-lkp@intel.com/config)
> compiler: clang version 22.0.0git (https://github.com/llvm/llvm-project 1b4db78d2eaa070b3f364a2d2b2b826a5439b892)
> reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250729/202507290540.9IANrMED-lkp@intel.com/reproduce)
> 
> If you fix the issue in a separate patch/commit (i.e. not just a new version of
> the same patch/commit), kindly add following tags
> | Reported-by: kernel test robot <lkp@intel.com>
> | Closes: https://lore.kernel.org/oe-kbuild-all/202507290540.9IANrMED-lkp@intel.com/
> 
> All warnings (new ones prefixed by >>):
> 
>>> security/lockdown/lockdown.c:31:5: warning: no previous prototype for function 'lock_kernel_down' [-Wmissing-prototypes]
>        31 | int lock_kernel_down(const char *where, enum lockdown_reason level)
>           |     ^
>     security/lockdown/lockdown.c:31:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
>        31 | int lock_kernel_down(const char *where, enum lockdown_reason level)
>           | ^
>           | static
>     1 warning generated.


That's a false positive, since the function is exported only for KUNIT 
case, what's the correct way to make testbot ignore it ?
> 
> 
> vim +/lock_kernel_down +31 security/lockdown/lockdown.c
> 
>      20	
>      21	static const enum lockdown_reason lockdown_levels[] = {LOCKDOWN_NONE,
>      22							 LOCKDOWN_INTEGRITY_MAX,
>      23							 LOCKDOWN_CONFIDENTIALITY_MAX};
>      24	
>      25	/*
>      26	 * Put the kernel into lock-down mode.
>      27	 */
>      28	#if !IS_ENABLED(CONFIG_KUNIT)
>      29	static
>      30	#endif
>    > 31	int lock_kernel_down(const char *where, enum lockdown_reason level)
>      32	{
>      33	
>      34		if (level > LOCKDOWN_CONFIDENTIALITY_MAX)
>      35			return -EINVAL;
>      36	
>      37		if (level == LOCKDOWN_INTEGRITY_MAX || level == LOCKDOWN_CONFIDENTIALITY_MAX)
>      38			bitmap_set(kernel_locked_down, 1, level);
>      39		else
>      40			bitmap_set(kernel_locked_down, level, 1);
>      41	
>      42		pr_notice("Kernel is locked down from %s; see man kernel_lockdown.7\n",
>      43			  where);
>      44		return 0;
>      45	}
>      46	
> 
Re: [PATCH v2 2/3] lockdown/kunit: Introduce kunit tests
Posted by Philip Li 2 months, 1 week ago
On Tue, Jul 29, 2025 at 10:46:48AM +0300, Nikolay Borisov wrote:
> 
> 
> On 29.07.25 г. 1:04 ч., kernel test robot wrote:
> > Hi Nikolay,
> > 
> > kernel test robot noticed the following build warnings:
> > 
> > [auto build test WARNING on linus/master]
> > [also build test WARNING on v6.16 next-20250728]
> > [If your patch is applied to the wrong git tree, kindly drop us a note.
> > And when submitting patch, we suggest to use '--base' as documented in
> > https://git-scm.com/docs/git-format-patch#_base_tree_information]
> > 
> > url:    https://github.com/intel-lab-lkp/linux/commits/Nikolay-Borisov/lockdown-Switch-implementation-to-using-bitmap/20250728-191807
> > base:   linus/master
> > patch link:    https://lore.kernel.org/r/20250728111517.134116-3-nik.borisov%40suse.com
> > patch subject: [PATCH v2 2/3] lockdown/kunit: Introduce kunit tests
> > config: arm-randconfig-004-20250729 (https://download.01.org/0day-ci/archive/20250729/202507290540.9IANrMED-lkp@intel.com/config)
> > compiler: clang version 22.0.0git (https://github.com/llvm/llvm-project 1b4db78d2eaa070b3f364a2d2b2b826a5439b892)
> > reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250729/202507290540.9IANrMED-lkp@intel.com/reproduce)
> > 
> > If you fix the issue in a separate patch/commit (i.e. not just a new version of
> > the same patch/commit), kindly add following tags
> > | Reported-by: kernel test robot <lkp@intel.com>
> > | Closes: https://lore.kernel.org/oe-kbuild-all/202507290540.9IANrMED-lkp@intel.com/
> > 
> > All warnings (new ones prefixed by >>):
> > 
> > > > security/lockdown/lockdown.c:31:5: warning: no previous prototype for function 'lock_kernel_down' [-Wmissing-prototypes]
> >        31 | int lock_kernel_down(const char *where, enum lockdown_reason level)
> >           |     ^
> >     security/lockdown/lockdown.c:31:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
> >        31 | int lock_kernel_down(const char *where, enum lockdown_reason level)
> >           | ^
> >           | static
> >     1 warning generated.
> 
> 
> That's a false positive, since the function is exported only for KUNIT case,
> what's the correct way to make testbot ignore it ?

thanks for the info, i will configure the bot to ignore this firstly, and
later to check whether there's any pattern for more general ignore. Sorry
for the noise.

> > 
> > 
> > vim +/lock_kernel_down +31 security/lockdown/lockdown.c
> > 
> >      20	
> >      21	static const enum lockdown_reason lockdown_levels[] = {LOCKDOWN_NONE,
> >      22							 LOCKDOWN_INTEGRITY_MAX,
> >      23							 LOCKDOWN_CONFIDENTIALITY_MAX};
> >      24	
> >      25	/*
> >      26	 * Put the kernel into lock-down mode.
> >      27	 */
> >      28	#if !IS_ENABLED(CONFIG_KUNIT)
> >      29	static
> >      30	#endif
> >    > 31	int lock_kernel_down(const char *where, enum lockdown_reason level)
> >      32	{
> >      33	
> >      34		if (level > LOCKDOWN_CONFIDENTIALITY_MAX)
> >      35			return -EINVAL;
> >      36	
> >      37		if (level == LOCKDOWN_INTEGRITY_MAX || level == LOCKDOWN_CONFIDENTIALITY_MAX)
> >      38			bitmap_set(kernel_locked_down, 1, level);
> >      39		else
> >      40			bitmap_set(kernel_locked_down, level, 1);
> >      41	
> >      42		pr_notice("Kernel is locked down from %s; see man kernel_lockdown.7\n",
> >      43			  where);
> >      44		return 0;
> >      45	}
> >      46	
> > 
> 
Re: [PATCH v2 2/3] lockdown/kunit: Introduce kunit tests
Posted by Serge E. Hallyn 2 months, 1 week ago
On Mon, Jul 28, 2025 at 02:15:16PM +0300, Nikolay Borisov wrote:
> Add a bunch of tests to ensure lockdown's conversion to bitmap hasn't
> regressed it.
> 
> Signed-off-by: Nikolay Borisov <nik.borisov@suse.com>

Reviewed-by: Serge Hallyn <serge@hallyn.com>

(And I see this answers my question to patch 1, but still a comment
there would be nice :)

thanks,
-serge

> ---
>  security/lockdown/Kconfig         |  5 +++
>  security/lockdown/Makefile        |  1 +
>  security/lockdown/lockdown.c      |  5 ++-
>  security/lockdown/lockdown_test.c | 54 +++++++++++++++++++++++++++++++
>  4 files changed, 64 insertions(+), 1 deletion(-)
>  create mode 100644 security/lockdown/lockdown_test.c
> 
> diff --git a/security/lockdown/Kconfig b/security/lockdown/Kconfig
> index e84ddf484010..5fb750da1f8c 100644
> --- a/security/lockdown/Kconfig
> +++ b/security/lockdown/Kconfig
> @@ -6,6 +6,11 @@ config SECURITY_LOCKDOWN_LSM
>  	  Build support for an LSM that enforces a coarse kernel lockdown
>  	  behaviour.
>  
> +config SECURITY_LOCKDOWN_LSM_TEST
> +	tristate "Test lockdown functionality" if !KUNIT_ALL_TESTS
> +	depends on SECURITY_LOCKDOWN_LSM && KUNIT
> +	default KUNIT_ALL_TESTS
> +
>  config SECURITY_LOCKDOWN_LSM_EARLY
>  	bool "Enable lockdown LSM early in init"
>  	depends on SECURITY_LOCKDOWN_LSM
> diff --git a/security/lockdown/Makefile b/security/lockdown/Makefile
> index e3634b9017e7..f35d90e39f1c 100644
> --- a/security/lockdown/Makefile
> +++ b/security/lockdown/Makefile
> @@ -1 +1,2 @@
>  obj-$(CONFIG_SECURITY_LOCKDOWN_LSM) += lockdown.o
> +obj-$(CONFIG_SECURITY_LOCKDOWN_LSM_TEST) += lockdown_test.o
> diff --git a/security/lockdown/lockdown.c b/security/lockdown/lockdown.c
> index 5014d18c423f..412184121279 100644
> --- a/security/lockdown/lockdown.c
> +++ b/security/lockdown/lockdown.c
> @@ -25,7 +25,10 @@ static const enum lockdown_reason lockdown_levels[] = {LOCKDOWN_NONE,
>  /*
>   * Put the kernel into lock-down mode.
>   */
> -static int lock_kernel_down(const char *where, enum lockdown_reason level)
> +#if !IS_ENABLED(CONFIG_KUNIT)
> +static
> +#endif
> +int lock_kernel_down(const char *where, enum lockdown_reason level)
>  {
>  
>  	if (level > LOCKDOWN_CONFIDENTIALITY_MAX)
> diff --git a/security/lockdown/lockdown_test.c b/security/lockdown/lockdown_test.c
> new file mode 100644
> index 000000000000..3a3c6db5b470
> --- /dev/null
> +++ b/security/lockdown/lockdown_test.c
> @@ -0,0 +1,54 @@
> +#include <linux/security.h>
> +#include <kunit/test.h>
> +
> +int lock_kernel_down(const char *where, enum lockdown_reason level);
> +
> +static void lockdown_test_invalid_level(struct kunit *test)
> +{
> +	KUNIT_EXPECT_EQ(test, -EINVAL, lock_kernel_down("TEST", LOCKDOWN_CONFIDENTIALITY_MAX+1));
> +}
> +
> +static void lockdown_test_depth_locking(struct kunit *test)
> +{
> +	KUNIT_EXPECT_EQ(test, 0, lock_kernel_down("TEST", LOCKDOWN_INTEGRITY_MAX));
> +	for (int i = 1; i < LOCKDOWN_INTEGRITY_MAX; i++)
> +		KUNIT_EXPECT_EQ_MSG(test, -EPERM, security_locked_down(i), "at i=%d", i);
> +
> +	KUNIT_EXPECT_EQ(test, -EPERM, security_locked_down(LOCKDOWN_INTEGRITY_MAX));
> +}
> +
> +static void lockdown_test_individual_level(struct kunit *test)
> +{
> +	KUNIT_EXPECT_EQ(test, 0, lock_kernel_down("TEST", LOCKDOWN_PERF));
> +	KUNIT_EXPECT_EQ(test, -EPERM, security_locked_down(LOCKDOWN_PERF));
> +	/* Ensure adjacent levels are untouched */
> +	KUNIT_EXPECT_EQ(test, 0, security_locked_down(LOCKDOWN_TRACEFS));
> +	KUNIT_EXPECT_EQ(test, 0, security_locked_down(LOCKDOWN_DBG_READ_KERNEL));
> +}
> +
> +static void lockdown_test_no_downgrade(struct kunit *test)
> +{
> +	KUNIT_EXPECT_EQ(test, 0, lock_kernel_down("TEST", LOCKDOWN_CONFIDENTIALITY_MAX));
> +	KUNIT_EXPECT_EQ(test, 0, lock_kernel_down("TEST", LOCKDOWN_INTEGRITY_MAX));
> +	/*
> +	 * Ensure having locked down to a lower leve after a higher level
> +	 * lockdown nothing is lost
> +	 */
> +	KUNIT_EXPECT_EQ(test, -EPERM, security_locked_down(LOCKDOWN_TRACEFS));
> +}
> +
> +static struct kunit_case lockdown_tests[] = {
> +	KUNIT_CASE(lockdown_test_invalid_level),
> +	KUNIT_CASE(lockdown_test_depth_locking),
> +	KUNIT_CASE(lockdown_test_individual_level),
> +	KUNIT_CASE(lockdown_test_no_downgrade),
> +	{}
> +};
> +
> +static struct kunit_suite lockdown_test_suite = {
> +	.name = "lockdown test",
> +	.test_cases = lockdown_tests,
> +};
> +kunit_test_suite(lockdown_test_suite);
> +
> +MODULE_LICENSE("GPL");
> -- 
> 2.34.1
>