> From: Zbigniew Jędrzejewski-Szmek [mailto:zbyszek@xxxxxxxxx] > Sent: Thursday, December 30, 2021 1:02 PM > The gist of the proposal is described thus: > > The new feature behaves as follows. A modified kernel with the DIGLIM > > patches will expose to user space an interface to add/remove file > > digests from the kernel hash table. A user space parser, executed by > > the kernel during early boot, parses RPM headers found in /etc/diglim > > in the initial ram disk (included with a custom dracut script) and > > uploads them to the kernel. When a file is accessed, IMA calculates > > the file digest and queries it with DIGLIM. If the digest is found, > > measurement is skipped and appraisal is successful. If the digest is > > not found, a measurement of the file is performed and appraisal fails. > > When packages are installed or removed, the kernel hash table is kept > > synchronized with a new rpm plugin. > > This description is … short. I saw you asked more questions below. I will answer there. > > A user space parser, executed by the kernel during early boot > > Is it really executed by the kernel? This description makes it sound > like a special old-hotplug-helper-style program that is spawned directly > by the kernel. Yes, it must be executed before init, otherwise the kernel would refuse to execute it. And probably, it must be executed earlier than now, as I'm seeing that the kmod binary is being executed (with the same mechanism, user-mode helper) before the digest lists are uploaded to the kernel. The reason for the kernel denying any operation enforced by the IMA policy would be that there are no file signatures for appraisal. The digests loaded by the helper are used instead. For the same reason, the digest of the helper itself must be in the native format understood by the kernel (the process of generation and signing is done in kernel.spec), and the kernel must scan /etc/diglim to load the native digest list before the helper is executed. > > parses RPM headers found in /etc/diglim in the initial ram disk > > In general we try not to stuff more things in /etc, especially when > there is no reason to. Why doesn't the helper just read files from > /var/lib/rpm (or whatever %_dbpath du jour)? The RPM DB cannot be loaded as it is. The kernel accepts a file format similar to kernel modules, with appended signatures (I added support for PGP appended signatures in IMA). Each RPM header, together with its signature, must be written individually in a file. Also files in other formats can be added to the same directory (for example the user-generated digest lists). If there is a better place than /etc, it would be fine for me to move the directory to a new location. > This opens a bigger design question: the implementation seems to be > closely tied to a very specific boot sequence implementation: > grub2 + dracut. Unfortunately this is made even more opaque by the > text description which uses generic terms like "boot loader configuration" > when talking about a script which is intimately tied to some obsolete > imperative grub2 installation mechanism. Ok, sorry for the confusion. We just need to add few parameters to the kernel command line, and include the digest lists in the initial ram disk. For now, I'm excluding the implementation of a custom script to select only the digest lists required for accessing files in the initial ram disk. > It would be much better if instead the helper to upload the hashes > to the kernel would be a generic tool that can be called whenever and > from whatever environment. _Then_ you can add a dracut module to call > it in the initrd, but that part should be a trivial wrapper, with all > the "business logic" contained in the generic helper. Too late. Also it cannot be a generic tool. First it is statically linked, to avoid depending on shared libraries for which a native digest list must be generated. At least with a static binary, only one file should be considered. Second, I had to develop an ad-hoc LSM to protect the helper against the other root processes. The problem is that an attacker might be able to tamper with the memory of the helper containing the digests extracted from RPMs, before the digests are uploaded to the kernel. Anything that the helper accesses must be inspected by IMA to provide the guarantee that the helper was not tampered. > This will make testing easier, and not preclude systems without an > initrd. > > > When a file is accessed, IMA calculates the file digest and queries it with > DIGLIM > > All files? What does "accessed" mean exactly in this context? IMA selects the files to analyze depending on a policy. That policy allows the usage of different criteria: inode UID/GID, process UID/EUID, LSM label, etc. IMA does this selection at the time a file is executed, mmapped, opened, or read from the kernel. DIGLIM is invoked only whenever IMA selected a file, and IMA decides what to do with the file depending on the result of the query (other than the action specified in the policy). > > When packages are installed or removed, the kernel hash table is kept > > synchronized with a new rpm plugin. > > Does this mean that old hashes are removed from the kernel after a > package has been upgraded? Yes, the old digests are removed. However, files in use could be still used, as the result of the last integrity evaluation is stored in the IMA cache. For cached results, DIGLIM is not invoked again. > Are there any race conditions: e.g. when a new version of a package is > installed, at what point in time are the new hashes uploaded? Something > may be executed concurrently with the package upgrade, which would mean > that the new hashes would need to be uploaded before any files land on > disk. Yes, we encountered this problem when we implemented the solution in openEuler. One of the problems was that we loaded the digests too late, and that prevented the RPM installation scripts to work. After some iterations, we seem to have found the right solution (will try to complete the rpm plugin soon). > And vice versa, if a file is opened, and later executed with fexecve(2), > and concurrently the package is upgraded between those two steps, > will the execution fail? We are handling concurrency with RCU. It depends if IMA, calling the DIGLIM lookup function, sees the old or the new version of the pointers in the hash table. Roberto HUAWEI TECHNOLOGIES Duesseldorf GmbH, HRB 56063 Managing Director: Li Peng, Zhong Ronghua _______________________________________________ devel mailing list -- devel@xxxxxxxxxxxxxxxxxxxxxxx To unsubscribe send an email to devel-leave@xxxxxxxxxxxxxxxxxxxxxxx Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/ List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedoraproject.org/archives/list/devel@xxxxxxxxxxxxxxxxxxxxxxx Do not reply to spam on the list, report it: https://pagure.io/fedora-infrastructure