Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security

Pull security subsystem updates from James Morris:
"Highlights:

- PKCS#7 support added to support signed kexec, also utilized for
module signing. See comments in 3f1e1bea.

** NOTE: this requires linking against the OpenSSL library, which
must be installed, e.g. the openssl-devel on Fedora **

- Smack
- add IPv6 host labeling; ignore labels on kernel threads
- support smack labeling mounts which use binary mount data

- SELinux:
- add ioctl whitelisting (see
http://kernsec.org/files/lss2015/vanderstoep.pdf)
- fix mprotect PROT_EXEC regression caused by mm change

- Seccomp:
- add ptrace options for suspend/resume"

* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (57 commits)
PKCS#7: Add OIDs for sha224, sha284 and sha512 hash algos and use them
Documentation/Changes: Now need OpenSSL devel packages for module signing
scripts: add extract-cert and sign-file to .gitignore
modsign: Handle signing key in source tree
modsign: Use if_changed rule for extracting cert from module signing key
Move certificate handling to its own directory
sign-file: Fix warning about BIO_reset() return value
PKCS#7: Add MODULE_LICENSE() to test module
Smack - Fix build error with bringup unconfigured
sign-file: Document dependency on OpenSSL devel libraries
PKCS#7: Appropriately restrict authenticated attributes and content type
KEYS: Add a name for PKEY_ID_PKCS7
PKCS#7: Improve and export the X.509 ASN.1 time object decoder
modsign: Use extract-cert to process CONFIG_SYSTEM_TRUSTED_KEYS
extract-cert: Cope with multiple X.509 certificates in a single file
sign-file: Generate CMS message as signature instead of PKCS#7
PKCS#7: Support CMS messages also [RFC5652]
X.509: Change recorded SKID & AKID to not include Subject or Issuer
PKCS#7: Check content type and versions
MAINTAINERS: The keyrings mailing list has moved
...

+3593 -1412
+1
.gitignore
··· 97 97 # Leavings from module signing 98 98 # 99 99 extra_certificates 100 + signing_key.pem 100 101 signing_key.priv 101 102 signing_key.x509 102 103 x509.genkey
+16 -1
Documentation/Changes
··· 43 43 o grub 0.93 # grub --version || grub-install --version 44 44 o mcelog 0.6 # mcelog --version 45 45 o iptables 1.4.2 # iptables -V 46 + o openssl & libcrypto 1.0.1k # openssl version 46 47 47 48 48 49 Kernel compilation ··· 78 77 -- 79 78 80 79 You will need bc to build kernels 3.10 and higher 80 + 81 + 82 + OpenSSL 83 + ------- 84 + 85 + Module signing and external certificate handling use the OpenSSL program and 86 + crypto library to do key creation and signature generation. 87 + 88 + You will need openssl to build kernels 3.7 and higher if module signing is 89 + enabled. You will also need openssl development packages to build kernels 4.3 90 + and higher. 81 91 82 92 83 93 System utilities ··· 307 295 -------- 308 296 o <ftp://ftp.kernel.org/pub/linux/devel/binutils/> 309 297 298 + OpenSSL 299 + ------- 300 + o <https://www.openssl.org/> 301 + 310 302 System utilities 311 303 **************** 312 304 ··· 408 392 NFS-Utils 409 393 --------- 410 394 o <http://nfs.sourceforge.net/> 411 -
+5
Documentation/kbuild/kbuild.txt
··· 174 174 175 175 The value can be overridden in which case the default value is ignored. 176 176 177 + KBUILD_SIGN_PIN 178 + -------------------------------------------------- 179 + This variable allows a passphrase or PIN to be passed to the sign-file 180 + utility when signing kernel modules, if the private key requires such. 181 + 177 182 KBUILD_MODPOST_WARN 178 183 -------------------------------------------------- 179 184 KBUILD_MODPOST_WARN can be set to avoid errors in case of undefined
+44 -12
Documentation/module-signing.txt
··· 89 89 their signatures checked without causing a dependency loop. 90 90 91 91 92 + (4) "File name or PKCS#11 URI of module signing key" (CONFIG_MODULE_SIG_KEY) 93 + 94 + Setting this option to something other than its default of 95 + "certs/signing_key.pem" will disable the autogeneration of signing keys 96 + and allow the kernel modules to be signed with a key of your choosing. 97 + The string provided should identify a file containing both a private key 98 + and its corresponding X.509 certificate in PEM form, or — on systems where 99 + the OpenSSL ENGINE_pkcs11 is functional — a PKCS#11 URI as defined by 100 + RFC7512. In the latter case, the PKCS#11 URI should reference both a 101 + certificate and a private key. 102 + 103 + If the PEM file containing the private key is encrypted, or if the 104 + PKCS#11 token requries a PIN, this can be provided at build time by 105 + means of the KBUILD_SIGN_PIN variable. 106 + 107 + 108 + (5) "Additional X.509 keys for default system keyring" (CONFIG_SYSTEM_TRUSTED_KEYS) 109 + 110 + This option can be set to the filename of a PEM-encoded file containing 111 + additional certificates which will be included in the system keyring by 112 + default. 113 + 114 + Note that enabling module signing adds a dependency on the OpenSSL devel 115 + packages to the kernel build processes for the tool that does the signing. 116 + 117 + 92 118 ======================= 93 119 GENERATING SIGNING KEYS 94 120 ======================= ··· 126 100 kernel so that it can be used to check the signatures as the modules are 127 101 loaded. 128 102 129 - Under normal conditions, the kernel build will automatically generate a new 130 - keypair using openssl if one does not exist in the files: 103 + Under normal conditions, when CONFIG_MODULE_SIG_KEY is unchanged from its 104 + default, the kernel build will automatically generate a new keypair using 105 + openssl if one does not exist in the file: 131 106 132 - signing_key.priv 133 - signing_key.x509 107 + certs/signing_key.pem 134 108 135 109 during the building of vmlinux (the public part of the key needs to be built 136 110 into vmlinux) using parameters in the: 137 111 138 - x509.genkey 112 + certs/x509.genkey 139 113 140 114 file (which is also generated if it does not already exist). 141 115 ··· 161 135 generate the public/private key files: 162 136 163 137 openssl req -new -nodes -utf8 -sha256 -days 36500 -batch -x509 \ 164 - -config x509.genkey -outform DER -out signing_key.x509 \ 165 - -keyout signing_key.priv 138 + -config x509.genkey -outform PEM -out kernel_key.pem \ 139 + -keyout kernel_key.pem 140 + 141 + The full pathname for the resulting kernel_key.pem file can then be specified 142 + in the CONFIG_MODULE_SIG_KEY option, and the certificate and key therein will 143 + be used instead of an autogenerated keypair. 166 144 167 145 168 146 ========================= ··· 182 152 302d2d52 I------ 1 perm 1f010000 0 0 asymmetri Fedora kernel signing key: d69a84e6bce3d216b979e9505b3e3ef9a7118079: X509.RSA a7118079 [] 183 153 ... 184 154 185 - Beyond the public key generated specifically for module signing, any file 186 - placed in the kernel source root directory or the kernel build root directory 187 - whose name is suffixed with ".x509" will be assumed to be an X.509 public key 188 - and will be added to the keyring. 155 + Beyond the public key generated specifically for module signing, additional 156 + trusted certificates can be provided in a PEM-encoded file referenced by the 157 + CONFIG_SYSTEM_TRUSTED_KEYS configuration option. 189 158 190 159 Further, the architecture code may take public keys from a hardware store and 191 160 add those in also (e.g. from the UEFI key database). ··· 210 181 the Linux kernel source tree. The script requires 4 arguments: 211 182 212 183 1. The hash algorithm (e.g., sha256) 213 - 2. The private key filename 184 + 2. The private key filename or PKCS#11 URI 214 185 3. The public key filename 215 186 4. The kernel module to be signed 216 187 ··· 222 193 The hash algorithm used does not have to match the one configured, but if it 223 194 doesn't, you should make sure that hash algorithm is either built into the 224 195 kernel or can be loaded without requiring itself. 196 + 197 + If the private key requires a passphrase or PIN, it can be provided in the 198 + $KBUILD_SIGN_PIN environment variable. 225 199 226 200 227 201 ============================
+26 -1
Documentation/security/Smack.txt
··· 28 28 configurations are intolerant of IP options and can impede 29 29 access to systems that use them as Smack does. 30 30 31 + Smack is used in the Tizen operating system. Please 32 + go to http://wiki.tizen.org for information about how 33 + Smack is used in Tizen. 34 + 31 35 The current git repository for Smack user space is: 32 36 33 37 git://github.com/smack-team/smack.git ··· 112 108 on /sys/fs/smackfs. 113 109 114 110 access 111 + Provided for backward compatibility. The access2 interface 112 + is preferred and should be used instead. 115 113 This interface reports whether a subject with the specified 116 114 Smack label has a particular access to an object with a 117 115 specified Smack label. Write a fixed format access rule to ··· 142 136 those in the fourth string. If there is no such rule it will be 143 137 created using the access specified in the third and the fourth strings. 144 138 cipso 139 + Provided for backward compatibility. The cipso2 interface 140 + is preferred and should be used instead. 145 141 This interface allows a specific CIPSO header to be assigned 146 142 to a Smack label. The format accepted on write is: 147 143 "%24s%4d%4d"["%4d"]... ··· 165 157 doi 166 158 This contains the CIPSO domain of interpretation used in 167 159 network packets. 160 + ipv6host 161 + This interface allows specific IPv6 internet addresses to be 162 + treated as single label hosts. Packets are sent to single 163 + label hosts only from processes that have Smack write access 164 + to the host label. All packets received from single label hosts 165 + are given the specified label. The format accepted on write is: 166 + "%h:%h:%h:%h:%h:%h:%h:%h label" or 167 + "%h:%h:%h:%h:%h:%h:%h:%h/%d label". 168 + The "::" address shortcut is not supported. 169 + If label is "-DELETE" a matched entry will be deleted. 168 170 load 171 + Provided for backward compatibility. The load2 interface 172 + is preferred and should be used instead. 169 173 This interface allows access control rules in addition to 170 174 the system defined rules to be specified. The format accepted 171 175 on write is: ··· 201 181 permissions that are not allowed. The string "r-x--" would 202 182 specify read and execute access. 203 183 load-self 184 + Provided for backward compatibility. The load-self2 interface 185 + is preferred and should be used instead. 204 186 This interface allows process specific access rules to be 205 187 defined. These rules are only consulted if access would 206 188 otherwise be permitted, and are intended to provide additional ··· 227 205 received from single label hosts are given the specified 228 206 label. The format accepted on write is: 229 207 "%d.%d.%d.%d label" or "%d.%d.%d.%d/%d label". 208 + If the label specified is "-CIPSO" the address is treated 209 + as a host that supports CIPSO headers. 230 210 onlycap 231 211 This contains labels processes must have for CAP_MAC_ADMIN 232 212 and CAP_MAC_OVERRIDE to be effective. If this file is empty ··· 256 232 is dangerous and can ruin the proper labeling of your system. 257 233 It should never be used in production. 258 234 259 - You can add access rules in /etc/smack/accesses. They take the form: 235 + If you are using the smackload utility 236 + you can add access rules in /etc/smack/accesses. They take the form: 260 237 261 238 subjectlabel objectlabel access 262 239
+4 -6
Documentation/security/Yama.txt
··· 1 - Yama is a Linux Security Module that collects a number of system-wide DAC 2 - security protections that are not handled by the core kernel itself. To 3 - select it at boot time, specify "security=yama" (though this will disable 4 - any other LSM). 5 - 6 - Yama is controlled through sysctl in /proc/sys/kernel/yama: 1 + Yama is a Linux Security Module that collects system-wide DAC security 2 + protections that are not handled by the core kernel itself. This is 3 + selectable at build-time with CONFIG_SECURITY_YAMA, and can be controlled 4 + at run-time through sysctls in /proc/sys/kernel/yama: 7 5 8 6 - ptrace_scope 9 7
+18 -3
MAINTAINERS
··· 2621 2621 F: Documentation/filesystems/ceph.txt 2622 2622 F: fs/ceph/ 2623 2623 2624 + CERTIFICATE HANDLING: 2625 + M: David Howells <dhowells@redhat.com> 2626 + M: David Woodhouse <dwmw2@infradead.org> 2627 + L: keyrings@linux-nfs.org 2628 + S: Maintained 2629 + F: Documentation/module-signing.txt 2630 + F: certs/ 2631 + F: scripts/extract-cert.c 2632 + 2624 2633 CERTIFIED WIRELESS USB (WUSB) SUBSYSTEM: 2625 2634 L: linux-usb@vger.kernel.org 2626 2635 S: Orphan ··· 6003 5994 6004 5995 KEYS/KEYRINGS: 6005 5996 M: David Howells <dhowells@redhat.com> 6006 - L: keyrings@linux-nfs.org 5997 + L: keyrings@vger.kernel.org 6007 5998 S: Maintained 6008 5999 F: Documentation/security/keys.txt 6009 6000 F: include/linux/key.h ··· 6015 6006 M: David Safford <safford@us.ibm.com> 6016 6007 M: Mimi Zohar <zohar@linux.vnet.ibm.com> 6017 6008 L: linux-security-module@vger.kernel.org 6018 - L: keyrings@linux-nfs.org 6009 + L: keyrings@vger.kernel.org 6019 6010 S: Supported 6020 6011 F: Documentation/security/keys-trusted-encrypted.txt 6021 6012 F: include/keys/trusted-type.h ··· 6026 6017 M: Mimi Zohar <zohar@linux.vnet.ibm.com> 6027 6018 M: David Safford <safford@us.ibm.com> 6028 6019 L: linux-security-module@vger.kernel.org 6029 - L: keyrings@linux-nfs.org 6020 + L: keyrings@vger.kernel.org 6030 6021 S: Supported 6031 6022 F: Documentation/security/keys-trusted-encrypted.txt 6032 6023 F: include/keys/encrypted-type.h ··· 9272 9263 T: git git://git.kernel.org/pub/scm/linux/kernel/git/jj/apparmor-dev.git 9273 9264 S: Supported 9274 9265 F: security/apparmor/ 9266 + 9267 + YAMA SECURITY MODULE 9268 + M: Kees Cook <keescook@chromium.org> 9269 + T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git yama/tip 9270 + S: Supported 9271 + F: security/yama/ 9275 9272 9276 9273 SENSABLE PHANTOM 9277 9274 M: Jiri Slaby <jirislaby@gmail.com>
+6 -7
Makefile
··· 875 875 # export INITRD_COMPRESS := $(INITRD_COMPRESS-y) 876 876 877 877 ifdef CONFIG_MODULE_SIG_ALL 878 - MODSECKEY = ./signing_key.priv 879 - MODPUBKEY = ./signing_key.x509 880 - export MODPUBKEY 881 - mod_sign_cmd = perl $(srctree)/scripts/sign-file $(CONFIG_MODULE_SIG_HASH) $(MODSECKEY) $(MODPUBKEY) 878 + $(eval $(call config_filename,MODULE_SIG_KEY)) 879 + 880 + mod_sign_cmd = scripts/sign-file $(CONFIG_MODULE_SIG_HASH) $(MODULE_SIG_KEY_SRCPREFIX)$(CONFIG_MODULE_SIG_KEY) certs/signing_key.x509 882 881 else 883 882 mod_sign_cmd = true 884 883 endif ··· 885 886 886 887 887 888 ifeq ($(KBUILD_EXTMOD),) 888 - core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ 889 + core-y += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/ 889 890 890 891 vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \ 891 892 $(core-y) $(core-m) $(drivers-y) $(drivers-m) \ ··· 1177 1178 arch/*/include/generated .tmp_objdiff 1178 1179 MRPROPER_FILES += .config .config.old .version .old_version \ 1179 1180 Module.symvers tags TAGS cscope* GPATH GTAGS GRTAGS GSYMS \ 1180 - signing_key.priv signing_key.x509 x509.genkey \ 1181 - extra_certificates signing_key.x509.keyid \ 1181 + signing_key.pem signing_key.priv signing_key.x509 \ 1182 + x509.genkey extra_certificates signing_key.x509.keyid \ 1182 1183 signing_key.x509.signer vmlinux-gdb.py 1183 1184 1184 1185 # clean - Delete most, but leave enough to build external modules
-1
arch/mips/configs/pistachio_defconfig
··· 320 320 CONFIG_SECURITY=y 321 321 CONFIG_SECURITY_NETWORK=y 322 322 CONFIG_SECURITY_YAMA=y 323 - CONFIG_SECURITY_YAMA_STACKED=y 324 323 CONFIG_DEFAULT_SECURITY_DAC=y 325 324 CONFIG_CRYPTO_AUTHENC=y 326 325 CONFIG_CRYPTO_HMAC=y
+3 -1
arch/x86/kernel/kexec-bzimage64.c
··· 533 533 int ret; 534 534 535 535 ret = verify_pefile_signature(kernel, kernel_len, 536 - system_trusted_keyring, &trusted); 536 + system_trusted_keyring, 537 + VERIFYING_KEXEC_PE_SIGNATURE, 538 + &trusted); 537 539 if (ret < 0) 538 540 return ret; 539 541 if (!trusted)
+42
certs/Kconfig
··· 1 + menu "Certificates for signature checking" 2 + 3 + config MODULE_SIG_KEY 4 + string "File name or PKCS#11 URI of module signing key" 5 + default "certs/signing_key.pem" 6 + depends on MODULE_SIG 7 + help 8 + Provide the file name of a private key/certificate in PEM format, 9 + or a PKCS#11 URI according to RFC7512. The file should contain, or 10 + the URI should identify, both the certificate and its corresponding 11 + private key. 12 + 13 + If this option is unchanged from its default "certs/signing_key.pem", 14 + then the kernel will automatically generate the private key and 15 + certificate as described in Documentation/module-signing.txt 16 + 17 + config SYSTEM_TRUSTED_KEYRING 18 + bool "Provide system-wide ring of trusted keys" 19 + depends on KEYS 20 + help 21 + Provide a system keyring to which trusted keys can be added. Keys in 22 + the keyring are considered to be trusted. Keys may be added at will 23 + by the kernel from compiled-in data and from hardware key stores, but 24 + userspace may only add extra keys if those keys can be verified by 25 + keys already in the keyring. 26 + 27 + Keys in this keyring are used by module signature checking. 28 + 29 + config SYSTEM_TRUSTED_KEYS 30 + string "Additional X.509 keys for default system keyring" 31 + depends on SYSTEM_TRUSTED_KEYRING 32 + help 33 + If set, this option should be the filename of a PEM-formatted file 34 + containing trusted X.509 certificates to be included in the default 35 + system keyring. Any certificate used for module signing is implicitly 36 + also trusted. 37 + 38 + NOTE: If you previously provided keys for the system keyring in the 39 + form of DER-encoded *.x509 files in the top-level build directory, 40 + those are no longer used. You will need to set this option instead. 41 + 42 + endmenu
+94
certs/Makefile
··· 1 + # 2 + # Makefile for the linux kernel signature checking certificates. 3 + # 4 + 5 + obj-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += system_keyring.o system_certificates.o 6 + 7 + ifeq ($(CONFIG_SYSTEM_TRUSTED_KEYRING),y) 8 + 9 + $(eval $(call config_filename,SYSTEM_TRUSTED_KEYS)) 10 + 11 + # GCC doesn't include .incbin files in -MD generated dependencies (PR#66871) 12 + $(obj)/system_certificates.o: $(obj)/x509_certificate_list 13 + 14 + # Cope with signing_key.x509 existing in $(srctree) not $(objtree) 15 + AFLAGS_system_certificates.o := -I$(srctree) 16 + 17 + quiet_cmd_extract_certs = EXTRACT_CERTS $(patsubst "%",%,$(2)) 18 + cmd_extract_certs = scripts/extract-cert $(2) $@ || ( rm $@; exit 1) 19 + 20 + targets += x509_certificate_list 21 + $(obj)/x509_certificate_list: scripts/extract-cert $(SYSTEM_TRUSTED_KEYS_SRCPREFIX)$(SYSTEM_TRUSTED_KEYS_FILENAME) FORCE 22 + $(call if_changed,extract_certs,$(SYSTEM_TRUSTED_KEYS_SRCPREFIX)$(CONFIG_SYSTEM_TRUSTED_KEYS)) 23 + endif 24 + 25 + clean-files := x509_certificate_list .x509.list 26 + 27 + ifeq ($(CONFIG_MODULE_SIG),y) 28 + ############################################################################### 29 + # 30 + # If module signing is requested, say by allyesconfig, but a key has not been 31 + # supplied, then one will need to be generated to make sure the build does not 32 + # fail and that the kernel may be used afterwards. 33 + # 34 + ############################################################################### 35 + ifndef CONFIG_MODULE_SIG_HASH 36 + $(error Could not determine digest type to use from kernel config) 37 + endif 38 + 39 + # We do it this way rather than having a boolean option for enabling an 40 + # external private key, because 'make randconfig' might enable such a 41 + # boolean option and we unfortunately can't make it depend on !RANDCONFIG. 42 + ifeq ($(CONFIG_MODULE_SIG_KEY),"certs/signing_key.pem") 43 + $(obj)/signing_key.pem: $(obj)/x509.genkey 44 + @echo "###" 45 + @echo "### Now generating an X.509 key pair to be used for signing modules." 46 + @echo "###" 47 + @echo "### If this takes a long time, you might wish to run rngd in the" 48 + @echo "### background to keep the supply of entropy topped up. It" 49 + @echo "### needs to be run as root, and uses a hardware random" 50 + @echo "### number generator if one is available." 51 + @echo "###" 52 + openssl req -new -nodes -utf8 -$(CONFIG_MODULE_SIG_HASH) -days 36500 \ 53 + -batch -x509 -config $(obj)/x509.genkey \ 54 + -outform PEM -out $(obj)/signing_key.pem \ 55 + -keyout $(obj)/signing_key.pem 2>&1 56 + @echo "###" 57 + @echo "### Key pair generated." 58 + @echo "###" 59 + 60 + $(obj)/x509.genkey: 61 + @echo Generating X.509 key generation config 62 + @echo >$@ "[ req ]" 63 + @echo >>$@ "default_bits = 4096" 64 + @echo >>$@ "distinguished_name = req_distinguished_name" 65 + @echo >>$@ "prompt = no" 66 + @echo >>$@ "string_mask = utf8only" 67 + @echo >>$@ "x509_extensions = myexts" 68 + @echo >>$@ 69 + @echo >>$@ "[ req_distinguished_name ]" 70 + @echo >>$@ "#O = Unspecified company" 71 + @echo >>$@ "CN = Build time autogenerated kernel key" 72 + @echo >>$@ "#emailAddress = unspecified.user@unspecified.company" 73 + @echo >>$@ 74 + @echo >>$@ "[ myexts ]" 75 + @echo >>$@ "basicConstraints=critical,CA:FALSE" 76 + @echo >>$@ "keyUsage=digitalSignature" 77 + @echo >>$@ "subjectKeyIdentifier=hash" 78 + @echo >>$@ "authorityKeyIdentifier=keyid" 79 + endif 80 + 81 + $(eval $(call config_filename,MODULE_SIG_KEY)) 82 + 83 + # If CONFIG_MODULE_SIG_KEY isn't a PKCS#11 URI, depend on it 84 + ifeq ($(patsubst pkcs11:%,%,$(firstword $(MODULE_SIG_KEY_FILENAME))),$(firstword $(MODULE_SIG_KEY_FILENAME))) 85 + X509_DEP := $(MODULE_SIG_KEY_SRCPREFIX)$(MODULE_SIG_KEY_FILENAME) 86 + endif 87 + 88 + # GCC PR#66871 again. 89 + $(obj)/system_certificates.o: $(obj)/signing_key.x509 90 + 91 + targets += signing_key.x509 92 + $(obj)/signing_key.x509: scripts/extract-cert $(X509_DEP) FORCE 93 + $(call if_changed,extract_certs,$(MODULE_SIG_KEY_SRCPREFIX)$(CONFIG_MODULE_SIG_KEY)) 94 + endif
+1
crypto/Kconfig
··· 1635 1635 1636 1636 source "drivers/crypto/Kconfig" 1637 1637 source crypto/asymmetric_keys/Kconfig 1638 + source certs/Kconfig 1638 1639 1639 1640 endif # if CRYPTO
+7 -1
crypto/asymmetric_keys/Makefile
··· 15 15 obj-$(CONFIG_X509_CERTIFICATE_PARSER) += x509_key_parser.o 16 16 x509_key_parser-y := \ 17 17 x509-asn1.o \ 18 + x509_akid-asn1.o \ 18 19 x509_rsakey-asn1.o \ 19 20 x509_cert_parser.o \ 20 21 x509_public_key.o 21 22 22 - $(obj)/x509_cert_parser.o: $(obj)/x509-asn1.h $(obj)/x509_rsakey-asn1.h 23 + $(obj)/x509_cert_parser.o: \ 24 + $(obj)/x509-asn1.h \ 25 + $(obj)/x509_akid-asn1.h \ 26 + $(obj)/x509_rsakey-asn1.h 23 27 $(obj)/x509-asn1.o: $(obj)/x509-asn1.c $(obj)/x509-asn1.h 28 + $(obj)/x509_akid-asn1.o: $(obj)/x509_akid-asn1.c $(obj)/x509_akid-asn1.h 24 29 $(obj)/x509_rsakey-asn1.o: $(obj)/x509_rsakey-asn1.c $(obj)/x509_rsakey-asn1.h 25 30 26 31 clean-files += x509-asn1.c x509-asn1.h 32 + clean-files += x509_akid-asn1.c x509_akid-asn1.h 27 33 clean-files += x509_rsakey-asn1.c x509_rsakey-asn1.h 28 34 29 35 #
+11
crypto/asymmetric_keys/asymmetric_type.c
··· 12 12 */ 13 13 #include <keys/asymmetric-subtype.h> 14 14 #include <keys/asymmetric-parser.h> 15 + #include <crypto/public_key.h> 15 16 #include <linux/seq_file.h> 16 17 #include <linux/module.h> 17 18 #include <linux/slab.h> ··· 20 19 #include "asymmetric_keys.h" 21 20 22 21 MODULE_LICENSE("GPL"); 22 + 23 + const char *const key_being_used_for[NR__KEY_BEING_USED_FOR] = { 24 + [VERIFYING_MODULE_SIGNATURE] = "mod sig", 25 + [VERIFYING_FIRMWARE_SIGNATURE] = "firmware sig", 26 + [VERIFYING_KEXEC_PE_SIGNATURE] = "kexec PE sig", 27 + [VERIFYING_KEY_SIGNATURE] = "key sig", 28 + [VERIFYING_KEY_SELF_SIGNATURE] = "key self sig", 29 + [VERIFYING_UNSPECIFIED_SIGNATURE] = "unspec sig", 30 + }; 31 + EXPORT_SYMBOL_GPL(key_being_used_for); 23 32 24 33 static LIST_HEAD(asymmetric_key_parsers); 25 34 static DECLARE_RWSEM(asymmetric_key_parsers_sem);
+9
crypto/asymmetric_keys/mscode_parser.c
··· 97 97 case OID_sha256: 98 98 ctx->digest_algo = HASH_ALGO_SHA256; 99 99 break; 100 + case OID_sha384: 101 + ctx->digest_algo = HASH_ALGO_SHA384; 102 + break; 103 + case OID_sha512: 104 + ctx->digest_algo = HASH_ALGO_SHA512; 105 + break; 106 + case OID_sha224: 107 + ctx->digest_algo = HASH_ALGO_SHA224; 108 + break; 100 109 101 110 case OID__NR: 102 111 sprint_oid(value, vlen, buffer, sizeof(buffer));
+15 -7
crypto/asymmetric_keys/pkcs7.asn1
··· 1 1 PKCS7ContentInfo ::= SEQUENCE { 2 - contentType ContentType, 2 + contentType ContentType ({ pkcs7_check_content_type }), 3 3 content [0] EXPLICIT SignedData OPTIONAL 4 4 } 5 5 6 6 ContentType ::= OBJECT IDENTIFIER ({ pkcs7_note_OID }) 7 7 8 8 SignedData ::= SEQUENCE { 9 - version INTEGER, 9 + version INTEGER ({ pkcs7_note_signeddata_version }), 10 10 digestAlgorithms DigestAlgorithmIdentifiers, 11 - contentInfo ContentInfo, 11 + contentInfo ContentInfo ({ pkcs7_note_content }), 12 12 certificates CHOICE { 13 13 certSet [0] IMPLICIT ExtendedCertificatesAndCertificates, 14 14 certSequence [2] IMPLICIT Certificates ··· 21 21 } 22 22 23 23 ContentInfo ::= SEQUENCE { 24 - contentType ContentType, 24 + contentType ContentType ({ pkcs7_note_OID }), 25 25 content [0] EXPLICIT Data OPTIONAL 26 26 } 27 27 ··· 68 68 } 69 69 70 70 SignerInfo ::= SEQUENCE { 71 - version INTEGER, 72 - issuerAndSerialNumber IssuerAndSerialNumber, 71 + version INTEGER ({ pkcs7_note_signerinfo_version }), 72 + sid SignerIdentifier, -- CMS variant, not PKCS#7 73 73 digestAlgorithm DigestAlgorithmIdentifier ({ pkcs7_sig_note_digest_algo }), 74 74 authenticatedAttributes CHOICE { 75 75 aaSet [0] IMPLICIT SetOfAuthenticatedAttribute ··· 88 88 } OPTIONAL 89 89 } ({ pkcs7_note_signed_info }) 90 90 91 + SignerIdentifier ::= CHOICE { 92 + -- RFC5652 sec 5.3 93 + issuerAndSerialNumber IssuerAndSerialNumber, 94 + subjectKeyIdentifier [0] IMPLICIT SubjectKeyIdentifier 95 + } 96 + 91 97 IssuerAndSerialNumber ::= SEQUENCE { 92 98 issuer Name ({ pkcs7_sig_note_issuer }), 93 99 serialNumber CertificateSerialNumber ({ pkcs7_sig_note_serial }) 94 100 } 95 101 96 102 CertificateSerialNumber ::= INTEGER 103 + 104 + SubjectKeyIdentifier ::= OCTET STRING ({ pkcs7_sig_note_skid }) 97 105 98 106 SetOfAuthenticatedAttribute ::= SET OF AuthenticatedAttribute 99 107 ··· 111 103 } 112 104 113 105 UnauthenticatedAttribute ::= SEQUENCE { 114 - type OBJECT IDENTIFIER ({ pkcs7_note_OID }), 106 + type OBJECT IDENTIFIER, 115 107 values SET OF ANY 116 108 } 117 109
+16 -1
crypto/asymmetric_keys/pkcs7_key_type.c
··· 14 14 #include <linux/err.h> 15 15 #include <linux/module.h> 16 16 #include <linux/key-type.h> 17 + #include <keys/asymmetric-type.h> 17 18 #include <crypto/pkcs7.h> 18 19 #include <keys/user-type.h> 19 20 #include <keys/system_keyring.h> 20 21 #include "pkcs7_parser.h" 22 + 23 + MODULE_LICENSE("GPL"); 24 + MODULE_DESCRIPTION("PKCS#7 testing key type"); 25 + 26 + static unsigned pkcs7_usage; 27 + module_param_named(usage, pkcs7_usage, uint, S_IWUSR | S_IRUGO); 28 + MODULE_PARM_DESC(pkcs7_usage, 29 + "Usage to specify when verifying the PKCS#7 message"); 21 30 22 31 /* 23 32 * Preparse a PKCS#7 wrapped and validated data blob. 24 33 */ 25 34 static int pkcs7_preparse(struct key_preparsed_payload *prep) 26 35 { 36 + enum key_being_used_for usage = pkcs7_usage; 27 37 struct pkcs7_message *pkcs7; 28 38 const void *data, *saved_prep_data; 29 39 size_t datalen, saved_prep_datalen; ··· 41 31 int ret; 42 32 43 33 kenter(""); 34 + 35 + if (usage >= NR__KEY_BEING_USED_FOR) { 36 + pr_err("Invalid usage type %d\n", usage); 37 + return -EINVAL; 38 + } 44 39 45 40 saved_prep_data = prep->data; 46 41 saved_prep_datalen = prep->datalen; ··· 55 40 goto error; 56 41 } 57 42 58 - ret = pkcs7_verify(pkcs7); 43 + ret = pkcs7_verify(pkcs7, usage); 59 44 if (ret < 0) 60 45 goto error_free; 61 46
+266 -11
crypto/asymmetric_keys/pkcs7_parser.c
··· 33 33 unsigned raw_serial_size; 34 34 unsigned raw_issuer_size; 35 35 const void *raw_issuer; 36 + const void *raw_skid; 37 + unsigned raw_skid_size; 38 + bool expect_skid; 36 39 }; 37 40 38 41 /* ··· 81 78 } 82 79 EXPORT_SYMBOL_GPL(pkcs7_free_message); 83 80 81 + /* 82 + * Check authenticatedAttributes are provided or not provided consistently. 83 + */ 84 + static int pkcs7_check_authattrs(struct pkcs7_message *msg) 85 + { 86 + struct pkcs7_signed_info *sinfo; 87 + bool want; 88 + 89 + sinfo = msg->signed_infos; 90 + if (sinfo->authattrs) { 91 + want = true; 92 + msg->have_authattrs = true; 93 + } 94 + 95 + for (sinfo = sinfo->next; sinfo; sinfo = sinfo->next) 96 + if (!!sinfo->authattrs != want) 97 + goto inconsistent; 98 + return 0; 99 + 100 + inconsistent: 101 + pr_warn("Inconsistently supplied authAttrs\n"); 102 + return -EINVAL; 103 + } 104 + 84 105 /** 85 106 * pkcs7_parse_message - Parse a PKCS#7 message 86 107 * @data: The raw binary ASN.1 encoded message to be parsed ··· 136 109 msg = ERR_PTR(ret); 137 110 goto out; 138 111 } 112 + 113 + ret = pkcs7_check_authattrs(ctx->msg); 114 + if (ret < 0) 115 + goto out; 139 116 140 117 msg = ctx->msg; 141 118 ctx->msg = NULL; ··· 229 198 case OID_sha256: 230 199 ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA256; 231 200 break; 201 + case OID_sha384: 202 + ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA384; 203 + break; 204 + case OID_sha512: 205 + ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA512; 206 + break; 207 + case OID_sha224: 208 + ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA224; 232 209 default: 233 210 printk("Unsupported digest algo: %u\n", ctx->last_oid); 234 211 return -ENOPKG; ··· 262 223 return -ENOPKG; 263 224 } 264 225 return 0; 226 + } 227 + 228 + /* 229 + * We only support signed data [RFC2315 sec 9]. 230 + */ 231 + int pkcs7_check_content_type(void *context, size_t hdrlen, 232 + unsigned char tag, 233 + const void *value, size_t vlen) 234 + { 235 + struct pkcs7_parse_context *ctx = context; 236 + 237 + if (ctx->last_oid != OID_signed_data) { 238 + pr_warn("Only support pkcs7_signedData type\n"); 239 + return -EINVAL; 240 + } 241 + 242 + return 0; 243 + } 244 + 245 + /* 246 + * Note the SignedData version 247 + */ 248 + int pkcs7_note_signeddata_version(void *context, size_t hdrlen, 249 + unsigned char tag, 250 + const void *value, size_t vlen) 251 + { 252 + struct pkcs7_parse_context *ctx = context; 253 + unsigned version; 254 + 255 + if (vlen != 1) 256 + goto unsupported; 257 + 258 + ctx->msg->version = version = *(const u8 *)value; 259 + switch (version) { 260 + case 1: 261 + /* PKCS#7 SignedData [RFC2315 sec 9.1] 262 + * CMS ver 1 SignedData [RFC5652 sec 5.1] 263 + */ 264 + break; 265 + case 3: 266 + /* CMS ver 3 SignedData [RFC2315 sec 5.1] */ 267 + break; 268 + default: 269 + goto unsupported; 270 + } 271 + 272 + return 0; 273 + 274 + unsupported: 275 + pr_warn("Unsupported SignedData version\n"); 276 + return -EINVAL; 277 + } 278 + 279 + /* 280 + * Note the SignerInfo version 281 + */ 282 + int pkcs7_note_signerinfo_version(void *context, size_t hdrlen, 283 + unsigned char tag, 284 + const void *value, size_t vlen) 285 + { 286 + struct pkcs7_parse_context *ctx = context; 287 + unsigned version; 288 + 289 + if (vlen != 1) 290 + goto unsupported; 291 + 292 + version = *(const u8 *)value; 293 + switch (version) { 294 + case 1: 295 + /* PKCS#7 SignerInfo [RFC2315 sec 9.2] 296 + * CMS ver 1 SignerInfo [RFC5652 sec 5.3] 297 + */ 298 + if (ctx->msg->version != 1) 299 + goto version_mismatch; 300 + ctx->expect_skid = false; 301 + break; 302 + case 3: 303 + /* CMS ver 3 SignerInfo [RFC2315 sec 5.3] */ 304 + if (ctx->msg->version == 1) 305 + goto version_mismatch; 306 + ctx->expect_skid = true; 307 + break; 308 + default: 309 + goto unsupported; 310 + } 311 + 312 + return 0; 313 + 314 + unsupported: 315 + pr_warn("Unsupported SignerInfo version\n"); 316 + return -EINVAL; 317 + version_mismatch: 318 + pr_warn("SignedData-SignerInfo version mismatch\n"); 319 + return -EBADMSG; 265 320 } 266 321 267 322 /* ··· 417 284 } 418 285 419 286 /* 287 + * Note the content type. 288 + */ 289 + int pkcs7_note_content(void *context, size_t hdrlen, 290 + unsigned char tag, 291 + const void *value, size_t vlen) 292 + { 293 + struct pkcs7_parse_context *ctx = context; 294 + 295 + if (ctx->last_oid != OID_data && 296 + ctx->last_oid != OID_msIndirectData) { 297 + pr_warn("Unsupported data type %d\n", ctx->last_oid); 298 + return -EINVAL; 299 + } 300 + 301 + ctx->msg->data_type = ctx->last_oid; 302 + return 0; 303 + } 304 + 305 + /* 420 306 * Extract the data from the message and store that and its content type OID in 421 307 * the context. 422 308 */ ··· 450 298 ctx->msg->data = value; 451 299 ctx->msg->data_len = vlen; 452 300 ctx->msg->data_hdrlen = hdrlen; 453 - ctx->msg->data_type = ctx->last_oid; 454 301 return 0; 455 302 } 456 303 457 304 /* 458 - * Parse authenticated attributes 305 + * Parse authenticated attributes. 459 306 */ 460 307 int pkcs7_sig_note_authenticated_attr(void *context, size_t hdrlen, 461 308 unsigned char tag, 462 309 const void *value, size_t vlen) 463 310 { 464 311 struct pkcs7_parse_context *ctx = context; 312 + struct pkcs7_signed_info *sinfo = ctx->sinfo; 313 + enum OID content_type; 465 314 466 315 pr_devel("AuthAttr: %02x %zu [%*ph]\n", tag, vlen, (unsigned)vlen, value); 467 316 468 317 switch (ctx->last_oid) { 318 + case OID_contentType: 319 + if (__test_and_set_bit(sinfo_has_content_type, &sinfo->aa_set)) 320 + goto repeated; 321 + content_type = look_up_OID(value, vlen); 322 + if (content_type != ctx->msg->data_type) { 323 + pr_warn("Mismatch between global data type (%d) and sinfo %u (%d)\n", 324 + ctx->msg->data_type, sinfo->index, 325 + content_type); 326 + return -EBADMSG; 327 + } 328 + return 0; 329 + 330 + case OID_signingTime: 331 + if (__test_and_set_bit(sinfo_has_signing_time, &sinfo->aa_set)) 332 + goto repeated; 333 + /* Should we check that the signing time is consistent 334 + * with the signer's X.509 cert? 335 + */ 336 + return x509_decode_time(&sinfo->signing_time, 337 + hdrlen, tag, value, vlen); 338 + 469 339 case OID_messageDigest: 340 + if (__test_and_set_bit(sinfo_has_message_digest, &sinfo->aa_set)) 341 + goto repeated; 470 342 if (tag != ASN1_OTS) 471 343 return -EBADMSG; 472 - ctx->sinfo->msgdigest = value; 473 - ctx->sinfo->msgdigest_len = vlen; 344 + sinfo->msgdigest = value; 345 + sinfo->msgdigest_len = vlen; 346 + return 0; 347 + 348 + case OID_smimeCapabilites: 349 + if (__test_and_set_bit(sinfo_has_smime_caps, &sinfo->aa_set)) 350 + goto repeated; 351 + if (ctx->msg->data_type != OID_msIndirectData) { 352 + pr_warn("S/MIME Caps only allowed with Authenticode\n"); 353 + return -EKEYREJECTED; 354 + } 355 + return 0; 356 + 357 + /* Microsoft SpOpusInfo seems to be contain cont[0] 16-bit BE 358 + * char URLs and cont[1] 8-bit char URLs. 359 + * 360 + * Microsoft StatementType seems to contain a list of OIDs that 361 + * are also used as extendedKeyUsage types in X.509 certs. 362 + */ 363 + case OID_msSpOpusInfo: 364 + if (__test_and_set_bit(sinfo_has_ms_opus_info, &sinfo->aa_set)) 365 + goto repeated; 366 + goto authenticode_check; 367 + case OID_msStatementType: 368 + if (__test_and_set_bit(sinfo_has_ms_statement_type, &sinfo->aa_set)) 369 + goto repeated; 370 + authenticode_check: 371 + if (ctx->msg->data_type != OID_msIndirectData) { 372 + pr_warn("Authenticode AuthAttrs only allowed with Authenticode\n"); 373 + return -EKEYREJECTED; 374 + } 375 + /* I'm not sure how to validate these */ 474 376 return 0; 475 377 default: 476 378 return 0; 477 379 } 380 + 381 + repeated: 382 + /* We permit max one item per AuthenticatedAttribute and no repeats */ 383 + pr_warn("Repeated/multivalue AuthAttrs not permitted\n"); 384 + return -EKEYREJECTED; 478 385 } 479 386 480 387 /* 481 - * Note the set of auth attributes for digestion purposes [RFC2315 9.3] 388 + * Note the set of auth attributes for digestion purposes [RFC2315 sec 9.3] 482 389 */ 483 390 int pkcs7_sig_note_set_of_authattrs(void *context, size_t hdrlen, 484 391 unsigned char tag, 485 392 const void *value, size_t vlen) 486 393 { 487 394 struct pkcs7_parse_context *ctx = context; 395 + struct pkcs7_signed_info *sinfo = ctx->sinfo; 396 + 397 + if (!test_bit(sinfo_has_content_type, &sinfo->aa_set) || 398 + !test_bit(sinfo_has_message_digest, &sinfo->aa_set) || 399 + (ctx->msg->data_type == OID_msIndirectData && 400 + !test_bit(sinfo_has_ms_opus_info, &sinfo->aa_set))) { 401 + pr_warn("Missing required AuthAttr\n"); 402 + return -EBADMSG; 403 + } 404 + 405 + if (ctx->msg->data_type != OID_msIndirectData && 406 + test_bit(sinfo_has_ms_opus_info, &sinfo->aa_set)) { 407 + pr_warn("Unexpected Authenticode AuthAttr\n"); 408 + return -EBADMSG; 409 + } 488 410 489 411 /* We need to switch the 'CONT 0' to a 'SET OF' when we digest */ 490 - ctx->sinfo->authattrs = value - (hdrlen - 1); 491 - ctx->sinfo->authattrs_len = vlen + (hdrlen - 1); 412 + sinfo->authattrs = value - (hdrlen - 1); 413 + sinfo->authattrs_len = vlen + (hdrlen - 1); 492 414 return 0; 493 415 } 494 416 ··· 589 363 struct pkcs7_parse_context *ctx = context; 590 364 ctx->raw_issuer = value; 591 365 ctx->raw_issuer_size = vlen; 366 + return 0; 367 + } 368 + 369 + /* 370 + * Note the issuing cert's subjectKeyIdentifier 371 + */ 372 + int pkcs7_sig_note_skid(void *context, size_t hdrlen, 373 + unsigned char tag, 374 + const void *value, size_t vlen) 375 + { 376 + struct pkcs7_parse_context *ctx = context; 377 + 378 + pr_devel("SKID: %02x %zu [%*ph]\n", tag, vlen, (unsigned)vlen, value); 379 + 380 + ctx->raw_skid = value; 381 + ctx->raw_skid_size = vlen; 592 382 return 0; 593 383 } 594 384 ··· 640 398 struct pkcs7_signed_info *sinfo = ctx->sinfo; 641 399 struct asymmetric_key_id *kid; 642 400 401 + if (ctx->msg->data_type == OID_msIndirectData && !sinfo->authattrs) { 402 + pr_warn("Authenticode requires AuthAttrs\n"); 403 + return -EBADMSG; 404 + } 405 + 643 406 /* Generate cert issuer + serial number key ID */ 644 - kid = asymmetric_key_generate_id(ctx->raw_serial, 645 - ctx->raw_serial_size, 646 - ctx->raw_issuer, 647 - ctx->raw_issuer_size); 407 + if (!ctx->expect_skid) { 408 + kid = asymmetric_key_generate_id(ctx->raw_serial, 409 + ctx->raw_serial_size, 410 + ctx->raw_issuer, 411 + ctx->raw_issuer_size); 412 + } else { 413 + kid = asymmetric_key_generate_id(ctx->raw_skid, 414 + ctx->raw_skid_size, 415 + "", 0); 416 + } 648 417 if (IS_ERR(kid)) 649 418 return PTR_ERR(kid); 419 + 420 + pr_devel("SINFO KID: %u [%*phN]\n", kid->len, kid->len, kid->data); 650 421 651 422 sinfo->signing_cert_id = kid; 652 423 sinfo->index = ++ctx->sinfo_index;
+16 -4
crypto/asymmetric_keys/pkcs7_parser.h
··· 21 21 struct pkcs7_signed_info { 22 22 struct pkcs7_signed_info *next; 23 23 struct x509_certificate *signer; /* Signing certificate (in msg->certs) */ 24 - unsigned index; 25 - bool trusted; 26 - bool unsupported_crypto; /* T if not usable due to missing crypto */ 24 + unsigned index; 25 + bool trusted; 26 + bool unsupported_crypto; /* T if not usable due to missing crypto */ 27 27 28 28 /* Message digest - the digest of the Content Data (or NULL) */ 29 29 const void *msgdigest; ··· 32 32 /* Authenticated Attribute data (or NULL) */ 33 33 unsigned authattrs_len; 34 34 const void *authattrs; 35 + unsigned long aa_set; 36 + #define sinfo_has_content_type 0 37 + #define sinfo_has_signing_time 1 38 + #define sinfo_has_message_digest 2 39 + #define sinfo_has_smime_caps 3 40 + #define sinfo_has_ms_opus_info 4 41 + #define sinfo_has_ms_statement_type 5 42 + time64_t signing_time; 35 43 36 - /* Issuing cert serial number and issuer's name */ 44 + /* Issuing cert serial number and issuer's name [PKCS#7 or CMS ver 1] 45 + * or issuing cert's SKID [CMS ver 3]. 46 + */ 37 47 struct asymmetric_key_id *signing_cert_id; 38 48 39 49 /* Message signature. ··· 60 50 struct x509_certificate *certs; /* Certificate list */ 61 51 struct x509_certificate *crl; /* Revocation list */ 62 52 struct pkcs7_signed_info *signed_infos; 53 + u8 version; /* Version of cert (1 -> PKCS#7 or CMS; 3 -> CMS) */ 54 + bool have_authattrs; /* T if have authattrs */ 63 55 64 56 /* Content Data (or NULL) */ 65 57 enum OID data_type; /* Type of Data */
+7 -3
crypto/asymmetric_keys/pkcs7_trust.c
··· 54 54 /* Look to see if this certificate is present in the trusted 55 55 * keys. 56 56 */ 57 - key = x509_request_asymmetric_key(trust_keyring, x509->id, 57 + key = x509_request_asymmetric_key(trust_keyring, 58 + x509->id, x509->skid, 58 59 false); 59 60 if (!IS_ERR(key)) { 60 61 /* One of the X.509 certificates in the PKCS#7 message ··· 86 85 /* No match - see if the root certificate has a signer amongst the 87 86 * trusted keys. 88 87 */ 89 - if (last && last->authority) { 90 - key = x509_request_asymmetric_key(trust_keyring, last->authority, 88 + if (last && (last->akid_id || last->akid_skid)) { 89 + key = x509_request_asymmetric_key(trust_keyring, 90 + last->akid_id, 91 + last->akid_skid, 91 92 false); 92 93 if (!IS_ERR(key)) { 93 94 x509 = last; ··· 106 103 */ 107 104 key = x509_request_asymmetric_key(trust_keyring, 108 105 sinfo->signing_cert_id, 106 + NULL, 109 107 false); 110 108 if (!IS_ERR(key)) { 111 109 pr_devel("sinfo %u: Direct signer is key %x\n",
+126 -17
crypto/asymmetric_keys/pkcs7_verify.c
··· 70 70 * message digest attribute amongst them which corresponds to the 71 71 * digest we just calculated. 72 72 */ 73 - if (sinfo->msgdigest) { 73 + if (sinfo->authattrs) { 74 74 u8 tag; 75 + 76 + if (!sinfo->msgdigest) { 77 + pr_warn("Sig %u: No messageDigest\n", sinfo->index); 78 + ret = -EKEYREJECTED; 79 + goto error; 80 + } 75 81 76 82 if (sinfo->msgdigest_len != sinfo->sig.digest_size) { 77 83 pr_debug("Sig %u: Invalid digest size (%u)\n", ··· 176 170 struct pkcs7_signed_info *sinfo) 177 171 { 178 172 struct x509_certificate *x509 = sinfo->signer, *p; 173 + struct asymmetric_key_id *auth; 179 174 int ret; 180 175 181 176 kenter(""); ··· 194 187 goto maybe_missing_crypto_in_x509; 195 188 196 189 pr_debug("- issuer %s\n", x509->issuer); 197 - if (x509->authority) 198 - pr_debug("- authkeyid %*phN\n", 199 - x509->authority->len, x509->authority->data); 190 + if (x509->akid_id) 191 + pr_debug("- authkeyid.id %*phN\n", 192 + x509->akid_id->len, x509->akid_id->data); 193 + if (x509->akid_skid) 194 + pr_debug("- authkeyid.skid %*phN\n", 195 + x509->akid_skid->len, x509->akid_skid->data); 200 196 201 - if (!x509->authority || 197 + if ((!x509->akid_id && !x509->akid_skid) || 202 198 strcmp(x509->subject, x509->issuer) == 0) { 203 199 /* If there's no authority certificate specified, then 204 200 * the certificate must be self-signed and is the root ··· 225 215 /* Look through the X.509 certificates in the PKCS#7 message's 226 216 * list to see if the next one is there. 227 217 */ 228 - pr_debug("- want %*phN\n", 229 - x509->authority->len, x509->authority->data); 230 - for (p = pkcs7->certs; p; p = p->next) { 231 - if (!p->skid) 232 - continue; 233 - pr_debug("- cmp [%u] %*phN\n", 234 - p->index, p->skid->len, p->skid->data); 235 - if (asymmetric_key_id_same(p->skid, x509->authority)) 236 - goto found_issuer; 218 + auth = x509->akid_id; 219 + if (auth) { 220 + pr_debug("- want %*phN\n", auth->len, auth->data); 221 + for (p = pkcs7->certs; p; p = p->next) { 222 + pr_debug("- cmp [%u] %*phN\n", 223 + p->index, p->id->len, p->id->data); 224 + if (asymmetric_key_id_same(p->id, auth)) 225 + goto found_issuer_check_skid; 226 + } 227 + } else { 228 + auth = x509->akid_skid; 229 + pr_debug("- want %*phN\n", auth->len, auth->data); 230 + for (p = pkcs7->certs; p; p = p->next) { 231 + if (!p->skid) 232 + continue; 233 + pr_debug("- cmp [%u] %*phN\n", 234 + p->index, p->skid->len, p->skid->data); 235 + if (asymmetric_key_id_same(p->skid, auth)) 236 + goto found_issuer; 237 + } 237 238 } 238 239 239 240 /* We didn't find the root of this chain */ 240 241 pr_debug("- top\n"); 241 242 return 0; 242 243 244 + found_issuer_check_skid: 245 + /* We matched issuer + serialNumber, but if there's an 246 + * authKeyId.keyId, that must match the CA subjKeyId also. 247 + */ 248 + if (x509->akid_skid && 249 + !asymmetric_key_id_same(p->skid, x509->akid_skid)) { 250 + pr_warn("Sig %u: X.509 chain contains auth-skid nonmatch (%u->%u)\n", 251 + sinfo->index, x509->index, p->index); 252 + return -EKEYREJECTED; 253 + } 243 254 found_issuer: 244 255 pr_debug("- subject %s\n", p->subject); 245 256 if (p->seen) { ··· 320 289 pr_devel("Using X.509[%u] for sig %u\n", 321 290 sinfo->signer->index, sinfo->index); 322 291 292 + /* Check that the PKCS#7 signing time is valid according to the X.509 293 + * certificate. We can't, however, check against the system clock 294 + * since that may not have been set yet and may be wrong. 295 + */ 296 + if (test_bit(sinfo_has_signing_time, &sinfo->aa_set)) { 297 + if (sinfo->signing_time < sinfo->signer->valid_from || 298 + sinfo->signing_time > sinfo->signer->valid_to) { 299 + pr_warn("Message signed outside of X.509 validity window\n"); 300 + return -EKEYREJECTED; 301 + } 302 + } 303 + 323 304 /* Verify the PKCS#7 binary against the key */ 324 305 ret = public_key_verify_signature(sinfo->signer->pub, &sinfo->sig); 325 306 if (ret < 0) ··· 346 303 /** 347 304 * pkcs7_verify - Verify a PKCS#7 message 348 305 * @pkcs7: The PKCS#7 message to be verified 306 + * @usage: The use to which the key is being put 349 307 * 350 308 * Verify a PKCS#7 message is internally consistent - that is, the data digest 351 309 * matches the digest in the AuthAttrs and any signature in the message or one ··· 357 313 * external public keys. 358 314 * 359 315 * Returns, in order of descending priority: 316 + * 317 + * (*) -EKEYREJECTED if a key was selected that had a usage restriction at 318 + * odds with the specified usage, or: 360 319 * 361 320 * (*) -EKEYREJECTED if a signature failed to match for which we found an 362 321 * appropriate X.509 certificate, or: ··· 372 325 * (*) 0 if all the signature chains that don't incur -ENOPKG can be verified 373 326 * (note that a signature chain may be of zero length), or: 374 327 */ 375 - int pkcs7_verify(struct pkcs7_message *pkcs7) 328 + int pkcs7_verify(struct pkcs7_message *pkcs7, 329 + enum key_being_used_for usage) 376 330 { 377 331 struct pkcs7_signed_info *sinfo; 378 332 struct x509_certificate *x509; ··· 382 334 383 335 kenter(""); 384 336 337 + switch (usage) { 338 + case VERIFYING_MODULE_SIGNATURE: 339 + if (pkcs7->data_type != OID_data) { 340 + pr_warn("Invalid module sig (not pkcs7-data)\n"); 341 + return -EKEYREJECTED; 342 + } 343 + if (pkcs7->have_authattrs) { 344 + pr_warn("Invalid module sig (has authattrs)\n"); 345 + return -EKEYREJECTED; 346 + } 347 + break; 348 + case VERIFYING_FIRMWARE_SIGNATURE: 349 + if (pkcs7->data_type != OID_data) { 350 + pr_warn("Invalid firmware sig (not pkcs7-data)\n"); 351 + return -EKEYREJECTED; 352 + } 353 + if (!pkcs7->have_authattrs) { 354 + pr_warn("Invalid firmware sig (missing authattrs)\n"); 355 + return -EKEYREJECTED; 356 + } 357 + break; 358 + case VERIFYING_KEXEC_PE_SIGNATURE: 359 + if (pkcs7->data_type != OID_msIndirectData) { 360 + pr_warn("Invalid kexec sig (not Authenticode)\n"); 361 + return -EKEYREJECTED; 362 + } 363 + /* Authattr presence checked in parser */ 364 + break; 365 + case VERIFYING_UNSPECIFIED_SIGNATURE: 366 + if (pkcs7->data_type != OID_data) { 367 + pr_warn("Invalid unspecified sig (not pkcs7-data)\n"); 368 + return -EKEYREJECTED; 369 + } 370 + break; 371 + default: 372 + return -EINVAL; 373 + } 374 + 385 375 for (n = 0, x509 = pkcs7->certs; x509; x509 = x509->next, n++) { 386 376 ret = x509_get_sig_params(x509); 387 377 if (ret < 0) 388 378 return ret; 389 - pr_debug("X.509[%u] %*phN\n", 390 - n, x509->authority->len, x509->authority->data); 391 379 } 392 380 393 381 for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) { ··· 443 359 return enopkg; 444 360 } 445 361 EXPORT_SYMBOL_GPL(pkcs7_verify); 362 + 363 + /** 364 + * pkcs7_supply_detached_data - Supply the data needed to verify a PKCS#7 message 365 + * @pkcs7: The PKCS#7 message 366 + * @data: The data to be verified 367 + * @datalen: The amount of data 368 + * 369 + * Supply the detached data needed to verify a PKCS#7 message. Note that no 370 + * attempt to retain/pin the data is made. That is left to the caller. The 371 + * data will not be modified by pkcs7_verify() and will not be freed when the 372 + * PKCS#7 message is freed. 373 + * 374 + * Returns -EINVAL if data is already supplied in the message, 0 otherwise. 375 + */ 376 + int pkcs7_supply_detached_data(struct pkcs7_message *pkcs7, 377 + const void *data, size_t datalen) 378 + { 379 + if (pkcs7->data) { 380 + pr_debug("Data already supplied\n"); 381 + return -EINVAL; 382 + } 383 + pkcs7->data = data; 384 + pkcs7->data_len = datalen; 385 + return 0; 386 + }
+1
crypto/asymmetric_keys/public_key.c
··· 39 39 const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST] = { 40 40 [PKEY_ID_PGP] = "PGP", 41 41 [PKEY_ID_X509] = "X509", 42 + [PKEY_ID_PKCS7] = "PKCS#7", 42 43 }; 43 44 EXPORT_SYMBOL_GPL(pkey_id_type_name); 44 45
+5 -2
crypto/asymmetric_keys/verify_pefile.c
··· 393 393 * @pebuf: Buffer containing the PE binary image 394 394 * @pelen: Length of the binary image 395 395 * @trust_keyring: Signing certificates to use as starting points 396 + * @usage: The use to which the key is being put. 396 397 * @_trusted: Set to true if trustworth, false otherwise 397 398 * 398 399 * Validate that the certificate chain inside the PKCS#7 message inside the PE ··· 418 417 * May also return -ENOMEM. 419 418 */ 420 419 int verify_pefile_signature(const void *pebuf, unsigned pelen, 421 - struct key *trusted_keyring, bool *_trusted) 420 + struct key *trusted_keyring, 421 + enum key_being_used_for usage, 422 + bool *_trusted) 422 423 { 423 424 struct pkcs7_message *pkcs7; 424 425 struct pefile_context ctx; ··· 465 462 if (ret < 0) 466 463 goto error; 467 464 468 - ret = pkcs7_verify(pkcs7); 465 + ret = pkcs7_verify(pkcs7, usage); 469 466 if (ret < 0) 470 467 goto error; 471 468
+35
crypto/asymmetric_keys/x509_akid.asn1
··· 1 + -- X.509 AuthorityKeyIdentifier 2 + -- rfc5280 section 4.2.1.1 3 + 4 + AuthorityKeyIdentifier ::= SEQUENCE { 5 + keyIdentifier [0] IMPLICIT KeyIdentifier OPTIONAL, 6 + authorityCertIssuer [1] IMPLICIT GeneralNames OPTIONAL, 7 + authorityCertSerialNumber [2] IMPLICIT CertificateSerialNumber OPTIONAL 8 + } 9 + 10 + KeyIdentifier ::= OCTET STRING ({ x509_akid_note_kid }) 11 + 12 + CertificateSerialNumber ::= INTEGER ({ x509_akid_note_serial }) 13 + 14 + GeneralNames ::= SEQUENCE OF GeneralName 15 + 16 + GeneralName ::= CHOICE { 17 + otherName [0] ANY, 18 + rfc822Name [1] IA5String, 19 + dNSName [2] IA5String, 20 + x400Address [3] ANY, 21 + directoryName [4] Name ({ x509_akid_note_name }), 22 + ediPartyName [5] ANY, 23 + uniformResourceIdentifier [6] IA5String, 24 + iPAddress [7] OCTET STRING, 25 + registeredID [8] OBJECT IDENTIFIER 26 + } 27 + 28 + Name ::= SEQUENCE OF RelativeDistinguishedName 29 + 30 + RelativeDistinguishedName ::= SET OF AttributeValueAssertion 31 + 32 + AttributeValueAssertion ::= SEQUENCE { 33 + attributeType OBJECT IDENTIFIER ({ x509_note_OID }), 34 + attributeValue ANY ({ x509_extract_name_segment }) 35 + }
+154 -77
crypto/asymmetric_keys/x509_cert_parser.c
··· 18 18 #include "public_key.h" 19 19 #include "x509_parser.h" 20 20 #include "x509-asn1.h" 21 + #include "x509_akid-asn1.h" 21 22 #include "x509_rsakey-asn1.h" 22 23 23 24 struct x509_parse_context { ··· 36 35 u16 o_offset; /* Offset of organizationName (O) */ 37 36 u16 cn_offset; /* Offset of commonName (CN) */ 38 37 u16 email_offset; /* Offset of emailAddress */ 38 + unsigned raw_akid_size; 39 + const void *raw_akid; /* Raw authorityKeyId in ASN.1 */ 40 + const void *akid_raw_issuer; /* Raw directoryName in authorityKeyId */ 41 + unsigned akid_raw_issuer_size; 39 42 }; 40 43 41 44 /* ··· 53 48 kfree(cert->subject); 54 49 kfree(cert->id); 55 50 kfree(cert->skid); 56 - kfree(cert->authority); 51 + kfree(cert->akid_id); 52 + kfree(cert->akid_skid); 57 53 kfree(cert->sig.digest); 58 54 mpi_free(cert->sig.rsa.s); 59 55 kfree(cert); ··· 90 84 ret = asn1_ber_decoder(&x509_decoder, ctx, data, datalen); 91 85 if (ret < 0) 92 86 goto error_decode; 87 + 88 + /* Decode the AuthorityKeyIdentifier */ 89 + if (ctx->raw_akid) { 90 + pr_devel("AKID: %u %*phN\n", 91 + ctx->raw_akid_size, ctx->raw_akid_size, ctx->raw_akid); 92 + ret = asn1_ber_decoder(&x509_akid_decoder, ctx, 93 + ctx->raw_akid, ctx->raw_akid_size); 94 + if (ret < 0) { 95 + pr_warn("Couldn't decode AuthKeyIdentifier\n"); 96 + goto error_decode; 97 + } 98 + } 93 99 94 100 /* Decode the public key */ 95 101 ret = asn1_ber_decoder(&x509_rsakey_decoder, ctx, ··· 440 422 struct x509_parse_context *ctx = context; 441 423 struct asymmetric_key_id *kid; 442 424 const unsigned char *v = value; 443 - int i; 444 425 445 426 pr_debug("Extension: %u\n", ctx->last_oid); 446 427 ··· 454 437 455 438 ctx->cert->raw_skid_size = vlen; 456 439 ctx->cert->raw_skid = v; 457 - kid = asymmetric_key_generate_id(ctx->cert->raw_subject, 458 - ctx->cert->raw_subject_size, 459 - v, vlen); 440 + kid = asymmetric_key_generate_id(v, vlen, "", 0); 460 441 if (IS_ERR(kid)) 461 442 return PTR_ERR(kid); 462 443 ctx->cert->skid = kid; ··· 464 449 465 450 if (ctx->last_oid == OID_authorityKeyIdentifier) { 466 451 /* Get hold of the CA key fingerprint */ 467 - if (ctx->cert->authority || vlen < 5) 468 - return -EBADMSG; 469 - 470 - /* Authority Key Identifier must be a Constructed SEQUENCE */ 471 - if (v[0] != (ASN1_SEQ | (ASN1_CONS << 5))) 472 - return -EBADMSG; 473 - 474 - /* Authority Key Identifier is not indefinite length */ 475 - if (unlikely(vlen == ASN1_INDEFINITE_LENGTH)) 476 - return -EBADMSG; 477 - 478 - if (vlen < ASN1_INDEFINITE_LENGTH) { 479 - /* Short Form length */ 480 - if (v[1] != vlen - 2 || 481 - v[2] != SEQ_TAG_KEYID || 482 - v[3] > vlen - 4) 483 - return -EBADMSG; 484 - 485 - vlen = v[3]; 486 - v += 4; 487 - } else { 488 - /* Long Form length */ 489 - size_t seq_len = 0; 490 - size_t sub = v[1] - ASN1_INDEFINITE_LENGTH; 491 - 492 - if (sub > 2) 493 - return -EBADMSG; 494 - 495 - /* calculate the length from subsequent octets */ 496 - v += 2; 497 - for (i = 0; i < sub; i++) { 498 - seq_len <<= 8; 499 - seq_len |= v[i]; 500 - } 501 - 502 - if (seq_len != vlen - 2 - sub || 503 - v[sub] != SEQ_TAG_KEYID || 504 - v[sub + 1] > vlen - 4 - sub) 505 - return -EBADMSG; 506 - 507 - vlen = v[sub + 1]; 508 - v += (sub + 2); 509 - } 510 - 511 - kid = asymmetric_key_generate_id(ctx->cert->raw_issuer, 512 - ctx->cert->raw_issuer_size, 513 - v, vlen); 514 - if (IS_ERR(kid)) 515 - return PTR_ERR(kid); 516 - pr_debug("authkeyid %*phN\n", kid->len, kid->data); 517 - ctx->cert->authority = kid; 452 + ctx->raw_akid = v; 453 + ctx->raw_akid_size = vlen; 518 454 return 0; 519 455 } 520 456 521 457 return 0; 522 458 } 523 459 524 - /* 525 - * Record a certificate time. 460 + /** 461 + * x509_decode_time - Decode an X.509 time ASN.1 object 462 + * @_t: The time to fill in 463 + * @hdrlen: The length of the object header 464 + * @tag: The object tag 465 + * @value: The object value 466 + * @vlen: The size of the object value 467 + * 468 + * Decode an ASN.1 universal time or generalised time field into a struct the 469 + * kernel can handle and check it for validity. The time is decoded thus: 470 + * 471 + * [RFC5280 §4.1.2.5] 472 + * CAs conforming to this profile MUST always encode certificate validity 473 + * dates through the year 2049 as UTCTime; certificate validity dates in 474 + * 2050 or later MUST be encoded as GeneralizedTime. Conforming 475 + * applications MUST be able to process validity dates that are encoded in 476 + * either UTCTime or GeneralizedTime. 526 477 */ 527 - static int x509_note_time(struct tm *tm, size_t hdrlen, 528 - unsigned char tag, 529 - const unsigned char *value, size_t vlen) 478 + int x509_decode_time(time64_t *_t, size_t hdrlen, 479 + unsigned char tag, 480 + const unsigned char *value, size_t vlen) 530 481 { 482 + static const unsigned char month_lengths[] = { 31, 29, 31, 30, 31, 30, 483 + 31, 31, 30, 31, 30, 31 }; 531 484 const unsigned char *p = value; 485 + unsigned year, mon, day, hour, min, sec, mon_len; 532 486 533 - #define dec2bin(X) ((X) - '0') 487 + #define dec2bin(X) ({ unsigned char x = (X) - '0'; if (x > 9) goto invalid_time; x; }) 534 488 #define DD2bin(P) ({ unsigned x = dec2bin(P[0]) * 10 + dec2bin(P[1]); P += 2; x; }) 535 489 536 490 if (tag == ASN1_UNITIM) { 537 491 /* UTCTime: YYMMDDHHMMSSZ */ 538 492 if (vlen != 13) 539 493 goto unsupported_time; 540 - tm->tm_year = DD2bin(p); 541 - if (tm->tm_year >= 50) 542 - tm->tm_year += 1900; 494 + year = DD2bin(p); 495 + if (year >= 50) 496 + year += 1900; 543 497 else 544 - tm->tm_year += 2000; 498 + year += 2000; 545 499 } else if (tag == ASN1_GENTIM) { 546 500 /* GenTime: YYYYMMDDHHMMSSZ */ 547 501 if (vlen != 15) 548 502 goto unsupported_time; 549 - tm->tm_year = DD2bin(p) * 100 + DD2bin(p); 503 + year = DD2bin(p) * 100 + DD2bin(p); 504 + if (year >= 1950 && year <= 2049) 505 + goto invalid_time; 550 506 } else { 551 507 goto unsupported_time; 552 508 } 553 509 554 - tm->tm_year -= 1900; 555 - tm->tm_mon = DD2bin(p) - 1; 556 - tm->tm_mday = DD2bin(p); 557 - tm->tm_hour = DD2bin(p); 558 - tm->tm_min = DD2bin(p); 559 - tm->tm_sec = DD2bin(p); 510 + mon = DD2bin(p); 511 + day = DD2bin(p); 512 + hour = DD2bin(p); 513 + min = DD2bin(p); 514 + sec = DD2bin(p); 560 515 561 516 if (*p != 'Z') 562 517 goto unsupported_time; 563 518 519 + mon_len = month_lengths[mon]; 520 + if (mon == 2) { 521 + if (year % 4 == 0) { 522 + mon_len = 29; 523 + if (year % 100 == 0) { 524 + year /= 100; 525 + if (year % 4 != 0) 526 + mon_len = 28; 527 + } 528 + } 529 + } 530 + 531 + if (year < 1970 || 532 + mon < 1 || mon > 12 || 533 + day < 1 || day > mon_len || 534 + hour < 0 || hour > 23 || 535 + min < 0 || min > 59 || 536 + sec < 0 || sec > 59) 537 + goto invalid_time; 538 + 539 + *_t = mktime64(year, mon, day, hour, min, sec); 564 540 return 0; 565 541 566 542 unsupported_time: 567 - pr_debug("Got unsupported time [tag %02x]: '%*.*s'\n", 568 - tag, (int)vlen, (int)vlen, value); 543 + pr_debug("Got unsupported time [tag %02x]: '%*phN'\n", 544 + tag, (int)vlen, value); 545 + return -EBADMSG; 546 + invalid_time: 547 + pr_debug("Got invalid time [tag %02x]: '%*phN'\n", 548 + tag, (int)vlen, value); 569 549 return -EBADMSG; 570 550 } 551 + EXPORT_SYMBOL_GPL(x509_decode_time); 571 552 572 553 int x509_note_not_before(void *context, size_t hdrlen, 573 554 unsigned char tag, 574 555 const void *value, size_t vlen) 575 556 { 576 557 struct x509_parse_context *ctx = context; 577 - return x509_note_time(&ctx->cert->valid_from, hdrlen, tag, value, vlen); 558 + return x509_decode_time(&ctx->cert->valid_from, hdrlen, tag, value, vlen); 578 559 } 579 560 580 561 int x509_note_not_after(void *context, size_t hdrlen, ··· 578 567 const void *value, size_t vlen) 579 568 { 580 569 struct x509_parse_context *ctx = context; 581 - return x509_note_time(&ctx->cert->valid_to, hdrlen, tag, value, vlen); 570 + return x509_decode_time(&ctx->cert->valid_to, hdrlen, tag, value, vlen); 571 + } 572 + 573 + /* 574 + * Note a key identifier-based AuthorityKeyIdentifier 575 + */ 576 + int x509_akid_note_kid(void *context, size_t hdrlen, 577 + unsigned char tag, 578 + const void *value, size_t vlen) 579 + { 580 + struct x509_parse_context *ctx = context; 581 + struct asymmetric_key_id *kid; 582 + 583 + pr_debug("AKID: keyid: %*phN\n", (int)vlen, value); 584 + 585 + if (ctx->cert->akid_skid) 586 + return 0; 587 + 588 + kid = asymmetric_key_generate_id(value, vlen, "", 0); 589 + if (IS_ERR(kid)) 590 + return PTR_ERR(kid); 591 + pr_debug("authkeyid %*phN\n", kid->len, kid->data); 592 + ctx->cert->akid_skid = kid; 593 + return 0; 594 + } 595 + 596 + /* 597 + * Note a directoryName in an AuthorityKeyIdentifier 598 + */ 599 + int x509_akid_note_name(void *context, size_t hdrlen, 600 + unsigned char tag, 601 + const void *value, size_t vlen) 602 + { 603 + struct x509_parse_context *ctx = context; 604 + 605 + pr_debug("AKID: name: %*phN\n", (int)vlen, value); 606 + 607 + ctx->akid_raw_issuer = value; 608 + ctx->akid_raw_issuer_size = vlen; 609 + return 0; 610 + } 611 + 612 + /* 613 + * Note a serial number in an AuthorityKeyIdentifier 614 + */ 615 + int x509_akid_note_serial(void *context, size_t hdrlen, 616 + unsigned char tag, 617 + const void *value, size_t vlen) 618 + { 619 + struct x509_parse_context *ctx = context; 620 + struct asymmetric_key_id *kid; 621 + 622 + pr_debug("AKID: serial: %*phN\n", (int)vlen, value); 623 + 624 + if (!ctx->akid_raw_issuer || ctx->cert->akid_id) 625 + return 0; 626 + 627 + kid = asymmetric_key_generate_id(value, 628 + vlen, 629 + ctx->akid_raw_issuer, 630 + ctx->akid_raw_issuer_size); 631 + if (IS_ERR(kid)) 632 + return PTR_ERR(kid); 633 + 634 + pr_debug("authkeyid %*phN\n", kid->len, kid->data); 635 + ctx->cert->akid_id = kid; 636 + return 0; 582 637 }
+8 -4
crypto/asymmetric_keys/x509_parser.h
··· 19 19 struct public_key_signature sig; /* Signature parameters */ 20 20 char *issuer; /* Name of certificate issuer */ 21 21 char *subject; /* Name of certificate subject */ 22 - struct asymmetric_key_id *id; /* Serial number + issuer */ 22 + struct asymmetric_key_id *id; /* Issuer + Serial number */ 23 23 struct asymmetric_key_id *skid; /* Subject + subjectKeyId (optional) */ 24 - struct asymmetric_key_id *authority; /* Authority key identifier (optional) */ 25 - struct tm valid_from; 26 - struct tm valid_to; 24 + struct asymmetric_key_id *akid_id; /* CA AuthKeyId matching ->id (optional) */ 25 + struct asymmetric_key_id *akid_skid; /* CA AuthKeyId matching ->skid (optional) */ 26 + time64_t valid_from; 27 + time64_t valid_to; 27 28 const void *tbs; /* Signed data */ 28 29 unsigned tbs_size; /* Size of signed data */ 29 30 unsigned raw_sig_size; /* Size of sigature */ ··· 49 48 */ 50 49 extern void x509_free_certificate(struct x509_certificate *cert); 51 50 extern struct x509_certificate *x509_cert_parse(const void *data, size_t datalen); 51 + extern int x509_decode_time(time64_t *_t, size_t hdrlen, 52 + unsigned char tag, 53 + const unsigned char *value, size_t vlen); 52 54 53 55 /* 54 56 * x509_public_key.c
+59 -34
crypto/asymmetric_keys/x509_public_key.c
··· 65 65 /** 66 66 * x509_request_asymmetric_key - Request a key by X.509 certificate params. 67 67 * @keyring: The keys to search. 68 - * @kid: The key ID. 68 + * @id: The issuer & serialNumber to look for or NULL. 69 + * @skid: The subjectKeyIdentifier to look for or NULL. 69 70 * @partial: Use partial match if true, exact if false. 70 71 * 71 - * Find a key in the given keyring by subject name and key ID. These might, 72 - * for instance, be the issuer name and the authority key ID of an X.509 73 - * certificate that needs to be verified. 72 + * Find a key in the given keyring by identifier. The preferred identifier is 73 + * the issuer + serialNumber and the fallback identifier is the 74 + * subjectKeyIdentifier. If both are given, the lookup is by the former, but 75 + * the latter must also match. 74 76 */ 75 77 struct key *x509_request_asymmetric_key(struct key *keyring, 76 - const struct asymmetric_key_id *kid, 78 + const struct asymmetric_key_id *id, 79 + const struct asymmetric_key_id *skid, 77 80 bool partial) 78 81 { 79 - key_ref_t key; 80 - char *id, *p; 82 + struct key *key; 83 + key_ref_t ref; 84 + const char *lookup; 85 + char *req, *p; 86 + int len; 81 87 88 + if (id) { 89 + lookup = id->data; 90 + len = id->len; 91 + } else { 92 + lookup = skid->data; 93 + len = skid->len; 94 + } 95 + 82 96 /* Construct an identifier "id:<keyid>". */ 83 - p = id = kmalloc(2 + 1 + kid->len * 2 + 1, GFP_KERNEL); 84 - if (!id) 97 + p = req = kmalloc(2 + 1 + len * 2 + 1, GFP_KERNEL); 98 + if (!req) 85 99 return ERR_PTR(-ENOMEM); 86 100 87 101 if (partial) { ··· 106 92 *p++ = 'x'; 107 93 } 108 94 *p++ = ':'; 109 - p = bin2hex(p, kid->data, kid->len); 95 + p = bin2hex(p, lookup, len); 110 96 *p = 0; 111 97 112 - pr_debug("Look up: \"%s\"\n", id); 98 + pr_debug("Look up: \"%s\"\n", req); 113 99 114 - key = keyring_search(make_key_ref(keyring, 1), 115 - &key_type_asymmetric, id); 116 - if (IS_ERR(key)) 117 - pr_debug("Request for key '%s' err %ld\n", id, PTR_ERR(key)); 118 - kfree(id); 100 + ref = keyring_search(make_key_ref(keyring, 1), 101 + &key_type_asymmetric, req); 102 + if (IS_ERR(ref)) 103 + pr_debug("Request for key '%s' err %ld\n", req, PTR_ERR(ref)); 104 + kfree(req); 119 105 120 - if (IS_ERR(key)) { 121 - switch (PTR_ERR(key)) { 106 + if (IS_ERR(ref)) { 107 + switch (PTR_ERR(ref)) { 122 108 /* Hide some search errors */ 123 109 case -EACCES: 124 110 case -ENOTDIR: 125 111 case -EAGAIN: 126 112 return ERR_PTR(-ENOKEY); 127 113 default: 128 - return ERR_CAST(key); 114 + return ERR_CAST(ref); 129 115 } 130 116 } 131 117 132 - pr_devel("<==%s() = 0 [%x]\n", __func__, 133 - key_serial(key_ref_to_ptr(key))); 134 - return key_ref_to_ptr(key); 118 + key = key_ref_to_ptr(ref); 119 + if (id && skid) { 120 + const struct asymmetric_key_ids *kids = asymmetric_key_ids(key); 121 + if (!kids->id[1]) { 122 + pr_debug("issuer+serial match, but expected SKID missing\n"); 123 + goto reject; 124 + } 125 + if (!asymmetric_key_id_same(skid, kids->id[1])) { 126 + pr_debug("issuer+serial match, but SKID does not\n"); 127 + goto reject; 128 + } 129 + } 130 + 131 + pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key)); 132 + return key; 133 + 134 + reject: 135 + key_put(key); 136 + return ERR_PTR(-EKEYREJECTED); 135 137 } 136 138 EXPORT_SYMBOL_GPL(x509_request_asymmetric_key); 137 139 ··· 257 227 if (!trust_keyring) 258 228 return -EOPNOTSUPP; 259 229 260 - if (ca_keyid && !asymmetric_key_id_partial(cert->authority, ca_keyid)) 230 + if (ca_keyid && !asymmetric_key_id_partial(cert->akid_skid, ca_keyid)) 261 231 return -EPERM; 262 232 263 - key = x509_request_asymmetric_key(trust_keyring, cert->authority, 233 + key = x509_request_asymmetric_key(trust_keyring, 234 + cert->akid_id, cert->akid_skid, 264 235 false); 265 236 if (!IS_ERR(key)) { 266 237 if (!use_builtin_keys ··· 302 271 } 303 272 304 273 pr_devel("Cert Key Algo: %s\n", pkey_algo_name[cert->pub->pkey_algo]); 305 - pr_devel("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n", 306 - cert->valid_from.tm_year + 1900, cert->valid_from.tm_mon + 1, 307 - cert->valid_from.tm_mday, cert->valid_from.tm_hour, 308 - cert->valid_from.tm_min, cert->valid_from.tm_sec); 309 - pr_devel("Cert Valid To: %04ld-%02d-%02d %02d:%02d:%02d\n", 310 - cert->valid_to.tm_year + 1900, cert->valid_to.tm_mon + 1, 311 - cert->valid_to.tm_mday, cert->valid_to.tm_hour, 312 - cert->valid_to.tm_min, cert->valid_to.tm_sec); 274 + pr_devel("Cert Valid period: %lld-%lld\n", cert->valid_from, cert->valid_to); 313 275 pr_devel("Cert Signature: %s + %s\n", 314 276 pkey_algo_name[cert->sig.pkey_algo], 315 277 hash_algo_name[cert->sig.pkey_hash_algo]); ··· 311 287 cert->pub->id_type = PKEY_ID_X509; 312 288 313 289 /* Check the signature on the key if it appears to be self-signed */ 314 - if (!cert->authority || 315 - asymmetric_key_id_same(cert->skid, cert->authority)) { 290 + if ((!cert->akid_skid && !cert->akid_id) || 291 + asymmetric_key_id_same(cert->skid, cert->akid_skid) || 292 + asymmetric_key_id_same(cert->id, cert->akid_id)) { 316 293 ret = x509_check_signature(cert->pub, cert); /* self-signed */ 317 294 if (ret < 0) 318 295 goto error_free_cert;
+12 -1
include/crypto/pkcs7.h
··· 9 9 * 2 of the Licence, or (at your option) any later version. 10 10 */ 11 11 12 + #ifndef _CRYPTO_PKCS7_H 13 + #define _CRYPTO_PKCS7_H 14 + 15 + #include <crypto/public_key.h> 16 + 12 17 struct key; 13 18 struct pkcs7_message; 14 19 ··· 38 33 /* 39 34 * pkcs7_verify.c 40 35 */ 41 - extern int pkcs7_verify(struct pkcs7_message *pkcs7); 36 + extern int pkcs7_verify(struct pkcs7_message *pkcs7, 37 + enum key_being_used_for usage); 38 + 39 + extern int pkcs7_supply_detached_data(struct pkcs7_message *pkcs7, 40 + const void *data, size_t datalen); 41 + 42 + #endif /* _CRYPTO_PKCS7_H */
+17 -1
include/crypto/public_key.h
··· 33 33 enum pkey_id_type { 34 34 PKEY_ID_PGP, /* OpenPGP generated key ID */ 35 35 PKEY_ID_X509, /* X.509 arbitrary subjectKeyIdentifier */ 36 + PKEY_ID_PKCS7, /* Signature in PKCS#7 message */ 36 37 PKEY_ID_TYPE__LAST 37 38 }; 38 39 39 40 extern const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST]; 41 + 42 + /* 43 + * The use to which an asymmetric key is being put. 44 + */ 45 + enum key_being_used_for { 46 + VERIFYING_MODULE_SIGNATURE, 47 + VERIFYING_FIRMWARE_SIGNATURE, 48 + VERIFYING_KEXEC_PE_SIGNATURE, 49 + VERIFYING_KEY_SIGNATURE, 50 + VERIFYING_KEY_SELF_SIGNATURE, 51 + VERIFYING_UNSPECIFIED_SIGNATURE, 52 + NR__KEY_BEING_USED_FOR 53 + }; 54 + extern const char *const key_being_used_for[NR__KEY_BEING_USED_FOR]; 40 55 41 56 /* 42 57 * Cryptographic data for the public-key subtype of the asymmetric key type. ··· 116 101 117 102 struct asymmetric_key_id; 118 103 extern struct key *x509_request_asymmetric_key(struct key *keyring, 119 - const struct asymmetric_key_id *kid, 104 + const struct asymmetric_key_id *id, 105 + const struct asymmetric_key_id *skid, 120 106 bool partial); 121 107 122 108 #endif /* _LINUX_PUBLIC_KEY_H */
+7
include/keys/system_keyring.h
··· 15 15 #ifdef CONFIG_SYSTEM_TRUSTED_KEYRING 16 16 17 17 #include <linux/key.h> 18 + #include <crypto/public_key.h> 18 19 19 20 extern struct key *system_trusted_keyring; 20 21 static inline struct key *get_system_trusted_keyring(void) ··· 27 26 { 28 27 return NULL; 29 28 } 29 + #endif 30 + 31 + #ifdef CONFIG_SYSTEM_DATA_VERIFICATION 32 + extern int system_verify_data(const void *data, unsigned long len, 33 + const void *raw_pkcs7, size_t pkcs7_len, 34 + enum key_being_used_for usage); 30 35 #endif 31 36 32 37 #endif /* _KEYS_SYSTEM_KEYRING_H */
+11 -5
include/linux/asn1_ber_bytecode.h
··· 45 45 ASN1_OP_MATCH_JUMP = 0x04, 46 46 ASN1_OP_MATCH_JUMP_OR_SKIP = 0x05, 47 47 ASN1_OP_MATCH_ANY = 0x08, 48 + ASN1_OP_MATCH_ANY_OR_SKIP = 0x09, 48 49 ASN1_OP_MATCH_ANY_ACT = 0x0a, 50 + ASN1_OP_MATCH_ANY_ACT_OR_SKIP = 0x0b, 49 51 /* Everything before here matches unconditionally */ 50 52 51 53 ASN1_OP_COND_MATCH_OR_SKIP = 0x11, 52 54 ASN1_OP_COND_MATCH_ACT_OR_SKIP = 0x13, 53 55 ASN1_OP_COND_MATCH_JUMP_OR_SKIP = 0x15, 54 56 ASN1_OP_COND_MATCH_ANY = 0x18, 57 + ASN1_OP_COND_MATCH_ANY_OR_SKIP = 0x19, 55 58 ASN1_OP_COND_MATCH_ANY_ACT = 0x1a, 59 + ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP = 0x1b, 56 60 57 61 /* Everything before here will want a tag from the data */ 58 - #define ASN1_OP__MATCHES_TAG ASN1_OP_COND_MATCH_ANY_ACT 62 + #define ASN1_OP__MATCHES_TAG ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP 59 63 60 64 /* These are here to help fill up space */ 61 - ASN1_OP_COND_FAIL = 0x1b, 62 - ASN1_OP_COMPLETE = 0x1c, 63 - ASN1_OP_ACT = 0x1d, 64 - ASN1_OP_RETURN = 0x1e, 65 + ASN1_OP_COND_FAIL = 0x1c, 66 + ASN1_OP_COMPLETE = 0x1d, 67 + ASN1_OP_ACT = 0x1e, 68 + ASN1_OP_MAYBE_ACT = 0x1f, 65 69 66 70 /* The following eight have bit 0 -> SET, 1 -> OF, 2 -> ACT */ 67 71 ASN1_OP_END_SEQ = 0x20, ··· 79 75 #define ASN1_OP_END__SET 0x01 80 76 #define ASN1_OP_END__OF 0x02 81 77 #define ASN1_OP_END__ACT 0x04 78 + 79 + ASN1_OP_RETURN = 0x28, 82 80 83 81 ASN1_OP__NR 84 82 };
+7
include/linux/lsm_audit.h
··· 40 40 } fam; 41 41 }; 42 42 43 + struct lsm_ioctlop_audit { 44 + struct path path; 45 + u16 cmd; 46 + }; 47 + 43 48 /* Auxiliary data to use in generating the audit record. */ 44 49 struct common_audit_data { 45 50 char type; ··· 58 53 #define LSM_AUDIT_DATA_KMOD 8 59 54 #define LSM_AUDIT_DATA_INODE 9 60 55 #define LSM_AUDIT_DATA_DENTRY 10 56 + #define LSM_AUDIT_DATA_IOCTL_OP 11 61 57 union { 62 58 struct path path; 63 59 struct dentry *dentry; ··· 74 68 } key_struct; 75 69 #endif 76 70 char *kmod_name; 71 + struct lsm_ioctlop_audit *op; 77 72 } u; 78 73 /* this union contains LSM specific data */ 79 74 union {
+4 -2
include/linux/lsm_hooks.h
··· 1881 1881 1882 1882 extern int __init security_module_enable(const char *module); 1883 1883 extern void __init capability_add_hooks(void); 1884 - #ifdef CONFIG_SECURITY_YAMA_STACKED 1885 - void __init yama_add_hooks(void); 1884 + #ifdef CONFIG_SECURITY_YAMA 1885 + extern void __init yama_add_hooks(void); 1886 + #else 1887 + static inline void __init yama_add_hooks(void) { } 1886 1888 #endif 1887 1889 1888 1890 #endif /* ! __LINUX_LSM_HOOKS_H */
+6 -1
include/linux/oid_registry.h
··· 41 41 OID_signed_data, /* 1.2.840.113549.1.7.2 */ 42 42 /* PKCS#9 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9)} */ 43 43 OID_email_address, /* 1.2.840.113549.1.9.1 */ 44 - OID_content_type, /* 1.2.840.113549.1.9.3 */ 44 + OID_contentType, /* 1.2.840.113549.1.9.3 */ 45 45 OID_messageDigest, /* 1.2.840.113549.1.9.4 */ 46 46 OID_signingTime, /* 1.2.840.113549.1.9.5 */ 47 47 OID_smimeCapabilites, /* 1.2.840.113549.1.9.15 */ ··· 54 54 55 55 /* Microsoft Authenticode & Software Publishing */ 56 56 OID_msIndirectData, /* 1.3.6.1.4.1.311.2.1.4 */ 57 + OID_msStatementType, /* 1.3.6.1.4.1.311.2.1.11 */ 58 + OID_msSpOpusInfo, /* 1.3.6.1.4.1.311.2.1.12 */ 57 59 OID_msPeImageDataObjId, /* 1.3.6.1.4.1.311.2.1.15 */ 58 60 OID_msIndividualSPKeyPurpose, /* 1.3.6.1.4.1.311.2.1.21 */ 59 61 OID_msOutlookExpress, /* 1.3.6.1.4.1.311.16.4 */ ··· 63 61 OID_certAuthInfoAccess, /* 1.3.6.1.5.5.7.1.1 */ 64 62 OID_sha1, /* 1.3.14.3.2.26 */ 65 63 OID_sha256, /* 2.16.840.1.101.3.4.2.1 */ 64 + OID_sha384, /* 2.16.840.1.101.3.4.2.2 */ 65 + OID_sha512, /* 2.16.840.1.101.3.4.2.3 */ 66 + OID_sha224, /* 2.16.840.1.101.3.4.2.4 */ 66 67 67 68 /* Distinguished Name attribute IDs [RFC 2256] */ 68 69 OID_commonName, /* 2.5.4.3 */
+1
include/linux/ptrace.h
··· 34 34 #define PT_TRACE_SECCOMP PT_EVENT_FLAG(PTRACE_EVENT_SECCOMP) 35 35 36 36 #define PT_EXITKILL (PTRACE_O_EXITKILL << PT_OPT_FLAG_SHIFT) 37 + #define PT_SUSPEND_SECCOMP (PTRACE_O_SUSPEND_SECCOMP << PT_OPT_FLAG_SHIFT) 37 38 38 39 /* single stepping state bits (used on ARM and PA-RISC) */ 39 40 #define PT_SINGLESTEP_BIT 31
+1 -1
include/linux/seccomp.h
··· 78 78 79 79 static inline int seccomp_mode(struct seccomp *s) 80 80 { 81 - return 0; 81 + return SECCOMP_MODE_DISABLED; 82 82 } 83 83 #endif /* CONFIG_SECCOMP */ 84 84
+5 -1
include/linux/verify_pefile.h
··· 12 12 #ifndef _LINUX_VERIFY_PEFILE_H 13 13 #define _LINUX_VERIFY_PEFILE_H 14 14 15 + #include <crypto/public_key.h> 16 + 15 17 extern int verify_pefile_signature(const void *pebuf, unsigned pelen, 16 - struct key *trusted_keyring, bool *_trusted); 18 + struct key *trusted_keyring, 19 + enum key_being_used_for usage, 20 + bool *_trusted); 17 21 18 22 #endif /* _LINUX_VERIFY_PEFILE_H */
+4 -2
include/uapi/linux/ptrace.h
··· 89 89 #define PTRACE_O_TRACESECCOMP (1 << PTRACE_EVENT_SECCOMP) 90 90 91 91 /* eventless options */ 92 - #define PTRACE_O_EXITKILL (1 << 20) 92 + #define PTRACE_O_EXITKILL (1 << 20) 93 + #define PTRACE_O_SUSPEND_SECCOMP (1 << 21) 93 94 94 - #define PTRACE_O_MASK (0x000000ff | PTRACE_O_EXITKILL) 95 + #define PTRACE_O_MASK (\ 96 + 0x000000ff | PTRACE_O_EXITKILL | PTRACE_O_SUSPEND_SECCOMP) 95 97 96 98 #include <asm/ptrace.h> 97 99
+21 -19
init/Kconfig
··· 1765 1765 1766 1766 See Documentation/nommu-mmap.txt for more information. 1767 1767 1768 - config SYSTEM_TRUSTED_KEYRING 1769 - bool "Provide system-wide ring of trusted keys" 1770 - depends on KEYS 1768 + config SYSTEM_DATA_VERIFICATION 1769 + def_bool n 1770 + select SYSTEM_TRUSTED_KEYRING 1771 + select KEYS 1772 + select CRYPTO 1773 + select ASYMMETRIC_KEY_TYPE 1774 + select ASYMMETRIC_PUBLIC_KEY_SUBTYPE 1775 + select PUBLIC_KEY_ALGO_RSA 1776 + select ASN1 1777 + select OID_REGISTRY 1778 + select X509_CERTIFICATE_PARSER 1779 + select PKCS7_MESSAGE_PARSER 1771 1780 help 1772 - Provide a system keyring to which trusted keys can be added. Keys in 1773 - the keyring are considered to be trusted. Keys may be added at will 1774 - by the kernel from compiled-in data and from hardware key stores, but 1775 - userspace may only add extra keys if those keys can be verified by 1776 - keys already in the keyring. 1777 - 1778 - Keys in this keyring are used by module signature checking. 1781 + Provide PKCS#7 message verification using the contents of the system 1782 + trusted keyring to provide public keys. This then can be used for 1783 + module verification, kexec image verification and firmware blob 1784 + verification. 1779 1785 1780 1786 config PROFILING 1781 1787 bool "Profiling support" ··· 1891 1885 config MODULE_SIG 1892 1886 bool "Module signature verification" 1893 1887 depends on MODULES 1894 - select SYSTEM_TRUSTED_KEYRING 1895 - select KEYS 1896 - select CRYPTO 1897 - select ASYMMETRIC_KEY_TYPE 1898 - select ASYMMETRIC_PUBLIC_KEY_SUBTYPE 1899 - select PUBLIC_KEY_ALGO_RSA 1900 - select ASN1 1901 - select OID_REGISTRY 1902 - select X509_CERTIFICATE_PARSER 1888 + select SYSTEM_DATA_VERIFICATION 1903 1889 help 1904 1890 Check modules for valid signatures upon load: the signature 1905 1891 is simply appended to the module. For more information see 1906 1892 Documentation/module-signing.txt. 1893 + 1894 + Note that this option adds the OpenSSL development packages as a 1895 + kernel build dependency so that the signing tool can use its crypto 1896 + library. 1907 1897 1908 1898 !!!WARNING!!! If you enable this option, you MUST make sure that the 1909 1899 module DOES NOT get stripped after being signed. This includes the
-97
kernel/Makefile
··· 45 45 obj-y += up.o 46 46 endif 47 47 obj-$(CONFIG_UID16) += uid16.o 48 - obj-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += system_keyring.o system_certificates.o 49 48 obj-$(CONFIG_MODULES) += module.o 50 49 obj-$(CONFIG_MODULE_SIG) += module_signing.o 51 50 obj-$(CONFIG_KALLSYMS) += kallsyms.o ··· 111 112 targets += config_data.h 112 113 $(obj)/config_data.h: $(obj)/config_data.gz FORCE 113 114 $(call filechk,ikconfiggz) 114 - 115 - ############################################################################### 116 - # 117 - # Roll all the X.509 certificates that we can find together and pull them into 118 - # the kernel so that they get loaded into the system trusted keyring during 119 - # boot. 120 - # 121 - # We look in the source root and the build root for all files whose name ends 122 - # in ".x509". Unfortunately, this will generate duplicate filenames, so we 123 - # have make canonicalise the pathnames and then sort them to discard the 124 - # duplicates. 125 - # 126 - ############################################################################### 127 - ifeq ($(CONFIG_SYSTEM_TRUSTED_KEYRING),y) 128 - X509_CERTIFICATES-y := $(wildcard *.x509) $(wildcard $(srctree)/*.x509) 129 - X509_CERTIFICATES-$(CONFIG_MODULE_SIG) += $(objtree)/signing_key.x509 130 - X509_CERTIFICATES-raw := $(sort $(foreach CERT,$(X509_CERTIFICATES-y), \ 131 - $(or $(realpath $(CERT)),$(CERT)))) 132 - X509_CERTIFICATES := $(subst $(realpath $(objtree))/,,$(X509_CERTIFICATES-raw)) 133 - 134 - ifeq ($(X509_CERTIFICATES),) 135 - $(warning *** No X.509 certificates found ***) 136 - endif 137 - 138 - ifneq ($(wildcard $(obj)/.x509.list),) 139 - ifneq ($(shell cat $(obj)/.x509.list),$(X509_CERTIFICATES)) 140 - $(warning X.509 certificate list changed to "$(X509_CERTIFICATES)" from "$(shell cat $(obj)/.x509.list)") 141 - $(shell rm $(obj)/.x509.list) 142 - endif 143 - endif 144 - 145 - kernel/system_certificates.o: $(obj)/x509_certificate_list 146 - 147 - quiet_cmd_x509certs = CERTS $@ 148 - cmd_x509certs = cat $(X509_CERTIFICATES) /dev/null >$@ $(foreach X509,$(X509_CERTIFICATES),; $(kecho) " - Including cert $(X509)") 149 - 150 - targets += $(obj)/x509_certificate_list 151 - $(obj)/x509_certificate_list: $(X509_CERTIFICATES) $(obj)/.x509.list 152 - $(call if_changed,x509certs) 153 - 154 - targets += $(obj)/.x509.list 155 - $(obj)/.x509.list: 156 - @echo $(X509_CERTIFICATES) >$@ 157 - endif 158 - 159 - clean-files := x509_certificate_list .x509.list 160 - 161 - ifeq ($(CONFIG_MODULE_SIG),y) 162 - ############################################################################### 163 - # 164 - # If module signing is requested, say by allyesconfig, but a key has not been 165 - # supplied, then one will need to be generated to make sure the build does not 166 - # fail and that the kernel may be used afterwards. 167 - # 168 - ############################################################################### 169 - ifndef CONFIG_MODULE_SIG_HASH 170 - $(error Could not determine digest type to use from kernel config) 171 - endif 172 - 173 - signing_key.priv signing_key.x509: x509.genkey 174 - @echo "###" 175 - @echo "### Now generating an X.509 key pair to be used for signing modules." 176 - @echo "###" 177 - @echo "### If this takes a long time, you might wish to run rngd in the" 178 - @echo "### background to keep the supply of entropy topped up. It" 179 - @echo "### needs to be run as root, and uses a hardware random" 180 - @echo "### number generator if one is available." 181 - @echo "###" 182 - openssl req -new -nodes -utf8 -$(CONFIG_MODULE_SIG_HASH) -days 36500 \ 183 - -batch -x509 -config x509.genkey \ 184 - -outform DER -out signing_key.x509 \ 185 - -keyout signing_key.priv 2>&1 186 - @echo "###" 187 - @echo "### Key pair generated." 188 - @echo "###" 189 - 190 - x509.genkey: 191 - @echo Generating X.509 key generation config 192 - @echo >x509.genkey "[ req ]" 193 - @echo >>x509.genkey "default_bits = 4096" 194 - @echo >>x509.genkey "distinguished_name = req_distinguished_name" 195 - @echo >>x509.genkey "prompt = no" 196 - @echo >>x509.genkey "string_mask = utf8only" 197 - @echo >>x509.genkey "x509_extensions = myexts" 198 - @echo >>x509.genkey 199 - @echo >>x509.genkey "[ req_distinguished_name ]" 200 - @echo >>x509.genkey "#O = Unspecified company" 201 - @echo >>x509.genkey "CN = Build time autogenerated kernel key" 202 - @echo >>x509.genkey "#emailAddress = unspecified.user@unspecified.company" 203 - @echo >>x509.genkey 204 - @echo >>x509.genkey "[ myexts ]" 205 - @echo >>x509.genkey "basicConstraints=critical,CA:FALSE" 206 - @echo >>x509.genkey "keyUsage=digitalSignature" 207 - @echo >>x509.genkey "subjectKeyIdentifier=hash" 208 - @echo >>x509.genkey "authorityKeyIdentifier=keyid" 209 - endif
+20 -193
kernel/module_signing.c
··· 10 10 */ 11 11 12 12 #include <linux/kernel.h> 13 - #include <linux/err.h> 14 - #include <crypto/public_key.h> 15 - #include <crypto/hash.h> 16 - #include <keys/asymmetric-type.h> 17 13 #include <keys/system_keyring.h> 14 + #include <crypto/public_key.h> 18 15 #include "module-internal.h" 19 16 20 17 /* ··· 25 28 * - Information block 26 29 */ 27 30 struct module_signature { 28 - u8 algo; /* Public-key crypto algorithm [enum pkey_algo] */ 29 - u8 hash; /* Digest algorithm [enum hash_algo] */ 30 - u8 id_type; /* Key identifier type [enum pkey_id_type] */ 31 - u8 signer_len; /* Length of signer's name */ 32 - u8 key_id_len; /* Length of key identifier */ 31 + u8 algo; /* Public-key crypto algorithm [0] */ 32 + u8 hash; /* Digest algorithm [0] */ 33 + u8 id_type; /* Key identifier type [PKEY_ID_PKCS7] */ 34 + u8 signer_len; /* Length of signer's name [0] */ 35 + u8 key_id_len; /* Length of key identifier [0] */ 33 36 u8 __pad[3]; 34 37 __be32 sig_len; /* Length of signature data */ 35 38 }; 36 - 37 - /* 38 - * Digest the module contents. 39 - */ 40 - static struct public_key_signature *mod_make_digest(enum hash_algo hash, 41 - const void *mod, 42 - unsigned long modlen) 43 - { 44 - struct public_key_signature *pks; 45 - struct crypto_shash *tfm; 46 - struct shash_desc *desc; 47 - size_t digest_size, desc_size; 48 - int ret; 49 - 50 - pr_devel("==>%s()\n", __func__); 51 - 52 - /* Allocate the hashing algorithm we're going to need and find out how 53 - * big the hash operational data will be. 54 - */ 55 - tfm = crypto_alloc_shash(hash_algo_name[hash], 0, 0); 56 - if (IS_ERR(tfm)) 57 - return (PTR_ERR(tfm) == -ENOENT) ? ERR_PTR(-ENOPKG) : ERR_CAST(tfm); 58 - 59 - desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); 60 - digest_size = crypto_shash_digestsize(tfm); 61 - 62 - /* We allocate the hash operational data storage on the end of our 63 - * context data and the digest output buffer on the end of that. 64 - */ 65 - ret = -ENOMEM; 66 - pks = kzalloc(digest_size + sizeof(*pks) + desc_size, GFP_KERNEL); 67 - if (!pks) 68 - goto error_no_pks; 69 - 70 - pks->pkey_hash_algo = hash; 71 - pks->digest = (u8 *)pks + sizeof(*pks) + desc_size; 72 - pks->digest_size = digest_size; 73 - 74 - desc = (void *)pks + sizeof(*pks); 75 - desc->tfm = tfm; 76 - desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; 77 - 78 - ret = crypto_shash_init(desc); 79 - if (ret < 0) 80 - goto error; 81 - 82 - ret = crypto_shash_finup(desc, mod, modlen, pks->digest); 83 - if (ret < 0) 84 - goto error; 85 - 86 - crypto_free_shash(tfm); 87 - pr_devel("<==%s() = ok\n", __func__); 88 - return pks; 89 - 90 - error: 91 - kfree(pks); 92 - error_no_pks: 93 - crypto_free_shash(tfm); 94 - pr_devel("<==%s() = %d\n", __func__, ret); 95 - return ERR_PTR(ret); 96 - } 97 - 98 - /* 99 - * Extract an MPI array from the signature data. This represents the actual 100 - * signature. Each raw MPI is prefaced by a BE 2-byte value indicating the 101 - * size of the MPI in bytes. 102 - * 103 - * RSA signatures only have one MPI, so currently we only read one. 104 - */ 105 - static int mod_extract_mpi_array(struct public_key_signature *pks, 106 - const void *data, size_t len) 107 - { 108 - size_t nbytes; 109 - MPI mpi; 110 - 111 - if (len < 3) 112 - return -EBADMSG; 113 - nbytes = ((const u8 *)data)[0] << 8 | ((const u8 *)data)[1]; 114 - data += 2; 115 - len -= 2; 116 - if (len != nbytes) 117 - return -EBADMSG; 118 - 119 - mpi = mpi_read_raw_data(data, nbytes); 120 - if (!mpi) 121 - return -ENOMEM; 122 - pks->mpi[0] = mpi; 123 - pks->nr_mpi = 1; 124 - return 0; 125 - } 126 - 127 - /* 128 - * Request an asymmetric key. 129 - */ 130 - static struct key *request_asymmetric_key(const char *signer, size_t signer_len, 131 - const u8 *key_id, size_t key_id_len) 132 - { 133 - key_ref_t key; 134 - size_t i; 135 - char *id, *q; 136 - 137 - pr_devel("==>%s(,%zu,,%zu)\n", __func__, signer_len, key_id_len); 138 - 139 - /* Construct an identifier. */ 140 - id = kmalloc(signer_len + 2 + key_id_len * 2 + 1, GFP_KERNEL); 141 - if (!id) 142 - return ERR_PTR(-ENOKEY); 143 - 144 - memcpy(id, signer, signer_len); 145 - 146 - q = id + signer_len; 147 - *q++ = ':'; 148 - *q++ = ' '; 149 - for (i = 0; i < key_id_len; i++) { 150 - *q++ = hex_asc[*key_id >> 4]; 151 - *q++ = hex_asc[*key_id++ & 0x0f]; 152 - } 153 - 154 - *q = 0; 155 - 156 - pr_debug("Look up: \"%s\"\n", id); 157 - 158 - key = keyring_search(make_key_ref(system_trusted_keyring, 1), 159 - &key_type_asymmetric, id); 160 - if (IS_ERR(key)) 161 - pr_warn("Request for unknown module key '%s' err %ld\n", 162 - id, PTR_ERR(key)); 163 - kfree(id); 164 - 165 - if (IS_ERR(key)) { 166 - switch (PTR_ERR(key)) { 167 - /* Hide some search errors */ 168 - case -EACCES: 169 - case -ENOTDIR: 170 - case -EAGAIN: 171 - return ERR_PTR(-ENOKEY); 172 - default: 173 - return ERR_CAST(key); 174 - } 175 - } 176 - 177 - pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key_ref_to_ptr(key))); 178 - return key_ref_to_ptr(key); 179 - } 180 39 181 40 /* 182 41 * Verify the signature on a module. 183 42 */ 184 43 int mod_verify_sig(const void *mod, unsigned long *_modlen) 185 44 { 186 - struct public_key_signature *pks; 187 45 struct module_signature ms; 188 - struct key *key; 189 - const void *sig; 190 46 size_t modlen = *_modlen, sig_len; 191 - int ret; 192 47 193 48 pr_devel("==>%s(,%zu)\n", __func__, modlen); 194 49 ··· 54 205 if (sig_len >= modlen) 55 206 return -EBADMSG; 56 207 modlen -= sig_len; 57 - if ((size_t)ms.signer_len + ms.key_id_len >= modlen) 58 - return -EBADMSG; 59 - modlen -= (size_t)ms.signer_len + ms.key_id_len; 60 - 61 208 *_modlen = modlen; 62 - sig = mod + modlen; 63 209 64 - /* For the moment, only support RSA and X.509 identifiers */ 65 - if (ms.algo != PKEY_ALGO_RSA || 66 - ms.id_type != PKEY_ID_X509) 210 + if (ms.id_type != PKEY_ID_PKCS7) { 211 + pr_err("Module is not signed with expected PKCS#7 message\n"); 67 212 return -ENOPKG; 68 - 69 - if (ms.hash >= PKEY_HASH__LAST || 70 - !hash_algo_name[ms.hash]) 71 - return -ENOPKG; 72 - 73 - key = request_asymmetric_key(sig, ms.signer_len, 74 - sig + ms.signer_len, ms.key_id_len); 75 - if (IS_ERR(key)) 76 - return PTR_ERR(key); 77 - 78 - pks = mod_make_digest(ms.hash, mod, modlen); 79 - if (IS_ERR(pks)) { 80 - ret = PTR_ERR(pks); 81 - goto error_put_key; 82 213 } 83 214 84 - ret = mod_extract_mpi_array(pks, sig + ms.signer_len + ms.key_id_len, 85 - sig_len); 86 - if (ret < 0) 87 - goto error_free_pks; 215 + if (ms.algo != 0 || 216 + ms.hash != 0 || 217 + ms.signer_len != 0 || 218 + ms.key_id_len != 0 || 219 + ms.__pad[0] != 0 || 220 + ms.__pad[1] != 0 || 221 + ms.__pad[2] != 0) { 222 + pr_err("PKCS#7 signature info has unexpected non-zero params\n"); 223 + return -EBADMSG; 224 + } 88 225 89 - ret = verify_signature(key, pks); 90 - pr_devel("verify_signature() = %d\n", ret); 91 - 92 - error_free_pks: 93 - mpi_free(pks->rsa.s); 94 - kfree(pks); 95 - error_put_key: 96 - key_put(key); 97 - pr_devel("<==%s() = %d\n", __func__, ret); 98 - return ret; 226 + return system_verify_data(mod, modlen, mod + modlen, sig_len, 227 + VERIFYING_MODULE_SIGNATURE); 99 228 }
+13
kernel/ptrace.c
··· 556 556 if (data & ~(unsigned long)PTRACE_O_MASK) 557 557 return -EINVAL; 558 558 559 + if (unlikely(data & PTRACE_O_SUSPEND_SECCOMP)) { 560 + if (!config_enabled(CONFIG_CHECKPOINT_RESTORE) || 561 + !config_enabled(CONFIG_SECCOMP)) 562 + return -EINVAL; 563 + 564 + if (!capable(CAP_SYS_ADMIN)) 565 + return -EPERM; 566 + 567 + if (seccomp_mode(&current->seccomp) != SECCOMP_MODE_DISABLED || 568 + current->ptrace & PT_SUSPEND_SECCOMP) 569 + return -EPERM; 570 + } 571 + 559 572 /* Avoid intermediate state when all opts are cleared */ 560 573 flags = child->ptrace; 561 574 flags &= ~(PTRACE_O_MASK << PT_OPT_FLAG_SHIFT);
+12 -5
kernel/seccomp.c
··· 175 175 */ 176 176 static u32 seccomp_run_filters(struct seccomp_data *sd) 177 177 { 178 - struct seccomp_filter *f = ACCESS_ONCE(current->seccomp.filter); 179 178 struct seccomp_data sd_local; 180 179 u32 ret = SECCOMP_RET_ALLOW; 180 + /* Make sure cross-thread synced filter points somewhere sane. */ 181 + struct seccomp_filter *f = 182 + lockless_dereference(current->seccomp.filter); 181 183 182 184 /* Ensure unexpected behavior doesn't result in failing open. */ 183 185 if (unlikely(WARN_ON(f == NULL))) 184 186 return SECCOMP_RET_KILL; 185 - 186 - /* Make sure cross-thread synced filter points somewhere sane. */ 187 - smp_read_barrier_depends(); 188 187 189 188 if (!sd) { 190 189 populate_seccomp_data(&sd_local); ··· 548 549 { 549 550 int mode = current->seccomp.mode; 550 551 551 - if (mode == 0) 552 + if (config_enabled(CONFIG_CHECKPOINT_RESTORE) && 553 + unlikely(current->ptrace & PT_SUSPEND_SECCOMP)) 554 + return; 555 + 556 + if (mode == SECCOMP_MODE_DISABLED) 552 557 return; 553 558 else if (mode == SECCOMP_MODE_STRICT) 554 559 __secure_computing_strict(this_syscall); ··· 652 649 int mode = current->seccomp.mode; 653 650 int this_syscall = sd ? sd->nr : 654 651 syscall_get_nr(current, task_pt_regs(current)); 652 + 653 + if (config_enabled(CONFIG_CHECKPOINT_RESTORE) && 654 + unlikely(current->ptrace & PT_SUSPEND_SECCOMP)) 655 + return SECCOMP_PHASE1_OK; 655 656 656 657 switch (mode) { 657 658 case SECCOMP_MODE_STRICT:
+4 -1
kernel/system_certificates.S certs/system_certificates.S
··· 7 7 .globl VMLINUX_SYMBOL(system_certificate_list) 8 8 VMLINUX_SYMBOL(system_certificate_list): 9 9 __cert_list_start: 10 - .incbin "kernel/x509_certificate_list" 10 + #ifdef CONFIG_MODULE_SIG 11 + .incbin "certs/signing_key.x509" 12 + #endif 13 + .incbin "certs/x509_certificate_list" 11 14 __cert_list_end: 12 15 13 16 .align 8
+52 -1
kernel/system_keyring.c certs/system_keyring.c
··· 16 16 #include <linux/err.h> 17 17 #include <keys/asymmetric-type.h> 18 18 #include <keys/system_keyring.h> 19 - #include "module-internal.h" 19 + #include <crypto/pkcs7.h> 20 20 21 21 struct key *system_trusted_keyring; 22 22 EXPORT_SYMBOL_GPL(system_trusted_keyring); ··· 104 104 return 0; 105 105 } 106 106 late_initcall(load_system_certificate_list); 107 + 108 + #ifdef CONFIG_SYSTEM_DATA_VERIFICATION 109 + 110 + /** 111 + * Verify a PKCS#7-based signature on system data. 112 + * @data: The data to be verified. 113 + * @len: Size of @data. 114 + * @raw_pkcs7: The PKCS#7 message that is the signature. 115 + * @pkcs7_len: The size of @raw_pkcs7. 116 + * @usage: The use to which the key is being put. 117 + */ 118 + int system_verify_data(const void *data, unsigned long len, 119 + const void *raw_pkcs7, size_t pkcs7_len, 120 + enum key_being_used_for usage) 121 + { 122 + struct pkcs7_message *pkcs7; 123 + bool trusted; 124 + int ret; 125 + 126 + pkcs7 = pkcs7_parse_message(raw_pkcs7, pkcs7_len); 127 + if (IS_ERR(pkcs7)) 128 + return PTR_ERR(pkcs7); 129 + 130 + /* The data should be detached - so we need to supply it. */ 131 + if (pkcs7_supply_detached_data(pkcs7, data, len) < 0) { 132 + pr_err("PKCS#7 signature with non-detached data\n"); 133 + ret = -EBADMSG; 134 + goto error; 135 + } 136 + 137 + ret = pkcs7_verify(pkcs7, usage); 138 + if (ret < 0) 139 + goto error; 140 + 141 + ret = pkcs7_validate_trust(pkcs7, system_trusted_keyring, &trusted); 142 + if (ret < 0) 143 + goto error; 144 + 145 + if (!trusted) { 146 + pr_err("PKCS#7 signature not signed with a trusted key\n"); 147 + ret = -ENOKEY; 148 + } 149 + 150 + error: 151 + pkcs7_free_message(pkcs7); 152 + pr_devel("<==%s() = %d\n", __func__, ret); 153 + return ret; 154 + } 155 + EXPORT_SYMBOL_GPL(system_verify_data); 156 + 157 + #endif /* CONFIG_SYSTEM_DATA_VERIFICATION */
+23 -4
lib/asn1_decoder.c
··· 24 24 [ASN1_OP_MATCH_JUMP] = 1 + 1 + 1, 25 25 [ASN1_OP_MATCH_JUMP_OR_SKIP] = 1 + 1 + 1, 26 26 [ASN1_OP_MATCH_ANY] = 1, 27 + [ASN1_OP_MATCH_ANY_OR_SKIP] = 1, 27 28 [ASN1_OP_MATCH_ANY_ACT] = 1 + 1, 29 + [ASN1_OP_MATCH_ANY_ACT_OR_SKIP] = 1 + 1, 28 30 [ASN1_OP_COND_MATCH_OR_SKIP] = 1 + 1, 29 31 [ASN1_OP_COND_MATCH_ACT_OR_SKIP] = 1 + 1 + 1, 30 32 [ASN1_OP_COND_MATCH_JUMP_OR_SKIP] = 1 + 1 + 1, 31 33 [ASN1_OP_COND_MATCH_ANY] = 1, 34 + [ASN1_OP_COND_MATCH_ANY_OR_SKIP] = 1, 32 35 [ASN1_OP_COND_MATCH_ANY_ACT] = 1 + 1, 36 + [ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP] = 1 + 1, 33 37 [ASN1_OP_COND_FAIL] = 1, 34 38 [ASN1_OP_COMPLETE] = 1, 35 39 [ASN1_OP_ACT] = 1 + 1, 40 + [ASN1_OP_MAYBE_ACT] = 1 + 1, 36 41 [ASN1_OP_RETURN] = 1, 37 42 [ASN1_OP_END_SEQ] = 1, 38 43 [ASN1_OP_END_SEQ_OF] = 1 + 1, ··· 182 177 unsigned char flags = 0; 183 178 #define FLAG_INDEFINITE_LENGTH 0x01 184 179 #define FLAG_MATCHED 0x02 180 + #define FLAG_LAST_MATCHED 0x04 /* Last tag matched */ 185 181 #define FLAG_CONS 0x20 /* Corresponds to CONS bit in the opcode tag 186 182 * - ie. whether or not we are going to parse 187 183 * a compound type. ··· 214 208 unsigned char tmp; 215 209 216 210 /* Skip conditional matches if possible */ 217 - if ((op & ASN1_OP_MATCH__COND && 218 - flags & FLAG_MATCHED) || 219 - dp == datalen) { 211 + if ((op & ASN1_OP_MATCH__COND && flags & FLAG_MATCHED) || 212 + (op & ASN1_OP_MATCH__SKIP && dp == datalen)) { 213 + flags &= ~FLAG_LAST_MATCHED; 220 214 pc += asn1_op_lengths[op]; 221 215 goto next_op; 222 216 } ··· 308 302 /* Decide how to handle the operation */ 309 303 switch (op) { 310 304 case ASN1_OP_MATCH_ANY_ACT: 305 + case ASN1_OP_MATCH_ANY_ACT_OR_SKIP: 311 306 case ASN1_OP_COND_MATCH_ANY_ACT: 307 + case ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP: 312 308 ret = actions[machine[pc + 1]](context, hdr, tag, data + dp, len); 313 309 if (ret < 0) 314 310 return ret; ··· 327 319 case ASN1_OP_MATCH: 328 320 case ASN1_OP_MATCH_OR_SKIP: 329 321 case ASN1_OP_MATCH_ANY: 322 + case ASN1_OP_MATCH_ANY_OR_SKIP: 330 323 case ASN1_OP_COND_MATCH_OR_SKIP: 331 324 case ASN1_OP_COND_MATCH_ANY: 325 + case ASN1_OP_COND_MATCH_ANY_OR_SKIP: 332 326 skip_data: 333 327 if (!(flags & FLAG_CONS)) { 334 328 if (flags & FLAG_INDEFINITE_LENGTH) { ··· 432 422 pc += asn1_op_lengths[op]; 433 423 goto next_op; 434 424 425 + case ASN1_OP_MAYBE_ACT: 426 + if (!(flags & FLAG_LAST_MATCHED)) { 427 + pc += asn1_op_lengths[op]; 428 + goto next_op; 429 + } 435 430 case ASN1_OP_ACT: 436 431 ret = actions[machine[pc + 1]](context, hdr, tag, data + tdp, len); 432 + if (ret < 0) 433 + return ret; 437 434 pc += asn1_op_lengths[op]; 438 435 goto next_op; 439 436 ··· 448 431 if (unlikely(jsp <= 0)) 449 432 goto jump_stack_underflow; 450 433 pc = jump_stack[--jsp]; 434 + flags |= FLAG_MATCHED | FLAG_LAST_MATCHED; 451 435 goto next_op; 452 436 453 437 default: ··· 456 438 } 457 439 458 440 /* Shouldn't reach here */ 459 - pr_err("ASN.1 decoder error: Found reserved opcode (%u)\n", op); 441 + pr_err("ASN.1 decoder error: Found reserved opcode (%u) pc=%zu\n", 442 + op, pc); 460 443 return -EBADMSG; 461 444 462 445 data_overrun_error:
+2
scripts/.gitignore
··· 10 10 docproc 11 11 sortextable 12 12 asn1_compiler 13 + extract-cert 14 + sign-file
+51
scripts/Kbuild.include
··· 303 303 304 304 echo-why = $(call escsq, $(strip $(why))) 305 305 endif 306 + 307 + ############################################################################### 308 + # 309 + # When a Kconfig string contains a filename, it is suitable for 310 + # passing to shell commands. It is surrounded by double-quotes, and 311 + # any double-quotes or backslashes within it are escaped by 312 + # backslashes. 313 + # 314 + # This is no use for dependencies or $(wildcard). We need to strip the 315 + # surrounding quotes and the escaping from quotes and backslashes, and 316 + # we *do* need to escape any spaces in the string. So, for example: 317 + # 318 + # Usage: $(eval $(call config_filename,FOO)) 319 + # 320 + # Defines FOO_FILENAME based on the contents of the CONFIG_FOO option, 321 + # transformed as described above to be suitable for use within the 322 + # makefile. 323 + # 324 + # Also, if the filename is a relative filename and exists in the source 325 + # tree but not the build tree, define FOO_SRCPREFIX as $(srctree)/ to 326 + # be prefixed to *both* command invocation and dependencies. 327 + # 328 + # Note: We also print the filenames in the quiet_cmd_foo text, and 329 + # perhaps ought to have a version specially escaped for that purpose. 330 + # But it's only cosmetic, and $(patsubst "%",%,$(CONFIG_FOO)) is good 331 + # enough. It'll strip the quotes in the common case where there's no 332 + # space and it's a simple filename, and it'll retain the quotes when 333 + # there's a space. There are some esoteric cases in which it'll print 334 + # the wrong thing, but we don't really care. The actual dependencies 335 + # and commands *do* get it right, with various combinations of single 336 + # and double quotes, backslashes and spaces in the filenames. 337 + # 338 + ############################################################################### 339 + # 340 + space_escape := %%%SPACE%%% 341 + # 342 + define config_filename 343 + ifneq ($$(CONFIG_$(1)),"") 344 + $(1)_FILENAME := $$(subst \\,\,$$(subst \$$(quote),$$(quote),$$(subst $$(space_escape),\$$(space),$$(patsubst "%",%,$$(subst $$(space),$$(space_escape),$$(CONFIG_$(1))))))) 345 + ifneq ($$(patsubst /%,%,$$(firstword $$($(1)_FILENAME))),$$(firstword $$($(1)_FILENAME))) 346 + else 347 + ifeq ($$(wildcard $$($(1)_FILENAME)),) 348 + ifneq ($$(wildcard $$(srctree)/$$($(1)_FILENAME)),) 349 + $(1)_SRCPREFIX := $(srctree)/ 350 + endif 351 + endif 352 + endif 353 + endif 354 + endef 355 + # 356 + ###############################################################################
+4
scripts/Makefile
··· 16 16 hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount 17 17 hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable 18 18 hostprogs-$(CONFIG_ASN1) += asn1_compiler 19 + hostprogs-$(CONFIG_MODULE_SIG) += sign-file 20 + hostprogs-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += extract-cert 19 21 20 22 HOSTCFLAGS_sortextable.o = -I$(srctree)/tools/include 21 23 HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include 24 + HOSTLOADLIBES_sign-file = -lcrypto 25 + HOSTLOADLIBES_extract-cert = -lcrypto 22 26 23 27 always := $(hostprogs-y) $(hostprogs-m) 24 28
+1 -1
scripts/Makefile.modinst
··· 22 22 mkdir -p $(2) ; \ 23 23 cp $@ $(2) ; \ 24 24 $(mod_strip_cmd) $(2)/$(notdir $@) ; \ 25 - $(mod_sign_cmd) $(2)/$(notdir $@) $(patsubst %,|| true,$(KBUILD_EXTMOD)) ; \ 25 + $(mod_sign_cmd) $(2)/$(notdir $@) $(patsubst %,|| true,$(KBUILD_EXTMOD)) && \ 26 26 $(mod_compress_cmd) $(2)/$(notdir $@) 27 27 28 28 # Modules built outside the kernel source tree go into extra by default
+154 -94
scripts/asn1_compiler.c
··· 13 13 #include <stdio.h> 14 14 #include <stdlib.h> 15 15 #include <stdint.h> 16 + #include <stdbool.h> 16 17 #include <string.h> 17 18 #include <ctype.h> 18 19 #include <unistd.h> ··· 294 293 295 294 struct action { 296 295 struct action *next; 296 + char *name; 297 297 unsigned char index; 298 - char name[]; 299 298 }; 300 299 301 300 static struct action *action_list; ··· 306 305 enum token_type token_type : 8; 307 306 unsigned char size; 308 307 struct action *action; 309 - const char *value; 308 + char *content; 310 309 struct type *type; 311 310 }; 312 311 313 312 static struct token *token_list; 314 313 static unsigned nr_tokens; 315 - static _Bool verbose; 314 + static bool verbose_opt; 315 + static bool debug_opt; 316 316 317 - #define debug(fmt, ...) do { if (verbose) printf(fmt, ## __VA_ARGS__); } while (0) 317 + #define verbose(fmt, ...) do { if (verbose_opt) printf(fmt, ## __VA_ARGS__); } while (0) 318 + #define debug(fmt, ...) do { if (debug_opt) printf(fmt, ## __VA_ARGS__); } while (0) 318 319 319 320 static int directive_compare(const void *_key, const void *_pdir) 320 321 { ··· 328 325 dlen = strlen(dir); 329 326 clen = (dlen < token->size) ? dlen : token->size; 330 327 331 - //debug("cmp(%*.*s,%s) = ", 332 - // (int)token->size, (int)token->size, token->value, 333 - // dir); 328 + //debug("cmp(%s,%s) = ", token->content, dir); 334 329 335 - val = memcmp(token->value, dir, clen); 330 + val = memcmp(token->content, dir, clen); 336 331 if (val != 0) { 337 332 //debug("%d [cmp]\n", val); 338 333 return val; ··· 350 349 static void tokenise(char *buffer, char *end) 351 350 { 352 351 struct token *tokens; 353 - char *line, *nl, *p, *q; 352 + char *line, *nl, *start, *p, *q; 354 353 unsigned tix, lineno; 355 354 356 355 /* Assume we're going to have half as many tokens as we have ··· 409 408 break; 410 409 411 410 tokens[tix].line = lineno; 412 - tokens[tix].value = p; 411 + start = p; 413 412 414 413 /* Handle string tokens */ 415 414 if (isalpha(*p)) { 416 - const char **dir; 415 + const char **dir, *start = p; 417 416 418 417 /* Can be a directive, type name or element 419 418 * name. Find the end of the name. ··· 424 423 tokens[tix].size = q - p; 425 424 p = q; 426 425 426 + tokens[tix].content = malloc(tokens[tix].size + 1); 427 + if (!tokens[tix].content) { 428 + perror(NULL); 429 + exit(1); 430 + } 431 + memcpy(tokens[tix].content, start, tokens[tix].size); 432 + tokens[tix].content[tokens[tix].size] = 0; 433 + 427 434 /* If it begins with a lowercase letter then 428 435 * it's an element name 429 436 */ 430 - if (islower(tokens[tix].value[0])) { 437 + if (islower(tokens[tix].content[0])) { 431 438 tokens[tix++].token_type = TOKEN_ELEMENT_NAME; 432 439 continue; 433 440 } ··· 464 455 q++; 465 456 tokens[tix].size = q - p; 466 457 p = q; 458 + tokens[tix].content = malloc(tokens[tix].size + 1); 459 + if (!tokens[tix].content) { 460 + perror(NULL); 461 + exit(1); 462 + } 463 + memcpy(tokens[tix].content, start, tokens[tix].size); 464 + tokens[tix].content[tokens[tix].size] = 0; 467 465 tokens[tix++].token_type = TOKEN_NUMBER; 468 466 continue; 469 467 } ··· 479 463 if (memcmp(p, "::=", 3) == 0) { 480 464 p += 3; 481 465 tokens[tix].size = 3; 466 + tokens[tix].content = "::="; 482 467 tokens[tix++].token_type = TOKEN_ASSIGNMENT; 483 468 continue; 484 469 } ··· 489 472 if (memcmp(p, "({", 2) == 0) { 490 473 p += 2; 491 474 tokens[tix].size = 2; 475 + tokens[tix].content = "({"; 492 476 tokens[tix++].token_type = TOKEN_OPEN_ACTION; 493 477 continue; 494 478 } 495 479 if (memcmp(p, "})", 2) == 0) { 496 480 p += 2; 497 481 tokens[tix].size = 2; 482 + tokens[tix].content = "})"; 498 483 tokens[tix++].token_type = TOKEN_CLOSE_ACTION; 499 484 continue; 500 485 } ··· 507 488 switch (*p) { 508 489 case '{': 509 490 p += 1; 491 + tokens[tix].content = "{"; 510 492 tokens[tix++].token_type = TOKEN_OPEN_CURLY; 511 493 continue; 512 494 case '}': 513 495 p += 1; 496 + tokens[tix].content = "}"; 514 497 tokens[tix++].token_type = TOKEN_CLOSE_CURLY; 515 498 continue; 516 499 case '[': 517 500 p += 1; 501 + tokens[tix].content = "["; 518 502 tokens[tix++].token_type = TOKEN_OPEN_SQUARE; 519 503 continue; 520 504 case ']': 521 505 p += 1; 506 + tokens[tix].content = "]"; 522 507 tokens[tix++].token_type = TOKEN_CLOSE_SQUARE; 523 508 continue; 524 509 case ',': 525 510 p += 1; 511 + tokens[tix].content = ","; 526 512 tokens[tix++].token_type = TOKEN_COMMA; 527 513 continue; 528 514 default: ··· 542 518 } 543 519 544 520 nr_tokens = tix; 545 - debug("Extracted %u tokens\n", nr_tokens); 521 + verbose("Extracted %u tokens\n", nr_tokens); 546 522 547 523 #if 0 548 524 { 549 525 int n; 550 526 for (n = 0; n < nr_tokens; n++) 551 - debug("Token %3u: '%*.*s'\n", 552 - n, 553 - (int)token_list[n].size, (int)token_list[n].size, 554 - token_list[n].value); 527 + debug("Token %3u: '%s'\n", n, token_list[n].content); 555 528 } 556 529 #endif 557 530 } 558 531 559 532 static void build_type_list(void); 560 533 static void parse(void); 534 + static void dump_elements(void); 561 535 static void render(FILE *out, FILE *hdr); 562 536 563 537 /* ··· 570 548 char *kbuild_verbose; 571 549 int fd; 572 550 551 + kbuild_verbose = getenv("KBUILD_VERBOSE"); 552 + if (kbuild_verbose) 553 + verbose_opt = atoi(kbuild_verbose); 554 + 555 + while (argc > 4) { 556 + if (strcmp(argv[1], "-v") == 0) 557 + verbose_opt = true; 558 + else if (strcmp(argv[1], "-d") == 0) 559 + debug_opt = true; 560 + else 561 + break; 562 + memmove(&argv[1], &argv[2], (argc - 2) * sizeof(char *)); 563 + argc--; 564 + } 565 + 573 566 if (argc != 4) { 574 - fprintf(stderr, "Format: %s <grammar-file> <c-file> <hdr-file>\n", 567 + fprintf(stderr, "Format: %s [-v] [-d] <grammar-file> <c-file> <hdr-file>\n", 575 568 argv[0]); 576 569 exit(2); 577 570 } 578 - 579 - kbuild_verbose = getenv("KBUILD_VERBOSE"); 580 - if (kbuild_verbose) 581 - verbose = atoi(kbuild_verbose); 582 571 583 572 filename = argv[1]; 584 573 outputname = argv[2]; ··· 641 608 tokenise(buffer, buffer + readlen); 642 609 build_type_list(); 643 610 parse(); 611 + dump_elements(); 644 612 645 613 out = fopen(outputname, "w"); 646 614 if (!out) { ··· 700 666 unsigned flags; 701 667 #define ELEMENT_IMPLICIT 0x0001 702 668 #define ELEMENT_EXPLICIT 0x0002 703 - #define ELEMENT_MARKED 0x0004 669 + #define ELEMENT_TAG_SPECIFIED 0x0004 704 670 #define ELEMENT_RENDERED 0x0008 705 671 #define ELEMENT_SKIPPABLE 0x0010 706 672 #define ELEMENT_CONDITIONAL 0x0020 ··· 727 693 if ((*a)->name->size != (*b)->name->size) 728 694 return (*a)->name->size - (*b)->name->size; 729 695 else 730 - return memcmp((*a)->name->value, (*b)->name->value, 696 + return memcmp((*a)->name->content, (*b)->name->content, 731 697 (*a)->name->size); 732 698 } 733 699 ··· 740 706 if (token->size != type->name->size) 741 707 return token->size - type->name->size; 742 708 else 743 - return memcmp(token->value, type->name->value, 709 + return memcmp(token->content, type->name->content, 744 710 token->size); 745 711 } 746 712 ··· 790 756 791 757 qsort(type_index, nr, sizeof(type_index[0]), type_index_compare); 792 758 793 - debug("Extracted %u types\n", nr_types); 759 + verbose("Extracted %u types\n", nr_types); 794 760 #if 0 795 761 for (n = 0; n < nr_types; n++) { 796 762 struct type *type = type_index[n]; 797 - debug("- %*.*s\n", 798 - (int)type->name->size, 799 - (int)type->name->size, 800 - type->name->value); 763 + debug("- %*.*s\n", type->name->content); 801 764 } 802 765 #endif 803 766 } ··· 824 793 type->element->type_def = type; 825 794 826 795 if (cursor != type[1].name) { 827 - fprintf(stderr, "%s:%d: Parse error at token '%*.*s'\n", 828 - filename, cursor->line, 829 - (int)cursor->size, (int)cursor->size, cursor->value); 796 + fprintf(stderr, "%s:%d: Parse error at token '%s'\n", 797 + filename, cursor->line, cursor->content); 830 798 exit(1); 831 799 } 832 800 833 801 } while (type++, !(type->flags & TYPE_STOP_MARKER)); 834 802 835 - debug("Extracted %u actions\n", nr_actions); 803 + verbose("Extracted %u actions\n", nr_actions); 836 804 } 837 805 838 806 static struct element *element_list; ··· 892 862 cursor++; 893 863 break; 894 864 default: 895 - fprintf(stderr, "%s:%d: Unrecognised tag class token '%*.*s'\n", 896 - filename, cursor->line, 897 - (int)cursor->size, (int)cursor->size, cursor->value); 865 + fprintf(stderr, "%s:%d: Unrecognised tag class token '%s'\n", 866 + filename, cursor->line, cursor->content); 898 867 exit(1); 899 868 } 900 869 901 870 if (cursor >= end) 902 871 goto overrun_error; 903 872 if (cursor->token_type != TOKEN_NUMBER) { 904 - fprintf(stderr, "%s:%d: Missing tag number '%*.*s'\n", 905 - filename, cursor->line, 906 - (int)cursor->size, (int)cursor->size, cursor->value); 873 + fprintf(stderr, "%s:%d: Missing tag number '%s'\n", 874 + filename, cursor->line, cursor->content); 907 875 exit(1); 908 876 } 909 877 910 878 element->tag &= ~0x1f; 911 - element->tag |= strtoul(cursor->value, &p, 10); 912 - if (p - cursor->value != cursor->size) 879 + element->tag |= strtoul(cursor->content, &p, 10); 880 + element->flags |= ELEMENT_TAG_SPECIFIED; 881 + if (p - cursor->content != cursor->size) 913 882 abort(); 914 883 cursor++; 915 884 916 885 if (cursor >= end) 917 886 goto overrun_error; 918 887 if (cursor->token_type != TOKEN_CLOSE_SQUARE) { 919 - fprintf(stderr, "%s:%d: Missing closing square bracket '%*.*s'\n", 920 - filename, cursor->line, 921 - (int)cursor->size, (int)cursor->size, cursor->value); 888 + fprintf(stderr, "%s:%d: Missing closing square bracket '%s'\n", 889 + filename, cursor->line, cursor->content); 922 890 exit(1); 923 891 } 924 892 cursor++; ··· 1016 988 ref = bsearch(cursor, type_index, nr_types, sizeof(type_index[0]), 1017 989 type_finder); 1018 990 if (!ref) { 1019 - fprintf(stderr, "%s:%d: Type '%*.*s' undefined\n", 1020 - filename, cursor->line, 1021 - (int)cursor->size, (int)cursor->size, cursor->value); 991 + fprintf(stderr, "%s:%d: Type '%s' undefined\n", 992 + filename, cursor->line, cursor->content); 1022 993 exit(1); 1023 994 } 1024 995 cursor->type = *ref; ··· 1066 1039 break; 1067 1040 1068 1041 default: 1069 - fprintf(stderr, "%s:%d: Token '%*.*s' does not introduce a type\n", 1070 - filename, cursor->line, 1071 - (int)cursor->size, (int)cursor->size, cursor->value); 1042 + fprintf(stderr, "%s:%d: Token '%s' does not introduce a type\n", 1043 + filename, cursor->line, cursor->content); 1072 1044 exit(1); 1073 1045 } 1074 1046 ··· 1084 1058 if (cursor >= end) 1085 1059 goto overrun_error; 1086 1060 if (cursor->token_type != TOKEN_ELEMENT_NAME) { 1087 - fprintf(stderr, "%s:%d: Token '%*.*s' is not an action function name\n", 1088 - filename, cursor->line, 1089 - (int)cursor->size, (int)cursor->size, cursor->value); 1061 + fprintf(stderr, "%s:%d: Token '%s' is not an action function name\n", 1062 + filename, cursor->line, cursor->content); 1090 1063 exit(1); 1091 1064 } 1092 1065 1093 - action = malloc(sizeof(struct action) + cursor->size + 1); 1066 + action = malloc(sizeof(struct action)); 1094 1067 if (!action) { 1095 1068 perror(NULL); 1096 1069 exit(1); 1097 1070 } 1098 1071 action->index = 0; 1099 - memcpy(action->name, cursor->value, cursor->size); 1100 - action->name[cursor->size] = 0; 1072 + action->name = cursor->content; 1101 1073 1102 1074 for (ppaction = &action_list; 1103 1075 *ppaction; ··· 1125 1101 if (cursor >= end) 1126 1102 goto overrun_error; 1127 1103 if (cursor->token_type != TOKEN_CLOSE_ACTION) { 1128 - fprintf(stderr, "%s:%d: Missing close action, got '%*.*s'\n", 1129 - filename, cursor->line, 1130 - (int)cursor->size, (int)cursor->size, cursor->value); 1104 + fprintf(stderr, "%s:%d: Missing close action, got '%s'\n", 1105 + filename, cursor->line, cursor->content); 1131 1106 exit(1); 1132 1107 } 1133 1108 cursor++; ··· 1136 1113 return top; 1137 1114 1138 1115 parse_error: 1139 - fprintf(stderr, "%s:%d: Unexpected token '%*.*s'\n", 1140 - filename, cursor->line, 1141 - (int)cursor->size, (int)cursor->size, cursor->value); 1116 + fprintf(stderr, "%s:%d: Unexpected token '%s'\n", 1117 + filename, cursor->line, cursor->content); 1142 1118 exit(1); 1143 1119 1144 1120 overrun_error: ··· 1155 1133 struct token *cursor = *_cursor, *name; 1156 1134 1157 1135 if (cursor->token_type != TOKEN_OPEN_CURLY) { 1158 - fprintf(stderr, "%s:%d: Expected compound to start with brace not '%*.*s'\n", 1159 - filename, cursor->line, 1160 - (int)cursor->size, (int)cursor->size, cursor->value); 1136 + fprintf(stderr, "%s:%d: Expected compound to start with brace not '%s'\n", 1137 + filename, cursor->line, cursor->content); 1161 1138 exit(1); 1162 1139 } 1163 1140 cursor++; ··· 1197 1176 children->flags &= ~ELEMENT_CONDITIONAL; 1198 1177 1199 1178 if (cursor->token_type != TOKEN_CLOSE_CURLY) { 1200 - fprintf(stderr, "%s:%d: Expected compound closure, got '%*.*s'\n", 1201 - filename, cursor->line, 1202 - (int)cursor->size, (int)cursor->size, cursor->value); 1179 + fprintf(stderr, "%s:%d: Expected compound closure, got '%s'\n", 1180 + filename, cursor->line, cursor->content); 1203 1181 exit(1); 1204 1182 } 1205 1183 cursor++; ··· 1209 1189 overrun_error: 1210 1190 fprintf(stderr, "%s: Unexpectedly hit EOF\n", filename); 1211 1191 exit(1); 1192 + } 1193 + 1194 + static void dump_element(const struct element *e, int level) 1195 + { 1196 + const struct element *c; 1197 + const struct type *t = e->type_def; 1198 + const char *name = e->name ? e->name->content : "."; 1199 + const char *tname = t && t->name ? t->name->content : "."; 1200 + char tag[32]; 1201 + 1202 + if (e->class == 0 && e->method == 0 && e->tag == 0) 1203 + strcpy(tag, "<...>"); 1204 + else if (e->class == ASN1_UNIV) 1205 + sprintf(tag, "%s %s %s", 1206 + asn1_classes[e->class], 1207 + asn1_methods[e->method], 1208 + asn1_universal_tags[e->tag]); 1209 + else 1210 + sprintf(tag, "%s %s %u", 1211 + asn1_classes[e->class], 1212 + asn1_methods[e->method], 1213 + e->tag); 1214 + 1215 + printf("%c%c%c%c%c %c %*s[*] \e[33m%s\e[m %s %s \e[35m%s\e[m\n", 1216 + e->flags & ELEMENT_IMPLICIT ? 'I' : '-', 1217 + e->flags & ELEMENT_EXPLICIT ? 'E' : '-', 1218 + e->flags & ELEMENT_TAG_SPECIFIED ? 'T' : '-', 1219 + e->flags & ELEMENT_SKIPPABLE ? 'S' : '-', 1220 + e->flags & ELEMENT_CONDITIONAL ? 'C' : '-', 1221 + "-tTqQcaro"[e->compound], 1222 + level, "", 1223 + tag, 1224 + tname, 1225 + name, 1226 + e->action ? e->action->name : ""); 1227 + if (e->compound == TYPE_REF) 1228 + dump_element(e->type->type->element, level + 3); 1229 + else 1230 + for (c = e->children; c; c = c->next) 1231 + dump_element(c, level + 3); 1232 + } 1233 + 1234 + static void dump_elements(void) 1235 + { 1236 + if (debug_opt) 1237 + dump_element(type_list[0].element, 0); 1212 1238 } 1213 1239 1214 1240 static void render_element(FILE *out, struct element *e, struct element *tag); ··· 1358 1292 } 1359 1293 1360 1294 /* We do two passes - the first one calculates all the offsets */ 1361 - debug("Pass 1\n"); 1295 + verbose("Pass 1\n"); 1362 1296 nr_entries = 0; 1363 1297 root = &type_list[0]; 1364 1298 render_element(NULL, root->element, NULL); ··· 1369 1303 e->flags &= ~ELEMENT_RENDERED; 1370 1304 1371 1305 /* And then we actually render */ 1372 - debug("Pass 2\n"); 1306 + verbose("Pass 2\n"); 1373 1307 fprintf(out, "\n"); 1374 1308 fprintf(out, "static const unsigned char %s_machine[] = {\n", 1375 1309 grammar_name); ··· 1442 1376 */ 1443 1377 static void render_element(FILE *out, struct element *e, struct element *tag) 1444 1378 { 1445 - struct element *ec; 1379 + struct element *ec, *x; 1446 1380 const char *cond, *act; 1447 1381 int entry, skippable = 0, outofline = 0; 1448 1382 ··· 1455 1389 outofline = 1; 1456 1390 1457 1391 if (e->type_def && out) { 1458 - render_more(out, "\t// %*.*s\n", 1459 - (int)e->type_def->name->size, (int)e->type_def->name->size, 1460 - e->type_def->name->value); 1392 + render_more(out, "\t// %s\n", e->type_def->name->content); 1461 1393 } 1462 1394 1463 1395 /* Render the operation */ ··· 1464 1400 act = e->action ? "_ACT" : ""; 1465 1401 switch (e->compound) { 1466 1402 case ANY: 1467 - render_opcode(out, "ASN1_OP_%sMATCH_ANY%s,", cond, act); 1403 + render_opcode(out, "ASN1_OP_%sMATCH_ANY%s%s,", 1404 + cond, act, skippable ? "_OR_SKIP" : ""); 1468 1405 if (e->name) 1469 - render_more(out, "\t\t// %*.*s", 1470 - (int)e->name->size, (int)e->name->size, 1471 - e->name->value); 1406 + render_more(out, "\t\t// %s", e->name->content); 1472 1407 render_more(out, "\n"); 1473 1408 goto dont_render_tag; 1474 1409 ··· 1498 1435 break; 1499 1436 } 1500 1437 1501 - if (e->name) 1502 - render_more(out, "\t\t// %*.*s", 1503 - (int)e->name->size, (int)e->name->size, 1504 - e->name->value); 1438 + x = tag ?: e; 1439 + if (x->name) 1440 + render_more(out, "\t\t// %s", x->name->content); 1505 1441 render_more(out, "\n"); 1506 1442 1507 1443 /* Render the tag */ 1508 - if (!tag) 1444 + if (!tag || !(tag->flags & ELEMENT_TAG_SPECIFIED)) 1509 1445 tag = e; 1446 + 1510 1447 if (tag->class == ASN1_UNIV && 1511 1448 tag->tag != 14 && 1512 1449 tag->tag != 15 && ··· 1528 1465 case TYPE_REF: 1529 1466 render_element(out, e->type->type->element, tag); 1530 1467 if (e->action) 1531 - render_opcode(out, "ASN1_OP_ACT,\n"); 1468 + render_opcode(out, "ASN1_OP_%sACT,\n", 1469 + skippable ? "MAYBE_" : ""); 1532 1470 break; 1533 1471 1534 1472 case SEQUENCE: ··· 1538 1474 * skipability */ 1539 1475 render_opcode(out, "_jump_target(%u),", e->entry_index); 1540 1476 if (e->type_def && e->type_def->name) 1541 - render_more(out, "\t\t// --> %*.*s", 1542 - (int)e->type_def->name->size, 1543 - (int)e->type_def->name->size, 1544 - e->type_def->name->value); 1477 + render_more(out, "\t\t// --> %s", 1478 + e->type_def->name->content); 1545 1479 render_more(out, "\n"); 1546 1480 if (!(e->flags & ELEMENT_RENDERED)) { 1547 1481 e->flags |= ELEMENT_RENDERED; ··· 1564 1502 * skipability */ 1565 1503 render_opcode(out, "_jump_target(%u),", e->entry_index); 1566 1504 if (e->type_def && e->type_def->name) 1567 - render_more(out, "\t\t// --> %*.*s", 1568 - (int)e->type_def->name->size, 1569 - (int)e->type_def->name->size, 1570 - e->type_def->name->value); 1505 + render_more(out, "\t\t// --> %s", 1506 + e->type_def->name->content); 1571 1507 render_more(out, "\n"); 1572 1508 if (!(e->flags & ELEMENT_RENDERED)) { 1573 1509 e->flags |= ELEMENT_RENDERED; ··· 1599 1539 1600 1540 case CHOICE: 1601 1541 for (ec = e->children; ec; ec = ec->next) 1602 - render_element(out, ec, NULL); 1542 + render_element(out, ec, ec); 1603 1543 if (!skippable) 1604 1544 render_opcode(out, "ASN1_OP_COND_FAIL,\n"); 1605 1545 if (e->action)
+166
scripts/extract-cert.c
··· 1 + /* Extract X.509 certificate in DER form from PKCS#11 or PEM. 2 + * 3 + * Copyright © 2014 Red Hat, Inc. All Rights Reserved. 4 + * Copyright © 2015 Intel Corporation. 5 + * 6 + * Authors: David Howells <dhowells@redhat.com> 7 + * David Woodhouse <dwmw2@infradead.org> 8 + * 9 + * This program is free software; you can redistribute it and/or 10 + * modify it under the terms of the GNU General Public Licence 11 + * as published by the Free Software Foundation; either version 12 + * 2 of the Licence, or (at your option) any later version. 13 + */ 14 + #define _GNU_SOURCE 15 + #include <stdio.h> 16 + #include <stdlib.h> 17 + #include <stdint.h> 18 + #include <stdbool.h> 19 + #include <string.h> 20 + #include <getopt.h> 21 + #include <err.h> 22 + #include <arpa/inet.h> 23 + #include <openssl/bio.h> 24 + #include <openssl/evp.h> 25 + #include <openssl/pem.h> 26 + #include <openssl/pkcs7.h> 27 + #include <openssl/err.h> 28 + #include <openssl/engine.h> 29 + 30 + #define PKEY_ID_PKCS7 2 31 + 32 + static __attribute__((noreturn)) 33 + void format(void) 34 + { 35 + fprintf(stderr, 36 + "Usage: scripts/extract-cert <source> <dest>\n"); 37 + exit(2); 38 + } 39 + 40 + static void display_openssl_errors(int l) 41 + { 42 + const char *file; 43 + char buf[120]; 44 + int e, line; 45 + 46 + if (ERR_peek_error() == 0) 47 + return; 48 + fprintf(stderr, "At main.c:%d:\n", l); 49 + 50 + while ((e = ERR_get_error_line(&file, &line))) { 51 + ERR_error_string(e, buf); 52 + fprintf(stderr, "- SSL %s: %s:%d\n", buf, file, line); 53 + } 54 + } 55 + 56 + static void drain_openssl_errors(void) 57 + { 58 + const char *file; 59 + int line; 60 + 61 + if (ERR_peek_error() == 0) 62 + return; 63 + while (ERR_get_error_line(&file, &line)) {} 64 + } 65 + 66 + #define ERR(cond, fmt, ...) \ 67 + do { \ 68 + bool __cond = (cond); \ 69 + display_openssl_errors(__LINE__); \ 70 + if (__cond) { \ 71 + err(1, fmt, ## __VA_ARGS__); \ 72 + } \ 73 + } while(0) 74 + 75 + static const char *key_pass; 76 + static BIO *wb; 77 + static char *cert_dst; 78 + int kbuild_verbose; 79 + 80 + static void write_cert(X509 *x509) 81 + { 82 + char buf[200]; 83 + 84 + if (!wb) { 85 + wb = BIO_new_file(cert_dst, "wb"); 86 + ERR(!wb, "%s", cert_dst); 87 + } 88 + X509_NAME_oneline(X509_get_subject_name(x509), buf, sizeof(buf)); 89 + ERR(!i2d_X509_bio(wb, x509), cert_dst); 90 + if (kbuild_verbose) 91 + fprintf(stderr, "Extracted cert: %s\n", buf); 92 + } 93 + 94 + int main(int argc, char **argv) 95 + { 96 + char *cert_src; 97 + 98 + OpenSSL_add_all_algorithms(); 99 + ERR_load_crypto_strings(); 100 + ERR_clear_error(); 101 + 102 + kbuild_verbose = atoi(getenv("KBUILD_VERBOSE")?:"0"); 103 + 104 + key_pass = getenv("KBUILD_SIGN_PIN"); 105 + 106 + if (argc != 3) 107 + format(); 108 + 109 + cert_src = argv[1]; 110 + cert_dst = argv[2]; 111 + 112 + if (!cert_src[0]) { 113 + /* Invoked with no input; create empty file */ 114 + FILE *f = fopen(cert_dst, "wb"); 115 + ERR(!f, "%s", cert_dst); 116 + fclose(f); 117 + exit(0); 118 + } else if (!strncmp(cert_src, "pkcs11:", 7)) { 119 + ENGINE *e; 120 + struct { 121 + const char *cert_id; 122 + X509 *cert; 123 + } parms; 124 + 125 + parms.cert_id = cert_src; 126 + parms.cert = NULL; 127 + 128 + ENGINE_load_builtin_engines(); 129 + drain_openssl_errors(); 130 + e = ENGINE_by_id("pkcs11"); 131 + ERR(!e, "Load PKCS#11 ENGINE"); 132 + if (ENGINE_init(e)) 133 + drain_openssl_errors(); 134 + else 135 + ERR(1, "ENGINE_init"); 136 + if (key_pass) 137 + ERR(!ENGINE_ctrl_cmd_string(e, "PIN", key_pass, 0), "Set PKCS#11 PIN"); 138 + ENGINE_ctrl_cmd(e, "LOAD_CERT_CTRL", 0, &parms, NULL, 1); 139 + ERR(!parms.cert, "Get X.509 from PKCS#11"); 140 + write_cert(parms.cert); 141 + } else { 142 + BIO *b; 143 + X509 *x509; 144 + 145 + b = BIO_new_file(cert_src, "rb"); 146 + ERR(!b, "%s", cert_src); 147 + 148 + while (1) { 149 + x509 = PEM_read_bio_X509(b, NULL, NULL, NULL); 150 + if (wb && !x509) { 151 + unsigned long err = ERR_peek_last_error(); 152 + if (ERR_GET_LIB(err) == ERR_LIB_PEM && 153 + ERR_GET_REASON(err) == PEM_R_NO_START_LINE) { 154 + ERR_clear_error(); 155 + break; 156 + } 157 + } 158 + ERR(!x509, "%s", cert_src); 159 + write_cert(x509); 160 + } 161 + } 162 + 163 + BIO_free(wb); 164 + 165 + return 0; 166 + }
+1
scripts/selinux/mdp/mdp.c
··· 98 98 99 99 /* types, roles, and allows */ 100 100 fprintf(fout, "type base_t;\n"); 101 + fprintf(fout, "role base_r;\n"); 101 102 fprintf(fout, "role base_r types { base_t };\n"); 102 103 for (i = 0; secclass_map[i].name; i++) 103 104 fprintf(fout, "allow base_t base_t:%s *;\n",
-421
scripts/sign-file
··· 1 - #!/usr/bin/perl -w 2 - # 3 - # Sign a module file using the given key. 4 - # 5 - 6 - my $USAGE = 7 - "Usage: scripts/sign-file [-v] <hash algo> <key> <x509> <module> [<dest>]\n" . 8 - " scripts/sign-file [-v] -s <raw sig> <hash algo> <x509> <module> [<dest>]\n"; 9 - 10 - use strict; 11 - use FileHandle; 12 - use IPC::Open2; 13 - use Getopt::Std; 14 - 15 - my %opts; 16 - getopts('vs:', \%opts) or die $USAGE; 17 - my $verbose = $opts{'v'}; 18 - my $signature_file = $opts{'s'}; 19 - 20 - die $USAGE if ($#ARGV > 4); 21 - die $USAGE if (!$signature_file && $#ARGV < 3 || $signature_file && $#ARGV < 2); 22 - 23 - my $dgst = shift @ARGV; 24 - my $private_key; 25 - if (!$signature_file) { 26 - $private_key = shift @ARGV; 27 - } 28 - my $x509 = shift @ARGV; 29 - my $module = shift @ARGV; 30 - my ($dest, $keep_orig); 31 - if (@ARGV) { 32 - $dest = $ARGV[0]; 33 - $keep_orig = 1; 34 - } else { 35 - $dest = $module . "~"; 36 - } 37 - 38 - die "Can't read private key\n" if (!$signature_file && !-r $private_key); 39 - die "Can't read signature file\n" if ($signature_file && !-r $signature_file); 40 - die "Can't read X.509 certificate\n" unless (-r $x509); 41 - die "Can't read module\n" unless (-r $module); 42 - 43 - # 44 - # Function to read the contents of a file into a variable. 45 - # 46 - sub read_file($) 47 - { 48 - my ($file) = @_; 49 - my $contents; 50 - my $len; 51 - 52 - open(FD, "<$file") || die $file; 53 - binmode FD; 54 - my @st = stat(FD); 55 - die $file if (!@st); 56 - $len = read(FD, $contents, $st[7]) || die $file; 57 - close(FD) || die $file; 58 - die "$file: Wanted length ", $st[7], ", got ", $len, "\n" 59 - if ($len != $st[7]); 60 - return $contents; 61 - } 62 - 63 - ############################################################################### 64 - # 65 - # First of all, we have to parse the X.509 certificate to find certain details 66 - # about it. 67 - # 68 - # We read the DER-encoded X509 certificate and parse it to extract the Subject 69 - # name and Subject Key Identifier. Theis provides the data we need to build 70 - # the certificate identifier. 71 - # 72 - # The signer's name part of the identifier is fabricated from the commonName, 73 - # the organizationName or the emailAddress components of the X.509 subject 74 - # name. 75 - # 76 - # The subject key ID is used to select which of that signer's certificates 77 - # we're intending to use to sign the module. 78 - # 79 - ############################################################################### 80 - my $x509_certificate = read_file($x509); 81 - 82 - my $UNIV = 0 << 6; 83 - my $APPL = 1 << 6; 84 - my $CONT = 2 << 6; 85 - my $PRIV = 3 << 6; 86 - 87 - my $CONS = 0x20; 88 - 89 - my $BOOLEAN = 0x01; 90 - my $INTEGER = 0x02; 91 - my $BIT_STRING = 0x03; 92 - my $OCTET_STRING = 0x04; 93 - my $NULL = 0x05; 94 - my $OBJ_ID = 0x06; 95 - my $UTF8String = 0x0c; 96 - my $SEQUENCE = 0x10; 97 - my $SET = 0x11; 98 - my $UTCTime = 0x17; 99 - my $GeneralizedTime = 0x18; 100 - 101 - my %OIDs = ( 102 - pack("CCC", 85, 4, 3) => "commonName", 103 - pack("CCC", 85, 4, 6) => "countryName", 104 - pack("CCC", 85, 4, 10) => "organizationName", 105 - pack("CCC", 85, 4, 11) => "organizationUnitName", 106 - pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 1) => "rsaEncryption", 107 - pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 5) => "sha1WithRSAEncryption", 108 - pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 9, 1) => "emailAddress", 109 - pack("CCC", 85, 29, 35) => "authorityKeyIdentifier", 110 - pack("CCC", 85, 29, 14) => "subjectKeyIdentifier", 111 - pack("CCC", 85, 29, 19) => "basicConstraints" 112 - ); 113 - 114 - ############################################################################### 115 - # 116 - # Extract an ASN.1 element from a string and return information about it. 117 - # 118 - ############################################################################### 119 - sub asn1_extract($$@) 120 - { 121 - my ($cursor, $expected_tag, $optional) = @_; 122 - 123 - return [ -1 ] 124 - if ($cursor->[1] == 0 && $optional); 125 - 126 - die $x509, ": ", $cursor->[0], ": ASN.1 data underrun (elem ", $cursor->[1], ")\n" 127 - if ($cursor->[1] < 2); 128 - 129 - my ($tag, $len) = unpack("CC", substr(${$cursor->[2]}, $cursor->[0], 2)); 130 - 131 - if ($expected_tag != -1 && $tag != $expected_tag) { 132 - return [ -1 ] 133 - if ($optional); 134 - die $x509, ": ", $cursor->[0], ": ASN.1 unexpected tag (", $tag, 135 - " not ", $expected_tag, ")\n"; 136 - } 137 - 138 - $cursor->[0] += 2; 139 - $cursor->[1] -= 2; 140 - 141 - die $x509, ": ", $cursor->[0], ": ASN.1 long tag\n" 142 - if (($tag & 0x1f) == 0x1f); 143 - die $x509, ": ", $cursor->[0], ": ASN.1 indefinite length\n" 144 - if ($len == 0x80); 145 - 146 - if ($len > 0x80) { 147 - my $l = $len - 0x80; 148 - die $x509, ": ", $cursor->[0], ": ASN.1 data underrun (len len $l)\n" 149 - if ($cursor->[1] < $l); 150 - 151 - if ($l == 0x1) { 152 - $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)); 153 - } elsif ($l == 0x2) { 154 - $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0], 2)); 155 - } elsif ($l == 0x3) { 156 - $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)) << 16; 157 - $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0] + 1, 2)); 158 - } elsif ($l == 0x4) { 159 - $len = unpack("N", substr(${$cursor->[2]}, $cursor->[0], 4)); 160 - } else { 161 - die $x509, ": ", $cursor->[0], ": ASN.1 element too long (", $l, ")\n"; 162 - } 163 - 164 - $cursor->[0] += $l; 165 - $cursor->[1] -= $l; 166 - } 167 - 168 - die $x509, ": ", $cursor->[0], ": ASN.1 data underrun (", $len, ")\n" 169 - if ($cursor->[1] < $len); 170 - 171 - my $ret = [ $tag, [ $cursor->[0], $len, $cursor->[2] ] ]; 172 - $cursor->[0] += $len; 173 - $cursor->[1] -= $len; 174 - 175 - return $ret; 176 - } 177 - 178 - ############################################################################### 179 - # 180 - # Retrieve the data referred to by a cursor 181 - # 182 - ############################################################################### 183 - sub asn1_retrieve($) 184 - { 185 - my ($cursor) = @_; 186 - my ($offset, $len, $data) = @$cursor; 187 - return substr($$data, $offset, $len); 188 - } 189 - 190 - ############################################################################### 191 - # 192 - # Roughly parse the X.509 certificate 193 - # 194 - ############################################################################### 195 - my $cursor = [ 0, length($x509_certificate), \$x509_certificate ]; 196 - 197 - my $cert = asn1_extract($cursor, $UNIV | $CONS | $SEQUENCE); 198 - my $tbs = asn1_extract($cert->[1], $UNIV | $CONS | $SEQUENCE); 199 - my $version = asn1_extract($tbs->[1], $CONT | $CONS | 0, 1); 200 - my $serial_number = asn1_extract($tbs->[1], $UNIV | $INTEGER); 201 - my $sig_type = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); 202 - my $issuer = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); 203 - my $validity = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); 204 - my $subject = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); 205 - my $key = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); 206 - my $issuer_uid = asn1_extract($tbs->[1], $CONT | $CONS | 1, 1); 207 - my $subject_uid = asn1_extract($tbs->[1], $CONT | $CONS | 2, 1); 208 - my $extension_list = asn1_extract($tbs->[1], $CONT | $CONS | 3, 1); 209 - 210 - my $subject_key_id = (); 211 - my $authority_key_id = (); 212 - 213 - # 214 - # Parse the extension list 215 - # 216 - if ($extension_list->[0] != -1) { 217 - my $extensions = asn1_extract($extension_list->[1], $UNIV | $CONS | $SEQUENCE); 218 - 219 - while ($extensions->[1]->[1] > 0) { 220 - my $ext = asn1_extract($extensions->[1], $UNIV | $CONS | $SEQUENCE); 221 - my $x_oid = asn1_extract($ext->[1], $UNIV | $OBJ_ID); 222 - my $x_crit = asn1_extract($ext->[1], $UNIV | $BOOLEAN, 1); 223 - my $x_val = asn1_extract($ext->[1], $UNIV | $OCTET_STRING); 224 - 225 - my $raw_oid = asn1_retrieve($x_oid->[1]); 226 - next if (!exists($OIDs{$raw_oid})); 227 - my $x_type = $OIDs{$raw_oid}; 228 - 229 - my $raw_value = asn1_retrieve($x_val->[1]); 230 - 231 - if ($x_type eq "subjectKeyIdentifier") { 232 - my $vcursor = [ 0, length($raw_value), \$raw_value ]; 233 - 234 - $subject_key_id = asn1_extract($vcursor, $UNIV | $OCTET_STRING); 235 - } 236 - } 237 - } 238 - 239 - ############################################################################### 240 - # 241 - # Determine what we're going to use as the signer's name. In order of 242 - # preference, take one of: commonName, organizationName or emailAddress. 243 - # 244 - ############################################################################### 245 - my $org = ""; 246 - my $cn = ""; 247 - my $email = ""; 248 - 249 - while ($subject->[1]->[1] > 0) { 250 - my $rdn = asn1_extract($subject->[1], $UNIV | $CONS | $SET); 251 - my $attr = asn1_extract($rdn->[1], $UNIV | $CONS | $SEQUENCE); 252 - my $n_oid = asn1_extract($attr->[1], $UNIV | $OBJ_ID); 253 - my $n_val = asn1_extract($attr->[1], -1); 254 - 255 - my $raw_oid = asn1_retrieve($n_oid->[1]); 256 - next if (!exists($OIDs{$raw_oid})); 257 - my $n_type = $OIDs{$raw_oid}; 258 - 259 - my $raw_value = asn1_retrieve($n_val->[1]); 260 - 261 - if ($n_type eq "organizationName") { 262 - $org = $raw_value; 263 - } elsif ($n_type eq "commonName") { 264 - $cn = $raw_value; 265 - } elsif ($n_type eq "emailAddress") { 266 - $email = $raw_value; 267 - } 268 - } 269 - 270 - my $signers_name = $email; 271 - 272 - if ($org && $cn) { 273 - # Don't use the organizationName if the commonName repeats it 274 - if (length($org) <= length($cn) && 275 - substr($cn, 0, length($org)) eq $org) { 276 - $signers_name = $cn; 277 - goto got_id_name; 278 - } 279 - 280 - # Or a signifcant chunk of it 281 - if (length($org) >= 7 && 282 - length($cn) >= 7 && 283 - substr($cn, 0, 7) eq substr($org, 0, 7)) { 284 - $signers_name = $cn; 285 - goto got_id_name; 286 - } 287 - 288 - $signers_name = $org . ": " . $cn; 289 - } elsif ($org) { 290 - $signers_name = $org; 291 - } elsif ($cn) { 292 - $signers_name = $cn; 293 - } 294 - 295 - got_id_name: 296 - 297 - die $x509, ": ", "X.509: Couldn't find the Subject Key Identifier extension\n" 298 - if (!$subject_key_id); 299 - 300 - my $key_identifier = asn1_retrieve($subject_key_id->[1]); 301 - 302 - ############################################################################### 303 - # 304 - # Create and attach the module signature 305 - # 306 - ############################################################################### 307 - 308 - # 309 - # Signature parameters 310 - # 311 - my $algo = 1; # Public-key crypto algorithm: RSA 312 - my $hash = 0; # Digest algorithm 313 - my $id_type = 1; # Identifier type: X.509 314 - 315 - # 316 - # Digest the data 317 - # 318 - my $prologue; 319 - if ($dgst eq "sha1") { 320 - $prologue = pack("C*", 321 - 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 322 - 0x2B, 0x0E, 0x03, 0x02, 0x1A, 323 - 0x05, 0x00, 0x04, 0x14); 324 - $hash = 2; 325 - } elsif ($dgst eq "sha224") { 326 - $prologue = pack("C*", 327 - 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 328 - 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 329 - 0x05, 0x00, 0x04, 0x1C); 330 - $hash = 7; 331 - } elsif ($dgst eq "sha256") { 332 - $prologue = pack("C*", 333 - 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 334 - 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 335 - 0x05, 0x00, 0x04, 0x20); 336 - $hash = 4; 337 - } elsif ($dgst eq "sha384") { 338 - $prologue = pack("C*", 339 - 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 340 - 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 341 - 0x05, 0x00, 0x04, 0x30); 342 - $hash = 5; 343 - } elsif ($dgst eq "sha512") { 344 - $prologue = pack("C*", 345 - 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 346 - 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 347 - 0x05, 0x00, 0x04, 0x40); 348 - $hash = 6; 349 - } else { 350 - die "Unknown hash algorithm: $dgst\n"; 351 - } 352 - 353 - my $signature; 354 - if ($signature_file) { 355 - $signature = read_file($signature_file); 356 - } else { 357 - # 358 - # Generate the digest and read from openssl's stdout 359 - # 360 - my $digest; 361 - $digest = readpipe("openssl dgst -$dgst -binary $module") || die "openssl dgst"; 362 - 363 - # 364 - # Generate the binary signature, which will be just the integer that 365 - # comprises the signature with no metadata attached. 366 - # 367 - my $pid; 368 - $pid = open2(*read_from, *write_to, 369 - "openssl rsautl -sign -inkey $private_key -keyform PEM") || 370 - die "openssl rsautl"; 371 - binmode write_to; 372 - print write_to $prologue . $digest || die "pipe to openssl rsautl"; 373 - close(write_to) || die "pipe to openssl rsautl"; 374 - 375 - binmode read_from; 376 - read(read_from, $signature, 4096) || die "pipe from openssl rsautl"; 377 - close(read_from) || die "pipe from openssl rsautl"; 378 - waitpid($pid, 0) || die; 379 - die "openssl rsautl died: $?" if ($? >> 8); 380 - } 381 - $signature = pack("n", length($signature)) . $signature, 382 - 383 - # 384 - # Build the signed binary 385 - # 386 - my $unsigned_module = read_file($module); 387 - 388 - my $magic_number = "~Module signature appended~\n"; 389 - 390 - my $info = pack("CCCCCxxxN", 391 - $algo, $hash, $id_type, 392 - length($signers_name), 393 - length($key_identifier), 394 - length($signature)); 395 - 396 - if ($verbose) { 397 - print "Size of unsigned module: ", length($unsigned_module), "\n"; 398 - print "Size of signer's name : ", length($signers_name), "\n"; 399 - print "Size of key identifier : ", length($key_identifier), "\n"; 400 - print "Size of signature : ", length($signature), "\n"; 401 - print "Size of information : ", length($info), "\n"; 402 - print "Size of magic number : ", length($magic_number), "\n"; 403 - print "Signer's name : '", $signers_name, "'\n"; 404 - print "Digest : $dgst\n"; 405 - } 406 - 407 - open(FD, ">$dest") || die $dest; 408 - binmode FD; 409 - print FD 410 - $unsigned_module, 411 - $signers_name, 412 - $key_identifier, 413 - $signature, 414 - $info, 415 - $magic_number 416 - ; 417 - close FD || die $dest; 418 - 419 - if (!$keep_orig) { 420 - rename($dest, $module) || die $module; 421 - }
+260
scripts/sign-file.c
··· 1 + /* Sign a module file using the given key. 2 + * 3 + * Copyright (C) 2014 Red Hat, Inc. All Rights Reserved. 4 + * Written by David Howells (dhowells@redhat.com) 5 + * 6 + * This program is free software; you can redistribute it and/or 7 + * modify it under the terms of the GNU General Public Licence 8 + * as published by the Free Software Foundation; either version 9 + * 2 of the Licence, or (at your option) any later version. 10 + */ 11 + #define _GNU_SOURCE 12 + #include <stdio.h> 13 + #include <stdlib.h> 14 + #include <stdint.h> 15 + #include <stdbool.h> 16 + #include <string.h> 17 + #include <getopt.h> 18 + #include <err.h> 19 + #include <arpa/inet.h> 20 + #include <openssl/bio.h> 21 + #include <openssl/evp.h> 22 + #include <openssl/pem.h> 23 + #include <openssl/cms.h> 24 + #include <openssl/err.h> 25 + #include <openssl/engine.h> 26 + 27 + struct module_signature { 28 + uint8_t algo; /* Public-key crypto algorithm [0] */ 29 + uint8_t hash; /* Digest algorithm [0] */ 30 + uint8_t id_type; /* Key identifier type [PKEY_ID_PKCS7] */ 31 + uint8_t signer_len; /* Length of signer's name [0] */ 32 + uint8_t key_id_len; /* Length of key identifier [0] */ 33 + uint8_t __pad[3]; 34 + uint32_t sig_len; /* Length of signature data */ 35 + }; 36 + 37 + #define PKEY_ID_PKCS7 2 38 + 39 + static char magic_number[] = "~Module signature appended~\n"; 40 + 41 + static __attribute__((noreturn)) 42 + void format(void) 43 + { 44 + fprintf(stderr, 45 + "Usage: scripts/sign-file [-dp] <hash algo> <key> <x509> <module> [<dest>]\n"); 46 + exit(2); 47 + } 48 + 49 + static void display_openssl_errors(int l) 50 + { 51 + const char *file; 52 + char buf[120]; 53 + int e, line; 54 + 55 + if (ERR_peek_error() == 0) 56 + return; 57 + fprintf(stderr, "At main.c:%d:\n", l); 58 + 59 + while ((e = ERR_get_error_line(&file, &line))) { 60 + ERR_error_string(e, buf); 61 + fprintf(stderr, "- SSL %s: %s:%d\n", buf, file, line); 62 + } 63 + } 64 + 65 + static void drain_openssl_errors(void) 66 + { 67 + const char *file; 68 + int line; 69 + 70 + if (ERR_peek_error() == 0) 71 + return; 72 + while (ERR_get_error_line(&file, &line)) {} 73 + } 74 + 75 + #define ERR(cond, fmt, ...) \ 76 + do { \ 77 + bool __cond = (cond); \ 78 + display_openssl_errors(__LINE__); \ 79 + if (__cond) { \ 80 + err(1, fmt, ## __VA_ARGS__); \ 81 + } \ 82 + } while(0) 83 + 84 + static const char *key_pass; 85 + 86 + static int pem_pw_cb(char *buf, int len, int w, void *v) 87 + { 88 + int pwlen; 89 + 90 + if (!key_pass) 91 + return -1; 92 + 93 + pwlen = strlen(key_pass); 94 + if (pwlen >= len) 95 + return -1; 96 + 97 + strcpy(buf, key_pass); 98 + 99 + /* If it's wrong, don't keep trying it. */ 100 + key_pass = NULL; 101 + 102 + return pwlen; 103 + } 104 + 105 + int main(int argc, char **argv) 106 + { 107 + struct module_signature sig_info = { .id_type = PKEY_ID_PKCS7 }; 108 + char *hash_algo = NULL; 109 + char *private_key_name, *x509_name, *module_name, *dest_name; 110 + bool save_cms = false, replace_orig; 111 + bool sign_only = false; 112 + unsigned char buf[4096]; 113 + unsigned long module_size, cms_size; 114 + unsigned int use_keyid = 0, use_signed_attrs = CMS_NOATTR; 115 + const EVP_MD *digest_algo; 116 + EVP_PKEY *private_key; 117 + CMS_ContentInfo *cms; 118 + X509 *x509; 119 + BIO *b, *bd = NULL, *bm; 120 + int opt, n; 121 + 122 + OpenSSL_add_all_algorithms(); 123 + ERR_load_crypto_strings(); 124 + ERR_clear_error(); 125 + 126 + key_pass = getenv("KBUILD_SIGN_PIN"); 127 + 128 + do { 129 + opt = getopt(argc, argv, "dpk"); 130 + switch (opt) { 131 + case 'p': save_cms = true; break; 132 + case 'd': sign_only = true; save_cms = true; break; 133 + case 'k': use_keyid = CMS_USE_KEYID; break; 134 + case -1: break; 135 + default: format(); 136 + } 137 + } while (opt != -1); 138 + 139 + argc -= optind; 140 + argv += optind; 141 + if (argc < 4 || argc > 5) 142 + format(); 143 + 144 + hash_algo = argv[0]; 145 + private_key_name = argv[1]; 146 + x509_name = argv[2]; 147 + module_name = argv[3]; 148 + if (argc == 5) { 149 + dest_name = argv[4]; 150 + replace_orig = false; 151 + } else { 152 + ERR(asprintf(&dest_name, "%s.~signed~", module_name) < 0, 153 + "asprintf"); 154 + replace_orig = true; 155 + } 156 + 157 + /* Read the private key and the X.509 cert the PKCS#7 message 158 + * will point to. 159 + */ 160 + if (!strncmp(private_key_name, "pkcs11:", 7)) { 161 + ENGINE *e; 162 + 163 + ENGINE_load_builtin_engines(); 164 + drain_openssl_errors(); 165 + e = ENGINE_by_id("pkcs11"); 166 + ERR(!e, "Load PKCS#11 ENGINE"); 167 + if (ENGINE_init(e)) 168 + drain_openssl_errors(); 169 + else 170 + ERR(1, "ENGINE_init"); 171 + if (key_pass) 172 + ERR(!ENGINE_ctrl_cmd_string(e, "PIN", key_pass, 0), "Set PKCS#11 PIN"); 173 + private_key = ENGINE_load_private_key(e, private_key_name, NULL, 174 + NULL); 175 + ERR(!private_key, "%s", private_key_name); 176 + } else { 177 + b = BIO_new_file(private_key_name, "rb"); 178 + ERR(!b, "%s", private_key_name); 179 + private_key = PEM_read_bio_PrivateKey(b, NULL, pem_pw_cb, NULL); 180 + ERR(!private_key, "%s", private_key_name); 181 + BIO_free(b); 182 + } 183 + 184 + b = BIO_new_file(x509_name, "rb"); 185 + ERR(!b, "%s", x509_name); 186 + x509 = d2i_X509_bio(b, NULL); /* Binary encoded X.509 */ 187 + if (!x509) { 188 + ERR(BIO_reset(b) != 1, "%s", x509_name); 189 + x509 = PEM_read_bio_X509(b, NULL, NULL, NULL); /* PEM encoded X.509 */ 190 + if (x509) 191 + drain_openssl_errors(); 192 + } 193 + BIO_free(b); 194 + ERR(!x509, "%s", x509_name); 195 + 196 + /* Open the destination file now so that we can shovel the module data 197 + * across as we read it. 198 + */ 199 + if (!sign_only) { 200 + bd = BIO_new_file(dest_name, "wb"); 201 + ERR(!bd, "%s", dest_name); 202 + } 203 + 204 + /* Digest the module data. */ 205 + OpenSSL_add_all_digests(); 206 + display_openssl_errors(__LINE__); 207 + digest_algo = EVP_get_digestbyname(hash_algo); 208 + ERR(!digest_algo, "EVP_get_digestbyname"); 209 + 210 + bm = BIO_new_file(module_name, "rb"); 211 + ERR(!bm, "%s", module_name); 212 + 213 + /* Load the CMS message from the digest buffer. */ 214 + cms = CMS_sign(NULL, NULL, NULL, NULL, 215 + CMS_NOCERTS | CMS_PARTIAL | CMS_BINARY | CMS_DETACHED | CMS_STREAM); 216 + ERR(!cms, "CMS_sign"); 217 + 218 + ERR(!CMS_add1_signer(cms, x509, private_key, digest_algo, 219 + CMS_NOCERTS | CMS_BINARY | CMS_NOSMIMECAP | 220 + use_keyid | use_signed_attrs), 221 + "CMS_sign_add_signer"); 222 + ERR(CMS_final(cms, bm, NULL, CMS_NOCERTS | CMS_BINARY) < 0, 223 + "CMS_final"); 224 + 225 + if (save_cms) { 226 + char *cms_name; 227 + 228 + ERR(asprintf(&cms_name, "%s.p7s", module_name) < 0, "asprintf"); 229 + b = BIO_new_file(cms_name, "wb"); 230 + ERR(!b, "%s", cms_name); 231 + ERR(i2d_CMS_bio_stream(b, cms, NULL, 0) < 0, "%s", cms_name); 232 + BIO_free(b); 233 + } 234 + 235 + if (sign_only) 236 + return 0; 237 + 238 + /* Append the marker and the PKCS#7 message to the destination file */ 239 + ERR(BIO_reset(bm) < 0, "%s", module_name); 240 + while ((n = BIO_read(bm, buf, sizeof(buf))), 241 + n > 0) { 242 + ERR(BIO_write(bd, buf, n) < 0, "%s", dest_name); 243 + } 244 + ERR(n < 0, "%s", module_name); 245 + module_size = BIO_number_written(bd); 246 + 247 + ERR(i2d_CMS_bio_stream(bd, cms, NULL, 0) < 0, "%s", dest_name); 248 + cms_size = BIO_number_written(bd) - module_size; 249 + sig_info.sig_len = htonl(cms_size); 250 + ERR(BIO_write(bd, &sig_info, sizeof(sig_info)) < 0, "%s", dest_name); 251 + ERR(BIO_write(bd, magic_number, sizeof(magic_number) - 1) < 0, "%s", dest_name); 252 + 253 + ERR(BIO_free(bd) < 0, "%s", dest_name); 254 + 255 + /* Finally, if we're signing in place, replace the original. */ 256 + if (replace_orig) 257 + ERR(rename(dest_name, module_name) < 0, "%s", dest_name); 258 + 259 + return 0; 260 + }
-5
security/Kconfig
··· 132 132 default DEFAULT_SECURITY_SMACK if SECURITY_SMACK 133 133 default DEFAULT_SECURITY_TOMOYO if SECURITY_TOMOYO 134 134 default DEFAULT_SECURITY_APPARMOR if SECURITY_APPARMOR 135 - default DEFAULT_SECURITY_YAMA if SECURITY_YAMA 136 135 default DEFAULT_SECURITY_DAC 137 136 138 137 help ··· 150 151 config DEFAULT_SECURITY_APPARMOR 151 152 bool "AppArmor" if SECURITY_APPARMOR=y 152 153 153 - config DEFAULT_SECURITY_YAMA 154 - bool "Yama" if SECURITY_YAMA=y 155 - 156 154 config DEFAULT_SECURITY_DAC 157 155 bool "Unix Discretionary Access Controls" 158 156 ··· 161 165 default "smack" if DEFAULT_SECURITY_SMACK 162 166 default "tomoyo" if DEFAULT_SECURITY_TOMOYO 163 167 default "apparmor" if DEFAULT_SECURITY_APPARMOR 164 - default "yama" if DEFAULT_SECURITY_YAMA 165 168 default "" if DEFAULT_SECURITY_DAC 166 169 167 170 endmenu
+15
security/lsm_audit.c
··· 245 245 } 246 246 break; 247 247 } 248 + case LSM_AUDIT_DATA_IOCTL_OP: { 249 + struct inode *inode; 250 + 251 + audit_log_d_path(ab, " path=", &a->u.op->path); 252 + 253 + inode = a->u.op->path.dentry->d_inode; 254 + if (inode) { 255 + audit_log_format(ab, " dev="); 256 + audit_log_untrustedstring(ab, inode->i_sb->s_id); 257 + audit_log_format(ab, " ino=%lu", inode->i_ino); 258 + } 259 + 260 + audit_log_format(ab, " ioctlcmd=%hx", a->u.op->cmd); 261 + break; 262 + } 248 263 case LSM_AUDIT_DATA_DENTRY: { 249 264 struct inode *inode; 250 265
+3 -8
security/security.c
··· 56 56 pr_info("Security Framework initialized\n"); 57 57 58 58 /* 59 - * Always load the capability module. 59 + * Load minor LSMs, with the capability module always first. 60 60 */ 61 61 capability_add_hooks(); 62 - #ifdef CONFIG_SECURITY_YAMA_STACKED 63 - /* 64 - * If Yama is configured for stacking load it next. 65 - */ 66 62 yama_add_hooks(); 67 - #endif 63 + 68 64 /* 69 - * Load the chosen module if there is one. 70 - * This will also find yama if it is stacking 65 + * Load all the remaining security modules. 71 66 */ 72 67 do_security_initcalls(); 73 68
+402 -16
security/selinux/avc.c
··· 22 22 #include <linux/init.h> 23 23 #include <linux/skbuff.h> 24 24 #include <linux/percpu.h> 25 + #include <linux/list.h> 25 26 #include <net/sock.h> 26 27 #include <linux/un.h> 27 28 #include <net/af_unix.h> ··· 49 48 u32 tsid; 50 49 u16 tclass; 51 50 struct av_decision avd; 51 + struct avc_xperms_node *xp_node; 52 52 }; 53 53 54 54 struct avc_node { 55 55 struct avc_entry ae; 56 56 struct hlist_node list; /* anchored in avc_cache->slots[i] */ 57 57 struct rcu_head rhead; 58 + }; 59 + 60 + struct avc_xperms_decision_node { 61 + struct extended_perms_decision xpd; 62 + struct list_head xpd_list; /* list of extended_perms_decision */ 63 + }; 64 + 65 + struct avc_xperms_node { 66 + struct extended_perms xp; 67 + struct list_head xpd_head; /* list head of extended_perms_decision */ 58 68 }; 59 69 60 70 struct avc_cache { ··· 92 80 static struct avc_cache avc_cache; 93 81 static struct avc_callback_node *avc_callbacks; 94 82 static struct kmem_cache *avc_node_cachep; 83 + static struct kmem_cache *avc_xperms_data_cachep; 84 + static struct kmem_cache *avc_xperms_decision_cachep; 85 + static struct kmem_cache *avc_xperms_cachep; 95 86 96 87 static inline int avc_hash(u32 ssid, u32 tsid, u16 tclass) 97 88 { ··· 116 101 return; 117 102 } 118 103 104 + BUG_ON(!tclass || tclass >= ARRAY_SIZE(secclass_map)); 119 105 perms = secclass_map[tclass-1].perms; 120 106 121 107 audit_log_format(ab, " {"); ··· 165 149 kfree(scontext); 166 150 } 167 151 168 - BUG_ON(tclass >= ARRAY_SIZE(secclass_map)); 152 + BUG_ON(!tclass || tclass >= ARRAY_SIZE(secclass_map)); 169 153 audit_log_format(ab, " tclass=%s", secclass_map[tclass-1].name); 170 154 } 171 155 ··· 186 170 atomic_set(&avc_cache.lru_hint, 0); 187 171 188 172 avc_node_cachep = kmem_cache_create("avc_node", sizeof(struct avc_node), 189 - 0, SLAB_PANIC, NULL); 173 + 0, SLAB_PANIC, NULL); 174 + avc_xperms_cachep = kmem_cache_create("avc_xperms_node", 175 + sizeof(struct avc_xperms_node), 176 + 0, SLAB_PANIC, NULL); 177 + avc_xperms_decision_cachep = kmem_cache_create( 178 + "avc_xperms_decision_node", 179 + sizeof(struct avc_xperms_decision_node), 180 + 0, SLAB_PANIC, NULL); 181 + avc_xperms_data_cachep = kmem_cache_create("avc_xperms_data", 182 + sizeof(struct extended_perms_data), 183 + 0, SLAB_PANIC, NULL); 190 184 191 185 audit_log(current->audit_context, GFP_KERNEL, AUDIT_KERNEL, "AVC INITIALIZED\n"); 192 186 } ··· 231 205 slots_used, AVC_CACHE_SLOTS, max_chain_len); 232 206 } 233 207 208 + /* 209 + * using a linked list for extended_perms_decision lookup because the list is 210 + * always small. i.e. less than 5, typically 1 211 + */ 212 + static struct extended_perms_decision *avc_xperms_decision_lookup(u8 driver, 213 + struct avc_xperms_node *xp_node) 214 + { 215 + struct avc_xperms_decision_node *xpd_node; 216 + 217 + list_for_each_entry(xpd_node, &xp_node->xpd_head, xpd_list) { 218 + if (xpd_node->xpd.driver == driver) 219 + return &xpd_node->xpd; 220 + } 221 + return NULL; 222 + } 223 + 224 + static inline unsigned int 225 + avc_xperms_has_perm(struct extended_perms_decision *xpd, 226 + u8 perm, u8 which) 227 + { 228 + unsigned int rc = 0; 229 + 230 + if ((which == XPERMS_ALLOWED) && 231 + (xpd->used & XPERMS_ALLOWED)) 232 + rc = security_xperm_test(xpd->allowed->p, perm); 233 + else if ((which == XPERMS_AUDITALLOW) && 234 + (xpd->used & XPERMS_AUDITALLOW)) 235 + rc = security_xperm_test(xpd->auditallow->p, perm); 236 + else if ((which == XPERMS_DONTAUDIT) && 237 + (xpd->used & XPERMS_DONTAUDIT)) 238 + rc = security_xperm_test(xpd->dontaudit->p, perm); 239 + return rc; 240 + } 241 + 242 + static void avc_xperms_allow_perm(struct avc_xperms_node *xp_node, 243 + u8 driver, u8 perm) 244 + { 245 + struct extended_perms_decision *xpd; 246 + security_xperm_set(xp_node->xp.drivers.p, driver); 247 + xpd = avc_xperms_decision_lookup(driver, xp_node); 248 + if (xpd && xpd->allowed) 249 + security_xperm_set(xpd->allowed->p, perm); 250 + } 251 + 252 + static void avc_xperms_decision_free(struct avc_xperms_decision_node *xpd_node) 253 + { 254 + struct extended_perms_decision *xpd; 255 + 256 + xpd = &xpd_node->xpd; 257 + if (xpd->allowed) 258 + kmem_cache_free(avc_xperms_data_cachep, xpd->allowed); 259 + if (xpd->auditallow) 260 + kmem_cache_free(avc_xperms_data_cachep, xpd->auditallow); 261 + if (xpd->dontaudit) 262 + kmem_cache_free(avc_xperms_data_cachep, xpd->dontaudit); 263 + kmem_cache_free(avc_xperms_decision_cachep, xpd_node); 264 + } 265 + 266 + static void avc_xperms_free(struct avc_xperms_node *xp_node) 267 + { 268 + struct avc_xperms_decision_node *xpd_node, *tmp; 269 + 270 + if (!xp_node) 271 + return; 272 + 273 + list_for_each_entry_safe(xpd_node, tmp, &xp_node->xpd_head, xpd_list) { 274 + list_del(&xpd_node->xpd_list); 275 + avc_xperms_decision_free(xpd_node); 276 + } 277 + kmem_cache_free(avc_xperms_cachep, xp_node); 278 + } 279 + 280 + static void avc_copy_xperms_decision(struct extended_perms_decision *dest, 281 + struct extended_perms_decision *src) 282 + { 283 + dest->driver = src->driver; 284 + dest->used = src->used; 285 + if (dest->used & XPERMS_ALLOWED) 286 + memcpy(dest->allowed->p, src->allowed->p, 287 + sizeof(src->allowed->p)); 288 + if (dest->used & XPERMS_AUDITALLOW) 289 + memcpy(dest->auditallow->p, src->auditallow->p, 290 + sizeof(src->auditallow->p)); 291 + if (dest->used & XPERMS_DONTAUDIT) 292 + memcpy(dest->dontaudit->p, src->dontaudit->p, 293 + sizeof(src->dontaudit->p)); 294 + } 295 + 296 + /* 297 + * similar to avc_copy_xperms_decision, but only copy decision 298 + * information relevant to this perm 299 + */ 300 + static inline void avc_quick_copy_xperms_decision(u8 perm, 301 + struct extended_perms_decision *dest, 302 + struct extended_perms_decision *src) 303 + { 304 + /* 305 + * compute index of the u32 of the 256 bits (8 u32s) that contain this 306 + * command permission 307 + */ 308 + u8 i = perm >> 5; 309 + 310 + dest->used = src->used; 311 + if (dest->used & XPERMS_ALLOWED) 312 + dest->allowed->p[i] = src->allowed->p[i]; 313 + if (dest->used & XPERMS_AUDITALLOW) 314 + dest->auditallow->p[i] = src->auditallow->p[i]; 315 + if (dest->used & XPERMS_DONTAUDIT) 316 + dest->dontaudit->p[i] = src->dontaudit->p[i]; 317 + } 318 + 319 + static struct avc_xperms_decision_node 320 + *avc_xperms_decision_alloc(u8 which) 321 + { 322 + struct avc_xperms_decision_node *xpd_node; 323 + struct extended_perms_decision *xpd; 324 + 325 + xpd_node = kmem_cache_zalloc(avc_xperms_decision_cachep, 326 + GFP_ATOMIC | __GFP_NOMEMALLOC); 327 + if (!xpd_node) 328 + return NULL; 329 + 330 + xpd = &xpd_node->xpd; 331 + if (which & XPERMS_ALLOWED) { 332 + xpd->allowed = kmem_cache_zalloc(avc_xperms_data_cachep, 333 + GFP_ATOMIC | __GFP_NOMEMALLOC); 334 + if (!xpd->allowed) 335 + goto error; 336 + } 337 + if (which & XPERMS_AUDITALLOW) { 338 + xpd->auditallow = kmem_cache_zalloc(avc_xperms_data_cachep, 339 + GFP_ATOMIC | __GFP_NOMEMALLOC); 340 + if (!xpd->auditallow) 341 + goto error; 342 + } 343 + if (which & XPERMS_DONTAUDIT) { 344 + xpd->dontaudit = kmem_cache_zalloc(avc_xperms_data_cachep, 345 + GFP_ATOMIC | __GFP_NOMEMALLOC); 346 + if (!xpd->dontaudit) 347 + goto error; 348 + } 349 + return xpd_node; 350 + error: 351 + avc_xperms_decision_free(xpd_node); 352 + return NULL; 353 + } 354 + 355 + static int avc_add_xperms_decision(struct avc_node *node, 356 + struct extended_perms_decision *src) 357 + { 358 + struct avc_xperms_decision_node *dest_xpd; 359 + 360 + node->ae.xp_node->xp.len++; 361 + dest_xpd = avc_xperms_decision_alloc(src->used); 362 + if (!dest_xpd) 363 + return -ENOMEM; 364 + avc_copy_xperms_decision(&dest_xpd->xpd, src); 365 + list_add(&dest_xpd->xpd_list, &node->ae.xp_node->xpd_head); 366 + return 0; 367 + } 368 + 369 + static struct avc_xperms_node *avc_xperms_alloc(void) 370 + { 371 + struct avc_xperms_node *xp_node; 372 + 373 + xp_node = kmem_cache_zalloc(avc_xperms_cachep, 374 + GFP_ATOMIC|__GFP_NOMEMALLOC); 375 + if (!xp_node) 376 + return xp_node; 377 + INIT_LIST_HEAD(&xp_node->xpd_head); 378 + return xp_node; 379 + } 380 + 381 + static int avc_xperms_populate(struct avc_node *node, 382 + struct avc_xperms_node *src) 383 + { 384 + struct avc_xperms_node *dest; 385 + struct avc_xperms_decision_node *dest_xpd; 386 + struct avc_xperms_decision_node *src_xpd; 387 + 388 + if (src->xp.len == 0) 389 + return 0; 390 + dest = avc_xperms_alloc(); 391 + if (!dest) 392 + return -ENOMEM; 393 + 394 + memcpy(dest->xp.drivers.p, src->xp.drivers.p, sizeof(dest->xp.drivers.p)); 395 + dest->xp.len = src->xp.len; 396 + 397 + /* for each source xpd allocate a destination xpd and copy */ 398 + list_for_each_entry(src_xpd, &src->xpd_head, xpd_list) { 399 + dest_xpd = avc_xperms_decision_alloc(src_xpd->xpd.used); 400 + if (!dest_xpd) 401 + goto error; 402 + avc_copy_xperms_decision(&dest_xpd->xpd, &src_xpd->xpd); 403 + list_add(&dest_xpd->xpd_list, &dest->xpd_head); 404 + } 405 + node->ae.xp_node = dest; 406 + return 0; 407 + error: 408 + avc_xperms_free(dest); 409 + return -ENOMEM; 410 + 411 + } 412 + 413 + static inline u32 avc_xperms_audit_required(u32 requested, 414 + struct av_decision *avd, 415 + struct extended_perms_decision *xpd, 416 + u8 perm, 417 + int result, 418 + u32 *deniedp) 419 + { 420 + u32 denied, audited; 421 + 422 + denied = requested & ~avd->allowed; 423 + if (unlikely(denied)) { 424 + audited = denied & avd->auditdeny; 425 + if (audited && xpd) { 426 + if (avc_xperms_has_perm(xpd, perm, XPERMS_DONTAUDIT)) 427 + audited &= ~requested; 428 + } 429 + } else if (result) { 430 + audited = denied = requested; 431 + } else { 432 + audited = requested & avd->auditallow; 433 + if (audited && xpd) { 434 + if (!avc_xperms_has_perm(xpd, perm, XPERMS_AUDITALLOW)) 435 + audited &= ~requested; 436 + } 437 + } 438 + 439 + *deniedp = denied; 440 + return audited; 441 + } 442 + 443 + static inline int avc_xperms_audit(u32 ssid, u32 tsid, u16 tclass, 444 + u32 requested, struct av_decision *avd, 445 + struct extended_perms_decision *xpd, 446 + u8 perm, int result, 447 + struct common_audit_data *ad) 448 + { 449 + u32 audited, denied; 450 + 451 + audited = avc_xperms_audit_required( 452 + requested, avd, xpd, perm, result, &denied); 453 + if (likely(!audited)) 454 + return 0; 455 + return slow_avc_audit(ssid, tsid, tclass, requested, 456 + audited, denied, result, ad, 0); 457 + } 458 + 234 459 static void avc_node_free(struct rcu_head *rhead) 235 460 { 236 461 struct avc_node *node = container_of(rhead, struct avc_node, rhead); 462 + avc_xperms_free(node->ae.xp_node); 237 463 kmem_cache_free(avc_node_cachep, node); 238 464 avc_cache_stats_incr(frees); 239 465 } ··· 499 221 500 222 static void avc_node_kill(struct avc_node *node) 501 223 { 224 + avc_xperms_free(node->ae.xp_node); 502 225 kmem_cache_free(avc_node_cachep, node); 503 226 avc_cache_stats_incr(frees); 504 227 atomic_dec(&avc_cache.active_nodes); ··· 646 367 * @tsid: target security identifier 647 368 * @tclass: target security class 648 369 * @avd: resulting av decision 370 + * @xp_node: resulting extended permissions 649 371 * 650 372 * Insert an AVC entry for the SID pair 651 373 * (@ssid, @tsid) and class @tclass. ··· 658 378 * the access vectors into a cache entry, returns 659 379 * avc_node inserted. Otherwise, this function returns NULL. 660 380 */ 661 - static struct avc_node *avc_insert(u32 ssid, u32 tsid, u16 tclass, struct av_decision *avd) 381 + static struct avc_node *avc_insert(u32 ssid, u32 tsid, u16 tclass, 382 + struct av_decision *avd, 383 + struct avc_xperms_node *xp_node) 662 384 { 663 385 struct avc_node *pos, *node = NULL; 664 386 int hvalue; ··· 673 391 if (node) { 674 392 struct hlist_head *head; 675 393 spinlock_t *lock; 394 + int rc = 0; 676 395 677 396 hvalue = avc_hash(ssid, tsid, tclass); 678 397 avc_node_populate(node, ssid, tsid, tclass, avd); 679 - 398 + rc = avc_xperms_populate(node, xp_node); 399 + if (rc) { 400 + kmem_cache_free(avc_node_cachep, node); 401 + return NULL; 402 + } 680 403 head = &avc_cache.slots[hvalue]; 681 404 lock = &avc_cache.slots_lock[hvalue]; 682 405 ··· 810 523 * @perms : Permission mask bits 811 524 * @ssid,@tsid,@tclass : identifier of an AVC entry 812 525 * @seqno : sequence number when decision was made 526 + * @xpd: extended_perms_decision to be added to the node 813 527 * 814 528 * if a valid AVC entry doesn't exist,this function returns -ENOENT. 815 529 * if kmalloc() called internal returns NULL, this function returns -ENOMEM. 816 530 * otherwise, this function updates the AVC entry. The original AVC-entry object 817 531 * will release later by RCU. 818 532 */ 819 - static int avc_update_node(u32 event, u32 perms, u32 ssid, u32 tsid, u16 tclass, 820 - u32 seqno) 533 + static int avc_update_node(u32 event, u32 perms, u8 driver, u8 xperm, u32 ssid, 534 + u32 tsid, u16 tclass, u32 seqno, 535 + struct extended_perms_decision *xpd, 536 + u32 flags) 821 537 { 822 538 int hvalue, rc = 0; 823 539 unsigned long flag; ··· 864 574 865 575 avc_node_populate(node, ssid, tsid, tclass, &orig->ae.avd); 866 576 577 + if (orig->ae.xp_node) { 578 + rc = avc_xperms_populate(node, orig->ae.xp_node); 579 + if (rc) { 580 + kmem_cache_free(avc_node_cachep, node); 581 + goto out_unlock; 582 + } 583 + } 584 + 867 585 switch (event) { 868 586 case AVC_CALLBACK_GRANT: 869 587 node->ae.avd.allowed |= perms; 588 + if (node->ae.xp_node && (flags & AVC_EXTENDED_PERMS)) 589 + avc_xperms_allow_perm(node->ae.xp_node, driver, xperm); 870 590 break; 871 591 case AVC_CALLBACK_TRY_REVOKE: 872 592 case AVC_CALLBACK_REVOKE: ··· 893 593 break; 894 594 case AVC_CALLBACK_AUDITDENY_DISABLE: 895 595 node->ae.avd.auditdeny &= ~perms; 596 + break; 597 + case AVC_CALLBACK_ADD_XPERMS: 598 + avc_add_xperms_decision(node, xpd); 896 599 break; 897 600 } 898 601 avc_node_replace(node, orig); ··· 968 665 * results in a bigger stack frame. 969 666 */ 970 667 static noinline struct avc_node *avc_compute_av(u32 ssid, u32 tsid, 971 - u16 tclass, struct av_decision *avd) 668 + u16 tclass, struct av_decision *avd, 669 + struct avc_xperms_node *xp_node) 972 670 { 973 671 rcu_read_unlock(); 974 - security_compute_av(ssid, tsid, tclass, avd); 672 + INIT_LIST_HEAD(&xp_node->xpd_head); 673 + security_compute_av(ssid, tsid, tclass, avd, &xp_node->xp); 975 674 rcu_read_lock(); 976 - return avc_insert(ssid, tsid, tclass, avd); 675 + return avc_insert(ssid, tsid, tclass, avd, xp_node); 977 676 } 978 677 979 678 static noinline int avc_denied(u32 ssid, u32 tsid, 980 - u16 tclass, u32 requested, 981 - unsigned flags, 982 - struct av_decision *avd) 679 + u16 tclass, u32 requested, 680 + u8 driver, u8 xperm, unsigned flags, 681 + struct av_decision *avd) 983 682 { 984 683 if (flags & AVC_STRICT) 985 684 return -EACCES; ··· 989 684 if (selinux_enforcing && !(avd->flags & AVD_FLAGS_PERMISSIVE)) 990 685 return -EACCES; 991 686 992 - avc_update_node(AVC_CALLBACK_GRANT, requested, ssid, 993 - tsid, tclass, avd->seqno); 687 + avc_update_node(AVC_CALLBACK_GRANT, requested, driver, xperm, ssid, 688 + tsid, tclass, avd->seqno, NULL, flags); 994 689 return 0; 995 690 } 996 691 692 + /* 693 + * The avc extended permissions logic adds an additional 256 bits of 694 + * permissions to an avc node when extended permissions for that node are 695 + * specified in the avtab. If the additional 256 permissions is not adequate, 696 + * as-is the case with ioctls, then multiple may be chained together and the 697 + * driver field is used to specify which set contains the permission. 698 + */ 699 + int avc_has_extended_perms(u32 ssid, u32 tsid, u16 tclass, u32 requested, 700 + u8 driver, u8 xperm, struct common_audit_data *ad) 701 + { 702 + struct avc_node *node; 703 + struct av_decision avd; 704 + u32 denied; 705 + struct extended_perms_decision local_xpd; 706 + struct extended_perms_decision *xpd = NULL; 707 + struct extended_perms_data allowed; 708 + struct extended_perms_data auditallow; 709 + struct extended_perms_data dontaudit; 710 + struct avc_xperms_node local_xp_node; 711 + struct avc_xperms_node *xp_node; 712 + int rc = 0, rc2; 713 + 714 + xp_node = &local_xp_node; 715 + BUG_ON(!requested); 716 + 717 + rcu_read_lock(); 718 + 719 + node = avc_lookup(ssid, tsid, tclass); 720 + if (unlikely(!node)) { 721 + node = avc_compute_av(ssid, tsid, tclass, &avd, xp_node); 722 + } else { 723 + memcpy(&avd, &node->ae.avd, sizeof(avd)); 724 + xp_node = node->ae.xp_node; 725 + } 726 + /* if extended permissions are not defined, only consider av_decision */ 727 + if (!xp_node || !xp_node->xp.len) 728 + goto decision; 729 + 730 + local_xpd.allowed = &allowed; 731 + local_xpd.auditallow = &auditallow; 732 + local_xpd.dontaudit = &dontaudit; 733 + 734 + xpd = avc_xperms_decision_lookup(driver, xp_node); 735 + if (unlikely(!xpd)) { 736 + /* 737 + * Compute the extended_perms_decision only if the driver 738 + * is flagged 739 + */ 740 + if (!security_xperm_test(xp_node->xp.drivers.p, driver)) { 741 + avd.allowed &= ~requested; 742 + goto decision; 743 + } 744 + rcu_read_unlock(); 745 + security_compute_xperms_decision(ssid, tsid, tclass, driver, 746 + &local_xpd); 747 + rcu_read_lock(); 748 + avc_update_node(AVC_CALLBACK_ADD_XPERMS, requested, driver, xperm, 749 + ssid, tsid, tclass, avd.seqno, &local_xpd, 0); 750 + } else { 751 + avc_quick_copy_xperms_decision(xperm, &local_xpd, xpd); 752 + } 753 + xpd = &local_xpd; 754 + 755 + if (!avc_xperms_has_perm(xpd, xperm, XPERMS_ALLOWED)) 756 + avd.allowed &= ~requested; 757 + 758 + decision: 759 + denied = requested & ~(avd.allowed); 760 + if (unlikely(denied)) 761 + rc = avc_denied(ssid, tsid, tclass, requested, driver, xperm, 762 + AVC_EXTENDED_PERMS, &avd); 763 + 764 + rcu_read_unlock(); 765 + 766 + rc2 = avc_xperms_audit(ssid, tsid, tclass, requested, 767 + &avd, xpd, xperm, rc, ad); 768 + if (rc2) 769 + return rc2; 770 + return rc; 771 + } 997 772 998 773 /** 999 774 * avc_has_perm_noaudit - Check permissions but perform no auditing. ··· 1101 716 struct av_decision *avd) 1102 717 { 1103 718 struct avc_node *node; 719 + struct avc_xperms_node xp_node; 1104 720 int rc = 0; 1105 721 u32 denied; 1106 722 ··· 1111 725 1112 726 node = avc_lookup(ssid, tsid, tclass); 1113 727 if (unlikely(!node)) 1114 - node = avc_compute_av(ssid, tsid, tclass, avd); 728 + node = avc_compute_av(ssid, tsid, tclass, avd, &xp_node); 1115 729 else 1116 730 memcpy(avd, &node->ae.avd, sizeof(*avd)); 1117 731 1118 732 denied = requested & ~(avd->allowed); 1119 733 if (unlikely(denied)) 1120 - rc = avc_denied(ssid, tsid, tclass, requested, flags, avd); 734 + rc = avc_denied(ssid, tsid, tclass, requested, 0, 0, flags, avd); 1121 735 1122 736 rcu_read_unlock(); 1123 737 return rc;
+97 -50
security/selinux/hooks.c
··· 254 254 struct inode_security_struct *isec = inode->i_security; 255 255 struct superblock_security_struct *sbsec = inode->i_sb->s_security; 256 256 257 - spin_lock(&sbsec->isec_lock); 258 - if (!list_empty(&isec->list)) 257 + /* 258 + * As not all inode security structures are in a list, we check for 259 + * empty list outside of the lock to make sure that we won't waste 260 + * time taking a lock doing nothing. 261 + * 262 + * The list_del_init() function can be safely called more than once. 263 + * It should not be possible for this function to be called with 264 + * concurrent list_add(), but for better safety against future changes 265 + * in the code, we use list_empty_careful() here. 266 + */ 267 + if (!list_empty_careful(&isec->list)) { 268 + spin_lock(&sbsec->isec_lock); 259 269 list_del_init(&isec->list); 260 - spin_unlock(&sbsec->isec_lock); 270 + spin_unlock(&sbsec->isec_lock); 271 + } 261 272 262 273 /* 263 274 * The inode may still be referenced in a path walk and ··· 1709 1698 return rc; 1710 1699 } 1711 1700 1701 + /* 1702 + * Determine the label for an inode that might be unioned. 1703 + */ 1704 + static int selinux_determine_inode_label(const struct inode *dir, 1705 + const struct qstr *name, 1706 + u16 tclass, 1707 + u32 *_new_isid) 1708 + { 1709 + const struct superblock_security_struct *sbsec = dir->i_sb->s_security; 1710 + const struct inode_security_struct *dsec = dir->i_security; 1711 + const struct task_security_struct *tsec = current_security(); 1712 + 1713 + if ((sbsec->flags & SE_SBINITIALIZED) && 1714 + (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)) { 1715 + *_new_isid = sbsec->mntpoint_sid; 1716 + } else if ((sbsec->flags & SBLABEL_MNT) && 1717 + tsec->create_sid) { 1718 + *_new_isid = tsec->create_sid; 1719 + } else { 1720 + return security_transition_sid(tsec->sid, dsec->sid, tclass, 1721 + name, _new_isid); 1722 + } 1723 + 1724 + return 0; 1725 + } 1726 + 1712 1727 /* Check whether a task can create a file. */ 1713 1728 static int may_create(struct inode *dir, 1714 1729 struct dentry *dentry, ··· 1751 1714 sbsec = dir->i_sb->s_security; 1752 1715 1753 1716 sid = tsec->sid; 1754 - newsid = tsec->create_sid; 1755 1717 1756 1718 ad.type = LSM_AUDIT_DATA_DENTRY; 1757 1719 ad.u.dentry = dentry; ··· 1761 1725 if (rc) 1762 1726 return rc; 1763 1727 1764 - if (!newsid || !(sbsec->flags & SBLABEL_MNT)) { 1765 - rc = security_transition_sid(sid, dsec->sid, tclass, 1766 - &dentry->d_name, &newsid); 1767 - if (rc) 1768 - return rc; 1769 - } 1728 + rc = selinux_determine_inode_label(dir, &dentry->d_name, tclass, 1729 + &newsid); 1730 + if (rc) 1731 + return rc; 1770 1732 1771 1733 rc = avc_has_perm(sid, newsid, tclass, FILE__CREATE, &ad); 1772 1734 if (rc) ··· 2738 2704 struct qstr *name, void **ctx, 2739 2705 u32 *ctxlen) 2740 2706 { 2741 - const struct cred *cred = current_cred(); 2742 - struct task_security_struct *tsec; 2743 - struct inode_security_struct *dsec; 2744 - struct superblock_security_struct *sbsec; 2745 - struct inode *dir = d_backing_inode(dentry->d_parent); 2746 2707 u32 newsid; 2747 2708 int rc; 2748 2709 2749 - tsec = cred->security; 2750 - dsec = dir->i_security; 2751 - sbsec = dir->i_sb->s_security; 2752 - 2753 - if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) { 2754 - newsid = tsec->create_sid; 2755 - } else { 2756 - rc = security_transition_sid(tsec->sid, dsec->sid, 2757 - inode_mode_to_security_class(mode), 2758 - name, 2759 - &newsid); 2760 - if (rc) { 2761 - printk(KERN_WARNING 2762 - "%s: security_transition_sid failed, rc=%d\n", 2763 - __func__, -rc); 2764 - return rc; 2765 - } 2766 - } 2710 + rc = selinux_determine_inode_label(d_inode(dentry->d_parent), name, 2711 + inode_mode_to_security_class(mode), 2712 + &newsid); 2713 + if (rc) 2714 + return rc; 2767 2715 2768 2716 return security_sid_to_context(newsid, (char **)ctx, ctxlen); 2769 2717 } ··· 2768 2752 sid = tsec->sid; 2769 2753 newsid = tsec->create_sid; 2770 2754 2771 - if ((sbsec->flags & SE_SBINITIALIZED) && 2772 - (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)) 2773 - newsid = sbsec->mntpoint_sid; 2774 - else if (!newsid || !(sbsec->flags & SBLABEL_MNT)) { 2775 - rc = security_transition_sid(sid, dsec->sid, 2776 - inode_mode_to_security_class(inode->i_mode), 2777 - qstr, &newsid); 2778 - if (rc) { 2779 - printk(KERN_WARNING "%s: " 2780 - "security_transition_sid failed, rc=%d (dev=%s " 2781 - "ino=%ld)\n", 2782 - __func__, 2783 - -rc, inode->i_sb->s_id, inode->i_ino); 2784 - return rc; 2785 - } 2786 - } 2755 + rc = selinux_determine_inode_label( 2756 + dir, qstr, 2757 + inode_mode_to_security_class(inode->i_mode), 2758 + &newsid); 2759 + if (rc) 2760 + return rc; 2787 2761 2788 2762 /* Possibly defer initialization to selinux_complete_init. */ 2789 2763 if (sbsec->flags & SE_SBINITIALIZED) { ··· 3234 3228 file_free_security(file); 3235 3229 } 3236 3230 3231 + /* 3232 + * Check whether a task has the ioctl permission and cmd 3233 + * operation to an inode. 3234 + */ 3235 + int ioctl_has_perm(const struct cred *cred, struct file *file, 3236 + u32 requested, u16 cmd) 3237 + { 3238 + struct common_audit_data ad; 3239 + struct file_security_struct *fsec = file->f_security; 3240 + struct inode *inode = file_inode(file); 3241 + struct inode_security_struct *isec = inode->i_security; 3242 + struct lsm_ioctlop_audit ioctl; 3243 + u32 ssid = cred_sid(cred); 3244 + int rc; 3245 + u8 driver = cmd >> 8; 3246 + u8 xperm = cmd & 0xff; 3247 + 3248 + ad.type = LSM_AUDIT_DATA_IOCTL_OP; 3249 + ad.u.op = &ioctl; 3250 + ad.u.op->cmd = cmd; 3251 + ad.u.op->path = file->f_path; 3252 + 3253 + if (ssid != fsec->sid) { 3254 + rc = avc_has_perm(ssid, fsec->sid, 3255 + SECCLASS_FD, 3256 + FD__USE, 3257 + &ad); 3258 + if (rc) 3259 + goto out; 3260 + } 3261 + 3262 + if (unlikely(IS_PRIVATE(inode))) 3263 + return 0; 3264 + 3265 + rc = avc_has_extended_perms(ssid, isec->sid, isec->sclass, 3266 + requested, driver, xperm, &ad); 3267 + out: 3268 + return rc; 3269 + } 3270 + 3237 3271 static int selinux_file_ioctl(struct file *file, unsigned int cmd, 3238 3272 unsigned long arg) 3239 3273 { ··· 3316 3270 * to the file's ioctl() function. 3317 3271 */ 3318 3272 default: 3319 - error = file_has_perm(cred, file, FILE__IOCTL); 3273 + error = ioctl_has_perm(cred, file, FILE__IOCTL, (u16) cmd); 3320 3274 } 3321 3275 return error; 3322 3276 } ··· 4566 4520 4567 4521 sksec->peer_sid = SECINITSID_UNLABELED; 4568 4522 sksec->sid = SECINITSID_UNLABELED; 4523 + sksec->sclass = SECCLASS_SOCKET; 4569 4524 selinux_netlbl_sk_security_reset(sksec); 4570 4525 sk->sk_security = sksec; 4571 4526
+6
security/selinux/include/avc.h
··· 143 143 } 144 144 145 145 #define AVC_STRICT 1 /* Ignore permissive mode. */ 146 + #define AVC_EXTENDED_PERMS 2 /* update extended permissions */ 146 147 int avc_has_perm_noaudit(u32 ssid, u32 tsid, 147 148 u16 tclass, u32 requested, 148 149 unsigned flags, ··· 157 156 struct common_audit_data *auditdata, 158 157 int flags); 159 158 159 + int avc_has_extended_perms(u32 ssid, u32 tsid, u16 tclass, u32 requested, 160 + u8 driver, u8 perm, struct common_audit_data *ad); 161 + 162 + 160 163 u32 avc_policy_seqno(void); 161 164 162 165 #define AVC_CALLBACK_GRANT 1 ··· 171 166 #define AVC_CALLBACK_AUDITALLOW_DISABLE 32 172 167 #define AVC_CALLBACK_AUDITDENY_ENABLE 64 173 168 #define AVC_CALLBACK_AUDITDENY_DISABLE 128 169 + #define AVC_CALLBACK_ADD_XPERMS 256 174 170 175 171 int avc_add_callback(int (*callback)(u32 event), u32 events); 176 172
+30 -2
security/selinux/include/security.h
··· 35 35 #define POLICYDB_VERSION_NEW_OBJECT_DEFAULTS 27 36 36 #define POLICYDB_VERSION_DEFAULT_TYPE 28 37 37 #define POLICYDB_VERSION_CONSTRAINT_NAMES 29 38 + #define POLICYDB_VERSION_XPERMS_IOCTL 30 38 39 39 40 /* Range of policy versions we understand*/ 40 41 #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE 41 42 #ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX 42 43 #define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE 43 44 #else 44 - #define POLICYDB_VERSION_MAX POLICYDB_VERSION_CONSTRAINT_NAMES 45 + #define POLICYDB_VERSION_MAX POLICYDB_VERSION_XPERMS_IOCTL 45 46 #endif 46 47 47 48 /* Mask for just the mount related flags */ ··· 110 109 u32 flags; 111 110 }; 112 111 112 + #define XPERMS_ALLOWED 1 113 + #define XPERMS_AUDITALLOW 2 114 + #define XPERMS_DONTAUDIT 4 115 + 116 + #define security_xperm_set(perms, x) (perms[x >> 5] |= 1 << (x & 0x1f)) 117 + #define security_xperm_test(perms, x) (1 & (perms[x >> 5] >> (x & 0x1f))) 118 + struct extended_perms_data { 119 + u32 p[8]; 120 + }; 121 + 122 + struct extended_perms_decision { 123 + u8 used; 124 + u8 driver; 125 + struct extended_perms_data *allowed; 126 + struct extended_perms_data *auditallow; 127 + struct extended_perms_data *dontaudit; 128 + }; 129 + 130 + struct extended_perms { 131 + u16 len; /* length associated decision chain */ 132 + struct extended_perms_data drivers; /* flag drivers that are used */ 133 + }; 134 + 113 135 /* definitions of av_decision.flags */ 114 136 #define AVD_FLAGS_PERMISSIVE 0x0001 115 137 116 138 void security_compute_av(u32 ssid, u32 tsid, 117 - u16 tclass, struct av_decision *avd); 139 + u16 tclass, struct av_decision *avd, 140 + struct extended_perms *xperms); 141 + 142 + void security_compute_xperms_decision(u32 ssid, u32 tsid, u16 tclass, 143 + u8 driver, struct extended_perms_decision *xpermd); 118 144 119 145 void security_compute_av_user(u32 ssid, u32 tsid, 120 146 u16 tclass, struct av_decision *avd);
+90 -14
security/selinux/ss/avtab.c
··· 24 24 #include "policydb.h" 25 25 26 26 static struct kmem_cache *avtab_node_cachep; 27 + static struct kmem_cache *avtab_xperms_cachep; 27 28 28 29 /* Based on MurmurHash3, written by Austin Appleby and placed in the 29 30 * public domain. ··· 71 70 struct avtab_key *key, struct avtab_datum *datum) 72 71 { 73 72 struct avtab_node *newnode; 73 + struct avtab_extended_perms *xperms; 74 74 newnode = kmem_cache_zalloc(avtab_node_cachep, GFP_KERNEL); 75 75 if (newnode == NULL) 76 76 return NULL; 77 77 newnode->key = *key; 78 - newnode->datum = *datum; 78 + 79 + if (key->specified & AVTAB_XPERMS) { 80 + xperms = kmem_cache_zalloc(avtab_xperms_cachep, GFP_KERNEL); 81 + if (xperms == NULL) { 82 + kmem_cache_free(avtab_node_cachep, newnode); 83 + return NULL; 84 + } 85 + *xperms = *(datum->u.xperms); 86 + newnode->datum.u.xperms = xperms; 87 + } else { 88 + newnode->datum.u.data = datum->u.data; 89 + } 90 + 79 91 if (prev) { 80 92 newnode->next = prev->next; 81 93 prev->next = newnode; ··· 121 107 if (key->source_type == cur->key.source_type && 122 108 key->target_type == cur->key.target_type && 123 109 key->target_class == cur->key.target_class && 124 - (specified & cur->key.specified)) 110 + (specified & cur->key.specified)) { 111 + /* extended perms may not be unique */ 112 + if (specified & AVTAB_XPERMS) 113 + break; 125 114 return -EEXIST; 115 + } 126 116 if (key->source_type < cur->key.source_type) 127 117 break; 128 118 if (key->source_type == cur->key.source_type && ··· 289 271 while (cur) { 290 272 temp = cur; 291 273 cur = cur->next; 274 + if (temp->key.specified & AVTAB_XPERMS) 275 + kmem_cache_free(avtab_xperms_cachep, 276 + temp->datum.u.xperms); 292 277 kmem_cache_free(avtab_node_cachep, temp); 293 278 } 294 279 } ··· 380 359 AVTAB_AUDITALLOW, 381 360 AVTAB_TRANSITION, 382 361 AVTAB_CHANGE, 383 - AVTAB_MEMBER 362 + AVTAB_MEMBER, 363 + AVTAB_XPERMS_ALLOWED, 364 + AVTAB_XPERMS_AUDITALLOW, 365 + AVTAB_XPERMS_DONTAUDIT 384 366 }; 385 367 386 368 int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, ··· 393 369 { 394 370 __le16 buf16[4]; 395 371 u16 enabled; 396 - __le32 buf32[7]; 397 372 u32 items, items2, val, vers = pol->policyvers; 398 373 struct avtab_key key; 399 374 struct avtab_datum datum; 375 + struct avtab_extended_perms xperms; 376 + __le32 buf32[ARRAY_SIZE(xperms.perms.p)]; 400 377 int i, rc; 401 378 unsigned set; 402 379 ··· 454 429 printk(KERN_ERR "SELinux: avtab: entry has both access vectors and types\n"); 455 430 return -EINVAL; 456 431 } 432 + if (val & AVTAB_XPERMS) { 433 + printk(KERN_ERR "SELinux: avtab: entry has extended permissions\n"); 434 + return -EINVAL; 435 + } 457 436 458 437 for (i = 0; i < ARRAY_SIZE(spec_order); i++) { 459 438 if (val & spec_order[i]) { 460 439 key.specified = spec_order[i] | enabled; 461 - datum.data = le32_to_cpu(buf32[items++]); 440 + datum.u.data = le32_to_cpu(buf32[items++]); 462 441 rc = insertf(a, &key, &datum, p); 463 442 if (rc) 464 443 return rc; ··· 505 476 return -EINVAL; 506 477 } 507 478 508 - rc = next_entry(buf32, fp, sizeof(u32)); 509 - if (rc) { 510 - printk(KERN_ERR "SELinux: avtab: truncated entry\n"); 511 - return rc; 479 + if ((vers < POLICYDB_VERSION_XPERMS_IOCTL) && 480 + (key.specified & AVTAB_XPERMS)) { 481 + printk(KERN_ERR "SELinux: avtab: policy version %u does not " 482 + "support extended permissions rules and one " 483 + "was specified\n", vers); 484 + return -EINVAL; 485 + } else if (key.specified & AVTAB_XPERMS) { 486 + memset(&xperms, 0, sizeof(struct avtab_extended_perms)); 487 + rc = next_entry(&xperms.specified, fp, sizeof(u8)); 488 + if (rc) { 489 + printk(KERN_ERR "SELinux: avtab: truncated entry\n"); 490 + return rc; 491 + } 492 + rc = next_entry(&xperms.driver, fp, sizeof(u8)); 493 + if (rc) { 494 + printk(KERN_ERR "SELinux: avtab: truncated entry\n"); 495 + return rc; 496 + } 497 + rc = next_entry(buf32, fp, sizeof(u32)*ARRAY_SIZE(xperms.perms.p)); 498 + if (rc) { 499 + printk(KERN_ERR "SELinux: avtab: truncated entry\n"); 500 + return rc; 501 + } 502 + for (i = 0; i < ARRAY_SIZE(xperms.perms.p); i++) 503 + xperms.perms.p[i] = le32_to_cpu(buf32[i]); 504 + datum.u.xperms = &xperms; 505 + } else { 506 + rc = next_entry(buf32, fp, sizeof(u32)); 507 + if (rc) { 508 + printk(KERN_ERR "SELinux: avtab: truncated entry\n"); 509 + return rc; 510 + } 511 + datum.u.data = le32_to_cpu(*buf32); 512 512 } 513 - datum.data = le32_to_cpu(*buf32); 514 513 if ((key.specified & AVTAB_TYPE) && 515 - !policydb_type_isvalid(pol, datum.data)) { 514 + !policydb_type_isvalid(pol, datum.u.data)) { 516 515 printk(KERN_ERR "SELinux: avtab: invalid type\n"); 517 516 return -EINVAL; 518 517 } ··· 600 543 int avtab_write_item(struct policydb *p, struct avtab_node *cur, void *fp) 601 544 { 602 545 __le16 buf16[4]; 603 - __le32 buf32[1]; 546 + __le32 buf32[ARRAY_SIZE(cur->datum.u.xperms->perms.p)]; 604 547 int rc; 548 + unsigned int i; 605 549 606 550 buf16[0] = cpu_to_le16(cur->key.source_type); 607 551 buf16[1] = cpu_to_le16(cur->key.target_type); ··· 611 553 rc = put_entry(buf16, sizeof(u16), 4, fp); 612 554 if (rc) 613 555 return rc; 614 - buf32[0] = cpu_to_le32(cur->datum.data); 615 - rc = put_entry(buf32, sizeof(u32), 1, fp); 556 + 557 + if (cur->key.specified & AVTAB_XPERMS) { 558 + rc = put_entry(&cur->datum.u.xperms->specified, sizeof(u8), 1, fp); 559 + if (rc) 560 + return rc; 561 + rc = put_entry(&cur->datum.u.xperms->driver, sizeof(u8), 1, fp); 562 + if (rc) 563 + return rc; 564 + for (i = 0; i < ARRAY_SIZE(cur->datum.u.xperms->perms.p); i++) 565 + buf32[i] = cpu_to_le32(cur->datum.u.xperms->perms.p[i]); 566 + rc = put_entry(buf32, sizeof(u32), 567 + ARRAY_SIZE(cur->datum.u.xperms->perms.p), fp); 568 + } else { 569 + buf32[0] = cpu_to_le32(cur->datum.u.data); 570 + rc = put_entry(buf32, sizeof(u32), 1, fp); 571 + } 616 572 if (rc) 617 573 return rc; 618 574 return 0; ··· 660 588 avtab_node_cachep = kmem_cache_create("avtab_node", 661 589 sizeof(struct avtab_node), 662 590 0, SLAB_PANIC, NULL); 591 + avtab_xperms_cachep = kmem_cache_create("avtab_extended_perms", 592 + sizeof(struct avtab_extended_perms), 593 + 0, SLAB_PANIC, NULL); 663 594 } 664 595 665 596 void avtab_cache_destroy(void) 666 597 { 667 598 kmem_cache_destroy(avtab_node_cachep); 599 + kmem_cache_destroy(avtab_xperms_cachep); 668 600 }
+32 -1
security/selinux/ss/avtab.h
··· 23 23 #ifndef _SS_AVTAB_H_ 24 24 #define _SS_AVTAB_H_ 25 25 26 + #include "security.h" 26 27 #include <linux/flex_array.h> 27 28 28 29 struct avtab_key { ··· 38 37 #define AVTAB_MEMBER 0x0020 39 38 #define AVTAB_CHANGE 0x0040 40 39 #define AVTAB_TYPE (AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE) 40 + /* extended permissions */ 41 + #define AVTAB_XPERMS_ALLOWED 0x0100 42 + #define AVTAB_XPERMS_AUDITALLOW 0x0200 43 + #define AVTAB_XPERMS_DONTAUDIT 0x0400 44 + #define AVTAB_XPERMS (AVTAB_XPERMS_ALLOWED | \ 45 + AVTAB_XPERMS_AUDITALLOW | \ 46 + AVTAB_XPERMS_DONTAUDIT) 41 47 #define AVTAB_ENABLED_OLD 0x80000000 /* reserved for used in cond_avtab */ 42 48 #define AVTAB_ENABLED 0x8000 /* reserved for used in cond_avtab */ 43 49 u16 specified; /* what field is specified */ 44 50 }; 45 51 52 + /* 53 + * For operations that require more than the 32 permissions provided by the avc 54 + * extended permissions may be used to provide 256 bits of permissions. 55 + */ 56 + struct avtab_extended_perms { 57 + /* These are not flags. All 256 values may be used */ 58 + #define AVTAB_XPERMS_IOCTLFUNCTION 0x01 59 + #define AVTAB_XPERMS_IOCTLDRIVER 0x02 60 + /* extension of the avtab_key specified */ 61 + u8 specified; /* ioctl, netfilter, ... */ 62 + /* 63 + * if 256 bits is not adequate as is often the case with ioctls, then 64 + * multiple extended perms may be used and the driver field 65 + * specifies which permissions are included. 66 + */ 67 + u8 driver; 68 + /* 256 bits of permissions */ 69 + struct extended_perms_data perms; 70 + }; 71 + 46 72 struct avtab_datum { 47 - u32 data; /* access vector or type value */ 73 + union { 74 + u32 data; /* access vector or type value */ 75 + struct avtab_extended_perms *xperms; 76 + } u; 48 77 }; 49 78 50 79 struct avtab_node {
+30 -8
security/selinux/ss/conditional.c
··· 15 15 16 16 #include "security.h" 17 17 #include "conditional.h" 18 + #include "services.h" 18 19 19 20 /* 20 21 * cond_evaluate_expr evaluates a conditional expr ··· 613 612 614 613 return 0; 615 614 } 616 - /* Determine whether additional permissions are granted by the conditional 617 - * av table, and if so, add them to the result 618 - */ 619 - void cond_compute_av(struct avtab *ctab, struct avtab_key *key, struct av_decision *avd) 615 + 616 + void cond_compute_xperms(struct avtab *ctab, struct avtab_key *key, 617 + struct extended_perms_decision *xpermd) 620 618 { 621 619 struct avtab_node *node; 622 620 623 - if (!ctab || !key || !avd) 621 + if (!ctab || !key || !xpermd) 622 + return; 623 + 624 + for (node = avtab_search_node(ctab, key); node; 625 + node = avtab_search_node_next(node, key->specified)) { 626 + if (node->key.specified & AVTAB_ENABLED) 627 + services_compute_xperms_decision(xpermd, node); 628 + } 629 + return; 630 + 631 + } 632 + /* Determine whether additional permissions are granted by the conditional 633 + * av table, and if so, add them to the result 634 + */ 635 + void cond_compute_av(struct avtab *ctab, struct avtab_key *key, 636 + struct av_decision *avd, struct extended_perms *xperms) 637 + { 638 + struct avtab_node *node; 639 + 640 + if (!ctab || !key || !avd || !xperms) 624 641 return; 625 642 626 643 for (node = avtab_search_node(ctab, key); node; 627 644 node = avtab_search_node_next(node, key->specified)) { 628 645 if ((u16)(AVTAB_ALLOWED|AVTAB_ENABLED) == 629 646 (node->key.specified & (AVTAB_ALLOWED|AVTAB_ENABLED))) 630 - avd->allowed |= node->datum.data; 647 + avd->allowed |= node->datum.u.data; 631 648 if ((u16)(AVTAB_AUDITDENY|AVTAB_ENABLED) == 632 649 (node->key.specified & (AVTAB_AUDITDENY|AVTAB_ENABLED))) 633 650 /* Since a '0' in an auditdeny mask represents a ··· 653 634 * the '&' operand to ensure that all '0's in the mask 654 635 * are retained (much unlike the allow and auditallow cases). 655 636 */ 656 - avd->auditdeny &= node->datum.data; 637 + avd->auditdeny &= node->datum.u.data; 657 638 if ((u16)(AVTAB_AUDITALLOW|AVTAB_ENABLED) == 658 639 (node->key.specified & (AVTAB_AUDITALLOW|AVTAB_ENABLED))) 659 - avd->auditallow |= node->datum.data; 640 + avd->auditallow |= node->datum.u.data; 641 + if ((node->key.specified & AVTAB_ENABLED) && 642 + (node->key.specified & AVTAB_XPERMS)) 643 + services_compute_xperms_drivers(xperms, node); 660 644 } 661 645 return; 662 646 }
+4 -2
security/selinux/ss/conditional.h
··· 73 73 int cond_write_bool(void *key, void *datum, void *ptr); 74 74 int cond_write_list(struct policydb *p, struct cond_node *list, void *fp); 75 75 76 - void cond_compute_av(struct avtab *ctab, struct avtab_key *key, struct av_decision *avd); 77 - 76 + void cond_compute_av(struct avtab *ctab, struct avtab_key *key, 77 + struct av_decision *avd, struct extended_perms *xperms); 78 + void cond_compute_xperms(struct avtab *ctab, struct avtab_key *key, 79 + struct extended_perms_decision *xpermd); 78 80 int evaluate_cond_node(struct policydb *p, struct cond_node *node); 79 81 80 82 #endif /* _CONDITIONAL_H_ */
+5
security/selinux/ss/policydb.c
··· 148 148 .sym_num = SYM_NUM, 149 149 .ocon_num = OCON_NUM, 150 150 }, 151 + { 152 + .version = POLICYDB_VERSION_XPERMS_IOCTL, 153 + .sym_num = SYM_NUM, 154 + .ocon_num = OCON_NUM, 155 + }, 151 156 }; 152 157 153 158 static struct policydb_compat_info *policydb_lookup_compat(int version)
+193 -20
security/selinux/ss/services.c
··· 93 93 u32 *scontext_len); 94 94 95 95 static void context_struct_compute_av(struct context *scontext, 96 - struct context *tcontext, 97 - u16 tclass, 98 - struct av_decision *avd); 96 + struct context *tcontext, 97 + u16 tclass, 98 + struct av_decision *avd, 99 + struct extended_perms *xperms); 99 100 100 101 struct selinux_mapping { 101 102 u16 value; /* policy value */ ··· 566 565 context_struct_compute_av(&lo_scontext, 567 566 tcontext, 568 567 tclass, 569 - &lo_avd); 568 + &lo_avd, 569 + NULL); 570 570 if ((lo_avd.allowed & avd->allowed) == avd->allowed) 571 571 return; /* no masked permission */ 572 572 masked = ~lo_avd.allowed & avd->allowed; ··· 582 580 context_struct_compute_av(scontext, 583 581 &lo_tcontext, 584 582 tclass, 585 - &lo_avd); 583 + &lo_avd, 584 + NULL); 586 585 if ((lo_avd.allowed & avd->allowed) == avd->allowed) 587 586 return; /* no masked permission */ 588 587 masked = ~lo_avd.allowed & avd->allowed; ··· 599 596 context_struct_compute_av(&lo_scontext, 600 597 &lo_tcontext, 601 598 tclass, 602 - &lo_avd); 599 + &lo_avd, 600 + NULL); 603 601 if ((lo_avd.allowed & avd->allowed) == avd->allowed) 604 602 return; /* no masked permission */ 605 603 masked = ~lo_avd.allowed & avd->allowed; ··· 617 613 } 618 614 619 615 /* 620 - * Compute access vectors based on a context structure pair for 621 - * the permissions in a particular class. 616 + * flag which drivers have permissions 617 + * only looking for ioctl based extended permssions 618 + */ 619 + void services_compute_xperms_drivers( 620 + struct extended_perms *xperms, 621 + struct avtab_node *node) 622 + { 623 + unsigned int i; 624 + 625 + if (node->datum.u.xperms->specified == AVTAB_XPERMS_IOCTLDRIVER) { 626 + /* if one or more driver has all permissions allowed */ 627 + for (i = 0; i < ARRAY_SIZE(xperms->drivers.p); i++) 628 + xperms->drivers.p[i] |= node->datum.u.xperms->perms.p[i]; 629 + } else if (node->datum.u.xperms->specified == AVTAB_XPERMS_IOCTLFUNCTION) { 630 + /* if allowing permissions within a driver */ 631 + security_xperm_set(xperms->drivers.p, 632 + node->datum.u.xperms->driver); 633 + } 634 + 635 + /* If no ioctl commands are allowed, ignore auditallow and auditdeny */ 636 + if (node->key.specified & AVTAB_XPERMS_ALLOWED) 637 + xperms->len = 1; 638 + } 639 + 640 + /* 641 + * Compute access vectors and extended permissions based on a context 642 + * structure pair for the permissions in a particular class. 622 643 */ 623 644 static void context_struct_compute_av(struct context *scontext, 624 - struct context *tcontext, 625 - u16 tclass, 626 - struct av_decision *avd) 645 + struct context *tcontext, 646 + u16 tclass, 647 + struct av_decision *avd, 648 + struct extended_perms *xperms) 627 649 { 628 650 struct constraint_node *constraint; 629 651 struct role_allow *ra; ··· 663 633 avd->allowed = 0; 664 634 avd->auditallow = 0; 665 635 avd->auditdeny = 0xffffffff; 636 + if (xperms) { 637 + memset(&xperms->drivers, 0, sizeof(xperms->drivers)); 638 + xperms->len = 0; 639 + } 666 640 667 641 if (unlikely(!tclass || tclass > policydb.p_classes.nprim)) { 668 642 if (printk_ratelimit()) ··· 681 647 * this permission check, then use it. 682 648 */ 683 649 avkey.target_class = tclass; 684 - avkey.specified = AVTAB_AV; 650 + avkey.specified = AVTAB_AV | AVTAB_XPERMS; 685 651 sattr = flex_array_get(policydb.type_attr_map_array, scontext->type - 1); 686 652 BUG_ON(!sattr); 687 653 tattr = flex_array_get(policydb.type_attr_map_array, tcontext->type - 1); ··· 694 660 node; 695 661 node = avtab_search_node_next(node, avkey.specified)) { 696 662 if (node->key.specified == AVTAB_ALLOWED) 697 - avd->allowed |= node->datum.data; 663 + avd->allowed |= node->datum.u.data; 698 664 else if (node->key.specified == AVTAB_AUDITALLOW) 699 - avd->auditallow |= node->datum.data; 665 + avd->auditallow |= node->datum.u.data; 700 666 else if (node->key.specified == AVTAB_AUDITDENY) 701 - avd->auditdeny &= node->datum.data; 667 + avd->auditdeny &= node->datum.u.data; 668 + else if (xperms && (node->key.specified & AVTAB_XPERMS)) 669 + services_compute_xperms_drivers(xperms, node); 702 670 } 703 671 704 672 /* Check conditional av table for additional permissions */ 705 - cond_compute_av(&policydb.te_cond_avtab, &avkey, avd); 673 + cond_compute_av(&policydb.te_cond_avtab, &avkey, 674 + avd, xperms); 706 675 707 676 } 708 677 } ··· 936 899 avd->flags = 0; 937 900 } 938 901 902 + void services_compute_xperms_decision(struct extended_perms_decision *xpermd, 903 + struct avtab_node *node) 904 + { 905 + unsigned int i; 906 + 907 + if (node->datum.u.xperms->specified == AVTAB_XPERMS_IOCTLFUNCTION) { 908 + if (xpermd->driver != node->datum.u.xperms->driver) 909 + return; 910 + } else if (node->datum.u.xperms->specified == AVTAB_XPERMS_IOCTLDRIVER) { 911 + if (!security_xperm_test(node->datum.u.xperms->perms.p, 912 + xpermd->driver)) 913 + return; 914 + } else { 915 + BUG(); 916 + } 917 + 918 + if (node->key.specified == AVTAB_XPERMS_ALLOWED) { 919 + xpermd->used |= XPERMS_ALLOWED; 920 + if (node->datum.u.xperms->specified == AVTAB_XPERMS_IOCTLDRIVER) { 921 + memset(xpermd->allowed->p, 0xff, 922 + sizeof(xpermd->allowed->p)); 923 + } 924 + if (node->datum.u.xperms->specified == AVTAB_XPERMS_IOCTLFUNCTION) { 925 + for (i = 0; i < ARRAY_SIZE(xpermd->allowed->p); i++) 926 + xpermd->allowed->p[i] |= 927 + node->datum.u.xperms->perms.p[i]; 928 + } 929 + } else if (node->key.specified == AVTAB_XPERMS_AUDITALLOW) { 930 + xpermd->used |= XPERMS_AUDITALLOW; 931 + if (node->datum.u.xperms->specified == AVTAB_XPERMS_IOCTLDRIVER) { 932 + memset(xpermd->auditallow->p, 0xff, 933 + sizeof(xpermd->auditallow->p)); 934 + } 935 + if (node->datum.u.xperms->specified == AVTAB_XPERMS_IOCTLFUNCTION) { 936 + for (i = 0; i < ARRAY_SIZE(xpermd->auditallow->p); i++) 937 + xpermd->auditallow->p[i] |= 938 + node->datum.u.xperms->perms.p[i]; 939 + } 940 + } else if (node->key.specified == AVTAB_XPERMS_DONTAUDIT) { 941 + xpermd->used |= XPERMS_DONTAUDIT; 942 + if (node->datum.u.xperms->specified == AVTAB_XPERMS_IOCTLDRIVER) { 943 + memset(xpermd->dontaudit->p, 0xff, 944 + sizeof(xpermd->dontaudit->p)); 945 + } 946 + if (node->datum.u.xperms->specified == AVTAB_XPERMS_IOCTLFUNCTION) { 947 + for (i = 0; i < ARRAY_SIZE(xpermd->dontaudit->p); i++) 948 + xpermd->dontaudit->p[i] |= 949 + node->datum.u.xperms->perms.p[i]; 950 + } 951 + } else { 952 + BUG(); 953 + } 954 + } 955 + 956 + void security_compute_xperms_decision(u32 ssid, 957 + u32 tsid, 958 + u16 orig_tclass, 959 + u8 driver, 960 + struct extended_perms_decision *xpermd) 961 + { 962 + u16 tclass; 963 + struct context *scontext, *tcontext; 964 + struct avtab_key avkey; 965 + struct avtab_node *node; 966 + struct ebitmap *sattr, *tattr; 967 + struct ebitmap_node *snode, *tnode; 968 + unsigned int i, j; 969 + 970 + xpermd->driver = driver; 971 + xpermd->used = 0; 972 + memset(xpermd->allowed->p, 0, sizeof(xpermd->allowed->p)); 973 + memset(xpermd->auditallow->p, 0, sizeof(xpermd->auditallow->p)); 974 + memset(xpermd->dontaudit->p, 0, sizeof(xpermd->dontaudit->p)); 975 + 976 + read_lock(&policy_rwlock); 977 + if (!ss_initialized) 978 + goto allow; 979 + 980 + scontext = sidtab_search(&sidtab, ssid); 981 + if (!scontext) { 982 + printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", 983 + __func__, ssid); 984 + goto out; 985 + } 986 + 987 + tcontext = sidtab_search(&sidtab, tsid); 988 + if (!tcontext) { 989 + printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", 990 + __func__, tsid); 991 + goto out; 992 + } 993 + 994 + tclass = unmap_class(orig_tclass); 995 + if (unlikely(orig_tclass && !tclass)) { 996 + if (policydb.allow_unknown) 997 + goto allow; 998 + goto out; 999 + } 1000 + 1001 + 1002 + if (unlikely(!tclass || tclass > policydb.p_classes.nprim)) { 1003 + pr_warn_ratelimited("SELinux: Invalid class %hu\n", tclass); 1004 + goto out; 1005 + } 1006 + 1007 + avkey.target_class = tclass; 1008 + avkey.specified = AVTAB_XPERMS; 1009 + sattr = flex_array_get(policydb.type_attr_map_array, 1010 + scontext->type - 1); 1011 + BUG_ON(!sattr); 1012 + tattr = flex_array_get(policydb.type_attr_map_array, 1013 + tcontext->type - 1); 1014 + BUG_ON(!tattr); 1015 + ebitmap_for_each_positive_bit(sattr, snode, i) { 1016 + ebitmap_for_each_positive_bit(tattr, tnode, j) { 1017 + avkey.source_type = i + 1; 1018 + avkey.target_type = j + 1; 1019 + for (node = avtab_search_node(&policydb.te_avtab, &avkey); 1020 + node; 1021 + node = avtab_search_node_next(node, avkey.specified)) 1022 + services_compute_xperms_decision(xpermd, node); 1023 + 1024 + cond_compute_xperms(&policydb.te_cond_avtab, 1025 + &avkey, xpermd); 1026 + } 1027 + } 1028 + out: 1029 + read_unlock(&policy_rwlock); 1030 + return; 1031 + allow: 1032 + memset(xpermd->allowed->p, 0xff, sizeof(xpermd->allowed->p)); 1033 + goto out; 1034 + } 939 1035 940 1036 /** 941 1037 * security_compute_av - Compute access vector decisions. ··· 1076 906 * @tsid: target security identifier 1077 907 * @tclass: target security class 1078 908 * @avd: access vector decisions 909 + * @xperms: extended permissions 1079 910 * 1080 911 * Compute a set of access vector decisions based on the 1081 912 * SID pair (@ssid, @tsid) for the permissions in @tclass. ··· 1084 913 void security_compute_av(u32 ssid, 1085 914 u32 tsid, 1086 915 u16 orig_tclass, 1087 - struct av_decision *avd) 916 + struct av_decision *avd, 917 + struct extended_perms *xperms) 1088 918 { 1089 919 u16 tclass; 1090 920 struct context *scontext = NULL, *tcontext = NULL; 1091 921 1092 922 read_lock(&policy_rwlock); 1093 923 avd_init(avd); 924 + xperms->len = 0; 1094 925 if (!ss_initialized) 1095 926 goto allow; 1096 927 ··· 1120 947 goto allow; 1121 948 goto out; 1122 949 } 1123 - context_struct_compute_av(scontext, tcontext, tclass, avd); 950 + context_struct_compute_av(scontext, tcontext, tclass, avd, xperms); 1124 951 map_decision(orig_tclass, avd, policydb.allow_unknown); 1125 952 out: 1126 953 read_unlock(&policy_rwlock); ··· 1166 993 goto out; 1167 994 } 1168 995 1169 - context_struct_compute_av(scontext, tcontext, tclass, avd); 996 + context_struct_compute_av(scontext, tcontext, tclass, avd, NULL); 1170 997 out: 1171 998 read_unlock(&policy_rwlock); 1172 999 return; ··· 1688 1515 1689 1516 if (avdatum) { 1690 1517 /* Use the type from the type transition/member/change rule. */ 1691 - newcontext.type = avdatum->data; 1518 + newcontext.type = avdatum->u.data; 1692 1519 } 1693 1520 1694 1521 /* if we have a objname this is a file trans check so check those rules */
+6
security/selinux/ss/services.h
··· 11 11 12 12 extern struct policydb policydb; 13 13 14 + void services_compute_xperms_drivers(struct extended_perms *xperms, 15 + struct avtab_node *node); 16 + 17 + void services_compute_xperms_decision(struct extended_perms_decision *xpermd, 18 + struct avtab_node *node); 19 + 14 20 #endif /* _SS_SERVICES_H_ */ 15 21
+57 -9
security/smack/smack.h
··· 17 17 #include <linux/spinlock.h> 18 18 #include <linux/lsm_hooks.h> 19 19 #include <linux/in.h> 20 + #if IS_ENABLED(CONFIG_IPV6) 21 + #include <linux/in6.h> 22 + #endif /* CONFIG_IPV6 */ 20 23 #include <net/netlabel.h> 21 24 #include <linux/list.h> 22 25 #include <linux/rculist.h> 23 26 #include <linux/lsm_audit.h> 27 + 28 + /* 29 + * Use IPv6 port labeling if IPv6 is enabled and secmarks 30 + * are not being used. 31 + */ 32 + #if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER) 33 + #define SMACK_IPV6_PORT_LABELING 1 34 + #endif 35 + 36 + #if IS_ENABLED(CONFIG_IPV6) && defined(CONFIG_SECURITY_SMACK_NETFILTER) 37 + #define SMACK_IPV6_SECMARK_LABELING 1 38 + #endif 24 39 25 40 /* 26 41 * Smack labels were limited to 23 characters for a long time. ··· 133 118 }; 134 119 135 120 /* 136 - * An entry in the table identifying hosts. 121 + * An entry in the table identifying IPv4 hosts. 137 122 */ 138 - struct smk_netlbladdr { 123 + struct smk_net4addr { 139 124 struct list_head list; 140 - struct sockaddr_in smk_host; /* network address */ 125 + struct in_addr smk_host; /* network address */ 141 126 struct in_addr smk_mask; /* network mask */ 127 + int smk_masks; /* mask size */ 142 128 struct smack_known *smk_label; /* label */ 143 129 }; 144 130 131 + #if IS_ENABLED(CONFIG_IPV6) 132 + /* 133 + * An entry in the table identifying IPv6 hosts. 134 + */ 135 + struct smk_net6addr { 136 + struct list_head list; 137 + struct in6_addr smk_host; /* network address */ 138 + struct in6_addr smk_mask; /* network mask */ 139 + int smk_masks; /* mask size */ 140 + struct smack_known *smk_label; /* label */ 141 + }; 142 + #endif /* CONFIG_IPV6 */ 143 + 144 + #ifdef SMACK_IPV6_PORT_LABELING 145 145 /* 146 146 * An entry in the table identifying ports. 147 147 */ ··· 167 137 struct smack_known *smk_in; /* inbound label */ 168 138 struct smack_known *smk_out; /* outgoing label */ 169 139 }; 140 + #endif /* SMACK_IPV6_PORT_LABELING */ 170 141 171 142 struct smack_onlycap { 172 143 struct list_head list; 173 144 struct smack_known *smk_label; 145 + }; 146 + 147 + /* Super block security struct flags for mount options */ 148 + #define FSDEFAULT_MNT 0x01 149 + #define FSFLOOR_MNT 0x02 150 + #define FSHAT_MNT 0x04 151 + #define FSROOT_MNT 0x08 152 + #define FSTRANS_MNT 0x10 153 + 154 + #define NUM_SMK_MNT_OPTS 5 155 + 156 + enum { 157 + Opt_error = -1, 158 + Opt_fsdefault = 1, 159 + Opt_fsfloor = 2, 160 + Opt_fshat = 3, 161 + Opt_fsroot = 4, 162 + Opt_fstransmute = 5, 174 163 }; 175 164 176 165 /* ··· 201 152 #define SMK_FSROOT "smackfsroot=" 202 153 #define SMK_FSTRANS "smackfstransmute=" 203 154 155 + #define SMACK_DELETE_OPTION "-DELETE" 204 156 #define SMACK_CIPSO_OPTION "-CIPSO" 205 157 206 158 /* ··· 284 234 struct smack_audit_data sad; 285 235 #endif 286 236 }; 287 - /* 288 - * These functions are in smack_lsm.c 289 - */ 290 - struct inode_smack *new_inode_smack(struct smack_known *); 291 237 292 238 /* 293 239 * These functions are in smack_access.c ··· 313 267 #ifdef CONFIG_SECURITY_SMACK_BRINGUP 314 268 extern struct smack_known *smack_unconfined; 315 269 #endif 316 - extern struct smack_known smack_cipso_option; 317 270 extern int smack_ptrace_rule; 318 271 319 272 extern struct smack_known smack_known_floor; ··· 324 279 325 280 extern struct mutex smack_known_lock; 326 281 extern struct list_head smack_known_list; 327 - extern struct list_head smk_netlbladdr_list; 282 + extern struct list_head smk_net4addr_list; 283 + #if IS_ENABLED(CONFIG_IPV6) 284 + extern struct list_head smk_net6addr_list; 285 + #endif /* CONFIG_IPV6 */ 328 286 329 287 extern struct mutex smack_onlycap_lock; 330 288 extern struct list_head smack_onlycap_list;
+6
security/smack/smack_access.c
··· 639 639 struct smack_known *skp = smk_of_current(); 640 640 struct smack_onlycap *sop; 641 641 642 + /* 643 + * All kernel tasks are privileged 644 + */ 645 + if (unlikely(current->flags & PF_KTHREAD)) 646 + return 1; 647 + 642 648 if (!capable(cap)) 643 649 return 0; 644 650
+398 -121
security/smack/smack_lsm.c
··· 41 41 #include <linux/msg.h> 42 42 #include <linux/shm.h> 43 43 #include <linux/binfmts.h> 44 + #include <linux/parser.h> 44 45 #include "smack.h" 45 46 46 47 #define TRANS_TRUE "TRUE" ··· 51 50 #define SMK_RECEIVING 1 52 51 #define SMK_SENDING 2 53 52 54 - #if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER) 53 + #ifdef SMACK_IPV6_PORT_LABELING 55 54 LIST_HEAD(smk_ipv6_port_list); 56 - #endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */ 55 + #endif 57 56 static struct kmem_cache *smack_inode_cache; 58 57 int smack_enabled; 58 + 59 + static const match_table_t smk_mount_tokens = { 60 + {Opt_fsdefault, SMK_FSDEFAULT "%s"}, 61 + {Opt_fsfloor, SMK_FSFLOOR "%s"}, 62 + {Opt_fshat, SMK_FSHAT "%s"}, 63 + {Opt_fsroot, SMK_FSROOT "%s"}, 64 + {Opt_fstransmute, SMK_FSTRANS "%s"}, 65 + {Opt_error, NULL}, 66 + }; 59 67 60 68 #ifdef CONFIG_SECURITY_SMACK_BRINGUP 61 69 static char *smk_bu_mess[] = { ··· 291 281 * 292 282 * Returns the new blob or NULL if there's no memory available 293 283 */ 294 - struct inode_smack *new_inode_smack(struct smack_known *skp) 284 + static struct inode_smack *new_inode_smack(struct smack_known *skp) 295 285 { 296 286 struct inode_smack *isp; 297 287 ··· 587 577 } 588 578 589 579 /** 590 - * smack_sb_kern_mount - Smack specific mount processing 580 + * smack_parse_opts_str - parse Smack specific mount options 581 + * @options: mount options string 582 + * @opts: where to store converted mount opts 583 + * 584 + * Returns 0 on success or -ENOMEM on error. 585 + * 586 + * converts Smack specific mount options to generic security option format 587 + */ 588 + static int smack_parse_opts_str(char *options, 589 + struct security_mnt_opts *opts) 590 + { 591 + char *p; 592 + char *fsdefault = NULL; 593 + char *fsfloor = NULL; 594 + char *fshat = NULL; 595 + char *fsroot = NULL; 596 + char *fstransmute = NULL; 597 + int rc = -ENOMEM; 598 + int num_mnt_opts = 0; 599 + int token; 600 + 601 + opts->num_mnt_opts = 0; 602 + 603 + if (!options) 604 + return 0; 605 + 606 + while ((p = strsep(&options, ",")) != NULL) { 607 + substring_t args[MAX_OPT_ARGS]; 608 + 609 + if (!*p) 610 + continue; 611 + 612 + token = match_token(p, smk_mount_tokens, args); 613 + 614 + switch (token) { 615 + case Opt_fsdefault: 616 + if (fsdefault) 617 + goto out_opt_err; 618 + fsdefault = match_strdup(&args[0]); 619 + if (!fsdefault) 620 + goto out_err; 621 + break; 622 + case Opt_fsfloor: 623 + if (fsfloor) 624 + goto out_opt_err; 625 + fsfloor = match_strdup(&args[0]); 626 + if (!fsfloor) 627 + goto out_err; 628 + break; 629 + case Opt_fshat: 630 + if (fshat) 631 + goto out_opt_err; 632 + fshat = match_strdup(&args[0]); 633 + if (!fshat) 634 + goto out_err; 635 + break; 636 + case Opt_fsroot: 637 + if (fsroot) 638 + goto out_opt_err; 639 + fsroot = match_strdup(&args[0]); 640 + if (!fsroot) 641 + goto out_err; 642 + break; 643 + case Opt_fstransmute: 644 + if (fstransmute) 645 + goto out_opt_err; 646 + fstransmute = match_strdup(&args[0]); 647 + if (!fstransmute) 648 + goto out_err; 649 + break; 650 + default: 651 + rc = -EINVAL; 652 + pr_warn("Smack: unknown mount option\n"); 653 + goto out_err; 654 + } 655 + } 656 + 657 + opts->mnt_opts = kcalloc(NUM_SMK_MNT_OPTS, sizeof(char *), GFP_ATOMIC); 658 + if (!opts->mnt_opts) 659 + goto out_err; 660 + 661 + opts->mnt_opts_flags = kcalloc(NUM_SMK_MNT_OPTS, sizeof(int), 662 + GFP_ATOMIC); 663 + if (!opts->mnt_opts_flags) { 664 + kfree(opts->mnt_opts); 665 + goto out_err; 666 + } 667 + 668 + if (fsdefault) { 669 + opts->mnt_opts[num_mnt_opts] = fsdefault; 670 + opts->mnt_opts_flags[num_mnt_opts++] = FSDEFAULT_MNT; 671 + } 672 + if (fsfloor) { 673 + opts->mnt_opts[num_mnt_opts] = fsfloor; 674 + opts->mnt_opts_flags[num_mnt_opts++] = FSFLOOR_MNT; 675 + } 676 + if (fshat) { 677 + opts->mnt_opts[num_mnt_opts] = fshat; 678 + opts->mnt_opts_flags[num_mnt_opts++] = FSHAT_MNT; 679 + } 680 + if (fsroot) { 681 + opts->mnt_opts[num_mnt_opts] = fsroot; 682 + opts->mnt_opts_flags[num_mnt_opts++] = FSROOT_MNT; 683 + } 684 + if (fstransmute) { 685 + opts->mnt_opts[num_mnt_opts] = fstransmute; 686 + opts->mnt_opts_flags[num_mnt_opts++] = FSTRANS_MNT; 687 + } 688 + 689 + opts->num_mnt_opts = num_mnt_opts; 690 + return 0; 691 + 692 + out_opt_err: 693 + rc = -EINVAL; 694 + pr_warn("Smack: duplicate mount options\n"); 695 + 696 + out_err: 697 + kfree(fsdefault); 698 + kfree(fsfloor); 699 + kfree(fshat); 700 + kfree(fsroot); 701 + kfree(fstransmute); 702 + return rc; 703 + } 704 + 705 + /** 706 + * smack_set_mnt_opts - set Smack specific mount options 591 707 * @sb: the file system superblock 592 - * @flags: the mount flags 593 - * @data: the smack mount options 708 + * @opts: Smack mount options 709 + * @kern_flags: mount option from kernel space or user space 710 + * @set_kern_flags: where to store converted mount opts 594 711 * 595 712 * Returns 0 on success, an error code on failure 713 + * 714 + * Allow filesystems with binary mount data to explicitly set Smack mount 715 + * labels. 596 716 */ 597 - static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) 717 + static int smack_set_mnt_opts(struct super_block *sb, 718 + struct security_mnt_opts *opts, 719 + unsigned long kern_flags, 720 + unsigned long *set_kern_flags) 598 721 { 599 722 struct dentry *root = sb->s_root; 600 723 struct inode *inode = d_backing_inode(root); 601 724 struct superblock_smack *sp = sb->s_security; 602 725 struct inode_smack *isp; 603 726 struct smack_known *skp; 604 - char *op; 605 - char *commap; 727 + int i; 728 + int num_opts = opts->num_mnt_opts; 606 729 int transmute = 0; 607 - int specified = 0; 608 730 609 731 if (sp->smk_initialized) 610 732 return 0; 611 733 612 734 sp->smk_initialized = 1; 613 735 614 - for (op = data; op != NULL; op = commap) { 615 - commap = strchr(op, ','); 616 - if (commap != NULL) 617 - *commap++ = '\0'; 618 - 619 - if (strncmp(op, SMK_FSHAT, strlen(SMK_FSHAT)) == 0) { 620 - op += strlen(SMK_FSHAT); 621 - skp = smk_import_entry(op, 0); 622 - if (IS_ERR(skp)) 623 - return PTR_ERR(skp); 624 - sp->smk_hat = skp; 625 - specified = 1; 626 - 627 - } else if (strncmp(op, SMK_FSFLOOR, strlen(SMK_FSFLOOR)) == 0) { 628 - op += strlen(SMK_FSFLOOR); 629 - skp = smk_import_entry(op, 0); 630 - if (IS_ERR(skp)) 631 - return PTR_ERR(skp); 632 - sp->smk_floor = skp; 633 - specified = 1; 634 - 635 - } else if (strncmp(op, SMK_FSDEFAULT, 636 - strlen(SMK_FSDEFAULT)) == 0) { 637 - op += strlen(SMK_FSDEFAULT); 638 - skp = smk_import_entry(op, 0); 736 + for (i = 0; i < num_opts; i++) { 737 + switch (opts->mnt_opts_flags[i]) { 738 + case FSDEFAULT_MNT: 739 + skp = smk_import_entry(opts->mnt_opts[i], 0); 639 740 if (IS_ERR(skp)) 640 741 return PTR_ERR(skp); 641 742 sp->smk_default = skp; 642 - specified = 1; 643 - 644 - } else if (strncmp(op, SMK_FSROOT, strlen(SMK_FSROOT)) == 0) { 645 - op += strlen(SMK_FSROOT); 646 - skp = smk_import_entry(op, 0); 743 + break; 744 + case FSFLOOR_MNT: 745 + skp = smk_import_entry(opts->mnt_opts[i], 0); 746 + if (IS_ERR(skp)) 747 + return PTR_ERR(skp); 748 + sp->smk_floor = skp; 749 + break; 750 + case FSHAT_MNT: 751 + skp = smk_import_entry(opts->mnt_opts[i], 0); 752 + if (IS_ERR(skp)) 753 + return PTR_ERR(skp); 754 + sp->smk_hat = skp; 755 + break; 756 + case FSROOT_MNT: 757 + skp = smk_import_entry(opts->mnt_opts[i], 0); 647 758 if (IS_ERR(skp)) 648 759 return PTR_ERR(skp); 649 760 sp->smk_root = skp; 650 - specified = 1; 651 - 652 - } else if (strncmp(op, SMK_FSTRANS, strlen(SMK_FSTRANS)) == 0) { 653 - op += strlen(SMK_FSTRANS); 654 - skp = smk_import_entry(op, 0); 761 + break; 762 + case FSTRANS_MNT: 763 + skp = smk_import_entry(opts->mnt_opts[i], 0); 655 764 if (IS_ERR(skp)) 656 765 return PTR_ERR(skp); 657 766 sp->smk_root = skp; 658 767 transmute = 1; 659 - specified = 1; 768 + break; 769 + default: 770 + break; 660 771 } 661 772 } 662 773 ··· 785 654 /* 786 655 * Unprivileged mounts don't get to specify Smack values. 787 656 */ 788 - if (specified) 657 + if (num_opts) 789 658 return -EPERM; 790 659 /* 791 660 * Unprivileged mounts get root and default from the caller. ··· 794 663 sp->smk_root = skp; 795 664 sp->smk_default = skp; 796 665 } 666 + 797 667 /* 798 668 * Initialize the root inode. 799 669 */ ··· 811 679 isp->smk_flags |= SMK_INODE_TRANSMUTE; 812 680 813 681 return 0; 682 + } 683 + 684 + /** 685 + * smack_sb_kern_mount - Smack specific mount processing 686 + * @sb: the file system superblock 687 + * @flags: the mount flags 688 + * @data: the smack mount options 689 + * 690 + * Returns 0 on success, an error code on failure 691 + */ 692 + static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) 693 + { 694 + int rc = 0; 695 + char *options = data; 696 + struct security_mnt_opts opts; 697 + 698 + security_init_mnt_opts(&opts); 699 + 700 + if (!options) 701 + goto out; 702 + 703 + rc = smack_parse_opts_str(options, &opts); 704 + if (rc) 705 + goto out_err; 706 + 707 + out: 708 + rc = smack_set_mnt_opts(sb, &opts, 0, NULL); 709 + 710 + out_err: 711 + security_free_mnt_opts(&opts); 712 + return rc; 814 713 } 815 714 816 715 /** ··· 2276 2113 } 2277 2114 2278 2115 /** 2279 - * smack_host_label - check host based restrictions 2116 + * smack_ipv4host_label - check host based restrictions 2280 2117 * @sip: the object end 2281 2118 * 2282 2119 * looks for host based access restrictions ··· 2287 2124 * 2288 2125 * Returns the label of the far end or NULL if it's not special. 2289 2126 */ 2290 - static struct smack_known *smack_host_label(struct sockaddr_in *sip) 2127 + static struct smack_known *smack_ipv4host_label(struct sockaddr_in *sip) 2291 2128 { 2292 - struct smk_netlbladdr *snp; 2129 + struct smk_net4addr *snp; 2293 2130 struct in_addr *siap = &sip->sin_addr; 2294 2131 2295 2132 if (siap->s_addr == 0) 2296 2133 return NULL; 2297 2134 2298 - list_for_each_entry_rcu(snp, &smk_netlbladdr_list, list) 2135 + list_for_each_entry_rcu(snp, &smk_net4addr_list, list) 2136 + /* 2137 + * we break after finding the first match because 2138 + * the list is sorted from longest to shortest mask 2139 + * so we have found the most specific match 2140 + */ 2141 + if (snp->smk_host.s_addr == 2142 + (siap->s_addr & snp->smk_mask.s_addr)) 2143 + return snp->smk_label; 2144 + 2145 + return NULL; 2146 + } 2147 + 2148 + #if IS_ENABLED(CONFIG_IPV6) 2149 + /* 2150 + * smk_ipv6_localhost - Check for local ipv6 host address 2151 + * @sip: the address 2152 + * 2153 + * Returns boolean true if this is the localhost address 2154 + */ 2155 + static bool smk_ipv6_localhost(struct sockaddr_in6 *sip) 2156 + { 2157 + __be16 *be16p = (__be16 *)&sip->sin6_addr; 2158 + __be32 *be32p = (__be32 *)&sip->sin6_addr; 2159 + 2160 + if (be32p[0] == 0 && be32p[1] == 0 && be32p[2] == 0 && be16p[6] == 0 && 2161 + ntohs(be16p[7]) == 1) 2162 + return true; 2163 + return false; 2164 + } 2165 + 2166 + /** 2167 + * smack_ipv6host_label - check host based restrictions 2168 + * @sip: the object end 2169 + * 2170 + * looks for host based access restrictions 2171 + * 2172 + * This version will only be appropriate for really small sets of single label 2173 + * hosts. The caller is responsible for ensuring that the RCU read lock is 2174 + * taken before calling this function. 2175 + * 2176 + * Returns the label of the far end or NULL if it's not special. 2177 + */ 2178 + static struct smack_known *smack_ipv6host_label(struct sockaddr_in6 *sip) 2179 + { 2180 + struct smk_net6addr *snp; 2181 + struct in6_addr *sap = &sip->sin6_addr; 2182 + int i; 2183 + int found = 0; 2184 + 2185 + /* 2186 + * It's local. Don't look for a host label. 2187 + */ 2188 + if (smk_ipv6_localhost(sip)) 2189 + return NULL; 2190 + 2191 + list_for_each_entry_rcu(snp, &smk_net6addr_list, list) { 2299 2192 /* 2300 2193 * we break after finding the first match because 2301 2194 * the list is sorted from longest to shortest mask 2302 2195 * so we have found the most specific match 2303 2196 */ 2304 - if ((&snp->smk_host.sin_addr)->s_addr == 2305 - (siap->s_addr & (&snp->smk_mask)->s_addr)) { 2306 - /* we have found the special CIPSO option */ 2307 - if (snp->smk_label == &smack_cipso_option) 2308 - return NULL; 2309 - return snp->smk_label; 2197 + for (found = 1, i = 0; i < 8; i++) { 2198 + /* 2199 + * If the label is NULL the entry has 2200 + * been renounced. Ignore it. 2201 + */ 2202 + if (snp->smk_label == NULL) 2203 + continue; 2204 + if ((sap->s6_addr16[i] & snp->smk_mask.s6_addr16[i]) != 2205 + snp->smk_host.s6_addr16[i]) { 2206 + found = 0; 2207 + break; 2208 + } 2310 2209 } 2210 + if (found) 2211 + return snp->smk_label; 2212 + } 2311 2213 2312 2214 return NULL; 2313 2215 } 2216 + #endif /* CONFIG_IPV6 */ 2314 2217 2315 2218 /** 2316 2219 * smack_netlabel - Set the secattr on a socket ··· 2440 2211 struct smk_audit_info ad; 2441 2212 2442 2213 rcu_read_lock(); 2443 - hkp = smack_host_label(sap); 2214 + hkp = smack_ipv4host_label(sap); 2444 2215 if (hkp != NULL) { 2445 2216 #ifdef CONFIG_AUDIT 2446 2217 struct lsm_network_audit net; ··· 2465 2236 return smack_netlabel(sk, sk_lbl); 2466 2237 } 2467 2238 2468 - #if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER) 2239 + #if IS_ENABLED(CONFIG_IPV6) 2240 + /** 2241 + * smk_ipv6_check - check Smack access 2242 + * @subject: subject Smack label 2243 + * @object: object Smack label 2244 + * @address: address 2245 + * @act: the action being taken 2246 + * 2247 + * Check an IPv6 access 2248 + */ 2249 + static int smk_ipv6_check(struct smack_known *subject, 2250 + struct smack_known *object, 2251 + struct sockaddr_in6 *address, int act) 2252 + { 2253 + #ifdef CONFIG_AUDIT 2254 + struct lsm_network_audit net; 2255 + #endif 2256 + struct smk_audit_info ad; 2257 + int rc; 2258 + 2259 + #ifdef CONFIG_AUDIT 2260 + smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); 2261 + ad.a.u.net->family = PF_INET6; 2262 + ad.a.u.net->dport = ntohs(address->sin6_port); 2263 + if (act == SMK_RECEIVING) 2264 + ad.a.u.net->v6info.saddr = address->sin6_addr; 2265 + else 2266 + ad.a.u.net->v6info.daddr = address->sin6_addr; 2267 + #endif 2268 + rc = smk_access(subject, object, MAY_WRITE, &ad); 2269 + rc = smk_bu_note("IPv6 check", subject, object, MAY_WRITE, rc); 2270 + return rc; 2271 + } 2272 + #endif /* CONFIG_IPV6 */ 2273 + 2274 + #ifdef SMACK_IPV6_PORT_LABELING 2469 2275 /** 2470 2276 * smk_ipv6_port_label - Smack port access table management 2471 2277 * @sock: socket ··· 2584 2320 static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address, 2585 2321 int act) 2586 2322 { 2587 - __be16 *bep; 2588 - __be32 *be32p; 2589 2323 struct smk_port_label *spp; 2590 2324 struct socket_smack *ssp = sk->sk_security; 2591 - struct smack_known *skp; 2592 - unsigned short port = 0; 2325 + struct smack_known *skp = NULL; 2326 + unsigned short port; 2593 2327 struct smack_known *object; 2594 - struct smk_audit_info ad; 2595 - int rc; 2596 - #ifdef CONFIG_AUDIT 2597 - struct lsm_network_audit net; 2598 - #endif 2599 2328 2600 2329 if (act == SMK_RECEIVING) { 2601 - skp = smack_net_ambient; 2330 + skp = smack_ipv6host_label(address); 2602 2331 object = ssp->smk_in; 2603 2332 } else { 2604 2333 skp = ssp->smk_out; 2605 - object = smack_net_ambient; 2334 + object = smack_ipv6host_label(address); 2606 2335 } 2607 2336 2608 2337 /* 2609 - * Get the IP address and port from the address. 2338 + * The other end is a single label host. 2610 2339 */ 2611 - port = ntohs(address->sin6_port); 2612 - bep = (__be16 *)(&address->sin6_addr); 2613 - be32p = (__be32 *)(&address->sin6_addr); 2340 + if (skp != NULL && object != NULL) 2341 + return smk_ipv6_check(skp, object, address, act); 2342 + if (skp == NULL) 2343 + skp = smack_net_ambient; 2344 + if (object == NULL) 2345 + object = smack_net_ambient; 2614 2346 2615 2347 /* 2616 2348 * It's remote, so port lookup does no good. 2617 2349 */ 2618 - if (be32p[0] || be32p[1] || be32p[2] || bep[6] || ntohs(bep[7]) != 1) 2619 - goto auditout; 2350 + if (!smk_ipv6_localhost(address)) 2351 + return smk_ipv6_check(skp, object, address, act); 2620 2352 2621 2353 /* 2622 2354 * It's local so the send check has to have passed. 2623 2355 */ 2624 - if (act == SMK_RECEIVING) { 2625 - skp = &smack_known_web; 2626 - goto auditout; 2627 - } 2356 + if (act == SMK_RECEIVING) 2357 + return 0; 2628 2358 2359 + port = ntohs(address->sin6_port); 2629 2360 list_for_each_entry(spp, &smk_ipv6_port_list, list) { 2630 2361 if (spp->smk_port != port) 2631 2362 continue; ··· 2630 2371 break; 2631 2372 } 2632 2373 2633 - auditout: 2634 - 2635 - #ifdef CONFIG_AUDIT 2636 - smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); 2637 - ad.a.u.net->family = sk->sk_family; 2638 - ad.a.u.net->dport = port; 2639 - if (act == SMK_RECEIVING) 2640 - ad.a.u.net->v6info.saddr = address->sin6_addr; 2641 - else 2642 - ad.a.u.net->v6info.daddr = address->sin6_addr; 2643 - #endif 2644 - rc = smk_access(skp, object, MAY_WRITE, &ad); 2645 - rc = smk_bu_note("IPv6 port check", skp, object, MAY_WRITE, rc); 2646 - return rc; 2374 + return smk_ipv6_check(skp, object, address, act); 2647 2375 } 2648 - #endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */ 2376 + #endif /* SMACK_IPV6_PORT_LABELING */ 2649 2377 2650 2378 /** 2651 2379 * smack_inode_setsecurity - set smack xattrs ··· 2693 2447 } else 2694 2448 return -EOPNOTSUPP; 2695 2449 2696 - #if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER) 2450 + #ifdef SMACK_IPV6_PORT_LABELING 2697 2451 if (sock->sk->sk_family == PF_INET6) 2698 2452 smk_ipv6_port_label(sock, NULL); 2699 - #endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */ 2453 + #endif 2700 2454 2701 2455 return 0; 2702 2456 } ··· 2738 2492 return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET); 2739 2493 } 2740 2494 2741 - #ifndef CONFIG_SECURITY_SMACK_NETFILTER 2495 + #ifdef SMACK_IPV6_PORT_LABELING 2742 2496 /** 2743 2497 * smack_socket_bind - record port binding information. 2744 2498 * @sock: the socket ··· 2752 2506 static int smack_socket_bind(struct socket *sock, struct sockaddr *address, 2753 2507 int addrlen) 2754 2508 { 2755 - #if IS_ENABLED(CONFIG_IPV6) 2756 2509 if (sock->sk != NULL && sock->sk->sk_family == PF_INET6) 2757 2510 smk_ipv6_port_label(sock, address); 2758 - #endif 2759 - 2760 2511 return 0; 2761 2512 } 2762 - #endif /* !CONFIG_SECURITY_SMACK_NETFILTER */ 2513 + #endif /* SMACK_IPV6_PORT_LABELING */ 2763 2514 2764 2515 /** 2765 2516 * smack_socket_connect - connect access check ··· 2772 2529 int addrlen) 2773 2530 { 2774 2531 int rc = 0; 2532 + #if IS_ENABLED(CONFIG_IPV6) 2533 + struct sockaddr_in6 *sip = (struct sockaddr_in6 *)sap; 2534 + #endif 2535 + #ifdef SMACK_IPV6_SECMARK_LABELING 2536 + struct smack_known *rsp; 2537 + struct socket_smack *ssp = sock->sk->sk_security; 2538 + #endif 2775 2539 2776 2540 if (sock->sk == NULL) 2777 2541 return 0; ··· 2792 2542 case PF_INET6: 2793 2543 if (addrlen < sizeof(struct sockaddr_in6)) 2794 2544 return -EINVAL; 2795 - #if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER) 2796 - rc = smk_ipv6_port_check(sock->sk, (struct sockaddr_in6 *)sap, 2545 + #ifdef SMACK_IPV6_SECMARK_LABELING 2546 + rsp = smack_ipv6host_label(sip); 2547 + if (rsp != NULL) 2548 + rc = smk_ipv6_check(ssp->smk_out, rsp, sip, 2797 2549 SMK_CONNECTING); 2798 - #endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */ 2550 + #endif 2551 + #ifdef SMACK_IPV6_PORT_LABELING 2552 + rc = smk_ipv6_port_check(sock->sk, sip, SMK_CONNECTING); 2553 + #endif 2799 2554 break; 2800 2555 } 2801 2556 return rc; ··· 3686 3431 int size) 3687 3432 { 3688 3433 struct sockaddr_in *sip = (struct sockaddr_in *) msg->msg_name; 3689 - #if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER) 3434 + #if IS_ENABLED(CONFIG_IPV6) 3690 3435 struct sockaddr_in6 *sap = (struct sockaddr_in6 *) msg->msg_name; 3691 - #endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */ 3436 + #endif 3437 + #ifdef SMACK_IPV6_SECMARK_LABELING 3438 + struct socket_smack *ssp = sock->sk->sk_security; 3439 + struct smack_known *rsp; 3440 + #endif 3692 3441 int rc = 0; 3693 3442 3694 3443 /* ··· 3706 3447 rc = smack_netlabel_send(sock->sk, sip); 3707 3448 break; 3708 3449 case AF_INET6: 3709 - #if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER) 3450 + #ifdef SMACK_IPV6_SECMARK_LABELING 3451 + rsp = smack_ipv6host_label(sap); 3452 + if (rsp != NULL) 3453 + rc = smk_ipv6_check(ssp->smk_out, rsp, sap, 3454 + SMK_CONNECTING); 3455 + #endif 3456 + #ifdef SMACK_IPV6_PORT_LABELING 3710 3457 rc = smk_ipv6_port_check(sock->sk, sap, SMK_SENDING); 3711 - #endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */ 3458 + #endif 3712 3459 break; 3713 3460 } 3714 3461 return rc; ··· 3928 3663 proto = smk_skb_to_addr_ipv6(skb, &sadd); 3929 3664 if (proto != IPPROTO_UDP && proto != IPPROTO_TCP) 3930 3665 break; 3931 - #ifdef CONFIG_SECURITY_SMACK_NETFILTER 3666 + #ifdef SMACK_IPV6_SECMARK_LABELING 3932 3667 if (skb && skb->secmark != 0) 3933 3668 skp = smack_from_secid(skb->secmark); 3934 3669 else 3670 + skp = smack_ipv6host_label(&sadd); 3671 + if (skp == NULL) 3935 3672 skp = smack_net_ambient; 3936 3673 #ifdef CONFIG_AUDIT 3937 3674 smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); ··· 3944 3677 rc = smk_access(skp, ssp->smk_in, MAY_WRITE, &ad); 3945 3678 rc = smk_bu_note("IPv6 delivery", skp, ssp->smk_in, 3946 3679 MAY_WRITE, rc); 3947 - #else /* CONFIG_SECURITY_SMACK_NETFILTER */ 3680 + #endif /* SMACK_IPV6_SECMARK_LABELING */ 3681 + #ifdef SMACK_IPV6_PORT_LABELING 3948 3682 rc = smk_ipv6_port_check(sk, &sadd, SMK_RECEIVING); 3949 - #endif /* CONFIG_SECURITY_SMACK_NETFILTER */ 3683 + #endif /* SMACK_IPV6_PORT_LABELING */ 3950 3684 break; 3951 3685 #endif /* CONFIG_IPV6 */ 3952 3686 } ··· 4045 3777 } 4046 3778 netlbl_secattr_destroy(&secattr); 4047 3779 break; 4048 - #if IS_ENABLED(CONFIG_IPV6) 4049 3780 case PF_INET6: 4050 - #ifdef CONFIG_SECURITY_SMACK_NETFILTER 3781 + #ifdef SMACK_IPV6_SECMARK_LABELING 4051 3782 s = skb->secmark; 4052 - #endif /* CONFIG_SECURITY_SMACK_NETFILTER */ 3783 + #endif 4053 3784 break; 4054 - #endif /* CONFIG_IPV6 */ 4055 3785 } 4056 3786 *secid = s; 4057 3787 if (s == 0) ··· 4172 3906 hdr = ip_hdr(skb); 4173 3907 addr.sin_addr.s_addr = hdr->saddr; 4174 3908 rcu_read_lock(); 4175 - hskp = smack_host_label(&addr); 3909 + hskp = smack_ipv4host_label(&addr); 4176 3910 rcu_read_unlock(); 4177 3911 4178 3912 if (hskp == NULL) ··· 4520 4254 return 0; 4521 4255 } 4522 4256 4523 - struct security_hook_list smack_hooks[] = { 4257 + static struct security_hook_list smack_hooks[] = { 4524 4258 LSM_HOOK_INIT(ptrace_access_check, smack_ptrace_access_check), 4525 4259 LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme), 4526 4260 LSM_HOOK_INIT(syslog, smack_syslog), ··· 4530 4264 LSM_HOOK_INIT(sb_copy_data, smack_sb_copy_data), 4531 4265 LSM_HOOK_INIT(sb_kern_mount, smack_sb_kern_mount), 4532 4266 LSM_HOOK_INIT(sb_statfs, smack_sb_statfs), 4267 + LSM_HOOK_INIT(sb_set_mnt_opts, smack_set_mnt_opts), 4268 + LSM_HOOK_INIT(sb_parse_opts_str, smack_parse_opts_str), 4533 4269 4534 4270 LSM_HOOK_INIT(bprm_set_creds, smack_bprm_set_creds), 4535 4271 LSM_HOOK_INIT(bprm_committing_creds, smack_bprm_committing_creds), ··· 4624 4356 LSM_HOOK_INIT(unix_may_send, smack_unix_may_send), 4625 4357 4626 4358 LSM_HOOK_INIT(socket_post_create, smack_socket_post_create), 4627 - #ifndef CONFIG_SECURITY_SMACK_NETFILTER 4359 + #ifdef SMACK_IPV6_PORT_LABELING 4628 4360 LSM_HOOK_INIT(socket_bind, smack_socket_bind), 4629 - #endif /* CONFIG_SECURITY_SMACK_NETFILTER */ 4361 + #endif 4630 4362 LSM_HOOK_INIT(socket_connect, smack_socket_connect), 4631 4363 LSM_HOOK_INIT(socket_sendmsg, smack_socket_sendmsg), 4632 4364 LSM_HOOK_INIT(socket_sock_rcv_skb, smack_socket_sock_rcv_skb), ··· 4721 4453 return -ENOMEM; 4722 4454 } 4723 4455 4724 - printk(KERN_INFO "Smack: Initializing.\n"); 4456 + pr_info("Smack: Initializing.\n"); 4457 + #ifdef CONFIG_SECURITY_SMACK_NETFILTER 4458 + pr_info("Smack: Netfilter enabled.\n"); 4459 + #endif 4460 + #ifdef SMACK_IPV6_PORT_LABELING 4461 + pr_info("Smack: IPv6 port labeling enabled.\n"); 4462 + #endif 4463 + #ifdef SMACK_IPV6_SECMARK_LABELING 4464 + pr_info("Smack: IPv6 Netfilter enabled.\n"); 4465 + #endif 4725 4466 4726 4467 /* 4727 4468 * Set the security state for the initial task.
+354 -82
security/smack/smackfs.c
··· 29 29 #include <linux/magic.h> 30 30 #include "smack.h" 31 31 32 + #define BEBITS (sizeof(__be32) * 8) 32 33 /* 33 34 * smackfs pseudo filesystem. 34 35 */ ··· 41 40 SMK_DOI = 5, /* CIPSO DOI */ 42 41 SMK_DIRECT = 6, /* CIPSO level indicating direct label */ 43 42 SMK_AMBIENT = 7, /* internet ambient label */ 44 - SMK_NETLBLADDR = 8, /* single label hosts */ 43 + SMK_NET4ADDR = 8, /* single label hosts */ 45 44 SMK_ONLYCAP = 9, /* the only "capable" label */ 46 45 SMK_LOGGING = 10, /* logging */ 47 46 SMK_LOAD_SELF = 11, /* task specific rules */ ··· 58 57 #ifdef CONFIG_SECURITY_SMACK_BRINGUP 59 58 SMK_UNCONFINED = 22, /* define an unconfined label */ 60 59 #endif 60 + #if IS_ENABLED(CONFIG_IPV6) 61 + SMK_NET6ADDR = 23, /* single label IPv6 hosts */ 62 + #endif /* CONFIG_IPV6 */ 61 63 }; 62 64 63 65 /* ··· 68 64 */ 69 65 static DEFINE_MUTEX(smack_cipso_lock); 70 66 static DEFINE_MUTEX(smack_ambient_lock); 71 - static DEFINE_MUTEX(smk_netlbladdr_lock); 67 + static DEFINE_MUTEX(smk_net4addr_lock); 68 + #if IS_ENABLED(CONFIG_IPV6) 69 + static DEFINE_MUTEX(smk_net6addr_lock); 70 + #endif /* CONFIG_IPV6 */ 72 71 73 72 /* 74 73 * This is the "ambient" label for network traffic. ··· 125 118 * can write to the specified label. 126 119 */ 127 120 128 - LIST_HEAD(smk_netlbladdr_list); 121 + LIST_HEAD(smk_net4addr_list); 122 + #if IS_ENABLED(CONFIG_IPV6) 123 + LIST_HEAD(smk_net6addr_list); 124 + #endif /* CONFIG_IPV6 */ 129 125 130 126 /* 131 127 * Rule lists are maintained for each label. ··· 139 129 struct smack_rule *smk_rule; 140 130 }; 141 131 142 - LIST_HEAD(smack_rule_list); 132 + static LIST_HEAD(smack_rule_list); 143 133 144 134 struct smack_parsed_rule { 145 135 struct smack_known *smk_subject; ··· 149 139 }; 150 140 151 141 static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT; 152 - 153 - struct smack_known smack_cipso_option = { 154 - .smk_known = SMACK_CIPSO_OPTION, 155 - .smk_secid = 0, 156 - }; 157 142 158 143 /* 159 144 * Values for parsing cipso rules ··· 1052 1047 * Seq_file read operations for /smack/netlabel 1053 1048 */ 1054 1049 1055 - static void *netlbladdr_seq_start(struct seq_file *s, loff_t *pos) 1050 + static void *net4addr_seq_start(struct seq_file *s, loff_t *pos) 1056 1051 { 1057 - return smk_seq_start(s, pos, &smk_netlbladdr_list); 1052 + return smk_seq_start(s, pos, &smk_net4addr_list); 1058 1053 } 1059 1054 1060 - static void *netlbladdr_seq_next(struct seq_file *s, void *v, loff_t *pos) 1055 + static void *net4addr_seq_next(struct seq_file *s, void *v, loff_t *pos) 1061 1056 { 1062 - return smk_seq_next(s, v, pos, &smk_netlbladdr_list); 1057 + return smk_seq_next(s, v, pos, &smk_net4addr_list); 1063 1058 } 1064 - #define BEBITS (sizeof(__be32) * 8) 1065 1059 1066 1060 /* 1067 1061 * Print host/label pairs 1068 1062 */ 1069 - static int netlbladdr_seq_show(struct seq_file *s, void *v) 1063 + static int net4addr_seq_show(struct seq_file *s, void *v) 1070 1064 { 1071 1065 struct list_head *list = v; 1072 - struct smk_netlbladdr *skp = 1073 - list_entry_rcu(list, struct smk_netlbladdr, list); 1074 - unsigned char *hp = (char *) &skp->smk_host.sin_addr.s_addr; 1075 - int maskn; 1076 - u32 temp_mask = be32_to_cpu(skp->smk_mask.s_addr); 1066 + struct smk_net4addr *skp = 1067 + list_entry_rcu(list, struct smk_net4addr, list); 1068 + char *kp = SMACK_CIPSO_OPTION; 1077 1069 1078 - for (maskn = 0; temp_mask; temp_mask <<= 1, maskn++); 1079 - 1080 - seq_printf(s, "%u.%u.%u.%u/%d %s\n", 1081 - hp[0], hp[1], hp[2], hp[3], maskn, skp->smk_label->smk_known); 1070 + if (skp->smk_label != NULL) 1071 + kp = skp->smk_label->smk_known; 1072 + seq_printf(s, "%pI4/%d %s\n", &skp->smk_host.s_addr, 1073 + skp->smk_masks, kp); 1082 1074 1083 1075 return 0; 1084 1076 } 1085 1077 1086 - static const struct seq_operations netlbladdr_seq_ops = { 1087 - .start = netlbladdr_seq_start, 1088 - .next = netlbladdr_seq_next, 1089 - .show = netlbladdr_seq_show, 1078 + static const struct seq_operations net4addr_seq_ops = { 1079 + .start = net4addr_seq_start, 1080 + .next = net4addr_seq_next, 1081 + .show = net4addr_seq_show, 1090 1082 .stop = smk_seq_stop, 1091 1083 }; 1092 1084 1093 1085 /** 1094 - * smk_open_netlbladdr - open() for /smack/netlabel 1086 + * smk_open_net4addr - open() for /smack/netlabel 1095 1087 * @inode: inode structure representing file 1096 1088 * @file: "netlabel" file pointer 1097 1089 * 1098 - * Connect our netlbladdr_seq_* operations with /smack/netlabel 1090 + * Connect our net4addr_seq_* operations with /smack/netlabel 1099 1091 * file_operations 1100 1092 */ 1101 - static int smk_open_netlbladdr(struct inode *inode, struct file *file) 1093 + static int smk_open_net4addr(struct inode *inode, struct file *file) 1102 1094 { 1103 - return seq_open(file, &netlbladdr_seq_ops); 1095 + return seq_open(file, &net4addr_seq_ops); 1104 1096 } 1105 1097 1106 1098 /** 1107 - * smk_netlbladdr_insert 1099 + * smk_net4addr_insert 1108 1100 * @new : netlabel to insert 1109 1101 * 1110 - * This helper insert netlabel in the smack_netlbladdrs list 1102 + * This helper insert netlabel in the smack_net4addrs list 1111 1103 * sorted by netmask length (longest to smallest) 1112 - * locked by &smk_netlbladdr_lock in smk_write_netlbladdr 1104 + * locked by &smk_net4addr_lock in smk_write_net4addr 1113 1105 * 1114 1106 */ 1115 - static void smk_netlbladdr_insert(struct smk_netlbladdr *new) 1107 + static void smk_net4addr_insert(struct smk_net4addr *new) 1116 1108 { 1117 - struct smk_netlbladdr *m, *m_next; 1109 + struct smk_net4addr *m; 1110 + struct smk_net4addr *m_next; 1118 1111 1119 - if (list_empty(&smk_netlbladdr_list)) { 1120 - list_add_rcu(&new->list, &smk_netlbladdr_list); 1112 + if (list_empty(&smk_net4addr_list)) { 1113 + list_add_rcu(&new->list, &smk_net4addr_list); 1121 1114 return; 1122 1115 } 1123 1116 1124 - m = list_entry_rcu(smk_netlbladdr_list.next, 1125 - struct smk_netlbladdr, list); 1117 + m = list_entry_rcu(smk_net4addr_list.next, 1118 + struct smk_net4addr, list); 1126 1119 1127 1120 /* the comparison '>' is a bit hacky, but works */ 1128 - if (new->smk_mask.s_addr > m->smk_mask.s_addr) { 1129 - list_add_rcu(&new->list, &smk_netlbladdr_list); 1121 + if (new->smk_masks > m->smk_masks) { 1122 + list_add_rcu(&new->list, &smk_net4addr_list); 1130 1123 return; 1131 1124 } 1132 1125 1133 - list_for_each_entry_rcu(m, &smk_netlbladdr_list, list) { 1134 - if (list_is_last(&m->list, &smk_netlbladdr_list)) { 1126 + list_for_each_entry_rcu(m, &smk_net4addr_list, list) { 1127 + if (list_is_last(&m->list, &smk_net4addr_list)) { 1135 1128 list_add_rcu(&new->list, &m->list); 1136 1129 return; 1137 1130 } 1138 1131 m_next = list_entry_rcu(m->list.next, 1139 - struct smk_netlbladdr, list); 1140 - if (new->smk_mask.s_addr > m_next->smk_mask.s_addr) { 1132 + struct smk_net4addr, list); 1133 + if (new->smk_masks > m_next->smk_masks) { 1141 1134 list_add_rcu(&new->list, &m->list); 1142 1135 return; 1143 1136 } ··· 1144 1141 1145 1142 1146 1143 /** 1147 - * smk_write_netlbladdr - write() for /smack/netlabel 1144 + * smk_write_net4addr - write() for /smack/netlabel 1148 1145 * @file: file pointer, not actually used 1149 1146 * @buf: where to get the data from 1150 1147 * @count: bytes sent 1151 1148 * @ppos: where to start 1152 1149 * 1153 - * Accepts only one netlbladdr per write call. 1150 + * Accepts only one net4addr per write call. 1154 1151 * Returns number of bytes written or error code, as appropriate 1155 1152 */ 1156 - static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf, 1153 + static ssize_t smk_write_net4addr(struct file *file, const char __user *buf, 1157 1154 size_t count, loff_t *ppos) 1158 1155 { 1159 - struct smk_netlbladdr *snp; 1156 + struct smk_net4addr *snp; 1160 1157 struct sockaddr_in newname; 1161 1158 char *smack; 1162 - struct smack_known *skp; 1159 + struct smack_known *skp = NULL; 1163 1160 char *data; 1164 1161 char *host = (char *)&newname.sin_addr.s_addr; 1165 1162 int rc; 1166 1163 struct netlbl_audit audit_info; 1167 1164 struct in_addr mask; 1168 1165 unsigned int m; 1166 + unsigned int masks; 1169 1167 int found; 1170 1168 u32 mask_bits = (1<<31); 1171 1169 __be32 nsa; ··· 1204 1200 data[count] = '\0'; 1205 1201 1206 1202 rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd/%u %s", 1207 - &host[0], &host[1], &host[2], &host[3], &m, smack); 1203 + &host[0], &host[1], &host[2], &host[3], &masks, smack); 1208 1204 if (rc != 6) { 1209 1205 rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd %s", 1210 1206 &host[0], &host[1], &host[2], &host[3], smack); ··· 1213 1209 goto free_out; 1214 1210 } 1215 1211 m = BEBITS; 1212 + masks = 32; 1216 1213 } 1217 - if (m > BEBITS) { 1214 + if (masks > BEBITS) { 1218 1215 rc = -EINVAL; 1219 1216 goto free_out; 1220 1217 } ··· 1230 1225 goto free_out; 1231 1226 } 1232 1227 } else { 1233 - /* check known options */ 1234 - if (strcmp(smack, smack_cipso_option.smk_known) == 0) 1235 - skp = &smack_cipso_option; 1236 - else { 1228 + /* 1229 + * Only the -CIPSO option is supported for IPv4 1230 + */ 1231 + if (strcmp(smack, SMACK_CIPSO_OPTION) != 0) { 1237 1232 rc = -EINVAL; 1238 1233 goto free_out; 1239 1234 } 1240 1235 } 1241 1236 1242 - for (temp_mask = 0; m > 0; m--) { 1237 + for (m = masks, temp_mask = 0; m > 0; m--) { 1243 1238 temp_mask |= mask_bits; 1244 1239 mask_bits >>= 1; 1245 1240 } ··· 1250 1245 * Only allow one writer at a time. Writes should be 1251 1246 * quite rare and small in any case. 1252 1247 */ 1253 - mutex_lock(&smk_netlbladdr_lock); 1248 + mutex_lock(&smk_net4addr_lock); 1254 1249 1255 1250 nsa = newname.sin_addr.s_addr; 1256 1251 /* try to find if the prefix is already in the list */ 1257 1252 found = 0; 1258 - list_for_each_entry_rcu(snp, &smk_netlbladdr_list, list) { 1259 - if (snp->smk_host.sin_addr.s_addr == nsa && 1260 - snp->smk_mask.s_addr == mask.s_addr) { 1253 + list_for_each_entry_rcu(snp, &smk_net4addr_list, list) { 1254 + if (snp->smk_host.s_addr == nsa && snp->smk_masks == masks) { 1261 1255 found = 1; 1262 1256 break; 1263 1257 } ··· 1269 1265 rc = -ENOMEM; 1270 1266 else { 1271 1267 rc = 0; 1272 - snp->smk_host.sin_addr.s_addr = newname.sin_addr.s_addr; 1268 + snp->smk_host.s_addr = newname.sin_addr.s_addr; 1273 1269 snp->smk_mask.s_addr = mask.s_addr; 1274 1270 snp->smk_label = skp; 1275 - smk_netlbladdr_insert(snp); 1271 + snp->smk_masks = masks; 1272 + smk_net4addr_insert(snp); 1276 1273 } 1277 1274 } else { 1278 - /* we delete the unlabeled entry, only if the previous label 1279 - * wasn't the special CIPSO option */ 1280 - if (snp->smk_label != &smack_cipso_option) 1275 + /* 1276 + * Delete the unlabeled entry, only if the previous label 1277 + * wasn't the special CIPSO option 1278 + */ 1279 + if (snp->smk_label != NULL) 1281 1280 rc = netlbl_cfg_unlbl_static_del(&init_net, NULL, 1282 - &snp->smk_host.sin_addr, &snp->smk_mask, 1281 + &snp->smk_host, &snp->smk_mask, 1283 1282 PF_INET, &audit_info); 1284 1283 else 1285 1284 rc = 0; ··· 1294 1287 * this host so that incoming packets get labeled. 1295 1288 * but only if we didn't get the special CIPSO option 1296 1289 */ 1297 - if (rc == 0 && skp != &smack_cipso_option) 1290 + if (rc == 0 && skp != NULL) 1298 1291 rc = netlbl_cfg_unlbl_static_add(&init_net, NULL, 1299 - &snp->smk_host.sin_addr, &snp->smk_mask, PF_INET, 1292 + &snp->smk_host, &snp->smk_mask, PF_INET, 1300 1293 snp->smk_label->smk_secid, &audit_info); 1301 1294 1302 1295 if (rc == 0) 1303 1296 rc = count; 1304 1297 1305 - mutex_unlock(&smk_netlbladdr_lock); 1298 + mutex_unlock(&smk_net4addr_lock); 1306 1299 1307 1300 free_out: 1308 1301 kfree(smack); ··· 1312 1305 return rc; 1313 1306 } 1314 1307 1315 - static const struct file_operations smk_netlbladdr_ops = { 1316 - .open = smk_open_netlbladdr, 1308 + static const struct file_operations smk_net4addr_ops = { 1309 + .open = smk_open_net4addr, 1317 1310 .read = seq_read, 1318 1311 .llseek = seq_lseek, 1319 - .write = smk_write_netlbladdr, 1312 + .write = smk_write_net4addr, 1320 1313 .release = seq_release, 1321 1314 }; 1315 + 1316 + #if IS_ENABLED(CONFIG_IPV6) 1317 + /* 1318 + * Seq_file read operations for /smack/netlabel6 1319 + */ 1320 + 1321 + static void *net6addr_seq_start(struct seq_file *s, loff_t *pos) 1322 + { 1323 + return smk_seq_start(s, pos, &smk_net6addr_list); 1324 + } 1325 + 1326 + static void *net6addr_seq_next(struct seq_file *s, void *v, loff_t *pos) 1327 + { 1328 + return smk_seq_next(s, v, pos, &smk_net6addr_list); 1329 + } 1330 + 1331 + /* 1332 + * Print host/label pairs 1333 + */ 1334 + static int net6addr_seq_show(struct seq_file *s, void *v) 1335 + { 1336 + struct list_head *list = v; 1337 + struct smk_net6addr *skp = 1338 + list_entry(list, struct smk_net6addr, list); 1339 + 1340 + if (skp->smk_label != NULL) 1341 + seq_printf(s, "%pI6/%d %s\n", &skp->smk_host, skp->smk_masks, 1342 + skp->smk_label->smk_known); 1343 + 1344 + return 0; 1345 + } 1346 + 1347 + static const struct seq_operations net6addr_seq_ops = { 1348 + .start = net6addr_seq_start, 1349 + .next = net6addr_seq_next, 1350 + .show = net6addr_seq_show, 1351 + .stop = smk_seq_stop, 1352 + }; 1353 + 1354 + /** 1355 + * smk_open_net6addr - open() for /smack/netlabel 1356 + * @inode: inode structure representing file 1357 + * @file: "netlabel" file pointer 1358 + * 1359 + * Connect our net6addr_seq_* operations with /smack/netlabel 1360 + * file_operations 1361 + */ 1362 + static int smk_open_net6addr(struct inode *inode, struct file *file) 1363 + { 1364 + return seq_open(file, &net6addr_seq_ops); 1365 + } 1366 + 1367 + /** 1368 + * smk_net6addr_insert 1369 + * @new : entry to insert 1370 + * 1371 + * This inserts an entry in the smack_net6addrs list 1372 + * sorted by netmask length (longest to smallest) 1373 + * locked by &smk_net6addr_lock in smk_write_net6addr 1374 + * 1375 + */ 1376 + static void smk_net6addr_insert(struct smk_net6addr *new) 1377 + { 1378 + struct smk_net6addr *m_next; 1379 + struct smk_net6addr *m; 1380 + 1381 + if (list_empty(&smk_net6addr_list)) { 1382 + list_add_rcu(&new->list, &smk_net6addr_list); 1383 + return; 1384 + } 1385 + 1386 + m = list_entry_rcu(smk_net6addr_list.next, 1387 + struct smk_net6addr, list); 1388 + 1389 + if (new->smk_masks > m->smk_masks) { 1390 + list_add_rcu(&new->list, &smk_net6addr_list); 1391 + return; 1392 + } 1393 + 1394 + list_for_each_entry_rcu(m, &smk_net6addr_list, list) { 1395 + if (list_is_last(&m->list, &smk_net6addr_list)) { 1396 + list_add_rcu(&new->list, &m->list); 1397 + return; 1398 + } 1399 + m_next = list_entry_rcu(m->list.next, 1400 + struct smk_net6addr, list); 1401 + if (new->smk_masks > m_next->smk_masks) { 1402 + list_add_rcu(&new->list, &m->list); 1403 + return; 1404 + } 1405 + } 1406 + } 1407 + 1408 + 1409 + /** 1410 + * smk_write_net6addr - write() for /smack/netlabel 1411 + * @file: file pointer, not actually used 1412 + * @buf: where to get the data from 1413 + * @count: bytes sent 1414 + * @ppos: where to start 1415 + * 1416 + * Accepts only one net6addr per write call. 1417 + * Returns number of bytes written or error code, as appropriate 1418 + */ 1419 + static ssize_t smk_write_net6addr(struct file *file, const char __user *buf, 1420 + size_t count, loff_t *ppos) 1421 + { 1422 + struct smk_net6addr *snp; 1423 + struct in6_addr newname; 1424 + struct in6_addr fullmask; 1425 + struct smack_known *skp = NULL; 1426 + char *smack; 1427 + char *data; 1428 + int rc = 0; 1429 + int found = 0; 1430 + int i; 1431 + unsigned int scanned[8]; 1432 + unsigned int m; 1433 + unsigned int mask = 128; 1434 + 1435 + /* 1436 + * Must have privilege. 1437 + * No partial writes. 1438 + * Enough data must be present. 1439 + * "<addr/mask, as a:b:c:d:e:f:g:h/e><space><label>" 1440 + * "<addr, as a:b:c:d:e:f:g:h><space><label>" 1441 + */ 1442 + if (!smack_privileged(CAP_MAC_ADMIN)) 1443 + return -EPERM; 1444 + if (*ppos != 0) 1445 + return -EINVAL; 1446 + if (count < SMK_NETLBLADDRMIN) 1447 + return -EINVAL; 1448 + 1449 + data = kzalloc(count + 1, GFP_KERNEL); 1450 + if (data == NULL) 1451 + return -ENOMEM; 1452 + 1453 + if (copy_from_user(data, buf, count) != 0) { 1454 + rc = -EFAULT; 1455 + goto free_data_out; 1456 + } 1457 + 1458 + smack = kzalloc(count + 1, GFP_KERNEL); 1459 + if (smack == NULL) { 1460 + rc = -ENOMEM; 1461 + goto free_data_out; 1462 + } 1463 + 1464 + data[count] = '\0'; 1465 + 1466 + i = sscanf(data, "%x:%x:%x:%x:%x:%x:%x:%x/%u %s", 1467 + &scanned[0], &scanned[1], &scanned[2], &scanned[3], 1468 + &scanned[4], &scanned[5], &scanned[6], &scanned[7], 1469 + &mask, smack); 1470 + if (i != 10) { 1471 + i = sscanf(data, "%x:%x:%x:%x:%x:%x:%x:%x %s", 1472 + &scanned[0], &scanned[1], &scanned[2], 1473 + &scanned[3], &scanned[4], &scanned[5], 1474 + &scanned[6], &scanned[7], smack); 1475 + if (i != 9) { 1476 + rc = -EINVAL; 1477 + goto free_out; 1478 + } 1479 + } 1480 + if (mask > 128) { 1481 + rc = -EINVAL; 1482 + goto free_out; 1483 + } 1484 + for (i = 0; i < 8; i++) { 1485 + if (scanned[i] > 0xffff) { 1486 + rc = -EINVAL; 1487 + goto free_out; 1488 + } 1489 + newname.s6_addr16[i] = htons(scanned[i]); 1490 + } 1491 + 1492 + /* 1493 + * If smack begins with '-', it is an option, don't import it 1494 + */ 1495 + if (smack[0] != '-') { 1496 + skp = smk_import_entry(smack, 0); 1497 + if (skp == NULL) { 1498 + rc = -EINVAL; 1499 + goto free_out; 1500 + } 1501 + } else { 1502 + /* 1503 + * Only -DELETE is supported for IPv6 1504 + */ 1505 + if (strcmp(smack, SMACK_DELETE_OPTION) != 0) { 1506 + rc = -EINVAL; 1507 + goto free_out; 1508 + } 1509 + } 1510 + 1511 + for (i = 0, m = mask; i < 8; i++) { 1512 + if (m >= 16) { 1513 + fullmask.s6_addr16[i] = 0xffff; 1514 + m -= 16; 1515 + } else if (m > 0) { 1516 + fullmask.s6_addr16[i] = (1 << m) - 1; 1517 + m = 0; 1518 + } else 1519 + fullmask.s6_addr16[i] = 0; 1520 + newname.s6_addr16[i] &= fullmask.s6_addr16[i]; 1521 + } 1522 + 1523 + /* 1524 + * Only allow one writer at a time. Writes should be 1525 + * quite rare and small in any case. 1526 + */ 1527 + mutex_lock(&smk_net6addr_lock); 1528 + /* 1529 + * Try to find the prefix in the list 1530 + */ 1531 + list_for_each_entry_rcu(snp, &smk_net6addr_list, list) { 1532 + if (mask != snp->smk_masks) 1533 + continue; 1534 + for (found = 1, i = 0; i < 8; i++) { 1535 + if (newname.s6_addr16[i] != 1536 + snp->smk_host.s6_addr16[i]) { 1537 + found = 0; 1538 + break; 1539 + } 1540 + } 1541 + if (found == 1) 1542 + break; 1543 + } 1544 + if (found == 0) { 1545 + snp = kzalloc(sizeof(*snp), GFP_KERNEL); 1546 + if (snp == NULL) 1547 + rc = -ENOMEM; 1548 + else { 1549 + snp->smk_host = newname; 1550 + snp->smk_mask = fullmask; 1551 + snp->smk_masks = mask; 1552 + snp->smk_label = skp; 1553 + smk_net6addr_insert(snp); 1554 + } 1555 + } else { 1556 + snp->smk_label = skp; 1557 + } 1558 + 1559 + if (rc == 0) 1560 + rc = count; 1561 + 1562 + mutex_unlock(&smk_net6addr_lock); 1563 + 1564 + free_out: 1565 + kfree(smack); 1566 + free_data_out: 1567 + kfree(data); 1568 + 1569 + return rc; 1570 + } 1571 + 1572 + static const struct file_operations smk_net6addr_ops = { 1573 + .open = smk_open_net6addr, 1574 + .read = seq_read, 1575 + .llseek = seq_lseek, 1576 + .write = smk_write_net6addr, 1577 + .release = seq_release, 1578 + }; 1579 + #endif /* CONFIG_IPV6 */ 1322 1580 1323 1581 /** 1324 1582 * smk_read_doi - read() for /smack/doi ··· 2592 2320 */ 2593 2321 static int smk_init_sysfs(void) 2594 2322 { 2595 - int err; 2596 - err = sysfs_create_mount_point(fs_kobj, "smackfs"); 2597 - if (err) 2598 - return err; 2599 - return 0; 2323 + return sysfs_create_mount_point(fs_kobj, "smackfs"); 2600 2324 } 2601 2325 2602 2326 /** ··· 2787 2519 "direct", &smk_direct_ops, S_IRUGO|S_IWUSR}, 2788 2520 [SMK_AMBIENT] = { 2789 2521 "ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR}, 2790 - [SMK_NETLBLADDR] = { 2791 - "netlabel", &smk_netlbladdr_ops, S_IRUGO|S_IWUSR}, 2522 + [SMK_NET4ADDR] = { 2523 + "netlabel", &smk_net4addr_ops, S_IRUGO|S_IWUSR}, 2792 2524 [SMK_ONLYCAP] = { 2793 2525 "onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR}, 2794 2526 [SMK_LOGGING] = { ··· 2820 2552 [SMK_UNCONFINED] = { 2821 2553 "unconfined", &smk_unconfined_ops, S_IRUGO|S_IWUSR}, 2822 2554 #endif 2555 + #if IS_ENABLED(CONFIG_IPV6) 2556 + [SMK_NET6ADDR] = { 2557 + "ipv6host", &smk_net6addr_ops, S_IRUGO|S_IWUSR}, 2558 + #endif /* CONFIG_IPV6 */ 2823 2559 /* last one */ 2824 2560 {""} 2825 2561 };
+1 -8
security/yama/Kconfig
··· 6 6 This selects Yama, which extends DAC support with additional 7 7 system-wide security settings beyond regular Linux discretionary 8 8 access controls. Currently available is ptrace scope restriction. 9 + Like capabilities, this security module stacks with other LSMs. 9 10 Further information can be found in Documentation/security/Yama.txt. 10 11 11 12 If you are unsure how to answer this question, answer N. 12 - 13 - config SECURITY_YAMA_STACKED 14 - bool "Yama stacked with other LSMs" 15 - depends on SECURITY_YAMA 16 - default n 17 - help 18 - When Yama is built into the kernel, force it to stack with the 19 - selected primary LSM.
+10 -23
security/yama/yama_lsm.c
··· 353 353 LSM_HOOK_INIT(task_free, yama_task_free), 354 354 }; 355 355 356 - void __init yama_add_hooks(void) 357 - { 358 - security_add_hooks(yama_hooks, ARRAY_SIZE(yama_hooks)); 359 - } 360 - 361 356 #ifdef CONFIG_SYSCTL 362 357 static int yama_dointvec_minmax(struct ctl_table *table, int write, 363 358 void __user *buffer, size_t *lenp, loff_t *ppos) ··· 391 396 }, 392 397 { } 393 398 }; 394 - #endif /* CONFIG_SYSCTL */ 395 - 396 - static __init int yama_init(void) 399 + static void __init yama_init_sysctl(void) 397 400 { 398 - #ifndef CONFIG_SECURITY_YAMA_STACKED 399 - /* 400 - * If yama is being stacked this is already taken care of. 401 - */ 402 - if (!security_module_enable("yama")) 403 - return 0; 404 - yama_add_hooks(); 405 - #endif 406 - pr_info("Yama: becoming mindful.\n"); 407 - 408 - #ifdef CONFIG_SYSCTL 409 401 if (!register_sysctl_paths(yama_sysctl_path, yama_sysctl_table)) 410 402 panic("Yama: sysctl registration failed.\n"); 411 - #endif 412 - 413 - return 0; 414 403 } 404 + #else 405 + static inline void yama_init_sysctl(void) { } 406 + #endif /* CONFIG_SYSCTL */ 415 407 416 - security_initcall(yama_init); 408 + void __init yama_add_hooks(void) 409 + { 410 + pr_info("Yama: becoming mindful.\n"); 411 + security_add_hooks(yama_hooks, ARRAY_SIZE(yama_hooks)); 412 + yama_init_sysctl(); 413 + }