From d252dfc541922a8a4303e43b53caa5b240274539 Mon Sep 17 00:00:00 2001 From: Scott Little Date: Wed, 1 Aug 2018 14:18:47 -0400 Subject: [PATCH] Relocate integrity to stx-integ/kernel/kernel-modules/integrity Move content from stx-gplv2 into stx-integ Packages will be relocated to stx-integ: base/ bash cgcs-users cluster-resource-agents dpkg haproxy libfdt netpbm rpm database/ mariadb filesystem/ iscsi-initiator-utils filesystem/drbd/ drbd-tools kernel/kernel-modules/ drbd integrity intel-e1000e intel-i40e intel-i40evf intel-ixgbe intel-ixgbevf qat17 tpmdd ldap/ ldapscripts networking/ iptables net-tools Change-Id: I899ba2b3a354e4f1be7fcb1f2a99a46356634a55 Story: 2002801 Task: 22687 Signed-off-by: Scott Little --- centos_pkg_dirs | 1 + centos_pkg_dirs_rt | 1 + kernel/kernel-modules/integrity/PKG-INFO | 12 + .../integrity/centos/build_srpm.data | 5 + .../integrity/centos/files/COPYING | 344 +++++ .../integrity/centos/files/README | 231 +++ .../integrity/centos/files/ima.conf | 1 + .../integrity/centos/files/ima.policy | 4 + .../integrity/centos/files/integrity.conf | 1 + .../integrity/centos/files/modules-load.conf | 3 + .../integrity/centos/integrity-kmod.spec | 138 ++ .../0001-integrity-kcompat-support.patch | 1283 +++++++++++++++++ .../0002-integrity-expose-module-params.patch | 156 ++ .../0003-integrity-restrict-by-iversion.patch | 54 + ...ntegrity-disable-set-xattr-on-imasig.patch | 121 ++ .../Changes-for-CentOS-7.4-support.patch | 28 + .../patches/integrity-kmod.spec.patchlist | 3 + 17 files changed, 2386 insertions(+) create mode 100644 kernel/kernel-modules/integrity/PKG-INFO create mode 100644 kernel/kernel-modules/integrity/centos/build_srpm.data create mode 100644 kernel/kernel-modules/integrity/centos/files/COPYING create mode 100644 kernel/kernel-modules/integrity/centos/files/README create mode 100644 kernel/kernel-modules/integrity/centos/files/ima.conf create mode 100644 kernel/kernel-modules/integrity/centos/files/ima.policy create mode 100644 kernel/kernel-modules/integrity/centos/files/integrity.conf create mode 100644 kernel/kernel-modules/integrity/centos/files/modules-load.conf create mode 100644 kernel/kernel-modules/integrity/centos/integrity-kmod.spec create mode 100644 kernel/kernel-modules/integrity/patches/0001-integrity-kcompat-support.patch create mode 100644 kernel/kernel-modules/integrity/patches/0002-integrity-expose-module-params.patch create mode 100644 kernel/kernel-modules/integrity/patches/0003-integrity-restrict-by-iversion.patch create mode 100644 kernel/kernel-modules/integrity/patches/0004-integrity-disable-set-xattr-on-imasig.patch create mode 100644 kernel/kernel-modules/integrity/patches/Changes-for-CentOS-7.4-support.patch create mode 100644 kernel/kernel-modules/integrity/patches/integrity-kmod.spec.patchlist diff --git a/centos_pkg_dirs b/centos_pkg_dirs index 37596095a..eeed11094 100644 --- a/centos_pkg_dirs +++ b/centos_pkg_dirs @@ -123,3 +123,4 @@ kernel/kernel-modules/intel-ixgbevf kernel/kernel-modules/intel-ixgbe kernel/kernel-modules/qat17 kernel/kernel-modules/tpmdd +kernel/kernel-modules/integrity diff --git a/centos_pkg_dirs_rt b/centos_pkg_dirs_rt index 8cacf3102..4c481dc34 100644 --- a/centos_pkg_dirs_rt +++ b/centos_pkg_dirs_rt @@ -9,3 +9,4 @@ kernel/kernel-modules/intel-ixgbevf kernel/kernel-modules/intel-ixgbe kernel/kernel-modules/qat17 kernel/kernel-modules/tpmdd +kernel/kernel-modules/integrity diff --git a/kernel/kernel-modules/integrity/PKG-INFO b/kernel/kernel-modules/integrity/PKG-INFO new file mode 100644 index 000000000..751b82a19 --- /dev/null +++ b/kernel/kernel-modules/integrity/PKG-INFO @@ -0,0 +1,12 @@ +Metadata-Version: 1.1 +Name: integrity-kmod +Version: 4.12 +Summary: Integrity Linux* Kernel Modules +Home-page: http://tpmdd.sourceforge.net/ +Author: +Author-email: +License: GPL +Description: +This package contains the Linux driver and modules for the Integrity subsystem + +Platform: UNKNOWN diff --git a/kernel/kernel-modules/integrity/centos/build_srpm.data b/kernel/kernel-modules/integrity/centos/build_srpm.data new file mode 100644 index 000000000..89d451b60 --- /dev/null +++ b/kernel/kernel-modules/integrity/centos/build_srpm.data @@ -0,0 +1,5 @@ +COPY_LIST=" \ + $FILES_BASE/* \ + $CGCS_BASE/mwa-gplv2/integrity/patches/* \ + $CGCS_BASE/downloads/integrity-kmod-668a8270.tar.gz" +TIS_PATCH_VER=5 diff --git a/kernel/kernel-modules/integrity/centos/files/COPYING b/kernel/kernel-modules/integrity/centos/files/COPYING new file mode 100644 index 000000000..e2fed1bf7 --- /dev/null +++ b/kernel/kernel-modules/integrity/centos/files/COPYING @@ -0,0 +1,344 @@ + +"This software program is licensed subject to the GNU General Public License +(GPL). Version 2, June 1991, available at +" + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/kernel/kernel-modules/integrity/centos/files/README b/kernel/kernel-modules/integrity/centos/files/README new file mode 100644 index 000000000..1dbb36f9e --- /dev/null +++ b/kernel/kernel-modules/integrity/centos/files/README @@ -0,0 +1,231 @@ + +Integrity and IMA Modules for CentOS 7 (Linux version 3.10) +=============================================================================== + +=============================================================================== + +Kam Nasim +Copyright (c) 2017 Wind River Systems, Inc. + +SPDX-License-Identifier: Apache-2.0 + + +August, 2017 + +=============================================================================== + +Contents +-------- + +- Overview +- Rebasing Guidelines +- Changesets + +================================================================================ + + +Important Notes +--------------- + +No support for APPENDING IMA policies +---------------------------------------------- + +A provision was introduced in April 2014 to allow multiple IMA policies to be +appended.This change involved setting up inode hooks which could not be +backported in the 3.10 Kernel. Therefore we do not allow the following operation +types: +echo /etc/ima/ima_policy > /sys/kernel/security/ima/policy + +only an overwrite is possible: +cat policy-file > /ima/policy + +EVM support disabled in Kernel +------------------------------------------------ + +The EVM Kernel Configuration option was mutually exclusive to the CONFIG_INTEGRITY +Kernel configuration option. Since Integrity is being disabled in the Kernel, EVM +would also need to be built out-of-tree as a Kernel module and would require some +refactoring if it is to be used with this module pack. + + +IMA Keyring allocated inside the Kernel +----------------------------------------- + +Normally, the _ima Keyring is allocated from user space, but this has the +added disadvantage of persisting the public key on the file system. Corruption +of this public key may cripple the system by triggering APPRAISAL failures if +ima 'Enforcement' is enabled. To prevent this, the IMA public key is compiled +into the Kernel and is placed in the Kernel SOURCE (ima_signing_key.pub) + + +Overview +-------- + +This module pack builds Integrity and IMA kernel modules for the 3.10 kernel version. +If newer kernel version are to be supported in the future then the COMPAT +layer (kcompat.h) will need to be adjusted to address kernel-driver compatibility +issues. As well as certain LINUX_VERSION_CODE <= KERNEL_VERSION(3,10,0) ifdefs + +It supports Linux supported x86_64 systems. + +These drivers are only supported as a loadable module at this time. + + +Rebasing Guidelines +-------------------- + +On rebasing TiC software heed the following: +- always rebase the Kernel first before rebasing this package +- get the HEAD from the tpmdd repo and generate a tarball, the tarball +should follow the naming convention: tpm-kmod-; use the short-hand +form of the git commit ID (8 characters) +- update the integrity-kmod spec to Source the new tarball +- apply all existing patches against the new tarball, and adjust the kcompat +layer (LINUX_VERSION_CODE ifdefs, kcompat.h and common.mk) accordingly + +IMA Signing Key Generation Guidelines +-------------------------------------- + +The following may be used to generate an IMA key pair: +openssl req -newkey rsa:2048 -nodes -days 10950 -x509 -outform DER -out ima_signing_key.pub -keyout ima_signing_key.priv + +The "ima_signing_key.pub" MUST be placed in the Kernel source (files/) so that the +Kernel build can pick it up and compile it in. + + +================================================================================ + + +Change Sets +------------------------- + +This driver is a fork from the tpmdd repo: +https://sourceforge.net/projects/tpmdd/ +http://git.infradead.org/users/jjs/linux-tpmdd.git/ + +Sync Head: 668a827057187403999b7ecfcf86b59979c8c3b2 + +COMPAT NOTES: + +1. In newer kernels, VFS layer read operations have been refactored: + VFS: refactor vfs_read() + + integrity_kernel_read() duplicates the file read operations code + in vfs_read(). This patch refactors vfs_read() code creating a + helper function __vfs_read(). It is used by both vfs_read() and + integrity_kernel_read(). + + Signed-off-by: Dmitry Kasatkin + Signed-off-by: Mimi Zohar + + The compat layer therefore needs to redefine the integrity vfs code to use + the original implementation + + +2. In newer kernels, a wrapper has been developed around inode mutex un/lock + + commit 5955102c9984fa081b2d570cfac75c97eecf8f3b + Author: Al Viro + Date: Fri Jan 22 15:40:57 2016 -0500 + + wrappers for ->i_mutex access + + parallel to mutex_{lock,unlock,trylock,is_locked,lock_nested}, + inode_foo(inode) being mutex_foo(&inode->i_mutex). + + Please, use those for access to ->i_mutex; over the coming cycle + ->i_mutex will become rwsem, with ->lookup() done with it held + only shared. + + Signed-off-by: Al Viro + + The compat layer needs to replace all instances of inode locking + with the underlying mutex locking/unlocking calls + + +3. In newer kernels, security PRE and POST Hooks are defined which +have their seperate appraisal calls + + commit 39eeb4fb97f60dbdfc823c1a673a8844b9226b60 + Author: Mimi Zohar + Date: Sat Jan 30 22:23:26 2016 -0500 + + security: define kernel_read_file hook + + The kernel_read_file security hook is called prior to reading the file + into memory. + + Changelog v4+: + - export security_kernel_read_file() + + Signed-off-by: Mimi Zohar + Acked-by: Kees Cook + Acked-by: Luis R. Rodriguez + Acked-by: Casey Schaufler + + The compat layer needs to ignore all PRE and POST File hooks and + cannot support such PRE and POST appraisals + + +4. In newer kernels, IMA policies can be applied by path as opposed to +content allowing multiple policies to be appended + + commit 7429b092811fb20c6a5b261c2c116a6a90cb9a29 +Author: Dmitry Kasatkin +Date: Fri Apr 11 17:47:01 2014 +0300 + + ima: load policy using path + + We currently cannot do appraisal or signature vetting of IMA policies + since we currently can only load IMA policies by writing the contents + of the policy directly in, as follows: + + cat policy-file > /ima/policy + + If we provide the kernel the path to the IMA policy so it can load + the policy itself it'd be able to later appraise or vet the file + signature if it has one. This patch adds support to load the IMA + policy with a given path as follows: + + echo /etc/ima/ima_policy > /sys/kernel/security/ima/policy + + Changelog v4+: + - moved kernel_read_file_from_path() error messages to callers + v3: + - moved kernel_read_file_from_path() to a separate patch + v2: + - after re-ordering the patches, replace calling integrity_kernel_read() + to read the file with kernel_read_file_from_path() (Mimi) + - Patch description re-written by Luis R. Rodriguez + + Signed-off-by: Dmitry Kasatkin + + This feature was removed from the IMA modules since it required extensive +backporting to the INODE and VFS layers inthe base kernel + +5. In newer kernels, IMA allows measurement lists to be preserved over +Kernel reinstalls or kexecs + + commit d9ddf077bb85b54200dfcb5f2edec4f0d6a7c2ca +Author: Mimi Zohar +Date: Thu Jan 14 20:59:14 2016 -0500 + + ima: support for kexec image and initramfs + + Add IMA policy support for measuring/appraising the kexec image and + initramfs. Two new IMA policy identifiers KEXEC_KERNEL_CHECK and + KEXEC_INITRAMFS_CHECK are defined. + + Example policy rules: + measure func=KEXEC_KERNEL_CHECK + appraise func=KEXEC_KERNEL_CHECK appraise_type=imasig + measure func=KEXEC_INITRAMFS_CHECK + appraise func=KEXEC_INITRAMFS_CHECK appraise_type=imasig + + Moving the enumeration to the vfs layer simplified the patches, allowing + the IMA changes, for the most part, to be separated from the other + changes. Unfortunately, passing either a kernel_read_file_id or a + ima_hooks enumeration within IMA is messy. + + This feature was removed from the IMA modules since it required defining a +new Kexec cache in the base Kernel which was an extensive backporting effort diff --git a/kernel/kernel-modules/integrity/centos/files/ima.conf b/kernel/kernel-modules/integrity/centos/files/ima.conf new file mode 100644 index 000000000..1c00690e6 --- /dev/null +++ b/kernel/kernel-modules/integrity/centos/files/ima.conf @@ -0,0 +1 @@ +options ima ima_appraise_param="log" ima_use_tpm=0 diff --git a/kernel/kernel-modules/integrity/centos/files/ima.policy b/kernel/kernel-modules/integrity/centos/files/ima.policy new file mode 100644 index 000000000..07b8b8135 --- /dev/null +++ b/kernel/kernel-modules/integrity/centos/files/ima.policy @@ -0,0 +1,4 @@ +# EXT4_SUPER_MAGIC +measure func=FILE_CHECK uid=0 fsmagic=0xEF53 +appraise func=FILE_MMAP mask=MAY_EXEC uid=0 appraise_type=imasig fsmagic=0xEF53 +appraise func=BPRM_CHECK mask=MAY_EXEC uid=0 appraise_type=imasig fsmagic=0xEF53 diff --git a/kernel/kernel-modules/integrity/centos/files/integrity.conf b/kernel/kernel-modules/integrity/centos/files/integrity.conf new file mode 100644 index 000000000..61694e52b --- /dev/null +++ b/kernel/kernel-modules/integrity/centos/files/integrity.conf @@ -0,0 +1 @@ +options integrity integrity_audit=0 diff --git a/kernel/kernel-modules/integrity/centos/files/modules-load.conf b/kernel/kernel-modules/integrity/centos/files/modules-load.conf new file mode 100644 index 000000000..1e720a56e --- /dev/null +++ b/kernel/kernel-modules/integrity/centos/files/modules-load.conf @@ -0,0 +1,3 @@ +tpm_tis +integrity +ima diff --git a/kernel/kernel-modules/integrity/centos/integrity-kmod.spec b/kernel/kernel-modules/integrity/centos/integrity-kmod.spec new file mode 100644 index 000000000..eb3c739cd --- /dev/null +++ b/kernel/kernel-modules/integrity/centos/integrity-kmod.spec @@ -0,0 +1,138 @@ +%if "%{?_tis_build_type}" == "rt" +%define bt_ext -rt +%else +%undefine bt_ext +%endif + +# Define the kmod package name here. +%define kmod_name integrity + +Name: %{kmod_name}-kmod%{?bt_ext} +# the version is the Kernel version from which +# this driver is extracted +Version: 4.12 +Release: 0%{?_tis_dist}.%{tis_patch_ver} +Group: System Environment/Kernel +License: GPLv2 +Summary: %{kmod_name}%{?bt_ext} kernel module(s) + +BuildRequires: kernel%{?bt_ext}-devel, redhat-rpm-config, perl, tpm-kmod%{?bt_ext}-symbols, openssl +ExclusiveArch: x86_64 + +# Sources. +# the integrity is available as a tarball, with +# the git commit Id referenced in the name +Source0: %{kmod_name}-kmod-668a8270.tar.gz +Source1: modules-load.conf +Source2: COPYING +Source3: README +Source4: integrity.conf +Source5: ima.conf +Source6: ima.policy + +# Patches +Patch01: 0001-integrity-kcompat-support.patch +Patch02: 0002-integrity-expose-module-params.patch +Patch03: 0003-integrity-restrict-by-iversion.patch +Patch04: 0004-integrity-disable-set-xattr-on-imasig.patch +Patch05: Changes-for-CentOS-7.4-support.patch + +%define kversion %(rpm -q kernel%{?bt_ext}-devel | sort --version-sort | tail -1 | sed 's/kernel%{?bt_ext}-devel-//') + +%package -n kmod-integrity%{?bt_ext} +Summary: Integrity kernel module(s) and driver +Group: System Environment/Kernel +%global _use_internal_dependency_generator 0 +Provides: kernel-modules >= %{kversion} +Provides: integrity-kmod = %{?epoch:%{epoch}:}%{version}-%{release} +Requires(post): /usr/sbin/depmod +Requires(postun): /usr/sbin/depmod + +%description -n kmod-integrity%{?bt_ext} +This package provides the %{version} Integrity / IMA kernel module(s) and drivers built +for the Linux kernel using the %{_target_cpu} family of processors. + +%post -n kmod-integrity%{?bt_ext} +echo "Working. This may take some time ..." +if [ -e "/boot/System.map-%{kversion}" ]; then + /usr/sbin/depmod -aeF "/boot/System.map-%{kversion}" "%{kversion}" > /dev/null || : +fi +modules=( $(find /lib/modules/%{kversion}/kernel/security/integrity/ | grep '\.ko$') ) +if [ -x "/sbin/weak-modules" ]; then + printf '%s\n' "${modules[@]}" | /sbin/weak-modules --add-modules +fi +echo "Done." + +%preun -n kmod-integrity%{?bt_ext} +rpm -ql kmod-integrity%{?bt_ext}-%{version}-%{release}.x86_64 | grep '\.ko$' > /var/run/rpm-kmod-integrity%{?bt_ext}-modules + +%postun -n kmod-integrity%{?bt_ext} +echo "Working. This may take some time ..." +if [ -e "/boot/System.map-%{kversion}" ]; then + /usr/sbin/depmod -aeF "/boot/System.map-%{kversion}" "%{kversion}" > /dev/null || : +fi +modules=( $(cat /var/run/rpm-kmod-integrity%{?bt_ext}-modules) ) +rm /var/run/rpm-kmod-integrity%{?bt_ext}-modules +if [ -x "/sbin/weak-modules" ]; then + printf '%s\n' "${modules[@]}" | /sbin/weak-modules --remove-modules +fi +echo "Done." + +%files -n kmod-integrity%{?bt_ext} +%defattr(-,root,root,-) +/lib/modules/%{kversion}/ +%doc /usr/share/doc/kmod-integrity/ +%{_sysconfdir}/modules-load.d/ima.conf +%config(noreplace) %{_sysconfdir}/modprobe.d/integrity.conf +%config(noreplace) %{_sysconfdir}/modprobe.d/ima.conf +%{_sysconfdir}/ima.policy + +# Disable the building of the debug package(s). +%define debug_package %{nil} + +%description +This package provides the %{kmod_name} kernel module(s). +It is built to depend upon the specific ABI provided by a range of releases +of the same variant of the Linux kernel and not on any one specific build. + +%prep +%autosetup -p 1 -n %{kmod_name} + +%build +# build out all the Integrity / IMA kernel modules +%{__make} KSRC=%{_usrsrc}/kernels/%{kversion} KBUILD_EXTRA_SYMBOLS=%{_usrsrc}/debug/tpm/Module.symvers + +%install +%{__install} -d %{buildroot}/lib/modules/%{kversion}/kernel/security/%{kmod_name}/ +%{__install} *.ko %{buildroot}/lib/modules/%{kversion}/kernel/security/%{kmod_name}/ +%{__install} -d %{buildroot}/lib/modules/%{kversion}/kernel/security/%{kmod_name}/ima/ +%{__install} ima/*.ko %{buildroot}/lib/modules/%{kversion}/kernel/security/%{kmod_name}/ima/ +%{__install} -d %{buildroot}%{_sysconfdir}/modules-load.d +%{__install} -m 644 %{SOURCE1} %{buildroot}%{_sysconfdir}/modules-load.d/ima.conf +%{__install} -d %{buildroot}%{_sysconfdir}/modprobe.d +%{__install} -p -m 0644 %{SOURCE4} %{buildroot}%{_sysconfdir}/modprobe.d/integrity.conf +%{__install} -p -m 0644 %{SOURCE5} %{buildroot}%{_sysconfdir}/modprobe.d/ima.conf +%{__install} -p -m 0400 %{SOURCE6} %{buildroot}%{_sysconfdir}/ima.policy +%{__install} -d %{buildroot}%{_defaultdocdir}/kmod-%{kmod_name}/ +%{__install} %{SOURCE2} %{buildroot}%{_defaultdocdir}/kmod-%{kmod_name}/ +%{__install} %{SOURCE3} %{buildroot}%{_defaultdocdir}/kmod-%{kmod_name}/ + +# Strip the modules(s). +find %{buildroot} -type f -name \*.ko -exec %{__strip} --strip-debug \{\} \; + +# Always Sign the modules(s). +# If the module signing keys are not defined, define them here. +%{!?privkey: %define privkey /usr/src/kernels/%{kversion}/signing_key.priv} +%{!?pubkey: %define pubkey /usr/src/kernels/%{kversion}/signing_key.x509} +for module in $(find %{buildroot} -type f -name \*.ko); +do %{__perl} /usr/src/kernels/%{kversion}/scripts/sign-file \ + sha256 %{privkey} %{pubkey} $module; +done + +%clean +%{__rm} -rf %{buildroot} + +%changelog +* Mon Aug 21 2017 Kam Nasim 4.12 +- Initial RPM package. + diff --git a/kernel/kernel-modules/integrity/patches/0001-integrity-kcompat-support.patch b/kernel/kernel-modules/integrity/patches/0001-integrity-kcompat-support.patch new file mode 100644 index 000000000..10cbfb417 --- /dev/null +++ b/kernel/kernel-modules/integrity/patches/0001-integrity-kcompat-support.patch @@ -0,0 +1,1283 @@ +From 7e956b974091563edc1b4f5a7646f4d8dff07ee5 Mon Sep 17 00:00:00 2001 +From: Kam Nasim +Date: Fri, 8 Sep 2017 16:34:25 -0400 +Subject: [PATCH] US101216: IMA out-of-tree modules for Titanium Kernel + +Build a kcompat layer and the ability to build out the Integrity and IMA +Kernel modules against a 3.10 Linux Kernel (CentOS v7.3) +--- + Makefile | 107 ++++++++++++++++- + common.mk | 330 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + digsig.c | 35 ++++-- + digsig_asymmetric.c | 22 +++- + iint.c | 52 +++++++-- + ima/Makefile | 8 +- + ima/ima.h | 9 +- + ima/ima_api.c | 14 +-- + ima/ima_appraise.c | 42 ++++--- + ima/ima_fs.c | 4 + + ima/ima_init.c | 4 +- + ima/ima_main.c | 40 +++++-- + ima/ima_policy.c | 32 ++++- + integrity.h | 9 +- + integrity_audit.c | 17 ++- + kcompat.h | 34 ++++++ + 16 files changed, 677 insertions(+), 82 deletions(-) + create mode 100644 common.mk + create mode 100644 kcompat.h + +diff --git a/Makefile b/Makefile +index 8d1f4bf..022a1b7 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,3 +1,7 @@ ++ ++ifneq ($(KERNELRELEASE),) ++# kbuild part of makefile ++ + # + # Makefile for caching inode integrity data (iint) + # +@@ -11,5 +15,104 @@ integrity-$(CONFIG_INTEGRITY_ASYMMETRIC_KEYS) += digsig_asymmetric.o + + subdir-$(CONFIG_IMA) += ima + obj-$(CONFIG_IMA) += ima/ +-subdir-$(CONFIG_EVM) += evm +-obj-$(CONFIG_EVM) += evm/ ++ ++else # ifneq($(KERNELRELEASE),) ++# normal makefile ++ ++# driver will be provided by the spec file ++DRIVER= ++ ++ifeq (,$(wildcard common.mk)) ++ $(error Cannot find common.mk build rules) ++else ++ include common.mk ++endif ++ ++############### ++# Build rules # ++############### ++ ++# Standard compilation, with regular output ++default: ++ @+$(call kernelbuild,modules) ++ ++# Noisy output, for extra debugging ++noisy: ++ @+$(call kernelbuild,modules,V=1) ++ ++# Silence any output generated ++silent: ++ @+$(call kernelbuild,modules,>/dev/null) ++ ++# Enable higher warning level ++checkwarnings: clean ++ @+$(call kernelbuild,modules,W=1) ++ ++# Run sparse static analyzer ++sparse: clean ++ @+$(call kernelbuild,modules,C=2 CF="-D__CHECK_ENDIAN__ -Wbitwise -Wcontext") ++ ++# Run coccicheck static analyzer ++ccc: clean ++ @+$(call kernelbuild,modules,coccicheck MODE=report) ++ ++# Install the modules ++install: default ++ @echo "Installing modules..." ++ @+$(call kernelbuild,modules_install) ++ @echo "Running depmod..." ++ @$(call cmd_depmod) ++ifeq (${cmd_initrd},) ++ @echo "Unable to update initrd. You may need to do this manually." ++else ++ @echo "Updating initrd..." ++ -@$(call cmd_initrd) ++endif ++ ++# Target used by rpmbuild spec file ++rpm: default ++ @install -D -m 644 ${DRIVER}.ko ${INSTALL_MOD_PATH}/lib/modules/${KVER}/${INSTALL_MOD_DIR}/${DRIVER}.ko ++ ++uninstall: ++ rm -f ${INSTALL_MOD_PATH}/lib/modules/${KVER}/${INSTALL_MOD_DIR}/${DRIVER}.ko; ++ $(call cmd_depmod) ++ifeq (${cmd_initrd},) ++ @echo "Unable to update initrd. You may need to do this manually." ++else ++ @echo "Updating initrd..." ++ -@$(call cmd_initrd) ++endif ++ ++######## ++# Help # ++######## ++help: ++ @echo 'Cleaning targets:' ++ @echo ' clean - Clean files generated by kernel module build' ++ @echo 'Build targets:' ++ @echo ' default - Build module(s) with standard verbosity' ++ @echo ' noisy - Build module(s) with V=1 verbosity -- very noisy' ++ @echo ' silent - Build module(s), squelching all output' ++ @echo 'Static Analysis:' ++ @echo ' checkwarnings - Clean, then build module(s) with W=1 warnings enabled' ++ @echo ' sparse - Clean, then check module(s) using sparse' ++ @echo ' ccc - Clean, then check module(s) using coccicheck' ++ @echo 'Other targets:' ++ @echo ' install - Build then install the module(s)' ++ @echo ' uninstall - Uninstall the module(s)' ++ @echo ' help - Display this help message' ++ @echo 'Variables:' ++ @echo ' LINUX_VERSION - Debug tool to force kernel LINUX_VERSION_CODE. Use at your own risk.' ++ @echo ' W=N - Kernel variable for setting warning levels' ++ @echo ' V=N - Kernel variable for setting output verbosity' ++ @echo ' INSTALL_MOD_PATH - Add prefix for the module and manpage installation path' ++ @echo ' INSTALL_MOD_DIR - Use module directory other than updates/security/integrity/${DRIVER}' ++ @echo ' KSRC - Specifies the full path to the kernel tree to build against' ++ @echo ' Other variables may be available for tuning make process, see' ++ @echo ' Kernel Kbuild documentation for more information' ++ ++.PHONY: default noisy clean silent sparse ccc install uninstall help ++ ++endif # ifneq($(KERNELRELEASE),) ++ ++ +diff --git a/common.mk b/common.mk +new file mode 100644 +index 0000000..3541284 +--- /dev/null ++++ b/common.mk +@@ -0,0 +1,330 @@ ++################################################################################ ++# ++# Linux IMA subsystem ++# Copyright(c) 2013 - 2017 Intel Corporation. ++# Copyright (c) 2017 Wind River Systems, Inc. ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# The full GNU General Public License is included in this distribution in ++# the file called "COPYING". ++# ++# Contact Information: ++# e1000-devel Mailing List ++# Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++################################################################################ ++ ++ ++# common Makefile rules useful for out-of-tree Linux driver builds ++# ++# Usage: include common.mk ++# ++# After including, you probably want to add a minimum_kver_check call ++# ++# Required Variables: ++# DRIVER ++# -- Set to the lowercase driver name ++ ++##################### ++# Helpful functions # ++##################### ++ ++readlink = $(shell readlink -f ${1}) ++ ++# helper functions for converting kernel version to version codes ++get_kver = $(or $(word ${2},$(subst ., ,${1})),0) ++get_kvercode = $(shell [ "${1}" -ge 0 -a "${1}" -le 255 2>/dev/null ] && \ ++ [ "${2}" -ge 0 -a "${2}" -le 255 2>/dev/null ] && \ ++ [ "${3}" -ge 0 -a "${3}" -le 255 2>/dev/null ] && \ ++ printf %d $$(( ( ${1} << 16 ) + ( ${2} << 8 ) + ( ${3} ) )) ) ++ ++################ ++# depmod Macro # ++################ ++ ++cmd_depmod = /sbin/depmod $(if ${SYSTEM_MAP_FILE},-e -F ${SYSTEM_MAP_FILE}) \ ++ $(if $(strip ${INSTALL_MOD_PATH}),-b ${INSTALL_MOD_PATH}) \ ++ -a ${KVER} ++ ++################ ++# dracut Macro # ++################ ++ ++cmd_initrd := $(shell \ ++ if which dracut > /dev/null 2>&1 ; then \ ++ echo "dracut --force"; \ ++ elif which update-initramfs > /dev/null 2>&1 ; then \ ++ echo "update-initramfs -u"; \ ++ fi ) ++ ++##################### ++# Environment tests # ++##################### ++ ++DRIVER_UPPERCASE := $(shell echo ${DRIVER} | tr "[:lower:]" "[:upper:]" ) ++ ++ifeq (,${BUILD_KERNEL}) ++BUILD_KERNEL=$(shell uname -r) ++endif ++ ++# Kernel Search Path ++# All the places we look for kernel source ++KSP := /lib/modules/${BUILD_KERNEL}/source \ ++ /lib/modules/${BUILD_KERNEL}/build \ ++ /usr/src/linux-${BUILD_KERNEL} \ ++ /usr/src/linux-$(${BUILD_KERNEL} | sed 's/-.*//') \ ++ /usr/src/kernel-headers-${BUILD_KERNEL} \ ++ /usr/src/kernel-source-${BUILD_KERNEL} \ ++ /usr/src/linux-$(${BUILD_KERNEL} | sed 's/\([0-9]*\.[0-9]*\)\..*/\1/') \ ++ /usr/src/linux \ ++ /usr/src/kernels/${BUILD_KERNEL} \ ++ /usr/src/kernels ++ ++# prune the list down to only values that exist and have an include/linux ++# sub-directory. We can't use include/config because some older kernels don't ++# have this. ++test_dir = $(shell [ -e ${dir}/include/linux ] && echo ${dir}) ++KSP := $(foreach dir, ${KSP}, ${test_dir}) ++ ++# we will use this first valid entry in the search path ++ifeq (,${KSRC}) ++ KSRC := $(firstword ${KSP}) ++endif ++ ++ifeq (,${KSRC}) ++ $(warning *** Kernel header files not in any of the expected locations.) ++ $(warning *** Install the appropriate kernel development package, e.g.) ++ $(error kernel-devel, for building kernel modules and try again) ++else ++ifeq (/lib/modules/${BUILD_KERNEL}/source, ${KSRC}) ++ KOBJ := /lib/modules/${BUILD_KERNEL}/build ++else ++ KOBJ := ${KSRC} ++endif ++endif ++ ++# Version file Search Path ++VSP := ${KOBJ}/include/generated/utsrelease.h \ ++ ${KOBJ}/include/linux/utsrelease.h \ ++ ${KOBJ}/include/linux/version.h \ ++ ${KOBJ}/include/generated/uapi/linux/version.h \ ++ /boot/vmlinuz.version.h ++ ++# Config file Search Path ++CSP := ${KOBJ}/include/generated/autoconf.h \ ++ ${KOBJ}/include/linux/autoconf.h \ ++ /boot/vmlinuz.autoconf.h ++ ++# System.map Search Path (for depmod) ++MSP := ${KSRC}/System.map \ ++ /boot/System.map-${BUILD_KERNEL} ++ ++# prune the lists down to only files that exist ++test_file = $(shell [ -f ${file} ] && echo ${file}) ++VSP := $(foreach file, ${VSP}, ${test_file}) ++CSP := $(foreach file, ${CSP}, ${test_file}) ++MSP := $(foreach file, ${MSP}, ${test_file}) ++ ++ ++# and use the first valid entry in the Search Paths ++ifeq (,${VERSION_FILE}) ++ VERSION_FILE := $(firstword ${VSP}) ++endif ++ ++ifeq (,${CONFIG_FILE}) ++ CONFIG_FILE := $(firstword ${CSP}) ++endif ++ ++ifeq (,${SYSTEM_MAP_FILE}) ++ SYSTEM_MAP_FILE := $(firstword ${MSP}) ++endif ++ ++ifeq (,$(wildcard ${VERSION_FILE})) ++ $(error Linux kernel source not configured - missing version header file) ++endif ++ ++ifeq (,$(wildcard ${CONFIG_FILE})) ++ $(error Linux kernel source not configured - missing autoconf.h) ++endif ++ ++ifeq (,$(wildcard ${SYSTEM_MAP_FILE})) ++ $(warning Missing System.map file - depmod will not check for missing symbols) ++endif ++ ++####################### ++# Linux Version Setup # ++####################### ++ ++# The following command line parameter is intended for development of KCOMPAT ++# against upstream kernels such as net-next which have broken or non-updated ++# version codes in their Makefile. They are intended for debugging and ++# development purpose only so that we can easily test new KCOMPAT early. If you ++# don't know what this means, you do not need to set this flag. There is no ++# arcane magic here. ++ ++# Convert LINUX_VERSION into LINUX_VERSION_CODE ++ifneq (${LINUX_VERSION},) ++ LINUX_VERSION_CODE=$(call get_kvercode,$(call get_kver,${LINUX_VERSION},1),$(call get_kver,${LINUX_VERSION},2),$(call get_kver,${LINUX_VERSION},3)) ++endif ++ ++# Honor LINUX_VERSION_CODE ++ifneq (${LINUX_VERSION_CODE},) ++ $(warning Forcing target kernel to build with LINUX_VERSION_CODE of ${LINUX_VERSION_CODE}$(if ${LINUX_VERSION}, from LINUX_VERSION=${LINUX_VERSION}). Do this at your own risk.) ++ KVER_CODE := ${LINUX_VERSION_CODE} ++ EXTRA_CFLAGS += -DLINUX_VERSION_CODE=${LINUX_VERSION_CODE} ++endif ++ ++# Determine SLE_LOCALVERSION_CODE for SuSE SLE >= 11 (needed by kcompat) ++# This assumes SuSE will continue setting CONFIG_LOCALVERSION to the string ++# appended to the stable kernel version on which their kernel is based with ++# additional versioning information (up to 3 numbers), a possible abbreviated ++# git SHA1 commit id and a kernel type, e.g. CONFIG_LOCALVERSION=-1.2.3-default ++# or CONFIG_LOCALVERSION=-999.gdeadbee-default ++ifeq (1,$(shell ${CC} -E -dM ${CONFIG_FILE} 2> /dev/null |\ ++ grep -m 1 CONFIG_SUSE_KERNEL | awk '{ print $$3 }')) ++ ++ifneq (10,$(shell ${CC} -E -dM ${CONFIG_FILE} 2> /dev/null |\ ++ grep -m 1 CONFIG_SLE_VERSION | awk '{ print $$3 }')) ++ ++ LOCALVERSION := $(shell ${CC} -E -dM ${CONFIG_FILE} 2> /dev/null |\ ++ grep -m 1 CONFIG_LOCALVERSION | awk '{ print $$3 }' |\ ++ cut -d'-' -f2 | sed 's/\.g[[:xdigit:]]\{7\}//') ++ LOCALVER_A := $(shell echo ${LOCALVERSION} | cut -d'.' -f1) ++ LOCALVER_B := $(shell echo ${LOCALVERSION} | cut -s -d'.' -f2) ++ LOCALVER_C := $(shell echo ${LOCALVERSION} | cut -s -d'.' -f3) ++ SLE_LOCALVERSION_CODE := $(shell expr ${LOCALVER_A} \* 65536 + \ ++ 0${LOCALVER_B} \* 256 + 0${LOCALVER_C}) ++ EXTRA_CFLAGS += -DSLE_LOCALVERSION_CODE=${SLE_LOCALVERSION_CODE} ++endif ++endif ++ ++EXTRA_CFLAGS += ${CFLAGS_EXTRA} ++ ++# get the kernel version - we use this to find the correct install path ++KVER := $(shell ${CC} ${EXTRA_CFLAGS} -E -dM ${VERSION_FILE} | grep UTS_RELEASE | \ ++ awk '{ print $$3 }' | sed 's/\"//g') ++ ++# assume source symlink is the same as build, otherwise adjust KOBJ ++ifneq (,$(wildcard /lib/modules/${KVER}/build)) ++ ifneq (${KSRC},$(call readlink,/lib/modules/${KVER}/build)) ++ KOBJ=/lib/modules/${KVER}/build ++ endif ++endif ++ ++ifeq (${KVER_CODE},) ++ KVER_CODE := $(shell ${CC} ${EXTRA_CFLAGS} -E -dM ${VSP} 2> /dev/null |\ ++ grep -m 1 LINUX_VERSION_CODE | awk '{ print $$3 }' | sed 's/\"//g') ++endif ++ ++# minimum_kver_check ++# ++# helper function to provide uniform output for different drivers to abort the ++# build based on kernel version check. Usage: "$(call minimum_kver_check,2,6,XX)". ++define _minimum_kver_check ++ifeq (0,$(shell [ ${KVER_CODE} -lt $(call get_kvercode,${1},${2},${3}) ]; echo "$$?")) ++ $$(warning *** Aborting the build.) ++ $$(error This driver is not supported on kernel versions older than ${1}.${2}.${3}) ++endif ++endef ++minimum_kver_check = $(eval $(call _minimum_kver_check,${1},${2},${3})) ++ ++################ ++# Manual Pages # ++################ ++ ++MANSECTION = 7 ++ ++ifeq (,${MANDIR}) ++ # find the best place to install the man page ++ MANPATH := $(shell (manpath 2>/dev/null || echo $MANPATH) | sed 's/:/ /g') ++ ifneq (,${MANPATH}) ++ # test based on inclusion in MANPATH ++ test_dir = $(findstring ${dir}, ${MANPATH}) ++ else ++ # no MANPATH, test based on directory existence ++ test_dir = $(shell [ -e ${dir} ] && echo ${dir}) ++ endif ++ # our preferred install path ++ # should /usr/local/man be in here ? ++ MANDIR := /usr/share/man /usr/man ++ MANDIR := $(foreach dir, ${MANDIR}, ${test_dir}) ++ MANDIR := $(firstword ${MANDIR}) ++endif ++ifeq (,${MANDIR}) ++ # fallback to /usr/man ++ MANDIR := /usr/man ++endif ++ ++#################### ++# CCFLAGS variable # ++#################### ++ ++# set correct CCFLAGS variable for kernels older than 2.6.24 ++ifeq (0,$(shell [ ${KVER_CODE} -lt $(call get_kvercode,2,6,24) ]; echo $$?)) ++CCFLAGS_VAR := EXTRA_CFLAGS ++else ++CCFLAGS_VAR := ccflags-y ++endif ++ ++################# ++# KBUILD_OUTPUT # ++################# ++ ++# Only set KBUILD_OUTPUT if KOBJ differs from KSRC ++ifneq (${KSRC},${KOBJ}) ++export KBUILD_OUTPUT ?= ${KOBJ} ++endif ++ ++############################ ++# Module Install Directory # ++############################ ++ ++# Default to using updates/security/integrity/ path, since depmod since ++# v3.1 defaults to checking updates folder first, and only checking kernels/ ++# and extra afterwards. We use updates instead of kernel/* due to desire to ++# prevent over-writing built-in modules files. ++export INSTALL_MOD_DIR ?= updates/security/integrity/ ++ ++ ++###################### ++# Kernel Build Macro # ++###################### ++ ++# kernel build function ++# ${1} is the kernel build target ++# ${2} may contain any extra rules to pass directly to the sub-make process ++# ++# This function is expected to be executed by ++# @+$(call kernelbuild,,) ++# from within a Makefile recipe. ++# ++# The following variables are expected to be defined for its use: ++# GCC_I_SYS -- if set it will enable use of gcc-i-sys.sh wrapper to use -isystem ++# CCFLAGS_VAR -- the CCFLAGS variable to set extra CFLAGS ++# EXTRA_CFLAGS -- a set of extra CFLAGS to pass into the ccflags-y variable ++# KSRC -- the location of the kernel source tree to build against ++# DRIVER_UPPERCASE -- the uppercase name of the kernel module, set from DRIVER ++# ++# N.B: We specify all of our hash, template and PCR choices ++# right when we build the option. This is because the kernel module ++# will be signed, and we will prevent users from modifying these ++# options at runtime and reloading the module ++kernelbuild = ${MAKE} $(if ${GCC_I_SYS},CC="${GCC_I_SYS}") \ ++ ${CCFLAGS_VAR}="${EXTRA_CFLAGS}" \ ++ -C "${KSRC}" \ ++ CONFIG_INTEGRITY=m \ ++ CONFIG_INTEGRITY_AUDIT=y \ ++ CONFIG_INTEGRITY_SIGNATURE=y \ ++ CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y \ ++ CONFIG_IMA=m \ ++ CONFIG_${DRIVER_UPPERCASE}=m \ ++ modules \ ++ M="${CURDIR}" \ ++ ${2} ${1} +diff --git a/digsig.c b/digsig.c +index 106e855..f850ef7 100644 +--- a/digsig.c ++++ b/digsig.c +@@ -37,9 +37,9 @@ static const char *keyring_name[INTEGRITY_KEYRING_MAX] = { + }; + + #ifdef CONFIG_INTEGRITY_TRUSTED_KEYRING +-static bool init_keyring __initdata = true; ++static bool init_keyring = true; + #else +-static bool init_keyring __initdata; ++static bool init_keyring; + #endif + + #ifdef CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY +@@ -77,32 +77,43 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, + + return -EOPNOTSUPP; + } ++EXPORT_SYMBOL_GPL(integrity_digsig_verify); + +-int __init integrity_init_keyring(const unsigned int id) ++int integrity_init_keyring(const unsigned int id) + { + const struct cred *cred = current_cred(); + int err = 0; + +- if (!init_keyring) ++ if (!init_keyring) { ++ /* WRS: This external keyring is created inside ++ * the Kernel as a trusted keyring for which ++ * a search reference is available ++ */ ++ keyring[id] = ima_keyring; + return 0; ++ } + + keyring[id] = keyring_alloc(keyring_name[id], KUIDT_INIT(0), +- KGIDT_INIT(0), cred, +- ((KEY_POS_ALL & ~KEY_POS_SETATTR) | +- KEY_USR_VIEW | KEY_USR_READ | +- KEY_USR_WRITE | KEY_USR_SEARCH), +- KEY_ALLOC_NOT_IN_QUOTA, +- restrict_link_to_ima, NULL); +- if (IS_ERR(keyring[id])) { ++ KGIDT_INIT(0), cred, ++ ((KEY_POS_ALL & ~KEY_POS_SETATTR) | ++ KEY_USR_VIEW | KEY_USR_READ | ++ KEY_USR_WRITE | KEY_USR_SEARCH), ++ KEY_ALLOC_NOT_IN_QUOTA, NULL); ++ ++ if (!IS_ERR(keyring[id])) ++ set_bit(KEY_FLAG_TRUSTED_ONLY, &keyring[id]->flags); ++ else { + err = PTR_ERR(keyring[id]); + pr_info("Can't allocate %s keyring (%d)\n", + keyring_name[id], err); + keyring[id] = NULL; + } ++ init_keyring = false; + return err; + } ++EXPORT_SYMBOL_GPL(integrity_init_keyring); + +-int __init integrity_load_x509(const unsigned int id, const char *path) ++int integrity_load_x509(const unsigned int id, const char *path) + { + key_ref_t key; + char *data; +diff --git a/digsig_asymmetric.c b/digsig_asymmetric.c +index 80052ed..1753b60 100644 +--- a/digsig_asymmetric.c ++++ b/digsig_asymmetric.c +@@ -34,6 +34,7 @@ static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid) + + pr_debug("key search: \"%s\"\n", name); + ++#ifdef CONFIG_IMA_MOK_KEYRING + key = get_ima_blacklist_keyring(); + if (key) { + key_ref_t kref; +@@ -45,6 +46,7 @@ static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid) + return ERR_PTR(-EKEYREJECTED); + } + } ++#endif + + if (keyring) { + /* search in specific keyring */ +@@ -95,7 +97,11 @@ int asymmetric_verify(struct key *keyring, const char *sig, + if (siglen != __be16_to_cpu(hdr->sig_size)) + return -EBADMSG; + ++#if ( LINUX_VERSION_CODE <= KERNEL_VERSION(3,10,0) ) ++ if (hdr->hash_algo >= PKEY_HASH__LAST) ++#else + if (hdr->hash_algo >= HASH_ALGO__LAST) ++#endif + return -ENOPKG; + + key = request_asymmetric_key(keyring, __be32_to_cpu(hdr->keyid)); +@@ -103,14 +109,24 @@ int asymmetric_verify(struct key *keyring, const char *sig, + return PTR_ERR(key); + + memset(&pks, 0, sizeof(pks)); +- +- pks.pkey_algo = "rsa"; +- pks.hash_algo = hash_algo_name[hdr->hash_algo]; ++ + pks.digest = (u8 *)data; + pks.digest_size = datalen; ++#if ( LINUX_VERSION_CODE <= KERNEL_VERSION(3,10,0) ) ++ pks.pkey_algo = PKEY_ALGO_RSA; ++ pks.pkey_hash_algo = hdr->hash_algo; ++ pks.nr_mpi =1; ++ pks.rsa.s = mpi_read_raw_data(hdr->sig, siglen); ++ if(pks.rsa.s) ++ ret = verify_signature(key, &pks); ++ mpi_free(pks.rsa.s); ++#else ++ pks.pkey_algo = "rsa"; ++ pks.hash_algo = hash_algo_name[hdr->hash_algo]; + pks.s = hdr->sig; + pks.s_size = siglen; + ret = verify_signature(key, &pks); ++#endif + key_put(key); + pr_debug("%s() = %d\n", __func__, ret); + return ret; +diff --git a/iint.c b/iint.c +index c710d22..83405a1 100644 +--- a/iint.c ++++ b/iint.c +@@ -27,6 +27,9 @@ static struct rb_root integrity_iint_tree = RB_ROOT; + static DEFINE_RWLOCK(integrity_iint_lock); + static struct kmem_cache *iint_cache __read_mostly; + ++static struct integrity_iint_cache * (*integrity_inode_get_kernel)(struct inode *); ++static void (*integrity_inode_free_kernel)(struct inode *); ++ + /* + * __integrity_iint_find - return the iint associated with an inode + */ +@@ -67,6 +70,7 @@ struct integrity_iint_cache *integrity_iint_find(struct inode *inode) + + return iint; + } ++EXPORT_SYMBOL_GPL(integrity_iint_find); + + static void iint_free(struct integrity_iint_cache *iint) + { +@@ -90,7 +94,7 @@ static void iint_free(struct integrity_iint_cache *iint) + * + * Caller must lock i_mutex + */ +-struct integrity_iint_cache *integrity_inode_get(struct inode *inode) ++static struct integrity_iint_cache *__integrity_inode_get(struct inode *inode) + { + struct rb_node **p; + struct rb_node *node, *parent = NULL; +@@ -100,7 +104,7 @@ struct integrity_iint_cache *integrity_inode_get(struct inode *inode) + if (iint) + return iint; + +- iint = kmem_cache_alloc(iint_cache, GFP_NOFS); ++ iint = kmem_cache_alloc(iint_cache, GFP_KERNEL); + if (!iint) + return NULL; + +@@ -110,7 +114,7 @@ struct integrity_iint_cache *integrity_inode_get(struct inode *inode) + while (*p) { + parent = *p; + test_iint = rb_entry(parent, struct integrity_iint_cache, +- rb_node); ++ rb_node); + if (inode < test_iint->inode) + p = &(*p)->rb_left; + else +@@ -133,7 +137,7 @@ struct integrity_iint_cache *integrity_inode_get(struct inode *inode) + * + * Free the integrity information(iint) associated with an inode. + */ +-void integrity_inode_free(struct inode *inode) ++static void __integrity_inode_free(struct inode *inode) + { + struct integrity_iint_cache *iint; + +@@ -166,8 +170,21 @@ static void init_once(void *foo) + static int __init integrity_iintcache_init(void) + { + iint_cache = +- kmem_cache_create("iint_cache", sizeof(struct integrity_iint_cache), +- 0, SLAB_PANIC, init_once); ++ kmem_cache_create("iint_cache", sizeof(struct integrity_iint_cache), ++ 0, SLAB_PANIC, init_once); ++ ++ /* ++ * stow away original Kernel references ++ * for these functions to assign back ++ * on deinit ++ */ ++ integrity_inode_get_kernel = integrity_inode_get; ++ integrity_inode_free_kernel = integrity_inode_free; ++ ++ integrity_inode_get = &__integrity_inode_get; ++ integrity_inode_free = &__integrity_inode_free; ++ pr_info("Initializing Integrity Base Module\n"); ++ + return 0; + } + security_initcall(integrity_iintcache_init); +@@ -186,18 +203,22 @@ int integrity_kernel_read(struct file *file, loff_t offset, + { + mm_segment_t old_fs; + char __user *buf = (char __user *)addr; +- ssize_t ret; ++ ssize_t ret = -EINVAL; + + if (!(file->f_mode & FMODE_READ)) + return -EBADF; + + old_fs = get_fs(); + set_fs(get_ds()); +- ret = __vfs_read(file, buf, count, &offset); ++ if (file->f_op->read) ++ ret = file->f_op->read(file, buf, count, &offset); ++ else if (file->f_op->aio_read) ++ ret = do_sync_read(file, buf, count, &offset); + set_fs(old_fs); + + return ret; + } ++EXPORT_SYMBOL_GPL(integrity_kernel_read); + + /* + * integrity_read_file - read entire file content into the buffer +@@ -259,3 +280,18 @@ void __init integrity_load_keys(void) + ima_load_x509(); + evm_load_x509(); + } ++ ++static void __exit cleanup_integrity(void) ++{ ++ /* ++ * assign back to default kernel definations ++ * for these dynamic functions ++ */ ++ integrity_inode_get = integrity_inode_get_kernel; ++ integrity_inode_free = integrity_inode_free_kernel; ++} ++ ++module_exit(cleanup_integrity); ++MODULE_DESCRIPTION("Integrity Base Driver"); ++MODULE_LICENSE("GPL"); ++ +diff --git a/ima/Makefile b/ima/Makefile +index 29f198b..cdf918c 100644 +--- a/ima/Makefile ++++ b/ima/Makefile +@@ -6,7 +6,7 @@ + obj-$(CONFIG_IMA) += ima.o + + ima-y := ima_fs.o ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o \ +- ima_policy.o ima_template.o ima_template_lib.o +-ima-$(CONFIG_IMA_APPRAISE) += ima_appraise.o +-ima-$(CONFIG_HAVE_IMA_KEXEC) += ima_kexec.o +-obj-$(CONFIG_IMA_BLACKLIST_KEYRING) += ima_mok.o ++ ima_policy.o ima_template.o ima_template_lib.o ima_appraise.o ++#ima-$(CONFIG_IMA_APPRAISE) += ima_appraise.o ++#ima-$(CONFIG_HAVE_IMA_KEXEC) += ima_kexec.o ++#obj-$(CONFIG_IMA_BLACKLIST_KEYRING) += ima_mok.o +diff --git a/ima/ima.h b/ima/ima.h +index b563fbd..5492dda 100644 +--- a/ima/ima.h ++++ b/ima/ima.h +@@ -17,6 +17,9 @@ + #ifndef __LINUX_IMA_H + #define __LINUX_IMA_H + ++// include kcompat layer ++#include "../kcompat.h" ++ + #include + #include + #include +@@ -155,6 +158,7 @@ unsigned long ima_get_binary_runtime_size(void); + int ima_init_template(void); + void ima_init_template_list(void); + ++ + /* + * used to protect h_table and sha_table + */ +@@ -242,7 +246,10 @@ enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value, + int xattr_len); + int ima_read_xattr(struct dentry *dentry, + struct evm_ima_xattr_data **xattr_value); +- ++void __ima_inode_post_setattr(struct dentry *dentry); ++int __ima_inode_setxattr(struct dentry *dentry, const char *xattr_name, ++ const void *xattr_value, size_t xattr_value_len); ++int __ima_inode_removexattr(struct dentry *dentry, const char *xattr_name); + #else + static inline int ima_appraise_measurement(enum ima_hooks func, + struct integrity_iint_cache *iint, +diff --git a/ima/ima_api.c b/ima/ima_api.c +index c2edba8..e14e9d0 100644 +--- a/ima/ima_api.c ++++ b/ima/ima_api.c +@@ -307,11 +307,9 @@ void ima_audit_measurement(struct integrity_iint_cache *iint, + if (!ab) + return; + +- audit_log_format(ab, "file="); +- audit_log_untrustedstring(ab, filename); +- audit_log_format(ab, " hash="); ++ audit_log_format(ab, "file=%s", filename); + snprintf(algo_hash, sizeof(algo_hash), "%s:%s", algo_name, hash); +- audit_log_untrustedstring(ab, algo_hash); ++ audit_log_format(ab, " hash=%s", algo_hash); + + audit_log_task_info(ab, current); + audit_log_end(ab); +@@ -332,12 +330,12 @@ void ima_audit_measurement(struct integrity_iint_cache *iint, + const char *ima_d_path(const struct path *path, char **pathbuf, char *namebuf) + { + char *pathname = NULL; +- +- *pathbuf = __getname(); ++ /* We will allow 11 spaces for ' (deleted)' to be appended */ ++ *pathbuf = kmalloc(PATH_MAX + 11, GFP_KERNEL); + if (*pathbuf) { +- pathname = d_absolute_path(path, *pathbuf, PATH_MAX); ++ pathname = d_path(path, *pathbuf, PATH_MAX + 11); + if (IS_ERR(pathname)) { +- __putname(*pathbuf); ++ kfree(*pathbuf); + *pathbuf = NULL; + pathname = NULL; + } +diff --git a/ima/ima_appraise.c b/ima/ima_appraise.c +index 1fd9539..b0d4286 100644 +--- a/ima/ima_appraise.c ++++ b/ima/ima_appraise.c +@@ -8,6 +8,9 @@ + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + */ ++ ++#include "../kcompat.h" ++ + #include + #include + #include +@@ -58,10 +61,10 @@ static int ima_fix_xattr(struct dentry *dentry, + iint->ima_hash->xattr.ng.type = IMA_XATTR_DIGEST_NG; + iint->ima_hash->xattr.ng.algo = algo; + } +- rc = __vfs_setxattr_noperm(dentry, XATTR_NAME_IMA, +- &iint->ima_hash->xattr.data[offset], +- (sizeof(iint->ima_hash->xattr) - offset) + +- iint->ima_hash->length, 0); ++ rc = vfs_setxattr(dentry, XATTR_NAME_IMA, ++ &iint->ima_hash->xattr.data[offset], ++ (sizeof(iint->ima_hash->xattr) - offset) + ++ iint->ima_hash->length, 0); + return rc; + } + +@@ -168,14 +171,14 @@ enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value, + int ima_read_xattr(struct dentry *dentry, + struct evm_ima_xattr_data **xattr_value) + { +- ssize_t ret; ++ struct inode *inode = d_backing_inode(dentry); ++ if (!inode->i_op->getxattr) ++ return 0; + +- ret = vfs_getxattr_alloc(dentry, XATTR_NAME_IMA, (char **)xattr_value, +- 0, GFP_NOFS); +- if (ret == -EOPNOTSUPP) +- ret = 0; +- return ret; ++ return vfs_getxattr_alloc(dentry, XATTR_NAME_IMA, (char **)xattr_value, ++ 0, GFP_NOFS); + } ++EXPORT_SYMBOL_GPL(ima_read_xattr); + + /* + * ima_appraise_measurement - appraise file measurement +@@ -198,7 +201,7 @@ int ima_appraise_measurement(enum ima_hooks func, + enum integrity_status status = INTEGRITY_UNKNOWN; + int rc = xattr_len, hash_start = 0; + +- if (!(inode->i_opflags & IOP_XATTR)) ++ if (!inode->i_op->getxattr) + return INTEGRITY_UNKNOWN; + + if (rc <= 0) { +@@ -214,7 +217,11 @@ int ima_appraise_measurement(enum ima_hooks func, + goto out; + } + ++#ifdef CONFIG_EVM + status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_value, rc, iint); ++#else ++ status = INTEGRITY_UNKNOWN; /* CONFIG_INTEGRITY */ ++#endif + if ((status != INTEGRITY_PASS) && (status != INTEGRITY_UNKNOWN)) { + if ((status == INTEGRITY_NOLABEL) + || (status == INTEGRITY_NOXATTRS)) +@@ -321,14 +328,14 @@ void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file) + * This function is called from notify_change(), which expects the caller + * to lock the inode's i_mutex. + */ +-void ima_inode_post_setattr(struct dentry *dentry) ++void __ima_inode_post_setattr(struct dentry *dentry) + { + struct inode *inode = d_backing_inode(dentry); + struct integrity_iint_cache *iint; +- int must_appraise; ++ int must_appraise, rc; + + if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode) +- || !(inode->i_opflags & IOP_XATTR)) ++ || !inode->i_op->removexattr) + return; + + must_appraise = ima_must_appraise(inode, MAY_ACCESS, POST_SETATTR); +@@ -341,7 +348,8 @@ void ima_inode_post_setattr(struct dentry *dentry) + iint->flags |= IMA_APPRAISE; + } + if (!must_appraise) +- __vfs_removexattr(dentry, XATTR_NAME_IMA); ++ rc = inode->i_op->removexattr(dentry, XATTR_NAME_IMA); ++ return; + } + + /* +@@ -378,7 +386,7 @@ static void ima_reset_appraise_flags(struct inode *inode, int digsig) + return; + } + +-int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name, ++int __ima_inode_setxattr(struct dentry *dentry, const char *xattr_name, + const void *xattr_value, size_t xattr_value_len) + { + const struct evm_ima_xattr_data *xvalue = xattr_value; +@@ -396,7 +404,7 @@ int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name, + return result; + } + +-int ima_inode_removexattr(struct dentry *dentry, const char *xattr_name) ++int __ima_inode_removexattr(struct dentry *dentry, const char *xattr_name) + { + int result; + +diff --git a/ima/ima_fs.c b/ima/ima_fs.c +index ca303e5..e871955 100644 +--- a/ima/ima_fs.c ++++ b/ima/ima_fs.c +@@ -274,6 +274,9 @@ static const struct file_operations ima_ascii_measurements_ops = { + + static ssize_t ima_read_policy(char *path) + { ++#if ( LINUX_VERSION_CODE <= KERNEL_VERSION(3,10,0) ) ++ return -EINVAL; ++#else + void *data; + char *datap; + loff_t size; +@@ -307,6 +310,7 @@ static ssize_t ima_read_policy(char *path) + return -EINVAL; + else + return pathlen; ++#endif + } + + static ssize_t ima_write_policy(struct file *file, const char __user *buf, +diff --git a/ima/ima_init.c b/ima/ima_init.c +index 2967d49..0759c8c 100644 +--- a/ima/ima_init.c ++++ b/ima/ima_init.c +@@ -117,7 +117,9 @@ int __init ima_init(void) + if (!ima_used_chip) + pr_info("No TPM chip found, activating TPM-bypass! (rc=%d)\n", + rc); +- ++ else ++ pr_info("TPM chip found, using TPM for aggregate measurements!\n"); ++ + rc = integrity_init_keyring(INTEGRITY_KEYRING_IMA); + if (rc) + return rc; +diff --git a/ima/ima_main.c b/ima/ima_main.c +index 2aebb79..5d6ba23 100644 +--- a/ima/ima_main.c ++++ b/ima/ima_main.c +@@ -16,6 +16,10 @@ + * implements the IMA hooks: ima_bprm_check, ima_file_mmap, + * and ima_file_check. + */ ++ ++// include kcompat layer ++#include "../kcompat.h" ++ + #include + #include + #include +@@ -30,7 +34,10 @@ + int ima_initialized; + + #ifdef CONFIG_IMA_APPRAISE +-int ima_appraise = IMA_APPRAISE_ENFORCE; ++/* ++ * WRS: Set default appraise action as "log" ++ */ ++int ima_appraise = IMA_APPRAISE_LOG; + #else + int ima_appraise; + #endif +@@ -140,7 +147,7 @@ static void ima_check_last_writer(struct integrity_iint_cache *iint, + * + * Flag files that changed, based on i_version + */ +-void ima_file_free(struct file *file) ++static void __ima_file_free(struct file *file) + { + struct inode *inode = file_inode(file); + struct integrity_iint_cache *iint; +@@ -259,8 +266,7 @@ out_digsig: + rc = -EACCES; + kfree(xattr_value); + out_free: +- if (pathbuf) +- __putname(pathbuf); ++ kfree(pathbuf); + out: + inode_unlock(inode); + if ((rc && must_appraise) && (ima_appraise & IMA_APPRAISE_ENFORCE)) +@@ -279,7 +285,7 @@ out: + * On success return 0. On integrity appraisal error, assuming the file + * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. + */ +-int ima_file_mmap(struct file *file, unsigned long prot) ++static int __ima_file_mmap(struct file *file, unsigned long prot) + { + if (file && (prot & PROT_EXEC)) + return process_measurement(file, NULL, 0, MAY_EXEC, +@@ -300,7 +306,7 @@ int ima_file_mmap(struct file *file, unsigned long prot) + * On success return 0. On integrity appraisal error, assuming the file + * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. + */ +-int ima_bprm_check(struct linux_binprm *bprm) ++static int __ima_bprm_check(struct linux_binprm *bprm) + { + return process_measurement(bprm->file, NULL, 0, MAY_EXEC, + BPRM_CHECK, 0); +@@ -316,13 +322,12 @@ int ima_bprm_check(struct linux_binprm *bprm) + * On success return 0. On integrity appraisal error, assuming the file + * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. + */ +-int ima_file_check(struct file *file, int mask, int opened) ++static int __ima_file_check(struct file *file, int mask, int opened) + { + return process_measurement(file, NULL, 0, + mask & (MAY_READ | MAY_WRITE | MAY_EXEC | + MAY_APPEND), FILE_CHECK, opened); + } +-EXPORT_SYMBOL_GPL(ima_file_check); + + /** + * ima_post_path_mknod - mark as a new inode +@@ -346,6 +351,7 @@ void ima_post_path_mknod(struct dentry *dentry) + iint->flags |= IMA_NEW_FILE; + } + ++#if ( LINUX_VERSION_CODE > KERNEL_VERSION(3,10,0) ) + /** + * ima_read_file - pre-measure/appraise hook decision based on policy + * @file: pointer to the file to be measured/appraised/audit +@@ -415,10 +421,28 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size, + func = read_idmap[read_id] ?: FILE_CHECK; + return process_measurement(file, buf, size, MAY_READ, func, 0); + } ++#endif + + static int __init init_ima(void) + { + int error; ++ ++ /* ++ * On loading the module, map the kernel inline ++ * function calls (used by the FS layer) to ++ * function definations within the module. ++ * ++ * N.B: No specific unmapping (to Kernel default) ++ * required as IMA module cannot be removed (even forcebly), ++ * once it binds to the Kernel VFS layer ++ */ ++ ima_bprm_check = &__ima_bprm_check; ++ ima_file_check = &__ima_file_check; ++ ima_file_free = &__ima_file_free; ++ ima_file_mmap = &__ima_file_mmap; ++ ima_inode_post_setattr = &__ima_inode_post_setattr; ++ ima_inode_setxattr = &__ima_inode_setxattr; ++ ima_inode_removexattr = &__ima_inode_removexattr; + + ima_init_template_list(); + hash_setup(CONFIG_IMA_DEFAULT_HASH); +diff --git a/ima/ima_policy.c b/ima/ima_policy.c +index aed47b7..dd52d98 100644 +--- a/ima/ima_policy.c ++++ b/ima/ima_policy.c +@@ -92,9 +92,11 @@ static struct ima_rule_entry dont_measure_rules[] = { + {.action = DONT_MEASURE, .fsmagic = BINFMTFS_MAGIC, .flags = IMA_FSMAGIC}, + {.action = DONT_MEASURE, .fsmagic = SECURITYFS_MAGIC, .flags = IMA_FSMAGIC}, + {.action = DONT_MEASURE, .fsmagic = SELINUX_MAGIC, .flags = IMA_FSMAGIC}, ++#if ( LINUX_VERSION_CODE > KERNEL_VERSION(3,10,0) ) ++ {.action = DONT_MEASURE, .fsmagic = NSFS_MAGIC, .flags = IMA_FSMAGIC}, ++#endif + {.action = DONT_MEASURE, .fsmagic = CGROUP_SUPER_MAGIC, +- .flags = IMA_FSMAGIC}, +- {.action = DONT_MEASURE, .fsmagic = NSFS_MAGIC, .flags = IMA_FSMAGIC} ++ .flags = IMA_FSMAGIC} + }; + + static struct ima_rule_entry original_measurement_rules[] = { +@@ -132,7 +134,9 @@ static struct ima_rule_entry default_appraise_rules[] = { + {.action = DONT_APPRAISE, .fsmagic = BINFMTFS_MAGIC, .flags = IMA_FSMAGIC}, + {.action = DONT_APPRAISE, .fsmagic = SECURITYFS_MAGIC, .flags = IMA_FSMAGIC}, + {.action = DONT_APPRAISE, .fsmagic = SELINUX_MAGIC, .flags = IMA_FSMAGIC}, ++#if ( LINUX_VERSION_CODE > KERNEL_VERSION(3,10,0) ) + {.action = DONT_APPRAISE, .fsmagic = NSFS_MAGIC, .flags = IMA_FSMAGIC}, ++#endif + {.action = DONT_APPRAISE, .fsmagic = CGROUP_SUPER_MAGIC, .flags = IMA_FSMAGIC}, + #ifdef CONFIG_IMA_WRITE_POLICY + {.action = APPRAISE, .func = POLICY_CHECK, +@@ -243,7 +247,11 @@ static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode, + if ((rule->flags & IMA_UID) && !uid_eq(rule->uid, cred->uid)) + return false; + if (rule->flags & IMA_EUID) { ++#if ( LINUX_VERSION_CODE > KERNEL_VERSION(3,10,0) ) + if (has_capability_noaudit(current, CAP_SETUID)) { ++#else ++ if (capable_wrt_inode_uidgid(inode, CAP_SETUID) || capable(CAP_SETUID)) { ++#endif + if (!uid_eq(rule->uid, cred->euid) + && !uid_eq(rule->uid, cred->suid) + && !uid_eq(rule->uid, cred->uid)) +@@ -541,10 +549,26 @@ static int ima_lsm_rule_init(struct ima_rule_entry *entry, + return result; + } + ++static int ima_string_contains_hex(const char *string, size_t len) ++{ ++ const unsigned char *p; ++ for (p = string; p < (const unsigned char *)string + len; p++) { ++ if (*p == '"' || *p < 0x21 || *p > 0x7e) ++ return 1; ++ } ++ return 0; ++} ++ ++ + static void ima_log_string(struct audit_buffer *ab, char *key, char *value) + { +- audit_log_format(ab, "%s=", key); +- audit_log_untrustedstring(ab, value); ++ if (ima_string_contains_hex(value, strlen(value))) { ++ // value string contains hex. Convert to hex instead ++ audit_log_format(ab, "%s=(contains hex)%s", key, value); ++ } ++ else { ++ audit_log_format(ab, "%s=%s", key, value); ++ } + audit_log_format(ab, " "); + } + +diff --git a/integrity.h b/integrity.h +index 24520b4..c13e61d 100644 +--- a/integrity.h ++++ b/integrity.h +@@ -16,6 +16,8 @@ + #include + #include + ++#include "kcompat.h" ++ + /* iint action cache flags */ + #define IMA_MEASURE 0x00000001 + #define IMA_MEASURED 0x00000002 +@@ -91,7 +93,7 @@ struct ima_digest_data { + struct signature_v2_hdr { + uint8_t type; /* xattr type */ + uint8_t version; /* signature format version */ +- uint8_t hash_algo; /* Digest algorithm [enum hash_algo] */ ++ uint8_t hash_algo; /* Digest algorithm [enum pkey_hash_algo] */ + uint32_t keyid; /* IMA key identifier - not X509/PGP specific */ + uint16_t sig_size; /* signature size */ + uint8_t sig[0]; /* signature payload */ +@@ -127,12 +129,11 @@ int __init integrity_read_file(const char *path, char **data); + #define INTEGRITY_KEYRING_MAX 3 + + #ifdef CONFIG_INTEGRITY_SIGNATURE +- + int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, + const char *digest, int digestlen); + +-int __init integrity_init_keyring(const unsigned int id); +-int __init integrity_load_x509(const unsigned int id, const char *path); ++int integrity_init_keyring(const unsigned int id); ++int integrity_load_x509(const unsigned int id, const char *path); + #else + + static inline int integrity_digsig_verify(const unsigned int id, +diff --git a/integrity_audit.c b/integrity_audit.c +index 90987d1..ba5e532 100644 +--- a/integrity_audit.c ++++ b/integrity_audit.c +@@ -10,6 +10,7 @@ + * Audit calls for the integrity subsystem + */ + ++#include "kcompat.h" + #include + #include + #include +@@ -45,21 +46,17 @@ void integrity_audit_msg(int audit_msgno, struct inode *inode, + from_kuid(&init_user_ns, audit_get_loginuid(current)), + audit_get_sessionid(current)); + audit_log_task_context(ab); +- audit_log_format(ab, " op="); +- audit_log_string(ab, op); +- audit_log_format(ab, " cause="); +- audit_log_string(ab, cause); +- audit_log_format(ab, " comm="); +- audit_log_untrustedstring(ab, get_task_comm(name, current)); ++ audit_log_format(ab, " op=\"%s\"", op); ++ audit_log_format(ab, " cause=\"%s\"", cause); ++ audit_log_format(ab, " comm=%s", get_task_comm(name, current)); + if (fname) { +- audit_log_format(ab, " name="); +- audit_log_untrustedstring(ab, fname); ++ audit_log_format(ab, " name=%s", fname); + } + if (inode) { +- audit_log_format(ab, " dev="); +- audit_log_untrustedstring(ab, inode->i_sb->s_id); ++ audit_log_format(ab, " dev=%s", inode->i_sb->s_id); + audit_log_format(ab, " ino=%lu", inode->i_ino); + } + audit_log_format(ab, " res=%d", !result); + audit_log_end(ab); + } ++EXPORT_SYMBOL_GPL(integrity_audit_msg); +diff --git a/kcompat.h b/kcompat.h +new file mode 100644 +index 0000000..936b76c +--- /dev/null ++++ b/kcompat.h +@@ -0,0 +1,34 @@ ++#ifndef _KCOMPAT_H_ ++#define _KCOMPAT_H_ ++ ++#ifndef LINUX_VERSION_CODE ++#include ++#else ++#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) ++#endif ++ ++#if ( LINUX_VERSION_CODE <= KERNEL_VERSION(3,10,0) ) ++ ++/* kcompat definitions */ ++#define CONFIG_TCG_TPM_MODULE 1 ++ ++#define CONFIG_IMA 1 ++#define CONFIG_IMA_APPRAISE_SIGNED_INIT 1 ++#define CONFIG_IMA_APPRAISE 1 ++#define CONFIG_IMA_DEFAULT_HASH "sha256" ++#define CONFIG_IMA_MEASURE_PCR_IDX 10 ++#define CONFIG_IMA_DEFAULT_TEMPLATE "ima-sig" ++#define CONFIG_INTEGRITY 1 ++#define CONFIG_INTEGRITY_AUDIT 1 ++#define CONFIG_INTEGRITY_ASYMMETRIC_KEYS 1 ++#define CONFIG_INTEGRITY_SIGNATURE 1 ++#define CONFIG_CRYPTO_RSA 1 ++ ++#define __GFP_RECLAIM __GFP_WAIT ++ ++#define inode_lock(_node) mutex_lock(&_node->i_mutex) ++#define inode_unlock(_node) mutex_unlock(&_node->i_mutex) ++ ++ ++#endif ++#endif +-- +1.8.3.1 + diff --git a/kernel/kernel-modules/integrity/patches/0002-integrity-expose-module-params.patch b/kernel/kernel-modules/integrity/patches/0002-integrity-expose-module-params.patch new file mode 100644 index 000000000..c35ab833d --- /dev/null +++ b/kernel/kernel-modules/integrity/patches/0002-integrity-expose-module-params.patch @@ -0,0 +1,156 @@ +From 6d0d8278d37b3874e0b272a6d01663fbfc91cdcb Mon Sep 17 00:00:00 2001 +From: Kam Nasim +Date: Fri, 22 Sep 2017 14:19:39 -0400 +Subject: [PATCH] US103091: IMA: System Configuration + +Expose integrity_audit and ima_appraise (which were only available +as boot parameters), as Module parameters since it is perceived that +customers would want to tune these at runtime. The integrity_audit +parameter can be toggled at runtime, however the ima_appraise modparam +will require a node reboot inorder to change appraise type. + +In addition we introduce a new module param to disable IMA-TPM +interactions. Ths is tunable at runtime. +--- + ima/ima_appraise.c | 47 +++++++++++++++++++++++++++++++++++++++++++++-- + ima/ima_init.c | 18 ++++++++++++------ + integrity_audit.c | 2 ++ + kcompat.h | 4 ++++ + 4 files changed, 63 insertions(+), 8 deletions(-) + +diff --git a/ima/ima_appraise.c b/ima/ima_appraise.c +index b0d4286..88b5091 100644 +--- a/ima/ima_appraise.c ++++ b/ima/ima_appraise.c +@@ -21,7 +21,21 @@ + + #include "ima.h" + +-static int __init default_appraise_setup(char *str) ++static char *ima_appraise_param = "log"; ++static int ima_appraise_param_set(const char *, ++ const struct kernel_param *); ++static struct kernel_param_ops ima_appraise_param_ops = { ++ .set = ima_appraise_param_set, ++ .get = param_get_charp, ++}; ++module_param_cb(ima_appraise_param, &ima_appraise_param_ops, ++ &ima_appraise_param, 0444); ++MODULE_PARM_DESC(ima_appraise_param, ++ "IMA appraise type " \ ++ "{ \"off\" | \"enforce\" | \"fix\" | \"log\" }" \ ++ "(default: log)."); ++ ++static int default_appraise_setup(char *str) + { + if (strncmp(str, "off", 3) == 0) + ima_appraise = 0; +@@ -29,11 +43,40 @@ static int __init default_appraise_setup(char *str) + ima_appraise = IMA_APPRAISE_LOG; + else if (strncmp(str, "fix", 3) == 0) + ima_appraise = IMA_APPRAISE_FIX; +- return 1; ++ else if (strncmp(str, "enforce", 7) == 0) ++ ima_appraise = IMA_APPRAISE_ENFORCE; ++ else { ++ return -1; ++ } ++ return 1; + } + + __setup("ima_appraise=", default_appraise_setup); + ++ ++static int ima_appraise_param_set(const char *val, ++ const struct kernel_param *kp) ++{ ++ char *ima_appraise_type = strstrip((char *)val); ++ ++ /* no change required */ ++ if (!strcmp(ima_appraise_type, *(char **)kp->arg)) ++ return 0; ++ ++ /* set the ima_appraise mode and only ++ * update the kernel parameter if the parameter ++ * was successfully set */ ++ int ret; ++ ret = default_appraise_setup(ima_appraise_type); ++ if (ret == -1) { ++ pr_err("Undefined value for ima_appraise_param: %s\n", ++ ima_appraise_type); ++ return -EINVAL; ++ } ++ ++ return param_set_charp(ima_appraise_type, kp); ++} ++ + /* + * ima_must_appraise - set appraise flag + * +diff --git a/ima/ima_init.c b/ima/ima_init.c +index 0759c8c..a7362e8 100644 +--- a/ima/ima_init.c ++++ b/ima/ima_init.c +@@ -26,7 +26,11 @@ + + /* name for boot aggregate entry */ + static const char *boot_aggregate_name = "boot_aggregate"; +-int ima_used_chip; ++int ima_used_chip = -1; ++module_param_named(ima_use_tpm, ima_used_chip, int, 0644); ++MODULE_PARM_DESC(ima_use_tpm, ++ "Enable TPM interaction for storing measurement aggregate " \ ++ " { 0(disable) | 1(enable) }(default: 0)."); + + /* Add the boot aggregate to the IMA measurement list and extend + * the PCR register. +@@ -108,11 +112,13 @@ int __init ima_init(void) + { + u8 pcr_i[TPM_DIGEST_SIZE]; + int rc; +- +- ima_used_chip = 0; +- rc = tpm_pcr_read(TPM_ANY_NUM, 0, pcr_i); +- if (rc == 0) +- ima_used_chip = 1; ++ ++ if (ima_used_chip != 0) { ++ ima_used_chip = 0; ++ rc = tpm_pcr_read(TPM_ANY_NUM, 0, pcr_i); ++ if (rc == 0) ++ ima_used_chip = 1; ++ } + + if (!ima_used_chip) + pr_info("No TPM chip found, activating TPM-bypass! (rc=%d)\n", +diff --git a/integrity_audit.c b/integrity_audit.c +index ba5e532..da29f91 100644 +--- a/integrity_audit.c ++++ b/integrity_audit.c +@@ -17,6 +17,8 @@ + #include "integrity.h" + + static int integrity_audit_info; ++module_param_named(integrity_audit, integrity_audit_info, uint, 0644); ++MODULE_PARM_DESC(integrity_audit, "Enable debug integrity auditing."); + + /* ima_audit_setup - enable informational auditing messages */ + static int __init integrity_audit_setup(char *str) +diff --git a/kcompat.h b/kcompat.h +index 936b76c..a5445aa 100644 +--- a/kcompat.h ++++ b/kcompat.h +@@ -9,6 +9,10 @@ + + #if ( LINUX_VERSION_CODE <= KERNEL_VERSION(3,10,0) ) + ++#include ++#include ++#include ++ + /* kcompat definitions */ + #define CONFIG_TCG_TPM_MODULE 1 + +-- +1.8.3.1 + diff --git a/kernel/kernel-modules/integrity/patches/0003-integrity-restrict-by-iversion.patch b/kernel/kernel-modules/integrity/patches/0003-integrity-restrict-by-iversion.patch new file mode 100644 index 000000000..0813915f4 --- /dev/null +++ b/kernel/kernel-modules/integrity/patches/0003-integrity-restrict-by-iversion.patch @@ -0,0 +1,54 @@ +From 0c83c892509e592692e5002d855ce1f3001149e5 Mon Sep 17 00:00:00 2001 +From: Kam Nasim +Date: Fri, 22 Sep 2017 16:47:36 -0400 +Subject: [PATCH] US103091: IMA: System Configuration + +Since IMA does measurements on all EXT4 file systems (as per IMA +policy), we end up with a large number of measurements for log files and +the DRBD fs. Therefore we restrict IMA to only do measurements & +appraisals on file systems that have i_version set, which is only the +rootfs. +--- + ima/ima_main.c | 6 +++++- + kcompat.h | 1 + + 2 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/ima/ima_main.c b/ima/ima_main.c +index 5d6ba23..ea3ace3 100644 +--- a/ima/ima_main.c ++++ b/ima/ima_main.c +@@ -22,6 +22,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -178,7 +179,10 @@ static int process_measurement(struct file *file, char *buf, loff_t size, + bool violation_check; + enum hash_algo hash_algo; + +- if (!ima_policy_flag || !S_ISREG(inode->i_mode)) ++ /* WRS: Only do measurements & appraisals ++ * on inodes that have i_version set (i.e the rootfs) ++ */ ++ if (!ima_policy_flag || !S_ISREG(inode->i_mode) || !IS_I_VERSION(inode)) + return 0; + + /* Return an IMA_MEASURE, IMA_APPRAISE, IMA_AUDIT action +diff --git a/kcompat.h b/kcompat.h +index a5445aa..59e32a8 100644 +--- a/kcompat.h ++++ b/kcompat.h +@@ -19,6 +19,7 @@ + #define CONFIG_IMA 1 + #define CONFIG_IMA_APPRAISE_SIGNED_INIT 1 + #define CONFIG_IMA_APPRAISE 1 ++#define CONFIG_IMA_LSM_RULES 1 + #define CONFIG_IMA_DEFAULT_HASH "sha256" + #define CONFIG_IMA_MEASURE_PCR_IDX 10 + #define CONFIG_IMA_DEFAULT_TEMPLATE "ima-sig" +-- +1.8.3.1 + diff --git a/kernel/kernel-modules/integrity/patches/0004-integrity-disable-set-xattr-on-imasig.patch b/kernel/kernel-modules/integrity/patches/0004-integrity-disable-set-xattr-on-imasig.patch new file mode 100644 index 000000000..cb489681e --- /dev/null +++ b/kernel/kernel-modules/integrity/patches/0004-integrity-disable-set-xattr-on-imasig.patch @@ -0,0 +1,121 @@ +From 928f2de735ab38802984938618aa051dd55f536c Mon Sep 17 00:00:00 2001 +From: Kam Nasim +Date: Wed, 4 Oct 2017 14:23:13 -0400 +Subject: [PATCH] US103091: IMA: System Configuration + +When appraise_type="imasig" is set in the IMA policy then don't allow +IMA to put a hash value for the security.ima xattr, if the extended +attribute is missing. This is a fool's errand, as there is already a +check in the driver which will give an appraisal failure if it detects +that the security.ima xattr is a Hash and NOT a Signature, so appraisal +would fail again next time that file is executed. + +The advantage of this fix is that it improves driver performance as we +are not collecting a measurement on appraisal failure + +By virtue of the same, we will not remove the security.ima xattr if we +detect that imasig is set on that iint +--- + ima/ima_appraise.c | 33 +++++++++++++++++++++++++++++---- + ima/ima_main.c | 2 -- + 2 files changed, 29 insertions(+), 6 deletions(-) + +diff --git a/ima/ima_appraise.c b/ima/ima_appraise.c +index 88b5091..cff2ad2 100644 +--- a/ima/ima_appraise.c ++++ b/ima/ima_appraise.c +@@ -250,8 +250,11 @@ int ima_appraise_measurement(enum ima_hooks func, + if (rc <= 0) { + if (rc && rc != -ENODATA) + goto out; +- +- cause = "missing-hash"; ++ ++ if (iint->flags & IMA_DIGSIG_REQUIRED) ++ cause = "missing-signature"; ++ else ++ cause = "missing-hash"; + status = INTEGRITY_NOLABEL; + if (opened & FILE_CREATED) { + iint->flags |= IMA_NEW_FILE; +@@ -352,7 +355,8 @@ void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file) + int rc = 0; + + /* do not collect and update hash for digital signatures */ +- if (iint->flags & IMA_DIGSIG) ++ /* WRS: Don't do it if appraise_type is set to imasig */ ++ if ((iint->flags & IMA_DIGSIG) || (iint->flags & IMA_DIGSIG_REQUIRED)) + return; + + rc = ima_collect_measurement(iint, file, NULL, 0, ima_hash_algo); +@@ -376,6 +380,7 @@ void __ima_inode_post_setattr(struct dentry *dentry) + struct inode *inode = d_backing_inode(dentry); + struct integrity_iint_cache *iint; + int must_appraise, rc; ++ int imasig = 0; + + if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode) + || !inode->i_op->removexattr) +@@ -384,11 +389,20 @@ void __ima_inode_post_setattr(struct dentry *dentry) + must_appraise = ima_must_appraise(inode, MAY_ACCESS, POST_SETATTR); + iint = integrity_iint_find(inode); + if (iint) { ++ /* WRS: Before we clear all the ACTION RULE FLAGS, check if ++ * imasig was set on this iint, which implies that we are ++ * expecting a signature for the security.ima xattr ++ */ ++ if (iint->flags & IMA_DIGSIG_REQUIRED) ++ imasig = 1; + iint->flags &= ~(IMA_APPRAISE | IMA_APPRAISED | + IMA_APPRAISE_SUBMASK | IMA_APPRAISED_SUBMASK | + IMA_ACTION_RULE_FLAGS); +- if (must_appraise) ++ if (must_appraise) { + iint->flags |= IMA_APPRAISE; ++ if (imasig) ++ iint->flags |= IMA_DIGSIG_REQUIRED; ++ } + } + if (!must_appraise) + rc = inode->i_op->removexattr(dentry, XATTR_NAME_IMA); +@@ -450,6 +464,17 @@ int __ima_inode_setxattr(struct dentry *dentry, const char *xattr_name, + int __ima_inode_removexattr(struct dentry *dentry, const char *xattr_name) + { + int result; ++ ++ /* WRS: If this security.ima xattr is a digital signature ++ * then we will not allow it to be removed (only if we ++ * have a cached iint entry for it) ++ */ ++ struct inode *inode = d_backing_inode(dentry); ++ struct integrity_iint_cache *iint = integrity_iint_find(inode); ++ if (iint) { ++ if (iint->flags & IMA_DIGSIG_REQUIRED) ++ return -EPERM; ++ } + + result = ima_protect_xattr(dentry, xattr_name, NULL, 0); + if (result == 1) { +diff --git a/ima/ima_main.c b/ima/ima_main.c +index ea3ace3..15ac6a7 100644 +--- a/ima/ima_main.c ++++ b/ima/ima_main.c +@@ -129,7 +129,6 @@ static void ima_check_last_writer(struct integrity_iint_cache *iint, + if (!(mode & FMODE_WRITE)) + return; + +- inode_lock(inode); + if (atomic_read(&inode->i_writecount) == 1) { + if ((iint->version != inode->i_version) || + (iint->flags & IMA_NEW_FILE)) { +@@ -139,7 +138,6 @@ static void ima_check_last_writer(struct integrity_iint_cache *iint, + ima_update_xattr(iint, file); + } + } +- inode_unlock(inode); + } + + /** +-- +1.8.3.1 + diff --git a/kernel/kernel-modules/integrity/patches/Changes-for-CentOS-7.4-support.patch b/kernel/kernel-modules/integrity/patches/Changes-for-CentOS-7.4-support.patch new file mode 100644 index 000000000..b20f9b2c5 --- /dev/null +++ b/kernel/kernel-modules/integrity/patches/Changes-for-CentOS-7.4-support.patch @@ -0,0 +1,28 @@ +From cf5d8b554d6fdacf3ad3d18333bd00f8b937ff54 Mon Sep 17 00:00:00 2001 +Message-Id: +From: Jim Somerville +Date: Wed, 11 Oct 2017 16:38:36 -0400 +Subject: [PATCH 1/1] Changes for CentOS 7.4 support + +Signed-off-by: Jim Somerville +--- + kcompat.h | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/kcompat.h b/kcompat.h +index 59e32a8..3d4e8f6 100644 +--- a/kcompat.h ++++ b/kcompat.h +@@ -31,9 +31,5 @@ + + #define __GFP_RECLAIM __GFP_WAIT + +-#define inode_lock(_node) mutex_lock(&_node->i_mutex) +-#define inode_unlock(_node) mutex_unlock(&_node->i_mutex) +- +- + #endif + #endif +-- +1.8.3.1 + diff --git a/kernel/kernel-modules/integrity/patches/integrity-kmod.spec.patchlist b/kernel/kernel-modules/integrity/patches/integrity-kmod.spec.patchlist new file mode 100644 index 000000000..e2a7a19a5 --- /dev/null +++ b/kernel/kernel-modules/integrity/patches/integrity-kmod.spec.patchlist @@ -0,0 +1,3 @@ +0001-integrity-kcompat-support.patch +0002-integrity-expose-module-params.patch +0003-integrity-restrict-by-iversion.patch