On 12/7/2023 9:34 AM, Paul Moore wrote: > On Wed, Dec 6, 2023 at 9:28 PM Yafang Shao <laoar.shao@xxxxxxxxx> wrote: >> On Wed, Dec 6, 2023 at 11:02 PM Frederick Lawler <fred@xxxxxxxxxxxxxx> 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. You can prevent Smack from making policy changes using the "onlycap" mechanism. It restricts what process labels can use CAP_MAC_ADMIN, which is required to update Smack rules. As with SELinux, it isn't recommended for general use.