Re: [PATCH v3 1/2] lsm: add backing_file LSM hooks
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 | <CAHC9VhRvJwrp47-A0frOjJcTmiLr0G218idQ9obXBrNpRWuDUQ@mail.gmail.com> |
On Mon, Mar 30, 2026 at 4:35 AM Amir Goldstein <[email protected]> wrote: > On Fri, Mar 27, 2026 at 11:05 PM Paul Moore <[email protected]> wrote: > > > > Stacked filesystems such as overlayfs do not currently provide the > > necessary mechanisms for LSMs to properly enforce access controls on the > > mmap() and mprotect() operations. In order to resolve this gap, a LSM > > security blob is being added to the backing_file struct and the following > > new LSM hooks are being created ... ... > > diff --git a/fs/file_table.c b/fs/file_table.c > > index aaa5faaace1e..0bdc26cae138 100644 > > --- a/fs/file_table.c > > +++ b/fs/file_table.c > > @@ -50,6 +50,7 @@ struct backing_file { > > struct path user_path; > > freeptr_t bf_freeptr; > > }; > > + void *security; > > This needs ifdef SECURITY Yep. That will require some other changes, but I should be able to keep those fairly limited. > and the name should be user_security I'd strongly prefer to keep it as "security" both because "void *security" is a very common pattern in the kernel when adding LSM blobs to structs, and we don't know what each and every LSM may need to store in the backing_file LSM blob. > > +void *backing_file_security(const struct file *f) > > +{ > > + return backing_file(f)->security; > > +} > > I prefer the name backing_file_user_security() > > Terminology here is very confusing but when saying > "backing file" it is more natural that one is referring to the > backing xfs file with overlayfs has opened. > > The "backing file" already has an LSM blob f->f_security > which is fair the call it the "backing file's LSM blob" ... From a LSM dev's perspective, I would call file->f_security blob a file's LSM blob regardless of if the file is a user or backing file; the backing_file->security blob would be a backing file LSM blob. If you look at what the SELinux code does, specifically in the __file_has_perm() and __file_map_prot_check() functions (newly added in this patchset), you'll see this supported by the code: the file->f_security field is basically handled the same regardless of if it is a user or backing file whereas the backing_file->security field is handled very differently because it is a backing file. While I think it makes sense to match the accessor function's name to the struct field, ultimately I care more about the struct field's name. If you really feel strongly about changing backing_file_security() to backing_file_user_security() I can live with that so long as we keep backing_file->security intact. > > @@ -73,8 +79,11 @@ static inline void file_free(struct file *f) > > percpu_counter_dec(&nr_files); > > put_cred(f->f_cred); > > if (unlikely(f->f_mode & FMODE_BACKING)) { > > - path_put(backing_file_user_path(f)); > > - kmem_cache_free(bfilp_cachep, backing_file(f)); > > + struct backing_file *ff = backing_file(f); > > + > > + security_backing_file_free(&ff->security); > > + path_put(&ff->user_path); > > + kmem_cache_free(bfilp_cachep, ff); > > Not directly related to your patch, but as this is growing, IMO > this would look cleaner with backing_file_free() inline helper > (see attached path). Sure, I'll include your patch in the patchset. I'll also fix the comment style in the patch to match C style in the rest of the file (I'll note the change in the metadata). > > } else { > > kmem_cache_free(filp_cachep, f); > > } > > @@ -290,7 +299,8 @@ struct file *alloc_empty_file_noaccount(int flags, const struct cred *cred) > > * This is only for kernel internal use, and the allocate file must not be > > * installed into file tables or such. > > */ > > -struct file *alloc_empty_backing_file(int flags, const struct cred *cred) > > +struct file *alloc_empty_backing_file(int flags, const struct cred *cred, > > + const struct file *user_file) > > { > > struct backing_file *ff; > > int error; > > @@ -306,6 +316,11 @@ struct file *alloc_empty_backing_file(int flags, const struct cred *cred) > > } > > > > ff->file.f_mode |= FMODE_BACKING | FMODE_NOACCOUNT; > > + error = security_backing_file_alloc(&ff->security, user_file); > > + if (unlikely(error)) { > > + fput(&ff->file); > > + return ERR_PTR(error); > > + } > > return &ff->file; > > } > > There is an API issue here. > in order to call fput() we must ensure that user_security was initialized to > NULL (or allocated). > > I don't think that we want security_backing_file_alloc() to provide this > semantic and the current patch does not implement it. > > Furthermore, user_path is also not initialized in the error case. > > Attached UNTESTED fixup patch to suggest a cleanup with > init_backing_file() helper. > > It also changes the variable and helper name to user_security > and plays some trick to avoid many ifdef SECURITY. > Feel free to take whichever bits you like with/without attribution. I think I've got a cleaner approach than what you've proposed, let me code it up, test it all, and I'll post a new revision of the patchset soon. -- paul-moore.com