Re: [RFC PATCH v2 2/2] selinux: fix overlayfs mmap() and mprotect() access checks
Paul Moore <[email protected]>
| Newsgroups | org.kernel.vger.linux-unionfs,org.kernel.vger.linux-fsdevel,org.kernel.vger.linux-security-module,org.kernel.vger.selinux,org.ozlabs.lists.linux-erofs |
|---|---|
| Message-ID | <CAHC9VhQJcuA0VTpGSD0-x+Z5a__SQBiYfwc9zWwLMDa6THfKPw@mail.gmail.com> |
On Mon, Mar 23, 2026 at 12:25 AM Paul Moore <[email protected]> wrote: > > The existing SELinux security model for overlayfs is to allow access if > the current task is able to access the top level file (the "user" file) > and the mounter's credentials are sufficient to access the lower > level file (the "backing" file). Unfortunately, the current code does > not properly enforce these access controls for both mmap() and mprotect() > operations on overlayfs filesystems. > > This patch makes use of the newly created security_mmap_backing_file() > LSM hook to provide the missing backing file enforcement for mmap() > operations, and leverages the backing file API and new LSM blob to > provide the necessary information to properly enforce the mprotect() > access controls. > > Cc: [email protected] > Signed-off-by: Paul Moore <[email protected]> > --- > security/selinux/hooks.c | 252 ++++++++++++++++++++++-------- > security/selinux/include/objsec.h | 17 ++ > 2 files changed, 200 insertions(+), 69 deletions(-) > > diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c > index d8224ea113d1..2a3d524dce24 100644 > --- a/security/selinux/hooks.c > +++ b/security/selinux/hooks.c > @@ -1745,6 +1745,60 @@ static inline int file_path_has_perm(const struct cred *cred, > static int bpf_fd_pass(const struct file *file, u32 sid); > #endif > > +static int __file_has_perm(bool bf_user_file, const struct cred *cred, > + const struct file *file, u32 av) > + > +{ > + struct common_audit_data ad; > + struct inode *inode; > + u32 ssid = cred_sid(cred); > + u32 tsid_fd; > + int rc; > + > + if (bf_user_file) { > + struct backing_file_security_struct *bfsec; > + const struct path *path; > + > + if (WARN_ON(!(file->f_mode & FMODE_BACKING))) > + return -EPERM; Based on other code paths, we should return -EIO here. I've updated the patch, but I'm holding off on posting another version for a day or so in case anyone else is able to take a look. > + bfsec = selinux_backing_file(file); > + path = backing_file_user_path(file); > + tsid_fd = bfsec->uf_sid; > + inode = d_inode(path->dentry); > + > + ad.type = LSM_AUDIT_DATA_PATH; > + ad.u.path = *path; > + } else { > + struct file_security_struct *fsec = selinux_file(file); > + > + tsid_fd = fsec->sid; > + inode = file_inode(file); > + > + ad.type = LSM_AUDIT_DATA_FILE; > + ad.u.file = file; > + } > + > + if (ssid != tsid_fd) { > + rc = avc_has_perm(ssid, tsid_fd, SECCLASS_FD, FD__USE, &ad); > + if (rc) > + return rc; > + } > + > +#ifdef CONFIG_BPF_SYSCALL > + /* regardless of backing vs user file, use the underlying file here */ > + rc = bpf_fd_pass(file, ssid); > + if (rc) > + return rc; > +#endif > + > + /* av is zero if only checking access to the descriptor. */ > + if (av) > + return inode_has_perm(cred, inode, av, &ad); > + > + return 0; > +} -- paul-moore.com