[PATCH 1/3] security: add Lilium - Linux Integrity Lock-In User Module
ℰ𝓃𝓏ℴ ℱ𝓊𝓀ℯ
milesonerd at outlook.com
Sun Jun 1 01:04:02 UTC 2025
From f34a53c7e615fb6e60b21bdcb5b1979edaf52088 Mon Sep 17 00:00:00 2001
From: Enzo Fuke <milesonerd at outlook.com>
Date: Sun, 1 Jun 2025 00:26:43 +0000
Subject: [PATCH] Lilium LSM
---
security/lilium/Kconfig | 82 ++++++
security/lilium/Makefile | 10 +
security/lilium/lilium_config.h | 24 ++
security/lilium/lilium_lsm.c | 468 ++++++++++++++++++++++++++++++++
security/lilium/lilium_rust.rs | 83 ++++++
5 files changed, 667 insertions(+)
create mode 100644 security/lilium/Kconfig
create mode 100644 security/lilium/Makefile
create mode 100644 security/lilium/lilium_config.h
create mode 100644 security/lilium/lilium_lsm.c
create mode 100644 security/lilium/lilium_rust.rs
diff --git a/security/lilium/Kconfig b/security/lilium/Kconfig
new file mode 100644
index 0000000..3072964
--- /dev/null
+++ b/security/lilium/Kconfig
@@ -0,0 +1,82 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Lilium (Linux Integrity Lock-In User Module)
+# Copyright (C) 2025 Enzo Fuke
+#
+config SECURITY_LILIUM
+ bool "Lilium (Linux Integrity Lock-In User Module) Support"
+ depends on SECURITY
+ help
+ This enables the Lilium Linux Security Module, which provides
+ modular security mechanisms for restricting various system
+ operations including ptrace, mmap/mprotect with PROT_EXEC,
+ kexec_load, clone/unshare, module management, and file operations.
+
+ All security mechanisms are disabled by default and can be
+ enabled individually through sysctl.
+
+ If you are unsure how to answer this question, answer N.
+
+config SECURITY_LILIUM_PTRACE
+ bool "Lilium ptrace restrictions"
+ depends on SECURITY_LILIUM
+ default n
+ help
+ This enables ptrace access restrictions in Lilium.
+
+ If you are unsure how to answer this question, answer N.
+
+config SECURITY_LILIUM_MPROTECT
+ bool "Lilium mmap/mprotect restrictions"
+ depends on SECURITY_LILIUM
+ default n
+ help
+ This enables mmap/mprotect with PROT_EXEC restrictions in Lilium.
+
+ If you are unsure how to answer this question, answer N.
+
+config SECURITY_LILIUM_KEXEC
+ bool "Lilium kexec_load restrictions"
+ depends on SECURITY_LILIUM
+ default n
+ help
+ This enables kexec_load restrictions in Lilium.
+
+ If you are unsure how to answer this question, answer N.
+
+config SECURITY_LILIUM_CLONE
+ bool "Lilium clone/unshare restrictions"
+ depends on SECURITY_LILIUM
+ default n
+ help
+ This enables clone and unshare restrictions in Lilium.
+
+ If you are unsure how to answer this question, answer N.
+
+config SECURITY_LILIUM_MODULE
+ bool "Lilium module management restrictions"
+ depends on SECURITY_LILIUM
+ default n
+ help
+ This enables module loading/unloading restrictions in Lilium.
+
+ If you are unsure how to answer this question, answer N.
+
+config SECURITY_LILIUM_OPEN
+ bool "Lilium file open restrictions"
+ depends on SECURITY_LILIUM
+ default n
+ help
+ This enables open/openat restrictions in Lilium.
+
+ If you are unsure how to answer this question, answer N.
+
+config SECURITY_LILIUM_IOCTL
+ bool "Lilium ioctl restrictions"
+ depends on SECURITY_LILIUM
+ default n
+ help
+ This enables ioctl restrictions in Lilium.
+
+ If you are unsure how to answer this question, answer N.
+
diff --git a/security/lilium/Makefile b/security/lilium/Makefile
new file mode 100644
index 0000000..17aeb04
--- /dev/null
+++ b/security/lilium/Makefile
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Lilium (Linux Integrity Lock-In User Module)
+# Copyright (C) 2025 Enzo Fuke
+#
+obj-$(CONFIG_SECURITY_LILIUM) += lilium.o
+
+lilium-y := lilium_lsm.o
+lilium-$(CONFIG_RUST) += lilium_rust.o
+
diff --git a/security/lilium/lilium_config.h b/security/lilium/lilium_config.h
new file mode 100644
index 0000000..1633c7e
--- /dev/null
+++ b/security/lilium/lilium_config.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Lilium (Linux Integrity Lock-In User Module)
+ * Copyright (C) 2025 Enzo Fuke
+ */
+
+#ifndef _SECURITY_LILIUM_CONFIG_H
+#define _SECURITY_LILIUM_CONFIG_H
+
+/* Default disabled state for all Lilium features */
+#define LILIUM_FEATURE_DISABLED 0
+#define LILIUM_FEATURE_ENABLED 1
+
+/* Feature control flags - all disabled by default */
+#define LILIUM_DEFAULT_PTRACE LILIUM_FEATURE_DISABLED
+#define LILIUM_DEFAULT_MPROTECT LILIUM_FEATURE_DISABLED
+#define LILIUM_DEFAULT_KEXEC LILIUM_FEATURE_DISABLED
+#define LILIUM_DEFAULT_CLONE LILIUM_FEATURE_DISABLED
+#define LILIUM_DEFAULT_MODULE LILIUM_FEATURE_DISABLED
+#define LILIUM_DEFAULT_OPEN LILIUM_FEATURE_DISABLED
+#define LILIUM_DEFAULT_IOCTL LILIUM_FEATURE_DISABLED
+
+#endif /* _SECURITY_LILIUM_CONFIG_H */
+
diff --git a/security/lilium/lilium_lsm.c b/security/lilium/lilium_lsm.c
new file mode 100644
index 0000000..82bac41
--- /dev/null
+++ b/security/lilium/lilium_lsm.c
@@ -0,0 +1,468 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Lilium (Linux Integrity Lock-In User Module)
+ * Copyright (C) 2025 Enzo Fuke
+ */
+
+#include <linux/lsm_hooks.h>
+#include <linux/ptrace.h>
+#include <linux/prctl.h>
+#include <linux/ratelimit.h>
+#include <linux/workqueue.h>
+#include <linux/string_helpers.h>
+#include <linux/task_work.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/uaccess.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/mman.h>
+#include <linux/kexec.h>
+#include <linux/slab.h>
+#include <linux/nsproxy.h>
+#include <linux/security.h>
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
+#include <uapi/linux/lsm.h>
+
+#include "lilium_config.h"
+
+/* Feature control variables - all disabled by default */
+static int lilium_ptrace_enabled = LILIUM_DEFAULT_PTRACE;
+static int lilium_mprotect_enabled = LILIUM_DEFAULT_MPROTECT;
+static int lilium_kexec_enabled = LILIUM_DEFAULT_KEXEC;
+static int lilium_clone_enabled = LILIUM_DEFAULT_CLONE;
+static int lilium_module_enabled = LILIUM_DEFAULT_MODULE;
+static int lilium_open_enabled = LILIUM_DEFAULT_OPEN;
+static int lilium_ioctl_enabled = LILIUM_DEFAULT_IOCTL;
+
+/* Kobject for Lilium sysfs interface */
+static struct kobject *lilium_kobj;
+
+/* Sysfs attribute show/store functions */
+static ssize_t ptrace_enabled_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return sysfs_emit(buf, "%d\n", lilium_ptrace_enabled);
+}
+
+static ssize_t ptrace_enabled_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret, val;
+
+ ret = kstrtoint(buf, 10, &val);
+ if (ret < 0)
+ return ret;
+
+ if (val != 0 && val != 1)
+ return -EINVAL;
+
+ lilium_ptrace_enabled = val;
+ return count;
+}
+
+static ssize_t mprotect_enabled_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return sysfs_emit(buf, "%d\n", lilium_mprotect_enabled);
+}
+
+static ssize_t mprotect_enabled_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret, val;
+
+ ret = kstrtoint(buf, 10, &val);
+ if (ret < 0)
+ return ret;
+
+ if (val != 0 && val != 1)
+ return -EINVAL;
+
+ lilium_mprotect_enabled = val;
+ return count;
+}
+
+static ssize_t kexec_enabled_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return sysfs_emit(buf, "%d\n", lilium_kexec_enabled);
+}
+
+static ssize_t kexec_enabled_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret, val;
+
+ ret = kstrtoint(buf, 10, &val);
+ if (ret < 0)
+ return ret;
+
+ if (val != 0 && val != 1)
+ return -EINVAL;
+
+ lilium_kexec_enabled = val;
+ return count;
+}
+
+static ssize_t clone_enabled_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return sysfs_emit(buf, "%d\n", lilium_clone_enabled);
+}
+
+static ssize_t clone_enabled_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret, val;
+
+ ret = kstrtoint(buf, 10, &val);
+ if (ret < 0)
+ return ret;
+
+ if (val != 0 && val != 1)
+ return -EINVAL;
+
+ lilium_clone_enabled = val;
+ return count;
+}
+
+static ssize_t module_enabled_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return sysfs_emit(buf, "%d\n", lilium_module_enabled);
+}
+
+static ssize_t module_enabled_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret, val;
+
+ ret = kstrtoint(buf, 10, &val);
+ if (ret < 0)
+ return ret;
+
+ if (val != 0 && val != 1)
+ return -EINVAL;
+
+ lilium_module_enabled = val;
+ return count;
+}
+
+static ssize_t open_enabled_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return sysfs_emit(buf, "%d\n", lilium_open_enabled);
+}
+
+static ssize_t open_enabled_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret, val;
+
+ ret = kstrtoint(buf, 10, &val);
+ if (ret < 0)
+ return ret;
+
+ if (val != 0 && val != 1)
+ return -EINVAL;
+
+ lilium_open_enabled = val;
+ return count;
+}
+
+static ssize_t ioctl_enabled_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return sysfs_emit(buf, "%d\n", lilium_ioctl_enabled);
+}
+
+static ssize_t ioctl_enabled_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret, val;
+
+ ret = kstrtoint(buf, 10, &val);
+ if (ret < 0)
+ return ret;
+
+ if (val != 0 && val != 1)
+ return -EINVAL;
+
+ lilium_ioctl_enabled = val;
+ return count;
+}
+
+/* Define sysfs attributes */
+static struct kobj_attribute ptrace_attr =
+ __ATTR(ptrace_enabled, 0644, ptrace_enabled_show, ptrace_enabled_store);
+static struct kobj_attribute mprotect_attr =
+ __ATTR(mprotect_enabled, 0644, mprotect_enabled_show, mprotect_enabled_store);
+static struct kobj_attribute kexec_attr =
+ __ATTR(kexec_enabled, 0644, kexec_enabled_show, kexec_enabled_store);
+static struct kobj_attribute clone_attr =
+ __ATTR(clone_enabled, 0644, clone_enabled_show, clone_enabled_store);
+static struct kobj_attribute module_attr =
+ __ATTR(module_enabled, 0644, module_enabled_show, module_enabled_store);
+static struct kobj_attribute open_attr =
+ __ATTR(open_enabled, 0644, open_enabled_show, open_enabled_store);
+static struct kobj_attribute ioctl_attr =
+ __ATTR(ioctl_enabled, 0644, ioctl_enabled_show, ioctl_enabled_store);
+
+/* Attribute group */
+static struct attribute *lilium_attrs[] = {
+ &ptrace_attr.attr,
+ &mprotect_attr.attr,
+ &kexec_attr.attr,
+ &clone_attr.attr,
+ &module_attr.attr,
+ &open_attr.attr,
+ &ioctl_attr.attr,
+ NULL,
+};
+
+static struct attribute_group lilium_attr_group = {
+ .attrs = lilium_attrs,
+};
+
+/* LSM Hook Implementations */
+
+static int lilium_ptrace_access_check(struct task_struct *child,
+ unsigned int mode)
+{
+ if (!lilium_ptrace_enabled)
+ return 0;
+
+ /* Implement contextual logic for ptrace restrictions */
+ if (mode & PTRACE_MODE_ATTACH) {
+ /* Allow if caller has CAP_SYS_PTRACE */
+ if (capable(CAP_SYS_PTRACE))
+ return 0;
+
+ /* Deny ptrace access */
+ return -EPERM;
+ }
+
+ return 0;
+}
+
+static int lilium_file_mprotect(struct vm_area_struct *vma,
+ unsigned long reqprot,
+ unsigned long prot)
+{
+ if (!lilium_mprotect_enabled)
+ return 0;
+
+ /* Implement contextual logic for mprotect restrictions */
+ if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
+ /* Allow if caller has CAP_SYS_ADMIN */
+ if (capable(CAP_SYS_ADMIN))
+ return 0;
+
+ /* Deny making non-executable memory executable */
+ return -EPERM;
+ }
+
+ return 0;
+}
+
+static int lilium_mmap_file(struct file *file, unsigned long reqprot,
+ unsigned long prot, unsigned long flags)
+{
+ if (!lilium_mprotect_enabled)
+ return 0;
+
+ /* Implement contextual logic for mmap restrictions */
+ if ((prot & PROT_EXEC) && (flags & MAP_ANONYMOUS)) {
+ /* Allow if caller has CAP_SYS_ADMIN */
+ if (capable(CAP_SYS_ADMIN))
+ return 0;
+
+ /* Deny executable anonymous mappings */
+ return -EPERM;
+ }
+
+ return 0;
+}
+
+static int lilium_task_create(struct task_struct *task,
+ struct task_struct *child)
+{
+ if (!lilium_clone_enabled)
+ return 0;
+
+ /* Implement contextual logic for clone restrictions */
+ /* This is a placeholder - actual implementation would check
+ * specific clone flags or namespace creation
+ */
+
+ return 0;
+}
+
+static int lilium_task_fix_setuid(struct task_struct *task,
+ struct cred *new,
+ const struct cred *old,
+ int flags)
+{
+ if (!lilium_clone_enabled)
+ return 0;
+
+ /* Implement contextual logic for unshare restrictions */
+ /* This is a placeholder - actual implementation would check
+ * specific unshare flags or namespace creation
+ */
+
+ return 0;
+}
+
+static int lilium_kernel_module_request(char *kmod_name)
+{
+ if (!lilium_module_enabled)
+ return 0;
+
+ /* Implement contextual logic for module loading restrictions */
+ /* Allow if caller has CAP_SYS_MODULE */
+ if (capable(CAP_SYS_MODULE))
+ return 0;
+
+ /* Deny module loading */
+ return -EPERM;
+}
+
+static int lilium_kernel_module_from_file(struct file *file)
+{
+ if (!lilium_module_enabled)
+ return 0;
+
+ /* Implement contextual logic for module loading restrictions */
+ /* Allow if caller has CAP_SYS_MODULE */
+ if (capable(CAP_SYS_MODULE))
+ return 0;
+
+ /* Deny module loading */
+ return -EPERM;
+}
+
+static int lilium_file_open(struct file *file)
+{
+ if (!lilium_open_enabled)
+ return 0;
+
+ /* Implement contextual logic for file open restrictions */
+ /* This is a placeholder - actual implementation would check
+ * specific file paths or attributes
+ */
+
+ return 0;
+}
+
+static int lilium_file_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ if (!lilium_ioctl_enabled)
+ return 0;
+
+ /* Implement contextual logic for ioctl restrictions */
+ /* This is a placeholder - actual implementation would check
+ * specific ioctl commands
+ */
+
+ return 0;
+}
+
+static int lilium_sb_mount(const char *dev_name, const struct path *path,
+ const char *type, unsigned long flags, void *data)
+{
+ if (!lilium_open_enabled)
+ return 0;
+
+ /* Implement contextual logic for mount restrictions */
+ /* This is a placeholder - actual implementation would check
+ * specific mount flags or filesystem types
+ */
+
+ return 0;
+}
+
+static int lilium_kexec_kernel_load(struct kimage *image)
+{
+ if (!lilium_kexec_enabled)
+ return 0;
+
+ /* Implement contextual logic for kexec_load restrictions */
+ /* Allow if caller has CAP_SYS_BOOT */
+ if (capable(CAP_SYS_BOOT))
+ return 0;
+
+ /* Deny kexec_load */
+ return -EPERM;
+}
+
+/* LSM Hook Definitions */
+static struct security_hook_list lilium_hooks[] = {
+ LSM_HOOK_INIT(ptrace_access_check, lilium_ptrace_access_check),
+ LSM_HOOK_INIT(file_mprotect, lilium_file_mprotect),
+ LSM_HOOK_INIT(mmap_file, lilium_mmap_file),
+ LSM_HOOK_INIT(task_create, lilium_task_create),
+ LSM_HOOK_INIT(task_fix_setuid, lilium_task_fix_setuid),
+ LSM_HOOK_INIT(kernel_module_request, lilium_kernel_module_request),
+ LSM_HOOK_INIT(kernel_module_from_file, lilium_kernel_module_from_file),
+ LSM_HOOK_INIT(file_open, lilium_file_open),
+ LSM_HOOK_INIT(file_ioctl, lilium_file_ioctl),
+ LSM_HOOK_INIT(sb_mount, lilium_sb_mount),
+ LSM_HOOK_INIT(kexec_kernel_load, lilium_kexec_kernel_load),
+};
+
+static const struct lsm_id lilium_lsmid = {
+ .name = "lilium",
+ .id = LSM_ID_MAJOR_MAX,
+};
+
+static void lilium_exit(void)
+{
+ if (lilium_kobj) {
+ sysfs_remove_group(lilium_kobj, &lilium_attr_group);
+ kobject_put(lilium_kobj);
+ }
+}
+
+static int __init lilium_init(void)
+{
+ int ret;
+
+ /* Create sysfs interface */
+ lilium_kobj = kobject_create_and_add("lilium", kernel_kobj);
+ if (!lilium_kobj)
+ return -ENOMEM;
+
+ ret = sysfs_create_group(lilium_kobj, &lilium_attr_group);
+ if (ret) {
+ kobject_put(lilium_kobj);
+ return ret;
+ }
+
+ /* Register LSM hooks */
+ security_add_hooks(lilium_hooks, ARRAY_SIZE(lilium_hooks), &lilium_lsmid);
+
+ pr_info("Lilium: Linux Integrity Lock-In User Module initialized\n");
+ return 0;
+}
+
+security_initcall(lilium_init);
+module_exit(lilium_exit);
+
+MODULE_DESCRIPTION("Lilium (Linux Integrity Lock-In User Module)");
+MODULE_AUTHOR("Enzo Fuke");
+MODULE_LICENSE("GPL v2");
+
diff --git a/security/lilium/lilium_rust.rs b/security/lilium/lilium_rust.rs
new file mode 100644
index 0000000..7901d9d
--- /dev/null
+++ b/security/lilium/lilium_rust.rs
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Lilium (Linux Integrity Lock-In User Module)
+ * Copyright (C) 2025 Enzo Fuke
+ */
+
+
+use kernel::prelude::*;
+use kernel::security;
+use kernel::file::File;
+use kernel::task::Task;
+use kernel::cred::Credential;
+
+const LILIUM_FEATURE_DISABLED: i32 = 0;
+const LILIUM_FEATURE_ENABLED: i32 = 1;
+
+extern "C" {
+ static lilium_ptrace_enabled: i32;
+ static lilium_mprotect_enabled: i32;
+ static lilium_kexec_enabled: i32;
+ static lilium_clone_enabled: i32;
+ static lilium_module_enabled: i32;
+ static lilium_open_enabled: i32;
+ static lilium_ioctl_enabled: i32;
+}
+
+pub struct LiliumOps;
+
+impl security::SecurityHooks for LiliumOps {
+ fn ptrace_access_check(
+ &self,
+ child: &Task,
+ mode: u32,
+ ) -> Result<security::SecurityHookResult> {
+ if unsafe { lilium_ptrace_enabled } == LILIUM_FEATURE_DISABLED {
+ return Ok(security::SecurityHookResult::Default);
+ }
+
+ if mode & security::PTRACE_MODE_ATTACH != 0 {
+ if kernel::current_cred().has_capability(kernel::CAP_SYS_PTRACE) {
+ return Ok(security::SecurityHookResult::Default);
+ }
+
+ return Ok(security::SecurityHookResult::Reject);
+ }
+
+ Ok(security::SecurityHookResult::Default)
+ }
+
+ fn file_mprotect(
+ &self,
+ vma: &kernel::mm::VirtualMemoryArea,
+ reqprot: u64,
+ prot: u64,
+ ) -> Result<security::SecurityHookResult> {
+ if unsafe { lilium_mprotect_enabled } == LILIUM_FEATURE_DISABLED {
+ return Ok(security::SecurityHookResult::Default);
+ }
+
+ if (prot & kernel::mm::PROT_EXEC) != 0 && (vma.flags() & kernel::mm::VM_EXEC) == 0 {
+ if kernel::current_cred().has_capability(kernel::CAP_SYS_ADMIN) {
+ return Ok(security::SecurityHookResult::Default);
+ }
+
+ return Ok(security::SecurityHookResult::Reject);
+ }
+
+ Ok(security::SecurityHookResult::Default)
+ }
+
+ fn file_open(
+ &self,
+ file: &File,
+ ) -> Result<security::SecurityHookResult> {
+ if unsafe { lilium_open_enabled } == LILIUM_FEATURE_DISABLED {
+ return Ok(security::SecurityHookResult::Default);
+ }
+
+
+ Ok(security::SecurityHookResult::Default)
+ }
+}
+
--
2.49.0
More information about the Linux-security-module-archive
mailing list