diff options
Diffstat (limited to 'security')
37 files changed, 538 insertions, 286 deletions
diff --git a/security/Kconfig b/security/Kconfig index afa91c6f06bb..27d8b2688f75 100644 --- a/security/Kconfig +++ b/security/Kconfig @@ -153,7 +153,6 @@ config HAVE_HARDENED_USERCOPY_ALLOCATOR config HARDENED_USERCOPY bool "Harden memory copies between kernel and userspace" depends on HAVE_HARDENED_USERCOPY_ALLOCATOR - select BUG imply STRICT_DEVMEM help This option checks for obviously wrong memory regions when diff --git a/security/commoncap.c b/security/commoncap.c index f4c33abd9959..2e489d6a3ac8 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -388,7 +388,7 @@ int cap_inode_getsecurity(struct inode *inode, const char *name, void **buffer, if (strcmp(name, "capability") != 0) return -EOPNOTSUPP; - dentry = d_find_alias(inode); + dentry = d_find_any_alias(inode); if (!dentry) return -EINVAL; diff --git a/security/integrity/digsig_asymmetric.c b/security/integrity/digsig_asymmetric.c index ab6a029062a1..6dc075144508 100644 --- a/security/integrity/digsig_asymmetric.c +++ b/security/integrity/digsig_asymmetric.c @@ -115,3 +115,26 @@ int asymmetric_verify(struct key *keyring, const char *sig, pr_debug("%s() = %d\n", __func__, ret); return ret; } + +/** + * integrity_kernel_module_request - prevent crypto-pkcs1pad(rsa,*) requests + * @kmod_name: kernel module name + * + * We have situation, when public_key_verify_signature() in case of RSA + * algorithm use alg_name to store internal information in order to + * construct an algorithm on the fly, but crypto_larval_lookup() will try + * to use alg_name in order to load kernel module with same name. + * Since we don't have any real "crypto-pkcs1pad(rsa,*)" kernel modules, + * we are safe to fail such module request from crypto_larval_lookup(). + * + * In this way we prevent modprobe execution during digsig verification + * and avoid possible deadlock if modprobe and/or it's dependencies + * also signed with digsig. + */ +int integrity_kernel_module_request(char *kmod_name) +{ + if (strncmp(kmod_name, "crypto-pkcs1pad(rsa,", 20) == 0) + return -EINVAL; + + return 0; +} diff --git a/security/integrity/evm/Kconfig b/security/integrity/evm/Kconfig index d593346d0bba..60221852b26a 100644 --- a/security/integrity/evm/Kconfig +++ b/security/integrity/evm/Kconfig @@ -4,6 +4,7 @@ config EVM select ENCRYPTED_KEYS select CRYPTO_HMAC select CRYPTO_SHA1 + select CRYPTO_HASH_INFO default n help EVM protects a file's security extended attributes against diff --git a/security/integrity/evm/evm.h b/security/integrity/evm/evm.h index 1257c3c24723..c3f437f5db10 100644 --- a/security/integrity/evm/evm.h +++ b/security/integrity/evm/evm.h @@ -47,6 +47,11 @@ extern struct crypto_shash *hash_tfm; /* List of EVM protected security xattrs */ extern struct list_head evm_config_xattrnames; +struct evm_digest { + struct ima_digest_data hdr; + char digest[IMA_MAX_DIGEST_SIZE]; +} __packed; + int evm_init_key(void); int evm_update_evmxattr(struct dentry *dentry, const char *req_xattr_name, @@ -54,10 +59,11 @@ int evm_update_evmxattr(struct dentry *dentry, size_t req_xattr_value_len); int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name, const char *req_xattr_value, - size_t req_xattr_value_len, char *digest); + size_t req_xattr_value_len, struct evm_digest *data); int evm_calc_hash(struct dentry *dentry, const char *req_xattr_name, const char *req_xattr_value, - size_t req_xattr_value_len, char type, char *digest); + size_t req_xattr_value_len, char type, + struct evm_digest *data); int evm_init_hmac(struct inode *inode, const struct xattr *xattr, char *hmac_val); int evm_init_secfs(void); diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c index b60524310855..8a3905bb02c7 100644 --- a/security/integrity/evm/evm_crypto.c +++ b/security/integrity/evm/evm_crypto.c @@ -21,6 +21,7 @@ #include <linux/evm.h> #include <keys/encrypted-type.h> #include <crypto/hash.h> +#include <crypto/hash_info.h> #include "evm.h" #define EVMKEY "evm-key" @@ -29,7 +30,7 @@ static unsigned char evmkey[MAX_KEY_SIZE]; static int evmkey_len = MAX_KEY_SIZE; struct crypto_shash *hmac_tfm; -struct crypto_shash *hash_tfm; +static struct crypto_shash *evm_tfm[HASH_ALGO__LAST]; static DEFINE_MUTEX(mutex); @@ -38,7 +39,6 @@ static DEFINE_MUTEX(mutex); static unsigned long evm_set_key_flags; static char * const evm_hmac = "hmac(sha1)"; -static char * const evm_hash = "sha1"; /** * evm_set_key() - set EVM HMAC key from the kernel @@ -74,10 +74,10 @@ busy: } EXPORT_SYMBOL_GPL(evm_set_key); -static struct shash_desc *init_desc(char type) +static struct shash_desc *init_desc(char type, uint8_t hash_algo) { long rc; - char *algo; + const char *algo; struct crypto_shash **tfm; struct shash_desc *desc; @@ -89,15 +89,16 @@ static struct shash_desc *init_desc(char type) tfm = &hmac_tfm; algo = evm_hmac; } else { - tfm = &hash_tfm; - algo = evm_hash; + tfm = &evm_tfm[hash_algo]; + algo = hash_algo_name[hash_algo]; } if (*tfm == NULL) { mutex_lock(&mutex); if (*tfm) goto out; - *tfm = crypto_alloc_shash(algo, 0, CRYPTO_ALG_ASYNC); + *tfm = crypto_alloc_shash(algo, 0, + CRYPTO_ALG_ASYNC | CRYPTO_NOLOAD); if (IS_ERR(*tfm)) { rc = PTR_ERR(*tfm); pr_err("Can not allocate %s (reason: %ld)\n", algo, rc); @@ -186,10 +187,10 @@ static void hmac_add_misc(struct shash_desc *desc, struct inode *inode, * each xattr, but attempt to re-use the previously allocated memory. */ static int evm_calc_hmac_or_hash(struct dentry *dentry, - const char *req_xattr_name, - const char *req_xattr_value, - size_t req_xattr_value_len, - char type, char *digest) + const char *req_xattr_name, + const char *req_xattr_value, + size_t req_xattr_value_len, + uint8_t type, struct evm_digest *data) { struct inode *inode = d_backing_inode(dentry); struct xattr_list *xattr; @@ -204,10 +205,12 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry, inode->i_sb->s_user_ns != &init_user_ns) return -EOPNOTSUPP; - desc = init_desc(type); + desc = init_desc(type, data->hdr.algo); if (IS_ERR(desc)) return PTR_ERR(desc); + data->hdr.length = crypto_shash_digestsize(desc->tfm); + error = -ENODATA; list_for_each_entry_rcu(xattr, &evm_config_xattrnames, list) { bool is_ima = false; @@ -239,7 +242,7 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry, if (is_ima) ima_present = true; } - hmac_add_misc(desc, inode, type, digest); + hmac_add_misc(desc, inode, type, data->digest); /* Portable EVM signatures must include an IMA hash */ if (type == EVM_XATTR_PORTABLE_DIGSIG && !ima_present) @@ -252,18 +255,18 @@ out: int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name, const char *req_xattr_value, size_t req_xattr_value_len, - char *digest) + struct evm_digest *data) { return evm_calc_hmac_or_hash(dentry, req_xattr_name, req_xattr_value, - req_xattr_value_len, EVM_XATTR_HMAC, digest); + req_xattr_value_len, EVM_XATTR_HMAC, data); } int evm_calc_hash(struct dentry *dentry, const char *req_xattr_name, const char *req_xattr_value, size_t req_xattr_value_len, - char type, char *digest) + char type, struct evm_digest *data) { return evm_calc_hmac_or_hash(dentry, req_xattr_name, req_xattr_value, - req_xattr_value_len, type, digest); + req_xattr_value_len, type, data); } static int evm_is_immutable(struct dentry *dentry, struct inode *inode) @@ -303,7 +306,7 @@ int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name, const char *xattr_value, size_t xattr_value_len) { struct inode *inode = d_backing_inode(dentry); - struct evm_ima_xattr_data xattr_data; + struct evm_digest data; int rc = 0; /* @@ -316,13 +319,14 @@ int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name, if (rc) return -EPERM; + data.hdr.algo = HASH_ALGO_SHA1; rc = evm_calc_hmac(dentry, xattr_name, xattr_value, - xattr_value_len, xattr_data.digest); + xattr_value_len, &data); if (rc == 0) { - xattr_data.type = EVM_XATTR_HMAC; + data.hdr.xattr.sha1.type = EVM_XATTR_HMAC; rc = __vfs_setxattr_noperm(dentry, XATTR_NAME_EVM, - &xattr_data, - sizeof(xattr_data), 0); + &data.hdr.xattr.data[1], + SHA1_DIGEST_SIZE + 1, 0); } else if (rc == -ENODATA && (inode->i_opflags & IOP_XATTR)) { rc = __vfs_removexattr(dentry, XATTR_NAME_EVM); } @@ -334,7 +338,7 @@ int evm_init_hmac(struct inode *inode, const struct xattr *lsm_xattr, { struct shash_desc *desc; - desc = init_desc(EVM_XATTR_HMAC); + desc = init_desc(EVM_XATTR_HMAC, HASH_ALGO_SHA1); if (IS_ERR(desc)) { pr_info("init_desc failed\n"); return PTR_ERR(desc); diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c index f9eff5041e4c..7f3f54d89a6e 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c @@ -25,6 +25,7 @@ #include <linux/magic.h> #include <crypto/hash.h> +#include <crypto/hash_info.h> #include <crypto/algapi.h> #include "evm.h" @@ -134,8 +135,9 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry, struct integrity_iint_cache *iint) { struct evm_ima_xattr_data *xattr_data = NULL; - struct evm_ima_xattr_data calc; + struct signature_v2_hdr *hdr; enum integrity_status evm_status = INTEGRITY_PASS; + struct evm_digest digest; struct inode *inode; int rc, xattr_len; @@ -171,25 +173,28 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry, evm_status = INTEGRITY_FAIL; goto out; } + + digest.hdr.algo = HASH_ALGO_SHA1; rc = evm_calc_hmac(dentry, xattr_name, xattr_value, - xattr_value_len, calc.digest); + xattr_value_len, &digest); if (rc) break; - rc = crypto_memneq(xattr_data->digest, calc.digest, - sizeof(calc.digest)); + rc = crypto_memneq(xattr_data->digest, digest.digest, + SHA1_DIGEST_SIZE); if (rc) rc = -EINVAL; break; case EVM_IMA_XATTR_DIGSIG: case EVM_XATTR_PORTABLE_DIGSIG: + hdr = (struct signature_v2_hdr *)xattr_data; + digest.hdr.algo = hdr->hash_algo; rc = evm_calc_hash(dentry, xattr_name, xattr_value, - xattr_value_len, xattr_data->type, - calc.digest); + xattr_value_len, xattr_data->type, &digest); if (rc) break; rc = integrity_digsig_verify(INTEGRITY_KEYRING_EVM, (const char *)xattr_data, xattr_len, - calc.digest, sizeof(calc.digest)); + digest.digest, digest.hdr.length); if (!rc) { inode = d_backing_inode(dentry); diff --git a/security/integrity/evm/evm_secfs.c b/security/integrity/evm/evm_secfs.c index 637eb999e340..77de71b7794c 100644 --- a/security/integrity/evm/evm_secfs.c +++ b/security/integrity/evm/evm_secfs.c @@ -193,8 +193,8 @@ static ssize_t evm_write_xattrs(struct file *file, const char __user *buf, return -E2BIG; ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_INTEGRITY_EVM_XATTR); - if (IS_ERR(ab)) - return PTR_ERR(ab); + if (!ab) + return -ENOMEM; xattr = kmalloc(sizeof(struct xattr_list), GFP_KERNEL); if (!xattr) { diff --git a/security/integrity/iint.c b/security/integrity/iint.c index 149faa81f6f0..5a6810041e5c 100644 --- a/security/integrity/iint.c +++ b/security/integrity/iint.c @@ -219,10 +219,13 @@ static int __init integrity_fs_init(void) { integrity_dir = securityfs_create_dir("integrity", NULL); if (IS_ERR(integrity_dir)) { - pr_err("Unable to create integrity sysfs dir: %ld\n", - PTR_ERR(integrity_dir)); + int ret = PTR_ERR(integrity_dir); + + if (ret != -ENODEV) + pr_err("Unable to create integrity sysfs dir: %d\n", + ret); integrity_dir = NULL; - return PTR_ERR(integrity_dir); + return ret; } return 0; diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig index 6a8f67714c83..13b446328dda 100644 --- a/security/integrity/ima/Kconfig +++ b/security/integrity/ima/Kconfig @@ -12,6 +12,7 @@ config IMA select TCG_TIS if TCG_TPM && X86 select TCG_CRB if TCG_TPM && ACPI select TCG_IBMVTPM if TCG_TPM && PPC_PSERIES + select INTEGRITY_AUDIT if AUDIT help The Trusted Computing Group(TCG) runtime Integrity Measurement Architecture(IMA) maintains a list of hash @@ -156,6 +157,64 @@ config IMA_APPRAISE <http://linux-ima.sourceforge.net> If unsure, say N. +config IMA_APPRAISE_BUILD_POLICY + bool "IMA build time configured policy rules" + depends on IMA_APPRAISE && INTEGRITY_ASYMMETRIC_KEYS + default n + help + This option defines an IMA appraisal policy at build time, which + is enforced at run time without having to specify a builtin + policy name on the boot command line. The build time appraisal + policy rules persist after loading a custom policy. + + Depending on the rules configured, this policy may require kernel + modules, firmware, the kexec kernel image, and/or the IMA policy + to be signed. Unsigned files might prevent the system from + booting or applications from working properly. + +config IMA_APPRAISE_REQUIRE_FIRMWARE_SIGS + bool "Appraise firmware signatures" + depends on IMA_APPRAISE_BUILD_POLICY + default n + help + This option defines a policy requiring all firmware to be signed, + including the regulatory.db. If both this option and + CFG80211_REQUIRE_SIGNED_REGDB are enabled, then both signature + verification methods are necessary. + +config IMA_APPRAISE_REQUIRE_KEXEC_SIGS + bool "Appraise kexec kernel image signatures" + depends on IMA_APPRAISE_BUILD_POLICY + default n + help + Enabling this rule will require all kexec'ed kernel images to + be signed and verified by a public key on the trusted IMA + keyring. + + Kernel image signatures can not be verified by the original + kexec_load syscall. Enabling this rule will prevent its + usage. + +config IMA_APPRAISE_REQUIRE_MODULE_SIGS + bool "Appraise kernel modules signatures" + depends on IMA_APPRAISE_BUILD_POLICY + default n + help + Enabling this rule will require all kernel modules to be signed + and verified by a public key on the trusted IMA keyring. + + Kernel module signatures can only be verified by IMA-appraisal, + via the finit_module syscall. Enabling this rule will prevent + the usage of the init_module syscall. + +config IMA_APPRAISE_REQUIRE_POLICY_SIGS + bool "Appraise IMA policy signature" + depends on IMA_APPRAISE_BUILD_POLICY + default n + help + Enabling this rule will require the IMA policy to be signed and + and verified by a key on the trusted IMA keyring. + config IMA_APPRAISE_BOOTPARAM bool "ima_appraise boot parameter" depends on IMA_APPRAISE diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index e4c1a236976c..67db9d9454ca 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -53,9 +53,9 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 }; extern int ima_policy_flag; /* set during initialization */ -extern int ima_used_chip; extern int ima_hash_algo; extern int ima_appraise; +extern struct tpm_chip *ima_tpm_chip; /* IMA event related data */ struct ima_event_data { @@ -232,6 +232,7 @@ int ima_policy_show(struct seq_file *m, void *v); #define IMA_APPRAISE_MODULES 0x08 #define IMA_APPRAISE_FIRMWARE 0x10 #define IMA_APPRAISE_POLICY 0x20 +#define IMA_APPRAISE_KEXEC 0x40 #ifdef CONFIG_IMA_APPRAISE int ima_appraise_measurement(enum ima_hooks func, diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c index 4e085a17124f..7e7e7e7c250a 100644 --- a/security/integrity/ima/ima_crypto.c +++ b/security/integrity/ima/ima_crypto.c @@ -631,10 +631,10 @@ int ima_calc_buffer_hash(const void *buf, loff_t len, static void __init ima_pcrread(int idx, u8 *pcr) { - if (!ima_used_chip) + if (!ima_tpm_chip) return; - if (tpm_pcr_read(NULL, idx, pcr) != 0) + if (tpm_pcr_read(ima_tpm_chip, idx, pcr) != 0) pr_err("Error Communicating to TPM chip\n"); } diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index 29b72cd2502e..faac9ecaa0ae 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -26,7 +26,7 @@ /* name for boot aggregate entry */ static const char *boot_aggregate_name = "boot_aggregate"; -int ima_used_chip; +struct tpm_chip *ima_tpm_chip; /* Add the boot aggregate to the IMA measurement list and extend * the PCR register. @@ -64,7 +64,7 @@ static int __init ima_add_boot_aggregate(void) iint->ima_hash->algo = HASH_ALGO_SHA1; iint->ima_hash->length = SHA1_DIGEST_SIZE; - if (ima_used_chip) { + if (ima_tpm_chip) { result = ima_calc_boot_aggregate(&hash.hdr); if (result < 0) { audit_cause = "hashing_error"; @@ -106,17 +106,11 @@ void __init ima_load_x509(void) int __init ima_init(void) { - u8 pcr_i[TPM_DIGEST_SIZE]; int rc; - ima_used_chip = 0; - rc = tpm_pcr_read(NULL, 0, pcr_i); - if (rc == 0) - ima_used_chip = 1; - - if (!ima_used_chip) - pr_info("No TPM chip found, activating TPM-bypass! (rc=%d)\n", - rc); + ima_tpm_chip = tpm_default_chip(); + if (!ima_tpm_chip) + pr_info("No TPM chip found, activating TPM-bypass!\n"); rc = integrity_init_keyring(INTEGRITY_KEYRING_IMA); if (rc) diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index b286f37712d5..2d31921fbda4 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -429,16 +429,14 @@ void ima_post_path_mknod(struct dentry *dentry) */ int ima_read_file(struct file *file, enum kernel_read_file_id read_id) { - bool sig_enforce = is_module_sig_enforced(); - - if (!file && read_id == READING_MODULE) { - if (!sig_enforce && (ima_appraise & IMA_APPRAISE_MODULES) && - (ima_appraise & IMA_APPRAISE_ENFORCE)) { - pr_err("impossible to appraise a module without a file descriptor. sig_enforce kernel parameter might help\n"); - return -EACCES; /* INTEGRITY_UNKNOWN */ - } - return 0; /* We rely on module signature checking */ - } + /* + * READING_FIRMWARE_PREALLOC_BUFFER + * + * Do devices using pre-allocated memory run the risk of the + * firmware being accessible to the device prior to the completion + * of IMA's signature verification any more than when using two + * buffers? + */ return 0; } @@ -472,14 +470,13 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size, if (!file && read_id == READING_FIRMWARE) { if ((ima_appraise & IMA_APPRAISE_FIRMWARE) && - (ima_appraise & IMA_APPRAISE_ENFORCE)) + (ima_appraise & IMA_APPRAISE_ENFORCE)) { + pr_err("Prevent firmware loading_store.\n"); return -EACCES; /* INTEGRITY_UNKNOWN */ + } return 0; } - if (!file && read_id == READING_MODULE) /* MODULE_SIG_FORCE enabled */ - return 0; - /* permit signed certs */ if (!file && read_id == READING_X509_CERTIFICATE) return 0; @@ -496,6 +493,49 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size, MAY_READ, func); } +/** + * ima_load_data - appraise decision based on policy + * @id: kernel load data caller identifier + * + * Callers of this LSM hook can not measure, appraise, or audit the + * data provided by userspace. Enforce policy rules requring a file + * signature (eg. kexec'ed kernel image). + * + * For permission return 0, otherwise return -EACCES. + */ +int ima_load_data(enum kernel_load_data_id id) +{ + bool sig_enforce; + + if ((ima_appraise & IMA_APPRAISE_ENFORCE) != IMA_APPRAISE_ENFORCE) + return 0; + + switch (id) { + case LOADING_KEXEC_IMAGE: + if (ima_appraise & IMA_APPRAISE_KEXEC) { + pr_err("impossible to appraise a kernel image without a file descriptor; try using kexec_file_load syscall.\n"); + return -EACCES; /* INTEGRITY_UNKNOWN */ + } + break; + case LOADING_FIRMWARE: + if (ima_appraise & IMA_APPRAISE_FIRMWARE) { + pr_err("Prevent firmware sysfs fallback loading.\n"); + return -EACCES; /* INTEGRITY_UNKNOWN */ + } + break; + case LOADING_MODULE: + sig_enforce = is_module_sig_enforced(); + + if (!sig_enforce && (ima_appraise & IMA_APPRAISE_MODULES)) { + pr_err("impossible to appraise a module without a file descriptor. sig_enforce kernel parameter might help\n"); + return -EACCES; /* INTEGRITY_UNKNOWN */ + } + default: + break; + } + return 0; +} + static int __init init_ima(void) { int error; diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index cdcc9a7b4e24..8c9499867c91 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -49,6 +49,7 @@ int ima_policy_flag; static int temp_ima_appraise; +static int build_ima_appraise __ro_after_init; #define MAX_LSM_RULES 6 enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE, @@ -162,6 +163,25 @@ static struct ima_rule_entry default_appraise_rules[] __ro_after_init = { #endif }; +static struct ima_rule_entry build_appraise_rules[] __ro_after_init = { +#ifdef CONFIG_IMA_APPRAISE_REQUIRE_MODULE_SIGS + {.action = APPRAISE, .func = MODULE_CHECK, + .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED}, +#endif +#ifdef CONFIG_IMA_APPRAISE_REQUIRE_FIRMWARE_SIGS + {.action = APPRAISE, .func = FIRMWARE_CHECK, + .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED}, +#endif +#ifdef CONFIG_IMA_APPRAISE_REQUIRE_KEXEC_SIGS + {.action = APPRAISE, .func = KEXEC_KERNEL_CHECK, + .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED}, +#endif +#ifdef CONFIG_IMA_APPRAISE_REQUIRE_POLICY_SIGS + {.action = APPRAISE, .func = POLICY_CHECK, + .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED}, +#endif +}; + static struct ima_rule_entry secure_boot_rules[] __ro_after_init = { {.action = APPRAISE, .func = MODULE_CHECK, .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED}, @@ -435,7 +455,7 @@ void ima_update_policy_flag(void) ima_policy_flag |= entry->action; } - ima_appraise |= temp_ima_appraise; + ima_appraise |= (build_ima_appraise | temp_ima_appraise); if (!ima_appraise) ima_policy_flag &= ~IMA_APPRAISE; } @@ -448,6 +468,8 @@ static int ima_appraise_flag(enum ima_hooks func) return IMA_APPRAISE_FIRMWARE; else if (func == POLICY_CHECK) return IMA_APPRAISE_POLICY; + else if (func == KEXEC_KERNEL_CHECK) + return IMA_APPRAISE_KEXEC; return 0; } @@ -486,8 +508,8 @@ void __init ima_init_policy(void) } /* - * Insert the appraise rules requiring file signatures, prior to - * any other appraise rules. + * Insert the builtin "secure_boot" policy rules requiring file + * signatures, prior to any other appraise rules. */ for (i = 0; i < secure_boot_entries; i++) { list_add_tail(&secure_boot_rules[i].list, &ima_default_rules); @@ -495,6 +517,26 @@ void __init ima_init_policy(void) ima_appraise_flag(secure_boot_rules[i].func); } + /* + * Insert the build time appraise rules requiring file signatures + * for both the initial and custom policies, prior to other appraise + * rules. + */ + for (i = 0; i < ARRAY_SIZE(build_appraise_rules); i++) { + struct ima_rule_entry *entry; + + if (!secure_boot_entries) + list_add_tail(&build_appraise_rules[i].list, + &ima_default_rules); + + entry = kmemdup(&build_appraise_rules[i], sizeof(*entry), + GFP_KERNEL); + if (entry) + list_add_tail(&entry->list, &ima_policy_rules); + build_ima_appraise |= + ima_appraise_flag(build_appraise_rules[i].func); + } + for (i = 0; i < appraise_entries; i++) { list_add_tail(&default_appraise_rules[i].list, &ima_default_rules); @@ -615,14 +657,16 @@ static int ima_lsm_rule_init(struct ima_rule_entry *entry, static void ima_log_string_op(struct audit_buffer *ab, char *key, char *value, bool (*rule_operator)(kuid_t, kuid_t)) { + if (!ab) + return; + if (rule_operator == &uid_gt) audit_log_format(ab, "%s>", key); else if (rule_operator == &uid_lt) audit_log_format(ab, "%s<", key); else audit_log_format(ab, "%s=", key); - audit_log_untrustedstring(ab, value); - audit_log_format(ab, " "); + audit_log_format(ab, "%s ", value); } static void ima_log_string(struct audit_buffer *ab, char *key, char *value) { @@ -637,7 +681,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) bool uid_token; int result = 0; - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_INTEGRITY_RULE); + ab = integrity_audit_log_start(audit_context(), GFP_KERNEL, + AUDIT_INTEGRITY_POLICY_RULE); entry->uid = INVALID_UID; entry->fowner = INVALID_UID; diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c index 418f35e38015..b186819bd5aa 100644 --- a/security/integrity/ima/ima_queue.c +++ b/security/integrity/ima/ima_queue.c @@ -142,10 +142,10 @@ static int ima_pcr_extend(const u8 *hash, int pcr) { int result = 0; - if (!ima_used_chip) + if (!ima_tpm_chip) return result; - result = tpm_pcr_extend(NULL, pcr, hash); + result = tpm_pcr_extend(ima_tpm_chip, pcr, hash); if (result != 0) pr_err("Error Communicating to TPM chip, result: %d\n", result); return result; diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h index 0bb372eed62a..e60473b13a8d 100644 --- a/security/integrity/integrity.h +++ b/security/integrity/integrity.h @@ -15,6 +15,7 @@ #include <linux/integrity.h> #include <crypto/sha.h> #include <linux/key.h> +#include <linux/audit.h> /* iint action cache flags */ #define IMA_MEASURE 0x00000001 @@ -199,6 +200,13 @@ static inline void evm_load_x509(void) void integrity_audit_msg(int audit_msgno, struct inode *inode, const unsigned char *fname, const char *op, const char *cause, int result, int info); + +static inline struct audit_buffer * +integrity_audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, int type) +{ + return audit_log_start(ctx, gfp_mask, type); +} + #else static inline void integrity_audit_msg(int audit_msgno, struct inode *inode, const unsigned char *fname, @@ -206,4 +214,11 @@ static inline void integrity_audit_msg(int audit_msgno, struct inode *inode, int result, int info) { } + +static inline struct audit_buffer * +integrity_audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, int type) +{ + return NULL; +} + #endif diff --git a/security/integrity/integrity_audit.c b/security/integrity/integrity_audit.c index ab10a25310a1..82c98f7d217e 100644 --- a/security/integrity/integrity_audit.c +++ b/security/integrity/integrity_audit.c @@ -45,11 +45,7 @@ void integrity_audit_msg(int audit_msgno, struct inode *inode, from_kuid(&init_user_ns, audit_get_loginuid(current)), audit_get_sessionid(current)); audit_log_task_context(ab); - audit_log_format(ab, " op="); - audit_log_string(ab, op); - audit_log_format(ab, " cause="); - audit_log_string(ab, cause); - audit_log_format(ab, " comm="); + audit_log_format(ab, " op=%s cause=%s comm=", op, cause); audit_log_untrustedstring(ab, get_task_comm(name, current)); if (fname) { audit_log_format(ab, " name="); diff --git a/security/keys/dh.c b/security/keys/dh.c index b203f7758f97..711e89d8c415 100644 --- a/security/keys/dh.c +++ b/security/keys/dh.c @@ -317,7 +317,7 @@ long __keyctl_dh_compute(struct keyctl_dh_params __user *params, if (ret) goto out3; - tfm = crypto_alloc_kpp("dh", CRYPTO_ALG_TYPE_KPP, 0); + tfm = crypto_alloc_kpp("dh", 0, 0); if (IS_ERR(tfm)) { ret = PTR_ERR(tfm); goto out3; diff --git a/security/loadpin/loadpin.c b/security/loadpin/loadpin.c index 5fa191252c8f..0716af28808a 100644 --- a/security/loadpin/loadpin.c +++ b/security/loadpin/loadpin.c @@ -173,9 +173,15 @@ static int loadpin_read_file(struct file *file, enum kernel_read_file_id id) return 0; } +static int loadpin_load_data(enum kernel_load_data_id id) +{ + return loadpin_read_file(NULL, (enum kernel_read_file_id) id); +} + static struct security_hook_list loadpin_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(sb_free_security, loadpin_sb_free_security), LSM_HOOK_INIT(kernel_read_file, loadpin_read_file), + LSM_HOOK_INIT(kernel_load_data, loadpin_load_data), }; void __init loadpin_add_hooks(void) diff --git a/security/security.c b/security/security.c index 5dce67070cdf..736e78da1ab9 100644 --- a/security/security.c +++ b/security/security.c @@ -48,14 +48,17 @@ static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] = static void __init do_security_initcalls(void) { int ret; - initcall_t *call; - call = __security_initcall_start; + initcall_t call; + initcall_entry_t *ce; + + ce = __security_initcall_start; trace_initcall_level("security"); - while (call < __security_initcall_end) { - trace_initcall_start((*call)); - ret = (*call) (); - trace_initcall_finish((*call), ret); - call++; + while (ce < __security_initcall_end) { + call = initcall_from_entry(ce); + trace_initcall_start(call); + ret = call(); + trace_initcall_finish(call, ret); + ce++; } } @@ -118,6 +121,8 @@ static int lsm_append(char *new, char **result) if (*result == NULL) { *result = kstrdup(new, GFP_KERNEL); + if (*result == NULL) + return -ENOMEM; } else { /* Check if it is the last registered name */ if (match_last_lsm(*result, new)) @@ -1030,7 +1035,12 @@ int security_kernel_create_files_as(struct cred *new, struct inode *inode) int security_kernel_module_request(char *kmod_name) { - return call_int_hook(kernel_module_request, 0, kmod_name); + int ret; + + ret = call_int_hook(kernel_module_request, 0, kmod_name); + if (ret) + return ret; + return integrity_kernel_module_request(kmod_name); } int security_kernel_read_file(struct file *file, enum kernel_read_file_id id) @@ -1056,6 +1066,17 @@ int security_kernel_post_read_file(struct file *file, char *buf, loff_t size, } EXPORT_SYMBOL_GPL(security_kernel_post_read_file); +int security_kernel_load_data(enum kernel_load_data_id id) +{ + int ret; + + ret = call_int_hook(kernel_load_data, 0, id); + if (ret) + return ret; + return ima_load_data(id); +} +EXPORT_SYMBOL_GPL(security_kernel_load_data); + int security_task_fix_setuid(struct cred *new, const struct cred *old, int flags) { diff --git a/security/selinux/avc.c b/security/selinux/avc.c index f3aedf077509..635e5c1e3e48 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -650,7 +650,7 @@ static int avc_latest_notif_update(struct selinux_avc *avc, spin_lock_irqsave(¬if_lock, flag); if (is_insert) { if (seqno < avc->avc_cache.latest_notif) { - printk(KERN_WARNING "SELinux: avc: seqno %d < latest_notif %d\n", + pr_warn("SELinux: avc: seqno %d < latest_notif %d\n", seqno, avc->avc_cache.latest_notif); ret = -EAGAIN; } diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 18006be15713..ad9a9b8e9979 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -530,7 +530,7 @@ static int sb_finish_set_opts(struct super_block *sb) the first boot of the SELinux kernel before we have assigned xattr values to the filesystem. */ if (!(root_inode->i_opflags & IOP_XATTR)) { - printk(KERN_WARNING "SELinux: (dev %s, type %s) has no " + pr_warn("SELinux: (dev %s, type %s) has no " "xattr support\n", sb->s_id, sb->s_type->name); rc = -EOPNOTSUPP; goto out; @@ -539,11 +539,11 @@ static int sb_finish_set_opts(struct super_block *sb) rc = __vfs_getxattr(root, root_inode, XATTR_NAME_SELINUX, NULL, 0); if (rc < 0 && rc != -ENODATA) { if (rc == -EOPNOTSUPP) - printk(KERN_WARNING "SELinux: (dev %s, type " + pr_warn("SELinux: (dev %s, type " "%s) has no security xattr handler\n", sb->s_id, sb->s_type->name); else - printk(KERN_WARNING "SELinux: (dev %s, type " + pr_warn("SELinux: (dev %s, type " "%s) getxattr errno %d\n", sb->s_id, sb->s_type->name, -rc); goto out; @@ -742,7 +742,7 @@ static int selinux_set_mnt_opts(struct super_block *sb, goto out; } rc = -EINVAL; - printk(KERN_WARNING "SELinux: Unable to set superblock options " + pr_warn("SELinux: Unable to set superblock options " "before the security server is initialized\n"); goto out; } @@ -784,7 +784,7 @@ static int selinux_set_mnt_opts(struct super_block *sb, mount_options[i], &sid, GFP_KERNEL); if (rc) { - printk(KERN_WARNING "SELinux: security_context_str_to_sid" + pr_warn("SELinux: security_context_str_to_sid" "(%s) failed for (dev %s, type %s) errno=%d\n", mount_options[i], sb->s_id, name, rc); goto out; @@ -860,8 +860,7 @@ static int selinux_set_mnt_opts(struct super_block *sb, */ rc = security_fs_use(&selinux_state, sb); if (rc) { - printk(KERN_WARNING - "%s: security_fs_use(%s) returned %d\n", + pr_warn("%s: security_fs_use(%s) returned %d\n", __func__, sb->s_type->name, rc); goto out; } @@ -947,7 +946,7 @@ static int selinux_set_mnt_opts(struct super_block *sb, if (sbsec->behavior != SECURITY_FS_USE_XATTR && sbsec->behavior != SECURITY_FS_USE_NATIVE) { rc = -EINVAL; - printk(KERN_WARNING "SELinux: defcontext option is " + pr_warn("SELinux: defcontext option is " "invalid for this filesystem type\n"); goto out; } @@ -969,7 +968,7 @@ out: return rc; out_double_mount: rc = -EINVAL; - printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different " + pr_warn("SELinux: mount invalid. Same superblock, different " "security settings for (dev %s, type %s)\n", sb->s_id, name); goto out; } @@ -998,7 +997,7 @@ static int selinux_cmp_sb_context(const struct super_block *oldsb, } return 0; mismatch: - printk(KERN_WARNING "SELinux: mount invalid. Same superblock, " + pr_warn("SELinux: mount invalid. Same superblock, " "different security settings for (dev %s, " "type %s)\n", newsb->s_id, newsb->s_type->name); return -EBUSY; @@ -1106,7 +1105,7 @@ static int selinux_parse_opts_str(char *options, case Opt_context: if (context || defcontext) { rc = -EINVAL; - printk(KERN_WARNING SEL_MOUNT_FAIL_MSG); + pr_warn(SEL_MOUNT_FAIL_MSG); goto out_err; } context = match_strdup(&args[0]); @@ -1119,7 +1118,7 @@ static int selinux_parse_opts_str(char *options, case Opt_fscontext: if (fscontext) { rc = -EINVAL; - printk(KERN_WARNING SEL_MOUNT_FAIL_MSG); + pr_warn(SEL_MOUNT_FAIL_MSG); goto out_err; } fscontext = match_strdup(&args[0]); @@ -1132,7 +1131,7 @@ static int selinux_parse_opts_str(char *options, case Opt_rootcontext: if (rootcontext) { rc = -EINVAL; - printk(KERN_WARNING SEL_MOUNT_FAIL_MSG); + pr_warn(SEL_MOUNT_FAIL_MSG); goto out_err; } rootcontext = match_strdup(&args[0]); @@ -1145,7 +1144,7 @@ static int selinux_parse_opts_str(char *options, case Opt_defcontext: if (context || defcontext) { rc = -EINVAL; - printk(KERN_WARNING SEL_MOUNT_FAIL_MSG); + pr_warn(SEL_MOUNT_FAIL_MSG); goto out_err; } defcontext = match_strdup(&args[0]); @@ -1158,7 +1157,7 @@ static int selinux_parse_opts_str(char *options, break; default: rc = -EINVAL; - printk(KERN_WARNING "SELinux: unknown mount option\n"); + pr_warn("SELinux: unknown mount option\n"); goto out_err; } @@ -1623,7 +1622,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent dput(dentry); if (rc < 0) { if (rc != -ENODATA) { - printk(KERN_WARNING "SELinux: %s: getxattr returned " + pr_warn("SELinux: %s: getxattr returned " "%d for dev=%s ino=%ld\n", __func__, -rc, inode->i_sb->s_id, inode->i_ino); kfree(context); @@ -1643,11 +1642,11 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent if (rc == -EINVAL) { if (printk_ratelimit()) - printk(KERN_NOTICE "SELinux: inode=%lu on dev=%s was found to have an invalid " + pr_notice("SELinux: inode=%lu on dev=%s was found to have an invalid " "context=%s. This indicates you may need to relabel the inode or the " "filesystem in question.\n", ino, dev, context); } else { - printk(KERN_WARNING "SELinux: %s: context_to_sid(%s) " + pr_warn("SELinux: %s: context_to_sid(%s) " "returned %d for dev=%s ino=%ld\n", __func__, context, -rc, dev, ino); } @@ -1785,8 +1784,7 @@ static int cred_has_capability(const struct cred *cred, sclass = initns ? SECCLASS_CAPABILITY2 : SECCLASS_CAP2_USERNS; break; default: - printk(KERN_ERR - "SELinux: out of range capability %d\n", cap); + pr_err("SELinux: out of range capability %d\n", cap); BUG(); return -EINVAL; } @@ -2029,7 +2027,7 @@ static int may_link(struct inode *dir, av = DIR__RMDIR; break; default: - printk(KERN_WARNING "SELinux: %s: unrecognized kind %d\n", + pr_warn("SELinux: %s: unrecognized kind %d\n", __func__, kind); return 0; } @@ -2875,7 +2873,7 @@ static int selinux_sb_remount(struct super_block *sb, void *data) mount_options[i], &sid, GFP_KERNEL); if (rc) { - printk(KERN_WARNING "SELinux: security_context_str_to_sid" + pr_warn("SELinux: security_context_str_to_sid" "(%s) failed for (dev %s, type %s) errno=%d\n", mount_options[i], sb->s_id, sb->s_type->name, rc); goto out_free_opts; @@ -2914,7 +2912,7 @@ out_free_secdata: free_secdata(secdata); return rc; out_bad_option: - printk(KERN_WARNING "SELinux: unable to change security options " + pr_warn("SELinux: unable to change security options " "during remount (dev %s, type=%s)\n", sb->s_id, sb->s_type->name); goto out_free_opts; @@ -3357,7 +3355,7 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name, rc = security_context_to_sid_force(&selinux_state, value, size, &newsid); if (rc) { - printk(KERN_ERR "SELinux: unable to map context to SID" + pr_err("SELinux: unable to map context to SID" "for (%s, %lu), rc=%d\n", inode->i_sb->s_id, inode->i_ino, -rc); return; @@ -4073,6 +4071,20 @@ static int selinux_kernel_read_file(struct file *file, return rc; } +static int selinux_kernel_load_data(enum kernel_load_data_id id) +{ + int rc = 0; + + switch (id) { + case LOADING_MODULE: + rc = selinux_kernel_module_from_file(NULL); + default: + break; + } + + return rc; +} + static int selinux_task_setpgid(struct task_struct *p, pid_t pgid) { return avc_has_perm(&selinux_state, @@ -4420,7 +4432,7 @@ static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad, } parse_error: - printk(KERN_WARNING + pr_warn( "SELinux: failure in selinux_parse_skb()," " unable to parse packet\n"); return ret; @@ -4463,7 +4475,7 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid) err = security_net_peersid_resolve(&selinux_state, nlbl_sid, nlbl_type, xfrm_sid, sid); if (unlikely(err)) { - printk(KERN_WARNING + pr_warn( "SELinux: failure in selinux_skb_peerlbl_sid()," " unable to determine packet's peer label\n"); return -EACCES; @@ -6972,6 +6984,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(kernel_act_as, selinux_kernel_act_as), LSM_HOOK_INIT(kernel_create_files_as, selinux_kernel_create_files_as), LSM_HOOK_INIT(kernel_module_request, selinux_kernel_module_request), + LSM_HOOK_INIT(kernel_load_data, selinux_kernel_load_data), LSM_HOOK_INIT(kernel_read_file, selinux_kernel_read_file), LSM_HOOK_INIT(task_setpgid, selinux_task_setpgid), LSM_HOOK_INIT(task_getpgid, selinux_task_getpgid), @@ -7126,11 +7139,11 @@ static __init int selinux_init(void) } if (!selinux_enabled) { - printk(KERN_INFO "SELinux: Disabled at boot.\n"); + pr_info("SELinux: Disabled at boot.\n"); return 0; } - printk(KERN_INFO "SELinux: Initializing.\n"); + pr_info("SELinux: Initializing.\n"); memset(&selinux_state, 0, sizeof(selinux_state)); enforcing_set(&selinux_state, selinux_enforcing_boot); @@ -7166,9 +7179,9 @@ static __init int selinux_init(void) panic("SELinux: Unable to register AVC LSM notifier callback\n"); if (selinux_enforcing_boot) - printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n"); + pr_debug("SELinux: Starting in enforcing mode\n"); else - printk(KERN_DEBUG "SELinux: Starting in permissive mode\n"); + pr_debug("SELinux: Starting in permissive mode\n"); return 0; } @@ -7180,10 +7193,10 @@ static void delayed_superblock_init(struct super_block *sb, void *unused) void selinux_complete_init(void) { - printk(KERN_DEBUG "SELinux: Completing initialization.\n"); + pr_debug("SELinux: Completing initialization.\n"); /* Set up any superblocks initialized prior to the policy load. */ - printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n"); + pr_debug("SELinux: Setting up existing superblocks.\n"); iterate_supers(delayed_superblock_init, NULL); } @@ -7258,7 +7271,7 @@ static int __init selinux_nf_ip_init(void) if (!selinux_enabled) return 0; - printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n"); + pr_debug("SELinux: Registering netfilter hooks\n"); err = register_pernet_subsys(&selinux_net_ops); if (err) @@ -7271,7 +7284,7 @@ __initcall(selinux_nf_ip_init); #ifdef CONFIG_SECURITY_SELINUX_DISABLE static void selinux_nf_ip_exit(void) { - printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n"); + pr_debug("SELinux: Unregistering netfilter hooks\n"); unregister_pernet_subsys(&selinux_net_ops); } @@ -7300,7 +7313,7 @@ int selinux_disable(struct selinux_state *state) state->disabled = 1; - printk(KERN_INFO "SELinux: Disabled at runtime.\n"); + pr_info("SELinux: Disabled at runtime.\n"); selinux_enabled = 0; diff --git a/security/selinux/netif.c b/security/selinux/netif.c index ac65f7417413..8c738c189942 100644 --- a/security/selinux/netif.c +++ b/security/selinux/netif.c @@ -145,9 +145,8 @@ static int sel_netif_sid_slow(struct net *ns, int ifindex, u32 *sid) dev = dev_get_by_index(ns, ifindex); if (unlikely(dev == NULL)) { - printk(KERN_WARNING - "SELinux: failure in sel_netif_sid_slow()," - " invalid network interface (%d)\n", ifindex); + pr_warn("SELinux: failure in %s(), invalid network interface (%d)\n", + __func__, ifindex); return -ENOENT; } @@ -177,10 +176,8 @@ out: spin_unlock_bh(&sel_netif_lock); dev_put(dev); if (unlikely(ret)) { - printk(KERN_WARNING - "SELinux: failure in sel_netif_sid_slow()," - " unable to determine network interface label (%d)\n", - ifindex); + pr_warn("SELinux: failure in %s(), unable to determine network interface label (%d)\n", + __func__, ifindex); kfree(new); } return ret; diff --git a/security/selinux/netlink.c b/security/selinux/netlink.c index 828fb6a4e941..8a8a72507437 100644 --- a/security/selinux/netlink.c +++ b/security/selinux/netlink.c @@ -94,7 +94,7 @@ out: out_kfree_skb: kfree_skb(skb); oom: - printk(KERN_ERR "SELinux: OOM in %s\n", __func__); + pr_err("SELinux: OOM in %s\n", __func__); goto out; } diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c index 6dd89b89bc1f..afa0d432436b 100644 --- a/security/selinux/netnode.c +++ b/security/selinux/netnode.c @@ -238,9 +238,8 @@ static int sel_netnode_sid_slow(void *addr, u16 family, u32 *sid) out: spin_unlock_bh(&sel_netnode_lock); if (unlikely(ret)) { - printk(KERN_WARNING - "SELinux: failure in sel_netnode_sid_slow()," - " unable to determine network node label\n"); + pr_warn("SELinux: failure in %s(), unable to determine network node label\n", + __func__); kfree(new); } return ret; diff --git a/security/selinux/netport.c b/security/selinux/netport.c index 9ed4c5064a5e..7a141cadbffc 100644 --- a/security/selinux/netport.c +++ b/security/selinux/netport.c @@ -173,9 +173,8 @@ static int sel_netport_sid_slow(u8 protocol, u16 pnum, u32 *sid) out: spin_unlock_bh(&sel_netport_lock); if (unlikely(ret)) { - printk(KERN_WARNING - "SELinux: failure in sel_netport_sid_slow()," - " unable to determine network port label\n"); + pr_warn("SELinux: failure in %s(), unable to determine network port label\n", + __func__); kfree(new); } return ret; diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c index 7b7433a1a34c..74b951f55608 100644 --- a/security/selinux/nlmsgtab.c +++ b/security/selinux/nlmsgtab.c @@ -159,7 +159,7 @@ int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm) switch (sclass) { case SECCLASS_NETLINK_ROUTE_SOCKET: /* RTM_MAX always point to RTM_SETxxxx, ie RTM_NEWxxx + 3 */ - BUILD_BUG_ON(RTM_MAX != (RTM_NEWCACHEREPORT + 3)); + BUILD_BUG_ON(RTM_MAX != (RTM_NEWCHAIN + 3)); err = nlmsg_perm(nlmsg_type, perm, nlmsg_route_perms, sizeof(nlmsg_route_perms)); break; diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 79d3709b0671..f3a5a138a096 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -614,7 +614,7 @@ static ssize_t sel_write_context(struct file *file, char *buf, size_t size) length = -ERANGE; if (len > SIMPLE_TRANSACTION_LIMIT) { - printk(KERN_ERR "SELinux: %s: context size (%u) exceeds " + pr_err("SELinux: %s: context size (%u) exceeds " "payload max\n", __func__, len); goto out; } @@ -767,7 +767,7 @@ static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size); static ssize_t sel_write_user(struct file *file, char *buf, size_t size); static ssize_t sel_write_member(struct file *file, char *buf, size_t size); -static ssize_t (*write_op[])(struct file *, char *, size_t) = { +static ssize_t (*const write_op[])(struct file *, char *, size_t) = { [SEL_ACCESS] = sel_write_access, [SEL_CREATE] = sel_write_create, [SEL_RELABEL] = sel_write_relabel, @@ -950,7 +950,7 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size) length = -ERANGE; if (len > SIMPLE_TRANSACTION_LIMIT) { - printk(KERN_ERR "SELinux: %s: context size (%u) exceeds " + pr_err("SELinux: %s: context size (%u) exceeds " "payload max\n", __func__, len); goto out; } @@ -1141,7 +1141,7 @@ static ssize_t sel_write_member(struct file *file, char *buf, size_t size) length = -ERANGE; if (len > SIMPLE_TRANSACTION_LIMIT) { - printk(KERN_ERR "SELinux: %s: context size (%u) exceeds " + pr_err("SELinux: %s: context size (%u) exceeds " "payload max\n", __func__, len); goto out; } @@ -1365,13 +1365,18 @@ static int sel_make_bools(struct selinux_fs_info *fsi) ret = -ENOMEM; inode = sel_make_inode(dir->d_sb, S_IFREG | S_IRUGO | S_IWUSR); - if (!inode) + if (!inode) { + dput(dentry); goto out; + } ret = -ENAMETOOLONG; len = snprintf(page, PAGE_SIZE, "/%s/%s", BOOL_DIR_NAME, names[i]); - if (len >= PAGE_SIZE) + if (len >= PAGE_SIZE) { + dput(dentry); + iput(inode); goto out; + } isec = (struct inode_security_struct *)inode->i_security; ret = security_genfs_sid(fsi->state, "selinuxfs", page, @@ -1586,8 +1591,10 @@ static int sel_make_avc_files(struct dentry *dir) return -ENOMEM; inode = sel_make_inode(dir->d_sb, S_IFREG|files[i].mode); - if (!inode) + if (!inode) { + dput(dentry); return -ENOMEM; + } inode->i_fop = files[i].ops; inode->i_ino = ++fsi->last_ino; @@ -1632,8 +1639,10 @@ static int sel_make_initcon_files(struct dentry *dir) return -ENOMEM; inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO); - if (!inode) + if (!inode) { + dput(dentry); return -ENOMEM; + } inode->i_fop = &sel_initcon_ops; inode->i_ino = i|SEL_INITCON_INO_OFFSET; @@ -1733,8 +1742,10 @@ static int sel_make_perm_files(char *objclass, int classvalue, rc = -ENOMEM; inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO); - if (!inode) + if (!inode) { + dput(dentry); goto out; + } inode->i_fop = &sel_perm_ops; /* i+1 since perm values are 1-indexed */ @@ -1763,8 +1774,10 @@ static int sel_make_class_dir_entries(char *classname, int index, return -ENOMEM; inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO); - if (!inode) + if (!inode) { + dput(dentry); return -ENOMEM; + } inode->i_fop = &sel_class_ops; inode->i_ino = sel_class_to_ino(index); @@ -1838,8 +1851,10 @@ static int sel_make_policycap(struct selinux_fs_info *fsi) return -ENOMEM; inode = sel_make_inode(fsi->sb, S_IFREG | 0444); - if (inode == NULL) + if (inode == NULL) { + dput(dentry); return -ENOMEM; + } inode->i_fop = &sel_policycap_ops; inode->i_ino = iter | SEL_POLICYCAP_INO_OFFSET; @@ -1932,8 +1947,10 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) ret = -ENOMEM; inode = sel_make_inode(sb, S_IFCHR | S_IRUGO | S_IWUGO); - if (!inode) + if (!inode) { + dput(dentry); goto err; + } inode->i_ino = ++fsi->last_ino; isec = (struct inode_security_struct *)inode->i_security; @@ -1984,7 +2001,7 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) goto err; return 0; err: - printk(KERN_ERR "SELinux: %s: failed while creating inodes\n", + pr_err("SELinux: %s: failed while creating inodes\n", __func__); selinux_fs_info_free(sb); @@ -2034,7 +2051,7 @@ static int __init init_sel_fs(void) selinux_null.mnt = selinuxfs_mount = kern_mount(&sel_fs_type); if (IS_ERR(selinuxfs_mount)) { - printk(KERN_ERR "selinuxfs: could not mount!\n"); + pr_err("selinuxfs: could not mount!\n"); err = PTR_ERR(selinuxfs_mount); selinuxfs_mount = NULL; } diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c index a2c9148b0662..c0417cf17fee 100644 --- a/security/selinux/ss/avtab.c +++ b/security/selinux/ss/avtab.c @@ -338,7 +338,7 @@ int avtab_alloc(struct avtab *h, u32 nrules) h->nel = 0; h->nslot = nslot; h->mask = mask; - printk(KERN_DEBUG "SELinux: %d avtab hash slots, %d rules.\n", + pr_debug("SELinux: %d avtab hash slots, %d rules.\n", h->nslot, nrules); return 0; } @@ -368,7 +368,7 @@ void avtab_hash_eval(struct avtab *h, char *tag) } } - printk(KERN_DEBUG "SELinux: %s: %d entries and %d/%d buckets used, " + pr_debug("SELinux: %s: %d entries and %d/%d buckets used, " "longest chain length %d sum of chain length^2 %llu\n", tag, h->nel, slots_used, h->nslot, max_chain_len, chain2_len_sum); @@ -407,18 +407,18 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, if (vers < POLICYDB_VERSION_AVTAB) { rc = next_entry(buf32, fp, sizeof(u32)); if (rc) { - printk(KERN_ERR "SELinux: avtab: truncated entry\n"); + pr_err("SELinux: avtab: truncated entry\n"); return rc; } items2 = le32_to_cpu(buf32[0]); if (items2 > ARRAY_SIZE(buf32)) { - printk(KERN_ERR "SELinux: avtab: entry overflow\n"); + pr_err("SELinux: avtab: entry overflow\n"); return -EINVAL; } rc = next_entry(buf32, fp, sizeof(u32)*items2); if (rc) { - printk(KERN_ERR "SELinux: avtab: truncated entry\n"); + pr_err("SELinux: avtab: truncated entry\n"); return rc; } items = 0; @@ -426,19 +426,19 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, val = le32_to_cpu(buf32[items++]); key.source_type = (u16)val; if (key.source_type != val) { - printk(KERN_ERR "SELinux: avtab: truncated source type\n"); + pr_err("SELinux: avtab: truncated source type\n"); return -EINVAL; } val = le32_to_cpu(buf32[items++]); key.target_type = (u16)val; if (key.target_type != val) { - printk(KERN_ERR "SELinux: avtab: truncated target type\n"); + pr_err("SELinux: avtab: truncated target type\n"); return -EINVAL; } val = le32_to_cpu(buf32[items++]); key.target_class = (u16)val; if (key.target_class != val) { - printk(KERN_ERR "SELinux: avtab: truncated target class\n"); + pr_err("SELinux: avtab: truncated target class\n"); return -EINVAL; } @@ -446,16 +446,16 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, enabled = (val & AVTAB_ENABLED_OLD) ? AVTAB_ENABLED : 0; if (!(val & (AVTAB_AV | AVTAB_TYPE))) { - printk(KERN_ERR "SELinux: avtab: null entry\n"); + pr_err("SELinux: avtab: null entry\n"); return -EINVAL; } if ((val & AVTAB_AV) && (val & AVTAB_TYPE)) { - printk(KERN_ERR "SELinux: avtab: entry has both access vectors and types\n"); + pr_err("SELinux: avtab: entry has both access vectors and types\n"); return -EINVAL; } if (val & AVTAB_XPERMS) { - printk(KERN_ERR "SELinux: avtab: entry has extended permissions\n"); + pr_err("SELinux: avtab: entry has extended permissions\n"); return -EINVAL; } @@ -470,7 +470,8 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, } if (items != items2) { - printk(KERN_ERR "SELinux: avtab: entry only had %d items, expected %d\n", items2, items); + pr_err("SELinux: avtab: entry only had %d items, expected %d\n", + items2, items); return -EINVAL; } return 0; @@ -478,7 +479,7 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, rc = next_entry(buf16, fp, sizeof(u16)*4); if (rc) { - printk(KERN_ERR "SELinux: avtab: truncated entry\n"); + pr_err("SELinux: avtab: truncated entry\n"); return rc; } @@ -491,7 +492,7 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, if (!policydb_type_isvalid(pol, key.source_type) || !policydb_type_isvalid(pol, key.target_type) || !policydb_class_isvalid(pol, key.target_class)) { - printk(KERN_ERR "SELinux: avtab: invalid type or class\n"); + pr_err("SELinux: avtab: invalid type or class\n"); return -EINVAL; } @@ -501,13 +502,13 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, set++; } if (!set || set > 1) { - printk(KERN_ERR "SELinux: avtab: more than one specifier\n"); + pr_err("SELinux: avtab: more than one specifier\n"); return -EINVAL; } if ((vers < POLICYDB_VERSION_XPERMS_IOCTL) && (key.specified & AVTAB_XPERMS)) { - printk(KERN_ERR "SELinux: avtab: policy version %u does not " + pr_err("SELinux: avtab: policy version %u does not " "support extended permissions rules and one " "was specified\n", vers); return -EINVAL; @@ -515,17 +516,17 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, memset(&xperms, 0, sizeof(struct avtab_extended_perms)); rc = next_entry(&xperms.specified, fp, sizeof(u8)); if (rc) { - printk(KERN_ERR "SELinux: avtab: truncated entry\n"); + pr_err("SELinux: avtab: truncated entry\n"); return rc; } rc = next_entry(&xperms.driver, fp, sizeof(u8)); if (rc) { - printk(KERN_ERR "SELinux: avtab: truncated entry\n"); + pr_err("SELinux: avtab: truncated entry\n"); return rc; } rc = next_entry(buf32, fp, sizeof(u32)*ARRAY_SIZE(xperms.perms.p)); if (rc) { - printk(KERN_ERR "SELinux: avtab: truncated entry\n"); + pr_err("SELinux: avtab: truncated entry\n"); return rc; } for (i = 0; i < ARRAY_SIZE(xperms.perms.p); i++) @@ -534,14 +535,14 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, } else { rc = next_entry(buf32, fp, sizeof(u32)); if (rc) { - printk(KERN_ERR "SELinux: avtab: truncated entry\n"); + pr_err("SELinux: avtab: truncated entry\n"); return rc; } datum.u.data = le32_to_cpu(*buf32); } if ((key.specified & AVTAB_TYPE) && !policydb_type_isvalid(pol, datum.u.data)) { - printk(KERN_ERR "SELinux: avtab: invalid type\n"); + pr_err("SELinux: avtab: invalid type\n"); return -EINVAL; } return insertf(a, &key, &datum, p); @@ -562,12 +563,12 @@ int avtab_read(struct avtab *a, void *fp, struct policydb *pol) rc = next_entry(buf, fp, sizeof(u32)); if (rc < 0) { - printk(KERN_ERR "SELinux: avtab: truncated table\n"); + pr_err("SELinux: avtab: truncated table\n"); goto bad; } nel = le32_to_cpu(buf[0]); if (!nel) { - printk(KERN_ERR "SELinux: avtab: table is empty\n"); + pr_err("SELinux: avtab: table is empty\n"); rc = -EINVAL; goto bad; } @@ -580,9 +581,9 @@ int avtab_read(struct avtab *a, void *fp, struct policydb *pol) rc = avtab_read_item(a, fp, pol, avtab_insertf, NULL); if (rc) { if (rc == -ENOMEM) - printk(KERN_ERR "SELinux: avtab: out of memory\n"); + pr_err("SELinux: avtab: out of memory\n"); else if (rc == -EEXIST) - printk(KERN_ERR "SELinux: avtab: duplicate entry\n"); + pr_err("SELinux: avtab: duplicate entry\n"); goto bad; } diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c index c91543a617ac..f49e522e932d 100644 --- a/security/selinux/ss/conditional.c +++ b/security/selinux/ss/conditional.c @@ -96,7 +96,7 @@ int evaluate_cond_node(struct policydb *p, struct cond_node *node) if (new_state != node->cur_state) { node->cur_state = new_state; if (new_state == -1) - printk(KERN_ERR "SELinux: expression result was undefined - disabling all rules.\n"); + pr_err("SELinux: expression result was undefined - disabling all rules.\n"); /* turn the rules on or off */ for (cur = node->true_list; cur; cur = cur->next) { if (new_state <= 0) @@ -287,7 +287,7 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum */ if (k->specified & AVTAB_TYPE) { if (avtab_search(&p->te_avtab, k)) { - printk(KERN_ERR "SELinux: type rule already exists outside of a conditional.\n"); + pr_err("SELinux: type rule already exists outside of a conditional.\n"); goto err; } /* @@ -302,7 +302,7 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum node_ptr = avtab_search_node(&p->te_cond_avtab, k); if (node_ptr) { if (avtab_search_node_next(node_ptr, k->specified)) { - printk(KERN_ERR "SELinux: too many conflicting type rules.\n"); + pr_err("SELinux: too many conflicting type rules.\n"); goto err; } found = 0; @@ -313,13 +313,13 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum } } if (!found) { - printk(KERN_ERR "SELinux: conflicting type rules.\n"); + pr_err("SELinux: conflicting type rules.\n"); goto err; } } } else { if (avtab_search(&p->te_cond_avtab, k)) { - printk(KERN_ERR "SELinux: conflicting type rules when adding type rule for true.\n"); + pr_err("SELinux: conflicting type rules when adding type rule for true.\n"); goto err; } } @@ -327,7 +327,7 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d); if (!node_ptr) { - printk(KERN_ERR "SELinux: could not insert rule.\n"); + pr_err("SELinux: could not insert rule.\n"); rc = -ENOMEM; goto err; } @@ -387,12 +387,12 @@ static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list * static int expr_isvalid(struct policydb *p, struct cond_expr *expr) { if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) { - printk(KERN_ERR "SELinux: conditional expressions uses unknown operator.\n"); + pr_err("SELinux: conditional expressions uses unknown operator.\n"); return 0; } if (expr->bool > p->p_bools.nprim) { - printk(KERN_ERR "SELinux: conditional expressions uses unknown bool.\n"); + pr_err("SELinux: conditional expressions uses unknown bool.\n"); return 0; } return 1; diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c index 5ae8c61b75bf..8f624f80055b 100644 --- a/security/selinux/ss/ebitmap.c +++ b/security/selinux/ss/ebitmap.c @@ -362,7 +362,7 @@ int ebitmap_read(struct ebitmap *e, void *fp) count = le32_to_cpu(buf[2]); if (mapunit != BITS_PER_U64) { - printk(KERN_ERR "SELinux: ebitmap: map size %u does not " + pr_err("SELinux: ebitmap: map size %u does not " "match my size %zd (high bit was %d)\n", mapunit, BITS_PER_U64, e->highbit); goto bad; @@ -383,19 +383,19 @@ int ebitmap_read(struct ebitmap *e, void *fp) for (i = 0; i < count; i++) { rc = next_entry(&startbit, fp, sizeof(u32)); if (rc < 0) { - printk(KERN_ERR "SELinux: ebitmap: truncated map\n"); + pr_err("SELinux: ebitmap: truncated map\n"); goto bad; } startbit = le32_to_cpu(startbit); if (startbit & (mapunit - 1)) { - printk(KERN_ERR "SELinux: ebitmap start bit (%d) is " + pr_err("SELinux: ebitmap start bit (%d) is " "not a multiple of the map unit size (%u)\n", startbit, mapunit); goto bad; } if (startbit > e->highbit - mapunit) { - printk(KERN_ERR "SELinux: ebitmap start bit (%d) is " + pr_err("SELinux: ebitmap start bit (%d) is " "beyond the end of the bitmap (%u)\n", startbit, (e->highbit - mapunit)); goto bad; @@ -405,8 +405,7 @@ int ebitmap_read(struct ebitmap *e, void *fp) struct ebitmap_node *tmp; tmp = kmem_cache_zalloc(ebitmap_node_cachep, GFP_KERNEL); if (!tmp) { - printk(KERN_ERR - "SELinux: ebitmap: out of memory\n"); + pr_err("SELinux: ebitmap: out of memory\n"); rc = -ENOMEM; goto bad; } @@ -418,7 +417,7 @@ int ebitmap_read(struct ebitmap *e, void *fp) e->node = tmp; n = tmp; } else if (startbit <= n->startbit) { - printk(KERN_ERR "SELinux: ebitmap: start bit %d" + pr_err("SELinux: ebitmap: start bit %d" " comes after start bit %d\n", startbit, n->startbit); goto bad; @@ -426,7 +425,7 @@ int ebitmap_read(struct ebitmap *e, void *fp) rc = next_entry(&map, fp, sizeof(u64)); if (rc < 0) { - printk(KERN_ERR "SELinux: ebitmap: truncated map\n"); + pr_err("SELinux: ebitmap: truncated map\n"); goto bad; } map = le64_to_cpu(map); diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 6e8c8056d7ad..e9394e7adc84 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -504,7 +504,7 @@ static void hash_eval(struct hashtab *h, const char *hash_name) struct hashtab_info info; hashtab_stat(h, &info); - printk(KERN_DEBUG "SELinux: %s: %d entries and %d/%d buckets used, " + pr_debug("SELinux: %s: %d entries and %d/%d buckets used, " "longest chain length %d\n", hash_name, h->nel, info.slots_used, h->size, info.max_chain_len); } @@ -533,15 +533,17 @@ static int policydb_index(struct policydb *p) { int i, rc; - printk(KERN_DEBUG "SELinux: %d users, %d roles, %d types, %d bools", - p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim); if (p->mls_enabled) - printk(KERN_CONT ", %d sens, %d cats", p->p_levels.nprim, - p->p_cats.nprim); - printk(KERN_CONT "\n"); + pr_debug("SELinux: %d users, %d roles, %d types, %d bools, %d sens, %d cats\n", + p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, + p->p_bools.nprim, p->p_levels.nprim, p->p_cats.nprim); + else + pr_debug("SELinux: %d users, %d roles, %d types, %d bools\n", + p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, + p->p_bools.nprim); - printk(KERN_DEBUG "SELinux: %d classes, %d rules\n", - p->p_classes.nprim, p->te_avtab.nel); + pr_debug("SELinux: %d classes, %d rules\n", + p->p_classes.nprim, p->te_avtab.nel); #ifdef DEBUG_HASHES avtab_hash_eval(&p->te_avtab, "rules"); @@ -897,7 +899,7 @@ int policydb_load_isids(struct policydb *p, struct sidtab *s) rc = sidtab_init(s); if (rc) { - printk(KERN_ERR "SELinux: out of memory on SID table init\n"); + pr_err("SELinux: out of memory on SID table init\n"); goto out; } @@ -905,14 +907,14 @@ int policydb_load_isids(struct policydb *p, struct sidtab *s) for (c = head; c; c = c->next) { rc = -EINVAL; if (!c->context[0].user) { - printk(KERN_ERR "SELinux: SID %s was never defined.\n", + pr_err("SELinux: SID %s was never defined.\n", c->u.name); goto out; } rc = sidtab_insert(s, c->sid[0], &c->context[0]); if (rc) { - printk(KERN_ERR "SELinux: unable to load initial SID %s.\n", + pr_err("SELinux: unable to load initial SID %s.\n", c->u.name); goto out; } @@ -1005,13 +1007,13 @@ static int mls_read_range_helper(struct mls_range *r, void *fp) rc = -EINVAL; items = le32_to_cpu(buf[0]); if (items > ARRAY_SIZE(buf)) { - printk(KERN_ERR "SELinux: mls: range overflow\n"); + pr_err("SELinux: mls: range overflow\n"); goto out; } rc = next_entry(buf, fp, sizeof(u32) * items); if (rc) { - printk(KERN_ERR "SELinux: mls: truncated range\n"); + pr_err("SELinux: mls: truncated range\n"); goto out; } @@ -1023,19 +1025,19 @@ static int mls_read_range_helper(struct mls_range *r, void *fp) rc = ebitmap_read(&r->level[0].cat, fp); if (rc) { - printk(KERN_ERR "SELinux: mls: error reading low categories\n"); + pr_err("SELinux: mls: error reading low categories\n"); goto out; } if (items > 1) { rc = ebitmap_read(&r->level[1].cat, fp); if (rc) { - printk(KERN_ERR "SELinux: mls: error reading high categories\n"); + pr_err("SELinux: mls: error reading high categories\n"); goto bad_high; } } else { rc = ebitmap_cpy(&r->level[1].cat, &r->level[0].cat); if (rc) { - printk(KERN_ERR "SELinux: mls: out of memory\n"); + pr_err("SELinux: mls: out of memory\n"); goto bad_high; } } @@ -1060,7 +1062,7 @@ static int context_read_and_validate(struct context *c, rc = next_entry(buf, fp, sizeof buf); if (rc) { - printk(KERN_ERR "SELinux: context truncated\n"); + pr_err("SELinux: context truncated\n"); goto out; } c->user = le32_to_cpu(buf[0]); @@ -1069,14 +1071,14 @@ static int context_read_and_validate(struct context *c, if (p->policyvers >= POLICYDB_VERSION_MLS) { rc = mls_read_range_helper(&c->range, fp); if (rc) { - printk(KERN_ERR "SELinux: error reading MLS range of context\n"); + pr_err("SELinux: error reading MLS range of context\n"); goto out; } } rc = -EINVAL; if (!policydb_context_isvalid(p, c)) { - printk(KERN_ERR "SELinux: invalid security context\n"); + pr_err("SELinux: invalid security context\n"); context_destroy(c); goto out; } @@ -1352,7 +1354,8 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) rc = -EINVAL; cladatum->comdatum = hashtab_search(p->p_commons.table, cladatum->comkey); if (!cladatum->comdatum) { - printk(KERN_ERR "SELinux: unknown common %s\n", cladatum->comkey); + pr_err("SELinux: unknown common %s\n", + cladatum->comkey); goto bad; } } @@ -1444,7 +1447,7 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp) if (strcmp(key, OBJECT_R) == 0) { rc = -EINVAL; if (role->value != OBJECT_R_VAL) { - printk(KERN_ERR "SELinux: Role %s has wrong value %d\n", + pr_err("SELinux: Role %s has wrong value %d\n", OBJECT_R, role->value); goto bad; } @@ -1522,14 +1525,14 @@ static int mls_read_level(struct mls_level *lp, void *fp) rc = next_entry(buf, fp, sizeof buf); if (rc) { - printk(KERN_ERR "SELinux: mls: truncated level\n"); + pr_err("SELinux: mls: truncated level\n"); return rc; } lp->sens = le32_to_cpu(buf[0]); rc = ebitmap_read(&lp->cat, fp); if (rc) { - printk(KERN_ERR "SELinux: mls: error reading level categories\n"); + pr_err("SELinux: mls: error reading level categories\n"); return rc; } return 0; @@ -1683,7 +1686,7 @@ static int user_bounds_sanity_check(void *key, void *datum, void *datap) unsigned long bit; if (++depth == POLICYDB_BOUNDS_MAXDEPTH) { - printk(KERN_ERR "SELinux: user %s: " + pr_err("SELinux: user %s: " "too deep or looped boundary", (char *) key); return -EINVAL; @@ -1694,8 +1697,7 @@ static int user_bounds_sanity_check(void *key, void *datum, void *datap) if (ebitmap_get_bit(&upper->roles, bit)) continue; - printk(KERN_ERR - "SELinux: boundary violated policy: " + pr_err("SELinux: boundary violated policy: " "user=%s role=%s bounds=%s\n", sym_name(p, SYM_USERS, user->value - 1), sym_name(p, SYM_ROLES, bit), @@ -1720,7 +1722,7 @@ static int role_bounds_sanity_check(void *key, void *datum, void *datap) unsigned long bit; if (++depth == POLICYDB_BOUNDS_MAXDEPTH) { - printk(KERN_ERR "SELinux: role %s: " + pr_err("SELinux: role %s: " "too deep or looped bounds\n", (char *) key); return -EINVAL; @@ -1731,8 +1733,7 @@ static int role_bounds_sanity_check(void *key, void *datum, void *datap) if (ebitmap_get_bit(&upper->types, bit)) continue; - printk(KERN_ERR - "SELinux: boundary violated policy: " + pr_err("SELinux: boundary violated policy: " "role=%s type=%s bounds=%s\n", sym_name(p, SYM_ROLES, role->value - 1), sym_name(p, SYM_TYPES, bit), @@ -1754,7 +1755,7 @@ static int type_bounds_sanity_check(void *key, void *datum, void *datap) upper = datum; while (upper->bounds) { if (++depth == POLICYDB_BOUNDS_MAXDEPTH) { - printk(KERN_ERR "SELinux: type %s: " + pr_err("SELinux: type %s: " "too deep or looped boundary\n", (char *) key); return -EINVAL; @@ -1765,7 +1766,7 @@ static int type_bounds_sanity_check(void *key, void *datum, void *datap) BUG_ON(!upper); if (upper->attribute) { - printk(KERN_ERR "SELinux: type %s: " + pr_err("SELinux: type %s: " "bounded by attribute %s", (char *) key, sym_name(p, SYM_TYPES, upper->value - 1)); @@ -1888,7 +1889,7 @@ static int range_read(struct policydb *p, void *fp) rc = -EINVAL; if (!mls_range_isvalid(p, r)) { - printk(KERN_WARNING "SELinux: rangetrans: invalid range\n"); + pr_warn("SELinux: rangetrans: invalid range\n"); goto out; } @@ -2023,7 +2024,7 @@ static int genfs_read(struct policydb *p, void *fp) genfs_p = genfs, genfs = genfs->next) { rc = -EINVAL; if (strcmp(newgenfs->fstype, genfs->fstype) == 0) { - printk(KERN_ERR "SELinux: dup genfs fstype %s\n", + pr_err("SELinux: dup genfs fstype %s\n", newgenfs->fstype); goto out; } @@ -2073,7 +2074,7 @@ static int genfs_read(struct policydb *p, void *fp) if (!strcmp(newc->u.name, c->u.name) && (!c->v.sclass || !newc->v.sclass || newc->v.sclass == c->v.sclass)) { - printk(KERN_ERR "SELinux: dup genfs entry (%s,%s)\n", + pr_err("SELinux: dup genfs entry (%s,%s)\n", genfs->fstype, c->u.name); goto out; } @@ -2295,7 +2296,7 @@ int policydb_read(struct policydb *p, void *fp) rc = -EINVAL; if (le32_to_cpu(buf[0]) != POLICYDB_MAGIC) { - printk(KERN_ERR "SELinux: policydb magic number 0x%x does " + pr_err("SELinux: policydb magic number 0x%x does " "not match expected magic number 0x%x\n", le32_to_cpu(buf[0]), POLICYDB_MAGIC); goto bad; @@ -2304,7 +2305,7 @@ int policydb_read(struct policydb *p, void *fp) rc = -EINVAL; len = le32_to_cpu(buf[1]); if (len != strlen(POLICYDB_STRING)) { - printk(KERN_ERR "SELinux: policydb string length %d does not " + pr_err("SELinux: policydb string length %d does not " "match expected length %zu\n", len, strlen(POLICYDB_STRING)); goto bad; @@ -2313,14 +2314,14 @@ int policydb_read(struct policydb *p, void *fp) rc = -ENOMEM; policydb_str = kmalloc(len + 1, GFP_KERNEL); if (!policydb_str) { - printk(KERN_ERR "SELinux: unable to allocate memory for policydb " + pr_err("SELinux: unable to allocate memory for policydb " "string of length %d\n", len); goto bad; } rc = next_entry(policydb_str, fp, len); if (rc) { - printk(KERN_ERR "SELinux: truncated policydb string identifier\n"); + pr_err("SELinux: truncated policydb string identifier\n"); kfree(policydb_str); goto bad; } @@ -2328,7 +2329,7 @@ int policydb_read(struct policydb *p, void *fp) rc = -EINVAL; policydb_str[len] = '\0'; if (strcmp(policydb_str, POLICYDB_STRING)) { - printk(KERN_ERR "SELinux: policydb string %s does not match " + pr_err("SELinux: policydb string %s does not match " "my string %s\n", policydb_str, POLICYDB_STRING); kfree(policydb_str); goto bad; @@ -2346,7 +2347,7 @@ int policydb_read(struct policydb *p, void *fp) p->policyvers = le32_to_cpu(buf[0]); if (p->policyvers < POLICYDB_VERSION_MIN || p->policyvers > POLICYDB_VERSION_MAX) { - printk(KERN_ERR "SELinux: policydb version %d does not match " + pr_err("SELinux: policydb version %d does not match " "my version range %d-%d\n", le32_to_cpu(buf[0]), POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX); goto bad; @@ -2357,7 +2358,7 @@ int policydb_read(struct policydb *p, void *fp) rc = -EINVAL; if (p->policyvers < POLICYDB_VERSION_MLS) { - printk(KERN_ERR "SELinux: security policydb version %d " + pr_err("SELinux: security policydb version %d " "(MLS) not backwards compatible\n", p->policyvers); goto bad; @@ -2381,7 +2382,7 @@ int policydb_read(struct policydb *p, void *fp) rc = -EINVAL; info = policydb_lookup_compat(p->policyvers); if (!info) { - printk(KERN_ERR "SELinux: unable to find policy compat info " + pr_err("SELinux: unable to find policy compat info " "for version %d\n", p->policyvers); goto bad; } @@ -2389,7 +2390,7 @@ int policydb_read(struct policydb *p, void *fp) rc = -EINVAL; if (le32_to_cpu(buf[2]) != info->sym_num || le32_to_cpu(buf[3]) != info->ocon_num) { - printk(KERN_ERR "SELinux: policydb table sizes (%d,%d) do " + pr_err("SELinux: policydb table sizes (%d,%d) do " "not match mine (%d,%d)\n", le32_to_cpu(buf[2]), le32_to_cpu(buf[3]), info->sym_num, info->ocon_num); @@ -3417,7 +3418,7 @@ int policydb_write(struct policydb *p, void *fp) * careful if you ever try to remove this restriction */ if (p->policyvers < POLICYDB_VERSION_AVTAB) { - printk(KERN_ERR "SELinux: refusing to write policy version %d." + pr_err("SELinux: refusing to write policy version %d." " Because it is less than version %d\n", p->policyvers, POLICYDB_VERSION_AVTAB); return -EINVAL; @@ -3446,7 +3447,7 @@ int policydb_write(struct policydb *p, void *fp) /* Write the version, config, and table sizes. */ info = policydb_lookup_compat(p->policyvers); if (!info) { - printk(KERN_ERR "SELinux: compatibility lookup failed for policy " + pr_err("SELinux: compatibility lookup failed for policy " "version %d", p->policyvers); return -EINVAL; } diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index dd2ceec06fef..f3def298a90e 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -136,8 +136,7 @@ static int selinux_set_mapping(struct policydb *pol, p_out->value = string_to_security_class(pol, p_in->name); if (!p_out->value) { - printk(KERN_INFO - "SELinux: Class %s not defined in policy.\n", + pr_info("SELinux: Class %s not defined in policy.\n", p_in->name); if (pol->reject_unknown) goto err; @@ -156,8 +155,7 @@ static int selinux_set_mapping(struct policydb *pol, p_out->perms[k] = string_to_av_perm(pol, p_out->value, p_in->perms[k]); if (!p_out->perms[k]) { - printk(KERN_INFO - "SELinux: Permission %s in class %s not defined in policy.\n", + pr_info("SELinux: Permission %s in class %s not defined in policy.\n", p_in->perms[k], p_in->name); if (pol->reject_unknown) goto err; @@ -170,7 +168,7 @@ static int selinux_set_mapping(struct policydb *pol, } if (print_unknown_handle) - printk(KERN_INFO "SELinux: the above unknown classes and permissions will be %s\n", + pr_info("SELinux: the above unknown classes and permissions will be %s\n", pol->allow_unknown ? "allowed" : "denied"); out_map->size = i; @@ -644,7 +642,7 @@ static void context_struct_compute_av(struct policydb *policydb, if (unlikely(!tclass || tclass > policydb->p_classes.nprim)) { if (printk_ratelimit()) - printk(KERN_WARNING "SELinux: Invalid class %hu\n", tclass); + pr_warn("SELinux: Invalid class %hu\n", tclass); return; } @@ -793,7 +791,7 @@ static int security_compute_validatetrans(struct selinux_state *state, ocontext = sidtab_search(sidtab, oldsid); if (!ocontext) { - printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", + pr_err("SELinux: %s: unrecognized SID %d\n", __func__, oldsid); rc = -EINVAL; goto out; @@ -801,7 +799,7 @@ static int security_compute_validatetrans(struct selinux_state *state, ncontext = sidtab_search(sidtab, newsid); if (!ncontext) { - printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", + pr_err("SELinux: %s: unrecognized SID %d\n", __func__, newsid); rc = -EINVAL; goto out; @@ -809,7 +807,7 @@ static int security_compute_validatetrans(struct selinux_state *state, tcontext = sidtab_search(sidtab, tasksid); if (!tcontext) { - printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", + pr_err("SELinux: %s: unrecognized SID %d\n", __func__, tasksid); rc = -EINVAL; goto out; @@ -883,7 +881,7 @@ int security_bounded_transition(struct selinux_state *state, rc = -EINVAL; old_context = sidtab_search(sidtab, old_sid); if (!old_context) { - printk(KERN_ERR "SELinux: %s: unrecognized SID %u\n", + pr_err("SELinux: %s: unrecognized SID %u\n", __func__, old_sid); goto out; } @@ -891,7 +889,7 @@ int security_bounded_transition(struct selinux_state *state, rc = -EINVAL; new_context = sidtab_search(sidtab, new_sid); if (!new_context) { - printk(KERN_ERR "SELinux: %s: unrecognized SID %u\n", + pr_err("SELinux: %s: unrecognized SID %u\n", __func__, new_sid); goto out; } @@ -1040,14 +1038,14 @@ void security_compute_xperms_decision(struct selinux_state *state, scontext = sidtab_search(sidtab, ssid); if (!scontext) { - printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", + pr_err("SELinux: %s: unrecognized SID %d\n", __func__, ssid); goto out; } tcontext = sidtab_search(sidtab, tsid); if (!tcontext) { - printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", + pr_err("SELinux: %s: unrecognized SID %d\n", __func__, tsid); goto out; } @@ -1129,7 +1127,7 @@ void security_compute_av(struct selinux_state *state, scontext = sidtab_search(sidtab, ssid); if (!scontext) { - printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", + pr_err("SELinux: %s: unrecognized SID %d\n", __func__, ssid); goto out; } @@ -1140,7 +1138,7 @@ void security_compute_av(struct selinux_state *state, tcontext = sidtab_search(sidtab, tsid); if (!tcontext) { - printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", + pr_err("SELinux: %s: unrecognized SID %d\n", __func__, tsid); goto out; } @@ -1183,7 +1181,7 @@ void security_compute_av_user(struct selinux_state *state, scontext = sidtab_search(sidtab, ssid); if (!scontext) { - printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", + pr_err("SELinux: %s: unrecognized SID %d\n", __func__, ssid); goto out; } @@ -1194,7 +1192,7 @@ void security_compute_av_user(struct selinux_state *state, tcontext = sidtab_search(sidtab, tsid); if (!tcontext) { - printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", + pr_err("SELinux: %s: unrecognized SID %d\n", __func__, tsid); goto out; } @@ -1310,7 +1308,7 @@ static int security_sid_to_context_core(struct selinux_state *state, *scontext = scontextp; goto out; } - printk(KERN_ERR "SELinux: %s: called before initial " + pr_err("SELinux: %s: called before initial " "load_policy on unknown SID %d\n", __func__, sid); rc = -EINVAL; goto out; @@ -1323,7 +1321,7 @@ static int security_sid_to_context_core(struct selinux_state *state, else context = sidtab_search(sidtab, sid); if (!context) { - printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", + pr_err("SELinux: %s: unrecognized SID %d\n", __func__, sid); rc = -EINVAL; goto out_unlock; @@ -1678,14 +1676,14 @@ static int security_compute_sid(struct selinux_state *state, scontext = sidtab_search(sidtab, ssid); if (!scontext) { - printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", + pr_err("SELinux: %s: unrecognized SID %d\n", __func__, ssid); rc = -EINVAL; goto out_unlock; } tcontext = sidtab_search(sidtab, tsid); if (!tcontext) { - printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", + pr_err("SELinux: %s: unrecognized SID %d\n", __func__, tsid); rc = -EINVAL; goto out_unlock; @@ -1911,7 +1909,8 @@ static inline int convert_context_handle_invalid_context( return -EINVAL; if (!context_struct_to_string(policydb, context, &s, &len)) { - printk(KERN_WARNING "SELinux: Context %s would be invalid if enforcing\n", s); + pr_warn("SELinux: Context %s would be invalid if enforcing\n", + s); kfree(s); } return 0; @@ -1962,7 +1961,7 @@ static int convert_context(u32 key, c->len, &ctx, SECSID_NULL); kfree(s); if (!rc) { - printk(KERN_INFO "SELinux: Context %s became valid (mapped).\n", + pr_info("SELinux: Context %s became valid (mapped).\n", c->str); /* Replace string with mapped representation. */ kfree(c->str); @@ -1974,7 +1973,7 @@ static int convert_context(u32 key, goto out; } else { /* Other error condition, e.g. ENOMEM. */ - printk(KERN_ERR "SELinux: Unable to map context %s, rc = %d.\n", + pr_err("SELinux: Unable to map context %s, rc = %d.\n", c->str, -rc); goto out; } @@ -2033,7 +2032,7 @@ static int convert_context(u32 key, oc = oc->next; rc = -EINVAL; if (!oc) { - printk(KERN_ERR "SELinux: unable to look up" + pr_err("SELinux: unable to look up" " the initial SIDs list\n"); goto bad; } @@ -2065,7 +2064,7 @@ bad: context_destroy(c); c->str = s; c->len = len; - printk(KERN_INFO "SELinux: Context %s became invalid (unmapped).\n", + pr_info("SELinux: Context %s became invalid (unmapped).\n", c->str); rc = 0; goto out; @@ -2170,13 +2169,13 @@ int security_load_policy(struct selinux_state *state, void *data, size_t len) newpolicydb->len = len; /* If switching between different policy types, log MLS status */ if (policydb->mls_enabled && !newpolicydb->mls_enabled) - printk(KERN_INFO "SELinux: Disabling MLS support...\n"); + pr_info("SELinux: Disabling MLS support...\n"); else if (!policydb->mls_enabled && newpolicydb->mls_enabled) - printk(KERN_INFO "SELinux: Enabling MLS support...\n"); + pr_info("SELinux: Enabling MLS support...\n"); rc = policydb_load_isids(newpolicydb, &newsidtab); if (rc) { - printk(KERN_ERR "SELinux: unable to load the initial SIDs\n"); + pr_err("SELinux: unable to load the initial SIDs\n"); policydb_destroy(newpolicydb); goto out; } @@ -2187,7 +2186,7 @@ int security_load_policy(struct selinux_state *state, void *data, size_t len) rc = security_preserve_bools(state, newpolicydb); if (rc) { - printk(KERN_ERR "SELinux: unable to preserve booleans\n"); + pr_err("SELinux: unable to preserve booleans\n"); goto err; } @@ -2207,7 +2206,7 @@ int security_load_policy(struct selinux_state *state, void *data, size_t len) args.newp = newpolicydb; rc = sidtab_map(&newsidtab, convert_context, &args); if (rc) { - printk(KERN_ERR "SELinux: unable to convert the internal" + pr_err("SELinux: unable to convert the internal" " representation of contexts in the new SID" " table\n"); goto err; @@ -2999,7 +2998,7 @@ int security_sid_mls_copy(struct selinux_state *state, rc = -EINVAL; context1 = sidtab_search(sidtab, sid); if (!context1) { - printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", + pr_err("SELinux: %s: unrecognized SID %d\n", __func__, sid); goto out_unlock; } @@ -3007,7 +3006,7 @@ int security_sid_mls_copy(struct selinux_state *state, rc = -EINVAL; context2 = sidtab_search(sidtab, mls_sid); if (!context2) { - printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", + pr_err("SELinux: %s: unrecognized SID %d\n", __func__, mls_sid); goto out_unlock; } @@ -3104,14 +3103,14 @@ int security_net_peersid_resolve(struct selinux_state *state, rc = -EINVAL; nlbl_ctx = sidtab_search(sidtab, nlbl_sid); if (!nlbl_ctx) { - printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", + pr_err("SELinux: %s: unrecognized SID %d\n", __func__, nlbl_sid); goto out; } rc = -EINVAL; xfrm_ctx = sidtab_search(sidtab, xfrm_sid); if (!xfrm_ctx) { - printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", + pr_err("SELinux: %s: unrecognized SID %d\n", __func__, xfrm_sid); goto out; } @@ -3202,7 +3201,7 @@ int security_get_permissions(struct selinux_state *state, rc = -EINVAL; match = hashtab_search(policydb->p_classes.table, class); if (!match) { - printk(KERN_ERR "SELinux: %s: unrecognized class %s\n", + pr_err("SELinux: %s: unrecognized class %s\n", __func__, class); goto out; } diff --git a/security/selinux/ss/sidtab.c b/security/selinux/ss/sidtab.c index 5be31b7af225..fd75a12fa8fc 100644 --- a/security/selinux/ss/sidtab.c +++ b/security/selinux/ss/sidtab.c @@ -214,8 +214,7 @@ int sidtab_context_to_sid(struct sidtab *s, } sid = s->next_sid++; if (context->len) - printk(KERN_INFO - "SELinux: Context %s is not valid (left unmapped).\n", + pr_info("SELinux: Context %s is not valid (left unmapped).\n", context->str); ret = sidtab_insert(s, sid, context); if (ret) @@ -253,7 +252,7 @@ void sidtab_hash_eval(struct sidtab *h, char *tag) } } - printk(KERN_DEBUG "%s: %d entries and %d/%d buckets used, longest " + pr_debug("%s: %d entries and %d/%d buckets used, longest " "chain length %d\n", tag, h->nel, slots_used, SIDTAB_SIZE, max_chain_len); } diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 9ab8097dab7c..340fc30ad85d 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -28,6 +28,7 @@ #include <linux/tcp.h> #include <linux/udp.h> #include <linux/dccp.h> +#include <linux/icmpv6.h> #include <linux/slab.h> #include <linux/mutex.h> #include <linux/pipe_fs_i.h> @@ -3896,6 +3897,7 @@ static int smk_skb_to_addr_ipv6(struct sk_buff *skb, struct sockaddr_in6 *sip) sip->sin6_port = th->source; break; case IPPROTO_UDP: + case IPPROTO_UDPLITE: uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph); if (uh != NULL) sip->sin6_port = uh->source; @@ -3924,15 +3926,19 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) struct smack_known *skp = NULL; int rc = 0; struct smk_audit_info ad; + u16 family = sk->sk_family; #ifdef CONFIG_AUDIT struct lsm_network_audit net; #endif #if IS_ENABLED(CONFIG_IPV6) struct sockaddr_in6 sadd; int proto; + + if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP)) + family = PF_INET; #endif /* CONFIG_IPV6 */ - switch (sk->sk_family) { + switch (family) { case PF_INET: #ifdef CONFIG_SECURITY_SMACK_NETFILTER /* @@ -3950,7 +3956,7 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) */ netlbl_secattr_init(&secattr); - rc = netlbl_skbuff_getattr(skb, sk->sk_family, &secattr); + rc = netlbl_skbuff_getattr(skb, family, &secattr); if (rc == 0) skp = smack_from_secattr(&secattr, ssp); else @@ -3963,7 +3969,7 @@ access_check: #endif #ifdef CONFIG_AUDIT smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); - ad.a.u.net->family = sk->sk_family; + ad.a.u.net->family = family; ad.a.u.net->netif = skb->skb_iif; ipv4_skb_to_auditdata(skb, &ad.a, NULL); #endif @@ -3977,12 +3983,13 @@ access_check: rc = smk_bu_note("IPv4 delivery", skp, ssp->smk_in, MAY_WRITE, rc); if (rc != 0) - netlbl_skbuff_err(skb, sk->sk_family, rc, 0); + netlbl_skbuff_err(skb, family, rc, 0); break; #if IS_ENABLED(CONFIG_IPV6) case PF_INET6: proto = smk_skb_to_addr_ipv6(skb, &sadd); - if (proto != IPPROTO_UDP && proto != IPPROTO_TCP) + if (proto != IPPROTO_UDP && proto != IPPROTO_UDPLITE && + proto != IPPROTO_TCP && proto != IPPROTO_DCCP) break; #ifdef SMACK_IPV6_SECMARK_LABELING if (skb && skb->secmark != 0) @@ -3993,7 +4000,7 @@ access_check: skp = smack_net_ambient; #ifdef CONFIG_AUDIT smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); - ad.a.u.net->family = sk->sk_family; + ad.a.u.net->family = family; ad.a.u.net->netif = skb->skb_iif; ipv6_skb_to_auditdata(skb, &ad.a, NULL); #endif /* CONFIG_AUDIT */ @@ -4004,6 +4011,9 @@ access_check: #ifdef SMACK_IPV6_PORT_LABELING rc = smk_ipv6_port_check(sk, &sadd, SMK_RECEIVING); #endif /* SMACK_IPV6_PORT_LABELING */ + if (rc != 0) + icmpv6_send(skb, ICMPV6_DEST_UNREACH, + ICMPV6_ADM_PROHIBITED, 0); break; #endif /* CONFIG_IPV6 */ } diff --git a/security/tomoyo/Makefile b/security/tomoyo/Makefile index b7c6a7ffc058..cca5a3012fee 100644 --- a/security/tomoyo/Makefile +++ b/security/tomoyo/Makefile @@ -4,7 +4,7 @@ obj-y = audit.o common.o condition.o domain.o environ.o file.o gc.o group.o load targets += builtin-policy.h define do_policy echo "static char tomoyo_builtin_$(1)[] __initdata ="; \ -$(objtree)/scripts/basic/bin2c <$(firstword $(wildcard $(obj)/policy/$(1).conf $(srctree)/$(src)/policy/$(1).conf.default) /dev/null); \ +$(objtree)/scripts/bin2c <$(firstword $(wildcard $(obj)/policy/$(1).conf $(srctree)/$(src)/policy/$(1).conf.default) /dev/null); \ echo ";" endef quiet_cmd_policy = POLICY $@ |