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