diff options
author | Armin Kuster <akuster808@gmail.com> | 2019-05-16 15:41:49 -0700 |
---|---|---|
committer | Armin Kuster <akuster808@gmail.com> | 2019-05-28 07:38:41 -0700 |
commit | 6680225c05bb0834280307c223c3a545b088cbd3 (patch) | |
tree | 701dca648e192c492e1165020a900028adefcbb2 | |
parent | 479d9cc23a741e89b2bd4884b62d8623b1cf2a19 (diff) | |
download | meta-security-6680225c05bb0834280307c223c3a545b088cbd3.tar.gz |
meta-integrity: port over from meta-intel-iot-security
Signed-off-by: Armin Kuster <akuster808@gmail.com>
30 files changed, 1402 insertions, 0 deletions
diff --git a/meta-integrity/README.md b/meta-integrity/README.md new file mode 100644 index 0000000..ba96d8e --- /dev/null +++ b/meta-integrity/README.md | |||
@@ -0,0 +1,253 @@ | |||
1 | This README file contains information on the contents of the | ||
2 | integrity layer. | ||
3 | |||
4 | Please see the corresponding sections below for details. | ||
5 | |||
6 | |||
7 | Dependencies | ||
8 | ============ | ||
9 | |||
10 | This layer depends on: | ||
11 | |||
12 | URI: git://git.openembedded.org/bitbake | ||
13 | branch: master | ||
14 | |||
15 | URI: git://git.openembedded.org/openembedded-core | ||
16 | layers: meta | ||
17 | branch: master | ||
18 | |||
19 | URI: git://github.com/01org/meta-security/meta-integrate | ||
20 | layers: security-framework | ||
21 | branch: master | ||
22 | |||
23 | |||
24 | Patches | ||
25 | ======= | ||
26 | |||
27 | Please submit any patches against the integrity layer via Github | ||
28 | pull requests. | ||
29 | |||
30 | For discussion or patch submission via email, use the | ||
31 | yocto@yoctoproject.org mailing list. When submitting patches that way, | ||
32 | make sure to copy the maintainer and add a "[meta-]" | ||
33 | prefix to the subject of the mails. | ||
34 | |||
35 | Maintainer: Armin Kuster <akuster808@gmail.com> | ||
36 | |||
37 | |||
38 | Table of Contents | ||
39 | ================= | ||
40 | |||
41 | 1. Adding the integrity layer to your build | ||
42 | 2. Usage | ||
43 | 3. Known Issues | ||
44 | |||
45 | |||
46 | 1. Adding the integrity layer to your build | ||
47 | =========================================== | ||
48 | |||
49 | In order to use this layer, you need to make the build system aware of | ||
50 | it. | ||
51 | |||
52 | Assuming the security repository exists at the top-level of your | ||
53 | yocto build tree, you can add it to the build system by adding the | ||
54 | location of the integrity layer to bblayers.conf, along with any | ||
55 | other layers needed. e.g.: | ||
56 | |||
57 | BBLAYERS ?= " \ | ||
58 | /path/to/yocto/meta \ | ||
59 | /path/to/yocto/meta-yocto \ | ||
60 | /path/to/yocto/meta-yocto-bsp \ | ||
61 | /path/to/yocto/meta-security/meta-integrity \ | ||
62 | " | ||
63 | |||
64 | It has some dependencies on a suitable BSP; in particular the kernel | ||
65 | must have a recent enough IMA/EVM subsystem. The layer was tested with | ||
66 | Linux 3.19 and uses some features (like loading X509 certificates | ||
67 | directly from the kernel) which were added in that release. Your | ||
68 | mileage may vary with older kernels. | ||
69 | |||
70 | The necessary kernel configuration parameters are added to all kernel | ||
71 | versions by this layer. Watch out for QA warnings about unused kernel | ||
72 | configuration parameters: those indicate that the kernel used by the BSP | ||
73 | does not have the necessary IMA/EVM features. | ||
74 | |||
75 | Adding the layer only enables IMA (see below regarding EVM) during | ||
76 | compilation of the Linux kernel. To also activate it when building | ||
77 | the image, enable image signing in the local.conf like this: | ||
78 | |||
79 | INHERIT += "ima-evm-rootfs" | ||
80 | IMA_EVM_KEY_DIR = "${IMA_EVM_BASE}/data/debug-keys" | ||
81 | |||
82 | This uses the default keys provided in the "data" directory of the layer. | ||
83 | Because everyone has access to these private keys, such an image | ||
84 | should never be used in production! | ||
85 | |||
86 | For that, create your own keys first. All tools and scripts required | ||
87 | for that are included in the layer. This is also how the | ||
88 | ``debug-keys`` were generated: | ||
89 | |||
90 | # Choose a directory for storing keys. Preserve this | ||
91 | # across builds and keep its private keys secret! | ||
92 | export IMA_EVM_KEY_DIR=/tmp/imaevm | ||
93 | mkdir -p $IMA_EVM_KEY_DIR | ||
94 | # Build the required tools. | ||
95 | bitbake openssl-native | ||
96 | # Set up shell for use of the tools. | ||
97 | bitbake -c devshell openssl-native | ||
98 | cd $IMA_EVM_KEY_DIR | ||
99 | # In that shell, create the keys. Several options exist: | ||
100 | |||
101 | # 1. Self-signed keys. | ||
102 | $IMA_EVM_BASE/scripts/ima-gen-self-signed.sh | ||
103 | |||
104 | # 2. Keys signed by a new CA. | ||
105 | # When asked for a PEM passphrase, that will be for the root CA. | ||
106 | # Signing images then will not require entering that passphrase, | ||
107 | # only creating new certificates does. Most likely the default | ||
108 | # attributes for these certificates need to be adapted; modify | ||
109 | # the scripts as needed. | ||
110 | # $IMA_EVM_BASE/scripts/ima-gen-local-ca.sh | ||
111 | # $IMA_EVM_BASE/scripts/ima-gen-CA-signed.sh | ||
112 | |||
113 | # 3. Keys signed by an existing CA. | ||
114 | # $IMA_EVM_BASE/scripts/ima-gen-CA-signed.sh <CA.pem> <CA.priv> | ||
115 | exit | ||
116 | |||
117 | When using ``ima-self-signed.sh`` as described above, self-signed keys | ||
118 | are created. Alternatively, one can also use keys signed by a CA. The | ||
119 | ``ima-gen-local-ca.sh`` and ``ima-gen.sh`` scripts create a root CA | ||
120 | and sign the signing keys with it. The ``ima-evm-rootfs.bbclass`` then | ||
121 | supports adding tha CA's public key to the kernel's system keyring by | ||
122 | compiling it directly into the kernel. Because it is unknown whether | ||
123 | that is necessary (for example, the CA might also get added to the | ||
124 | system key ring via UEFI Secure Boot), one has to enable compilation | ||
125 | into the kernel explicitly in a local.conf with: | ||
126 | |||
127 | IMA_EVM_ROOT_CA = "<path to .x509 file, for example the ima-local-ca.x509 created by ima-gen-local-ca.sh>" | ||
128 | |||
129 | |||
130 | |||
131 | |||
132 | To use the personal keys, override the default IMA_EVM_KEY_DIR in your | ||
133 | local.conf and/or override the individual variables from | ||
134 | ima-evm-rootfs.bbclass: | ||
135 | |||
136 | IMA_EVM_KEY_DIR = "<full path>" | ||
137 | IMA_EVM_PRIVKEY = "<some other path/privkey_ima.pem>" | ||
138 | |||
139 | By default, the entire file system gets signed. When using a policy which | ||
140 | does not require that, the set of files to be labelled can be chosen | ||
141 | by overriding the default "find" expression, for example like this: | ||
142 | |||
143 | IMA_EVM_ROOTFS_FILES = "usr sbin bin lib -type f" | ||
144 | |||
145 | |||
146 | 2. Usage | ||
147 | ======== | ||
148 | |||
149 | After creating an image with IMA/EVM enabled, one needs to enable | ||
150 | the built-in policies before IMA/EVM is active at runtime. To do this, | ||
151 | add one or both of these boot parameters: | ||
152 | |||
153 | ima_tcb # measures all files read as root and all files executed | ||
154 | ima_appraise_tcb # appraises all files owned by root, beware of | ||
155 | # the known issue mentioned below | ||
156 | |||
157 | Instead of booting with default policies, one can also activate custom | ||
158 | policies in different ways. First, boot without any IMA policy and | ||
159 | then cat a policy file into | ||
160 | `/sys/kernel/security/ima/policy`. This can only be done once | ||
161 | after booting and is useful for debugging. | ||
162 | |||
163 | In production, the long term goal is to load a verified policy | ||
164 | directly from the kernel, using a patch which still needs to be | ||
165 | included upstream ("ima: load policy from the kernel", | ||
166 | <https://lwn.net/Articles/595759/>). | ||
167 | |||
168 | Loading via systemd also works with systemd, but is considered less | ||
169 | secure (policy file is not checked before activating it). Beware that | ||
170 | IMA policy loading became broken in systemd 2.18. The modified systemd | ||
171 | 2.19 in meta-security-smack has a patch reverting the broken | ||
172 | changes. To activate policy loading via systemd, place a policy file | ||
173 | in `/etc/ima/ima-policy`, for example with: | ||
174 | |||
175 | IMA_EVM_POLICY_SYSTEMD = "${IMA_EVM_BASE}/data/ima_policy_simple" | ||
176 | |||
177 | To check that measuring works, look at `/sys/kernel/security/ima/ascii_runtime_measurements` | ||
178 | |||
179 | To check that appraisal works, try modifying executables and ensure | ||
180 | that executing them fails: | ||
181 | |||
182 | echo "foobar" >>/usr/bin/rpm | ||
183 | evmctl ima_verify /usr/bin/rpm | ||
184 | rpm --version | ||
185 | |||
186 | Depending on the current appraisal policy, the `echo` command may | ||
187 | already fail because writing is not allowed. If the file was modified | ||
188 | and the current appraisal policy allows reading, then `evmctl` will | ||
189 | report (the errno value seems to be printed always and is unrelated to | ||
190 | the actual verification failure here): | ||
191 | |||
192 | Verification failed: 35 | ||
193 | errno: No such file or directory (2) | ||
194 | |||
195 | After enabling a suitable IMA appraisal policy, reading and/or | ||
196 | executing the file is no longer allowed: | ||
197 | |||
198 | # evmctl ima_verify /usr/bin/rpm | ||
199 | Failed to open: /usr/bin/rpm | ||
200 | errno: Permission denied (13) | ||
201 | # rpm --version | ||
202 | -sh: /usr/bin/rpm: Permission denied | ||
203 | |||
204 | Enabling the audit kernel subsystem may help to debug appraisal | ||
205 | issues. Enable it by adding the meta-security-framework layer and | ||
206 | changing your local.conf: | ||
207 | SRC_URI_append_pn-linux-yocto = " file://audit.cfg" | ||
208 | CORE_IMAGE_EXTRA_INSTALL += "auditd" | ||
209 | |||
210 | Then boot with "ima_appraise=log ima_appraise_tcb". | ||
211 | |||
212 | Adding auditd is not strictly necessary but helps to capture a | ||
213 | more complete set of events in /var/log/audit/ and search in | ||
214 | them with ausearch. | ||
215 | |||
216 | |||
217 | 3. Known Issues | ||
218 | =============== | ||
219 | |||
220 | EVM is not enabled, for multiple reasons: | ||
221 | * Signing files in advance with a X509 certificate and then not having | ||
222 | any confidential keys on the device would be the most useful mode, | ||
223 | but is not supported by EVM [1]. | ||
224 | * EVM signing in advance would only work on the final file system and thus | ||
225 | will require further integration work with image creation. The content | ||
226 | of the files can be signed for IMA in the rootfs, with the extended | ||
227 | attributes remaining valid when copying the files to the final image. | ||
228 | But for EVM that copy operation changes relevant parameters (for example, | ||
229 | inode) and thus invalidates the EVM hash. | ||
230 | * On device creation of EVM hashes depends on secure key handling on the | ||
231 | device (TPM) and booting at least once in a special mode (file system | ||
232 | writable, evm=fix as boot parameter, reboot after opening all files); | ||
233 | such a mode is too device specific to be implemented in a generic way. | ||
234 | |||
235 | IMA appraisal with "ima_appraise_tcb" enables rules which are too strict | ||
236 | for most distros. For example, systemd needs to write certain files | ||
237 | as root, which is prevented by the ima_appraise_tcb appraise rules. As | ||
238 | a result, the system fails to boot: | ||
239 | |||
240 | [FAILED] Failed to start Commit a transient machine-id on disk. | ||
241 | See "systemctl status systemd-machine-id-commit.service" for details. | ||
242 | ... | ||
243 | [FAILED] Failed to start Network Service. | ||
244 | See "systemctl status systemd-networkd.service" for details. | ||
245 | [FAILED] Failed to start Login Service. | ||
246 | See "systemctl status systemd-logind.service" for details. | ||
247 | |||
248 | No package manager is integrated with IMA/EVM. When updating packages, | ||
249 | files will end up getting installed without correct IMA/EVM attributes | ||
250 | and thus will not be usable when appraisal is turned on. | ||
251 | |||
252 | [1] http://permalink.gmane.org/gmane.comp.handhelds.tizen.devel/6281 | ||
253 | [2] http://permalink.gmane.org/gmane.comp.handhelds.tizen.devel/6275 | ||
diff --git a/meta-integrity/classes/ima-evm-rootfs.bbclass b/meta-integrity/classes/ima-evm-rootfs.bbclass new file mode 100644 index 0000000..8aec388 --- /dev/null +++ b/meta-integrity/classes/ima-evm-rootfs.bbclass | |||
@@ -0,0 +1,92 @@ | |||
1 | # No default! Either this or IMA_EVM_PRIVKEY/IMA_EVM_X509 have to be | ||
2 | # set explicitly in a local.conf before activating ima-evm-rootfs. | ||
3 | # To use the insecure (because public) example keys, use | ||
4 | # IMA_EVM_KEY_DIR = "${IMA_EVM_BASE}/data/debug-keys" | ||
5 | IMA_EVM_KEY_DIR ?= "IMA_EVM_KEY_DIR_NOT_SET" | ||
6 | |||
7 | # Private key for IMA signing. The default is okay when | ||
8 | # using the example key directory. | ||
9 | IMA_EVM_PRIVKEY ?= "${IMA_EVM_KEY_DIR}/privkey_ima.pem" | ||
10 | |||
11 | # Public part of certificates (used for both IMA and EVM). | ||
12 | # The default is okay when using the example key directory. | ||
13 | IMA_EVM_X509 ?= "${IMA_EVM_KEY_DIR}/x509_ima.der" | ||
14 | |||
15 | # Root CA to be compiled into the kernel, none by default. | ||
16 | # Must be the absolute path to a der-encoded x509 CA certificate | ||
17 | # with a .x509 suffix. See linux-%.bbappend for details. | ||
18 | # | ||
19 | # ima-local-ca.x509 is what ima-gen-local-ca.sh creates. | ||
20 | IMA_EVM_ROOT_CA ?= "" | ||
21 | |||
22 | # Sign all regular files by default. | ||
23 | IMA_EVM_ROOTFS_SIGNED ?= ". -type f" | ||
24 | # Hash nothing by default. | ||
25 | IMA_EVM_ROOTFS_HASHED ?= ". -depth 0 -false" | ||
26 | |||
27 | # Mount these file systems (identified via their mount point) with | ||
28 | # the iversion flags (needed by IMA when allowing writing). | ||
29 | IMA_EVM_ROOTFS_IVERSION ?= "" | ||
30 | |||
31 | ima_evm_sign_rootfs () { | ||
32 | cd ${IMAGE_ROOTFS} | ||
33 | |||
34 | # Beware that all operations below must also work when | ||
35 | # ima_evm_sign_rootfs was already called earlier for the same | ||
36 | # rootfs. That's because do_image might again run for various | ||
37 | # reasons (including a change of the signing keys) without also | ||
38 | # re-running do_rootfs. | ||
39 | |||
40 | # Copy file(s) which must be on the device. Note that | ||
41 | # evmctl uses x509_evm.der also for "ima_verify", which is probably | ||
42 | # a bug (should default to x509_ima.der). Does not matter for us | ||
43 | # because we use the same key for both. | ||
44 | install -d ./${sysconfdir}/keys | ||
45 | rm -f ./${sysconfdir}/keys/x509_evm.der | ||
46 | install "${IMA_EVM_X509}" ./${sysconfdir}/keys/x509_evm.der | ||
47 | ln -sf x509_evm.der ./${sysconfdir}/keys/x509_ima.der | ||
48 | |||
49 | # Fix /etc/fstab: it must include the "i_version" mount option for | ||
50 | # those file systems where writing files is allowed, otherwise | ||
51 | # these changes will not get detected at runtime. | ||
52 | # | ||
53 | # Note that "i_version" is documented in "man mount" only for ext4, | ||
54 | # whereas "iversion" is said to be filesystem-independent. In practice, | ||
55 | # there is only one MS_I_VERSION flag in the syscall and ext2/ext3/ext4 | ||
56 | # all support it. | ||
57 | # | ||
58 | # coreutils translates "iversion" into MS_I_VERSION. busybox rejects | ||
59 | # "iversion" and only understands "i_version". systemd only understands | ||
60 | # "iversion". We pick "iversion" here for systemd, whereas rootflags | ||
61 | # for initramfs must use "i_version" for busybox. | ||
62 | # | ||
63 | # Deduplicates iversion in case that this gets called more than once. | ||
64 | if [ -f etc/fstab ]; then | ||
65 | perl -pi -e 's;(\S+)(\s+)(${@"|".join((d.getVar("IMA_EVM_ROOTFS_IVERSION", True) or "no-such-mount-point").split())})(\s+)(\S+)(\s+)(\S+);\1\2\3\4\5\6\7,iversion;; s/(,iversion)+/,iversion/;' etc/fstab | ||
66 | fi | ||
67 | |||
68 | # Sign file with private IMA key. EVM not supported at the moment. | ||
69 | bbnote "IMA/EVM: signing files 'find ${IMA_EVM_ROOTFS_SIGNED}' with private key '${IMA_EVM_PRIVKEY}'" | ||
70 | find ${IMA_EVM_ROOTFS_SIGNED} | xargs -d "\n" --no-run-if-empty --verbose evmctl ima_sign --key ${IMA_EVM_PRIVKEY} | ||
71 | bbnote "IMA/EVM: hashing files 'find ${IMA_EVM_ROOTFS_HASHED}'" | ||
72 | find ${IMA_EVM_ROOTFS_HASHED} | xargs -d "\n" --no-run-if-empty --verbose evmctl ima_hash | ||
73 | |||
74 | # Optionally install custom policy for loading by systemd. | ||
75 | if [ "${IMA_EVM_POLICY_SYSTEMD}" ]; then | ||
76 | install -d ./${sysconfdir}/ima | ||
77 | rm -f ./${sysconfdir}/ima/ima-policy | ||
78 | install "${IMA_EVM_POLICY_SYSTEMD}" ./${sysconfdir}/ima/ima-policy | ||
79 | fi | ||
80 | } | ||
81 | |||
82 | # Signing must run as late as possible in the do_rootfs task. | ||
83 | # IMAGE_PREPROCESS_COMMAND runs after ROOTFS_POSTPROCESS_COMMAND, so | ||
84 | # append (not prepend!) to IMAGE_PREPROCESS_COMMAND, and do it with | ||
85 | # _append instead of += because _append gets evaluated later. In | ||
86 | # particular, we must run after prelink_image in | ||
87 | # IMAGE_PREPROCESS_COMMAND, because prelinking changes executables. | ||
88 | |||
89 | IMAGE_PREPROCESS_COMMAND_append = " ima_evm_sign_rootfs ; " | ||
90 | |||
91 | # evmctl must have been installed first. | ||
92 | do_rootfs[depends] += "ima-evm-utils-native:do_populate_sysroot" | ||
diff --git a/meta-integrity/conf/layer.conf b/meta-integrity/conf/layer.conf new file mode 100644 index 0000000..e8bb268 --- /dev/null +++ b/meta-integrity/conf/layer.conf | |||
@@ -0,0 +1,22 @@ | |||
1 | # We have a conf and classes directory, add to BBPATH | ||
2 | BBPATH =. "${LAYERDIR}:" | ||
3 | |||
4 | # We have a packages directory, add to BBFILES | ||
5 | BBFILES := "${BBFILES} \ | ||
6 | ${LAYERDIR}/recipes-*/*/*.bb \ | ||
7 | ${LAYERDIR}/recipes-*/*/*.bbappend" | ||
8 | |||
9 | BBFILE_COLLECTIONS += "integrity" | ||
10 | BBFILE_PATTERN_integrity := "^${LAYERDIR}/" | ||
11 | BBFILE_PRIORITY_integrity = "6" | ||
12 | |||
13 | # Set a variable to get to the top of the metadata location. Needed | ||
14 | # for finding scripts (when following the README.md instructions) and | ||
15 | # default debug keys (in ima-evm-rootfs.bbclass). | ||
16 | IMA_EVM_BASE := '${LAYERDIR}' | ||
17 | |||
18 | # We must not export this path to all shell scripts (as in "export | ||
19 | # IMA_EVM_BASE"), because that causes problems with sstate (becames | ||
20 | # dependent on location of the layer). Exporting it to just the | ||
21 | # interactive shell is enough. | ||
22 | OE_TERMINAL_EXPORTS += "IMA_EVM_BASE" | ||
diff --git a/meta-integrity/data/debug-keys/privkey_ima.pem b/meta-integrity/data/debug-keys/privkey_ima.pem new file mode 100644 index 0000000..502a0b6 --- /dev/null +++ b/meta-integrity/data/debug-keys/privkey_ima.pem | |||
@@ -0,0 +1,16 @@ | |||
1 | -----BEGIN PRIVATE KEY----- | ||
2 | MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJw2G3d0fM36rcQU | ||
3 | Bt8V/SapJe0lxWJ+CY+HcMx8AhWY9XQ66AXcqBsRHiUnYCaFGXFI35VKGC6d/Gs6 | ||
4 | IWlHgI0tcTyzy5eul+BKRLy/3PNjkK2jJETlbetQy+gE6gUtg4RmPV5ALGksK74p | ||
5 | OrAfKnahoMi82NVIiBitwmRimms1AgMBAAECgYBTxciRFU1hAVBy2PKebKJoO0n1 | ||
6 | lc329fSWnmHlp5NOlcr8XCLWEfGtIk7ySd2MitCMKjKNU0EIrv0RXAlS9l9/gBYW | ||
7 | HY+eEaa6l80sp8q4aPKImSi0pb3LVNqWKXJg8qr4AZ45/TEL/fzILFv5QcY8xDjV | ||
8 | aj6DOlEnNDjlBlBbQQJBAMyYDlKItes/Rnmtp9roXj3XUfiBDHTLY2HVgDBe87sA | ||
9 | TOSnbgIv+6urd1h9XvBmJlRYH7YKJmBSZWcSlfdC6XkCQQDDdfkUMxQZo9PC/Eue | ||
10 | WYzytx4xUm3ItWcuKILtFgcNh3c4s4dMx4X/WhQj5/H/nVOIWDioQ0mrW3ap/qcb | ||
11 | SBydAkAf/gb/UPFhf9t9W3JMANn7wZfHzCYufT9lJQWOisqCC2H6v1Osc+Rey8k1 | ||
12 | xST7Yn3L4pvS03N8zGWe4IEi0QvBAkAWdTWbNos2rvYjzy05Enz5XkTf0eK/Tuh+ | ||
13 | CzWP3BoPWeM+5pHDJqGkx0rNHVdW0VLJtak83A5Y2/d0bMfygISZAkBFGui4HW+Q | ||
14 | 1BlpmDeslsE11wm5jSmm6Ti12a2dVKGFo9QLQcSj4bfgxtqU2dQaYRmajXtSBrGQ | ||
15 | 3vVaxg2EfqB1 | ||
16 | -----END PRIVATE KEY----- | ||
diff --git a/meta-integrity/data/debug-keys/x509_ima.der b/meta-integrity/data/debug-keys/x509_ima.der new file mode 100644 index 0000000..087ca6b --- /dev/null +++ b/meta-integrity/data/debug-keys/x509_ima.der | |||
Binary files differ | |||
diff --git a/meta-integrity/data/ima_policy_appraise_all b/meta-integrity/data/ima_policy_appraise_all new file mode 100644 index 0000000..36e71a7 --- /dev/null +++ b/meta-integrity/data/ima_policy_appraise_all | |||
@@ -0,0 +1,29 @@ | |||
1 | # | ||
2 | # Integrity measure policy (http://sourceforge.net/p/linux-ima/wiki/Home/#measure-nothing-appraise-everything) | ||
3 | # | ||
4 | # Do not measure anything, but appraise everything | ||
5 | # | ||
6 | # PROC_SUPER_MAGIC | ||
7 | dont_appraise fsmagic=0x9fa0 | ||
8 | # SYSFS_MAGIC | ||
9 | dont_appraise fsmagic=0x62656572 | ||
10 | # DEBUGFS_MAGIC | ||
11 | dont_appraise fsmagic=0x64626720 | ||
12 | # TMPFS_MAGIC | ||
13 | dont_appraise fsmagic=0x01021994 | ||
14 | # RAMFS_MAGIC | ||
15 | dont_appraise fsmagic=0x858458f6 | ||
16 | # DEVPTS_SUPER_MAGIC | ||
17 | dont_appraise fsmagic=0x1cd1 | ||
18 | # BIFMT | ||
19 | dont_appraise fsmagic=0x42494e4d | ||
20 | # SECURITYFS_MAGIC | ||
21 | dont_appraise fsmagic=0x73636673 | ||
22 | # SELINUXFS_MAGIC | ||
23 | dont_appraise fsmagic=0xf97cff8c | ||
24 | # NSFS_MAGIC (introduced in 3.19, see cd025f7 and e149ed2 in the upstream Linux kernel) | ||
25 | dont_appraise fsmagic=0x6e736673 | ||
26 | # EFIVARFS_MAGIC | ||
27 | dont_appraise fsmagic=0xde5e81e4 | ||
28 | |||
29 | appraise | ||
diff --git a/meta-integrity/data/ima_policy_hashed b/meta-integrity/data/ima_policy_hashed new file mode 100644 index 0000000..7f89c8d --- /dev/null +++ b/meta-integrity/data/ima_policy_hashed | |||
@@ -0,0 +1,77 @@ | |||
1 | # With this policy, all files on regular partitions are | ||
2 | # appraised. Files with signed IMA hash and normal hash are | ||
3 | # accepted. Signed files cannot be modified while hashed files can be | ||
4 | # (which will also update the hash). However, signed files can | ||
5 | # be deleted, so in practice it is still possible to replace them | ||
6 | # with a modified version. | ||
7 | # | ||
8 | # Without EVM, this is obviously not very secure, so this policy is | ||
9 | # just an example and/or basis for further improvements. For that | ||
10 | # purpose, some comments show what could be added to make the policy | ||
11 | # more secure. | ||
12 | # | ||
13 | # With EVM the situation might be different because access | ||
14 | # to the EVM key can be restricted. | ||
15 | # | ||
16 | # Files which are appraised are also measured. This allows | ||
17 | # debugging whether a file is in policy by looking at | ||
18 | # /sys/kernel/security/ima/ascii_runtime_measurements | ||
19 | |||
20 | # PROC_SUPER_MAGIC | ||
21 | dont_appraise fsmagic=0x9fa0 | ||
22 | dont_measure fsmagic=0x9fa0 | ||
23 | # SYSFS_MAGIC | ||
24 | dont_appraise fsmagic=0x62656572 | ||
25 | dont_measure fsmagic=0x62656572 | ||
26 | # DEBUGFS_MAGIC | ||
27 | dont_appraise fsmagic=0x64626720 | ||
28 | dont_measure fsmagic=0x64626720 | ||
29 | # TMPFS_MAGIC | ||
30 | dont_appraise fsmagic=0x01021994 | ||
31 | dont_measure fsmagic=0x01021994 | ||
32 | # RAMFS_MAGIC | ||
33 | dont_appraise fsmagic=0x858458f6 | ||
34 | dont_measure fsmagic=0x858458f6 | ||
35 | # DEVPTS_SUPER_MAGIC | ||
36 | dont_appraise fsmagic=0x1cd1 | ||
37 | dont_measure fsmagic=0x1cd1 | ||
38 | # BIFMT | ||
39 | dont_appraise fsmagic=0x42494e4d | ||
40 | dont_measure fsmagic=0x42494e4d | ||
41 | # SECURITYFS_MAGIC | ||
42 | dont_appraise fsmagic=0x73636673 | ||
43 | dont_measure fsmagic=0x73636673 | ||
44 | # SELINUXFS_MAGIC | ||
45 | dont_appraise fsmagic=0xf97cff8c | ||
46 | dont_measure fsmagic=0xf97cff8c | ||
47 | # NSFS_MAGIC (introduced in 3.19, see cd025f7 and e149ed2 in the upstream Linux kernel) | ||
48 | dont_appraise fsmagic=0x6e736673 | ||
49 | dont_measure fsmagic=0x6e736673 | ||
50 | # SMACK_MAGIC | ||
51 | dont_appraise fsmagic=0x43415d53 | ||
52 | dont_measure fsmagic=0x43415d53 | ||
53 | # CGROUP_SUPER_MAGIC | ||
54 | dont_appraise fsmagic=0x27e0eb | ||
55 | dont_measure fsmagic=0x27e0eb | ||
56 | # EFIVARFS_MAGIC | ||
57 | dont_appraise fsmagic=0xde5e81e4 | ||
58 | dont_measure fsmagic=0xde5e81e4 | ||
59 | |||
60 | # Special partition, no checking done. | ||
61 | # dont_measure fsuuid=a11234... | ||
62 | # dont_appraise fsuuid=a11243... | ||
63 | |||
64 | # Special immutable group. | ||
65 | # appraise appraise_type=imasig func=FILE_CHECK mask=MAY_READ fgroup=200 | ||
66 | |||
67 | # All executables must be signed - too strict, we need to | ||
68 | # allow installing executables on the device. | ||
69 | # appraise appraise_type=imasig func=FILE_MMAP mask=MAY_EXEC | ||
70 | # appraise appraise_type=imasig func=BPRM_CHECK mask=MAY_EXEC | ||
71 | |||
72 | # Default rule. Would be needed also when other rules were added that | ||
73 | # determine what to do in case of reading (mask=MAY_READ or | ||
74 | # mask=MAY_EXEC) because otherwise writing does not update the file | ||
75 | # hash. | ||
76 | appraise | ||
77 | measure | ||
diff --git a/meta-integrity/data/ima_policy_simple b/meta-integrity/data/ima_policy_simple new file mode 100644 index 0000000..38ca8f5 --- /dev/null +++ b/meta-integrity/data/ima_policy_simple | |||
@@ -0,0 +1,4 @@ | |||
1 | # Very simple policy demonstrating the systemd policy loading bug | ||
2 | # (policy with one line works, two lines don't). | ||
3 | dont_appraise fsmagic=0x9fa0 | ||
4 | dont_appraise fsmagic=0x62656572 | ||
diff --git a/meta-integrity/lib/oeqa/runtime/__init__.py b/meta-integrity/lib/oeqa/runtime/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/meta-integrity/lib/oeqa/runtime/__init__.py | |||
diff --git a/meta-integrity/lib/oeqa/runtime/ima.py b/meta-integrity/lib/oeqa/runtime/ima.py new file mode 100644 index 0000000..2e5b258 --- /dev/null +++ b/meta-integrity/lib/oeqa/runtime/ima.py | |||
@@ -0,0 +1,82 @@ | |||
1 | #!/usr/bin/env python | ||
2 | # | ||
3 | # Authors: Cristina Moraru <cristina.moraru@intel.com> | ||
4 | # Alexandru Cornea <alexandru.cornea@intel.com> | ||
5 | |||
6 | import unittest | ||
7 | import string | ||
8 | from time import sleep | ||
9 | from oeqa.oetest import oeRuntimeTest, skipModule | ||
10 | from oeqa.utils.decorators import * | ||
11 | |||
12 | @tag(TestType = 'FVT', FeatureID = 'IOTOS-617,IOTOS-619') | ||
13 | class IMACheck(oeRuntimeTest): | ||
14 | def test_ima_before_systemd(self): | ||
15 | ''' Test if IMA policy is loaded before systemd starts''' | ||
16 | |||
17 | ima_search = "IMA: policy update completed" | ||
18 | systemd_search = "systemd .* running" | ||
19 | status, output = self.target.run("dmesg | grep -n '%s'" %ima_search) | ||
20 | self.assertEqual( status, 0, "Did not find '%s' in dmesg" %ima_search) | ||
21 | ima_id = int(output.split(":")[0]) | ||
22 | status, output = self.target.run("dmesg | grep -n '%s'" %systemd_search) | ||
23 | self.assertEqual(status, 0, "Did not find '%s' in dmesg" %systemd_search) | ||
24 | init_id = int(output.split(":")[0]) | ||
25 | if ima_id > init_id: | ||
26 | self.fail("IMA does not start before systemd") | ||
27 | |||
28 | def test_ima_hash(self): | ||
29 | ''' Test if IMA stores correct file hash ''' | ||
30 | filename = "/etc/filetest" | ||
31 | ima_measure_file = "/sys/kernel/security/ima/ascii_runtime_measurements" | ||
32 | status, output = self.target.run("echo test > %s" %filename) | ||
33 | self.assertEqual(status, 0, "Cannot create file %s on target" %filename) | ||
34 | |||
35 | # wait for the IMA system to update the entry | ||
36 | maximum_tries = 30 | ||
37 | tries = 0 | ||
38 | status, output = self.target.run("sha1sum %s" %filename) | ||
39 | current_hash = output.split()[0] | ||
40 | ima_hash = "" | ||
41 | |||
42 | while tries < maximum_tries: | ||
43 | status, output = self.target.run("cat %s | grep %s" \ | ||
44 | %(ima_measure_file, filename)) | ||
45 | # get last entry, 4th field | ||
46 | if status == 0: | ||
47 | tokens = output.split("\n")[-1].split()[3] | ||
48 | ima_hash = tokens.split(":")[1] | ||
49 | if ima_hash == current_hash: | ||
50 | break | ||
51 | |||
52 | tries += 1 | ||
53 | sleep(1) | ||
54 | |||
55 | # clean target | ||
56 | self.target.run("rm %s" %filename) | ||
57 | if ima_hash != current_hash: | ||
58 | self.fail("Hash stored by IMA does not match actual hash") | ||
59 | |||
60 | def test_ima_signature(self): | ||
61 | ''' Test if IMA stores correct signature for system binaries''' | ||
62 | locations = ["/bin", "/usr/bin"] | ||
63 | binaries = [] | ||
64 | for l in locations: | ||
65 | status, output = self.target.run("find %s -type f" %l) | ||
66 | binaries.extend(output.split("\n")) | ||
67 | |||
68 | for b in binaries: | ||
69 | status, output = self.target.run("evmctl ima_verify %s" %b) | ||
70 | if "Verification is OK" not in output: | ||
71 | self.fail("IMA signature verification fails for file %s" %b) | ||
72 | |||
73 | def test_ima_overwrite(self): | ||
74 | ''' Test if IMA prevents overwriting signed files ''' | ||
75 | status, output = self.target.run("find /bin -type f") | ||
76 | self.assertEqual(status, 0 , "ssh to device fail: %s" %output) | ||
77 | signed_file = output.strip().split()[0] | ||
78 | print("\n signed_file is %s" % signed_file) | ||
79 | status, output = self.target.run(" echo 'foo' >> %s" %signed_file) | ||
80 | self.assertNotEqual(status, 0 , "Signed file could be written") | ||
81 | self.assertIn("Permission denied", output, | ||
82 | "Did not find expected error message. Got: %s" %output) | ||
diff --git a/meta-integrity/recipes-core/initrdscripts/initramfs-framework-ima.bb b/meta-integrity/recipes-core/initrdscripts/initramfs-framework-ima.bb new file mode 100644 index 0000000..aca38b7 --- /dev/null +++ b/meta-integrity/recipes-core/initrdscripts/initramfs-framework-ima.bb | |||
@@ -0,0 +1,32 @@ | |||
1 | # This recipe creates a module for the initramfs-framework in OE-core | ||
2 | # which initializes IMA by loading a policy before transferring | ||
3 | # control to the init process in the rootfs. The advantage over having | ||
4 | # that init process doing the policy loading (which systemd could do) | ||
5 | # is that already the integrity of the init binary itself will be | ||
6 | # checked by the kernel. | ||
7 | |||
8 | SUMMARY = "IMA module for the modular initramfs system" | ||
9 | LICENSE = "MIT" | ||
10 | LIC_FILES_CHKSUM = "file://${COREBASE}/meta/COPYING.MIT;md5=3da9cfbcb788c80a0384361b4de20420" | ||
11 | RDEPENDS_${PN} += "initramfs-framework-base" | ||
12 | |||
13 | # This policy file will get installed as /etc/ima/ima-policy. | ||
14 | # It is located via the normal file search path, so a .bbappend | ||
15 | # to this recipe can just point towards one of its own files. | ||
16 | IMA_POLICY ?= "ima_policy_hashed" | ||
17 | FILESEXTRAPATHS =. "${IMA_EVM_BASE}/data:" | ||
18 | |||
19 | SRC_URI = " \ | ||
20 | file://${IMA_POLICY} \ | ||
21 | file://ima \ | ||
22 | " | ||
23 | |||
24 | do_install () { | ||
25 | install -d ${D}/${sysconfdir}/ima | ||
26 | install ${WORKDIR}/${IMA_POLICY} ${D}/${sysconfdir}/ima-policy | ||
27 | install -d ${D}/init.d | ||
28 | install ${WORKDIR}/ima ${D}/init.d/20-ima | ||
29 | } | ||
30 | |||
31 | FILES_${PN} = "/init.d ${sysconfdir}" | ||
32 | RDEPENDS_${PN} = "keyutils" | ||
diff --git a/meta-integrity/recipes-core/initrdscripts/initramfs-framework-ima/ima b/meta-integrity/recipes-core/initrdscripts/initramfs-framework-ima/ima new file mode 100644 index 0000000..8616f99 --- /dev/null +++ b/meta-integrity/recipes-core/initrdscripts/initramfs-framework-ima/ima | |||
@@ -0,0 +1,52 @@ | |||
1 | #!/bin/sh | ||
2 | # | ||
3 | # Loads IMA policy into the kernel. | ||
4 | |||
5 | ima_enabled() { | ||
6 | if [ "$bootparam_no_ima" = "true" ]; then | ||
7 | return 1 | ||
8 | fi | ||
9 | } | ||
10 | |||
11 | ima_run() { | ||
12 | info "Initializing IMA (can be skipped with no_ima boot parameter)." | ||
13 | if ! grep -w securityfs /proc/mounts >/dev/null; then | ||
14 | if ! mount -t securityfs securityfs /sys/kernel/security; then | ||
15 | fatal "Could not mount securityfs." | ||
16 | fi | ||
17 | fi | ||
18 | if [ ! -d /sys/kernel/security/ima ]; then | ||
19 | fatal "No /sys/kernel/security/ima. Cannot proceed without IMA enabled in the kernel." | ||
20 | fi | ||
21 | |||
22 | # Instead of depending on the kernel to load the IMA X.509 certificate, | ||
23 | # use keyctl. This avoids a bug in certain kernels (https://lkml.org/lkml/2015/9/10/492) | ||
24 | # where the loaded key was not checked sufficiently. We use keyctl here because it is | ||
25 | # slightly smaller than evmctl and is needed anyway. | ||
26 | # (see http://sourceforge.net/p/linux-ima/ima-evm-utils/ci/v0.9/tree/README#l349). | ||
27 | for kind in ima evm; do | ||
28 | key=/etc/keys/x509_$kind.der | ||
29 | if [ -s $key ]; then | ||
30 | id=$(grep -w -e "\.$kind" /proc/keys | cut -d ' ' -f1 | head -n 1) | ||
31 | if [ "$id" ]; then | ||
32 | id=$(printf "%d" 0x$id) | ||
33 | fi | ||
34 | if [ -z "$id" ]; then | ||
35 | id=`keyctl search @u keyring _$kind 2>/dev/null` | ||
36 | if [ -z "$id" ]; then | ||
37 | id=`keyctl newring _$kind @u` | ||
38 | fi | ||
39 | fi | ||
40 | info "Loading $key into $kind keyring $id" | ||
41 | keyctl padd asymmetric "" $id <$key | ||
42 | fi | ||
43 | done | ||
44 | |||
45 | # In theory, a simple "cat" should be enough. In practice, loading sometimes fails randomly | ||
46 | # ("[Linux-ima-user] IMA policy loading via cat") and we get better error reporting when | ||
47 | # checking the write of each line. To minimize the risk of policy loading going wrong we | ||
48 | # also remove comments and blank lines ourselves. | ||
49 | if ! (set -e; while read i; do if echo "$i" | grep -q -e '^#' -e '^ *$'; then debug "Skipping IMA policy: $i"; else debug "Writing IMA policy: $i"; if echo $i; then sleep ${bootparam_ima_delay:-0}; else fatal "Invalid line in IMA policy: $i"; exit 1; fi; fi; done) </etc/ima-policy >/sys/kernel/security/ima/policy; then | ||
50 | fatal "Could not load IMA policy." | ||
51 | fi | ||
52 | } | ||
diff --git a/meta-integrity/recipes-core/packagegroups/packagegroup-ima-evm-utils.bb b/meta-integrity/recipes-core/packagegroups/packagegroup-ima-evm-utils.bb new file mode 100644 index 0000000..18acc9d --- /dev/null +++ b/meta-integrity/recipes-core/packagegroups/packagegroup-ima-evm-utils.bb | |||
@@ -0,0 +1,9 @@ | |||
1 | SUMMARY = "IMA/EVM userspace tools" | ||
2 | LICENSE = "MIT" | ||
3 | |||
4 | inherit packagegroup | ||
5 | |||
6 | # Only one at the moment, but perhaps more will come in the future. | ||
7 | RDEPENDS_${PN} = " \ | ||
8 | ima-evm-utils \ | ||
9 | " | ||
diff --git a/meta-integrity/recipes-core/systemd/files/machine-id-commit-sync.conf b/meta-integrity/recipes-core/systemd/files/machine-id-commit-sync.conf new file mode 100644 index 0000000..d6d3240 --- /dev/null +++ b/meta-integrity/recipes-core/systemd/files/machine-id-commit-sync.conf | |||
@@ -0,0 +1,2 @@ | |||
1 | [Service] | ||
2 | ExecStartPost=/bin/sync | ||
diff --git a/meta-integrity/recipes-core/systemd/files/random-seed-sync.conf b/meta-integrity/recipes-core/systemd/files/random-seed-sync.conf new file mode 100644 index 0000000..f4c170b --- /dev/null +++ b/meta-integrity/recipes-core/systemd/files/random-seed-sync.conf | |||
@@ -0,0 +1,3 @@ | |||
1 | [Service] | ||
2 | ExecStopPost=/bin/sync | ||
3 | ExecStartPost=/bin/sync | ||
diff --git a/meta-integrity/recipes-core/systemd/systemd_%.bbappend b/meta-integrity/recipes-core/systemd/systemd_%.bbappend new file mode 100644 index 0000000..3b45541 --- /dev/null +++ b/meta-integrity/recipes-core/systemd/systemd_%.bbappend | |||
@@ -0,0 +1,13 @@ | |||
1 | FILESEXTRAPATHS_prepend := "${THISDIR}/files:" | ||
2 | |||
3 | SRC_URI += " \ | ||
4 | file://machine-id-commit-sync.conf \ | ||
5 | file://random-seed-sync.conf \ | ||
6 | " | ||
7 | |||
8 | do_install_append () { | ||
9 | for i in machine-id-commit random-seed; do | ||
10 | install -d ${D}/${systemd_system_unitdir}/systemd-$i.service.d | ||
11 | install -m 0644 ${WORKDIR}/$i-sync.conf ${D}/${systemd_system_unitdir}/systemd-$i.service.d | ||
12 | done | ||
13 | } | ||
diff --git a/meta-integrity/recipes-kernel/linux/linux-%.bbappend b/meta-integrity/recipes-kernel/linux/linux-%.bbappend new file mode 100644 index 0000000..48560b1 --- /dev/null +++ b/meta-integrity/recipes-kernel/linux/linux-%.bbappend | |||
@@ -0,0 +1,116 @@ | |||
1 | IMA_ENABLED_HERE := "${@'yes' if bb.data.inherits_class('kernel', d) and 'ima' in d.getVar('DISTRO_FEATURES', True).split() else 'no'}" | ||
2 | |||
3 | IMA_FILESEXTRAPATHS_yes := "${THISDIR}/linux:" | ||
4 | IMA_FILESEXTRAPATHS_no := "" | ||
5 | FILESEXTRAPATHS_prepend := "${IMA_FILESEXTRAPATHS_${IMA_ENABLED_HERE}}" | ||
6 | |||
7 | # These two patches are necessary to unpack archives with security.ima xattr | ||
8 | # such that security.ima is taken from the archive. If the policy | ||
9 | # allows hashing, unpatched kernels (at least up to 4.3) will replace | ||
10 | # a signed hash in security.ima with a locally computed hash. | ||
11 | # | ||
12 | # Note that only bsdtar/libarchive are known to work; GNU tar sets | ||
13 | # the security.ima on an empty file and the tries re-opening it for | ||
14 | # writing its content, which then fails due to the IMA hash mismatch. | ||
15 | # | ||
16 | # Kernels >= 4.7 have the patches, while older kernels are likely to | ||
17 | # need the patches. So apply them by default. To avoid that, | ||
18 | # set IMA_EVM_SETATTR_PATCH_x.y.z (where x.y.z == linux kernel version) | ||
19 | # to an empty string (to avoid patching) or some other patch files | ||
20 | # suitable for that kernel. | ||
21 | def ima_evm_setattr_patch(d): | ||
22 | result = [] | ||
23 | linux_version = d.getVar('LINUX_VERSION', True) or '' | ||
24 | # These two patches are known to be included upstream. | ||
25 | if bb.utils.vercmp_string_op(linux_version, '4.7', '<'): | ||
26 | patches = d.getVar('IMA_EVM_SETATTR_PATCH_' + linux_version, True) | ||
27 | if patches != None: | ||
28 | # Patches explicitly chosen, may be empty. | ||
29 | result.append(patches) | ||
30 | else: | ||
31 | # Enabled by default. | ||
32 | result.append('file://0001-ima-fix-ima_inode_post_setattr.patch file://0002-ima-add-support-for-creating-files-using-the-mknodat.patch') | ||
33 | # This one addresses a problem added in 4.2. The upstream revert will land | ||
34 | # in some future kernel. We need to extend version check once we know | ||
35 | # which kernels have the patch. | ||
36 | if bb.utils.vercmp_string_op(linux_version, '4.2', '>='): | ||
37 | patches = d.getVar('IMA_EVM_SETATTR_REVERT_PATCH_' + linux_version, True) | ||
38 | if patches != None: | ||
39 | # Patches explicitly chosen, may be empty. | ||
40 | result.append(patches) | ||
41 | else: | ||
42 | # Enabled by default. | ||
43 | result.append('file://Revert-ima-limit-file-hash-setting-by-user-to-fix-an.patch') | ||
44 | return ' '.join(result) | ||
45 | |||
46 | # Edison kernel too old, patch not applicable -> swupd is broken in Ostro OS for Edison. | ||
47 | IMA_EVM_SETATTR_PATCH_3.10.98 = "" | ||
48 | |||
49 | # Kernel config fragment enabling IMA/EVM and (where necessary and possible) | ||
50 | # also patching the kernel. | ||
51 | IMA_EVM_CFG_yes = " file://ima.cfg \ | ||
52 | ${@ ima_evm_setattr_patch(d)} \ | ||
53 | " | ||
54 | IMA_EVM_CFG_no = "" | ||
55 | SRC_URI_append = "${IMA_EVM_CFG_${IMA_ENABLED_HERE}}" | ||
56 | |||
57 | # IMA_EVM_ROOT_CA, if set, is the absolute path to a der-encoded | ||
58 | # x509 CA certificate which will get compiled into the kernel. | ||
59 | # The kernel will then use it to validate additional certificates, | ||
60 | # like the one loaded dynamically for IMA. | ||
61 | # | ||
62 | # Depending on the kernel version, there are two ways to add the | ||
63 | # CA certificate: | ||
64 | # - For Linux < 4.3, we put the x509 file into the source directory | ||
65 | # where the kernel compilation will find it automatically | ||
66 | # (http://lxr.free-electrons.com/source/kernel/Makefile?v=4.2#L115). | ||
67 | # - For Linux >= 4.3, we set SYSTEM_TRUSTED_KEYS | ||
68 | # (http://lxr.free-electrons.com/source/certs/Kconfig?v=4.3#L29). | ||
69 | # The ima_evm_root_ca.cfg only contains a blank file name. | ||
70 | # The actual file name gets patched in after the file was used | ||
71 | # to configure the kernel (see do_kernel_configme_append). | ||
72 | # This has to point to a single file, i.e. using it for IMA has to | ||
73 | # be coordinated with other usages. | ||
74 | # | ||
75 | # The IMA_EVM_ROOT_CA default is set globally in ima-evm-rootfs.bbclass. | ||
76 | # Need weaker default here in case that ima-evm-rootfs.bbclass is not | ||
77 | # inherited. | ||
78 | IMA_EVM_ROOT_CA ??= "" | ||
79 | |||
80 | # Add CONFIG_SYSTEM_TRUSTED_KEYS (for recent kernels) and | ||
81 | # copy the root certificate into the build directory. By using | ||
82 | # the normal fetcher mechanism for the certificate we ensure that | ||
83 | # a rebuild is triggered when the file name or content change. | ||
84 | # | ||
85 | # Recompiling on name change is a bit too aggressive and causes | ||
86 | # unnecessary rebuilds when only the location of the file, but not its | ||
87 | # content change. This may need further work, should it become a problem | ||
88 | # in practice. For example, IMA_EVM_ROOT_CA could be redefined as | ||
89 | # an URL that then gets found via the normal file lookup. | ||
90 | # | ||
91 | # The fetcher does not expand SRC_URI. We have to enforce that here. | ||
92 | IMA_EVM_ROOT_CA_CFG_yes = "${@ \ | ||
93 | ((' file://ima_evm_root_ca.cfg' if bb.utils.vercmp_string_op('${LINUX_VERSION}', '4.3', '>=') else '') + \ | ||
94 | ' file://${IMA_EVM_ROOT_CA}') \ | ||
95 | if '${IMA_EVM_ROOT_CA}' else ''}" | ||
96 | IMA_EVM_ROOT_CA_CFG_no = "" | ||
97 | |||
98 | SRC_URI_append = "${IMA_EVM_ROOT_CA_CFG_${IMA_ENABLED_HERE}}" | ||
99 | |||
100 | do_kernel_configme_append () { | ||
101 | if [ '${IMA_EVM_ROOT_CA}' ] && grep -q '^CONFIG_SYSTEM_TRUSTED_KEYS=' ${B}/.config; then | ||
102 | # We can replace a blank value from ima_evm_root_ca.cfg, | ||
103 | # but when we find some other value, then we have to abort | ||
104 | # because we can't set more than one value. | ||
105 | eval `grep '^CONFIG_SYSTEM_TRUSTED_KEYS='` | ||
106 | if [ "$CONFIG_SYSTEM_TRUSTED_KEYS" ] && [ "$CONFIG_SYSTEM_TRUSTED_KEYS" != "${IMA_EVM_ROOT_CA}" ]; then | ||
107 | bbfatal "CONFIG_SYSTEM_TRUSTED_KEYS already set to $CONFIG_SYSTEM_TRUSTED_KEYS, cannot replace with IMA_EVM_ROOT_CA = ${IMA_EVM_ROOT_CA}" | ||
108 | exit 1 | ||
109 | fi | ||
110 | pemcert=${B}/`basename ${IMA_EVM_ROOT_CA}`.pem | ||
111 | openssl x509 -inform der -in ${IMA_EVM_ROOT_CA} -out $pemcert | ||
112 | sed -i -e "s;^CONFIG_SYSTEM_TRUSTED_KEYS=.*;CONFIG_SYSTEM_TRUSTED_KEYS=\"$pemcert\";" ${B}/.config | ||
113 | fi | ||
114 | } | ||
115 | |||
116 | do_kernel_configme[depends] += "${@ 'openssl-native:do_populate_sysroot' if '${IMA_ENABLED_HERE}' == 'yes' and '${IMA_EVM_ROOT_CA}' else '' }" | ||
diff --git a/meta-integrity/recipes-kernel/linux/linux/0001-ima-fix-ima_inode_post_setattr.patch b/meta-integrity/recipes-kernel/linux/linux/0001-ima-fix-ima_inode_post_setattr.patch new file mode 100644 index 0000000..64016dd --- /dev/null +++ b/meta-integrity/recipes-kernel/linux/linux/0001-ima-fix-ima_inode_post_setattr.patch | |||
@@ -0,0 +1,51 @@ | |||
1 | From 45ea681ebc0dd44aaec5d3cc4143b9722070d3ac Mon Sep 17 00:00:00 2001 | ||
2 | From: Mimi Zohar <zohar@linux.vnet.ibm.com> | ||
3 | Date: Tue, 8 Mar 2016 16:43:55 -0500 | ||
4 | Subject: [PATCH] ima: fix ima_inode_post_setattr | ||
5 | |||
6 | Changing file metadata (eg. uid, guid) could result in having to | ||
7 | re-appraise a file's integrity, but does not change the "new file" | ||
8 | status nor the security.ima xattr. The IMA_PERMIT_DIRECTIO and | ||
9 | IMA_DIGSIG_REQUIRED flags are policy rule specific. This patch | ||
10 | only resets these flags, not the IMA_NEW_FILE or IMA_DIGSIG flags. | ||
11 | |||
12 | With this patch, changing the file timestamp will not remove the | ||
13 | file signature on new files. | ||
14 | |||
15 | Upstream-Status: Accepted [https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/security/integrity/ima/ima_appraise.c?id=42a4c603198f0d45b7aa936d3ac6ba1b8bd14a1b] | ||
16 | |||
17 | Reported-by: Dmitry Rozhkov <dmitry.rozhkov@linux.intel.com> | ||
18 | Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com> | ||
19 | --- | ||
20 | security/integrity/ima/ima_appraise.c | 2 +- | ||
21 | security/integrity/integrity.h | 1 + | ||
22 | 2 files changed, 2 insertions(+), 1 deletion(-) | ||
23 | |||
24 | diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c | ||
25 | index 4df493e..a384ba1 100644 | ||
26 | --- a/security/integrity/ima/ima_appraise.c | ||
27 | +++ b/security/integrity/ima/ima_appraise.c | ||
28 | @@ -327,7 +327,7 @@ void ima_inode_post_setattr(struct dentry *dentry) | ||
29 | if (iint) { | ||
30 | iint->flags &= ~(IMA_APPRAISE | IMA_APPRAISED | | ||
31 | IMA_APPRAISE_SUBMASK | IMA_APPRAISED_SUBMASK | | ||
32 | - IMA_ACTION_FLAGS); | ||
33 | + IMA_ACTION_RULE_FLAGS); | ||
34 | if (must_appraise) | ||
35 | iint->flags |= IMA_APPRAISE; | ||
36 | } | ||
37 | diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h | ||
38 | index 0fc9519..f9decae 100644 | ||
39 | --- a/security/integrity/integrity.h | ||
40 | +++ b/security/integrity/integrity.h | ||
41 | @@ -28,6 +28,7 @@ | ||
42 | |||
43 | /* iint cache flags */ | ||
44 | #define IMA_ACTION_FLAGS 0xff000000 | ||
45 | +#define IMA_ACTION_RULE_FLAGS 0x06000000 | ||
46 | #define IMA_DIGSIG 0x01000000 | ||
47 | #define IMA_DIGSIG_REQUIRED 0x02000000 | ||
48 | #define IMA_PERMIT_DIRECTIO 0x04000000 | ||
49 | -- | ||
50 | 2.5.0 | ||
51 | |||
diff --git a/meta-integrity/recipes-kernel/linux/linux/0002-ima-add-support-for-creating-files-using-the-mknodat.patch b/meta-integrity/recipes-kernel/linux/linux/0002-ima-add-support-for-creating-files-using-the-mknodat.patch new file mode 100644 index 0000000..6ab7ce2 --- /dev/null +++ b/meta-integrity/recipes-kernel/linux/linux/0002-ima-add-support-for-creating-files-using-the-mknodat.patch | |||
@@ -0,0 +1,138 @@ | |||
1 | From baaec960e9e7be0b526eaf831b079ddfe5c15124 Mon Sep 17 00:00:00 2001 | ||
2 | From: Mimi Zohar <zohar@linux.vnet.ibm.com> | ||
3 | Date: Thu, 10 Mar 2016 18:19:20 +0200 | ||
4 | Subject: [PATCH] ima: add support for creating files using the mknodat | ||
5 | syscall | ||
6 | |||
7 | Commit 3034a14 "ima: pass 'opened' flag to identify newly created files" | ||
8 | stopped identifying empty files as new files. However new empty files | ||
9 | can be created using the mknodat syscall. On systems with IMA-appraisal | ||
10 | enabled, these empty files are not labeled with security.ima extended | ||
11 | attributes properly, preventing them from subsequently being opened in | ||
12 | order to write the file data contents. This patch marks these empty | ||
13 | files, created using mknodat, as new in order to allow the file data | ||
14 | contents to be written. | ||
15 | |||
16 | Files with security.ima xattrs containing a file signature are considered | ||
17 | "immutable" and can not be modified. The file contents need to be | ||
18 | written, before signing the file. This patch relaxes this requirement | ||
19 | for new files, allowing the file signature to be written before the file | ||
20 | contents. | ||
21 | |||
22 | Upstream-Status: Accepted [https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/security/integrity/ima/ima_appraise.c?id=05d1a717ec0430c916a749b94eb90ab74bbfa356] | ||
23 | |||
24 | Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com> | ||
25 | --- | ||
26 | fs/namei.c | 2 ++ | ||
27 | include/linux/ima.h | 7 ++++++- | ||
28 | security/integrity/ima/ima_appraise.c | 3 +++ | ||
29 | security/integrity/ima/ima_main.c | 32 +++++++++++++++++++++++++++++++- | ||
30 | 4 files changed, 42 insertions(+), 2 deletions(-) | ||
31 | |||
32 | diff --git a/fs/namei.c b/fs/namei.c | ||
33 | index ccd7f98..19502da 100644 | ||
34 | --- a/fs/namei.c | ||
35 | +++ b/fs/namei.c | ||
36 | @@ -3526,6 +3526,8 @@ retry: | ||
37 | switch (mode & S_IFMT) { | ||
38 | case 0: case S_IFREG: | ||
39 | error = vfs_create(path.dentry->d_inode,dentry,mode,true); | ||
40 | + if (!error) | ||
41 | + ima_post_path_mknod(dentry); | ||
42 | break; | ||
43 | case S_IFCHR: case S_IFBLK: | ||
44 | error = vfs_mknod(path.dentry->d_inode,dentry,mode, | ||
45 | diff --git a/include/linux/ima.h b/include/linux/ima.h | ||
46 | index 120ccc5..7f51971 100644 | ||
47 | --- a/include/linux/ima.h | ||
48 | +++ b/include/linux/ima.h | ||
49 | @@ -20,7 +20,7 @@ extern void ima_file_free(struct file *file); | ||
50 | extern int ima_file_mmap(struct file *file, unsigned long prot); | ||
51 | extern int ima_module_check(struct file *file); | ||
52 | extern int ima_fw_from_file(struct file *file, char *buf, size_t size); | ||
53 | - | ||
54 | +extern void ima_post_path_mknod(struct dentry *dentry); | ||
55 | #else | ||
56 | static inline int ima_bprm_check(struct linux_binprm *bprm) | ||
57 | { | ||
58 | @@ -52,6 +52,11 @@ static inline int ima_fw_from_file(struct file *file, char *buf, size_t size) | ||
59 | return 0; | ||
60 | } | ||
61 | |||
62 | +static inline void ima_post_path_mknod(struct dentry *dentry) | ||
63 | +{ | ||
64 | + return; | ||
65 | +} | ||
66 | + | ||
67 | #endif /* CONFIG_IMA */ | ||
68 | |||
69 | #ifdef CONFIG_IMA_APPRAISE | ||
70 | diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c | ||
71 | index 4df493e..20806ea 100644 | ||
72 | --- a/security/integrity/ima/ima_appraise.c | ||
73 | +++ b/security/integrity/ima/ima_appraise.c | ||
74 | @@ -274,6 +274,11 @@ out: | ||
75 | xattr_value->type != EVM_IMA_XATTR_DIGSIG)) { | ||
76 | if (!ima_fix_xattr(dentry, iint)) | ||
77 | status = INTEGRITY_PASS; | ||
78 | + } else if ((inode->i_size == 0) && | ||
79 | + (iint->flags & IMA_NEW_FILE) && | ||
80 | + (xattr_value && | ||
81 | + xattr_value->type == EVM_IMA_XATTR_DIGSIG)) { | ||
82 | + status = INTEGRITY_PASS; | ||
83 | } | ||
84 | integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename, | ||
85 | op, cause, rc, 0); | ||
86 | diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c | ||
87 | index eeee00dc..705bf78 100644 | ||
88 | --- a/security/integrity/ima/ima_main.c | ||
89 | +++ b/security/integrity/ima/ima_main.c | ||
90 | @@ -242,7 +242,8 @@ static int process_measurement(struct file *file, int mask, int function, | ||
91 | ima_audit_measurement(iint, pathname); | ||
92 | |||
93 | out_digsig: | ||
94 | - if ((mask & MAY_WRITE) && (iint->flags & IMA_DIGSIG)) | ||
95 | + if ((mask & MAY_WRITE) && (iint->flags & IMA_DIGSIG) && | ||
96 | + !(iint->flags & IMA_NEW_FILE)) | ||
97 | rc = -EACCES; | ||
98 | kfree(xattr_value); | ||
99 | out_free: | ||
100 | @@ -310,6 +311,35 @@ int ima_file_check(struct file *file, int mask, int opened) | ||
101 | EXPORT_SYMBOL_GPL(ima_file_check); | ||
102 | |||
103 | /** | ||
104 | + * ima_post_path_mknod - mark as a new inode | ||
105 | + * @dentry: newly created dentry | ||
106 | + * | ||
107 | + * Mark files created via the mknodat syscall as new, so that the | ||
108 | + * file data can be written later. | ||
109 | + */ | ||
110 | +void ima_post_path_mknod(struct dentry *dentry) | ||
111 | +{ | ||
112 | + struct integrity_iint_cache *iint; | ||
113 | + struct inode *inode; | ||
114 | + int must_appraise; | ||
115 | + | ||
116 | + if (!dentry || !dentry->d_inode) | ||
117 | + return; | ||
118 | + | ||
119 | + inode = dentry->d_inode; | ||
120 | + if (inode->i_size != 0) | ||
121 | + return; | ||
122 | + | ||
123 | + must_appraise = ima_must_appraise(inode, MAY_ACCESS, FILE_CHECK); | ||
124 | + if (!must_appraise) | ||
125 | + return; | ||
126 | + | ||
127 | + iint = integrity_inode_get(inode); | ||
128 | + if (iint) | ||
129 | + iint->flags |= IMA_NEW_FILE; | ||
130 | +} | ||
131 | + | ||
132 | +/** | ||
133 | * ima_module_check - based on policy, collect/store/appraise measurement. | ||
134 | * @file: pointer to the file to be measured/appraised | ||
135 | * | ||
136 | -- | ||
137 | 2.5.0 | ||
138 | |||
diff --git a/meta-integrity/recipes-kernel/linux/linux/Revert-ima-limit-file-hash-setting-by-user-to-fix-an.patch b/meta-integrity/recipes-kernel/linux/linux/Revert-ima-limit-file-hash-setting-by-user-to-fix-an.patch new file mode 100644 index 0000000..157c007 --- /dev/null +++ b/meta-integrity/recipes-kernel/linux/linux/Revert-ima-limit-file-hash-setting-by-user-to-fix-an.patch | |||
@@ -0,0 +1,60 @@ | |||
1 | From a34d61850b680c152e1dcc958ee83c3ab3261c3d Mon Sep 17 00:00:00 2001 | ||
2 | From: Patrick Ohly <patrick.ohly@intel.com> | ||
3 | Date: Tue, 15 Nov 2016 10:10:23 +0100 | ||
4 | Subject: [PATCH] Revert "ima: limit file hash setting by user to fix and log | ||
5 | modes" | ||
6 | |||
7 | This reverts commit c68ed80c97d9720f51ef31fe91560fdd1e121533. | ||
8 | |||
9 | The original motivation was security hardening ("File hashes are | ||
10 | automatically set and updated and should not be manually set.") | ||
11 | |||
12 | However, that hardening ignores and breaks some valid use cases: | ||
13 | - File hashes might not be set because the file is currently | ||
14 | outside of the policy and therefore have to be set by the | ||
15 | creator. Examples: | ||
16 | - Booting into an initramfs with an IMA-enabled kernel but | ||
17 | without setting an IMA policy, then installing | ||
18 | the OS onto the target partition by unpacking a rootfs archive | ||
19 | which has the file hashes pre-computed. | ||
20 | - Unpacking a file into a staging area with meta data (like owner) | ||
21 | that leaves the file outside of the current policy, then changing | ||
22 | the meta data such that it becomes part of the current policy. | ||
23 | - "should not be set manually" implies that the creator is aware | ||
24 | of IMA semantic, the current system's configuration, and then | ||
25 | skips setting file hashes in security.ima if (and only if) the | ||
26 | kernel would prevent it. That's not the case for standard, unmodified | ||
27 | tools. Example: unpacking an archive with security.ima xattrs with | ||
28 | bsdtar or GNU tar. | ||
29 | |||
30 | Upstream-Status: Submitted [https://sourceforge.net/p/linux-ima/mailman/message/35492824/] | ||
31 | |||
32 | Signed-off-by: Patrick Ohly <patrick.ohly@intel.com> | ||
33 | --- | ||
34 | security/integrity/ima/ima_appraise.c | 8 ++------ | ||
35 | 1 file changed, 2 insertions(+), 6 deletions(-) | ||
36 | |||
37 | diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c | ||
38 | index 4b9b4a4..b8b2dd9 100644 | ||
39 | --- a/security/integrity/ima/ima_appraise.c | ||
40 | +++ b/security/integrity/ima/ima_appraise.c | ||
41 | @@ -385,14 +385,10 @@ int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name, | ||
42 | result = ima_protect_xattr(dentry, xattr_name, xattr_value, | ||
43 | xattr_value_len); | ||
44 | if (result == 1) { | ||
45 | - bool digsig; | ||
46 | - | ||
47 | if (!xattr_value_len || (xvalue->type >= IMA_XATTR_LAST)) | ||
48 | return -EINVAL; | ||
49 | - digsig = (xvalue->type == EVM_IMA_XATTR_DIGSIG); | ||
50 | - if (!digsig && (ima_appraise & IMA_APPRAISE_ENFORCE)) | ||
51 | - return -EPERM; | ||
52 | - ima_reset_appraise_flags(d_backing_inode(dentry), digsig); | ||
53 | + ima_reset_appraise_flags(d_backing_inode(dentry), | ||
54 | + (xvalue->type == EVM_IMA_XATTR_DIGSIG) ? 1 : 0); | ||
55 | result = 0; | ||
56 | } | ||
57 | return result; | ||
58 | -- | ||
59 | 2.1.4 | ||
60 | |||
diff --git a/meta-integrity/recipes-kernel/linux/linux/ima.cfg b/meta-integrity/recipes-kernel/linux/linux/ima.cfg new file mode 100644 index 0000000..02381aa --- /dev/null +++ b/meta-integrity/recipes-kernel/linux/linux/ima.cfg | |||
@@ -0,0 +1,16 @@ | |||
1 | # Enable bare minimum IMA measurement and appraisal as needed by this layer. | ||
2 | |||
3 | CONFIG_SECURITY=y | ||
4 | CONFIG_INTEGRITY=y | ||
5 | |||
6 | # measurement | ||
7 | CONFIG_IMA=y | ||
8 | |||
9 | # appraisal | ||
10 | CONFIG_IMA_APPRAISE=y | ||
11 | CONFIG_INTEGRITY_SIGNATURE=y | ||
12 | CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y | ||
13 | |||
14 | # Kernel will get built with embedded X.509 root CA key and all keys | ||
15 | # need to be signed with that. | ||
16 | CONFIG_IMA_TRUSTED_KEYRING=y | ||
diff --git a/meta-integrity/recipes-kernel/linux/linux/ima_evm_root_ca.cfg b/meta-integrity/recipes-kernel/linux/linux/ima_evm_root_ca.cfg new file mode 100644 index 0000000..7338232 --- /dev/null +++ b/meta-integrity/recipes-kernel/linux/linux/ima_evm_root_ca.cfg | |||
@@ -0,0 +1,3 @@ | |||
1 | CONFIG_KEYS=y | ||
2 | CONFIG_SYSTEM_TRUSTED_KEYRING=y | ||
3 | CONFIG_SYSTEM_TRUSTED_KEYS="" | ||
diff --git a/meta-integrity/recipes-security/ima-evm-utils/ima-evm-utils.inc b/meta-integrity/recipes-security/ima-evm-utils/ima-evm-utils.inc new file mode 100644 index 0000000..72a13f7 --- /dev/null +++ b/meta-integrity/recipes-security/ima-evm-utils/ima-evm-utils.inc | |||
@@ -0,0 +1,19 @@ | |||
1 | DESCRIPTION = "IMA/EVM control utility" | ||
2 | LICENSE = "GPL-2.0-with-OpenSSL-exception" | ||
3 | LIC_FILES_CHKSUM = "file://COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263" | ||
4 | |||
5 | DEPENDS = " \ | ||
6 | openssl \ | ||
7 | attr \ | ||
8 | keyutils \ | ||
9 | pkgconfig \ | ||
10 | " | ||
11 | |||
12 | # blkid is called by evmctl when creating evm checksums. | ||
13 | # This is less useful when signing files on the build host, | ||
14 | # so disable it when compiling on the host. | ||
15 | RDEPENDS_${PN}_append_class-target = " util-linux-blkid" | ||
16 | |||
17 | inherit autotools | ||
18 | |||
19 | BBCLASSEXTEND = "native" | ||
diff --git a/meta-integrity/recipes-security/ima-evm-utils/ima-evm-utils/command-line-apply-operation-to-all-paths.patch b/meta-integrity/recipes-security/ima-evm-utils/ima-evm-utils/command-line-apply-operation-to-all-paths.patch new file mode 100644 index 0000000..35c3162 --- /dev/null +++ b/meta-integrity/recipes-security/ima-evm-utils/ima-evm-utils/command-line-apply-operation-to-all-paths.patch | |||
@@ -0,0 +1,68 @@ | |||
1 | From 5834216fb3aa4e5e59ee13e871c70db1b4e13f02 Mon Sep 17 00:00:00 2001 | ||
2 | From: Patrick Ohly <patrick.ohly@intel.com> | ||
3 | Date: Fri, 30 Sep 2016 10:22:16 +0200 | ||
4 | Subject: [PATCH] command line: apply operation to all paths | ||
5 | |||
6 | Previously, invocations like "evmctl ima_hash foo bar" silently | ||
7 | ignored all parameters after the first path name ("foo" in this | ||
8 | example). | ||
9 | |||
10 | Now evmctl iterates over all specified paths. It aborts with an | ||
11 | error as soon as the selected operation fails for a path. | ||
12 | |||
13 | Supporting more than one parameter is useful in combination with | ||
14 | "find" and "xargs" because it is noticably faster than invoking | ||
15 | evmutil separately for each file, in particular when run under pseudo | ||
16 | (a fakeroot environment used by the OpenEmbedded build system). | ||
17 | |||
18 | This complements the recursive mode and can be used when more control | ||
19 | over file selection is needed. | ||
20 | |||
21 | Signed-off-by: Patrick Ohly <patrick.ohly@intel.com> | ||
22 | --- | ||
23 | src/evmctl.c | 21 ++++++++++++--------- | ||
24 | 1 file changed, 12 insertions(+), 9 deletions(-) | ||
25 | |||
26 | diff --git a/src/evmctl.c b/src/evmctl.c | ||
27 | index 23cf54c..2072034 100644 | ||
28 | --- a/src/evmctl.c | ||
29 | +++ b/src/evmctl.c | ||
30 | @@ -626,7 +626,7 @@ static int get_file_type(const char *path, const char *search_type) | ||
31 | static int do_cmd(struct command *cmd, find_cb_t func) | ||
32 | { | ||
33 | char *path = g_argv[optind++]; | ||
34 | - int err, dts = REG_MASK; /* only regular files by default */ | ||
35 | + int err = 0, dts = REG_MASK; /* only regular files by default */ | ||
36 | |||
37 | if (!path) { | ||
38 | log_err("Parameters missing\n"); | ||
39 | @@ -634,15 +634,18 @@ static int do_cmd(struct command *cmd, find_cb_t func) | ||
40 | return -1; | ||
41 | } | ||
42 | |||
43 | - if (recursive) { | ||
44 | - if (search_type) { | ||
45 | - dts = get_file_type(path, search_type); | ||
46 | - if (dts < 0) | ||
47 | - return dts; | ||
48 | + while (path && !err) { | ||
49 | + if (recursive) { | ||
50 | + if (search_type) { | ||
51 | + dts = get_file_type(path, search_type); | ||
52 | + if (dts < 0) | ||
53 | + return dts; | ||
54 | + } | ||
55 | + err = find(path, dts, func); | ||
56 | + } else { | ||
57 | + err = func(path); | ||
58 | } | ||
59 | - err = find(path, dts, func); | ||
60 | - } else { | ||
61 | - err = func(path); | ||
62 | + path = g_argv[optind++]; | ||
63 | } | ||
64 | |||
65 | return err; | ||
66 | -- | ||
67 | 2.1.4 | ||
68 | |||
diff --git a/meta-integrity/recipes-security/ima-evm-utils/ima-evm-utils/disable-doc-creation.patch b/meta-integrity/recipes-security/ima-evm-utils/ima-evm-utils/disable-doc-creation.patch new file mode 100644 index 0000000..75076f5 --- /dev/null +++ b/meta-integrity/recipes-security/ima-evm-utils/ima-evm-utils/disable-doc-creation.patch | |||
@@ -0,0 +1,50 @@ | |||
1 | From 321a602098d11ee712ebd01f51033b5fd369eae9 Mon Sep 17 00:00:00 2001 | ||
2 | From: Patrick Ohly <patrick.ohly@intel.com> | ||
3 | Date: Wed, 13 May 2015 03:41:02 -0700 | ||
4 | Subject: [PATCH] Makefile.am: disable man page creation | ||
5 | |||
6 | Depends on asciidoc, which is not available. | ||
7 | |||
8 | Upstream-Status: Inappropriate [embedded specific] | ||
9 | |||
10 | Signed-off-by: Patrick Ohly <patrick.ohly@intel.com> | ||
11 | --- | ||
12 | Makefile.am | 19 ++++++++++++++++++- | ||
13 | 1 file changed, 18 insertions(+), 1 deletion(-) | ||
14 | |||
15 | diff --git a/Makefile.am b/Makefile.am | ||
16 | index 06ebf59..4ddd52c 100644 | ||
17 | --- a/Makefile.am | ||
18 | +++ b/Makefile.am | ||
19 | @@ -1,5 +1,5 @@ | ||
20 | SUBDIRS = src | ||
21 | -dist_man_MANS = evmctl.1 | ||
22 | +# dist_man_MANS = evmctl.1 | ||
23 | |||
24 | doc_DATA = examples/ima-genkey-self.sh examples/ima-genkey.sh examples/ima-gen-local-ca.sh | ||
25 | EXTRA_DIST = autogen.sh $(doc_DATA) | ||
26 | @@ -39,4 +39,21 @@ rmman: | ||
27 | |||
28 | doc: evmctl.1.html rmman evmctl.1 | ||
29 | |||
30 | +# requires asciidoc, xslproc, docbook-xsl | ||
31 | +# FIXME Disabled until docbook-xsl is unavaliable on tizen.org | ||
32 | +#MANPAGE_DOCBOOK_XSL = /usr/share/xml/docbook/stylesheet/docbook-xsl/manpages/docbook.xsl | ||
33 | +# | ||
34 | +#evmctl.1.html: README | ||
35 | +# @asciidoc -o $@ $< | ||
36 | +# | ||
37 | +#evmctl.1: | ||
38 | +# asciidoc -d manpage -b docbook -o evmctl.1.xsl README | ||
39 | +# xsltproc --nonet -o $@ $(MANPAGE_DOCBOOK_XSL) evmctl.1.xsl | ||
40 | +# rm -f evmctl.1.xsl | ||
41 | +# | ||
42 | +#rmman: | ||
43 | +# rm -f evmctl.1 | ||
44 | +# | ||
45 | +#doc: evmctl.1.html rmman evmctl.1 | ||
46 | + | ||
47 | .PHONY: $(tarname) | ||
48 | -- | ||
49 | 1.8.4.5 | ||
50 | |||
diff --git a/meta-integrity/recipes-security/ima-evm-utils/ima-evm-utils/evmctl.c-do-not-depend-on-xattr.h-with-IMA-defines.patch b/meta-integrity/recipes-security/ima-evm-utils/ima-evm-utils/evmctl.c-do-not-depend-on-xattr.h-with-IMA-defines.patch new file mode 100644 index 0000000..c0bdd9b --- /dev/null +++ b/meta-integrity/recipes-security/ima-evm-utils/ima-evm-utils/evmctl.c-do-not-depend-on-xattr.h-with-IMA-defines.patch | |||
@@ -0,0 +1,47 @@ | |||
1 | From 2dec9199f8a8a2c84b25a3d3e7e2f41b71e07834 Mon Sep 17 00:00:00 2001 | ||
2 | From: Patrick Ohly <patrick.ohly@intel.com> | ||
3 | Date: Wed, 17 Jun 2015 14:28:18 +0200 | ||
4 | Subject: [PATCH 20/20] evmctl.c: do not depend on xattr.h with IMA defines | ||
5 | |||
6 | Compilation on older Linux distros (like Ubuntu 12.04) fails | ||
7 | because linux/xattr.h does not yet have the IMA defines. Compiling | ||
8 | there makes sense when only the tools are needed, for example when | ||
9 | signing an image in cross-compile mode. | ||
10 | |||
11 | To support this, add fallbacks for the two defines which are needed. | ||
12 | Their value is part of the Linux ABI and thus fixed. | ||
13 | |||
14 | Upstream-status: Submitted [linux-ima-devel@lists.sourceforge.net] | ||
15 | |||
16 | Signed-off-by: Patrick Ohly <patrick.ohly@intel.com> | ||
17 | |||
18 | --- | ||
19 | src/evmctl.c | 12 ++++++++++++ | ||
20 | 1 file changed, 12 insertions(+) | ||
21 | |||
22 | diff --git a/src/evmctl.c b/src/evmctl.c | ||
23 | index c54efbb..23cf54c 100644 | ||
24 | --- a/src/evmctl.c | ||
25 | +++ b/src/evmctl.c | ||
26 | @@ -56,6 +56,18 @@ | ||
27 | #include <ctype.h> | ||
28 | #include <termios.h> | ||
29 | |||
30 | +/* | ||
31 | + * linux/xattr.h might be old to have this. Allow compilation on older | ||
32 | + * Linux distros (like Ubuntu 12.04) by falling back to our own | ||
33 | + * definition. | ||
34 | + */ | ||
35 | +#ifndef XATTR_IMA_SUFFIX | ||
36 | +# define XATTR_IMA_SUFFIX "ima" | ||
37 | +#endif | ||
38 | +#ifndef XATTR_NAME_IMA | ||
39 | +# define XATTR_NAME_IMA XATTR_SECURITY_PREFIX XATTR_IMA_SUFFIX | ||
40 | +#endif | ||
41 | + | ||
42 | #include <openssl/sha.h> | ||
43 | #include <openssl/pem.h> | ||
44 | #include <openssl/hmac.h> | ||
45 | -- | ||
46 | 2.1.4 | ||
47 | |||
diff --git a/meta-integrity/recipes-security/ima-evm-utils/ima-evm-utils_git.bb b/meta-integrity/recipes-security/ima-evm-utils/ima-evm-utils_git.bb new file mode 100644 index 0000000..8a9999f --- /dev/null +++ b/meta-integrity/recipes-security/ima-evm-utils/ima-evm-utils_git.bb | |||
@@ -0,0 +1,17 @@ | |||
1 | require ima-evm-utils.inc | ||
2 | |||
3 | PV = "1.0+git${SRCPV}" | ||
4 | SRCREV = "3e2a67bdb0673581a97506262e62db098efef6d7" | ||
5 | SRC_URI = "git://git.code.sf.net/p/linux-ima/ima-evm-utils" | ||
6 | S = "${WORKDIR}/git" | ||
7 | |||
8 | # Documentation depends on asciidoc, which we do not have, so | ||
9 | # do not build documentation. | ||
10 | SRC_URI += "file://disable-doc-creation.patch" | ||
11 | |||
12 | # Workaround for upstream incompatibility with older Linux distros. | ||
13 | # Relevant for us when compiling ima-evm-utils-native. | ||
14 | SRC_URI += "file://evmctl.c-do-not-depend-on-xattr.h-with-IMA-defines.patch" | ||
15 | |||
16 | # Required for xargs with more than one path as argument (better for performance). | ||
17 | SRC_URI += "file://command-line-apply-operation-to-all-paths.patch" | ||
diff --git a/meta-integrity/scripts/ima-gen-CA-signed.sh b/meta-integrity/scripts/ima-gen-CA-signed.sh new file mode 100755 index 0000000..5f3a728 --- /dev/null +++ b/meta-integrity/scripts/ima-gen-CA-signed.sh | |||
@@ -0,0 +1,48 @@ | |||
1 | #!/bin/sh | ||
2 | # | ||
3 | # Copied from ima-evm-utils. | ||
4 | # | ||
5 | # This program is free software; you can redistribute it and/or | ||
6 | # modify it under the terms of the GNU General Public License | ||
7 | # version 2 as published by the Free Software Foundation. | ||
8 | # | ||
9 | # This program is distributed in the hope that it will be useful, | ||
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | # GNU General Public License for more details. | ||
13 | # | ||
14 | # You should have received a copy of the GNU General Public License | ||
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
16 | |||
17 | GENKEY=ima.genkey | ||
18 | CA=${1:-ima-local-ca.pem} | ||
19 | CAKEY=${2:-ima-local-ca.priv} | ||
20 | |||
21 | cat << __EOF__ >$GENKEY | ||
22 | [ req ] | ||
23 | default_bits = 1024 | ||
24 | distinguished_name = req_distinguished_name | ||
25 | prompt = no | ||
26 | string_mask = utf8only | ||
27 | x509_extensions = v3_usr | ||
28 | |||
29 | [ req_distinguished_name ] | ||
30 | O = example.com | ||
31 | CN = meta-intel-iot-security example signing key | ||
32 | emailAddress = john.doe@example.com | ||
33 | |||
34 | [ v3_usr ] | ||
35 | basicConstraints=critical,CA:FALSE | ||
36 | #basicConstraints=CA:FALSE | ||
37 | keyUsage=digitalSignature | ||
38 | #keyUsage = nonRepudiation, digitalSignature, keyEncipherment | ||
39 | subjectKeyIdentifier=hash | ||
40 | authorityKeyIdentifier=keyid | ||
41 | #authorityKeyIdentifier=keyid,issuer | ||
42 | __EOF__ | ||
43 | |||
44 | openssl req -new -nodes -utf8 -sha1 -days 365 -batch -config $GENKEY \ | ||
45 | -out csr_ima.pem -keyout privkey_ima.pem | ||
46 | openssl x509 -req -in csr_ima.pem -days 365 -extfile $GENKEY -extensions v3_usr \ | ||
47 | -CA $CA -CAkey $CAKEY -CAcreateserial \ | ||
48 | -outform DER -out x509_ima.der | ||
diff --git a/meta-integrity/scripts/ima-gen-local-ca.sh b/meta-integrity/scripts/ima-gen-local-ca.sh new file mode 100755 index 0000000..b600761 --- /dev/null +++ b/meta-integrity/scripts/ima-gen-local-ca.sh | |||
@@ -0,0 +1,42 @@ | |||
1 | #!/bin/sh | ||
2 | # | ||
3 | # Copied from ima-evm-utils. | ||
4 | # | ||
5 | # This program is free software; you can redistribute it and/or | ||
6 | # modify it under the terms of the GNU General Public License | ||
7 | # version 2 as published by the Free Software Foundation. | ||
8 | # | ||
9 | # This program is distributed in the hope that it will be useful, | ||
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | # GNU General Public License for more details. | ||
13 | # | ||
14 | # You should have received a copy of the GNU General Public License | ||
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
16 | |||
17 | GENKEY=ima-local-ca.genkey | ||
18 | |||
19 | cat << __EOF__ >$GENKEY | ||
20 | [ req ] | ||
21 | default_bits = 2048 | ||
22 | distinguished_name = req_distinguished_name | ||
23 | prompt = no | ||
24 | string_mask = utf8only | ||
25 | x509_extensions = v3_ca | ||
26 | |||
27 | [ req_distinguished_name ] | ||
28 | O = example.com | ||
29 | CN = meta-intel-iot-security example certificate signing key | ||
30 | emailAddress = john.doe@example.com | ||
31 | |||
32 | [ v3_ca ] | ||
33 | basicConstraints=CA:TRUE | ||
34 | subjectKeyIdentifier=hash | ||
35 | authorityKeyIdentifier=keyid:always,issuer | ||
36 | # keyUsage = cRLSign, keyCertSign | ||
37 | __EOF__ | ||
38 | |||
39 | openssl req -new -x509 -utf8 -sha1 -days 3650 -batch -config $GENKEY \ | ||
40 | -outform DER -out ima-local-ca.x509 -keyout ima-local-ca.priv | ||
41 | |||
42 | openssl x509 -inform DER -in ima-local-ca.x509 -out ima-local-ca.pem | ||
diff --git a/meta-integrity/scripts/ima-gen-self-signed.sh b/meta-integrity/scripts/ima-gen-self-signed.sh new file mode 100755 index 0000000..5ee876c --- /dev/null +++ b/meta-integrity/scripts/ima-gen-self-signed.sh | |||
@@ -0,0 +1,41 @@ | |||
1 | #!/bin/sh | ||
2 | # | ||
3 | # Copied from ima-evm-utils. | ||
4 | # | ||
5 | # This program is free software; you can redistribute it and/or | ||
6 | # modify it under the terms of the GNU General Public License | ||
7 | # version 2 as published by the Free Software Foundation. | ||
8 | # | ||
9 | # This program is distributed in the hope that it will be useful, | ||
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | # GNU General Public License for more details. | ||
13 | # | ||
14 | # You should have received a copy of the GNU General Public License | ||
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
16 | |||
17 | GENKEY=ima.genkey | ||
18 | |||
19 | cat << __EOF__ >$GENKEY | ||
20 | [ req ] | ||
21 | default_bits = 1024 | ||
22 | distinguished_name = req_distinguished_name | ||
23 | prompt = no | ||
24 | string_mask = utf8only | ||
25 | x509_extensions = myexts | ||
26 | |||
27 | [ req_distinguished_name ] | ||
28 | O = example.com | ||
29 | CN = meta-intel-iot-security example signing key | ||
30 | emailAddress = john.doe@example.com | ||
31 | |||
32 | [ myexts ] | ||
33 | basicConstraints=critical,CA:FALSE | ||
34 | keyUsage=digitalSignature | ||
35 | subjectKeyIdentifier=hash | ||
36 | authorityKeyIdentifier=keyid | ||
37 | __EOF__ | ||
38 | |||
39 | openssl req -new -nodes -utf8 -sha1 -days 36500 -batch \ | ||
40 | -x509 -config $GENKEY \ | ||
41 | -outform DER -out x509_ima.der -keyout privkey_ima.pem | ||