From: MontanaOS Kernel Team Date: Wed, 6 May 2026 00:00:00 +0000 Subject: [PATCH] mm: kernel.user_mlock_unrestricted sysctl Adds a sysctl that allows unprivileged processes to mlock pages beyond their RLIMIT_MEMLOCK when set to 1. This is required for Montana node daemons running in a non-root namespace (Termux or system service running as a dedicated UID without CAP_IPC_LOCK), where the default RLIMIT_MEMLOCK of 64 KB is insufficient to lock the working set of cryptographic secrets. Default value is 0, which preserves vanilla kernel behavior. The sysctl is set to 1 by MontanaOS init.rc only after the system finishes early boot and montana_main service class is started. Security model: enabling this sysctl allows any unprivileged process to lock arbitrary amounts of memory, which could be used for a denial-of-service attack against other processes on the same system. On a single-purpose appliance device (MontanaOS phone running as a dedicated validator), this is an acceptable trade-off. The sysctl must NOT be enabled on multi-tenant systems. Signed-off-by: MontanaOS Kernel Team --- kernel/sysctl.c | 12 ++++++++++++ mm/mlock.c | 6 ++++++ 2 files changed, 18 insertions(+) diff --git a/kernel/sysctl.c b/kernel/sysctl.c --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -100,6 +100,9 @@ static const int six_hundred_forty_kb = 640 * 1024; #endif #endif +int sysctl_user_mlock_unrestricted; +EXPORT_SYMBOL(sysctl_user_mlock_unrestricted); + #ifdef CONFIG_PERF_EVENTS static const int six_hundred_forty_kb = 640 * 1024; #endif @@ -1850,6 +1853,15 @@ static struct ctl_table kern_table[] = { .proc_handler = proc_dointvec, }, #endif + { + .procname = "user_mlock_unrestricted", + .data = &sysctl_user_mlock_unrestricted, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_ONE, + }, {} }; diff --git a/mm/mlock.c b/mm/mlock.c --- a/mm/mlock.c +++ b/mm/mlock.c @@ -589,8 +589,14 @@ static __must_check int do_mlock(unsigned long start, size_t len, vm_flags_t fla return error; } +extern int sysctl_user_mlock_unrestricted; + static int can_do_mlock(void) { + if (sysctl_user_mlock_unrestricted) + return 1; if (rlimit(RLIMIT_MEMLOCK) != 0) return 1; if (capable(CAP_IPC_LOCK))