BPF LSM prevent program unload
Paul Moore
paul at paul-moore.com
Thu Dec 7 17:34:15 UTC 2023
On Wed, Dec 6, 2023 at 9:28 PM Yafang Shao <laoar.shao at gmail.com> wrote:
> On Wed, Dec 6, 2023 at 11:02 PM Frederick Lawler <fred at cloudflare.com> wrote:
> > On Wed, Dec 06, 2023 at 10:42:50AM +0800, Yafang Shao wrote:
> > > On Wed, Dec 6, 2023 at 4:39 AM Frederick Lawler wrote:
> > > >
> > > > Hi,
> > > >
> > > > IIUC, LSMs are supposed to give us the ability to design policy around
> > > > unprivileged users and in addition to privileged users. As we expand
> > > > our usage of BPF LSM's, there are cases where we want to restrict
> > > > privileged users from unloading our progs. For instance, any privileged
> > > > user that wants to remove restrictions we've placed on privileged users.
> > > >
> > > > We currently have a loader application doesn't leverage BPF skeletons. We
> > > > instead load BPF object files, and then pin the progs to a mount point that
> > > > is a bpf filesystem. On next run, if we have new policies, load in new
> > > > policies, and finally unload the old.
> > > >
> > > > Here are some conditions a privileged user may unload programs:
> > > >
> > > > umount /sys/fs/bpf
> > > > rm -rf /sys/fs/bpf/lsm
> > > > rm /sys/fs/bpf/lsm/some_prog
> > > > unlink /sys/fs/bpf/lsm/some_prog
> > > >
> > > > This works because once we remove the last reference, the programs and
> > > > pinned maps are cleaned up.
> > > >
> > > > Moving individual pins or moving the mount entirely with mount --move
> > > > do not perform any clean up operations. Lastly, bpftool doesn't currently
> > > > have the ability to unload LSM's AFAIK.
If you haven't already, I would suggest talking with KP Singh as he is
the BPF LSM maintainer; I see him on the To/CC line so I'm sure he'll
comment when he has the chance to do so.
> > > > The few ideas I have floating around are:
> > > >
> > > > 1. Leverage some LSM hooks (BPF or otherwise) to restrict on the functions
> > > > security_sb_umount(), security_path_unlink(), security_inode_unlink().
> > > >
> > > > Both security_path_unlink() and security_inode_unlink() handle the
> > > > unlink/remove case, but not the umount case.
I'm not a BPF expert, but this seems like the most obvious solution,
although as Tetsuo already mentioned you probably don't want to block
all unmount operations as that would be bad for obvious reasons. I'm
guessing that a BPF LSM would have access to things like the current
task credentials and enough of the mounted filesystem's state (BPF
prog pinning?) to make a reasonable decision about granting or denying
the umount operation request.
> > > > 3. Leverage SELinux/Apparmor to possibly handle these cases.
SELinux has support for restricting unmount operations as well BPF
program loading. I see that AppArmor also has controls around
unmount, but I am less familiar with how that works. It is also worth
mentioning that Tomoyo and Landlock provide unmount hook
implementations although both LSMs are fairly unique so I can't say if
they would be a good fit for your proposed use case.
> > > > 4. Introduce a security_bpf_prog_unload() to target hopefully the
> > > > umount and unlink cases at the same time.
At first glance that seems reasonable, but I guess we would need to
see it discussed a bit before I could promise to commit to that.
As a FYI, we have some documented guidelines on creating new LSM
hooks; it's worth a quick read if you haven't seen it already.
https://github.com/LinuxSecurityModule/kernel?tab=readme-ov-file#new-lsm-hook-guidelines
> > > All the above programs can also be removed by privileged users.
> > >
> >
> > I should probably clarify the "BPF or otherwise" a bit better. Even a
> > compiled in LSM module? If so, where can I find a bit more information
> > about that?
I'm not quite sure what you are asking about here, but we don't
currently support "unloading" built-in LSM modules and I don't see us
changing that anytime soon. The closest one could get would be with a
LSM that supports runtime configuration of its security policy; one
could go from a restrictive or an allow-all, permissive policy
effectively disabling the LSM from an access control standpoint.
I don't want to speak for all the LSMs here, but at least SELinux has
the ability to restrict policy loading so that one could prevent
replacing a relatively strict policy with a more permissive policy.
Although it is worth noting that enabling this restriction has a
number of caveats, i.e. policy updates require a reboot, and isn't
something I would recommend for a general purpose system.
--
paul-moore.com
More information about the Linux-security-module-archive
mailing list