[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