[PATCH 2/3] proc: query LSMs for introspective mem access (if PROC_MEM_FORCE_ALWAYS)
Christian Brauner
brauner at kernel.org
Wed Aug 26 13:01:21 UTC 2026
On Wed, Aug 26, 2026 at 12:29:14PM +0200, Christian Brauner wrote:
> On Tue, Aug 25, 2026 at 04:00:40PM +0200, Jann Horn wrote:
> > On Tue, Aug 25, 2026 at 3:19 PM Christian Brauner <brauner at kernel.org> wrote:
> > > On Tue, Aug 18, 2026 at 09:51:06PM +0200, Jann Horn wrote:
> > > > If the system is running with PROC_MEM_FORCE_ALWAYS, LSMs currently have no
> > > > good opportunity to block a process from overwriting read-only code in its
> > > > own address space through FOLL_FORCE writes via /proc/self/mem.
> > > > The security_ptrace_access_check() LSM hook is bypassed when a process
> > > > opens /proc/self/mem because this is considered "introspection".
> > > >
> > > > This causes a hole in SELinux EXECMEM enforcement, which tries to ensure
> > > > that a process cannot create executable anonymous pages.
> > > >
> > > > PROC_MEM_FORCE_PTRACE prevents that and ensures that such FOLL_FORCE
> > > > accesses are only possible when the LSM allows ptrace() attachment; but it
> > > > is unclear how quickly PROC_MEM_FORCE_PTRACE can be deployed in
> > > > environments running lots of third-party code, such as Android.
> > > >
> > > > So, introduce a new LSM hook that can forbid FOLL_FORCE specifically for
> > > > such "introspective" accesses.
> > > >
> > > > Signed-off-by: Jann Horn <jannh at google.com>
> > > > ---
> > > > fs/proc/base.c | 6 ++++++
> > > > include/linux/lsm_hook_defs.h | 1 +
> > > > include/linux/security.h | 6 ++++++
> > > > security/security.c | 15 +++++++++++++++
> > > > 4 files changed, 28 insertions(+)
> > > >
> > > > diff --git a/fs/proc/base.c b/fs/proc/base.c
> > > > index bec6197329dc..3dfaef49bb70 100644
> > > > --- a/fs/proc/base.c
> > > > +++ b/fs/proc/base.c
> > > > @@ -851,6 +851,8 @@ static int __mem_open(struct inode *inode, struct file *file, unsigned int mode)
> > > > /* private_data for proc_mem_operations */
> > > > struct mem_private {
> > > > struct mm_struct *mm;
> > > > + /* Was the ptrace access check bypassed due to introspection? */
> > > > + bool introspection;
> > > > };
> > > >
> > > > static int mem_open(struct inode *inode, struct file *file)
> > > > @@ -864,12 +866,14 @@ static int mem_open(struct inode *inode, struct file *file)
> > > > priv->mm = proc_mem_open(inode, PTRACE_MODE_ATTACH);
> > > > if (IS_ERR_OR_NULL(priv->mm))
> > > > return priv->mm ? PTR_ERR(priv->mm) : -ESRCH;
> > > > + priv->introspection = priv->mm == current->mm;
> > > > file->private_data = no_free_ptr(priv);
> > > > return 0;
> > > > }
> > > >
> > > > static bool proc_mem_foll_force(struct file *file, struct mm_struct *mm)
> > > > {
> > > > + struct mem_private *priv = file->private_data;
> > > > struct task_struct *task;
> > > > bool ptrace_active = false;
> > > >
> > > > @@ -886,6 +890,8 @@ static bool proc_mem_foll_force(struct file *file, struct mm_struct *mm)
> > > > }
> > > > return ptrace_active;
> > > > default:
> > > > + if (priv->introspection)
> > > > + return security_introspect_mem_foll_force(file->f_cred) == 0;
> > >
> > > Hm. Why not pass the reason to security_introspect_mem_foll_force() and
> > > call it unconditionally? Similarly it could also be called for the
> > > active ptracer case. Then you'd just need to pass a flag to the security
> > > hook and the LSM can decide based on that.
> >
> > A process which is attached as a ptracer can modify memory with (for
> > example) PTRACE_POKETEXT and registers with (for example)
> > PTRACE_SETREGS. LSMs that want to prevent such debugging operations
> > are supposed to prevent ptrace attachment with the ptrace_access_check
> > hook.
>
> Yeah, but as I said elsewhere that is very very coarse and you can't
> differentiate between the different operations performed on the other
> task.
>
> > I am just trying to plug the enforcement hole where ptrace-style
> > modification of process state is possible without going through
> > ptrace_access_check - which means just looking at these
> > "introspection" cases.
>
> It seems odd to just call a hook when it's introspection denied.
> And if that's the case why not also have a general hook in
> ptrace_may_access() itself in the introspection branch?
>
> I would actually have use-cases for this btw.
To be clear: I have no quarrels with this going in as is. I'm just
interested in how policy decision such as this can be made more
meaningful in general. If you have thoughts around this you want to
share, please do.
More information about the Linux-security-module-archive
mailing list