diff options
| author | Jiri Kosina <jkosina@suse.cz> | 2014-11-20 08:42:02 -0500 |
|---|---|---|
| committer | Jiri Kosina <jkosina@suse.cz> | 2014-11-20 08:42:02 -0500 |
| commit | a02001086bbfb4da35d1228bebc2f1b442db455f (patch) | |
| tree | 62ab47936cef06fd08657ca5b6cd1df98c19be57 /security | |
| parent | eff264efeeb0898408e8c9df72d8a32621035bed (diff) | |
| parent | fc14f9c1272f62c3e8d01300f52467c0d9af50f9 (diff) | |
Merge Linus' tree to be be to apply submitted patches to newer code than
current trivial.git base
Diffstat (limited to 'security')
43 files changed, 959 insertions, 646 deletions
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 998100093332..65ca451a764d 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c | |||
| @@ -668,7 +668,7 @@ static int param_set_aabool(const char *val, const struct kernel_param *kp); | |||
| 668 | static int param_get_aabool(char *buffer, const struct kernel_param *kp); | 668 | static int param_get_aabool(char *buffer, const struct kernel_param *kp); |
| 669 | #define param_check_aabool param_check_bool | 669 | #define param_check_aabool param_check_bool |
| 670 | static struct kernel_param_ops param_ops_aabool = { | 670 | static struct kernel_param_ops param_ops_aabool = { |
| 671 | .flags = KERNEL_PARAM_FL_NOARG, | 671 | .flags = KERNEL_PARAM_OPS_FL_NOARG, |
| 672 | .set = param_set_aabool, | 672 | .set = param_set_aabool, |
| 673 | .get = param_get_aabool | 673 | .get = param_get_aabool |
| 674 | }; | 674 | }; |
| @@ -685,7 +685,7 @@ static int param_set_aalockpolicy(const char *val, const struct kernel_param *kp | |||
| 685 | static int param_get_aalockpolicy(char *buffer, const struct kernel_param *kp); | 685 | static int param_get_aalockpolicy(char *buffer, const struct kernel_param *kp); |
| 686 | #define param_check_aalockpolicy param_check_bool | 686 | #define param_check_aalockpolicy param_check_bool |
| 687 | static struct kernel_param_ops param_ops_aalockpolicy = { | 687 | static struct kernel_param_ops param_ops_aalockpolicy = { |
| 688 | .flags = KERNEL_PARAM_FL_NOARG, | 688 | .flags = KERNEL_PARAM_OPS_FL_NOARG, |
| 689 | .set = param_set_aalockpolicy, | 689 | .set = param_set_aalockpolicy, |
| 690 | .get = param_get_aalockpolicy | 690 | .get = param_get_aalockpolicy |
| 691 | }; | 691 | }; |
diff --git a/security/capability.c b/security/capability.c index a74fde6a7468..d68c57a62bcf 100644 --- a/security/capability.c +++ b/security/capability.c | |||
| @@ -343,9 +343,9 @@ static int cap_file_fcntl(struct file *file, unsigned int cmd, | |||
| 343 | return 0; | 343 | return 0; |
| 344 | } | 344 | } |
| 345 | 345 | ||
| 346 | static int cap_file_set_fowner(struct file *file) | 346 | static void cap_file_set_fowner(struct file *file) |
| 347 | { | 347 | { |
| 348 | return 0; | 348 | return; |
| 349 | } | 349 | } |
| 350 | 350 | ||
| 351 | static int cap_file_send_sigiotask(struct task_struct *tsk, | 351 | static int cap_file_send_sigiotask(struct task_struct *tsk, |
diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig index 245c6d92065b..b76235ae4786 100644 --- a/security/integrity/Kconfig +++ b/security/integrity/Kconfig | |||
| @@ -1,11 +1,23 @@ | |||
| 1 | # | 1 | # |
| 2 | config INTEGRITY | 2 | config INTEGRITY |
| 3 | def_bool y | 3 | bool "Integrity subsystem" |
| 4 | depends on IMA || EVM | 4 | depends on SECURITY |
| 5 | default y | ||
| 6 | help | ||
| 7 | This option enables the integrity subsystem, which is comprised | ||
| 8 | of a number of different components including the Integrity | ||
| 9 | Measurement Architecture (IMA), Extended Verification Module | ||
| 10 | (EVM), IMA-appraisal extension, digital signature verification | ||
| 11 | extension and audit measurement log support. | ||
| 12 | |||
| 13 | Each of these components can be enabled/disabled separately. | ||
| 14 | Refer to the individual components for additional details. | ||
| 15 | |||
| 16 | if INTEGRITY | ||
| 5 | 17 | ||
| 6 | config INTEGRITY_SIGNATURE | 18 | config INTEGRITY_SIGNATURE |
| 7 | boolean "Digital signature verification using multiple keyrings" | 19 | boolean "Digital signature verification using multiple keyrings" |
| 8 | depends on INTEGRITY && KEYS | 20 | depends on KEYS |
| 9 | default n | 21 | default n |
| 10 | select SIGNATURE | 22 | select SIGNATURE |
| 11 | help | 23 | help |
| @@ -17,9 +29,21 @@ config INTEGRITY_SIGNATURE | |||
| 17 | This is useful for evm and module keyrings, when keys are | 29 | This is useful for evm and module keyrings, when keys are |
| 18 | usually only added from initramfs. | 30 | usually only added from initramfs. |
| 19 | 31 | ||
| 32 | config INTEGRITY_ASYMMETRIC_KEYS | ||
| 33 | boolean "Enable asymmetric keys support" | ||
| 34 | depends on INTEGRITY_SIGNATURE | ||
| 35 | default n | ||
| 36 | select ASYMMETRIC_KEY_TYPE | ||
| 37 | select ASYMMETRIC_PUBLIC_KEY_SUBTYPE | ||
| 38 | select PUBLIC_KEY_ALGO_RSA | ||
| 39 | select X509_CERTIFICATE_PARSER | ||
| 40 | help | ||
| 41 | This option enables digital signature verification using | ||
| 42 | asymmetric keys. | ||
| 43 | |||
| 20 | config INTEGRITY_AUDIT | 44 | config INTEGRITY_AUDIT |
| 21 | bool "Enables integrity auditing support " | 45 | bool "Enables integrity auditing support " |
| 22 | depends on INTEGRITY && AUDIT | 46 | depends on AUDIT |
| 23 | default y | 47 | default y |
| 24 | help | 48 | help |
| 25 | In addition to enabling integrity auditing support, this | 49 | In addition to enabling integrity auditing support, this |
| @@ -32,17 +56,7 @@ config INTEGRITY_AUDIT | |||
| 32 | be enabled by specifying 'integrity_audit=1' on the kernel | 56 | be enabled by specifying 'integrity_audit=1' on the kernel |
| 33 | command line. | 57 | command line. |
| 34 | 58 | ||
| 35 | config INTEGRITY_ASYMMETRIC_KEYS | ||
| 36 | boolean "Enable asymmetric keys support" | ||
| 37 | depends on INTEGRITY_SIGNATURE | ||
| 38 | default n | ||
| 39 | select ASYMMETRIC_KEY_TYPE | ||
| 40 | select ASYMMETRIC_PUBLIC_KEY_SUBTYPE | ||
| 41 | select PUBLIC_KEY_ALGO_RSA | ||
| 42 | select X509_CERTIFICATE_PARSER | ||
| 43 | help | ||
| 44 | This option enables digital signature verification using | ||
| 45 | asymmetric keys. | ||
| 46 | |||
| 47 | source security/integrity/ima/Kconfig | 59 | source security/integrity/ima/Kconfig |
| 48 | source security/integrity/evm/Kconfig | 60 | source security/integrity/evm/Kconfig |
| 61 | |||
| 62 | endif # if INTEGRITY | ||
diff --git a/security/integrity/Makefile b/security/integrity/Makefile index 0793f4811cb7..8d1f4bf51087 100644 --- a/security/integrity/Makefile +++ b/security/integrity/Makefile | |||
| @@ -3,11 +3,11 @@ | |||
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | obj-$(CONFIG_INTEGRITY) += integrity.o | 5 | obj-$(CONFIG_INTEGRITY) += integrity.o |
| 6 | obj-$(CONFIG_INTEGRITY_AUDIT) += integrity_audit.o | ||
| 7 | obj-$(CONFIG_INTEGRITY_SIGNATURE) += digsig.o | ||
| 8 | obj-$(CONFIG_INTEGRITY_ASYMMETRIC_KEYS) += digsig_asymmetric.o | ||
| 9 | 6 | ||
| 10 | integrity-y := iint.o | 7 | integrity-y := iint.o |
| 8 | integrity-$(CONFIG_INTEGRITY_AUDIT) += integrity_audit.o | ||
| 9 | integrity-$(CONFIG_INTEGRITY_SIGNATURE) += digsig.o | ||
| 10 | integrity-$(CONFIG_INTEGRITY_ASYMMETRIC_KEYS) += digsig_asymmetric.o | ||
| 11 | 11 | ||
| 12 | subdir-$(CONFIG_IMA) += ima | 12 | subdir-$(CONFIG_IMA) += ima |
| 13 | obj-$(CONFIG_IMA) += ima/ | 13 | obj-$(CONFIG_IMA) += ima/ |
diff --git a/security/integrity/digsig_asymmetric.c b/security/integrity/digsig_asymmetric.c index 9eae4809006b..4fec1816a2b3 100644 --- a/security/integrity/digsig_asymmetric.c +++ b/security/integrity/digsig_asymmetric.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 13 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
| 14 | 14 | ||
| 15 | #include <linux/err.h> | 15 | #include <linux/err.h> |
| 16 | #include <linux/ratelimit.h> | ||
| 16 | #include <linux/key-type.h> | 17 | #include <linux/key-type.h> |
| 17 | #include <crypto/public_key.h> | 18 | #include <crypto/public_key.h> |
| 18 | #include <keys/asymmetric-type.h> | 19 | #include <keys/asymmetric-type.h> |
| @@ -27,7 +28,7 @@ static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid) | |||
| 27 | struct key *key; | 28 | struct key *key; |
| 28 | char name[12]; | 29 | char name[12]; |
| 29 | 30 | ||
| 30 | sprintf(name, "id:%x", keyid); | 31 | sprintf(name, "id:%08x", keyid); |
| 31 | 32 | ||
| 32 | pr_debug("key search: \"%s\"\n", name); | 33 | pr_debug("key search: \"%s\"\n", name); |
| 33 | 34 | ||
| @@ -45,8 +46,8 @@ static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid) | |||
| 45 | } | 46 | } |
| 46 | 47 | ||
| 47 | if (IS_ERR(key)) { | 48 | if (IS_ERR(key)) { |
| 48 | pr_warn("Request for unknown key '%s' err %ld\n", | 49 | pr_err_ratelimited("Request for unknown key '%s' err %ld\n", |
| 49 | name, PTR_ERR(key)); | 50 | name, PTR_ERR(key)); |
| 50 | switch (PTR_ERR(key)) { | 51 | switch (PTR_ERR(key)) { |
| 51 | /* Hide some search errors */ | 52 | /* Hide some search errors */ |
| 52 | case -EACCES: | 53 | case -EACCES: |
diff --git a/security/integrity/evm/Kconfig b/security/integrity/evm/Kconfig index d606f3d12d6b..df586fa00ef1 100644 --- a/security/integrity/evm/Kconfig +++ b/security/integrity/evm/Kconfig | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | config EVM | 1 | config EVM |
| 2 | boolean "EVM support" | 2 | boolean "EVM support" |
| 3 | depends on SECURITY | ||
| 4 | select KEYS | 3 | select KEYS |
| 5 | select ENCRYPTED_KEYS | 4 | select ENCRYPTED_KEYS |
| 6 | select CRYPTO_HMAC | 5 | select CRYPTO_HMAC |
| @@ -12,10 +11,6 @@ config EVM | |||
| 12 | 11 | ||
| 13 | If you are unsure how to answer this question, answer N. | 12 | If you are unsure how to answer this question, answer N. |
| 14 | 13 | ||
| 15 | if EVM | ||
| 16 | |||
| 17 | menu "EVM options" | ||
| 18 | |||
| 19 | config EVM_ATTR_FSUUID | 14 | config EVM_ATTR_FSUUID |
| 20 | bool "FSUUID (version 2)" | 15 | bool "FSUUID (version 2)" |
| 21 | default y | 16 | default y |
| @@ -47,6 +42,3 @@ config EVM_EXTRA_SMACK_XATTRS | |||
| 47 | additional info to the calculation, requires existing EVM | 42 | additional info to the calculation, requires existing EVM |
| 48 | labeled file systems to be relabeled. | 43 | labeled file systems to be relabeled. |
| 49 | 44 | ||
| 50 | endmenu | ||
| 51 | |||
| 52 | endif | ||
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c index 3bcb80df4d01..c5ee1a7c5e8a 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c | |||
| @@ -126,14 +126,15 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry, | |||
| 126 | rc = vfs_getxattr_alloc(dentry, XATTR_NAME_EVM, (char **)&xattr_data, 0, | 126 | rc = vfs_getxattr_alloc(dentry, XATTR_NAME_EVM, (char **)&xattr_data, 0, |
| 127 | GFP_NOFS); | 127 | GFP_NOFS); |
| 128 | if (rc <= 0) { | 128 | if (rc <= 0) { |
| 129 | if (rc == 0) | 129 | evm_status = INTEGRITY_FAIL; |
| 130 | evm_status = INTEGRITY_FAIL; /* empty */ | 130 | if (rc == -ENODATA) { |
| 131 | else if (rc == -ENODATA) { | ||
| 132 | rc = evm_find_protected_xattrs(dentry); | 131 | rc = evm_find_protected_xattrs(dentry); |
| 133 | if (rc > 0) | 132 | if (rc > 0) |
| 134 | evm_status = INTEGRITY_NOLABEL; | 133 | evm_status = INTEGRITY_NOLABEL; |
| 135 | else if (rc == 0) | 134 | else if (rc == 0) |
| 136 | evm_status = INTEGRITY_NOXATTRS; /* new file */ | 135 | evm_status = INTEGRITY_NOXATTRS; /* new file */ |
| 136 | } else if (rc == -EOPNOTSUPP) { | ||
| 137 | evm_status = INTEGRITY_UNKNOWN; | ||
| 137 | } | 138 | } |
| 138 | goto out; | 139 | goto out; |
| 139 | } | 140 | } |
| @@ -284,6 +285,13 @@ static int evm_protect_xattr(struct dentry *dentry, const char *xattr_name, | |||
| 284 | goto out; | 285 | goto out; |
| 285 | } | 286 | } |
| 286 | evm_status = evm_verify_current_integrity(dentry); | 287 | evm_status = evm_verify_current_integrity(dentry); |
| 288 | if (evm_status == INTEGRITY_NOXATTRS) { | ||
| 289 | struct integrity_iint_cache *iint; | ||
| 290 | |||
| 291 | iint = integrity_iint_find(dentry->d_inode); | ||
| 292 | if (iint && (iint->flags & IMA_NEW_FILE)) | ||
| 293 | return 0; | ||
| 294 | } | ||
| 287 | out: | 295 | out: |
| 288 | if (evm_status != INTEGRITY_PASS) | 296 | if (evm_status != INTEGRITY_PASS) |
| 289 | integrity_audit_msg(AUDIT_INTEGRITY_METADATA, dentry->d_inode, | 297 | integrity_audit_msg(AUDIT_INTEGRITY_METADATA, dentry->d_inode, |
| @@ -311,9 +319,12 @@ int evm_inode_setxattr(struct dentry *dentry, const char *xattr_name, | |||
| 311 | { | 319 | { |
| 312 | const struct evm_ima_xattr_data *xattr_data = xattr_value; | 320 | const struct evm_ima_xattr_data *xattr_data = xattr_value; |
| 313 | 321 | ||
| 314 | if ((strcmp(xattr_name, XATTR_NAME_EVM) == 0) | 322 | if (strcmp(xattr_name, XATTR_NAME_EVM) == 0) { |
| 315 | && (xattr_data->type == EVM_XATTR_HMAC)) | 323 | if (!xattr_value_len) |
| 316 | return -EPERM; | 324 | return -EINVAL; |
| 325 | if (xattr_data->type != EVM_IMA_XATTR_DIGSIG) | ||
| 326 | return -EPERM; | ||
| 327 | } | ||
| 317 | return evm_protect_xattr(dentry, xattr_name, xattr_value, | 328 | return evm_protect_xattr(dentry, xattr_name, xattr_value, |
| 318 | xattr_value_len); | 329 | xattr_value_len); |
| 319 | } | 330 | } |
| @@ -352,7 +363,6 @@ void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name, | |||
| 352 | return; | 363 | return; |
| 353 | 364 | ||
| 354 | evm_update_evmxattr(dentry, xattr_name, xattr_value, xattr_value_len); | 365 | evm_update_evmxattr(dentry, xattr_name, xattr_value, xattr_value_len); |
| 355 | return; | ||
| 356 | } | 366 | } |
| 357 | 367 | ||
| 358 | /** | 368 | /** |
| @@ -372,7 +382,6 @@ void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name) | |||
| 372 | mutex_lock(&inode->i_mutex); | 382 | mutex_lock(&inode->i_mutex); |
| 373 | evm_update_evmxattr(dentry, xattr_name, NULL, 0); | 383 | evm_update_evmxattr(dentry, xattr_name, NULL, 0); |
| 374 | mutex_unlock(&inode->i_mutex); | 384 | mutex_unlock(&inode->i_mutex); |
| 375 | return; | ||
| 376 | } | 385 | } |
| 377 | 386 | ||
| 378 | /** | 387 | /** |
| @@ -414,7 +423,6 @@ void evm_inode_post_setattr(struct dentry *dentry, int ia_valid) | |||
| 414 | 423 | ||
| 415 | if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)) | 424 | if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)) |
| 416 | evm_update_evmxattr(dentry, NULL, NULL, 0); | 425 | evm_update_evmxattr(dentry, NULL, NULL, 0); |
| 417 | return; | ||
| 418 | } | 426 | } |
| 419 | 427 | ||
| 420 | /* | 428 | /* |
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig index 08758fbd496f..e099875643c5 100644 --- a/security/integrity/ima/Kconfig +++ b/security/integrity/ima/Kconfig | |||
| @@ -2,8 +2,6 @@ | |||
| 2 | # | 2 | # |
| 3 | config IMA | 3 | config IMA |
| 4 | bool "Integrity Measurement Architecture(IMA)" | 4 | bool "Integrity Measurement Architecture(IMA)" |
| 5 | depends on SECURITY | ||
| 6 | select INTEGRITY | ||
| 7 | select SECURITYFS | 5 | select SECURITYFS |
| 8 | select CRYPTO | 6 | select CRYPTO |
| 9 | select CRYPTO_HMAC | 7 | select CRYPTO_HMAC |
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 57da4bd7ba0c..8ee997dff139 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h | |||
| @@ -43,6 +43,9 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 }; | |||
| 43 | #define IMA_TEMPLATE_IMA_NAME "ima" | 43 | #define IMA_TEMPLATE_IMA_NAME "ima" |
| 44 | #define IMA_TEMPLATE_IMA_FMT "d|n" | 44 | #define IMA_TEMPLATE_IMA_FMT "d|n" |
| 45 | 45 | ||
| 46 | /* current content of the policy */ | ||
| 47 | extern int ima_policy_flag; | ||
| 48 | |||
| 46 | /* set during initialization */ | 49 | /* set during initialization */ |
| 47 | extern int ima_initialized; | 50 | extern int ima_initialized; |
| 48 | extern int ima_used_chip; | 51 | extern int ima_used_chip; |
| @@ -90,10 +93,7 @@ extern struct list_head ima_measurements; /* list of all measurements */ | |||
| 90 | 93 | ||
| 91 | /* Internal IMA function definitions */ | 94 | /* Internal IMA function definitions */ |
| 92 | int ima_init(void); | 95 | int ima_init(void); |
| 93 | void ima_cleanup(void); | ||
| 94 | int ima_fs_init(void); | 96 | int ima_fs_init(void); |
| 95 | void ima_fs_cleanup(void); | ||
| 96 | int ima_inode_alloc(struct inode *inode); | ||
| 97 | int ima_add_template_entry(struct ima_template_entry *entry, int violation, | 97 | int ima_add_template_entry(struct ima_template_entry *entry, int violation, |
| 98 | const char *op, struct inode *inode, | 98 | const char *op, struct inode *inode, |
| 99 | const unsigned char *filename); | 99 | const unsigned char *filename); |
| @@ -110,8 +110,6 @@ void ima_print_digest(struct seq_file *m, u8 *digest, int size); | |||
| 110 | struct ima_template_desc *ima_template_desc_current(void); | 110 | struct ima_template_desc *ima_template_desc_current(void); |
| 111 | int ima_init_template(void); | 111 | int ima_init_template(void); |
| 112 | 112 | ||
| 113 | int ima_init_template(void); | ||
| 114 | |||
| 115 | /* | 113 | /* |
| 116 | * used to protect h_table and sha_table | 114 | * used to protect h_table and sha_table |
| 117 | */ | 115 | */ |
| @@ -151,12 +149,6 @@ int ima_store_template(struct ima_template_entry *entry, int violation, | |||
| 151 | void ima_free_template_entry(struct ima_template_entry *entry); | 149 | void ima_free_template_entry(struct ima_template_entry *entry); |
| 152 | const char *ima_d_path(struct path *path, char **pathbuf); | 150 | const char *ima_d_path(struct path *path, char **pathbuf); |
| 153 | 151 | ||
| 154 | /* rbtree tree calls to lookup, insert, delete | ||
| 155 | * integrity data associated with an inode. | ||
| 156 | */ | ||
| 157 | struct integrity_iint_cache *integrity_iint_insert(struct inode *inode); | ||
| 158 | struct integrity_iint_cache *integrity_iint_find(struct inode *inode); | ||
| 159 | |||
| 160 | /* IMA policy related functions */ | 152 | /* IMA policy related functions */ |
| 161 | enum ima_hooks { FILE_CHECK = 1, MMAP_CHECK, BPRM_CHECK, MODULE_CHECK, FIRMWARE_CHECK, POST_SETATTR }; | 153 | enum ima_hooks { FILE_CHECK = 1, MMAP_CHECK, BPRM_CHECK, MODULE_CHECK, FIRMWARE_CHECK, POST_SETATTR }; |
| 162 | 154 | ||
| @@ -164,20 +156,22 @@ int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask, | |||
| 164 | int flags); | 156 | int flags); |
| 165 | void ima_init_policy(void); | 157 | void ima_init_policy(void); |
| 166 | void ima_update_policy(void); | 158 | void ima_update_policy(void); |
| 159 | void ima_update_policy_flag(void); | ||
| 167 | ssize_t ima_parse_add_rule(char *); | 160 | ssize_t ima_parse_add_rule(char *); |
| 168 | void ima_delete_rules(void); | 161 | void ima_delete_rules(void); |
| 169 | 162 | ||
| 170 | /* Appraise integrity measurements */ | 163 | /* Appraise integrity measurements */ |
| 171 | #define IMA_APPRAISE_ENFORCE 0x01 | 164 | #define IMA_APPRAISE_ENFORCE 0x01 |
| 172 | #define IMA_APPRAISE_FIX 0x02 | 165 | #define IMA_APPRAISE_FIX 0x02 |
| 173 | #define IMA_APPRAISE_MODULES 0x04 | 166 | #define IMA_APPRAISE_LOG 0x04 |
| 174 | #define IMA_APPRAISE_FIRMWARE 0x08 | 167 | #define IMA_APPRAISE_MODULES 0x08 |
| 168 | #define IMA_APPRAISE_FIRMWARE 0x10 | ||
| 175 | 169 | ||
| 176 | #ifdef CONFIG_IMA_APPRAISE | 170 | #ifdef CONFIG_IMA_APPRAISE |
| 177 | int ima_appraise_measurement(int func, struct integrity_iint_cache *iint, | 171 | int ima_appraise_measurement(int func, struct integrity_iint_cache *iint, |
| 178 | struct file *file, const unsigned char *filename, | 172 | struct file *file, const unsigned char *filename, |
| 179 | struct evm_ima_xattr_data *xattr_value, | 173 | struct evm_ima_xattr_data *xattr_value, |
| 180 | int xattr_len); | 174 | int xattr_len, int opened); |
| 181 | int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func); | 175 | int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func); |
| 182 | void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file); | 176 | void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file); |
| 183 | enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint, | 177 | enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint, |
| @@ -193,7 +187,7 @@ static inline int ima_appraise_measurement(int func, | |||
| 193 | struct file *file, | 187 | struct file *file, |
| 194 | const unsigned char *filename, | 188 | const unsigned char *filename, |
| 195 | struct evm_ima_xattr_data *xattr_value, | 189 | struct evm_ima_xattr_data *xattr_value, |
| 196 | int xattr_len) | 190 | int xattr_len, int opened) |
| 197 | { | 191 | { |
| 198 | return INTEGRITY_UNKNOWN; | 192 | return INTEGRITY_UNKNOWN; |
| 199 | } | 193 | } |
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index d9cd5ce14d2b..86885979918c 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c | |||
| @@ -179,11 +179,6 @@ int ima_get_action(struct inode *inode, int mask, int function) | |||
| 179 | return ima_match_policy(inode, function, mask, flags); | 179 | return ima_match_policy(inode, function, mask, flags); |
| 180 | } | 180 | } |
| 181 | 181 | ||
| 182 | int ima_must_measure(struct inode *inode, int mask, int function) | ||
| 183 | { | ||
| 184 | return ima_match_policy(inode, function, mask, IMA_MEASURE); | ||
| 185 | } | ||
| 186 | |||
| 187 | /* | 182 | /* |
| 188 | * ima_collect_measurement - collect file measurement | 183 | * ima_collect_measurement - collect file measurement |
| 189 | * | 184 | * |
| @@ -330,10 +325,9 @@ const char *ima_d_path(struct path *path, char **pathbuf) | |||
| 330 | { | 325 | { |
| 331 | char *pathname = NULL; | 326 | char *pathname = NULL; |
| 332 | 327 | ||
| 333 | /* We will allow 11 spaces for ' (deleted)' to be appended */ | 328 | *pathbuf = kmalloc(PATH_MAX, GFP_KERNEL); |
| 334 | *pathbuf = kmalloc(PATH_MAX + 11, GFP_KERNEL); | ||
| 335 | if (*pathbuf) { | 329 | if (*pathbuf) { |
| 336 | pathname = d_path(path, *pathbuf, PATH_MAX + 11); | 330 | pathname = d_absolute_path(path, *pathbuf, PATH_MAX); |
| 337 | if (IS_ERR(pathname)) { | 331 | if (IS_ERR(pathname)) { |
| 338 | kfree(*pathbuf); | 332 | kfree(*pathbuf); |
| 339 | *pathbuf = NULL; | 333 | *pathbuf = NULL; |
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index 86bfd5c5df85..7c8f41e618b6 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c | |||
| @@ -23,6 +23,8 @@ static int __init default_appraise_setup(char *str) | |||
| 23 | { | 23 | { |
| 24 | if (strncmp(str, "off", 3) == 0) | 24 | if (strncmp(str, "off", 3) == 0) |
| 25 | ima_appraise = 0; | 25 | ima_appraise = 0; |
| 26 | else if (strncmp(str, "log", 3) == 0) | ||
| 27 | ima_appraise = IMA_APPRAISE_LOG; | ||
| 26 | else if (strncmp(str, "fix", 3) == 0) | 28 | else if (strncmp(str, "fix", 3) == 0) |
| 27 | ima_appraise = IMA_APPRAISE_FIX; | 29 | ima_appraise = IMA_APPRAISE_FIX; |
| 28 | return 1; | 30 | return 1; |
| @@ -183,7 +185,7 @@ int ima_read_xattr(struct dentry *dentry, | |||
| 183 | int ima_appraise_measurement(int func, struct integrity_iint_cache *iint, | 185 | int ima_appraise_measurement(int func, struct integrity_iint_cache *iint, |
| 184 | struct file *file, const unsigned char *filename, | 186 | struct file *file, const unsigned char *filename, |
| 185 | struct evm_ima_xattr_data *xattr_value, | 187 | struct evm_ima_xattr_data *xattr_value, |
| 186 | int xattr_len) | 188 | int xattr_len, int opened) |
| 187 | { | 189 | { |
| 188 | static const char op[] = "appraise_data"; | 190 | static const char op[] = "appraise_data"; |
| 189 | char *cause = "unknown"; | 191 | char *cause = "unknown"; |
| @@ -192,8 +194,6 @@ int ima_appraise_measurement(int func, struct integrity_iint_cache *iint, | |||
| 192 | enum integrity_status status = INTEGRITY_UNKNOWN; | 194 | enum integrity_status status = INTEGRITY_UNKNOWN; |
| 193 | int rc = xattr_len, hash_start = 0; | 195 | int rc = xattr_len, hash_start = 0; |
| 194 | 196 | ||
| 195 | if (!ima_appraise) | ||
| 196 | return 0; | ||
| 197 | if (!inode->i_op->getxattr) | 197 | if (!inode->i_op->getxattr) |
| 198 | return INTEGRITY_UNKNOWN; | 198 | return INTEGRITY_UNKNOWN; |
| 199 | 199 | ||
| @@ -202,8 +202,11 @@ int ima_appraise_measurement(int func, struct integrity_iint_cache *iint, | |||
| 202 | goto out; | 202 | goto out; |
| 203 | 203 | ||
| 204 | cause = "missing-hash"; | 204 | cause = "missing-hash"; |
| 205 | status = | 205 | status = INTEGRITY_NOLABEL; |
| 206 | (inode->i_size == 0) ? INTEGRITY_PASS : INTEGRITY_NOLABEL; | 206 | if (opened & FILE_CREATED) { |
| 207 | iint->flags |= IMA_NEW_FILE; | ||
| 208 | status = INTEGRITY_PASS; | ||
| 209 | } | ||
| 207 | goto out; | 210 | goto out; |
| 208 | } | 211 | } |
| 209 | 212 | ||
| @@ -315,7 +318,7 @@ void ima_inode_post_setattr(struct dentry *dentry) | |||
| 315 | struct integrity_iint_cache *iint; | 318 | struct integrity_iint_cache *iint; |
| 316 | int must_appraise, rc; | 319 | int must_appraise, rc; |
| 317 | 320 | ||
| 318 | if (!ima_initialized || !ima_appraise || !S_ISREG(inode->i_mode) | 321 | if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode) |
| 319 | || !inode->i_op->removexattr) | 322 | || !inode->i_op->removexattr) |
| 320 | return; | 323 | return; |
| 321 | 324 | ||
| @@ -353,7 +356,7 @@ static void ima_reset_appraise_flags(struct inode *inode, int digsig) | |||
| 353 | { | 356 | { |
| 354 | struct integrity_iint_cache *iint; | 357 | struct integrity_iint_cache *iint; |
| 355 | 358 | ||
| 356 | if (!ima_initialized || !ima_appraise || !S_ISREG(inode->i_mode)) | 359 | if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode)) |
| 357 | return; | 360 | return; |
| 358 | 361 | ||
| 359 | iint = integrity_iint_find(inode); | 362 | iint = integrity_iint_find(inode); |
| @@ -375,6 +378,8 @@ int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name, | |||
| 375 | result = ima_protect_xattr(dentry, xattr_name, xattr_value, | 378 | result = ima_protect_xattr(dentry, xattr_name, xattr_value, |
| 376 | xattr_value_len); | 379 | xattr_value_len); |
| 377 | if (result == 1) { | 380 | if (result == 1) { |
| 381 | if (!xattr_value_len || (xvalue->type >= IMA_XATTR_LAST)) | ||
| 382 | return -EINVAL; | ||
| 378 | ima_reset_appraise_flags(dentry->d_inode, | 383 | ima_reset_appraise_flags(dentry->d_inode, |
| 379 | (xvalue->type == EVM_IMA_XATTR_DIGSIG) ? 1 : 0); | 384 | (xvalue->type == EVM_IMA_XATTR_DIGSIG) ? 1 : 0); |
| 380 | result = 0; | 385 | result = 0; |
diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c index 0bd732843fe7..78d66dae15f4 100644 --- a/security/integrity/ima/ima_crypto.c +++ b/security/integrity/ima/ima_crypto.c | |||
| @@ -80,24 +80,24 @@ static int ima_kernel_read(struct file *file, loff_t offset, | |||
| 80 | { | 80 | { |
| 81 | mm_segment_t old_fs; | 81 | mm_segment_t old_fs; |
| 82 | char __user *buf = addr; | 82 | char __user *buf = addr; |
| 83 | ssize_t ret; | 83 | ssize_t ret = -EINVAL; |
| 84 | 84 | ||
| 85 | if (!(file->f_mode & FMODE_READ)) | 85 | if (!(file->f_mode & FMODE_READ)) |
| 86 | return -EBADF; | 86 | return -EBADF; |
| 87 | if (!file->f_op->read && !file->f_op->aio_read) | ||
| 88 | return -EINVAL; | ||
| 89 | 87 | ||
| 90 | old_fs = get_fs(); | 88 | old_fs = get_fs(); |
| 91 | set_fs(get_ds()); | 89 | set_fs(get_ds()); |
| 92 | if (file->f_op->read) | 90 | if (file->f_op->read) |
| 93 | ret = file->f_op->read(file, buf, count, &offset); | 91 | ret = file->f_op->read(file, buf, count, &offset); |
| 94 | else | 92 | else if (file->f_op->aio_read) |
| 95 | ret = do_sync_read(file, buf, count, &offset); | 93 | ret = do_sync_read(file, buf, count, &offset); |
| 94 | else if (file->f_op->read_iter) | ||
| 95 | ret = new_sync_read(file, buf, count, &offset); | ||
| 96 | set_fs(old_fs); | 96 | set_fs(old_fs); |
| 97 | return ret; | 97 | return ret; |
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | int ima_init_crypto(void) | 100 | int __init ima_init_crypto(void) |
| 101 | { | 101 | { |
| 102 | long rc; | 102 | long rc; |
| 103 | 103 | ||
| @@ -116,7 +116,10 @@ static struct crypto_shash *ima_alloc_tfm(enum hash_algo algo) | |||
| 116 | struct crypto_shash *tfm = ima_shash_tfm; | 116 | struct crypto_shash *tfm = ima_shash_tfm; |
| 117 | int rc; | 117 | int rc; |
| 118 | 118 | ||
| 119 | if (algo != ima_hash_algo && algo < HASH_ALGO__LAST) { | 119 | if (algo < 0 || algo >= HASH_ALGO__LAST) |
| 120 | algo = ima_hash_algo; | ||
| 121 | |||
| 122 | if (algo != ima_hash_algo) { | ||
| 120 | tfm = crypto_alloc_shash(hash_algo_name[algo], 0, 0); | 123 | tfm = crypto_alloc_shash(hash_algo_name[algo], 0, 0); |
| 121 | if (IS_ERR(tfm)) { | 124 | if (IS_ERR(tfm)) { |
| 122 | rc = PTR_ERR(tfm); | 125 | rc = PTR_ERR(tfm); |
| @@ -200,7 +203,10 @@ static struct crypto_ahash *ima_alloc_atfm(enum hash_algo algo) | |||
| 200 | struct crypto_ahash *tfm = ima_ahash_tfm; | 203 | struct crypto_ahash *tfm = ima_ahash_tfm; |
| 201 | int rc; | 204 | int rc; |
| 202 | 205 | ||
| 203 | if ((algo != ima_hash_algo && algo < HASH_ALGO__LAST) || !tfm) { | 206 | if (algo < 0 || algo >= HASH_ALGO__LAST) |
| 207 | algo = ima_hash_algo; | ||
| 208 | |||
| 209 | if (algo != ima_hash_algo || !tfm) { | ||
| 204 | tfm = crypto_alloc_ahash(hash_algo_name[algo], 0, 0); | 210 | tfm = crypto_alloc_ahash(hash_algo_name[algo], 0, 0); |
| 205 | if (!IS_ERR(tfm)) { | 211 | if (!IS_ERR(tfm)) { |
| 206 | if (algo == ima_hash_algo) | 212 | if (algo == ima_hash_algo) |
| @@ -380,17 +386,14 @@ static int ima_calc_file_hash_tfm(struct file *file, | |||
| 380 | loff_t i_size, offset = 0; | 386 | loff_t i_size, offset = 0; |
| 381 | char *rbuf; | 387 | char *rbuf; |
| 382 | int rc, read = 0; | 388 | int rc, read = 0; |
| 383 | struct { | 389 | SHASH_DESC_ON_STACK(shash, tfm); |
| 384 | struct shash_desc shash; | ||
| 385 | char ctx[crypto_shash_descsize(tfm)]; | ||
| 386 | } desc; | ||
| 387 | 390 | ||
| 388 | desc.shash.tfm = tfm; | 391 | shash->tfm = tfm; |
| 389 | desc.shash.flags = 0; | 392 | shash->flags = 0; |
| 390 | 393 | ||
| 391 | hash->length = crypto_shash_digestsize(tfm); | 394 | hash->length = crypto_shash_digestsize(tfm); |
| 392 | 395 | ||
| 393 | rc = crypto_shash_init(&desc.shash); | 396 | rc = crypto_shash_init(shash); |
| 394 | if (rc != 0) | 397 | if (rc != 0) |
| 395 | return rc; | 398 | return rc; |
| 396 | 399 | ||
| @@ -420,7 +423,7 @@ static int ima_calc_file_hash_tfm(struct file *file, | |||
| 420 | break; | 423 | break; |
| 421 | offset += rbuf_len; | 424 | offset += rbuf_len; |
| 422 | 425 | ||
| 423 | rc = crypto_shash_update(&desc.shash, rbuf, rbuf_len); | 426 | rc = crypto_shash_update(shash, rbuf, rbuf_len); |
| 424 | if (rc) | 427 | if (rc) |
| 425 | break; | 428 | break; |
| 426 | } | 429 | } |
| @@ -429,7 +432,7 @@ static int ima_calc_file_hash_tfm(struct file *file, | |||
| 429 | kfree(rbuf); | 432 | kfree(rbuf); |
| 430 | out: | 433 | out: |
| 431 | if (!rc) | 434 | if (!rc) |
| 432 | rc = crypto_shash_final(&desc.shash, hash->digest); | 435 | rc = crypto_shash_final(shash, hash->digest); |
| 433 | return rc; | 436 | return rc; |
| 434 | } | 437 | } |
| 435 | 438 | ||
| @@ -487,18 +490,15 @@ static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data, | |||
| 487 | struct ima_digest_data *hash, | 490 | struct ima_digest_data *hash, |
| 488 | struct crypto_shash *tfm) | 491 | struct crypto_shash *tfm) |
| 489 | { | 492 | { |
| 490 | struct { | 493 | SHASH_DESC_ON_STACK(shash, tfm); |
| 491 | struct shash_desc shash; | ||
| 492 | char ctx[crypto_shash_descsize(tfm)]; | ||
| 493 | } desc; | ||
| 494 | int rc, i; | 494 | int rc, i; |
| 495 | 495 | ||
| 496 | desc.shash.tfm = tfm; | 496 | shash->tfm = tfm; |
| 497 | desc.shash.flags = 0; | 497 | shash->flags = 0; |
| 498 | 498 | ||
| 499 | hash->length = crypto_shash_digestsize(tfm); | 499 | hash->length = crypto_shash_digestsize(tfm); |
| 500 | 500 | ||
| 501 | rc = crypto_shash_init(&desc.shash); | 501 | rc = crypto_shash_init(shash); |
| 502 | if (rc != 0) | 502 | if (rc != 0) |
| 503 | return rc; | 503 | return rc; |
| 504 | 504 | ||
| @@ -508,7 +508,7 @@ static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data, | |||
| 508 | u32 datalen = field_data[i].len; | 508 | u32 datalen = field_data[i].len; |
| 509 | 509 | ||
| 510 | if (strcmp(td->name, IMA_TEMPLATE_IMA_NAME) != 0) { | 510 | if (strcmp(td->name, IMA_TEMPLATE_IMA_NAME) != 0) { |
| 511 | rc = crypto_shash_update(&desc.shash, | 511 | rc = crypto_shash_update(shash, |
| 512 | (const u8 *) &field_data[i].len, | 512 | (const u8 *) &field_data[i].len, |
| 513 | sizeof(field_data[i].len)); | 513 | sizeof(field_data[i].len)); |
| 514 | if (rc) | 514 | if (rc) |
| @@ -518,13 +518,13 @@ static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data, | |||
| 518 | data_to_hash = buffer; | 518 | data_to_hash = buffer; |
| 519 | datalen = IMA_EVENT_NAME_LEN_MAX + 1; | 519 | datalen = IMA_EVENT_NAME_LEN_MAX + 1; |
| 520 | } | 520 | } |
| 521 | rc = crypto_shash_update(&desc.shash, data_to_hash, datalen); | 521 | rc = crypto_shash_update(shash, data_to_hash, datalen); |
| 522 | if (rc) | 522 | if (rc) |
| 523 | break; | 523 | break; |
| 524 | } | 524 | } |
| 525 | 525 | ||
| 526 | if (!rc) | 526 | if (!rc) |
| 527 | rc = crypto_shash_final(&desc.shash, hash->digest); | 527 | rc = crypto_shash_final(shash, hash->digest); |
| 528 | 528 | ||
| 529 | return rc; | 529 | return rc; |
| 530 | } | 530 | } |
| @@ -565,15 +565,12 @@ static int __init ima_calc_boot_aggregate_tfm(char *digest, | |||
| 565 | { | 565 | { |
| 566 | u8 pcr_i[TPM_DIGEST_SIZE]; | 566 | u8 pcr_i[TPM_DIGEST_SIZE]; |
| 567 | int rc, i; | 567 | int rc, i; |
| 568 | struct { | 568 | SHASH_DESC_ON_STACK(shash, tfm); |
| 569 | struct shash_desc shash; | ||
| 570 | char ctx[crypto_shash_descsize(tfm)]; | ||
| 571 | } desc; | ||
| 572 | 569 | ||
| 573 | desc.shash.tfm = tfm; | 570 | shash->tfm = tfm; |
| 574 | desc.shash.flags = 0; | 571 | shash->flags = 0; |
| 575 | 572 | ||
| 576 | rc = crypto_shash_init(&desc.shash); | 573 | rc = crypto_shash_init(shash); |
| 577 | if (rc != 0) | 574 | if (rc != 0) |
| 578 | return rc; | 575 | return rc; |
| 579 | 576 | ||
| @@ -581,10 +578,10 @@ static int __init ima_calc_boot_aggregate_tfm(char *digest, | |||
| 581 | for (i = TPM_PCR0; i < TPM_PCR8; i++) { | 578 | for (i = TPM_PCR0; i < TPM_PCR8; i++) { |
| 582 | ima_pcrread(i, pcr_i); | 579 | ima_pcrread(i, pcr_i); |
| 583 | /* now accumulate with current aggregate */ | 580 | /* now accumulate with current aggregate */ |
| 584 | rc = crypto_shash_update(&desc.shash, pcr_i, TPM_DIGEST_SIZE); | 581 | rc = crypto_shash_update(shash, pcr_i, TPM_DIGEST_SIZE); |
| 585 | } | 582 | } |
| 586 | if (!rc) | 583 | if (!rc) |
| 587 | crypto_shash_final(&desc.shash, digest); | 584 | crypto_shash_final(shash, digest); |
| 588 | return rc; | 585 | return rc; |
| 589 | } | 586 | } |
| 590 | 587 | ||
diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index e8f9d70a465d..9164fc8cac84 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c | |||
| @@ -43,7 +43,7 @@ int ima_used_chip; | |||
| 43 | * a different value.) Violations add a zero entry to the measurement | 43 | * a different value.) Violations add a zero entry to the measurement |
| 44 | * list and extend the aggregate PCR value with ff...ff's. | 44 | * list and extend the aggregate PCR value with ff...ff's. |
| 45 | */ | 45 | */ |
| 46 | static void __init ima_add_boot_aggregate(void) | 46 | static int __init ima_add_boot_aggregate(void) |
| 47 | { | 47 | { |
| 48 | static const char op[] = "add_boot_aggregate"; | 48 | static const char op[] = "add_boot_aggregate"; |
| 49 | const char *audit_cause = "ENOMEM"; | 49 | const char *audit_cause = "ENOMEM"; |
| @@ -72,17 +72,23 @@ static void __init ima_add_boot_aggregate(void) | |||
| 72 | 72 | ||
| 73 | result = ima_alloc_init_template(iint, NULL, boot_aggregate_name, | 73 | result = ima_alloc_init_template(iint, NULL, boot_aggregate_name, |
| 74 | NULL, 0, &entry); | 74 | NULL, 0, &entry); |
| 75 | if (result < 0) | 75 | if (result < 0) { |
| 76 | return; | 76 | audit_cause = "alloc_entry"; |
| 77 | goto err_out; | ||
| 78 | } | ||
| 77 | 79 | ||
| 78 | result = ima_store_template(entry, violation, NULL, | 80 | result = ima_store_template(entry, violation, NULL, |
| 79 | boot_aggregate_name); | 81 | boot_aggregate_name); |
| 80 | if (result < 0) | 82 | if (result < 0) { |
| 81 | ima_free_template_entry(entry); | 83 | ima_free_template_entry(entry); |
| 82 | return; | 84 | audit_cause = "store_entry"; |
| 85 | goto err_out; | ||
| 86 | } | ||
| 87 | return 0; | ||
| 83 | err_out: | 88 | err_out: |
| 84 | integrity_audit_msg(AUDIT_INTEGRITY_PCR, NULL, boot_aggregate_name, op, | 89 | integrity_audit_msg(AUDIT_INTEGRITY_PCR, NULL, boot_aggregate_name, op, |
| 85 | audit_cause, result, 0); | 90 | audit_cause, result, 0); |
| 91 | return result; | ||
| 86 | } | 92 | } |
| 87 | 93 | ||
| 88 | int __init ima_init(void) | 94 | int __init ima_init(void) |
| @@ -98,6 +104,10 @@ int __init ima_init(void) | |||
| 98 | if (!ima_used_chip) | 104 | if (!ima_used_chip) |
| 99 | pr_info("No TPM chip found, activating TPM-bypass!\n"); | 105 | pr_info("No TPM chip found, activating TPM-bypass!\n"); |
| 100 | 106 | ||
| 107 | rc = ima_init_keyring(INTEGRITY_KEYRING_IMA); | ||
| 108 | if (rc) | ||
| 109 | return rc; | ||
| 110 | |||
| 101 | rc = ima_init_crypto(); | 111 | rc = ima_init_crypto(); |
| 102 | if (rc) | 112 | if (rc) |
| 103 | return rc; | 113 | return rc; |
| @@ -105,7 +115,10 @@ int __init ima_init(void) | |||
| 105 | if (rc != 0) | 115 | if (rc != 0) |
| 106 | return rc; | 116 | return rc; |
| 107 | 117 | ||
| 108 | ima_add_boot_aggregate(); /* boot aggregate must be first entry */ | 118 | rc = ima_add_boot_aggregate(); /* boot aggregate must be first entry */ |
| 119 | if (rc != 0) | ||
| 120 | return rc; | ||
| 121 | |||
| 109 | ima_init_policy(); | 122 | ima_init_policy(); |
| 110 | 123 | ||
| 111 | return ima_fs_init(); | 124 | return ima_fs_init(); |
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 2917f980bf30..62f59eca32d3 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c | |||
| @@ -77,42 +77,39 @@ __setup("ima_hash=", hash_setup); | |||
| 77 | * could result in a file measurement error. | 77 | * could result in a file measurement error. |
| 78 | * | 78 | * |
| 79 | */ | 79 | */ |
| 80 | static void ima_rdwr_violation_check(struct file *file) | 80 | static void ima_rdwr_violation_check(struct file *file, |
| 81 | struct integrity_iint_cache *iint, | ||
| 82 | int must_measure, | ||
| 83 | char **pathbuf, | ||
| 84 | const char **pathname) | ||
| 81 | { | 85 | { |
| 82 | struct inode *inode = file_inode(file); | 86 | struct inode *inode = file_inode(file); |
| 83 | fmode_t mode = file->f_mode; | 87 | fmode_t mode = file->f_mode; |
| 84 | bool send_tomtou = false, send_writers = false; | 88 | bool send_tomtou = false, send_writers = false; |
| 85 | char *pathbuf = NULL; | ||
| 86 | const char *pathname; | ||
| 87 | |||
| 88 | if (!S_ISREG(inode->i_mode) || !ima_initialized) | ||
| 89 | return; | ||
| 90 | 89 | ||
| 91 | if (mode & FMODE_WRITE) { | 90 | if (mode & FMODE_WRITE) { |
| 92 | if (atomic_read(&inode->i_readcount) && IS_IMA(inode)) { | 91 | if (atomic_read(&inode->i_readcount) && IS_IMA(inode)) { |
| 93 | struct integrity_iint_cache *iint; | 92 | if (!iint) |
| 94 | iint = integrity_iint_find(inode); | 93 | iint = integrity_iint_find(inode); |
| 95 | /* IMA_MEASURE is set from reader side */ | 94 | /* IMA_MEASURE is set from reader side */ |
| 96 | if (iint && (iint->flags & IMA_MEASURE)) | 95 | if (iint && (iint->flags & IMA_MEASURE)) |
| 97 | send_tomtou = true; | 96 | send_tomtou = true; |
| 98 | } | 97 | } |
| 99 | } else { | 98 | } else { |
| 100 | if ((atomic_read(&inode->i_writecount) > 0) && | 99 | if ((atomic_read(&inode->i_writecount) > 0) && must_measure) |
| 101 | ima_must_measure(inode, MAY_READ, FILE_CHECK)) | ||
| 102 | send_writers = true; | 100 | send_writers = true; |
| 103 | } | 101 | } |
| 104 | 102 | ||
| 105 | if (!send_tomtou && !send_writers) | 103 | if (!send_tomtou && !send_writers) |
| 106 | return; | 104 | return; |
| 107 | 105 | ||
| 108 | pathname = ima_d_path(&file->f_path, &pathbuf); | 106 | *pathname = ima_d_path(&file->f_path, pathbuf); |
| 109 | 107 | ||
| 110 | if (send_tomtou) | 108 | if (send_tomtou) |
| 111 | ima_add_violation(file, pathname, "invalid_pcr", "ToMToU"); | 109 | ima_add_violation(file, *pathname, "invalid_pcr", "ToMToU"); |
| 112 | if (send_writers) | 110 | if (send_writers) |
| 113 | ima_add_violation(file, pathname, | 111 | ima_add_violation(file, *pathname, |
| 114 | "invalid_pcr", "open_writers"); | 112 | "invalid_pcr", "open_writers"); |
| 115 | kfree(pathbuf); | ||
| 116 | } | 113 | } |
| 117 | 114 | ||
| 118 | static void ima_check_last_writer(struct integrity_iint_cache *iint, | 115 | static void ima_check_last_writer(struct integrity_iint_cache *iint, |
| @@ -124,11 +121,13 @@ static void ima_check_last_writer(struct integrity_iint_cache *iint, | |||
| 124 | return; | 121 | return; |
| 125 | 122 | ||
| 126 | mutex_lock(&inode->i_mutex); | 123 | mutex_lock(&inode->i_mutex); |
| 127 | if (atomic_read(&inode->i_writecount) == 1 && | 124 | if (atomic_read(&inode->i_writecount) == 1) { |
| 128 | iint->version != inode->i_version) { | 125 | if ((iint->version != inode->i_version) || |
| 129 | iint->flags &= ~IMA_DONE_MASK; | 126 | (iint->flags & IMA_NEW_FILE)) { |
| 130 | if (iint->flags & IMA_APPRAISE) | 127 | iint->flags &= ~(IMA_DONE_MASK | IMA_NEW_FILE); |
| 131 | ima_update_xattr(iint, file); | 128 | if (iint->flags & IMA_APPRAISE) |
| 129 | ima_update_xattr(iint, file); | ||
| 130 | } | ||
| 132 | } | 131 | } |
| 133 | mutex_unlock(&inode->i_mutex); | 132 | mutex_unlock(&inode->i_mutex); |
| 134 | } | 133 | } |
| @@ -154,19 +153,20 @@ void ima_file_free(struct file *file) | |||
| 154 | ima_check_last_writer(iint, inode, file); | 153 | ima_check_last_writer(iint, inode, file); |
| 155 | } | 154 | } |
| 156 | 155 | ||
| 157 | static int process_measurement(struct file *file, const char *filename, | 156 | static int process_measurement(struct file *file, int mask, int function, |
| 158 | int mask, int function) | 157 | int opened) |
| 159 | { | 158 | { |
| 160 | struct inode *inode = file_inode(file); | 159 | struct inode *inode = file_inode(file); |
| 161 | struct integrity_iint_cache *iint; | 160 | struct integrity_iint_cache *iint = NULL; |
| 162 | struct ima_template_desc *template_desc; | 161 | struct ima_template_desc *template_desc; |
| 163 | char *pathbuf = NULL; | 162 | char *pathbuf = NULL; |
| 164 | const char *pathname = NULL; | 163 | const char *pathname = NULL; |
| 165 | int rc = -ENOMEM, action, must_appraise, _func; | 164 | int rc = -ENOMEM, action, must_appraise; |
| 166 | struct evm_ima_xattr_data *xattr_value = NULL, **xattr_ptr = NULL; | 165 | struct evm_ima_xattr_data *xattr_value = NULL, **xattr_ptr = NULL; |
| 167 | int xattr_len = 0; | 166 | int xattr_len = 0; |
| 167 | bool violation_check; | ||
| 168 | 168 | ||
| 169 | if (!ima_initialized || !S_ISREG(inode->i_mode)) | 169 | if (!ima_policy_flag || !S_ISREG(inode->i_mode)) |
| 170 | return 0; | 170 | return 0; |
| 171 | 171 | ||
| 172 | /* Return an IMA_MEASURE, IMA_APPRAISE, IMA_AUDIT action | 172 | /* Return an IMA_MEASURE, IMA_APPRAISE, IMA_AUDIT action |
| @@ -174,19 +174,33 @@ static int process_measurement(struct file *file, const char *filename, | |||
| 174 | * Included is the appraise submask. | 174 | * Included is the appraise submask. |
| 175 | */ | 175 | */ |
| 176 | action = ima_get_action(inode, mask, function); | 176 | action = ima_get_action(inode, mask, function); |
| 177 | if (!action) | 177 | violation_check = ((function == FILE_CHECK || function == MMAP_CHECK) && |
| 178 | (ima_policy_flag & IMA_MEASURE)); | ||
| 179 | if (!action && !violation_check) | ||
| 178 | return 0; | 180 | return 0; |
| 179 | 181 | ||
| 180 | must_appraise = action & IMA_APPRAISE; | 182 | must_appraise = action & IMA_APPRAISE; |
| 181 | 183 | ||
| 182 | /* Is the appraise rule hook specific? */ | 184 | /* Is the appraise rule hook specific? */ |
| 183 | _func = (action & IMA_FILE_APPRAISE) ? FILE_CHECK : function; | 185 | if (action & IMA_FILE_APPRAISE) |
| 186 | function = FILE_CHECK; | ||
| 184 | 187 | ||
| 185 | mutex_lock(&inode->i_mutex); | 188 | mutex_lock(&inode->i_mutex); |
| 186 | 189 | ||
| 187 | iint = integrity_inode_get(inode); | 190 | if (action) { |
| 188 | if (!iint) | 191 | iint = integrity_inode_get(inode); |
| 189 | goto out; | 192 | if (!iint) |
| 193 | goto out; | ||
| 194 | } | ||
| 195 | |||
| 196 | if (violation_check) { | ||
| 197 | ima_rdwr_violation_check(file, iint, action & IMA_MEASURE, | ||
| 198 | &pathbuf, &pathname); | ||
| 199 | if (!action) { | ||
| 200 | rc = 0; | ||
| 201 | goto out_free; | ||
| 202 | } | ||
| 203 | } | ||
| 190 | 204 | ||
| 191 | /* Determine if already appraised/measured based on bitmask | 205 | /* Determine if already appraised/measured based on bitmask |
| 192 | * (IMA_MEASURE, IMA_MEASURED, IMA_XXXX_APPRAISE, IMA_XXXX_APPRAISED, | 206 | * (IMA_MEASURE, IMA_MEASURED, IMA_XXXX_APPRAISE, IMA_XXXX_APPRAISED, |
| @@ -199,15 +213,13 @@ static int process_measurement(struct file *file, const char *filename, | |||
| 199 | /* Nothing to do, just return existing appraised status */ | 213 | /* Nothing to do, just return existing appraised status */ |
| 200 | if (!action) { | 214 | if (!action) { |
| 201 | if (must_appraise) | 215 | if (must_appraise) |
| 202 | rc = ima_get_cache_status(iint, _func); | 216 | rc = ima_get_cache_status(iint, function); |
| 203 | goto out_digsig; | 217 | goto out_digsig; |
| 204 | } | 218 | } |
| 205 | 219 | ||
| 206 | template_desc = ima_template_desc_current(); | 220 | template_desc = ima_template_desc_current(); |
| 207 | if (strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) == 0) { | 221 | if ((action & IMA_APPRAISE_SUBMASK) || |
| 208 | if (action & IMA_APPRAISE_SUBMASK) | 222 | strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) != 0) |
| 209 | xattr_ptr = &xattr_value; | ||
| 210 | } else | ||
| 211 | xattr_ptr = &xattr_value; | 223 | xattr_ptr = &xattr_value; |
| 212 | 224 | ||
| 213 | rc = ima_collect_measurement(iint, file, xattr_ptr, &xattr_len); | 225 | rc = ima_collect_measurement(iint, file, xattr_ptr, &xattr_len); |
| @@ -217,23 +229,26 @@ static int process_measurement(struct file *file, const char *filename, | |||
| 217 | goto out_digsig; | 229 | goto out_digsig; |
| 218 | } | 230 | } |
| 219 | 231 | ||
| 220 | pathname = filename ?: ima_d_path(&file->f_path, &pathbuf); | 232 | if (!pathname) /* ima_rdwr_violation possibly pre-fetched */ |
| 233 | pathname = ima_d_path(&file->f_path, &pathbuf); | ||
| 221 | 234 | ||
| 222 | if (action & IMA_MEASURE) | 235 | if (action & IMA_MEASURE) |
| 223 | ima_store_measurement(iint, file, pathname, | 236 | ima_store_measurement(iint, file, pathname, |
| 224 | xattr_value, xattr_len); | 237 | xattr_value, xattr_len); |
| 225 | if (action & IMA_APPRAISE_SUBMASK) | 238 | if (action & IMA_APPRAISE_SUBMASK) |
| 226 | rc = ima_appraise_measurement(_func, iint, file, pathname, | 239 | rc = ima_appraise_measurement(function, iint, file, pathname, |
| 227 | xattr_value, xattr_len); | 240 | xattr_value, xattr_len, opened); |
| 228 | if (action & IMA_AUDIT) | 241 | if (action & IMA_AUDIT) |
| 229 | ima_audit_measurement(iint, pathname); | 242 | ima_audit_measurement(iint, pathname); |
| 230 | kfree(pathbuf); | 243 | |
| 231 | out_digsig: | 244 | out_digsig: |
| 232 | if ((mask & MAY_WRITE) && (iint->flags & IMA_DIGSIG)) | 245 | if ((mask & MAY_WRITE) && (iint->flags & IMA_DIGSIG)) |
| 233 | rc = -EACCES; | 246 | rc = -EACCES; |
| 247 | kfree(xattr_value); | ||
| 248 | out_free: | ||
| 249 | kfree(pathbuf); | ||
| 234 | out: | 250 | out: |
| 235 | mutex_unlock(&inode->i_mutex); | 251 | mutex_unlock(&inode->i_mutex); |
| 236 | kfree(xattr_value); | ||
| 237 | if ((rc && must_appraise) && (ima_appraise & IMA_APPRAISE_ENFORCE)) | 252 | if ((rc && must_appraise) && (ima_appraise & IMA_APPRAISE_ENFORCE)) |
| 238 | return -EACCES; | 253 | return -EACCES; |
| 239 | return 0; | 254 | return 0; |
| @@ -253,7 +268,7 @@ out: | |||
| 253 | int ima_file_mmap(struct file *file, unsigned long prot) | 268 | int ima_file_mmap(struct file *file, unsigned long prot) |
| 254 | { | 269 | { |
| 255 | if (file && (prot & PROT_EXEC)) | 270 | if (file && (prot & PROT_EXEC)) |
| 256 | return process_measurement(file, NULL, MAY_EXEC, MMAP_CHECK); | 271 | return process_measurement(file, MAY_EXEC, MMAP_CHECK, 0); |
| 257 | return 0; | 272 | return 0; |
| 258 | } | 273 | } |
| 259 | 274 | ||
| @@ -272,10 +287,7 @@ int ima_file_mmap(struct file *file, unsigned long prot) | |||
| 272 | */ | 287 | */ |
| 273 | int ima_bprm_check(struct linux_binprm *bprm) | 288 | int ima_bprm_check(struct linux_binprm *bprm) |
| 274 | { | 289 | { |
| 275 | return process_measurement(bprm->file, | 290 | return process_measurement(bprm->file, MAY_EXEC, BPRM_CHECK, 0); |
| 276 | (strcmp(bprm->filename, bprm->interp) == 0) ? | ||
| 277 | bprm->filename : bprm->interp, | ||
| 278 | MAY_EXEC, BPRM_CHECK); | ||
| 279 | } | 291 | } |
| 280 | 292 | ||
| 281 | /** | 293 | /** |
| @@ -288,12 +300,11 @@ int ima_bprm_check(struct linux_binprm *bprm) | |||
| 288 | * On success return 0. On integrity appraisal error, assuming the file | 300 | * On success return 0. On integrity appraisal error, assuming the file |
| 289 | * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. | 301 | * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. |
| 290 | */ | 302 | */ |
| 291 | int ima_file_check(struct file *file, int mask) | 303 | int ima_file_check(struct file *file, int mask, int opened) |
| 292 | { | 304 | { |
| 293 | ima_rdwr_violation_check(file); | 305 | return process_measurement(file, |
| 294 | return process_measurement(file, NULL, | ||
| 295 | mask & (MAY_READ | MAY_WRITE | MAY_EXEC), | 306 | mask & (MAY_READ | MAY_WRITE | MAY_EXEC), |
| 296 | FILE_CHECK); | 307 | FILE_CHECK, opened); |
| 297 | } | 308 | } |
| 298 | EXPORT_SYMBOL_GPL(ima_file_check); | 309 | EXPORT_SYMBOL_GPL(ima_file_check); |
| 299 | 310 | ||
| @@ -316,7 +327,7 @@ int ima_module_check(struct file *file) | |||
| 316 | #endif | 327 | #endif |
| 317 | return 0; /* We rely on module signature checking */ | 328 | return 0; /* We rely on module signature checking */ |
| 318 | } | 329 | } |
| 319 | return process_measurement(file, NULL, MAY_EXEC, MODULE_CHECK); | 330 | return process_measurement(file, MAY_EXEC, MODULE_CHECK, 0); |
| 320 | } | 331 | } |
| 321 | 332 | ||
| 322 | int ima_fw_from_file(struct file *file, char *buf, size_t size) | 333 | int ima_fw_from_file(struct file *file, char *buf, size_t size) |
| @@ -327,7 +338,7 @@ int ima_fw_from_file(struct file *file, char *buf, size_t size) | |||
| 327 | return -EACCES; /* INTEGRITY_UNKNOWN */ | 338 | return -EACCES; /* INTEGRITY_UNKNOWN */ |
| 328 | return 0; | 339 | return 0; |
| 329 | } | 340 | } |
| 330 | return process_measurement(file, NULL, MAY_EXEC, FIRMWARE_CHECK); | 341 | return process_measurement(file, MAY_EXEC, FIRMWARE_CHECK, 0); |
| 331 | } | 342 | } |
| 332 | 343 | ||
| 333 | static int __init init_ima(void) | 344 | static int __init init_ima(void) |
| @@ -336,14 +347,10 @@ static int __init init_ima(void) | |||
| 336 | 347 | ||
| 337 | hash_setup(CONFIG_IMA_DEFAULT_HASH); | 348 | hash_setup(CONFIG_IMA_DEFAULT_HASH); |
| 338 | error = ima_init(); | 349 | error = ima_init(); |
| 339 | if (error) | 350 | if (!error) { |
| 340 | goto out; | 351 | ima_initialized = 1; |
| 341 | 352 | ima_update_policy_flag(); | |
| 342 | error = ima_init_keyring(INTEGRITY_KEYRING_IMA); | 353 | } |
| 343 | if (error) | ||
| 344 | goto out; | ||
| 345 | ima_initialized = 1; | ||
| 346 | out: | ||
| 347 | return error; | 354 | return error; |
| 348 | } | 355 | } |
| 349 | 356 | ||
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 07099a8bc283..cdc620b2152f 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c | |||
| @@ -35,6 +35,8 @@ | |||
| 35 | #define DONT_APPRAISE 0x0008 | 35 | #define DONT_APPRAISE 0x0008 |
| 36 | #define AUDIT 0x0040 | 36 | #define AUDIT 0x0040 |
| 37 | 37 | ||
| 38 | int ima_policy_flag; | ||
| 39 | |||
| 38 | #define MAX_LSM_RULES 6 | 40 | #define MAX_LSM_RULES 6 |
| 39 | enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE, | 41 | enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE, |
| 40 | LSM_SUBJ_USER, LSM_SUBJ_ROLE, LSM_SUBJ_TYPE | 42 | LSM_SUBJ_USER, LSM_SUBJ_ROLE, LSM_SUBJ_TYPE |
| @@ -295,6 +297,26 @@ int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask, | |||
| 295 | return action; | 297 | return action; |
| 296 | } | 298 | } |
| 297 | 299 | ||
| 300 | /* | ||
| 301 | * Initialize the ima_policy_flag variable based on the currently | ||
| 302 | * loaded policy. Based on this flag, the decision to short circuit | ||
| 303 | * out of a function or not call the function in the first place | ||
| 304 | * can be made earlier. | ||
| 305 | */ | ||
| 306 | void ima_update_policy_flag(void) | ||
| 307 | { | ||
| 308 | struct ima_rule_entry *entry; | ||
| 309 | |||
| 310 | ima_policy_flag = 0; | ||
| 311 | list_for_each_entry(entry, ima_rules, list) { | ||
| 312 | if (entry->action & IMA_DO_MASK) | ||
| 313 | ima_policy_flag |= entry->action; | ||
| 314 | } | ||
| 315 | |||
| 316 | if (!ima_appraise) | ||
| 317 | ima_policy_flag &= ~IMA_APPRAISE; | ||
| 318 | } | ||
| 319 | |||
| 298 | /** | 320 | /** |
| 299 | * ima_init_policy - initialize the default measure rules. | 321 | * ima_init_policy - initialize the default measure rules. |
| 300 | * | 322 | * |
| @@ -341,6 +363,7 @@ void ima_update_policy(void) | |||
| 341 | 363 | ||
| 342 | if (ima_rules == &ima_default_rules) { | 364 | if (ima_rules == &ima_default_rules) { |
| 343 | ima_rules = &ima_policy_rules; | 365 | ima_rules = &ima_policy_rules; |
| 366 | ima_update_policy_flag(); | ||
| 344 | cause = "complete"; | 367 | cause = "complete"; |
| 345 | result = 0; | 368 | result = 0; |
| 346 | } | 369 | } |
diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c index a076a967ec47..e854862c9337 100644 --- a/security/integrity/ima/ima_template.c +++ b/security/integrity/ima/ima_template.c | |||
| @@ -152,24 +152,6 @@ out: | |||
| 152 | return result; | 152 | return result; |
| 153 | } | 153 | } |
| 154 | 154 | ||
| 155 | static int init_defined_templates(void) | ||
| 156 | { | ||
| 157 | int i = 0; | ||
| 158 | int result = 0; | ||
| 159 | |||
| 160 | /* Init defined templates. */ | ||
| 161 | for (i = 0; i < ARRAY_SIZE(defined_templates); i++) { | ||
| 162 | struct ima_template_desc *template = &defined_templates[i]; | ||
| 163 | |||
| 164 | result = template_desc_init_fields(template->fmt, | ||
| 165 | &(template->fields), | ||
| 166 | &(template->num_fields)); | ||
| 167 | if (result < 0) | ||
| 168 | return result; | ||
| 169 | } | ||
| 170 | return result; | ||
| 171 | } | ||
| 172 | |||
| 173 | struct ima_template_desc *ima_template_desc_current(void) | 155 | struct ima_template_desc *ima_template_desc_current(void) |
| 174 | { | 156 | { |
| 175 | if (!ima_template) | 157 | if (!ima_template) |
| @@ -178,13 +160,11 @@ struct ima_template_desc *ima_template_desc_current(void) | |||
| 178 | return ima_template; | 160 | return ima_template; |
| 179 | } | 161 | } |
| 180 | 162 | ||
| 181 | int ima_init_template(void) | 163 | int __init ima_init_template(void) |
| 182 | { | 164 | { |
| 183 | int result; | 165 | struct ima_template_desc *template = ima_template_desc_current(); |
| 184 | |||
| 185 | result = init_defined_templates(); | ||
| 186 | if (result < 0) | ||
| 187 | return result; | ||
| 188 | 166 | ||
| 189 | return 0; | 167 | return template_desc_init_fields(template->fmt, |
| 168 | &(template->fields), | ||
| 169 | &(template->num_fields)); | ||
| 190 | } | 170 | } |
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h index 19b8e314ca96..9d1c2ebfe12a 100644 --- a/security/integrity/integrity.h +++ b/security/integrity/integrity.h | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #define IMA_DIGSIG 0x01000000 | 31 | #define IMA_DIGSIG 0x01000000 |
| 32 | #define IMA_DIGSIG_REQUIRED 0x02000000 | 32 | #define IMA_DIGSIG_REQUIRED 0x02000000 |
| 33 | #define IMA_PERMIT_DIRECTIO 0x04000000 | 33 | #define IMA_PERMIT_DIRECTIO 0x04000000 |
| 34 | #define IMA_NEW_FILE 0x08000000 | ||
| 34 | 35 | ||
| 35 | #define IMA_DO_MASK (IMA_MEASURE | IMA_APPRAISE | IMA_AUDIT | \ | 36 | #define IMA_DO_MASK (IMA_MEASURE | IMA_APPRAISE | IMA_AUDIT | \ |
| 36 | IMA_APPRAISE_SUBMASK) | 37 | IMA_APPRAISE_SUBMASK) |
| @@ -60,6 +61,7 @@ enum evm_ima_xattr_type { | |||
| 60 | EVM_XATTR_HMAC, | 61 | EVM_XATTR_HMAC, |
| 61 | EVM_IMA_XATTR_DIGSIG, | 62 | EVM_IMA_XATTR_DIGSIG, |
| 62 | IMA_XATTR_DIGEST_NG, | 63 | IMA_XATTR_DIGEST_NG, |
| 64 | IMA_XATTR_LAST | ||
| 63 | }; | 65 | }; |
| 64 | 66 | ||
| 65 | struct evm_ima_xattr_data { | 67 | struct evm_ima_xattr_data { |
| @@ -116,7 +118,6 @@ struct integrity_iint_cache { | |||
| 116 | /* rbtree tree calls to lookup, insert, delete | 118 | /* rbtree tree calls to lookup, insert, delete |
| 117 | * integrity data associated with an inode. | 119 | * integrity data associated with an inode. |
| 118 | */ | 120 | */ |
| 119 | struct integrity_iint_cache *integrity_iint_insert(struct inode *inode); | ||
| 120 | struct integrity_iint_cache *integrity_iint_find(struct inode *inode); | 121 | struct integrity_iint_cache *integrity_iint_find(struct inode *inode); |
| 121 | 122 | ||
| 122 | #define INTEGRITY_KEYRING_EVM 0 | 123 | #define INTEGRITY_KEYRING_EVM 0 |
diff --git a/security/keys/big_key.c b/security/keys/big_key.c index c2f91a0cf889..b6adb94f6d52 100644 --- a/security/keys/big_key.c +++ b/security/keys/big_key.c | |||
| @@ -33,11 +33,9 @@ MODULE_LICENSE("GPL"); | |||
| 33 | */ | 33 | */ |
| 34 | struct key_type key_type_big_key = { | 34 | struct key_type key_type_big_key = { |
| 35 | .name = "big_key", | 35 | .name = "big_key", |
| 36 | .def_lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, | ||
| 37 | .preparse = big_key_preparse, | 36 | .preparse = big_key_preparse, |
| 38 | .free_preparse = big_key_free_preparse, | 37 | .free_preparse = big_key_free_preparse, |
| 39 | .instantiate = generic_key_instantiate, | 38 | .instantiate = generic_key_instantiate, |
| 40 | .match = user_match, | ||
| 41 | .revoke = big_key_revoke, | 39 | .revoke = big_key_revoke, |
| 42 | .destroy = big_key_destroy, | 40 | .destroy = big_key_destroy, |
| 43 | .describe = big_key_describe, | 41 | .describe = big_key_describe, |
diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c index 5fe443d120af..db9675db1026 100644 --- a/security/keys/encrypted-keys/encrypted.c +++ b/security/keys/encrypted-keys/encrypted.c | |||
| @@ -970,7 +970,6 @@ struct key_type key_type_encrypted = { | |||
| 970 | .name = "encrypted", | 970 | .name = "encrypted", |
| 971 | .instantiate = encrypted_instantiate, | 971 | .instantiate = encrypted_instantiate, |
| 972 | .update = encrypted_update, | 972 | .update = encrypted_update, |
| 973 | .match = user_match, | ||
| 974 | .destroy = encrypted_destroy, | 973 | .destroy = encrypted_destroy, |
| 975 | .describe = user_describe, | 974 | .describe = user_describe, |
| 976 | .read = encrypted_read, | 975 | .read = encrypted_read, |
diff --git a/security/keys/internal.h b/security/keys/internal.h index 5f20da01fd8d..b8960c4959a5 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h | |||
| @@ -107,20 +107,16 @@ extern int iterate_over_keyring(const struct key *keyring, | |||
| 107 | int (*func)(const struct key *key, void *data), | 107 | int (*func)(const struct key *key, void *data), |
| 108 | void *data); | 108 | void *data); |
| 109 | 109 | ||
| 110 | typedef int (*key_match_func_t)(const struct key *, const void *); | ||
| 111 | |||
| 112 | struct keyring_search_context { | 110 | struct keyring_search_context { |
| 113 | struct keyring_index_key index_key; | 111 | struct keyring_index_key index_key; |
| 114 | const struct cred *cred; | 112 | const struct cred *cred; |
| 115 | key_match_func_t match; | 113 | struct key_match_data match_data; |
| 116 | const void *match_data; | ||
| 117 | unsigned flags; | 114 | unsigned flags; |
| 118 | #define KEYRING_SEARCH_LOOKUP_TYPE 0x0001 /* [as type->def_lookup_type] */ | 115 | #define KEYRING_SEARCH_NO_STATE_CHECK 0x0001 /* Skip state checks */ |
| 119 | #define KEYRING_SEARCH_NO_STATE_CHECK 0x0002 /* Skip state checks */ | 116 | #define KEYRING_SEARCH_DO_STATE_CHECK 0x0002 /* Override NO_STATE_CHECK */ |
| 120 | #define KEYRING_SEARCH_DO_STATE_CHECK 0x0004 /* Override NO_STATE_CHECK */ | 117 | #define KEYRING_SEARCH_NO_UPDATE_TIME 0x0004 /* Don't update times */ |
| 121 | #define KEYRING_SEARCH_NO_UPDATE_TIME 0x0008 /* Don't update times */ | 118 | #define KEYRING_SEARCH_NO_CHECK_PERM 0x0008 /* Don't check permissions */ |
| 122 | #define KEYRING_SEARCH_NO_CHECK_PERM 0x0010 /* Don't check permissions */ | 119 | #define KEYRING_SEARCH_DETECT_TOO_DEEP 0x0010 /* Give an error on excessive depth */ |
| 123 | #define KEYRING_SEARCH_DETECT_TOO_DEEP 0x0020 /* Give an error on excessive depth */ | ||
| 124 | 120 | ||
| 125 | int (*iterator)(const void *object, void *iterator_data); | 121 | int (*iterator)(const void *object, void *iterator_data); |
| 126 | 122 | ||
| @@ -131,6 +127,8 @@ struct keyring_search_context { | |||
| 131 | struct timespec now; | 127 | struct timespec now; |
| 132 | }; | 128 | }; |
| 133 | 129 | ||
| 130 | extern bool key_default_cmp(const struct key *key, | ||
| 131 | const struct key_match_data *match_data); | ||
| 134 | extern key_ref_t keyring_search_aux(key_ref_t keyring_ref, | 132 | extern key_ref_t keyring_search_aux(key_ref_t keyring_ref, |
| 135 | struct keyring_search_context *ctx); | 133 | struct keyring_search_context *ctx); |
| 136 | 134 | ||
| @@ -152,7 +150,8 @@ extern struct key *request_key_and_link(struct key_type *type, | |||
| 152 | struct key *dest_keyring, | 150 | struct key *dest_keyring, |
| 153 | unsigned long flags); | 151 | unsigned long flags); |
| 154 | 152 | ||
| 155 | extern int lookup_user_key_possessed(const struct key *key, const void *target); | 153 | extern bool lookup_user_key_possessed(const struct key *key, |
| 154 | const struct key_match_data *match_data); | ||
| 156 | extern key_ref_t lookup_user_key(key_serial_t id, unsigned long flags, | 155 | extern key_ref_t lookup_user_key(key_serial_t id, unsigned long flags, |
| 157 | key_perm_t perm); | 156 | key_perm_t perm); |
| 158 | #define KEY_LOOKUP_CREATE 0x01 | 157 | #define KEY_LOOKUP_CREATE 0x01 |
diff --git a/security/keys/key.c b/security/keys/key.c index b90a68c4e2c4..e17ba6aefdc0 100644 --- a/security/keys/key.c +++ b/security/keys/key.c | |||
| @@ -27,8 +27,8 @@ DEFINE_SPINLOCK(key_serial_lock); | |||
| 27 | struct rb_root key_user_tree; /* tree of quota records indexed by UID */ | 27 | struct rb_root key_user_tree; /* tree of quota records indexed by UID */ |
| 28 | DEFINE_SPINLOCK(key_user_lock); | 28 | DEFINE_SPINLOCK(key_user_lock); |
| 29 | 29 | ||
| 30 | unsigned int key_quota_root_maxkeys = 200; /* root's key count quota */ | 30 | unsigned int key_quota_root_maxkeys = 1000000; /* root's key count quota */ |
| 31 | unsigned int key_quota_root_maxbytes = 20000; /* root's key space quota */ | 31 | unsigned int key_quota_root_maxbytes = 25000000; /* root's key space quota */ |
| 32 | unsigned int key_quota_maxkeys = 200; /* general key count quota */ | 32 | unsigned int key_quota_maxkeys = 200; /* general key count quota */ |
| 33 | unsigned int key_quota_maxbytes = 20000; /* general key space quota */ | 33 | unsigned int key_quota_maxbytes = 20000; /* general key space quota */ |
| 34 | 34 | ||
| @@ -799,7 +799,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
| 799 | } | 799 | } |
| 800 | 800 | ||
| 801 | key_ref = ERR_PTR(-EINVAL); | 801 | key_ref = ERR_PTR(-EINVAL); |
| 802 | if (!index_key.type->match || !index_key.type->instantiate || | 802 | if (!index_key.type->instantiate || |
| 803 | (!index_key.description && !index_key.type->preparse)) | 803 | (!index_key.description && !index_key.type->preparse)) |
| 804 | goto error_put_type; | 804 | goto error_put_type; |
| 805 | 805 | ||
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index e26f860e5f2e..eff88a5f5d40 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
| @@ -37,6 +37,8 @@ static int key_get_type_from_user(char *type, | |||
| 37 | return ret; | 37 | return ret; |
| 38 | if (ret == 0 || ret >= len) | 38 | if (ret == 0 || ret >= len) |
| 39 | return -EINVAL; | 39 | return -EINVAL; |
| 40 | if (type[0] == '.') | ||
| 41 | return -EPERM; | ||
| 40 | type[len - 1] = '\0'; | 42 | type[len - 1] = '\0'; |
| 41 | return 0; | 43 | return 0; |
| 42 | } | 44 | } |
diff --git a/security/keys/keyring.c b/security/keys/keyring.c index 8314a7d2104d..8177010174f7 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c | |||
| @@ -89,7 +89,6 @@ struct key_type key_type_keyring = { | |||
| 89 | .preparse = keyring_preparse, | 89 | .preparse = keyring_preparse, |
| 90 | .free_preparse = keyring_free_preparse, | 90 | .free_preparse = keyring_free_preparse, |
| 91 | .instantiate = keyring_instantiate, | 91 | .instantiate = keyring_instantiate, |
| 92 | .match = user_match, | ||
| 93 | .revoke = keyring_revoke, | 92 | .revoke = keyring_revoke, |
| 94 | .destroy = keyring_destroy, | 93 | .destroy = keyring_destroy, |
| 95 | .describe = keyring_describe, | 94 | .describe = keyring_describe, |
| @@ -512,6 +511,15 @@ struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid, | |||
| 512 | EXPORT_SYMBOL(keyring_alloc); | 511 | EXPORT_SYMBOL(keyring_alloc); |
| 513 | 512 | ||
| 514 | /* | 513 | /* |
| 514 | * By default, we keys found by getting an exact match on their descriptions. | ||
| 515 | */ | ||
| 516 | bool key_default_cmp(const struct key *key, | ||
| 517 | const struct key_match_data *match_data) | ||
| 518 | { | ||
| 519 | return strcmp(key->description, match_data->raw_data) == 0; | ||
| 520 | } | ||
| 521 | |||
| 522 | /* | ||
| 515 | * Iteration function to consider each key found. | 523 | * Iteration function to consider each key found. |
| 516 | */ | 524 | */ |
| 517 | static int keyring_search_iterator(const void *object, void *iterator_data) | 525 | static int keyring_search_iterator(const void *object, void *iterator_data) |
| @@ -545,7 +553,7 @@ static int keyring_search_iterator(const void *object, void *iterator_data) | |||
| 545 | } | 553 | } |
| 546 | 554 | ||
| 547 | /* keys that don't match */ | 555 | /* keys that don't match */ |
| 548 | if (!ctx->match(key, ctx->match_data)) { | 556 | if (!ctx->match_data.cmp(key, &ctx->match_data)) { |
| 549 | kleave(" = 0 [!match]"); | 557 | kleave(" = 0 [!match]"); |
| 550 | return 0; | 558 | return 0; |
| 551 | } | 559 | } |
| @@ -585,8 +593,7 @@ skipped: | |||
| 585 | */ | 593 | */ |
| 586 | static int search_keyring(struct key *keyring, struct keyring_search_context *ctx) | 594 | static int search_keyring(struct key *keyring, struct keyring_search_context *ctx) |
| 587 | { | 595 | { |
| 588 | if ((ctx->flags & KEYRING_SEARCH_LOOKUP_TYPE) == | 596 | if (ctx->match_data.lookup_type == KEYRING_SEARCH_LOOKUP_DIRECT) { |
| 589 | KEYRING_SEARCH_LOOKUP_DIRECT) { | ||
| 590 | const void *object; | 597 | const void *object; |
| 591 | 598 | ||
| 592 | object = assoc_array_find(&keyring->keys, | 599 | object = assoc_array_find(&keyring->keys, |
| @@ -627,7 +634,7 @@ static bool search_nested_keyrings(struct key *keyring, | |||
| 627 | /* Check to see if this top-level keyring is what we are looking for | 634 | /* Check to see if this top-level keyring is what we are looking for |
| 628 | * and whether it is valid or not. | 635 | * and whether it is valid or not. |
| 629 | */ | 636 | */ |
| 630 | if (ctx->flags & KEYRING_SEARCH_LOOKUP_ITERATE || | 637 | if (ctx->match_data.lookup_type == KEYRING_SEARCH_LOOKUP_ITERATE || |
| 631 | keyring_compare_object(keyring, &ctx->index_key)) { | 638 | keyring_compare_object(keyring, &ctx->index_key)) { |
| 632 | ctx->skipped_ret = 2; | 639 | ctx->skipped_ret = 2; |
| 633 | ctx->flags |= KEYRING_SEARCH_DO_STATE_CHECK; | 640 | ctx->flags |= KEYRING_SEARCH_DO_STATE_CHECK; |
| @@ -885,16 +892,25 @@ key_ref_t keyring_search(key_ref_t keyring, | |||
| 885 | .index_key.type = type, | 892 | .index_key.type = type, |
| 886 | .index_key.description = description, | 893 | .index_key.description = description, |
| 887 | .cred = current_cred(), | 894 | .cred = current_cred(), |
| 888 | .match = type->match, | 895 | .match_data.cmp = key_default_cmp, |
| 889 | .match_data = description, | 896 | .match_data.raw_data = description, |
| 890 | .flags = (type->def_lookup_type | | 897 | .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, |
| 891 | KEYRING_SEARCH_DO_STATE_CHECK), | 898 | .flags = KEYRING_SEARCH_DO_STATE_CHECK, |
| 892 | }; | 899 | }; |
| 900 | key_ref_t key; | ||
| 901 | int ret; | ||
| 893 | 902 | ||
| 894 | if (!ctx.match) | 903 | if (type->match_preparse) { |
| 895 | return ERR_PTR(-ENOKEY); | 904 | ret = type->match_preparse(&ctx.match_data); |
| 905 | if (ret < 0) | ||
| 906 | return ERR_PTR(ret); | ||
| 907 | } | ||
| 896 | 908 | ||
| 897 | return keyring_search_aux(keyring, &ctx); | 909 | key = keyring_search_aux(keyring, &ctx); |
| 910 | |||
| 911 | if (type->match_free) | ||
| 912 | type->match_free(&ctx.match_data); | ||
| 913 | return key; | ||
| 898 | } | 914 | } |
| 899 | EXPORT_SYMBOL(keyring_search); | 915 | EXPORT_SYMBOL(keyring_search); |
| 900 | 916 | ||
| @@ -1014,7 +1030,7 @@ static int keyring_detect_cycle_iterator(const void *object, | |||
| 1014 | 1030 | ||
| 1015 | /* We might get a keyring with matching index-key that is nonetheless a | 1031 | /* We might get a keyring with matching index-key that is nonetheless a |
| 1016 | * different keyring. */ | 1032 | * different keyring. */ |
| 1017 | if (key != ctx->match_data) | 1033 | if (key != ctx->match_data.raw_data) |
| 1018 | return 0; | 1034 | return 0; |
| 1019 | 1035 | ||
| 1020 | ctx->result = ERR_PTR(-EDEADLK); | 1036 | ctx->result = ERR_PTR(-EDEADLK); |
| @@ -1031,14 +1047,14 @@ static int keyring_detect_cycle_iterator(const void *object, | |||
| 1031 | static int keyring_detect_cycle(struct key *A, struct key *B) | 1047 | static int keyring_detect_cycle(struct key *A, struct key *B) |
| 1032 | { | 1048 | { |
| 1033 | struct keyring_search_context ctx = { | 1049 | struct keyring_search_context ctx = { |
| 1034 | .index_key = A->index_key, | 1050 | .index_key = A->index_key, |
| 1035 | .match_data = A, | 1051 | .match_data.raw_data = A, |
| 1036 | .iterator = keyring_detect_cycle_iterator, | 1052 | .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, |
| 1037 | .flags = (KEYRING_SEARCH_LOOKUP_DIRECT | | 1053 | .iterator = keyring_detect_cycle_iterator, |
| 1038 | KEYRING_SEARCH_NO_STATE_CHECK | | 1054 | .flags = (KEYRING_SEARCH_NO_STATE_CHECK | |
| 1039 | KEYRING_SEARCH_NO_UPDATE_TIME | | 1055 | KEYRING_SEARCH_NO_UPDATE_TIME | |
| 1040 | KEYRING_SEARCH_NO_CHECK_PERM | | 1056 | KEYRING_SEARCH_NO_CHECK_PERM | |
| 1041 | KEYRING_SEARCH_DETECT_TOO_DEEP), | 1057 | KEYRING_SEARCH_DETECT_TOO_DEEP), |
| 1042 | }; | 1058 | }; |
| 1043 | 1059 | ||
| 1044 | rcu_read_lock(); | 1060 | rcu_read_lock(); |
diff --git a/security/keys/proc.c b/security/keys/proc.c index d3f6f2fd21db..972eeb336b81 100644 --- a/security/keys/proc.c +++ b/security/keys/proc.c | |||
| @@ -194,10 +194,10 @@ static int proc_keys_show(struct seq_file *m, void *v) | |||
| 194 | .index_key.type = key->type, | 194 | .index_key.type = key->type, |
| 195 | .index_key.description = key->description, | 195 | .index_key.description = key->description, |
| 196 | .cred = current_cred(), | 196 | .cred = current_cred(), |
| 197 | .match = lookup_user_key_possessed, | 197 | .match_data.cmp = lookup_user_key_possessed, |
| 198 | .match_data = key, | 198 | .match_data.raw_data = key, |
| 199 | .flags = (KEYRING_SEARCH_NO_STATE_CHECK | | 199 | .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, |
| 200 | KEYRING_SEARCH_LOOKUP_DIRECT), | 200 | .flags = KEYRING_SEARCH_NO_STATE_CHECK, |
| 201 | }; | 201 | }; |
| 202 | 202 | ||
| 203 | key_ref = make_key_ref(key, 0); | 203 | key_ref = make_key_ref(key, 0); |
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 0cf8a130a267..bd536cb221e2 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c | |||
| @@ -489,9 +489,10 @@ found: | |||
| 489 | /* | 489 | /* |
| 490 | * See if the key we're looking at is the target key. | 490 | * See if the key we're looking at is the target key. |
| 491 | */ | 491 | */ |
| 492 | int lookup_user_key_possessed(const struct key *key, const void *target) | 492 | bool lookup_user_key_possessed(const struct key *key, |
| 493 | const struct key_match_data *match_data) | ||
| 493 | { | 494 | { |
| 494 | return key == target; | 495 | return key == match_data->raw_data; |
| 495 | } | 496 | } |
| 496 | 497 | ||
| 497 | /* | 498 | /* |
| @@ -516,9 +517,9 @@ key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags, | |||
| 516 | key_perm_t perm) | 517 | key_perm_t perm) |
| 517 | { | 518 | { |
| 518 | struct keyring_search_context ctx = { | 519 | struct keyring_search_context ctx = { |
| 519 | .match = lookup_user_key_possessed, | 520 | .match_data.cmp = lookup_user_key_possessed, |
| 520 | .flags = (KEYRING_SEARCH_NO_STATE_CHECK | | 521 | .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, |
| 521 | KEYRING_SEARCH_LOOKUP_DIRECT), | 522 | .flags = KEYRING_SEARCH_NO_STATE_CHECK, |
| 522 | }; | 523 | }; |
| 523 | struct request_key_auth *rka; | 524 | struct request_key_auth *rka; |
| 524 | struct key *key; | 525 | struct key *key; |
| @@ -673,7 +674,7 @@ try_again: | |||
| 673 | ctx.index_key.type = key->type; | 674 | ctx.index_key.type = key->type; |
| 674 | ctx.index_key.description = key->description; | 675 | ctx.index_key.description = key->description; |
| 675 | ctx.index_key.desc_len = strlen(key->description); | 676 | ctx.index_key.desc_len = strlen(key->description); |
| 676 | ctx.match_data = key; | 677 | ctx.match_data.raw_data = key; |
| 677 | kdebug("check possessed"); | 678 | kdebug("check possessed"); |
| 678 | skey_ref = search_process_keyrings(&ctx); | 679 | skey_ref = search_process_keyrings(&ctx); |
| 679 | kdebug("possessed=%p", skey_ref); | 680 | kdebug("possessed=%p", skey_ref); |
diff --git a/security/keys/request_key.c b/security/keys/request_key.c index 26a94f18af94..bb4337c7ae1b 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c | |||
| @@ -513,9 +513,9 @@ struct key *request_key_and_link(struct key_type *type, | |||
| 513 | .index_key.type = type, | 513 | .index_key.type = type, |
| 514 | .index_key.description = description, | 514 | .index_key.description = description, |
| 515 | .cred = current_cred(), | 515 | .cred = current_cred(), |
| 516 | .match = type->match, | 516 | .match_data.cmp = key_default_cmp, |
| 517 | .match_data = description, | 517 | .match_data.raw_data = description, |
| 518 | .flags = KEYRING_SEARCH_LOOKUP_DIRECT, | 518 | .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, |
| 519 | }; | 519 | }; |
| 520 | struct key *key; | 520 | struct key *key; |
| 521 | key_ref_t key_ref; | 521 | key_ref_t key_ref; |
| @@ -525,6 +525,14 @@ struct key *request_key_and_link(struct key_type *type, | |||
| 525 | ctx.index_key.type->name, ctx.index_key.description, | 525 | ctx.index_key.type->name, ctx.index_key.description, |
| 526 | callout_info, callout_len, aux, dest_keyring, flags); | 526 | callout_info, callout_len, aux, dest_keyring, flags); |
| 527 | 527 | ||
| 528 | if (type->match_preparse) { | ||
| 529 | ret = type->match_preparse(&ctx.match_data); | ||
| 530 | if (ret < 0) { | ||
| 531 | key = ERR_PTR(ret); | ||
| 532 | goto error; | ||
| 533 | } | ||
| 534 | } | ||
| 535 | |||
| 528 | /* search all the process keyrings for a key */ | 536 | /* search all the process keyrings for a key */ |
| 529 | key_ref = search_process_keyrings(&ctx); | 537 | key_ref = search_process_keyrings(&ctx); |
| 530 | 538 | ||
| @@ -537,7 +545,7 @@ struct key *request_key_and_link(struct key_type *type, | |||
| 537 | if (ret < 0) { | 545 | if (ret < 0) { |
| 538 | key_put(key); | 546 | key_put(key); |
| 539 | key = ERR_PTR(ret); | 547 | key = ERR_PTR(ret); |
| 540 | goto error; | 548 | goto error_free; |
| 541 | } | 549 | } |
| 542 | } | 550 | } |
| 543 | } else if (PTR_ERR(key_ref) != -EAGAIN) { | 551 | } else if (PTR_ERR(key_ref) != -EAGAIN) { |
| @@ -547,12 +555,15 @@ struct key *request_key_and_link(struct key_type *type, | |||
| 547 | * should consult userspace if we can */ | 555 | * should consult userspace if we can */ |
| 548 | key = ERR_PTR(-ENOKEY); | 556 | key = ERR_PTR(-ENOKEY); |
| 549 | if (!callout_info) | 557 | if (!callout_info) |
| 550 | goto error; | 558 | goto error_free; |
| 551 | 559 | ||
| 552 | key = construct_key_and_link(&ctx, callout_info, callout_len, | 560 | key = construct_key_and_link(&ctx, callout_info, callout_len, |
| 553 | aux, dest_keyring, flags); | 561 | aux, dest_keyring, flags); |
| 554 | } | 562 | } |
| 555 | 563 | ||
| 564 | error_free: | ||
| 565 | if (type->match_free) | ||
| 566 | type->match_free(&ctx.match_data); | ||
| 556 | error: | 567 | error: |
| 557 | kleave(" = %p", key); | 568 | kleave(" = %p", key); |
| 558 | return key; | 569 | return key; |
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c index 842e6f410d50..6639e2cb8853 100644 --- a/security/keys/request_key_auth.c +++ b/security/keys/request_key_auth.c | |||
| @@ -44,12 +44,12 @@ struct key_type key_type_request_key_auth = { | |||
| 44 | .read = request_key_auth_read, | 44 | .read = request_key_auth_read, |
| 45 | }; | 45 | }; |
| 46 | 46 | ||
| 47 | int request_key_auth_preparse(struct key_preparsed_payload *prep) | 47 | static int request_key_auth_preparse(struct key_preparsed_payload *prep) |
| 48 | { | 48 | { |
| 49 | return 0; | 49 | return 0; |
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | void request_key_auth_free_preparse(struct key_preparsed_payload *prep) | 52 | static void request_key_auth_free_preparse(struct key_preparsed_payload *prep) |
| 53 | { | 53 | { |
| 54 | } | 54 | } |
| 55 | 55 | ||
| @@ -246,9 +246,9 @@ struct key *key_get_instantiation_authkey(key_serial_t target_id) | |||
| 246 | .index_key.type = &key_type_request_key_auth, | 246 | .index_key.type = &key_type_request_key_auth, |
| 247 | .index_key.description = description, | 247 | .index_key.description = description, |
| 248 | .cred = current_cred(), | 248 | .cred = current_cred(), |
| 249 | .match = user_match, | 249 | .match_data.cmp = key_default_cmp, |
| 250 | .match_data = description, | 250 | .match_data.raw_data = description, |
| 251 | .flags = KEYRING_SEARCH_LOOKUP_DIRECT, | 251 | .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, |
| 252 | }; | 252 | }; |
| 253 | struct key *authkey; | 253 | struct key *authkey; |
| 254 | key_ref_t authkey_ref; | 254 | key_ref_t authkey_ref; |
diff --git a/security/keys/trusted.c b/security/keys/trusted.c index 6b804aa4529a..c0594cb07ada 100644 --- a/security/keys/trusted.c +++ b/security/keys/trusted.c | |||
| @@ -1096,7 +1096,6 @@ struct key_type key_type_trusted = { | |||
| 1096 | .name = "trusted", | 1096 | .name = "trusted", |
| 1097 | .instantiate = trusted_instantiate, | 1097 | .instantiate = trusted_instantiate, |
| 1098 | .update = trusted_update, | 1098 | .update = trusted_update, |
| 1099 | .match = user_match, | ||
| 1100 | .destroy = trusted_destroy, | 1099 | .destroy = trusted_destroy, |
| 1101 | .describe = user_describe, | 1100 | .describe = user_describe, |
| 1102 | .read = trusted_read, | 1101 | .read = trusted_read, |
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c index eee340011f2b..36b47bbd3d8c 100644 --- a/security/keys/user_defined.c +++ b/security/keys/user_defined.c | |||
| @@ -26,12 +26,10 @@ static int logon_vet_description(const char *desc); | |||
| 26 | */ | 26 | */ |
| 27 | struct key_type key_type_user = { | 27 | struct key_type key_type_user = { |
| 28 | .name = "user", | 28 | .name = "user", |
| 29 | .def_lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, | ||
| 30 | .preparse = user_preparse, | 29 | .preparse = user_preparse, |
| 31 | .free_preparse = user_free_preparse, | 30 | .free_preparse = user_free_preparse, |
| 32 | .instantiate = generic_key_instantiate, | 31 | .instantiate = generic_key_instantiate, |
| 33 | .update = user_update, | 32 | .update = user_update, |
| 34 | .match = user_match, | ||
| 35 | .revoke = user_revoke, | 33 | .revoke = user_revoke, |
| 36 | .destroy = user_destroy, | 34 | .destroy = user_destroy, |
| 37 | .describe = user_describe, | 35 | .describe = user_describe, |
| @@ -48,12 +46,10 @@ EXPORT_SYMBOL_GPL(key_type_user); | |||
| 48 | */ | 46 | */ |
| 49 | struct key_type key_type_logon = { | 47 | struct key_type key_type_logon = { |
| 50 | .name = "logon", | 48 | .name = "logon", |
| 51 | .def_lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, | ||
| 52 | .preparse = user_preparse, | 49 | .preparse = user_preparse, |
| 53 | .free_preparse = user_free_preparse, | 50 | .free_preparse = user_free_preparse, |
| 54 | .instantiate = generic_key_instantiate, | 51 | .instantiate = generic_key_instantiate, |
| 55 | .update = user_update, | 52 | .update = user_update, |
| 56 | .match = user_match, | ||
| 57 | .revoke = user_revoke, | 53 | .revoke = user_revoke, |
| 58 | .destroy = user_destroy, | 54 | .destroy = user_destroy, |
| 59 | .describe = user_describe, | 55 | .describe = user_describe, |
| @@ -139,16 +135,6 @@ error: | |||
| 139 | EXPORT_SYMBOL_GPL(user_update); | 135 | EXPORT_SYMBOL_GPL(user_update); |
| 140 | 136 | ||
| 141 | /* | 137 | /* |
| 142 | * match users on their name | ||
| 143 | */ | ||
| 144 | int user_match(const struct key *key, const void *description) | ||
| 145 | { | ||
| 146 | return strcmp(key->description, description) == 0; | ||
| 147 | } | ||
| 148 | |||
| 149 | EXPORT_SYMBOL_GPL(user_match); | ||
| 150 | |||
| 151 | /* | ||
| 152 | * dispose of the links from a revoked keyring | 138 | * dispose of the links from a revoked keyring |
| 153 | * - called with the key sem write-locked | 139 | * - called with the key sem write-locked |
| 154 | */ | 140 | */ |
diff --git a/security/security.c b/security/security.c index e41b1a8d7644..18b35c63fc0c 100644 --- a/security/security.c +++ b/security/security.c | |||
| @@ -775,9 +775,9 @@ int security_file_fcntl(struct file *file, unsigned int cmd, unsigned long arg) | |||
| 775 | return security_ops->file_fcntl(file, cmd, arg); | 775 | return security_ops->file_fcntl(file, cmd, arg); |
| 776 | } | 776 | } |
| 777 | 777 | ||
| 778 | int security_file_set_fowner(struct file *file) | 778 | void security_file_set_fowner(struct file *file) |
| 779 | { | 779 | { |
| 780 | return security_ops->file_set_fowner(file); | 780 | security_ops->file_set_fowner(file); |
| 781 | } | 781 | } |
| 782 | 782 | ||
| 783 | int security_file_send_sigiotask(struct task_struct *tsk, | 783 | int security_file_send_sigiotask(struct task_struct *tsk, |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index b0e940497e23..c603b20356ad 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
| @@ -481,6 +481,7 @@ next_inode: | |||
| 481 | list_entry(sbsec->isec_head.next, | 481 | list_entry(sbsec->isec_head.next, |
| 482 | struct inode_security_struct, list); | 482 | struct inode_security_struct, list); |
| 483 | struct inode *inode = isec->inode; | 483 | struct inode *inode = isec->inode; |
| 484 | list_del_init(&isec->list); | ||
| 484 | spin_unlock(&sbsec->isec_lock); | 485 | spin_unlock(&sbsec->isec_lock); |
| 485 | inode = igrab(inode); | 486 | inode = igrab(inode); |
| 486 | if (inode) { | 487 | if (inode) { |
| @@ -489,7 +490,6 @@ next_inode: | |||
| 489 | iput(inode); | 490 | iput(inode); |
| 490 | } | 491 | } |
| 491 | spin_lock(&sbsec->isec_lock); | 492 | spin_lock(&sbsec->isec_lock); |
| 492 | list_del_init(&isec->list); | ||
| 493 | goto next_inode; | 493 | goto next_inode; |
| 494 | } | 494 | } |
| 495 | spin_unlock(&sbsec->isec_lock); | 495 | spin_unlock(&sbsec->isec_lock); |
| @@ -2097,6 +2097,41 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages) | |||
| 2097 | 2097 | ||
| 2098 | /* binprm security operations */ | 2098 | /* binprm security operations */ |
| 2099 | 2099 | ||
| 2100 | static int check_nnp_nosuid(const struct linux_binprm *bprm, | ||
| 2101 | const struct task_security_struct *old_tsec, | ||
| 2102 | const struct task_security_struct *new_tsec) | ||
| 2103 | { | ||
| 2104 | int nnp = (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS); | ||
| 2105 | int nosuid = (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID); | ||
| 2106 | int rc; | ||
| 2107 | |||
| 2108 | if (!nnp && !nosuid) | ||
| 2109 | return 0; /* neither NNP nor nosuid */ | ||
| 2110 | |||
| 2111 | if (new_tsec->sid == old_tsec->sid) | ||
| 2112 | return 0; /* No change in credentials */ | ||
| 2113 | |||
| 2114 | /* | ||
| 2115 | * The only transitions we permit under NNP or nosuid | ||
| 2116 | * are transitions to bounded SIDs, i.e. SIDs that are | ||
| 2117 | * guaranteed to only be allowed a subset of the permissions | ||
| 2118 | * of the current SID. | ||
| 2119 | */ | ||
| 2120 | rc = security_bounded_transition(old_tsec->sid, new_tsec->sid); | ||
| 2121 | if (rc) { | ||
| 2122 | /* | ||
| 2123 | * On failure, preserve the errno values for NNP vs nosuid. | ||
| 2124 | * NNP: Operation not permitted for caller. | ||
| 2125 | * nosuid: Permission denied to file. | ||
| 2126 | */ | ||
| 2127 | if (nnp) | ||
| 2128 | return -EPERM; | ||
| 2129 | else | ||
| 2130 | return -EACCES; | ||
| 2131 | } | ||
| 2132 | return 0; | ||
| 2133 | } | ||
| 2134 | |||
| 2100 | static int selinux_bprm_set_creds(struct linux_binprm *bprm) | 2135 | static int selinux_bprm_set_creds(struct linux_binprm *bprm) |
| 2101 | { | 2136 | { |
| 2102 | const struct task_security_struct *old_tsec; | 2137 | const struct task_security_struct *old_tsec; |
| @@ -2133,14 +2168,10 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |||
| 2133 | /* Reset exec SID on execve. */ | 2168 | /* Reset exec SID on execve. */ |
| 2134 | new_tsec->exec_sid = 0; | 2169 | new_tsec->exec_sid = 0; |
| 2135 | 2170 | ||
| 2136 | /* | 2171 | /* Fail on NNP or nosuid if not an allowed transition. */ |
| 2137 | * Minimize confusion: if no_new_privs or nosuid and a | 2172 | rc = check_nnp_nosuid(bprm, old_tsec, new_tsec); |
| 2138 | * transition is explicitly requested, then fail the exec. | 2173 | if (rc) |
| 2139 | */ | 2174 | return rc; |
| 2140 | if (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) | ||
| 2141 | return -EPERM; | ||
| 2142 | if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) | ||
| 2143 | return -EACCES; | ||
| 2144 | } else { | 2175 | } else { |
| 2145 | /* Check for a default transition on this program. */ | 2176 | /* Check for a default transition on this program. */ |
| 2146 | rc = security_transition_sid(old_tsec->sid, isec->sid, | 2177 | rc = security_transition_sid(old_tsec->sid, isec->sid, |
| @@ -2148,15 +2179,19 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |||
| 2148 | &new_tsec->sid); | 2179 | &new_tsec->sid); |
| 2149 | if (rc) | 2180 | if (rc) |
| 2150 | return rc; | 2181 | return rc; |
| 2182 | |||
| 2183 | /* | ||
| 2184 | * Fallback to old SID on NNP or nosuid if not an allowed | ||
| 2185 | * transition. | ||
| 2186 | */ | ||
| 2187 | rc = check_nnp_nosuid(bprm, old_tsec, new_tsec); | ||
| 2188 | if (rc) | ||
| 2189 | new_tsec->sid = old_tsec->sid; | ||
| 2151 | } | 2190 | } |
| 2152 | 2191 | ||
| 2153 | ad.type = LSM_AUDIT_DATA_PATH; | 2192 | ad.type = LSM_AUDIT_DATA_PATH; |
| 2154 | ad.u.path = bprm->file->f_path; | 2193 | ad.u.path = bprm->file->f_path; |
| 2155 | 2194 | ||
| 2156 | if ((bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) || | ||
| 2157 | (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS)) | ||
| 2158 | new_tsec->sid = old_tsec->sid; | ||
| 2159 | |||
| 2160 | if (new_tsec->sid == old_tsec->sid) { | 2195 | if (new_tsec->sid == old_tsec->sid) { |
| 2161 | rc = avc_has_perm(old_tsec->sid, isec->sid, | 2196 | rc = avc_has_perm(old_tsec->sid, isec->sid, |
| 2162 | SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad); | 2197 | SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad); |
| @@ -3346,14 +3381,12 @@ static int selinux_file_fcntl(struct file *file, unsigned int cmd, | |||
| 3346 | return err; | 3381 | return err; |
| 3347 | } | 3382 | } |
| 3348 | 3383 | ||
| 3349 | static int selinux_file_set_fowner(struct file *file) | 3384 | static void selinux_file_set_fowner(struct file *file) |
| 3350 | { | 3385 | { |
| 3351 | struct file_security_struct *fsec; | 3386 | struct file_security_struct *fsec; |
| 3352 | 3387 | ||
| 3353 | fsec = file->f_security; | 3388 | fsec = file->f_security; |
| 3354 | fsec->fown_sid = current_sid(); | 3389 | fsec->fown_sid = current_sid(); |
| 3355 | |||
| 3356 | return 0; | ||
| 3357 | } | 3390 | } |
| 3358 | 3391 | ||
| 3359 | static int selinux_file_send_sigiotask(struct task_struct *tsk, | 3392 | static int selinux_file_send_sigiotask(struct task_struct *tsk, |
| @@ -4272,15 +4305,15 @@ static int selinux_socket_unix_may_send(struct socket *sock, | |||
| 4272 | &ad); | 4305 | &ad); |
| 4273 | } | 4306 | } |
| 4274 | 4307 | ||
| 4275 | static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family, | 4308 | static int selinux_inet_sys_rcv_skb(struct net *ns, int ifindex, |
| 4276 | u32 peer_sid, | 4309 | char *addrp, u16 family, u32 peer_sid, |
| 4277 | struct common_audit_data *ad) | 4310 | struct common_audit_data *ad) |
| 4278 | { | 4311 | { |
| 4279 | int err; | 4312 | int err; |
| 4280 | u32 if_sid; | 4313 | u32 if_sid; |
| 4281 | u32 node_sid; | 4314 | u32 node_sid; |
| 4282 | 4315 | ||
| 4283 | err = sel_netif_sid(ifindex, &if_sid); | 4316 | err = sel_netif_sid(ns, ifindex, &if_sid); |
| 4284 | if (err) | 4317 | if (err) |
| 4285 | return err; | 4318 | return err; |
| 4286 | err = avc_has_perm(peer_sid, if_sid, | 4319 | err = avc_has_perm(peer_sid, if_sid, |
| @@ -4373,8 +4406,8 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
| 4373 | err = selinux_skb_peerlbl_sid(skb, family, &peer_sid); | 4406 | err = selinux_skb_peerlbl_sid(skb, family, &peer_sid); |
| 4374 | if (err) | 4407 | if (err) |
| 4375 | return err; | 4408 | return err; |
| 4376 | err = selinux_inet_sys_rcv_skb(skb->skb_iif, addrp, family, | 4409 | err = selinux_inet_sys_rcv_skb(sock_net(sk), skb->skb_iif, |
| 4377 | peer_sid, &ad); | 4410 | addrp, family, peer_sid, &ad); |
| 4378 | if (err) { | 4411 | if (err) { |
| 4379 | selinux_netlbl_err(skb, err, 0); | 4412 | selinux_netlbl_err(skb, err, 0); |
| 4380 | return err; | 4413 | return err; |
| @@ -4692,10 +4725,10 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) | |||
| 4692 | err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm); | 4725 | err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm); |
| 4693 | if (err) { | 4726 | if (err) { |
| 4694 | if (err == -EINVAL) { | 4727 | if (err == -EINVAL) { |
| 4695 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR, | 4728 | printk(KERN_WARNING |
| 4696 | "SELinux: unrecognized netlink message" | 4729 | "SELinux: unrecognized netlink message:" |
| 4697 | " type=%hu for sclass=%hu\n", | 4730 | " protocol=%hu nlmsg_type=%hu sclass=%hu\n", |
| 4698 | nlh->nlmsg_type, sksec->sclass); | 4731 | sk->sk_protocol, nlh->nlmsg_type, sksec->sclass); |
| 4699 | if (!selinux_enforcing || security_get_allow_unknown()) | 4732 | if (!selinux_enforcing || security_get_allow_unknown()) |
| 4700 | err = 0; | 4733 | err = 0; |
| 4701 | } | 4734 | } |
| @@ -4713,7 +4746,8 @@ out: | |||
| 4713 | 4746 | ||
| 4714 | #ifdef CONFIG_NETFILTER | 4747 | #ifdef CONFIG_NETFILTER |
| 4715 | 4748 | ||
| 4716 | static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, | 4749 | static unsigned int selinux_ip_forward(struct sk_buff *skb, |
| 4750 | const struct net_device *indev, | ||
| 4717 | u16 family) | 4751 | u16 family) |
| 4718 | { | 4752 | { |
| 4719 | int err; | 4753 | int err; |
| @@ -4739,14 +4773,14 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, | |||
| 4739 | 4773 | ||
| 4740 | ad.type = LSM_AUDIT_DATA_NET; | 4774 | ad.type = LSM_AUDIT_DATA_NET; |
| 4741 | ad.u.net = &net; | 4775 | ad.u.net = &net; |
| 4742 | ad.u.net->netif = ifindex; | 4776 | ad.u.net->netif = indev->ifindex; |
| 4743 | ad.u.net->family = family; | 4777 | ad.u.net->family = family; |
| 4744 | if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0) | 4778 | if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0) |
| 4745 | return NF_DROP; | 4779 | return NF_DROP; |
| 4746 | 4780 | ||
| 4747 | if (peerlbl_active) { | 4781 | if (peerlbl_active) { |
| 4748 | err = selinux_inet_sys_rcv_skb(ifindex, addrp, family, | 4782 | err = selinux_inet_sys_rcv_skb(dev_net(indev), indev->ifindex, |
| 4749 | peer_sid, &ad); | 4783 | addrp, family, peer_sid, &ad); |
| 4750 | if (err) { | 4784 | if (err) { |
| 4751 | selinux_netlbl_err(skb, err, 1); | 4785 | selinux_netlbl_err(skb, err, 1); |
| 4752 | return NF_DROP; | 4786 | return NF_DROP; |
| @@ -4775,7 +4809,7 @@ static unsigned int selinux_ipv4_forward(const struct nf_hook_ops *ops, | |||
| 4775 | const struct net_device *out, | 4809 | const struct net_device *out, |
| 4776 | int (*okfn)(struct sk_buff *)) | 4810 | int (*okfn)(struct sk_buff *)) |
| 4777 | { | 4811 | { |
| 4778 | return selinux_ip_forward(skb, in->ifindex, PF_INET); | 4812 | return selinux_ip_forward(skb, in, PF_INET); |
| 4779 | } | 4813 | } |
| 4780 | 4814 | ||
| 4781 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 4815 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
| @@ -4785,7 +4819,7 @@ static unsigned int selinux_ipv6_forward(const struct nf_hook_ops *ops, | |||
| 4785 | const struct net_device *out, | 4819 | const struct net_device *out, |
| 4786 | int (*okfn)(struct sk_buff *)) | 4820 | int (*okfn)(struct sk_buff *)) |
| 4787 | { | 4821 | { |
| 4788 | return selinux_ip_forward(skb, in->ifindex, PF_INET6); | 4822 | return selinux_ip_forward(skb, in, PF_INET6); |
| 4789 | } | 4823 | } |
| 4790 | #endif /* IPV6 */ | 4824 | #endif /* IPV6 */ |
| 4791 | 4825 | ||
| @@ -4873,11 +4907,13 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, | |||
| 4873 | return NF_ACCEPT; | 4907 | return NF_ACCEPT; |
| 4874 | } | 4908 | } |
| 4875 | 4909 | ||
| 4876 | static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, | 4910 | static unsigned int selinux_ip_postroute(struct sk_buff *skb, |
| 4911 | const struct net_device *outdev, | ||
| 4877 | u16 family) | 4912 | u16 family) |
| 4878 | { | 4913 | { |
| 4879 | u32 secmark_perm; | 4914 | u32 secmark_perm; |
| 4880 | u32 peer_sid; | 4915 | u32 peer_sid; |
| 4916 | int ifindex = outdev->ifindex; | ||
| 4881 | struct sock *sk; | 4917 | struct sock *sk; |
| 4882 | struct common_audit_data ad; | 4918 | struct common_audit_data ad; |
| 4883 | struct lsm_network_audit net = {0,}; | 4919 | struct lsm_network_audit net = {0,}; |
| @@ -4958,6 +4994,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, | |||
| 4958 | case PF_INET6: | 4994 | case PF_INET6: |
| 4959 | if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) | 4995 | if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) |
| 4960 | return NF_ACCEPT; | 4996 | return NF_ACCEPT; |
| 4997 | break; | ||
| 4961 | default: | 4998 | default: |
| 4962 | return NF_DROP_ERR(-ECONNREFUSED); | 4999 | return NF_DROP_ERR(-ECONNREFUSED); |
| 4963 | } | 5000 | } |
| @@ -4989,7 +5026,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, | |||
| 4989 | u32 if_sid; | 5026 | u32 if_sid; |
| 4990 | u32 node_sid; | 5027 | u32 node_sid; |
| 4991 | 5028 | ||
| 4992 | if (sel_netif_sid(ifindex, &if_sid)) | 5029 | if (sel_netif_sid(dev_net(outdev), ifindex, &if_sid)) |
| 4993 | return NF_DROP; | 5030 | return NF_DROP; |
| 4994 | if (avc_has_perm(peer_sid, if_sid, | 5031 | if (avc_has_perm(peer_sid, if_sid, |
| 4995 | SECCLASS_NETIF, NETIF__EGRESS, &ad)) | 5032 | SECCLASS_NETIF, NETIF__EGRESS, &ad)) |
| @@ -5011,7 +5048,7 @@ static unsigned int selinux_ipv4_postroute(const struct nf_hook_ops *ops, | |||
| 5011 | const struct net_device *out, | 5048 | const struct net_device *out, |
| 5012 | int (*okfn)(struct sk_buff *)) | 5049 | int (*okfn)(struct sk_buff *)) |
| 5013 | { | 5050 | { |
| 5014 | return selinux_ip_postroute(skb, out->ifindex, PF_INET); | 5051 | return selinux_ip_postroute(skb, out, PF_INET); |
| 5015 | } | 5052 | } |
| 5016 | 5053 | ||
| 5017 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 5054 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
| @@ -5021,7 +5058,7 @@ static unsigned int selinux_ipv6_postroute(const struct nf_hook_ops *ops, | |||
| 5021 | const struct net_device *out, | 5058 | const struct net_device *out, |
| 5022 | int (*okfn)(struct sk_buff *)) | 5059 | int (*okfn)(struct sk_buff *)) |
| 5023 | { | 5060 | { |
| 5024 | return selinux_ip_postroute(skb, out->ifindex, PF_INET6); | 5061 | return selinux_ip_postroute(skb, out, PF_INET6); |
| 5025 | } | 5062 | } |
| 5026 | #endif /* IPV6 */ | 5063 | #endif /* IPV6 */ |
| 5027 | 5064 | ||
| @@ -6035,7 +6072,7 @@ security_initcall(selinux_init); | |||
| 6035 | 6072 | ||
| 6036 | #if defined(CONFIG_NETFILTER) | 6073 | #if defined(CONFIG_NETFILTER) |
| 6037 | 6074 | ||
| 6038 | static struct nf_hook_ops selinux_ipv4_ops[] = { | 6075 | static struct nf_hook_ops selinux_nf_ops[] = { |
| 6039 | { | 6076 | { |
| 6040 | .hook = selinux_ipv4_postroute, | 6077 | .hook = selinux_ipv4_postroute, |
| 6041 | .owner = THIS_MODULE, | 6078 | .owner = THIS_MODULE, |
| @@ -6056,12 +6093,8 @@ static struct nf_hook_ops selinux_ipv4_ops[] = { | |||
| 6056 | .pf = NFPROTO_IPV4, | 6093 | .pf = NFPROTO_IPV4, |
| 6057 | .hooknum = NF_INET_LOCAL_OUT, | 6094 | .hooknum = NF_INET_LOCAL_OUT, |
| 6058 | .priority = NF_IP_PRI_SELINUX_FIRST, | 6095 | .priority = NF_IP_PRI_SELINUX_FIRST, |
| 6059 | } | 6096 | }, |
| 6060 | }; | ||
| 6061 | |||
| 6062 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 6097 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
| 6063 | |||
| 6064 | static struct nf_hook_ops selinux_ipv6_ops[] = { | ||
| 6065 | { | 6098 | { |
| 6066 | .hook = selinux_ipv6_postroute, | 6099 | .hook = selinux_ipv6_postroute, |
| 6067 | .owner = THIS_MODULE, | 6100 | .owner = THIS_MODULE, |
| @@ -6075,32 +6108,24 @@ static struct nf_hook_ops selinux_ipv6_ops[] = { | |||
| 6075 | .pf = NFPROTO_IPV6, | 6108 | .pf = NFPROTO_IPV6, |
| 6076 | .hooknum = NF_INET_FORWARD, | 6109 | .hooknum = NF_INET_FORWARD, |
| 6077 | .priority = NF_IP6_PRI_SELINUX_FIRST, | 6110 | .priority = NF_IP6_PRI_SELINUX_FIRST, |
| 6078 | } | 6111 | }, |
| 6079 | }; | ||
| 6080 | |||
| 6081 | #endif /* IPV6 */ | 6112 | #endif /* IPV6 */ |
| 6113 | }; | ||
| 6082 | 6114 | ||
| 6083 | static int __init selinux_nf_ip_init(void) | 6115 | static int __init selinux_nf_ip_init(void) |
| 6084 | { | 6116 | { |
| 6085 | int err = 0; | 6117 | int err; |
| 6086 | 6118 | ||
| 6087 | if (!selinux_enabled) | 6119 | if (!selinux_enabled) |
| 6088 | goto out; | 6120 | return 0; |
| 6089 | 6121 | ||
| 6090 | printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n"); | 6122 | printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n"); |
| 6091 | 6123 | ||
| 6092 | err = nf_register_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops)); | 6124 | err = nf_register_hooks(selinux_nf_ops, ARRAY_SIZE(selinux_nf_ops)); |
| 6093 | if (err) | ||
| 6094 | panic("SELinux: nf_register_hooks for IPv4: error %d\n", err); | ||
| 6095 | |||
| 6096 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
| 6097 | err = nf_register_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops)); | ||
| 6098 | if (err) | 6125 | if (err) |
| 6099 | panic("SELinux: nf_register_hooks for IPv6: error %d\n", err); | 6126 | panic("SELinux: nf_register_hooks: error %d\n", err); |
| 6100 | #endif /* IPV6 */ | ||
| 6101 | 6127 | ||
| 6102 | out: | 6128 | return 0; |
| 6103 | return err; | ||
| 6104 | } | 6129 | } |
| 6105 | 6130 | ||
| 6106 | __initcall(selinux_nf_ip_init); | 6131 | __initcall(selinux_nf_ip_init); |
| @@ -6110,10 +6135,7 @@ static void selinux_nf_ip_exit(void) | |||
| 6110 | { | 6135 | { |
| 6111 | printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n"); | 6136 | printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n"); |
| 6112 | 6137 | ||
| 6113 | nf_unregister_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops)); | 6138 | nf_unregister_hooks(selinux_nf_ops, ARRAY_SIZE(selinux_nf_ops)); |
| 6114 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
| 6115 | nf_unregister_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops)); | ||
| 6116 | #endif /* IPV6 */ | ||
| 6117 | } | 6139 | } |
| 6118 | #endif | 6140 | #endif |
| 6119 | 6141 | ||
diff --git a/security/selinux/include/netif.h b/security/selinux/include/netif.h index 57c6eae81eac..c72145444090 100644 --- a/security/selinux/include/netif.h +++ b/security/selinux/include/netif.h | |||
| @@ -17,9 +17,11 @@ | |||
| 17 | #ifndef _SELINUX_NETIF_H_ | 17 | #ifndef _SELINUX_NETIF_H_ |
| 18 | #define _SELINUX_NETIF_H_ | 18 | #define _SELINUX_NETIF_H_ |
| 19 | 19 | ||
| 20 | #include <net/net_namespace.h> | ||
| 21 | |||
| 20 | void sel_netif_flush(void); | 22 | void sel_netif_flush(void); |
| 21 | 23 | ||
| 22 | int sel_netif_sid(int ifindex, u32 *sid); | 24 | int sel_netif_sid(struct net *ns, int ifindex, u32 *sid); |
| 23 | 25 | ||
| 24 | #endif /* _SELINUX_NETIF_H_ */ | 26 | #endif /* _SELINUX_NETIF_H_ */ |
| 25 | 27 | ||
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index 078e553f52f2..81fa718d5cb3 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <linux/binfmts.h> | 24 | #include <linux/binfmts.h> |
| 25 | #include <linux/in.h> | 25 | #include <linux/in.h> |
| 26 | #include <linux/spinlock.h> | 26 | #include <linux/spinlock.h> |
| 27 | #include <net/net_namespace.h> | ||
| 27 | #include "flask.h" | 28 | #include "flask.h" |
| 28 | #include "avc.h" | 29 | #include "avc.h" |
| 29 | 30 | ||
| @@ -78,6 +79,7 @@ struct ipc_security_struct { | |||
| 78 | }; | 79 | }; |
| 79 | 80 | ||
| 80 | struct netif_security_struct { | 81 | struct netif_security_struct { |
| 82 | struct net *ns; /* network namespace */ | ||
| 81 | int ifindex; /* device index */ | 83 | int ifindex; /* device index */ |
| 82 | u32 sid; /* SID for this interface */ | 84 | u32 sid; /* SID for this interface */ |
| 83 | }; | 85 | }; |
diff --git a/security/selinux/netif.c b/security/selinux/netif.c index 3c3de4ca0ebc..e607b4473ef6 100644 --- a/security/selinux/netif.c +++ b/security/selinux/netif.c | |||
| @@ -45,6 +45,7 @@ static struct list_head sel_netif_hash[SEL_NETIF_HASH_SIZE]; | |||
| 45 | 45 | ||
| 46 | /** | 46 | /** |
| 47 | * sel_netif_hashfn - Hashing function for the interface table | 47 | * sel_netif_hashfn - Hashing function for the interface table |
| 48 | * @ns: the network namespace | ||
| 48 | * @ifindex: the network interface | 49 | * @ifindex: the network interface |
| 49 | * | 50 | * |
| 50 | * Description: | 51 | * Description: |
| @@ -52,13 +53,14 @@ static struct list_head sel_netif_hash[SEL_NETIF_HASH_SIZE]; | |||
| 52 | * bucket number for the given interface. | 53 | * bucket number for the given interface. |
| 53 | * | 54 | * |
| 54 | */ | 55 | */ |
| 55 | static inline u32 sel_netif_hashfn(int ifindex) | 56 | static inline u32 sel_netif_hashfn(const struct net *ns, int ifindex) |
| 56 | { | 57 | { |
| 57 | return (ifindex & (SEL_NETIF_HASH_SIZE - 1)); | 58 | return (((uintptr_t)ns + ifindex) & (SEL_NETIF_HASH_SIZE - 1)); |
| 58 | } | 59 | } |
| 59 | 60 | ||
| 60 | /** | 61 | /** |
| 61 | * sel_netif_find - Search for an interface record | 62 | * sel_netif_find - Search for an interface record |
| 63 | * @ns: the network namespace | ||
| 62 | * @ifindex: the network interface | 64 | * @ifindex: the network interface |
| 63 | * | 65 | * |
| 64 | * Description: | 66 | * Description: |
| @@ -66,15 +68,15 @@ static inline u32 sel_netif_hashfn(int ifindex) | |||
| 66 | * If an entry can not be found in the table return NULL. | 68 | * If an entry can not be found in the table return NULL. |
| 67 | * | 69 | * |
| 68 | */ | 70 | */ |
| 69 | static inline struct sel_netif *sel_netif_find(int ifindex) | 71 | static inline struct sel_netif *sel_netif_find(const struct net *ns, |
| 72 | int ifindex) | ||
| 70 | { | 73 | { |
| 71 | int idx = sel_netif_hashfn(ifindex); | 74 | int idx = sel_netif_hashfn(ns, ifindex); |
| 72 | struct sel_netif *netif; | 75 | struct sel_netif *netif; |
| 73 | 76 | ||
| 74 | list_for_each_entry_rcu(netif, &sel_netif_hash[idx], list) | 77 | list_for_each_entry_rcu(netif, &sel_netif_hash[idx], list) |
| 75 | /* all of the devices should normally fit in the hash, so we | 78 | if (net_eq(netif->nsec.ns, ns) && |
| 76 | * optimize for that case */ | 79 | netif->nsec.ifindex == ifindex) |
| 77 | if (likely(netif->nsec.ifindex == ifindex)) | ||
| 78 | return netif; | 80 | return netif; |
| 79 | 81 | ||
| 80 | return NULL; | 82 | return NULL; |
| @@ -96,7 +98,7 @@ static int sel_netif_insert(struct sel_netif *netif) | |||
| 96 | if (sel_netif_total >= SEL_NETIF_HASH_MAX) | 98 | if (sel_netif_total >= SEL_NETIF_HASH_MAX) |
| 97 | return -ENOSPC; | 99 | return -ENOSPC; |
| 98 | 100 | ||
| 99 | idx = sel_netif_hashfn(netif->nsec.ifindex); | 101 | idx = sel_netif_hashfn(netif->nsec.ns, netif->nsec.ifindex); |
| 100 | list_add_rcu(&netif->list, &sel_netif_hash[idx]); | 102 | list_add_rcu(&netif->list, &sel_netif_hash[idx]); |
| 101 | sel_netif_total++; | 103 | sel_netif_total++; |
| 102 | 104 | ||
| @@ -120,6 +122,7 @@ static void sel_netif_destroy(struct sel_netif *netif) | |||
| 120 | 122 | ||
| 121 | /** | 123 | /** |
| 122 | * sel_netif_sid_slow - Lookup the SID of a network interface using the policy | 124 | * sel_netif_sid_slow - Lookup the SID of a network interface using the policy |
| 125 | * @ns: the network namespace | ||
| 123 | * @ifindex: the network interface | 126 | * @ifindex: the network interface |
| 124 | * @sid: interface SID | 127 | * @sid: interface SID |
| 125 | * | 128 | * |
| @@ -130,7 +133,7 @@ static void sel_netif_destroy(struct sel_netif *netif) | |||
| 130 | * failure. | 133 | * failure. |
| 131 | * | 134 | * |
| 132 | */ | 135 | */ |
| 133 | static int sel_netif_sid_slow(int ifindex, u32 *sid) | 136 | static int sel_netif_sid_slow(struct net *ns, int ifindex, u32 *sid) |
| 134 | { | 137 | { |
| 135 | int ret; | 138 | int ret; |
| 136 | struct sel_netif *netif; | 139 | struct sel_netif *netif; |
| @@ -140,7 +143,7 @@ static int sel_netif_sid_slow(int ifindex, u32 *sid) | |||
| 140 | /* NOTE: we always use init's network namespace since we don't | 143 | /* NOTE: we always use init's network namespace since we don't |
| 141 | * currently support containers */ | 144 | * currently support containers */ |
| 142 | 145 | ||
| 143 | dev = dev_get_by_index(&init_net, ifindex); | 146 | dev = dev_get_by_index(ns, ifindex); |
| 144 | if (unlikely(dev == NULL)) { | 147 | if (unlikely(dev == NULL)) { |
| 145 | printk(KERN_WARNING | 148 | printk(KERN_WARNING |
| 146 | "SELinux: failure in sel_netif_sid_slow()," | 149 | "SELinux: failure in sel_netif_sid_slow()," |
| @@ -149,7 +152,7 @@ static int sel_netif_sid_slow(int ifindex, u32 *sid) | |||
| 149 | } | 152 | } |
| 150 | 153 | ||
| 151 | spin_lock_bh(&sel_netif_lock); | 154 | spin_lock_bh(&sel_netif_lock); |
| 152 | netif = sel_netif_find(ifindex); | 155 | netif = sel_netif_find(ns, ifindex); |
| 153 | if (netif != NULL) { | 156 | if (netif != NULL) { |
| 154 | *sid = netif->nsec.sid; | 157 | *sid = netif->nsec.sid; |
| 155 | ret = 0; | 158 | ret = 0; |
| @@ -163,6 +166,7 @@ static int sel_netif_sid_slow(int ifindex, u32 *sid) | |||
| 163 | ret = security_netif_sid(dev->name, &new->nsec.sid); | 166 | ret = security_netif_sid(dev->name, &new->nsec.sid); |
| 164 | if (ret != 0) | 167 | if (ret != 0) |
| 165 | goto out; | 168 | goto out; |
| 169 | new->nsec.ns = ns; | ||
| 166 | new->nsec.ifindex = ifindex; | 170 | new->nsec.ifindex = ifindex; |
| 167 | ret = sel_netif_insert(new); | 171 | ret = sel_netif_insert(new); |
| 168 | if (ret != 0) | 172 | if (ret != 0) |
| @@ -184,6 +188,7 @@ out: | |||
| 184 | 188 | ||
| 185 | /** | 189 | /** |
| 186 | * sel_netif_sid - Lookup the SID of a network interface | 190 | * sel_netif_sid - Lookup the SID of a network interface |
| 191 | * @ns: the network namespace | ||
| 187 | * @ifindex: the network interface | 192 | * @ifindex: the network interface |
| 188 | * @sid: interface SID | 193 | * @sid: interface SID |
| 189 | * | 194 | * |
| @@ -195,12 +200,12 @@ out: | |||
| 195 | * on failure. | 200 | * on failure. |
| 196 | * | 201 | * |
| 197 | */ | 202 | */ |
| 198 | int sel_netif_sid(int ifindex, u32 *sid) | 203 | int sel_netif_sid(struct net *ns, int ifindex, u32 *sid) |
| 199 | { | 204 | { |
| 200 | struct sel_netif *netif; | 205 | struct sel_netif *netif; |
| 201 | 206 | ||
| 202 | rcu_read_lock(); | 207 | rcu_read_lock(); |
| 203 | netif = sel_netif_find(ifindex); | 208 | netif = sel_netif_find(ns, ifindex); |
| 204 | if (likely(netif != NULL)) { | 209 | if (likely(netif != NULL)) { |
| 205 | *sid = netif->nsec.sid; | 210 | *sid = netif->nsec.sid; |
| 206 | rcu_read_unlock(); | 211 | rcu_read_unlock(); |
| @@ -208,11 +213,12 @@ int sel_netif_sid(int ifindex, u32 *sid) | |||
| 208 | } | 213 | } |
| 209 | rcu_read_unlock(); | 214 | rcu_read_unlock(); |
| 210 | 215 | ||
| 211 | return sel_netif_sid_slow(ifindex, sid); | 216 | return sel_netif_sid_slow(ns, ifindex, sid); |
| 212 | } | 217 | } |
| 213 | 218 | ||
| 214 | /** | 219 | /** |
| 215 | * sel_netif_kill - Remove an entry from the network interface table | 220 | * sel_netif_kill - Remove an entry from the network interface table |
| 221 | * @ns: the network namespace | ||
| 216 | * @ifindex: the network interface | 222 | * @ifindex: the network interface |
| 217 | * | 223 | * |
| 218 | * Description: | 224 | * Description: |
| @@ -220,13 +226,13 @@ int sel_netif_sid(int ifindex, u32 *sid) | |||
| 220 | * table if it exists. | 226 | * table if it exists. |
| 221 | * | 227 | * |
| 222 | */ | 228 | */ |
| 223 | static void sel_netif_kill(int ifindex) | 229 | static void sel_netif_kill(const struct net *ns, int ifindex) |
| 224 | { | 230 | { |
| 225 | struct sel_netif *netif; | 231 | struct sel_netif *netif; |
| 226 | 232 | ||
| 227 | rcu_read_lock(); | 233 | rcu_read_lock(); |
| 228 | spin_lock_bh(&sel_netif_lock); | 234 | spin_lock_bh(&sel_netif_lock); |
| 229 | netif = sel_netif_find(ifindex); | 235 | netif = sel_netif_find(ns, ifindex); |
| 230 | if (netif) | 236 | if (netif) |
| 231 | sel_netif_destroy(netif); | 237 | sel_netif_destroy(netif); |
| 232 | spin_unlock_bh(&sel_netif_lock); | 238 | spin_unlock_bh(&sel_netif_lock); |
| @@ -257,11 +263,8 @@ static int sel_netif_netdev_notifier_handler(struct notifier_block *this, | |||
| 257 | { | 263 | { |
| 258 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); | 264 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); |
| 259 | 265 | ||
| 260 | if (dev_net(dev) != &init_net) | ||
| 261 | return NOTIFY_DONE; | ||
| 262 | |||
| 263 | if (event == NETDEV_DOWN) | 266 | if (event == NETDEV_DOWN) |
| 264 | sel_netif_kill(dev->ifindex); | 267 | sel_netif_kill(dev_net(dev), dev->ifindex); |
| 265 | 268 | ||
| 266 | return NOTIFY_DONE; | 269 | return NOTIFY_DONE; |
| 267 | } | 270 | } |
| @@ -272,7 +275,7 @@ static struct notifier_block sel_netif_netdev_notifier = { | |||
| 272 | 275 | ||
| 273 | static __init int sel_netif_init(void) | 276 | static __init int sel_netif_init(void) |
| 274 | { | 277 | { |
| 275 | int i, err; | 278 | int i; |
| 276 | 279 | ||
| 277 | if (!selinux_enabled) | 280 | if (!selinux_enabled) |
| 278 | return 0; | 281 | return 0; |
| @@ -282,7 +285,7 @@ static __init int sel_netif_init(void) | |||
| 282 | 285 | ||
| 283 | register_netdevice_notifier(&sel_netif_netdev_notifier); | 286 | register_netdevice_notifier(&sel_netif_netdev_notifier); |
| 284 | 287 | ||
| 285 | return err; | 288 | return 0; |
| 286 | } | 289 | } |
| 287 | 290 | ||
| 288 | __initcall(sel_netif_init); | 291 | __initcall(sel_netif_init); |
diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c index ddf315260839..da923f89d2a9 100644 --- a/security/selinux/netnode.c +++ b/security/selinux/netnode.c | |||
| @@ -303,7 +303,6 @@ void sel_netnode_flush(void) | |||
| 303 | static __init int sel_netnode_init(void) | 303 | static __init int sel_netnode_init(void) |
| 304 | { | 304 | { |
| 305 | int iter; | 305 | int iter; |
| 306 | int ret; | ||
| 307 | 306 | ||
| 308 | if (!selinux_enabled) | 307 | if (!selinux_enabled) |
| 309 | return 0; | 308 | return 0; |
| @@ -313,7 +312,7 @@ static __init int sel_netnode_init(void) | |||
| 313 | sel_netnode_hash[iter].size = 0; | 312 | sel_netnode_hash[iter].size = 0; |
| 314 | } | 313 | } |
| 315 | 314 | ||
| 316 | return ret; | 315 | return 0; |
| 317 | } | 316 | } |
| 318 | 317 | ||
| 319 | __initcall(sel_netnode_init); | 318 | __initcall(sel_netnode_init); |
diff --git a/security/selinux/netport.c b/security/selinux/netport.c index 73ac6784d091..3311cc393cb4 100644 --- a/security/selinux/netport.c +++ b/security/selinux/netport.c | |||
| @@ -237,7 +237,6 @@ void sel_netport_flush(void) | |||
| 237 | static __init int sel_netport_init(void) | 237 | static __init int sel_netport_init(void) |
| 238 | { | 238 | { |
| 239 | int iter; | 239 | int iter; |
| 240 | int ret; | ||
| 241 | 240 | ||
| 242 | if (!selinux_enabled) | 241 | if (!selinux_enabled) |
| 243 | return 0; | 242 | return 0; |
| @@ -247,7 +246,7 @@ static __init int sel_netport_init(void) | |||
| 247 | sel_netport_hash[iter].size = 0; | 246 | sel_netport_hash[iter].size = 0; |
| 248 | } | 247 | } |
| 249 | 248 | ||
| 250 | return ret; | 249 | return 0; |
| 251 | } | 250 | } |
| 252 | 251 | ||
| 253 | __initcall(sel_netport_init); | 252 | __initcall(sel_netport_init); |
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 2aa9d172dc7e..a1d3944751b9 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
| @@ -728,7 +728,7 @@ static int security_validtrans_handle_fail(struct context *ocontext, | |||
| 728 | if (context_struct_to_string(tcontext, &t, &tlen)) | 728 | if (context_struct_to_string(tcontext, &t, &tlen)) |
| 729 | goto out; | 729 | goto out; |
| 730 | audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR, | 730 | audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR, |
| 731 | "security_validate_transition: denied for" | 731 | "op=security_validate_transition seresult=denied" |
| 732 | " oldcontext=%s newcontext=%s taskcontext=%s tclass=%s", | 732 | " oldcontext=%s newcontext=%s taskcontext=%s tclass=%s", |
| 733 | o, n, t, sym_name(&policydb, SYM_CLASSES, tclass-1)); | 733 | o, n, t, sym_name(&policydb, SYM_CLASSES, tclass-1)); |
| 734 | out: | 734 | out: |
| @@ -877,7 +877,7 @@ int security_bounded_transition(u32 old_sid, u32 new_sid) | |||
| 877 | audit_log(current->audit_context, | 877 | audit_log(current->audit_context, |
| 878 | GFP_ATOMIC, AUDIT_SELINUX_ERR, | 878 | GFP_ATOMIC, AUDIT_SELINUX_ERR, |
| 879 | "op=security_bounded_transition " | 879 | "op=security_bounded_transition " |
| 880 | "result=denied " | 880 | "seresult=denied " |
| 881 | "oldcontext=%s newcontext=%s", | 881 | "oldcontext=%s newcontext=%s", |
| 882 | old_name, new_name); | 882 | old_name, new_name); |
| 883 | } | 883 | } |
| @@ -1351,8 +1351,8 @@ static int compute_sid_handle_invalid_context( | |||
| 1351 | if (context_struct_to_string(newcontext, &n, &nlen)) | 1351 | if (context_struct_to_string(newcontext, &n, &nlen)) |
| 1352 | goto out; | 1352 | goto out; |
| 1353 | audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR, | 1353 | audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR, |
| 1354 | "security_compute_sid: invalid context %s" | 1354 | "op=security_compute_sid invalid_context=%s" |
| 1355 | " for scontext=%s" | 1355 | " scontext=%s" |
| 1356 | " tcontext=%s" | 1356 | " tcontext=%s" |
| 1357 | " tclass=%s", | 1357 | " tclass=%s", |
| 1358 | n, s, t, sym_name(&policydb, SYM_CLASSES, tclass-1)); | 1358 | n, s, t, sym_name(&policydb, SYM_CLASSES, tclass-1)); |
| @@ -2607,8 +2607,10 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid) | |||
| 2607 | rc = convert_context_handle_invalid_context(&newcon); | 2607 | rc = convert_context_handle_invalid_context(&newcon); |
| 2608 | if (rc) { | 2608 | if (rc) { |
| 2609 | if (!context_struct_to_string(&newcon, &s, &len)) { | 2609 | if (!context_struct_to_string(&newcon, &s, &len)) { |
| 2610 | audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR, | 2610 | audit_log(current->audit_context, |
| 2611 | "security_sid_mls_copy: invalid context %s", s); | 2611 | GFP_ATOMIC, AUDIT_SELINUX_ERR, |
| 2612 | "op=security_sid_mls_copy " | ||
| 2613 | "invalid_context=%s", s); | ||
| 2612 | kfree(s); | 2614 | kfree(s); |
| 2613 | } | 2615 | } |
| 2614 | goto out_unlock; | 2616 | goto out_unlock; |
diff --git a/security/smack/Kconfig b/security/smack/Kconfig index e69de9c642b7..b065f9789418 100644 --- a/security/smack/Kconfig +++ b/security/smack/Kconfig | |||
| @@ -12,3 +12,19 @@ config SECURITY_SMACK | |||
| 12 | of other mandatory security schemes. | 12 | of other mandatory security schemes. |
| 13 | If you are unsure how to answer this question, answer N. | 13 | If you are unsure how to answer this question, answer N. |
| 14 | 14 | ||
| 15 | config SECURITY_SMACK_BRINGUP | ||
| 16 | bool "Reporting on access granted by Smack rules" | ||
| 17 | depends on SECURITY_SMACK | ||
| 18 | default n | ||
| 19 | help | ||
| 20 | Enable the bring-up ("b") access mode in Smack rules. | ||
| 21 | When access is granted by a rule with the "b" mode a | ||
| 22 | message about the access requested is generated. The | ||
| 23 | intention is that a process can be granted a wide set | ||
| 24 | of access initially with the bringup mode set on the | ||
| 25 | rules. The developer can use the information to | ||
| 26 | identify which rules are necessary and what accesses | ||
| 27 | may be inappropriate. The developer can reduce the | ||
| 28 | access rule set once the behavior is well understood. | ||
| 29 | This is a superior mechanism to the oft abused | ||
| 30 | "permissive" mode of other systems. | ||
diff --git a/security/smack/smack.h b/security/smack/smack.h index 020307ef0972..b828a379377c 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h | |||
| @@ -71,11 +71,11 @@ struct smack_known { | |||
| 71 | #define SMK_CIPSOLEN 24 | 71 | #define SMK_CIPSOLEN 24 |
| 72 | 72 | ||
| 73 | struct superblock_smack { | 73 | struct superblock_smack { |
| 74 | char *smk_root; | 74 | struct smack_known *smk_root; |
| 75 | char *smk_floor; | 75 | struct smack_known *smk_floor; |
| 76 | char *smk_hat; | 76 | struct smack_known *smk_hat; |
| 77 | char *smk_default; | 77 | struct smack_known *smk_default; |
| 78 | int smk_initialized; | 78 | int smk_initialized; |
| 79 | }; | 79 | }; |
| 80 | 80 | ||
| 81 | struct socket_smack { | 81 | struct socket_smack { |
| @@ -88,7 +88,7 @@ struct socket_smack { | |||
| 88 | * Inode smack data | 88 | * Inode smack data |
| 89 | */ | 89 | */ |
| 90 | struct inode_smack { | 90 | struct inode_smack { |
| 91 | char *smk_inode; /* label of the fso */ | 91 | struct smack_known *smk_inode; /* label of the fso */ |
| 92 | struct smack_known *smk_task; /* label of the task */ | 92 | struct smack_known *smk_task; /* label of the task */ |
| 93 | struct smack_known *smk_mmap; /* label of the mmap domain */ | 93 | struct smack_known *smk_mmap; /* label of the mmap domain */ |
| 94 | struct mutex smk_lock; /* initialization lock */ | 94 | struct mutex smk_lock; /* initialization lock */ |
| @@ -112,7 +112,7 @@ struct task_smack { | |||
| 112 | struct smack_rule { | 112 | struct smack_rule { |
| 113 | struct list_head list; | 113 | struct list_head list; |
| 114 | struct smack_known *smk_subject; | 114 | struct smack_known *smk_subject; |
| 115 | char *smk_object; | 115 | struct smack_known *smk_object; |
| 116 | int smk_access; | 116 | int smk_access; |
| 117 | }; | 117 | }; |
| 118 | 118 | ||
| @@ -123,7 +123,7 @@ struct smk_netlbladdr { | |||
| 123 | struct list_head list; | 123 | struct list_head list; |
| 124 | struct sockaddr_in smk_host; /* network address */ | 124 | struct sockaddr_in smk_host; /* network address */ |
| 125 | struct in_addr smk_mask; /* network mask */ | 125 | struct in_addr smk_mask; /* network mask */ |
| 126 | char *smk_label; /* label */ | 126 | struct smack_known *smk_label; /* label */ |
| 127 | }; | 127 | }; |
| 128 | 128 | ||
| 129 | /* | 129 | /* |
| @@ -191,6 +191,7 @@ struct smk_port_label { | |||
| 191 | */ | 191 | */ |
| 192 | #define MAY_TRANSMUTE 0x00001000 /* Controls directory labeling */ | 192 | #define MAY_TRANSMUTE 0x00001000 /* Controls directory labeling */ |
| 193 | #define MAY_LOCK 0x00002000 /* Locks should be writes, but ... */ | 193 | #define MAY_LOCK 0x00002000 /* Locks should be writes, but ... */ |
| 194 | #define MAY_BRINGUP 0x00004000 /* Report use of this rule */ | ||
| 194 | 195 | ||
| 195 | /* | 196 | /* |
| 196 | * Just to make the common cases easier to deal with | 197 | * Just to make the common cases easier to deal with |
| @@ -200,9 +201,9 @@ struct smk_port_label { | |||
| 200 | #define MAY_NOT 0 | 201 | #define MAY_NOT 0 |
| 201 | 202 | ||
| 202 | /* | 203 | /* |
| 203 | * Number of access types used by Smack (rwxatl) | 204 | * Number of access types used by Smack (rwxatlb) |
| 204 | */ | 205 | */ |
| 205 | #define SMK_NUM_ACCESS_TYPE 6 | 206 | #define SMK_NUM_ACCESS_TYPE 7 |
| 206 | 207 | ||
| 207 | /* SMACK data */ | 208 | /* SMACK data */ |
| 208 | struct smack_audit_data { | 209 | struct smack_audit_data { |
| @@ -226,23 +227,23 @@ struct smk_audit_info { | |||
| 226 | /* | 227 | /* |
| 227 | * These functions are in smack_lsm.c | 228 | * These functions are in smack_lsm.c |
| 228 | */ | 229 | */ |
| 229 | struct inode_smack *new_inode_smack(char *); | 230 | struct inode_smack *new_inode_smack(struct smack_known *); |
| 230 | 231 | ||
| 231 | /* | 232 | /* |
| 232 | * These functions are in smack_access.c | 233 | * These functions are in smack_access.c |
| 233 | */ | 234 | */ |
| 234 | int smk_access_entry(char *, char *, struct list_head *); | 235 | int smk_access_entry(char *, char *, struct list_head *); |
| 235 | int smk_access(struct smack_known *, char *, int, struct smk_audit_info *); | 236 | int smk_access(struct smack_known *, struct smack_known *, |
| 236 | int smk_tskacc(struct task_smack *, char *, u32, struct smk_audit_info *); | 237 | int, struct smk_audit_info *); |
| 237 | int smk_curacc(char *, u32, struct smk_audit_info *); | 238 | int smk_tskacc(struct task_smack *, struct smack_known *, |
| 239 | u32, struct smk_audit_info *); | ||
| 240 | int smk_curacc(struct smack_known *, u32, struct smk_audit_info *); | ||
| 238 | struct smack_known *smack_from_secid(const u32); | 241 | struct smack_known *smack_from_secid(const u32); |
| 239 | char *smk_parse_smack(const char *string, int len); | 242 | char *smk_parse_smack(const char *string, int len); |
| 240 | int smk_netlbl_mls(int, char *, struct netlbl_lsm_secattr *, int); | 243 | int smk_netlbl_mls(int, char *, struct netlbl_lsm_secattr *, int); |
| 241 | char *smk_import(const char *, int); | ||
| 242 | struct smack_known *smk_import_entry(const char *, int); | 244 | struct smack_known *smk_import_entry(const char *, int); |
| 243 | void smk_insert_entry(struct smack_known *skp); | 245 | void smk_insert_entry(struct smack_known *skp); |
| 244 | struct smack_known *smk_find_entry(const char *); | 246 | struct smack_known *smk_find_entry(const char *); |
| 245 | u32 smack_to_secid(const char *); | ||
| 246 | 247 | ||
| 247 | /* | 248 | /* |
| 248 | * Shared data. | 249 | * Shared data. |
| @@ -252,7 +253,7 @@ extern int smack_cipso_mapped; | |||
| 252 | extern struct smack_known *smack_net_ambient; | 253 | extern struct smack_known *smack_net_ambient; |
| 253 | extern struct smack_known *smack_onlycap; | 254 | extern struct smack_known *smack_onlycap; |
| 254 | extern struct smack_known *smack_syslog_label; | 255 | extern struct smack_known *smack_syslog_label; |
| 255 | extern const char *smack_cipso_option; | 256 | extern struct smack_known smack_cipso_option; |
| 256 | extern int smack_ptrace_rule; | 257 | extern int smack_ptrace_rule; |
| 257 | 258 | ||
| 258 | extern struct smack_known smack_known_floor; | 259 | extern struct smack_known smack_known_floor; |
| @@ -281,9 +282,9 @@ static inline int smk_inode_transmutable(const struct inode *isp) | |||
| 281 | } | 282 | } |
| 282 | 283 | ||
| 283 | /* | 284 | /* |
| 284 | * Present a pointer to the smack label in an inode blob. | 285 | * Present a pointer to the smack label entry in an inode blob. |
| 285 | */ | 286 | */ |
| 286 | static inline char *smk_of_inode(const struct inode *isp) | 287 | static inline struct smack_known *smk_of_inode(const struct inode *isp) |
| 287 | { | 288 | { |
| 288 | struct inode_smack *sip = isp->i_security; | 289 | struct inode_smack *sip = isp->i_security; |
| 289 | return sip->smk_inode; | 290 | return sip->smk_inode; |
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c index f97d0842e621..5b970ffde024 100644 --- a/security/smack/smack_access.c +++ b/security/smack/smack_access.c | |||
| @@ -94,7 +94,7 @@ int smk_access_entry(char *subject_label, char *object_label, | |||
| 94 | struct smack_rule *srp; | 94 | struct smack_rule *srp; |
| 95 | 95 | ||
| 96 | list_for_each_entry_rcu(srp, rule_list, list) { | 96 | list_for_each_entry_rcu(srp, rule_list, list) { |
| 97 | if (srp->smk_object == object_label && | 97 | if (srp->smk_object->smk_known == object_label && |
| 98 | srp->smk_subject->smk_known == subject_label) { | 98 | srp->smk_subject->smk_known == subject_label) { |
| 99 | may = srp->smk_access; | 99 | may = srp->smk_access; |
| 100 | break; | 100 | break; |
| @@ -111,8 +111,8 @@ int smk_access_entry(char *subject_label, char *object_label, | |||
| 111 | 111 | ||
| 112 | /** | 112 | /** |
| 113 | * smk_access - determine if a subject has a specific access to an object | 113 | * smk_access - determine if a subject has a specific access to an object |
| 114 | * @subject_known: a pointer to the subject's Smack label entry | 114 | * @subject: a pointer to the subject's Smack label entry |
| 115 | * @object_label: a pointer to the object's Smack label | 115 | * @object: a pointer to the object's Smack label entry |
| 116 | * @request: the access requested, in "MAY" format | 116 | * @request: the access requested, in "MAY" format |
| 117 | * @a : a pointer to the audit data | 117 | * @a : a pointer to the audit data |
| 118 | * | 118 | * |
| @@ -122,8 +122,8 @@ int smk_access_entry(char *subject_label, char *object_label, | |||
| 122 | * | 122 | * |
| 123 | * Smack labels are shared on smack_list | 123 | * Smack labels are shared on smack_list |
| 124 | */ | 124 | */ |
| 125 | int smk_access(struct smack_known *subject_known, char *object_label, | 125 | int smk_access(struct smack_known *subject, struct smack_known *object, |
| 126 | int request, struct smk_audit_info *a) | 126 | int request, struct smk_audit_info *a) |
| 127 | { | 127 | { |
| 128 | int may = MAY_NOT; | 128 | int may = MAY_NOT; |
| 129 | int rc = 0; | 129 | int rc = 0; |
| @@ -133,7 +133,7 @@ int smk_access(struct smack_known *subject_known, char *object_label, | |||
| 133 | * | 133 | * |
| 134 | * A star subject can't access any object. | 134 | * A star subject can't access any object. |
| 135 | */ | 135 | */ |
| 136 | if (subject_known == &smack_known_star) { | 136 | if (subject == &smack_known_star) { |
| 137 | rc = -EACCES; | 137 | rc = -EACCES; |
| 138 | goto out_audit; | 138 | goto out_audit; |
| 139 | } | 139 | } |
| @@ -142,28 +142,28 @@ int smk_access(struct smack_known *subject_known, char *object_label, | |||
| 142 | * Tasks cannot be assigned the internet label. | 142 | * Tasks cannot be assigned the internet label. |
| 143 | * An internet subject can access any object. | 143 | * An internet subject can access any object. |
| 144 | */ | 144 | */ |
| 145 | if (object_label == smack_known_web.smk_known || | 145 | if (object == &smack_known_web || |
| 146 | subject_known == &smack_known_web) | 146 | subject == &smack_known_web) |
| 147 | goto out_audit; | 147 | goto out_audit; |
| 148 | /* | 148 | /* |
| 149 | * A star object can be accessed by any subject. | 149 | * A star object can be accessed by any subject. |
| 150 | */ | 150 | */ |
| 151 | if (object_label == smack_known_star.smk_known) | 151 | if (object == &smack_known_star) |
| 152 | goto out_audit; | 152 | goto out_audit; |
| 153 | /* | 153 | /* |
| 154 | * An object can be accessed in any way by a subject | 154 | * An object can be accessed in any way by a subject |
| 155 | * with the same label. | 155 | * with the same label. |
| 156 | */ | 156 | */ |
| 157 | if (subject_known->smk_known == object_label) | 157 | if (subject->smk_known == object->smk_known) |
| 158 | goto out_audit; | 158 | goto out_audit; |
| 159 | /* | 159 | /* |
| 160 | * A hat subject can read any object. | 160 | * A hat subject can read any object. |
| 161 | * A floor object can be read by any subject. | 161 | * A floor object can be read by any subject. |
| 162 | */ | 162 | */ |
| 163 | if ((request & MAY_ANYREAD) == request) { | 163 | if ((request & MAY_ANYREAD) == request) { |
| 164 | if (object_label == smack_known_floor.smk_known) | 164 | if (object == &smack_known_floor) |
| 165 | goto out_audit; | 165 | goto out_audit; |
| 166 | if (subject_known == &smack_known_hat) | 166 | if (subject == &smack_known_hat) |
| 167 | goto out_audit; | 167 | goto out_audit; |
| 168 | } | 168 | } |
| 169 | /* | 169 | /* |
| @@ -174,27 +174,38 @@ int smk_access(struct smack_known *subject_known, char *object_label, | |||
| 174 | * indicates there is no entry for this pair. | 174 | * indicates there is no entry for this pair. |
| 175 | */ | 175 | */ |
| 176 | rcu_read_lock(); | 176 | rcu_read_lock(); |
| 177 | may = smk_access_entry(subject_known->smk_known, object_label, | 177 | may = smk_access_entry(subject->smk_known, object->smk_known, |
| 178 | &subject_known->smk_rules); | 178 | &subject->smk_rules); |
| 179 | rcu_read_unlock(); | 179 | rcu_read_unlock(); |
| 180 | 180 | ||
| 181 | if (may > 0 && (request & may) == request) | 181 | if (may <= 0 || (request & may) != request) { |
| 182 | rc = -EACCES; | ||
| 182 | goto out_audit; | 183 | goto out_audit; |
| 184 | } | ||
| 185 | #ifdef CONFIG_SECURITY_SMACK_BRINGUP | ||
| 186 | /* | ||
| 187 | * Return a positive value if using bringup mode. | ||
| 188 | * This allows the hooks to identify checks that | ||
| 189 | * succeed because of "b" rules. | ||
| 190 | */ | ||
| 191 | if (may & MAY_BRINGUP) | ||
| 192 | rc = MAY_BRINGUP; | ||
| 193 | #endif | ||
| 183 | 194 | ||
| 184 | rc = -EACCES; | ||
| 185 | out_audit: | 195 | out_audit: |
| 186 | #ifdef CONFIG_AUDIT | 196 | #ifdef CONFIG_AUDIT |
| 187 | if (a) | 197 | if (a) |
| 188 | smack_log(subject_known->smk_known, object_label, request, | 198 | smack_log(subject->smk_known, object->smk_known, |
| 189 | rc, a); | 199 | request, rc, a); |
| 190 | #endif | 200 | #endif |
| 201 | |||
| 191 | return rc; | 202 | return rc; |
| 192 | } | 203 | } |
| 193 | 204 | ||
| 194 | /** | 205 | /** |
| 195 | * smk_tskacc - determine if a task has a specific access to an object | 206 | * smk_tskacc - determine if a task has a specific access to an object |
| 196 | * @tsp: a pointer to the subject task | 207 | * @tsp: a pointer to the subject's task |
| 197 | * @obj_label: a pointer to the object's Smack label | 208 | * @obj_known: a pointer to the object's label entry |
| 198 | * @mode: the access requested, in "MAY" format | 209 | * @mode: the access requested, in "MAY" format |
| 199 | * @a : common audit data | 210 | * @a : common audit data |
| 200 | * | 211 | * |
| @@ -203,24 +214,25 @@ out_audit: | |||
| 203 | * non zero otherwise. It allows that the task may have the capability | 214 | * non zero otherwise. It allows that the task may have the capability |
| 204 | * to override the rules. | 215 | * to override the rules. |
| 205 | */ | 216 | */ |
| 206 | int smk_tskacc(struct task_smack *subject, char *obj_label, | 217 | int smk_tskacc(struct task_smack *tsp, struct smack_known *obj_known, |
| 207 | u32 mode, struct smk_audit_info *a) | 218 | u32 mode, struct smk_audit_info *a) |
| 208 | { | 219 | { |
| 209 | struct smack_known *skp = smk_of_task(subject); | 220 | struct smack_known *sbj_known = smk_of_task(tsp); |
| 210 | int may; | 221 | int may; |
| 211 | int rc; | 222 | int rc; |
| 212 | 223 | ||
| 213 | /* | 224 | /* |
| 214 | * Check the global rule list | 225 | * Check the global rule list |
| 215 | */ | 226 | */ |
| 216 | rc = smk_access(skp, obj_label, mode, NULL); | 227 | rc = smk_access(sbj_known, obj_known, mode, NULL); |
| 217 | if (rc == 0) { | 228 | if (rc >= 0) { |
| 218 | /* | 229 | /* |
| 219 | * If there is an entry in the task's rule list | 230 | * If there is an entry in the task's rule list |
| 220 | * it can further restrict access. | 231 | * it can further restrict access. |
| 221 | */ | 232 | */ |
| 222 | may = smk_access_entry(skp->smk_known, obj_label, | 233 | may = smk_access_entry(sbj_known->smk_known, |
| 223 | &subject->smk_rules); | 234 | obj_known->smk_known, |
| 235 | &tsp->smk_rules); | ||
| 224 | if (may < 0) | 236 | if (may < 0) |
| 225 | goto out_audit; | 237 | goto out_audit; |
| 226 | if ((mode & may) == mode) | 238 | if ((mode & may) == mode) |
| @@ -237,14 +249,15 @@ int smk_tskacc(struct task_smack *subject, char *obj_label, | |||
| 237 | out_audit: | 249 | out_audit: |
| 238 | #ifdef CONFIG_AUDIT | 250 | #ifdef CONFIG_AUDIT |
| 239 | if (a) | 251 | if (a) |
| 240 | smack_log(skp->smk_known, obj_label, mode, rc, a); | 252 | smack_log(sbj_known->smk_known, obj_known->smk_known, |
| 253 | mode, rc, a); | ||
| 241 | #endif | 254 | #endif |
| 242 | return rc; | 255 | return rc; |
| 243 | } | 256 | } |
| 244 | 257 | ||
| 245 | /** | 258 | /** |
| 246 | * smk_curacc - determine if current has a specific access to an object | 259 | * smk_curacc - determine if current has a specific access to an object |
| 247 | * @obj_label: a pointer to the object's Smack label | 260 | * @obj_known: a pointer to the object's Smack label entry |
| 248 | * @mode: the access requested, in "MAY" format | 261 | * @mode: the access requested, in "MAY" format |
| 249 | * @a : common audit data | 262 | * @a : common audit data |
| 250 | * | 263 | * |
| @@ -253,11 +266,12 @@ out_audit: | |||
| 253 | * non zero otherwise. It allows that current may have the capability | 266 | * non zero otherwise. It allows that current may have the capability |
| 254 | * to override the rules. | 267 | * to override the rules. |
| 255 | */ | 268 | */ |
| 256 | int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a) | 269 | int smk_curacc(struct smack_known *obj_known, |
| 270 | u32 mode, struct smk_audit_info *a) | ||
| 257 | { | 271 | { |
| 258 | struct task_smack *tsp = current_security(); | 272 | struct task_smack *tsp = current_security(); |
| 259 | 273 | ||
| 260 | return smk_tskacc(tsp, obj_label, mode, a); | 274 | return smk_tskacc(tsp, obj_known, mode, a); |
| 261 | } | 275 | } |
| 262 | 276 | ||
| 263 | #ifdef CONFIG_AUDIT | 277 | #ifdef CONFIG_AUDIT |
| @@ -328,6 +342,13 @@ void smack_log(char *subject_label, char *object_label, int request, | |||
| 328 | struct smack_audit_data *sad; | 342 | struct smack_audit_data *sad; |
| 329 | struct common_audit_data *a = &ad->a; | 343 | struct common_audit_data *a = &ad->a; |
| 330 | 344 | ||
| 345 | #ifdef CONFIG_SECURITY_SMACK_BRINGUP | ||
| 346 | /* | ||
| 347 | * The result may be positive in bringup mode. | ||
| 348 | */ | ||
| 349 | if (result > 0) | ||
| 350 | result = 0; | ||
| 351 | #endif | ||
| 331 | /* check if we have to log the current event */ | 352 | /* check if we have to log the current event */ |
| 332 | if (result != 0 && (log_policy & SMACK_AUDIT_DENIED) == 0) | 353 | if (result != 0 && (log_policy & SMACK_AUDIT_DENIED) == 0) |
| 333 | return; | 354 | return; |
| @@ -544,27 +565,6 @@ unlockout: | |||
| 544 | } | 565 | } |
| 545 | 566 | ||
| 546 | /** | 567 | /** |
| 547 | * smk_import - import a smack label | ||
| 548 | * @string: a text string that might be a Smack label | ||
| 549 | * @len: the maximum size, or zero if it is NULL terminated. | ||
| 550 | * | ||
| 551 | * Returns a pointer to the label in the label list that | ||
| 552 | * matches the passed string, adding it if necessary. | ||
| 553 | */ | ||
| 554 | char *smk_import(const char *string, int len) | ||
| 555 | { | ||
| 556 | struct smack_known *skp; | ||
| 557 | |||
| 558 | /* labels cannot begin with a '-' */ | ||
| 559 | if (string[0] == '-') | ||
| 560 | return NULL; | ||
| 561 | skp = smk_import_entry(string, len); | ||
| 562 | if (skp == NULL) | ||
| 563 | return NULL; | ||
| 564 | return skp->smk_known; | ||
| 565 | } | ||
| 566 | |||
| 567 | /** | ||
| 568 | * smack_from_secid - find the Smack label associated with a secid | 568 | * smack_from_secid - find the Smack label associated with a secid |
| 569 | * @secid: an integer that might be associated with a Smack label | 569 | * @secid: an integer that might be associated with a Smack label |
| 570 | * | 570 | * |
| @@ -590,19 +590,3 @@ struct smack_known *smack_from_secid(const u32 secid) | |||
| 590 | rcu_read_unlock(); | 590 | rcu_read_unlock(); |
| 591 | return &smack_known_invalid; | 591 | return &smack_known_invalid; |
| 592 | } | 592 | } |
| 593 | |||
| 594 | /** | ||
| 595 | * smack_to_secid - find the secid associated with a Smack label | ||
| 596 | * @smack: the Smack label | ||
| 597 | * | ||
| 598 | * Returns the appropriate secid if there is one, | ||
| 599 | * otherwise 0 | ||
| 600 | */ | ||
| 601 | u32 smack_to_secid(const char *smack) | ||
| 602 | { | ||
| 603 | struct smack_known *skp = smk_find_entry(smack); | ||
| 604 | |||
| 605 | if (skp == NULL) | ||
| 606 | return 0; | ||
| 607 | return skp->smk_secid; | ||
| 608 | } | ||
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index e6ab307ce86e..d515ec25ae9f 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
| @@ -54,6 +54,151 @@ | |||
| 54 | 54 | ||
| 55 | LIST_HEAD(smk_ipv6_port_list); | 55 | LIST_HEAD(smk_ipv6_port_list); |
| 56 | 56 | ||
| 57 | #ifdef CONFIG_SECURITY_SMACK_BRINGUP | ||
| 58 | static void smk_bu_mode(int mode, char *s) | ||
| 59 | { | ||
| 60 | int i = 0; | ||
| 61 | |||
| 62 | if (mode & MAY_READ) | ||
| 63 | s[i++] = 'r'; | ||
| 64 | if (mode & MAY_WRITE) | ||
| 65 | s[i++] = 'w'; | ||
| 66 | if (mode & MAY_EXEC) | ||
| 67 | s[i++] = 'x'; | ||
| 68 | if (mode & MAY_APPEND) | ||
| 69 | s[i++] = 'a'; | ||
| 70 | if (mode & MAY_TRANSMUTE) | ||
| 71 | s[i++] = 't'; | ||
| 72 | if (mode & MAY_LOCK) | ||
| 73 | s[i++] = 'l'; | ||
| 74 | if (i == 0) | ||
| 75 | s[i++] = '-'; | ||
| 76 | s[i] = '\0'; | ||
| 77 | } | ||
| 78 | #endif | ||
| 79 | |||
| 80 | #ifdef CONFIG_SECURITY_SMACK_BRINGUP | ||
| 81 | static int smk_bu_note(char *note, struct smack_known *sskp, | ||
| 82 | struct smack_known *oskp, int mode, int rc) | ||
| 83 | { | ||
| 84 | char acc[SMK_NUM_ACCESS_TYPE + 1]; | ||
| 85 | |||
| 86 | if (rc <= 0) | ||
| 87 | return rc; | ||
| 88 | |||
| 89 | smk_bu_mode(mode, acc); | ||
| 90 | pr_info("Smack Bringup: (%s %s %s) %s\n", | ||
| 91 | sskp->smk_known, oskp->smk_known, acc, note); | ||
| 92 | return 0; | ||
| 93 | } | ||
| 94 | #else | ||
| 95 | #define smk_bu_note(note, sskp, oskp, mode, RC) (RC) | ||
| 96 | #endif | ||
| 97 | |||
| 98 | #ifdef CONFIG_SECURITY_SMACK_BRINGUP | ||
| 99 | static int smk_bu_current(char *note, struct smack_known *oskp, | ||
| 100 | int mode, int rc) | ||
| 101 | { | ||
| 102 | struct task_smack *tsp = current_security(); | ||
| 103 | char acc[SMK_NUM_ACCESS_TYPE + 1]; | ||
| 104 | |||
| 105 | if (rc <= 0) | ||
| 106 | return rc; | ||
| 107 | |||
| 108 | smk_bu_mode(mode, acc); | ||
| 109 | pr_info("Smack Bringup: (%s %s %s) %s %s\n", | ||
| 110 | tsp->smk_task->smk_known, oskp->smk_known, | ||
| 111 | acc, current->comm, note); | ||
| 112 | return 0; | ||
| 113 | } | ||
| 114 | #else | ||
| 115 | #define smk_bu_current(note, oskp, mode, RC) (RC) | ||
| 116 | #endif | ||
| 117 | |||
| 118 | #ifdef CONFIG_SECURITY_SMACK_BRINGUP | ||
| 119 | static int smk_bu_task(struct task_struct *otp, int mode, int rc) | ||
| 120 | { | ||
| 121 | struct task_smack *tsp = current_security(); | ||
| 122 | struct task_smack *otsp = task_security(otp); | ||
| 123 | char acc[SMK_NUM_ACCESS_TYPE + 1]; | ||
| 124 | |||
| 125 | if (rc <= 0) | ||
| 126 | return rc; | ||
| 127 | |||
| 128 | smk_bu_mode(mode, acc); | ||
| 129 | pr_info("Smack Bringup: (%s %s %s) %s to %s\n", | ||
| 130 | tsp->smk_task->smk_known, otsp->smk_task->smk_known, acc, | ||
| 131 | current->comm, otp->comm); | ||
| 132 | return 0; | ||
| 133 | } | ||
| 134 | #else | ||
| 135 | #define smk_bu_task(otp, mode, RC) (RC) | ||
| 136 | #endif | ||
| 137 | |||
| 138 | #ifdef CONFIG_SECURITY_SMACK_BRINGUP | ||
| 139 | static int smk_bu_inode(struct inode *inode, int mode, int rc) | ||
| 140 | { | ||
| 141 | struct task_smack *tsp = current_security(); | ||
| 142 | char acc[SMK_NUM_ACCESS_TYPE + 1]; | ||
| 143 | |||
| 144 | if (rc <= 0) | ||
| 145 | return rc; | ||
| 146 | |||
| 147 | smk_bu_mode(mode, acc); | ||
| 148 | pr_info("Smack Bringup: (%s %s %s) inode=(%s %ld) %s\n", | ||
| 149 | tsp->smk_task->smk_known, smk_of_inode(inode)->smk_known, acc, | ||
| 150 | inode->i_sb->s_id, inode->i_ino, current->comm); | ||
| 151 | return 0; | ||
| 152 | } | ||
| 153 | #else | ||
| 154 | #define smk_bu_inode(inode, mode, RC) (RC) | ||
| 155 | #endif | ||
| 156 | |||
| 157 | #ifdef CONFIG_SECURITY_SMACK_BRINGUP | ||
| 158 | static int smk_bu_file(struct file *file, int mode, int rc) | ||
| 159 | { | ||
| 160 | struct task_smack *tsp = current_security(); | ||
| 161 | struct smack_known *sskp = tsp->smk_task; | ||
| 162 | struct inode *inode = file->f_inode; | ||
| 163 | char acc[SMK_NUM_ACCESS_TYPE + 1]; | ||
| 164 | |||
| 165 | if (rc <= 0) | ||
| 166 | return rc; | ||
| 167 | |||
| 168 | smk_bu_mode(mode, acc); | ||
| 169 | pr_info("Smack Bringup: (%s %s %s) file=(%s %ld %s) %s\n", | ||
| 170 | sskp->smk_known, (char *)file->f_security, acc, | ||
| 171 | inode->i_sb->s_id, inode->i_ino, file->f_dentry->d_name.name, | ||
| 172 | current->comm); | ||
| 173 | return 0; | ||
| 174 | } | ||
| 175 | #else | ||
| 176 | #define smk_bu_file(file, mode, RC) (RC) | ||
| 177 | #endif | ||
| 178 | |||
| 179 | #ifdef CONFIG_SECURITY_SMACK_BRINGUP | ||
| 180 | static int smk_bu_credfile(const struct cred *cred, struct file *file, | ||
| 181 | int mode, int rc) | ||
| 182 | { | ||
| 183 | struct task_smack *tsp = cred->security; | ||
| 184 | struct smack_known *sskp = tsp->smk_task; | ||
| 185 | struct inode *inode = file->f_inode; | ||
| 186 | char acc[SMK_NUM_ACCESS_TYPE + 1]; | ||
| 187 | |||
| 188 | if (rc <= 0) | ||
| 189 | return rc; | ||
| 190 | |||
| 191 | smk_bu_mode(mode, acc); | ||
| 192 | pr_info("Smack Bringup: (%s %s %s) file=(%s %ld %s) %s\n", | ||
| 193 | sskp->smk_known, smk_of_inode(inode)->smk_known, acc, | ||
| 194 | inode->i_sb->s_id, inode->i_ino, file->f_dentry->d_name.name, | ||
| 195 | current->comm); | ||
| 196 | return 0; | ||
| 197 | } | ||
| 198 | #else | ||
| 199 | #define smk_bu_credfile(cred, file, mode, RC) (RC) | ||
| 200 | #endif | ||
| 201 | |||
| 57 | /** | 202 | /** |
| 58 | * smk_fetch - Fetch the smack label from a file. | 203 | * smk_fetch - Fetch the smack label from a file. |
| 59 | * @ip: a pointer to the inode | 204 | * @ip: a pointer to the inode |
| @@ -87,11 +232,11 @@ static struct smack_known *smk_fetch(const char *name, struct inode *ip, | |||
| 87 | 232 | ||
| 88 | /** | 233 | /** |
| 89 | * new_inode_smack - allocate an inode security blob | 234 | * new_inode_smack - allocate an inode security blob |
| 90 | * @smack: a pointer to the Smack label to use in the blob | 235 | * @skp: a pointer to the Smack label entry to use in the blob |
| 91 | * | 236 | * |
| 92 | * Returns the new blob or NULL if there's no memory available | 237 | * Returns the new blob or NULL if there's no memory available |
| 93 | */ | 238 | */ |
| 94 | struct inode_smack *new_inode_smack(char *smack) | 239 | struct inode_smack *new_inode_smack(struct smack_known *skp) |
| 95 | { | 240 | { |
| 96 | struct inode_smack *isp; | 241 | struct inode_smack *isp; |
| 97 | 242 | ||
| @@ -99,7 +244,7 @@ struct inode_smack *new_inode_smack(char *smack) | |||
| 99 | if (isp == NULL) | 244 | if (isp == NULL) |
| 100 | return NULL; | 245 | return NULL; |
| 101 | 246 | ||
| 102 | isp->smk_inode = smack; | 247 | isp->smk_inode = skp; |
| 103 | isp->smk_flags = 0; | 248 | isp->smk_flags = 0; |
| 104 | mutex_init(&isp->smk_lock); | 249 | mutex_init(&isp->smk_lock); |
| 105 | 250 | ||
| @@ -178,20 +323,20 @@ static inline unsigned int smk_ptrace_mode(unsigned int mode) | |||
| 178 | /** | 323 | /** |
| 179 | * smk_ptrace_rule_check - helper for ptrace access | 324 | * smk_ptrace_rule_check - helper for ptrace access |
| 180 | * @tracer: tracer process | 325 | * @tracer: tracer process |
| 181 | * @tracee_label: label of the process that's about to be traced, | 326 | * @tracee_known: label entry of the process that's about to be traced |
| 182 | * the pointer must originate from smack structures | ||
| 183 | * @mode: ptrace attachment mode (PTRACE_MODE_*) | 327 | * @mode: ptrace attachment mode (PTRACE_MODE_*) |
| 184 | * @func: name of the function that called us, used for audit | 328 | * @func: name of the function that called us, used for audit |
| 185 | * | 329 | * |
| 186 | * Returns 0 on access granted, -error on error | 330 | * Returns 0 on access granted, -error on error |
| 187 | */ | 331 | */ |
| 188 | static int smk_ptrace_rule_check(struct task_struct *tracer, char *tracee_label, | 332 | static int smk_ptrace_rule_check(struct task_struct *tracer, |
| 333 | struct smack_known *tracee_known, | ||
| 189 | unsigned int mode, const char *func) | 334 | unsigned int mode, const char *func) |
| 190 | { | 335 | { |
| 191 | int rc; | 336 | int rc; |
| 192 | struct smk_audit_info ad, *saip = NULL; | 337 | struct smk_audit_info ad, *saip = NULL; |
| 193 | struct task_smack *tsp; | 338 | struct task_smack *tsp; |
| 194 | struct smack_known *skp; | 339 | struct smack_known *tracer_known; |
| 195 | 340 | ||
| 196 | if ((mode & PTRACE_MODE_NOAUDIT) == 0) { | 341 | if ((mode & PTRACE_MODE_NOAUDIT) == 0) { |
| 197 | smk_ad_init(&ad, func, LSM_AUDIT_DATA_TASK); | 342 | smk_ad_init(&ad, func, LSM_AUDIT_DATA_TASK); |
| @@ -200,12 +345,12 @@ static int smk_ptrace_rule_check(struct task_struct *tracer, char *tracee_label, | |||
| 200 | } | 345 | } |
| 201 | 346 | ||
| 202 | tsp = task_security(tracer); | 347 | tsp = task_security(tracer); |
| 203 | skp = smk_of_task(tsp); | 348 | tracer_known = smk_of_task(tsp); |
| 204 | 349 | ||
| 205 | if ((mode & PTRACE_MODE_ATTACH) && | 350 | if ((mode & PTRACE_MODE_ATTACH) && |
| 206 | (smack_ptrace_rule == SMACK_PTRACE_EXACT || | 351 | (smack_ptrace_rule == SMACK_PTRACE_EXACT || |
| 207 | smack_ptrace_rule == SMACK_PTRACE_DRACONIAN)) { | 352 | smack_ptrace_rule == SMACK_PTRACE_DRACONIAN)) { |
| 208 | if (skp->smk_known == tracee_label) | 353 | if (tracer_known->smk_known == tracee_known->smk_known) |
| 209 | rc = 0; | 354 | rc = 0; |
| 210 | else if (smack_ptrace_rule == SMACK_PTRACE_DRACONIAN) | 355 | else if (smack_ptrace_rule == SMACK_PTRACE_DRACONIAN) |
| 211 | rc = -EACCES; | 356 | rc = -EACCES; |
| @@ -215,13 +360,15 @@ static int smk_ptrace_rule_check(struct task_struct *tracer, char *tracee_label, | |||
| 215 | rc = -EACCES; | 360 | rc = -EACCES; |
| 216 | 361 | ||
| 217 | if (saip) | 362 | if (saip) |
| 218 | smack_log(skp->smk_known, tracee_label, 0, rc, saip); | 363 | smack_log(tracer_known->smk_known, |
| 364 | tracee_known->smk_known, | ||
| 365 | 0, rc, saip); | ||
| 219 | 366 | ||
| 220 | return rc; | 367 | return rc; |
| 221 | } | 368 | } |
| 222 | 369 | ||
| 223 | /* In case of rule==SMACK_PTRACE_DEFAULT or mode==PTRACE_MODE_READ */ | 370 | /* In case of rule==SMACK_PTRACE_DEFAULT or mode==PTRACE_MODE_READ */ |
| 224 | rc = smk_tskacc(tsp, tracee_label, smk_ptrace_mode(mode), saip); | 371 | rc = smk_tskacc(tsp, tracee_known, smk_ptrace_mode(mode), saip); |
| 225 | return rc; | 372 | return rc; |
| 226 | } | 373 | } |
| 227 | 374 | ||
| @@ -250,7 +397,7 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode) | |||
| 250 | 397 | ||
| 251 | skp = smk_of_task(task_security(ctp)); | 398 | skp = smk_of_task(task_security(ctp)); |
| 252 | 399 | ||
| 253 | rc = smk_ptrace_rule_check(current, skp->smk_known, mode, __func__); | 400 | rc = smk_ptrace_rule_check(current, skp, mode, __func__); |
| 254 | return rc; | 401 | return rc; |
| 255 | } | 402 | } |
| 256 | 403 | ||
| @@ -273,8 +420,7 @@ static int smack_ptrace_traceme(struct task_struct *ptp) | |||
| 273 | 420 | ||
| 274 | skp = smk_of_task(current_security()); | 421 | skp = smk_of_task(current_security()); |
| 275 | 422 | ||
| 276 | rc = smk_ptrace_rule_check(ptp, skp->smk_known, | 423 | rc = smk_ptrace_rule_check(ptp, skp, PTRACE_MODE_ATTACH, __func__); |
| 277 | PTRACE_MODE_ATTACH, __func__); | ||
| 278 | return rc; | 424 | return rc; |
| 279 | } | 425 | } |
| 280 | 426 | ||
| @@ -318,10 +464,10 @@ static int smack_sb_alloc_security(struct super_block *sb) | |||
| 318 | if (sbsp == NULL) | 464 | if (sbsp == NULL) |
| 319 | return -ENOMEM; | 465 | return -ENOMEM; |
| 320 | 466 | ||
| 321 | sbsp->smk_root = smack_known_floor.smk_known; | 467 | sbsp->smk_root = &smack_known_floor; |
| 322 | sbsp->smk_default = smack_known_floor.smk_known; | 468 | sbsp->smk_default = &smack_known_floor; |
| 323 | sbsp->smk_floor = smack_known_floor.smk_known; | 469 | sbsp->smk_floor = &smack_known_floor; |
| 324 | sbsp->smk_hat = smack_known_hat.smk_known; | 470 | sbsp->smk_hat = &smack_known_hat; |
| 325 | /* | 471 | /* |
| 326 | * smk_initialized will be zero from kzalloc. | 472 | * smk_initialized will be zero from kzalloc. |
| 327 | */ | 473 | */ |
| @@ -405,7 +551,6 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) | |||
| 405 | struct smack_known *skp; | 551 | struct smack_known *skp; |
| 406 | char *op; | 552 | char *op; |
| 407 | char *commap; | 553 | char *commap; |
| 408 | char *nsp; | ||
| 409 | int transmute = 0; | 554 | int transmute = 0; |
| 410 | int specified = 0; | 555 | int specified = 0; |
| 411 | 556 | ||
| @@ -421,38 +566,38 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) | |||
| 421 | 566 | ||
| 422 | if (strncmp(op, SMK_FSHAT, strlen(SMK_FSHAT)) == 0) { | 567 | if (strncmp(op, SMK_FSHAT, strlen(SMK_FSHAT)) == 0) { |
| 423 | op += strlen(SMK_FSHAT); | 568 | op += strlen(SMK_FSHAT); |
| 424 | nsp = smk_import(op, 0); | 569 | skp = smk_import_entry(op, 0); |
| 425 | if (nsp != NULL) { | 570 | if (skp != NULL) { |
| 426 | sp->smk_hat = nsp; | 571 | sp->smk_hat = skp; |
| 427 | specified = 1; | 572 | specified = 1; |
| 428 | } | 573 | } |
| 429 | } else if (strncmp(op, SMK_FSFLOOR, strlen(SMK_FSFLOOR)) == 0) { | 574 | } else if (strncmp(op, SMK_FSFLOOR, strlen(SMK_FSFLOOR)) == 0) { |
| 430 | op += strlen(SMK_FSFLOOR); | 575 | op += strlen(SMK_FSFLOOR); |
| 431 | nsp = smk_import(op, 0); | 576 | skp = smk_import_entry(op, 0); |
| 432 | if (nsp != NULL) { | 577 | if (skp != NULL) { |
| 433 | sp->smk_floor = nsp; | 578 | sp->smk_floor = skp; |
| 434 | specified = 1; | 579 | specified = 1; |
| 435 | } | 580 | } |
| 436 | } else if (strncmp(op, SMK_FSDEFAULT, | 581 | } else if (strncmp(op, SMK_FSDEFAULT, |
| 437 | strlen(SMK_FSDEFAULT)) == 0) { | 582 | strlen(SMK_FSDEFAULT)) == 0) { |
| 438 | op += strlen(SMK_FSDEFAULT); | 583 | op += strlen(SMK_FSDEFAULT); |
| 439 | nsp = smk_import(op, 0); | 584 | skp = smk_import_entry(op, 0); |
| 440 | if (nsp != NULL) { | 585 | if (skp != NULL) { |
| 441 | sp->smk_default = nsp; | 586 | sp->smk_default = skp; |
| 442 | specified = 1; | 587 | specified = 1; |
| 443 | } | 588 | } |
| 444 | } else if (strncmp(op, SMK_FSROOT, strlen(SMK_FSROOT)) == 0) { | 589 | } else if (strncmp(op, SMK_FSROOT, strlen(SMK_FSROOT)) == 0) { |
| 445 | op += strlen(SMK_FSROOT); | 590 | op += strlen(SMK_FSROOT); |
| 446 | nsp = smk_import(op, 0); | 591 | skp = smk_import_entry(op, 0); |
| 447 | if (nsp != NULL) { | 592 | if (skp != NULL) { |
| 448 | sp->smk_root = nsp; | 593 | sp->smk_root = skp; |
| 449 | specified = 1; | 594 | specified = 1; |
| 450 | } | 595 | } |
| 451 | } else if (strncmp(op, SMK_FSTRANS, strlen(SMK_FSTRANS)) == 0) { | 596 | } else if (strncmp(op, SMK_FSTRANS, strlen(SMK_FSTRANS)) == 0) { |
| 452 | op += strlen(SMK_FSTRANS); | 597 | op += strlen(SMK_FSTRANS); |
| 453 | nsp = smk_import(op, 0); | 598 | skp = smk_import_entry(op, 0); |
| 454 | if (nsp != NULL) { | 599 | if (skp != NULL) { |
| 455 | sp->smk_root = nsp; | 600 | sp->smk_root = skp; |
| 456 | transmute = 1; | 601 | transmute = 1; |
| 457 | specified = 1; | 602 | specified = 1; |
| 458 | } | 603 | } |
| @@ -469,8 +614,8 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) | |||
| 469 | * Unprivileged mounts get root and default from the caller. | 614 | * Unprivileged mounts get root and default from the caller. |
| 470 | */ | 615 | */ |
| 471 | skp = smk_of_current(); | 616 | skp = smk_of_current(); |
| 472 | sp->smk_root = skp->smk_known; | 617 | sp->smk_root = skp; |
| 473 | sp->smk_default = skp->smk_known; | 618 | sp->smk_default = skp; |
| 474 | } | 619 | } |
| 475 | /* | 620 | /* |
| 476 | * Initialize the root inode. | 621 | * Initialize the root inode. |
| @@ -507,6 +652,7 @@ static int smack_sb_statfs(struct dentry *dentry) | |||
| 507 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); | 652 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); |
| 508 | 653 | ||
| 509 | rc = smk_curacc(sbp->smk_floor, MAY_READ, &ad); | 654 | rc = smk_curacc(sbp->smk_floor, MAY_READ, &ad); |
| 655 | rc = smk_bu_current("statfs", sbp->smk_floor, MAY_READ, rc); | ||
| 510 | return rc; | 656 | return rc; |
| 511 | } | 657 | } |
| 512 | 658 | ||
| @@ -546,7 +692,7 @@ static int smack_bprm_set_creds(struct linux_binprm *bprm) | |||
| 546 | tracer = ptrace_parent(current); | 692 | tracer = ptrace_parent(current); |
| 547 | if (likely(tracer != NULL)) | 693 | if (likely(tracer != NULL)) |
| 548 | rc = smk_ptrace_rule_check(tracer, | 694 | rc = smk_ptrace_rule_check(tracer, |
| 549 | isp->smk_task->smk_known, | 695 | isp->smk_task, |
| 550 | PTRACE_MODE_ATTACH, | 696 | PTRACE_MODE_ATTACH, |
| 551 | __func__); | 697 | __func__); |
| 552 | rcu_read_unlock(); | 698 | rcu_read_unlock(); |
| @@ -607,7 +753,7 @@ static int smack_inode_alloc_security(struct inode *inode) | |||
| 607 | { | 753 | { |
| 608 | struct smack_known *skp = smk_of_current(); | 754 | struct smack_known *skp = smk_of_current(); |
| 609 | 755 | ||
| 610 | inode->i_security = new_inode_smack(skp->smk_known); | 756 | inode->i_security = new_inode_smack(skp); |
| 611 | if (inode->i_security == NULL) | 757 | if (inode->i_security == NULL) |
| 612 | return -ENOMEM; | 758 | return -ENOMEM; |
| 613 | return 0; | 759 | return 0; |
| @@ -627,8 +773,8 @@ static void smack_inode_free_security(struct inode *inode) | |||
| 627 | 773 | ||
| 628 | /** | 774 | /** |
| 629 | * smack_inode_init_security - copy out the smack from an inode | 775 | * smack_inode_init_security - copy out the smack from an inode |
| 630 | * @inode: the inode | 776 | * @inode: the newly created inode |
| 631 | * @dir: unused | 777 | * @dir: containing directory object |
| 632 | * @qstr: unused | 778 | * @qstr: unused |
| 633 | * @name: where to put the attribute name | 779 | * @name: where to put the attribute name |
| 634 | * @value: where to put the attribute value | 780 | * @value: where to put the attribute value |
| @@ -642,8 +788,8 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, | |||
| 642 | { | 788 | { |
| 643 | struct inode_smack *issp = inode->i_security; | 789 | struct inode_smack *issp = inode->i_security; |
| 644 | struct smack_known *skp = smk_of_current(); | 790 | struct smack_known *skp = smk_of_current(); |
| 645 | char *isp = smk_of_inode(inode); | 791 | struct smack_known *isp = smk_of_inode(inode); |
| 646 | char *dsp = smk_of_inode(dir); | 792 | struct smack_known *dsp = smk_of_inode(dir); |
| 647 | int may; | 793 | int may; |
| 648 | 794 | ||
| 649 | if (name) | 795 | if (name) |
| @@ -651,7 +797,8 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, | |||
| 651 | 797 | ||
| 652 | if (value) { | 798 | if (value) { |
| 653 | rcu_read_lock(); | 799 | rcu_read_lock(); |
| 654 | may = smk_access_entry(skp->smk_known, dsp, &skp->smk_rules); | 800 | may = smk_access_entry(skp->smk_known, dsp->smk_known, |
| 801 | &skp->smk_rules); | ||
| 655 | rcu_read_unlock(); | 802 | rcu_read_unlock(); |
| 656 | 803 | ||
| 657 | /* | 804 | /* |
| @@ -666,13 +813,13 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, | |||
| 666 | issp->smk_flags |= SMK_INODE_CHANGED; | 813 | issp->smk_flags |= SMK_INODE_CHANGED; |
| 667 | } | 814 | } |
| 668 | 815 | ||
| 669 | *value = kstrdup(isp, GFP_NOFS); | 816 | *value = kstrdup(isp->smk_known, GFP_NOFS); |
| 670 | if (*value == NULL) | 817 | if (*value == NULL) |
| 671 | return -ENOMEM; | 818 | return -ENOMEM; |
| 672 | } | 819 | } |
| 673 | 820 | ||
| 674 | if (len) | 821 | if (len) |
| 675 | *len = strlen(isp) + 1; | 822 | *len = strlen(isp->smk_known); |
| 676 | 823 | ||
| 677 | return 0; | 824 | return 0; |
| 678 | } | 825 | } |
| @@ -688,7 +835,7 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, | |||
| 688 | static int smack_inode_link(struct dentry *old_dentry, struct inode *dir, | 835 | static int smack_inode_link(struct dentry *old_dentry, struct inode *dir, |
| 689 | struct dentry *new_dentry) | 836 | struct dentry *new_dentry) |
| 690 | { | 837 | { |
| 691 | char *isp; | 838 | struct smack_known *isp; |
| 692 | struct smk_audit_info ad; | 839 | struct smk_audit_info ad; |
| 693 | int rc; | 840 | int rc; |
| 694 | 841 | ||
| @@ -697,11 +844,13 @@ static int smack_inode_link(struct dentry *old_dentry, struct inode *dir, | |||
| 697 | 844 | ||
| 698 | isp = smk_of_inode(old_dentry->d_inode); | 845 | isp = smk_of_inode(old_dentry->d_inode); |
| 699 | rc = smk_curacc(isp, MAY_WRITE, &ad); | 846 | rc = smk_curacc(isp, MAY_WRITE, &ad); |
| 847 | rc = smk_bu_inode(old_dentry->d_inode, MAY_WRITE, rc); | ||
| 700 | 848 | ||
| 701 | if (rc == 0 && new_dentry->d_inode != NULL) { | 849 | if (rc == 0 && new_dentry->d_inode != NULL) { |
| 702 | isp = smk_of_inode(new_dentry->d_inode); | 850 | isp = smk_of_inode(new_dentry->d_inode); |
| 703 | smk_ad_setfield_u_fs_path_dentry(&ad, new_dentry); | 851 | smk_ad_setfield_u_fs_path_dentry(&ad, new_dentry); |
| 704 | rc = smk_curacc(isp, MAY_WRITE, &ad); | 852 | rc = smk_curacc(isp, MAY_WRITE, &ad); |
| 853 | rc = smk_bu_inode(new_dentry->d_inode, MAY_WRITE, rc); | ||
| 705 | } | 854 | } |
| 706 | 855 | ||
| 707 | return rc; | 856 | return rc; |
| @@ -728,6 +877,7 @@ static int smack_inode_unlink(struct inode *dir, struct dentry *dentry) | |||
| 728 | * You need write access to the thing you're unlinking | 877 | * You need write access to the thing you're unlinking |
| 729 | */ | 878 | */ |
| 730 | rc = smk_curacc(smk_of_inode(ip), MAY_WRITE, &ad); | 879 | rc = smk_curacc(smk_of_inode(ip), MAY_WRITE, &ad); |
| 880 | rc = smk_bu_inode(ip, MAY_WRITE, rc); | ||
| 731 | if (rc == 0) { | 881 | if (rc == 0) { |
| 732 | /* | 882 | /* |
| 733 | * You also need write access to the containing directory | 883 | * You also need write access to the containing directory |
| @@ -735,6 +885,7 @@ static int smack_inode_unlink(struct inode *dir, struct dentry *dentry) | |||
| 735 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_INODE); | 885 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_INODE); |
| 736 | smk_ad_setfield_u_fs_inode(&ad, dir); | 886 | smk_ad_setfield_u_fs_inode(&ad, dir); |
| 737 | rc = smk_curacc(smk_of_inode(dir), MAY_WRITE, &ad); | 887 | rc = smk_curacc(smk_of_inode(dir), MAY_WRITE, &ad); |
| 888 | rc = smk_bu_inode(dir, MAY_WRITE, rc); | ||
| 738 | } | 889 | } |
| 739 | return rc; | 890 | return rc; |
| 740 | } | 891 | } |
| @@ -759,6 +910,7 @@ static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry) | |||
| 759 | * You need write access to the thing you're removing | 910 | * You need write access to the thing you're removing |
| 760 | */ | 911 | */ |
| 761 | rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad); | 912 | rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad); |
| 913 | rc = smk_bu_inode(dentry->d_inode, MAY_WRITE, rc); | ||
| 762 | if (rc == 0) { | 914 | if (rc == 0) { |
| 763 | /* | 915 | /* |
| 764 | * You also need write access to the containing directory | 916 | * You also need write access to the containing directory |
| @@ -766,6 +918,7 @@ static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry) | |||
| 766 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_INODE); | 918 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_INODE); |
| 767 | smk_ad_setfield_u_fs_inode(&ad, dir); | 919 | smk_ad_setfield_u_fs_inode(&ad, dir); |
| 768 | rc = smk_curacc(smk_of_inode(dir), MAY_WRITE, &ad); | 920 | rc = smk_curacc(smk_of_inode(dir), MAY_WRITE, &ad); |
| 921 | rc = smk_bu_inode(dir, MAY_WRITE, rc); | ||
| 769 | } | 922 | } |
| 770 | 923 | ||
| 771 | return rc; | 924 | return rc; |
| @@ -773,10 +926,10 @@ static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry) | |||
| 773 | 926 | ||
| 774 | /** | 927 | /** |
| 775 | * smack_inode_rename - Smack check on rename | 928 | * smack_inode_rename - Smack check on rename |
| 776 | * @old_inode: the old directory | 929 | * @old_inode: unused |
| 777 | * @old_dentry: unused | 930 | * @old_dentry: the old object |
| 778 | * @new_inode: the new directory | 931 | * @new_inode: unused |
| 779 | * @new_dentry: unused | 932 | * @new_dentry: the new object |
| 780 | * | 933 | * |
| 781 | * Read and write access is required on both the old and | 934 | * Read and write access is required on both the old and |
| 782 | * new directories. | 935 | * new directories. |
| @@ -789,7 +942,7 @@ static int smack_inode_rename(struct inode *old_inode, | |||
| 789 | struct dentry *new_dentry) | 942 | struct dentry *new_dentry) |
| 790 | { | 943 | { |
| 791 | int rc; | 944 | int rc; |
| 792 | char *isp; | 945 | struct smack_known *isp; |
| 793 | struct smk_audit_info ad; | 946 | struct smk_audit_info ad; |
| 794 | 947 | ||
| 795 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); | 948 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); |
| @@ -797,11 +950,13 @@ static int smack_inode_rename(struct inode *old_inode, | |||
| 797 | 950 | ||
| 798 | isp = smk_of_inode(old_dentry->d_inode); | 951 | isp = smk_of_inode(old_dentry->d_inode); |
| 799 | rc = smk_curacc(isp, MAY_READWRITE, &ad); | 952 | rc = smk_curacc(isp, MAY_READWRITE, &ad); |
| 953 | rc = smk_bu_inode(old_dentry->d_inode, MAY_READWRITE, rc); | ||
| 800 | 954 | ||
| 801 | if (rc == 0 && new_dentry->d_inode != NULL) { | 955 | if (rc == 0 && new_dentry->d_inode != NULL) { |
| 802 | isp = smk_of_inode(new_dentry->d_inode); | 956 | isp = smk_of_inode(new_dentry->d_inode); |
| 803 | smk_ad_setfield_u_fs_path_dentry(&ad, new_dentry); | 957 | smk_ad_setfield_u_fs_path_dentry(&ad, new_dentry); |
| 804 | rc = smk_curacc(isp, MAY_READWRITE, &ad); | 958 | rc = smk_curacc(isp, MAY_READWRITE, &ad); |
| 959 | rc = smk_bu_inode(new_dentry->d_inode, MAY_READWRITE, rc); | ||
| 805 | } | 960 | } |
| 806 | return rc; | 961 | return rc; |
| 807 | } | 962 | } |
| @@ -819,6 +974,7 @@ static int smack_inode_permission(struct inode *inode, int mask) | |||
| 819 | { | 974 | { |
| 820 | struct smk_audit_info ad; | 975 | struct smk_audit_info ad; |
| 821 | int no_block = mask & MAY_NOT_BLOCK; | 976 | int no_block = mask & MAY_NOT_BLOCK; |
| 977 | int rc; | ||
| 822 | 978 | ||
| 823 | mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND); | 979 | mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND); |
| 824 | /* | 980 | /* |
| @@ -832,7 +988,9 @@ static int smack_inode_permission(struct inode *inode, int mask) | |||
| 832 | return -ECHILD; | 988 | return -ECHILD; |
| 833 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_INODE); | 989 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_INODE); |
| 834 | smk_ad_setfield_u_fs_inode(&ad, inode); | 990 | smk_ad_setfield_u_fs_inode(&ad, inode); |
| 835 | return smk_curacc(smk_of_inode(inode), mask, &ad); | 991 | rc = smk_curacc(smk_of_inode(inode), mask, &ad); |
| 992 | rc = smk_bu_inode(inode, mask, rc); | ||
| 993 | return rc; | ||
| 836 | } | 994 | } |
| 837 | 995 | ||
| 838 | /** | 996 | /** |
| @@ -845,6 +1003,8 @@ static int smack_inode_permission(struct inode *inode, int mask) | |||
| 845 | static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr) | 1003 | static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr) |
| 846 | { | 1004 | { |
| 847 | struct smk_audit_info ad; | 1005 | struct smk_audit_info ad; |
| 1006 | int rc; | ||
| 1007 | |||
| 848 | /* | 1008 | /* |
| 849 | * Need to allow for clearing the setuid bit. | 1009 | * Need to allow for clearing the setuid bit. |
| 850 | */ | 1010 | */ |
| @@ -853,12 +1013,14 @@ static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr) | |||
| 853 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); | 1013 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); |
| 854 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); | 1014 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); |
| 855 | 1015 | ||
| 856 | return smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad); | 1016 | rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad); |
| 1017 | rc = smk_bu_inode(dentry->d_inode, MAY_WRITE, rc); | ||
| 1018 | return rc; | ||
| 857 | } | 1019 | } |
| 858 | 1020 | ||
| 859 | /** | 1021 | /** |
| 860 | * smack_inode_getattr - Smack check for getting attributes | 1022 | * smack_inode_getattr - Smack check for getting attributes |
| 861 | * @mnt: unused | 1023 | * @mnt: vfsmount of the object |
| 862 | * @dentry: the object | 1024 | * @dentry: the object |
| 863 | * | 1025 | * |
| 864 | * Returns 0 if access is permitted, an error code otherwise | 1026 | * Returns 0 if access is permitted, an error code otherwise |
| @@ -867,21 +1029,24 @@ static int smack_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) | |||
| 867 | { | 1029 | { |
| 868 | struct smk_audit_info ad; | 1030 | struct smk_audit_info ad; |
| 869 | struct path path; | 1031 | struct path path; |
| 1032 | int rc; | ||
| 870 | 1033 | ||
| 871 | path.dentry = dentry; | 1034 | path.dentry = dentry; |
| 872 | path.mnt = mnt; | 1035 | path.mnt = mnt; |
| 873 | 1036 | ||
| 874 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); | 1037 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); |
| 875 | smk_ad_setfield_u_fs_path(&ad, path); | 1038 | smk_ad_setfield_u_fs_path(&ad, path); |
| 876 | return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad); | 1039 | rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad); |
| 1040 | rc = smk_bu_inode(dentry->d_inode, MAY_READ, rc); | ||
| 1041 | return rc; | ||
| 877 | } | 1042 | } |
| 878 | 1043 | ||
| 879 | /** | 1044 | /** |
| 880 | * smack_inode_setxattr - Smack check for setting xattrs | 1045 | * smack_inode_setxattr - Smack check for setting xattrs |
| 881 | * @dentry: the object | 1046 | * @dentry: the object |
| 882 | * @name: name of the attribute | 1047 | * @name: name of the attribute |
| 883 | * @value: unused | 1048 | * @value: value of the attribute |
| 884 | * @size: unused | 1049 | * @size: size of the value |
| 885 | * @flags: unused | 1050 | * @flags: unused |
| 886 | * | 1051 | * |
| 887 | * This protects the Smack attribute explicitly. | 1052 | * This protects the Smack attribute explicitly. |
| @@ -923,7 +1088,7 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name, | |||
| 923 | rc = -EPERM; | 1088 | rc = -EPERM; |
| 924 | 1089 | ||
| 925 | if (rc == 0 && check_import) { | 1090 | if (rc == 0 && check_import) { |
| 926 | skp = smk_import_entry(value, size); | 1091 | skp = size ? smk_import_entry(value, size) : NULL; |
| 927 | if (skp == NULL || (check_star && | 1092 | if (skp == NULL || (check_star && |
| 928 | (skp == &smack_known_star || skp == &smack_known_web))) | 1093 | (skp == &smack_known_star || skp == &smack_known_web))) |
| 929 | rc = -EINVAL; | 1094 | rc = -EINVAL; |
| @@ -932,8 +1097,10 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name, | |||
| 932 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); | 1097 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); |
| 933 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); | 1098 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); |
| 934 | 1099 | ||
| 935 | if (rc == 0) | 1100 | if (rc == 0) { |
| 936 | rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad); | 1101 | rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad); |
| 1102 | rc = smk_bu_inode(dentry->d_inode, MAY_WRITE, rc); | ||
| 1103 | } | ||
| 937 | 1104 | ||
| 938 | return rc; | 1105 | return rc; |
| 939 | } | 1106 | } |
| @@ -963,9 +1130,9 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name, | |||
| 963 | if (strcmp(name, XATTR_NAME_SMACK) == 0) { | 1130 | if (strcmp(name, XATTR_NAME_SMACK) == 0) { |
| 964 | skp = smk_import_entry(value, size); | 1131 | skp = smk_import_entry(value, size); |
| 965 | if (skp != NULL) | 1132 | if (skp != NULL) |
| 966 | isp->smk_inode = skp->smk_known; | 1133 | isp->smk_inode = skp; |
| 967 | else | 1134 | else |
| 968 | isp->smk_inode = smack_known_invalid.smk_known; | 1135 | isp->smk_inode = &smack_known_invalid; |
| 969 | } else if (strcmp(name, XATTR_NAME_SMACKEXEC) == 0) { | 1136 | } else if (strcmp(name, XATTR_NAME_SMACKEXEC) == 0) { |
| 970 | skp = smk_import_entry(value, size); | 1137 | skp = smk_import_entry(value, size); |
| 971 | if (skp != NULL) | 1138 | if (skp != NULL) |
| @@ -993,11 +1160,14 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name, | |||
| 993 | static int smack_inode_getxattr(struct dentry *dentry, const char *name) | 1160 | static int smack_inode_getxattr(struct dentry *dentry, const char *name) |
| 994 | { | 1161 | { |
| 995 | struct smk_audit_info ad; | 1162 | struct smk_audit_info ad; |
| 1163 | int rc; | ||
| 996 | 1164 | ||
| 997 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); | 1165 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); |
| 998 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); | 1166 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); |
| 999 | 1167 | ||
| 1000 | return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad); | 1168 | rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad); |
| 1169 | rc = smk_bu_inode(dentry->d_inode, MAY_READ, rc); | ||
| 1170 | return rc; | ||
| 1001 | } | 1171 | } |
| 1002 | 1172 | ||
| 1003 | /** | 1173 | /** |
| @@ -1033,6 +1203,7 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name) | |||
| 1033 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); | 1203 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); |
| 1034 | 1204 | ||
| 1035 | rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad); | 1205 | rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad); |
| 1206 | rc = smk_bu_inode(dentry->d_inode, MAY_WRITE, rc); | ||
| 1036 | if (rc != 0) | 1207 | if (rc != 0) |
| 1037 | return rc; | 1208 | return rc; |
| 1038 | 1209 | ||
| @@ -1070,14 +1241,14 @@ static int smack_inode_getsecurity(const struct inode *inode, | |||
| 1070 | struct socket *sock; | 1241 | struct socket *sock; |
| 1071 | struct super_block *sbp; | 1242 | struct super_block *sbp; |
| 1072 | struct inode *ip = (struct inode *)inode; | 1243 | struct inode *ip = (struct inode *)inode; |
| 1073 | char *isp; | 1244 | struct smack_known *isp; |
| 1074 | int ilen; | 1245 | int ilen; |
| 1075 | int rc = 0; | 1246 | int rc = 0; |
| 1076 | 1247 | ||
| 1077 | if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) { | 1248 | if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) { |
| 1078 | isp = smk_of_inode(inode); | 1249 | isp = smk_of_inode(inode); |
| 1079 | ilen = strlen(isp) + 1; | 1250 | ilen = strlen(isp->smk_known); |
| 1080 | *buffer = isp; | 1251 | *buffer = isp->smk_known; |
| 1081 | return ilen; | 1252 | return ilen; |
| 1082 | } | 1253 | } |
| 1083 | 1254 | ||
| @@ -1095,15 +1266,15 @@ static int smack_inode_getsecurity(const struct inode *inode, | |||
| 1095 | ssp = sock->sk->sk_security; | 1266 | ssp = sock->sk->sk_security; |
| 1096 | 1267 | ||
| 1097 | if (strcmp(name, XATTR_SMACK_IPIN) == 0) | 1268 | if (strcmp(name, XATTR_SMACK_IPIN) == 0) |
| 1098 | isp = ssp->smk_in->smk_known; | 1269 | isp = ssp->smk_in; |
| 1099 | else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) | 1270 | else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) |
| 1100 | isp = ssp->smk_out->smk_known; | 1271 | isp = ssp->smk_out; |
| 1101 | else | 1272 | else |
| 1102 | return -EOPNOTSUPP; | 1273 | return -EOPNOTSUPP; |
| 1103 | 1274 | ||
| 1104 | ilen = strlen(isp) + 1; | 1275 | ilen = strlen(isp->smk_known); |
| 1105 | if (rc == 0) { | 1276 | if (rc == 0) { |
| 1106 | *buffer = isp; | 1277 | *buffer = isp->smk_known; |
| 1107 | rc = ilen; | 1278 | rc = ilen; |
| 1108 | } | 1279 | } |
| 1109 | 1280 | ||
| @@ -1122,13 +1293,12 @@ static int smack_inode_getsecurity(const struct inode *inode, | |||
| 1122 | static int smack_inode_listsecurity(struct inode *inode, char *buffer, | 1293 | static int smack_inode_listsecurity(struct inode *inode, char *buffer, |
| 1123 | size_t buffer_size) | 1294 | size_t buffer_size) |
| 1124 | { | 1295 | { |
| 1125 | int len = strlen(XATTR_NAME_SMACK); | 1296 | int len = sizeof(XATTR_NAME_SMACK); |
| 1126 | 1297 | ||
| 1127 | if (buffer != NULL && len <= buffer_size) { | 1298 | if (buffer != NULL && len <= buffer_size) |
| 1128 | memcpy(buffer, XATTR_NAME_SMACK, len); | 1299 | memcpy(buffer, XATTR_NAME_SMACK, len); |
| 1129 | return len; | 1300 | |
| 1130 | } | 1301 | return len; |
| 1131 | return -EINVAL; | ||
| 1132 | } | 1302 | } |
| 1133 | 1303 | ||
| 1134 | /** | 1304 | /** |
| @@ -1140,7 +1310,7 @@ static void smack_inode_getsecid(const struct inode *inode, u32 *secid) | |||
| 1140 | { | 1310 | { |
| 1141 | struct inode_smack *isp = inode->i_security; | 1311 | struct inode_smack *isp = inode->i_security; |
| 1142 | 1312 | ||
| 1143 | *secid = smack_to_secid(isp->smk_inode); | 1313 | *secid = isp->smk_inode->smk_secid; |
| 1144 | } | 1314 | } |
| 1145 | 1315 | ||
| 1146 | /* | 1316 | /* |
| @@ -1179,7 +1349,7 @@ static int smack_file_alloc_security(struct file *file) | |||
| 1179 | { | 1349 | { |
| 1180 | struct smack_known *skp = smk_of_current(); | 1350 | struct smack_known *skp = smk_of_current(); |
| 1181 | 1351 | ||
| 1182 | file->f_security = skp->smk_known; | 1352 | file->f_security = skp; |
| 1183 | return 0; | 1353 | return 0; |
| 1184 | } | 1354 | } |
| 1185 | 1355 | ||
| @@ -1214,11 +1384,15 @@ static int smack_file_ioctl(struct file *file, unsigned int cmd, | |||
| 1214 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); | 1384 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); |
| 1215 | smk_ad_setfield_u_fs_path(&ad, file->f_path); | 1385 | smk_ad_setfield_u_fs_path(&ad, file->f_path); |
| 1216 | 1386 | ||
| 1217 | if (_IOC_DIR(cmd) & _IOC_WRITE) | 1387 | if (_IOC_DIR(cmd) & _IOC_WRITE) { |
| 1218 | rc = smk_curacc(file->f_security, MAY_WRITE, &ad); | 1388 | rc = smk_curacc(file->f_security, MAY_WRITE, &ad); |
| 1389 | rc = smk_bu_file(file, MAY_WRITE, rc); | ||
| 1390 | } | ||
| 1219 | 1391 | ||
| 1220 | if (rc == 0 && (_IOC_DIR(cmd) & _IOC_READ)) | 1392 | if (rc == 0 && (_IOC_DIR(cmd) & _IOC_READ)) { |
| 1221 | rc = smk_curacc(file->f_security, MAY_READ, &ad); | 1393 | rc = smk_curacc(file->f_security, MAY_READ, &ad); |
| 1394 | rc = smk_bu_file(file, MAY_READ, rc); | ||
| 1395 | } | ||
| 1222 | 1396 | ||
| 1223 | return rc; | 1397 | return rc; |
| 1224 | } | 1398 | } |
| @@ -1233,10 +1407,13 @@ static int smack_file_ioctl(struct file *file, unsigned int cmd, | |||
| 1233 | static int smack_file_lock(struct file *file, unsigned int cmd) | 1407 | static int smack_file_lock(struct file *file, unsigned int cmd) |
| 1234 | { | 1408 | { |
| 1235 | struct smk_audit_info ad; | 1409 | struct smk_audit_info ad; |
| 1410 | int rc; | ||
| 1236 | 1411 | ||
| 1237 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); | 1412 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); |
| 1238 | smk_ad_setfield_u_fs_path(&ad, file->f_path); | 1413 | smk_ad_setfield_u_fs_path(&ad, file->f_path); |
| 1239 | return smk_curacc(file->f_security, MAY_LOCK, &ad); | 1414 | rc = smk_curacc(file->f_security, MAY_LOCK, &ad); |
| 1415 | rc = smk_bu_file(file, MAY_LOCK, rc); | ||
| 1416 | return rc; | ||
| 1240 | } | 1417 | } |
| 1241 | 1418 | ||
| 1242 | /** | 1419 | /** |
| @@ -1266,12 +1443,14 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd, | |||
| 1266 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); | 1443 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); |
| 1267 | smk_ad_setfield_u_fs_path(&ad, file->f_path); | 1444 | smk_ad_setfield_u_fs_path(&ad, file->f_path); |
| 1268 | rc = smk_curacc(file->f_security, MAY_LOCK, &ad); | 1445 | rc = smk_curacc(file->f_security, MAY_LOCK, &ad); |
| 1446 | rc = smk_bu_file(file, MAY_LOCK, rc); | ||
| 1269 | break; | 1447 | break; |
| 1270 | case F_SETOWN: | 1448 | case F_SETOWN: |
| 1271 | case F_SETSIG: | 1449 | case F_SETSIG: |
| 1272 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); | 1450 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); |
| 1273 | smk_ad_setfield_u_fs_path(&ad, file->f_path); | 1451 | smk_ad_setfield_u_fs_path(&ad, file->f_path); |
| 1274 | rc = smk_curacc(file->f_security, MAY_WRITE, &ad); | 1452 | rc = smk_curacc(file->f_security, MAY_WRITE, &ad); |
| 1453 | rc = smk_bu_file(file, MAY_WRITE, rc); | ||
| 1275 | break; | 1454 | break; |
| 1276 | default: | 1455 | default: |
| 1277 | break; | 1456 | break; |
| @@ -1298,7 +1477,7 @@ static int smack_mmap_file(struct file *file, | |||
| 1298 | struct smack_known *mkp; | 1477 | struct smack_known *mkp; |
| 1299 | struct smack_rule *srp; | 1478 | struct smack_rule *srp; |
| 1300 | struct task_smack *tsp; | 1479 | struct task_smack *tsp; |
| 1301 | char *osmack; | 1480 | struct smack_known *okp; |
| 1302 | struct inode_smack *isp; | 1481 | struct inode_smack *isp; |
| 1303 | int may; | 1482 | int may; |
| 1304 | int mmay; | 1483 | int mmay; |
| @@ -1324,18 +1503,19 @@ static int smack_mmap_file(struct file *file, | |||
| 1324 | * to that rule's object label. | 1503 | * to that rule's object label. |
| 1325 | */ | 1504 | */ |
| 1326 | list_for_each_entry_rcu(srp, &skp->smk_rules, list) { | 1505 | list_for_each_entry_rcu(srp, &skp->smk_rules, list) { |
| 1327 | osmack = srp->smk_object; | 1506 | okp = srp->smk_object; |
| 1328 | /* | 1507 | /* |
| 1329 | * Matching labels always allows access. | 1508 | * Matching labels always allows access. |
| 1330 | */ | 1509 | */ |
| 1331 | if (mkp->smk_known == osmack) | 1510 | if (mkp->smk_known == okp->smk_known) |
| 1332 | continue; | 1511 | continue; |
| 1333 | /* | 1512 | /* |
| 1334 | * If there is a matching local rule take | 1513 | * If there is a matching local rule take |
| 1335 | * that into account as well. | 1514 | * that into account as well. |
| 1336 | */ | 1515 | */ |
| 1337 | may = smk_access_entry(srp->smk_subject->smk_known, osmack, | 1516 | may = smk_access_entry(srp->smk_subject->smk_known, |
| 1338 | &tsp->smk_rules); | 1517 | okp->smk_known, |
| 1518 | &tsp->smk_rules); | ||
| 1339 | if (may == -ENOENT) | 1519 | if (may == -ENOENT) |
| 1340 | may = srp->smk_access; | 1520 | may = srp->smk_access; |
| 1341 | else | 1521 | else |
| @@ -1352,8 +1532,8 @@ static int smack_mmap_file(struct file *file, | |||
| 1352 | * If there isn't one a SMACK64MMAP subject | 1532 | * If there isn't one a SMACK64MMAP subject |
| 1353 | * can't have as much access as current. | 1533 | * can't have as much access as current. |
| 1354 | */ | 1534 | */ |
| 1355 | mmay = smk_access_entry(mkp->smk_known, osmack, | 1535 | mmay = smk_access_entry(mkp->smk_known, okp->smk_known, |
| 1356 | &mkp->smk_rules); | 1536 | &mkp->smk_rules); |
| 1357 | if (mmay == -ENOENT) { | 1537 | if (mmay == -ENOENT) { |
| 1358 | rc = -EACCES; | 1538 | rc = -EACCES; |
| 1359 | break; | 1539 | break; |
| @@ -1362,8 +1542,8 @@ static int smack_mmap_file(struct file *file, | |||
| 1362 | * If there is a local entry it modifies the | 1542 | * If there is a local entry it modifies the |
| 1363 | * potential access, too. | 1543 | * potential access, too. |
| 1364 | */ | 1544 | */ |
| 1365 | tmay = smk_access_entry(mkp->smk_known, osmack, | 1545 | tmay = smk_access_entry(mkp->smk_known, okp->smk_known, |
| 1366 | &tsp->smk_rules); | 1546 | &tsp->smk_rules); |
| 1367 | if (tmay != -ENOENT) | 1547 | if (tmay != -ENOENT) |
| 1368 | mmay &= tmay; | 1548 | mmay &= tmay; |
| 1369 | 1549 | ||
| @@ -1390,12 +1570,11 @@ static int smack_mmap_file(struct file *file, | |||
| 1390 | * Returns 0 | 1570 | * Returns 0 |
| 1391 | * Further research may be required on this one. | 1571 | * Further research may be required on this one. |
| 1392 | */ | 1572 | */ |
| 1393 | static int smack_file_set_fowner(struct file *file) | 1573 | static void smack_file_set_fowner(struct file *file) |
| 1394 | { | 1574 | { |
| 1395 | struct smack_known *skp = smk_of_current(); | 1575 | struct smack_known *skp = smk_of_current(); |
| 1396 | 1576 | ||
| 1397 | file->f_security = skp->smk_known; | 1577 | file->f_security = skp; |
| 1398 | return 0; | ||
| 1399 | } | 1578 | } |
| 1400 | 1579 | ||
| 1401 | /** | 1580 | /** |
| @@ -1424,14 +1603,15 @@ static int smack_file_send_sigiotask(struct task_struct *tsk, | |||
| 1424 | file = container_of(fown, struct file, f_owner); | 1603 | file = container_of(fown, struct file, f_owner); |
| 1425 | 1604 | ||
| 1426 | /* we don't log here as rc can be overriden */ | 1605 | /* we don't log here as rc can be overriden */ |
| 1427 | skp = smk_find_entry(file->f_security); | 1606 | skp = file->f_security; |
| 1428 | rc = smk_access(skp, tkp->smk_known, MAY_WRITE, NULL); | 1607 | rc = smk_access(skp, tkp, MAY_WRITE, NULL); |
| 1608 | rc = smk_bu_note("sigiotask", skp, tkp, MAY_WRITE, rc); | ||
| 1429 | if (rc != 0 && has_capability(tsk, CAP_MAC_OVERRIDE)) | 1609 | if (rc != 0 && has_capability(tsk, CAP_MAC_OVERRIDE)) |
| 1430 | rc = 0; | 1610 | rc = 0; |
| 1431 | 1611 | ||
| 1432 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); | 1612 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); |
| 1433 | smk_ad_setfield_u_tsk(&ad, tsk); | 1613 | smk_ad_setfield_u_tsk(&ad, tsk); |
| 1434 | smack_log(file->f_security, tkp->smk_known, MAY_WRITE, rc, &ad); | 1614 | smack_log(skp->smk_known, tkp->smk_known, MAY_WRITE, rc, &ad); |
| 1435 | return rc; | 1615 | return rc; |
| 1436 | } | 1616 | } |
| 1437 | 1617 | ||
| @@ -1443,6 +1623,7 @@ static int smack_file_send_sigiotask(struct task_struct *tsk, | |||
| 1443 | */ | 1623 | */ |
| 1444 | static int smack_file_receive(struct file *file) | 1624 | static int smack_file_receive(struct file *file) |
| 1445 | { | 1625 | { |
| 1626 | int rc; | ||
| 1446 | int may = 0; | 1627 | int may = 0; |
| 1447 | struct smk_audit_info ad; | 1628 | struct smk_audit_info ad; |
| 1448 | 1629 | ||
| @@ -1456,7 +1637,9 @@ static int smack_file_receive(struct file *file) | |||
| 1456 | if (file->f_mode & FMODE_WRITE) | 1637 | if (file->f_mode & FMODE_WRITE) |
| 1457 | may |= MAY_WRITE; | 1638 | may |= MAY_WRITE; |
| 1458 | 1639 | ||
| 1459 | return smk_curacc(file->f_security, may, &ad); | 1640 | rc = smk_curacc(file->f_security, may, &ad); |
| 1641 | rc = smk_bu_file(file, may, rc); | ||
| 1642 | return rc; | ||
| 1460 | } | 1643 | } |
| 1461 | 1644 | ||
| 1462 | /** | 1645 | /** |
| @@ -1478,12 +1661,15 @@ static int smack_file_open(struct file *file, const struct cred *cred) | |||
| 1478 | struct smk_audit_info ad; | 1661 | struct smk_audit_info ad; |
| 1479 | int rc; | 1662 | int rc; |
| 1480 | 1663 | ||
| 1481 | if (smack_privileged(CAP_MAC_OVERRIDE)) | 1664 | if (smack_privileged(CAP_MAC_OVERRIDE)) { |
| 1665 | file->f_security = isp->smk_inode; | ||
| 1482 | return 0; | 1666 | return 0; |
| 1667 | } | ||
| 1483 | 1668 | ||
| 1484 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); | 1669 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); |
| 1485 | smk_ad_setfield_u_fs_path(&ad, file->f_path); | 1670 | smk_ad_setfield_u_fs_path(&ad, file->f_path); |
| 1486 | rc = smk_access(tsp->smk_task, isp->smk_inode, MAY_READ, &ad); | 1671 | rc = smk_access(tsp->smk_task, isp->smk_inode, MAY_READ, &ad); |
| 1672 | rc = smk_bu_credfile(cred, file, MAY_READ, rc); | ||
| 1487 | if (rc == 0) | 1673 | if (rc == 0) |
| 1488 | file->f_security = isp->smk_inode; | 1674 | file->f_security = isp->smk_inode; |
| 1489 | 1675 | ||
| @@ -1622,7 +1808,7 @@ static int smack_kernel_create_files_as(struct cred *new, | |||
| 1622 | struct inode_smack *isp = inode->i_security; | 1808 | struct inode_smack *isp = inode->i_security; |
| 1623 | struct task_smack *tsp = new->security; | 1809 | struct task_smack *tsp = new->security; |
| 1624 | 1810 | ||
| 1625 | tsp->smk_forked = smk_find_entry(isp->smk_inode); | 1811 | tsp->smk_forked = isp->smk_inode; |
| 1626 | tsp->smk_task = tsp->smk_forked; | 1812 | tsp->smk_task = tsp->smk_forked; |
| 1627 | return 0; | 1813 | return 0; |
| 1628 | } | 1814 | } |
| @@ -1640,10 +1826,13 @@ static int smk_curacc_on_task(struct task_struct *p, int access, | |||
| 1640 | { | 1826 | { |
| 1641 | struct smk_audit_info ad; | 1827 | struct smk_audit_info ad; |
| 1642 | struct smack_known *skp = smk_of_task(task_security(p)); | 1828 | struct smack_known *skp = smk_of_task(task_security(p)); |
| 1829 | int rc; | ||
| 1643 | 1830 | ||
| 1644 | smk_ad_init(&ad, caller, LSM_AUDIT_DATA_TASK); | 1831 | smk_ad_init(&ad, caller, LSM_AUDIT_DATA_TASK); |
| 1645 | smk_ad_setfield_u_tsk(&ad, p); | 1832 | smk_ad_setfield_u_tsk(&ad, p); |
| 1646 | return smk_curacc(skp->smk_known, access, &ad); | 1833 | rc = smk_curacc(skp, access, &ad); |
| 1834 | rc = smk_bu_task(p, access, rc); | ||
| 1835 | return rc; | ||
| 1647 | } | 1836 | } |
| 1648 | 1837 | ||
| 1649 | /** | 1838 | /** |
| @@ -1797,6 +1986,7 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info, | |||
| 1797 | struct smk_audit_info ad; | 1986 | struct smk_audit_info ad; |
| 1798 | struct smack_known *skp; | 1987 | struct smack_known *skp; |
| 1799 | struct smack_known *tkp = smk_of_task(task_security(p)); | 1988 | struct smack_known *tkp = smk_of_task(task_security(p)); |
| 1989 | int rc; | ||
| 1800 | 1990 | ||
| 1801 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); | 1991 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); |
| 1802 | smk_ad_setfield_u_tsk(&ad, p); | 1992 | smk_ad_setfield_u_tsk(&ad, p); |
| @@ -1804,15 +1994,20 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info, | |||
| 1804 | * Sending a signal requires that the sender | 1994 | * Sending a signal requires that the sender |
| 1805 | * can write the receiver. | 1995 | * can write the receiver. |
| 1806 | */ | 1996 | */ |
| 1807 | if (secid == 0) | 1997 | if (secid == 0) { |
| 1808 | return smk_curacc(tkp->smk_known, MAY_WRITE, &ad); | 1998 | rc = smk_curacc(tkp, MAY_WRITE, &ad); |
| 1999 | rc = smk_bu_task(p, MAY_WRITE, rc); | ||
| 2000 | return rc; | ||
| 2001 | } | ||
| 1809 | /* | 2002 | /* |
| 1810 | * If the secid isn't 0 we're dealing with some USB IO | 2003 | * If the secid isn't 0 we're dealing with some USB IO |
| 1811 | * specific behavior. This is not clean. For one thing | 2004 | * specific behavior. This is not clean. For one thing |
| 1812 | * we can't take privilege into account. | 2005 | * we can't take privilege into account. |
| 1813 | */ | 2006 | */ |
| 1814 | skp = smack_from_secid(secid); | 2007 | skp = smack_from_secid(secid); |
| 1815 | return smk_access(skp, tkp->smk_known, MAY_WRITE, &ad); | 2008 | rc = smk_access(skp, tkp, MAY_WRITE, &ad); |
| 2009 | rc = smk_bu_note("USB signal", skp, tkp, MAY_WRITE, rc); | ||
| 2010 | return rc; | ||
| 1816 | } | 2011 | } |
| 1817 | 2012 | ||
| 1818 | /** | 2013 | /** |
| @@ -1846,7 +2041,7 @@ static void smack_task_to_inode(struct task_struct *p, struct inode *inode) | |||
| 1846 | struct inode_smack *isp = inode->i_security; | 2041 | struct inode_smack *isp = inode->i_security; |
| 1847 | struct smack_known *skp = smk_of_task(task_security(p)); | 2042 | struct smack_known *skp = smk_of_task(task_security(p)); |
| 1848 | 2043 | ||
| 1849 | isp->smk_inode = skp->smk_known; | 2044 | isp->smk_inode = skp; |
| 1850 | } | 2045 | } |
| 1851 | 2046 | ||
| 1852 | /* | 2047 | /* |
| @@ -1904,7 +2099,7 @@ static void smack_sk_free_security(struct sock *sk) | |||
| 1904 | * | 2099 | * |
| 1905 | * Returns the label of the far end or NULL if it's not special. | 2100 | * Returns the label of the far end or NULL if it's not special. |
| 1906 | */ | 2101 | */ |
| 1907 | static char *smack_host_label(struct sockaddr_in *sip) | 2102 | static struct smack_known *smack_host_label(struct sockaddr_in *sip) |
| 1908 | { | 2103 | { |
| 1909 | struct smk_netlbladdr *snp; | 2104 | struct smk_netlbladdr *snp; |
| 1910 | struct in_addr *siap = &sip->sin_addr; | 2105 | struct in_addr *siap = &sip->sin_addr; |
| @@ -1921,7 +2116,7 @@ static char *smack_host_label(struct sockaddr_in *sip) | |||
| 1921 | if ((&snp->smk_host.sin_addr)->s_addr == | 2116 | if ((&snp->smk_host.sin_addr)->s_addr == |
| 1922 | (siap->s_addr & (&snp->smk_mask)->s_addr)) { | 2117 | (siap->s_addr & (&snp->smk_mask)->s_addr)) { |
| 1923 | /* we have found the special CIPSO option */ | 2118 | /* we have found the special CIPSO option */ |
| 1924 | if (snp->smk_label == smack_cipso_option) | 2119 | if (snp->smk_label == &smack_cipso_option) |
| 1925 | return NULL; | 2120 | return NULL; |
| 1926 | return snp->smk_label; | 2121 | return snp->smk_label; |
| 1927 | } | 2122 | } |
| @@ -1986,13 +2181,13 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap) | |||
| 1986 | struct smack_known *skp; | 2181 | struct smack_known *skp; |
| 1987 | int rc; | 2182 | int rc; |
| 1988 | int sk_lbl; | 2183 | int sk_lbl; |
| 1989 | char *hostsp; | 2184 | struct smack_known *hkp; |
| 1990 | struct socket_smack *ssp = sk->sk_security; | 2185 | struct socket_smack *ssp = sk->sk_security; |
| 1991 | struct smk_audit_info ad; | 2186 | struct smk_audit_info ad; |
| 1992 | 2187 | ||
| 1993 | rcu_read_lock(); | 2188 | rcu_read_lock(); |
| 1994 | hostsp = smack_host_label(sap); | 2189 | hkp = smack_host_label(sap); |
| 1995 | if (hostsp != NULL) { | 2190 | if (hkp != NULL) { |
| 1996 | #ifdef CONFIG_AUDIT | 2191 | #ifdef CONFIG_AUDIT |
| 1997 | struct lsm_network_audit net; | 2192 | struct lsm_network_audit net; |
| 1998 | 2193 | ||
| @@ -2003,7 +2198,8 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap) | |||
| 2003 | #endif | 2198 | #endif |
| 2004 | sk_lbl = SMACK_UNLABELED_SOCKET; | 2199 | sk_lbl = SMACK_UNLABELED_SOCKET; |
| 2005 | skp = ssp->smk_out; | 2200 | skp = ssp->smk_out; |
| 2006 | rc = smk_access(skp, hostsp, MAY_WRITE, &ad); | 2201 | rc = smk_access(skp, hkp, MAY_WRITE, &ad); |
| 2202 | rc = smk_bu_note("IPv4 host check", skp, hkp, MAY_WRITE, rc); | ||
| 2007 | } else { | 2203 | } else { |
| 2008 | sk_lbl = SMACK_CIPSO_SOCKET; | 2204 | sk_lbl = SMACK_CIPSO_SOCKET; |
| 2009 | rc = 0; | 2205 | rc = 0; |
| @@ -2104,18 +2300,19 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address, | |||
| 2104 | struct socket_smack *ssp = sk->sk_security; | 2300 | struct socket_smack *ssp = sk->sk_security; |
| 2105 | struct smack_known *skp; | 2301 | struct smack_known *skp; |
| 2106 | unsigned short port = 0; | 2302 | unsigned short port = 0; |
| 2107 | char *object; | 2303 | struct smack_known *object; |
| 2108 | struct smk_audit_info ad; | 2304 | struct smk_audit_info ad; |
| 2305 | int rc; | ||
| 2109 | #ifdef CONFIG_AUDIT | 2306 | #ifdef CONFIG_AUDIT |
| 2110 | struct lsm_network_audit net; | 2307 | struct lsm_network_audit net; |
| 2111 | #endif | 2308 | #endif |
| 2112 | 2309 | ||
| 2113 | if (act == SMK_RECEIVING) { | 2310 | if (act == SMK_RECEIVING) { |
| 2114 | skp = smack_net_ambient; | 2311 | skp = smack_net_ambient; |
| 2115 | object = ssp->smk_in->smk_known; | 2312 | object = ssp->smk_in; |
| 2116 | } else { | 2313 | } else { |
| 2117 | skp = ssp->smk_out; | 2314 | skp = ssp->smk_out; |
| 2118 | object = smack_net_ambient->smk_known; | 2315 | object = smack_net_ambient; |
| 2119 | } | 2316 | } |
| 2120 | 2317 | ||
| 2121 | /* | 2318 | /* |
| @@ -2142,7 +2339,7 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address, | |||
| 2142 | list_for_each_entry(spp, &smk_ipv6_port_list, list) { | 2339 | list_for_each_entry(spp, &smk_ipv6_port_list, list) { |
| 2143 | if (spp->smk_port != port) | 2340 | if (spp->smk_port != port) |
| 2144 | continue; | 2341 | continue; |
| 2145 | object = spp->smk_in->smk_known; | 2342 | object = spp->smk_in; |
| 2146 | if (act == SMK_CONNECTING) | 2343 | if (act == SMK_CONNECTING) |
| 2147 | ssp->smk_packet = spp->smk_out; | 2344 | ssp->smk_packet = spp->smk_out; |
| 2148 | break; | 2345 | break; |
| @@ -2159,7 +2356,9 @@ auditout: | |||
| 2159 | else | 2356 | else |
| 2160 | ad.a.u.net->v6info.daddr = address->sin6_addr; | 2357 | ad.a.u.net->v6info.daddr = address->sin6_addr; |
| 2161 | #endif | 2358 | #endif |
| 2162 | return smk_access(skp, object, MAY_WRITE, &ad); | 2359 | rc = smk_access(skp, object, MAY_WRITE, &ad); |
| 2360 | rc = smk_bu_note("IPv6 port check", skp, object, MAY_WRITE, rc); | ||
| 2361 | return rc; | ||
| 2163 | } | 2362 | } |
| 2164 | 2363 | ||
| 2165 | /** | 2364 | /** |
| @@ -2191,7 +2390,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name, | |||
| 2191 | return -EINVAL; | 2390 | return -EINVAL; |
| 2192 | 2391 | ||
| 2193 | if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) { | 2392 | if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) { |
| 2194 | nsp->smk_inode = skp->smk_known; | 2393 | nsp->smk_inode = skp; |
| 2195 | nsp->smk_flags |= SMK_INODE_INSTANT; | 2394 | nsp->smk_flags |= SMK_INODE_INSTANT; |
| 2196 | return 0; | 2395 | return 0; |
| 2197 | } | 2396 | } |
| @@ -2333,7 +2532,7 @@ static int smack_msg_msg_alloc_security(struct msg_msg *msg) | |||
| 2333 | { | 2532 | { |
| 2334 | struct smack_known *skp = smk_of_current(); | 2533 | struct smack_known *skp = smk_of_current(); |
| 2335 | 2534 | ||
| 2336 | msg->security = skp->smk_known; | 2535 | msg->security = skp; |
| 2337 | return 0; | 2536 | return 0; |
| 2338 | } | 2537 | } |
| 2339 | 2538 | ||
| @@ -2354,9 +2553,9 @@ static void smack_msg_msg_free_security(struct msg_msg *msg) | |||
| 2354 | * | 2553 | * |
| 2355 | * Returns a pointer to the smack value | 2554 | * Returns a pointer to the smack value |
| 2356 | */ | 2555 | */ |
| 2357 | static char *smack_of_shm(struct shmid_kernel *shp) | 2556 | static struct smack_known *smack_of_shm(struct shmid_kernel *shp) |
| 2358 | { | 2557 | { |
| 2359 | return (char *)shp->shm_perm.security; | 2558 | return (struct smack_known *)shp->shm_perm.security; |
| 2360 | } | 2559 | } |
| 2361 | 2560 | ||
| 2362 | /** | 2561 | /** |
| @@ -2370,7 +2569,7 @@ static int smack_shm_alloc_security(struct shmid_kernel *shp) | |||
| 2370 | struct kern_ipc_perm *isp = &shp->shm_perm; | 2569 | struct kern_ipc_perm *isp = &shp->shm_perm; |
| 2371 | struct smack_known *skp = smk_of_current(); | 2570 | struct smack_known *skp = smk_of_current(); |
| 2372 | 2571 | ||
| 2373 | isp->security = skp->smk_known; | 2572 | isp->security = skp; |
| 2374 | return 0; | 2573 | return 0; |
| 2375 | } | 2574 | } |
| 2376 | 2575 | ||
| @@ -2396,14 +2595,17 @@ static void smack_shm_free_security(struct shmid_kernel *shp) | |||
| 2396 | */ | 2595 | */ |
| 2397 | static int smk_curacc_shm(struct shmid_kernel *shp, int access) | 2596 | static int smk_curacc_shm(struct shmid_kernel *shp, int access) |
| 2398 | { | 2597 | { |
| 2399 | char *ssp = smack_of_shm(shp); | 2598 | struct smack_known *ssp = smack_of_shm(shp); |
| 2400 | struct smk_audit_info ad; | 2599 | struct smk_audit_info ad; |
| 2600 | int rc; | ||
| 2401 | 2601 | ||
| 2402 | #ifdef CONFIG_AUDIT | 2602 | #ifdef CONFIG_AUDIT |
| 2403 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC); | 2603 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC); |
| 2404 | ad.a.u.ipc_id = shp->shm_perm.id; | 2604 | ad.a.u.ipc_id = shp->shm_perm.id; |
| 2405 | #endif | 2605 | #endif |
| 2406 | return smk_curacc(ssp, access, &ad); | 2606 | rc = smk_curacc(ssp, access, &ad); |
| 2607 | rc = smk_bu_current("shm", ssp, access, rc); | ||
| 2608 | return rc; | ||
| 2407 | } | 2609 | } |
| 2408 | 2610 | ||
| 2409 | /** | 2611 | /** |
| @@ -2478,9 +2680,9 @@ static int smack_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr, | |||
| 2478 | * | 2680 | * |
| 2479 | * Returns a pointer to the smack value | 2681 | * Returns a pointer to the smack value |
| 2480 | */ | 2682 | */ |
| 2481 | static char *smack_of_sem(struct sem_array *sma) | 2683 | static struct smack_known *smack_of_sem(struct sem_array *sma) |
| 2482 | { | 2684 | { |
| 2483 | return (char *)sma->sem_perm.security; | 2685 | return (struct smack_known *)sma->sem_perm.security; |
| 2484 | } | 2686 | } |
| 2485 | 2687 | ||
| 2486 | /** | 2688 | /** |
| @@ -2494,7 +2696,7 @@ static int smack_sem_alloc_security(struct sem_array *sma) | |||
| 2494 | struct kern_ipc_perm *isp = &sma->sem_perm; | 2696 | struct kern_ipc_perm *isp = &sma->sem_perm; |
| 2495 | struct smack_known *skp = smk_of_current(); | 2697 | struct smack_known *skp = smk_of_current(); |
| 2496 | 2698 | ||
| 2497 | isp->security = skp->smk_known; | 2699 | isp->security = skp; |
| 2498 | return 0; | 2700 | return 0; |
| 2499 | } | 2701 | } |
| 2500 | 2702 | ||
| @@ -2520,14 +2722,17 @@ static void smack_sem_free_security(struct sem_array *sma) | |||
| 2520 | */ | 2722 | */ |
| 2521 | static int smk_curacc_sem(struct sem_array *sma, int access) | 2723 | static int smk_curacc_sem(struct sem_array *sma, int access) |
| 2522 | { | 2724 | { |
| 2523 | char *ssp = smack_of_sem(sma); | 2725 | struct smack_known *ssp = smack_of_sem(sma); |
| 2524 | struct smk_audit_info ad; | 2726 | struct smk_audit_info ad; |
| 2727 | int rc; | ||
| 2525 | 2728 | ||
| 2526 | #ifdef CONFIG_AUDIT | 2729 | #ifdef CONFIG_AUDIT |
| 2527 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC); | 2730 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC); |
| 2528 | ad.a.u.ipc_id = sma->sem_perm.id; | 2731 | ad.a.u.ipc_id = sma->sem_perm.id; |
| 2529 | #endif | 2732 | #endif |
| 2530 | return smk_curacc(ssp, access, &ad); | 2733 | rc = smk_curacc(ssp, access, &ad); |
| 2734 | rc = smk_bu_current("sem", ssp, access, rc); | ||
| 2735 | return rc; | ||
| 2531 | } | 2736 | } |
| 2532 | 2737 | ||
| 2533 | /** | 2738 | /** |
| @@ -2613,7 +2818,7 @@ static int smack_msg_queue_alloc_security(struct msg_queue *msq) | |||
| 2613 | struct kern_ipc_perm *kisp = &msq->q_perm; | 2818 | struct kern_ipc_perm *kisp = &msq->q_perm; |
| 2614 | struct smack_known *skp = smk_of_current(); | 2819 | struct smack_known *skp = smk_of_current(); |
| 2615 | 2820 | ||
| 2616 | kisp->security = skp->smk_known; | 2821 | kisp->security = skp; |
| 2617 | return 0; | 2822 | return 0; |
| 2618 | } | 2823 | } |
| 2619 | 2824 | ||
| @@ -2634,11 +2839,11 @@ static void smack_msg_queue_free_security(struct msg_queue *msq) | |||
| 2634 | * smack_of_msq - the smack pointer for the msq | 2839 | * smack_of_msq - the smack pointer for the msq |
| 2635 | * @msq: the object | 2840 | * @msq: the object |
| 2636 | * | 2841 | * |
| 2637 | * Returns a pointer to the smack value | 2842 | * Returns a pointer to the smack label entry |
| 2638 | */ | 2843 | */ |
| 2639 | static char *smack_of_msq(struct msg_queue *msq) | 2844 | static struct smack_known *smack_of_msq(struct msg_queue *msq) |
| 2640 | { | 2845 | { |
| 2641 | return (char *)msq->q_perm.security; | 2846 | return (struct smack_known *)msq->q_perm.security; |
| 2642 | } | 2847 | } |
| 2643 | 2848 | ||
| 2644 | /** | 2849 | /** |
| @@ -2650,14 +2855,17 @@ static char *smack_of_msq(struct msg_queue *msq) | |||
| 2650 | */ | 2855 | */ |
| 2651 | static int smk_curacc_msq(struct msg_queue *msq, int access) | 2856 | static int smk_curacc_msq(struct msg_queue *msq, int access) |
| 2652 | { | 2857 | { |
| 2653 | char *msp = smack_of_msq(msq); | 2858 | struct smack_known *msp = smack_of_msq(msq); |
| 2654 | struct smk_audit_info ad; | 2859 | struct smk_audit_info ad; |
| 2860 | int rc; | ||
| 2655 | 2861 | ||
| 2656 | #ifdef CONFIG_AUDIT | 2862 | #ifdef CONFIG_AUDIT |
| 2657 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC); | 2863 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC); |
| 2658 | ad.a.u.ipc_id = msq->q_perm.id; | 2864 | ad.a.u.ipc_id = msq->q_perm.id; |
| 2659 | #endif | 2865 | #endif |
| 2660 | return smk_curacc(msp, access, &ad); | 2866 | rc = smk_curacc(msp, access, &ad); |
| 2867 | rc = smk_bu_current("msq", msp, access, rc); | ||
| 2868 | return rc; | ||
| 2661 | } | 2869 | } |
| 2662 | 2870 | ||
| 2663 | /** | 2871 | /** |
| @@ -2750,15 +2958,18 @@ static int smack_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, | |||
| 2750 | */ | 2958 | */ |
| 2751 | static int smack_ipc_permission(struct kern_ipc_perm *ipp, short flag) | 2959 | static int smack_ipc_permission(struct kern_ipc_perm *ipp, short flag) |
| 2752 | { | 2960 | { |
| 2753 | char *isp = ipp->security; | 2961 | struct smack_known *iskp = ipp->security; |
| 2754 | int may = smack_flags_to_may(flag); | 2962 | int may = smack_flags_to_may(flag); |
| 2755 | struct smk_audit_info ad; | 2963 | struct smk_audit_info ad; |
| 2964 | int rc; | ||
| 2756 | 2965 | ||
| 2757 | #ifdef CONFIG_AUDIT | 2966 | #ifdef CONFIG_AUDIT |
| 2758 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC); | 2967 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC); |
| 2759 | ad.a.u.ipc_id = ipp->id; | 2968 | ad.a.u.ipc_id = ipp->id; |
| 2760 | #endif | 2969 | #endif |
| 2761 | return smk_curacc(isp, may, &ad); | 2970 | rc = smk_curacc(iskp, may, &ad); |
| 2971 | rc = smk_bu_current("svipc", iskp, may, rc); | ||
| 2972 | return rc; | ||
| 2762 | } | 2973 | } |
| 2763 | 2974 | ||
| 2764 | /** | 2975 | /** |
| @@ -2768,9 +2979,9 @@ static int smack_ipc_permission(struct kern_ipc_perm *ipp, short flag) | |||
| 2768 | */ | 2979 | */ |
| 2769 | static void smack_ipc_getsecid(struct kern_ipc_perm *ipp, u32 *secid) | 2980 | static void smack_ipc_getsecid(struct kern_ipc_perm *ipp, u32 *secid) |
| 2770 | { | 2981 | { |
| 2771 | char *smack = ipp->security; | 2982 | struct smack_known *iskp = ipp->security; |
| 2772 | 2983 | ||
| 2773 | *secid = smack_to_secid(smack); | 2984 | *secid = iskp->smk_secid; |
| 2774 | } | 2985 | } |
| 2775 | 2986 | ||
| 2776 | /** | 2987 | /** |
| @@ -2787,7 +2998,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
| 2787 | struct inode_smack *isp; | 2998 | struct inode_smack *isp; |
| 2788 | struct smack_known *skp; | 2999 | struct smack_known *skp; |
| 2789 | struct smack_known *ckp = smk_of_current(); | 3000 | struct smack_known *ckp = smk_of_current(); |
| 2790 | char *final; | 3001 | struct smack_known *final; |
| 2791 | char trattr[TRANS_TRUE_SIZE]; | 3002 | char trattr[TRANS_TRUE_SIZE]; |
| 2792 | int transflag = 0; | 3003 | int transflag = 0; |
| 2793 | int rc; | 3004 | int rc; |
| @@ -2827,8 +3038,8 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
| 2827 | * so there's no opportunity to set the mount | 3038 | * so there's no opportunity to set the mount |
| 2828 | * options. | 3039 | * options. |
| 2829 | */ | 3040 | */ |
| 2830 | sbsp->smk_root = smack_known_star.smk_known; | 3041 | sbsp->smk_root = &smack_known_star; |
| 2831 | sbsp->smk_default = smack_known_star.smk_known; | 3042 | sbsp->smk_default = &smack_known_star; |
| 2832 | } | 3043 | } |
| 2833 | isp->smk_inode = sbsp->smk_root; | 3044 | isp->smk_inode = sbsp->smk_root; |
| 2834 | isp->smk_flags |= SMK_INODE_INSTANT; | 3045 | isp->smk_flags |= SMK_INODE_INSTANT; |
| @@ -2858,7 +3069,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
| 2858 | * | 3069 | * |
| 2859 | * Cgroupfs is special | 3070 | * Cgroupfs is special |
| 2860 | */ | 3071 | */ |
| 2861 | final = smack_known_star.smk_known; | 3072 | final = &smack_known_star; |
| 2862 | break; | 3073 | break; |
| 2863 | case DEVPTS_SUPER_MAGIC: | 3074 | case DEVPTS_SUPER_MAGIC: |
| 2864 | /* | 3075 | /* |
| @@ -2866,7 +3077,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
| 2866 | * Programs that change smack have to treat the | 3077 | * Programs that change smack have to treat the |
| 2867 | * pty with respect. | 3078 | * pty with respect. |
| 2868 | */ | 3079 | */ |
| 2869 | final = ckp->smk_known; | 3080 | final = ckp; |
| 2870 | break; | 3081 | break; |
| 2871 | case PROC_SUPER_MAGIC: | 3082 | case PROC_SUPER_MAGIC: |
| 2872 | /* | 3083 | /* |
| @@ -2880,7 +3091,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
| 2880 | * but watch out, because they're volitile, | 3091 | * but watch out, because they're volitile, |
| 2881 | * getting recreated on every reboot. | 3092 | * getting recreated on every reboot. |
| 2882 | */ | 3093 | */ |
| 2883 | final = smack_known_star.smk_known; | 3094 | final = &smack_known_star; |
| 2884 | /* | 3095 | /* |
| 2885 | * No break. | 3096 | * No break. |
| 2886 | * | 3097 | * |
| @@ -2899,7 +3110,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
| 2899 | * UNIX domain sockets use lower level socket data. | 3110 | * UNIX domain sockets use lower level socket data. |
| 2900 | */ | 3111 | */ |
| 2901 | if (S_ISSOCK(inode->i_mode)) { | 3112 | if (S_ISSOCK(inode->i_mode)) { |
| 2902 | final = smack_known_star.smk_known; | 3113 | final = &smack_known_star; |
| 2903 | break; | 3114 | break; |
| 2904 | } | 3115 | } |
| 2905 | /* | 3116 | /* |
| @@ -2916,7 +3127,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
| 2916 | dp = dget(opt_dentry); | 3127 | dp = dget(opt_dentry); |
| 2917 | skp = smk_fetch(XATTR_NAME_SMACK, inode, dp); | 3128 | skp = smk_fetch(XATTR_NAME_SMACK, inode, dp); |
| 2918 | if (skp != NULL) | 3129 | if (skp != NULL) |
| 2919 | final = skp->smk_known; | 3130 | final = skp; |
| 2920 | 3131 | ||
| 2921 | /* | 3132 | /* |
| 2922 | * Transmuting directory | 3133 | * Transmuting directory |
| @@ -2965,7 +3176,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
| 2965 | } | 3176 | } |
| 2966 | 3177 | ||
| 2967 | if (final == NULL) | 3178 | if (final == NULL) |
| 2968 | isp->smk_inode = ckp->smk_known; | 3179 | isp->smk_inode = ckp; |
| 2969 | else | 3180 | else |
| 2970 | isp->smk_inode = final; | 3181 | isp->smk_inode = final; |
| 2971 | 3182 | ||
| @@ -3090,9 +3301,13 @@ static int smack_unix_stream_connect(struct sock *sock, | |||
| 3090 | smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); | 3301 | smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); |
| 3091 | smk_ad_setfield_u_net_sk(&ad, other); | 3302 | smk_ad_setfield_u_net_sk(&ad, other); |
| 3092 | #endif | 3303 | #endif |
| 3093 | rc = smk_access(skp, okp->smk_known, MAY_WRITE, &ad); | 3304 | rc = smk_access(skp, okp, MAY_WRITE, &ad); |
| 3094 | if (rc == 0) | 3305 | rc = smk_bu_note("UDS connect", skp, okp, MAY_WRITE, rc); |
| 3095 | rc = smk_access(okp, okp->smk_known, MAY_WRITE, NULL); | 3306 | if (rc == 0) { |
| 3307 | rc = smk_access(okp, skp, MAY_WRITE, NULL); | ||
| 3308 | rc = smk_bu_note("UDS connect", okp, skp, | ||
| 3309 | MAY_WRITE, rc); | ||
| 3310 | } | ||
| 3096 | } | 3311 | } |
| 3097 | 3312 | ||
| 3098 | /* | 3313 | /* |
| @@ -3118,8 +3333,8 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other) | |||
| 3118 | { | 3333 | { |
| 3119 | struct socket_smack *ssp = sock->sk->sk_security; | 3334 | struct socket_smack *ssp = sock->sk->sk_security; |
| 3120 | struct socket_smack *osp = other->sk->sk_security; | 3335 | struct socket_smack *osp = other->sk->sk_security; |
| 3121 | struct smack_known *skp; | ||
| 3122 | struct smk_audit_info ad; | 3336 | struct smk_audit_info ad; |
| 3337 | int rc; | ||
| 3123 | 3338 | ||
| 3124 | #ifdef CONFIG_AUDIT | 3339 | #ifdef CONFIG_AUDIT |
| 3125 | struct lsm_network_audit net; | 3340 | struct lsm_network_audit net; |
| @@ -3131,8 +3346,9 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other) | |||
| 3131 | if (smack_privileged(CAP_MAC_OVERRIDE)) | 3346 | if (smack_privileged(CAP_MAC_OVERRIDE)) |
| 3132 | return 0; | 3347 | return 0; |
| 3133 | 3348 | ||
| 3134 | skp = ssp->smk_out; | 3349 | rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad); |
| 3135 | return smk_access(skp, osp->smk_in->smk_known, MAY_WRITE, &ad); | 3350 | rc = smk_bu_note("UDS send", ssp->smk_out, osp->smk_in, MAY_WRITE, rc); |
| 3351 | return rc; | ||
| 3136 | } | 3352 | } |
| 3137 | 3353 | ||
| 3138 | /** | 3354 | /** |
| @@ -3346,7 +3562,9 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
| 3346 | * This is the simplist possible security model | 3562 | * This is the simplist possible security model |
| 3347 | * for networking. | 3563 | * for networking. |
| 3348 | */ | 3564 | */ |
| 3349 | rc = smk_access(skp, ssp->smk_in->smk_known, MAY_WRITE, &ad); | 3565 | rc = smk_access(skp, ssp->smk_in, MAY_WRITE, &ad); |
| 3566 | rc = smk_bu_note("IPv4 delivery", skp, ssp->smk_in, | ||
| 3567 | MAY_WRITE, rc); | ||
| 3350 | if (rc != 0) | 3568 | if (rc != 0) |
| 3351 | netlbl_skbuff_err(skb, rc, 0); | 3569 | netlbl_skbuff_err(skb, rc, 0); |
| 3352 | break; | 3570 | break; |
| @@ -3489,7 +3707,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, | |||
| 3489 | struct netlbl_lsm_secattr secattr; | 3707 | struct netlbl_lsm_secattr secattr; |
| 3490 | struct sockaddr_in addr; | 3708 | struct sockaddr_in addr; |
| 3491 | struct iphdr *hdr; | 3709 | struct iphdr *hdr; |
| 3492 | char *hsp; | 3710 | struct smack_known *hskp; |
| 3493 | int rc; | 3711 | int rc; |
| 3494 | struct smk_audit_info ad; | 3712 | struct smk_audit_info ad; |
| 3495 | #ifdef CONFIG_AUDIT | 3713 | #ifdef CONFIG_AUDIT |
| @@ -3526,7 +3744,8 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, | |||
| 3526 | * Receiving a packet requires that the other end be able to write | 3744 | * Receiving a packet requires that the other end be able to write |
| 3527 | * here. Read access is not required. | 3745 | * here. Read access is not required. |
| 3528 | */ | 3746 | */ |
| 3529 | rc = smk_access(skp, ssp->smk_in->smk_known, MAY_WRITE, &ad); | 3747 | rc = smk_access(skp, ssp->smk_in, MAY_WRITE, &ad); |
| 3748 | rc = smk_bu_note("IPv4 connect", skp, ssp->smk_in, MAY_WRITE, rc); | ||
| 3530 | if (rc != 0) | 3749 | if (rc != 0) |
| 3531 | return rc; | 3750 | return rc; |
| 3532 | 3751 | ||
| @@ -3544,10 +3763,10 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, | |||
| 3544 | hdr = ip_hdr(skb); | 3763 | hdr = ip_hdr(skb); |
| 3545 | addr.sin_addr.s_addr = hdr->saddr; | 3764 | addr.sin_addr.s_addr = hdr->saddr; |
| 3546 | rcu_read_lock(); | 3765 | rcu_read_lock(); |
| 3547 | hsp = smack_host_label(&addr); | 3766 | hskp = smack_host_label(&addr); |
| 3548 | rcu_read_unlock(); | 3767 | rcu_read_unlock(); |
| 3549 | 3768 | ||
| 3550 | if (hsp == NULL) | 3769 | if (hskp == NULL) |
| 3551 | rc = netlbl_req_setattr(req, &skp->smk_netlabel); | 3770 | rc = netlbl_req_setattr(req, &skp->smk_netlabel); |
| 3552 | else | 3771 | else |
| 3553 | netlbl_req_delattr(req); | 3772 | netlbl_req_delattr(req); |
| @@ -3599,7 +3818,7 @@ static int smack_key_alloc(struct key *key, const struct cred *cred, | |||
| 3599 | { | 3818 | { |
| 3600 | struct smack_known *skp = smk_of_task(cred->security); | 3819 | struct smack_known *skp = smk_of_task(cred->security); |
| 3601 | 3820 | ||
| 3602 | key->security = skp->smk_known; | 3821 | key->security = skp; |
| 3603 | return 0; | 3822 | return 0; |
| 3604 | } | 3823 | } |
| 3605 | 3824 | ||
| @@ -3630,6 +3849,7 @@ static int smack_key_permission(key_ref_t key_ref, | |||
| 3630 | struct smk_audit_info ad; | 3849 | struct smk_audit_info ad; |
| 3631 | struct smack_known *tkp = smk_of_task(cred->security); | 3850 | struct smack_known *tkp = smk_of_task(cred->security); |
| 3632 | int request = 0; | 3851 | int request = 0; |
| 3852 | int rc; | ||
| 3633 | 3853 | ||
| 3634 | keyp = key_ref_to_ptr(key_ref); | 3854 | keyp = key_ref_to_ptr(key_ref); |
| 3635 | if (keyp == NULL) | 3855 | if (keyp == NULL) |
| @@ -3654,7 +3874,9 @@ static int smack_key_permission(key_ref_t key_ref, | |||
| 3654 | request = MAY_READ; | 3874 | request = MAY_READ; |
| 3655 | if (perm & (KEY_NEED_WRITE | KEY_NEED_LINK | KEY_NEED_SETATTR)) | 3875 | if (perm & (KEY_NEED_WRITE | KEY_NEED_LINK | KEY_NEED_SETATTR)) |
| 3656 | request = MAY_WRITE; | 3876 | request = MAY_WRITE; |
| 3657 | return smk_access(tkp, keyp->security, request, &ad); | 3877 | rc = smk_access(tkp, keyp->security, request, &ad); |
| 3878 | rc = smk_bu_note("key access", tkp, keyp->security, request, rc); | ||
| 3879 | return rc; | ||
| 3658 | } | 3880 | } |
| 3659 | #endif /* CONFIG_KEYS */ | 3881 | #endif /* CONFIG_KEYS */ |
| 3660 | 3882 | ||
| @@ -3685,6 +3907,7 @@ static int smack_key_permission(key_ref_t key_ref, | |||
| 3685 | */ | 3907 | */ |
| 3686 | static int smack_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule) | 3908 | static int smack_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule) |
| 3687 | { | 3909 | { |
| 3910 | struct smack_known *skp; | ||
| 3688 | char **rule = (char **)vrule; | 3911 | char **rule = (char **)vrule; |
| 3689 | *rule = NULL; | 3912 | *rule = NULL; |
| 3690 | 3913 | ||
| @@ -3694,7 +3917,9 @@ static int smack_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule) | |||
| 3694 | if (op != Audit_equal && op != Audit_not_equal) | 3917 | if (op != Audit_equal && op != Audit_not_equal) |
| 3695 | return -EINVAL; | 3918 | return -EINVAL; |
| 3696 | 3919 | ||
| 3697 | *rule = smk_import(rulestr, 0); | 3920 | skp = smk_import_entry(rulestr, 0); |
| 3921 | if (skp) | ||
| 3922 | *rule = skp->smk_known; | ||
| 3698 | 3923 | ||
| 3699 | return 0; | 3924 | return 0; |
| 3700 | } | 3925 | } |
| @@ -3813,7 +4038,12 @@ static int smack_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) | |||
| 3813 | */ | 4038 | */ |
| 3814 | static int smack_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid) | 4039 | static int smack_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid) |
| 3815 | { | 4040 | { |
| 3816 | *secid = smack_to_secid(secdata); | 4041 | struct smack_known *skp = smk_find_entry(secdata); |
| 4042 | |||
| 4043 | if (skp) | ||
| 4044 | *secid = skp->smk_secid; | ||
| 4045 | else | ||
| 4046 | *secid = 0; | ||
| 3817 | return 0; | 4047 | return 0; |
| 3818 | } | 4048 | } |
| 3819 | 4049 | ||
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 3c720ff10591..bce4e8f1b267 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c | |||
| @@ -131,14 +131,17 @@ LIST_HEAD(smack_rule_list); | |||
| 131 | 131 | ||
| 132 | struct smack_parsed_rule { | 132 | struct smack_parsed_rule { |
| 133 | struct smack_known *smk_subject; | 133 | struct smack_known *smk_subject; |
| 134 | char *smk_object; | 134 | struct smack_known *smk_object; |
| 135 | int smk_access1; | 135 | int smk_access1; |
| 136 | int smk_access2; | 136 | int smk_access2; |
| 137 | }; | 137 | }; |
| 138 | 138 | ||
| 139 | static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT; | 139 | static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT; |
| 140 | 140 | ||
| 141 | const char *smack_cipso_option = SMACK_CIPSO_OPTION; | 141 | struct smack_known smack_cipso_option = { |
| 142 | .smk_known = SMACK_CIPSO_OPTION, | ||
| 143 | .smk_secid = 0, | ||
| 144 | }; | ||
| 142 | 145 | ||
| 143 | /* | 146 | /* |
| 144 | * Values for parsing cipso rules | 147 | * Values for parsing cipso rules |
| @@ -304,6 +307,10 @@ static int smk_perm_from_str(const char *string) | |||
| 304 | case 'L': | 307 | case 'L': |
| 305 | perm |= MAY_LOCK; | 308 | perm |= MAY_LOCK; |
| 306 | break; | 309 | break; |
| 310 | case 'b': | ||
| 311 | case 'B': | ||
| 312 | perm |= MAY_BRINGUP; | ||
| 313 | break; | ||
| 307 | default: | 314 | default: |
| 308 | return perm; | 315 | return perm; |
| 309 | } | 316 | } |
| @@ -335,7 +342,7 @@ static int smk_fill_rule(const char *subject, const char *object, | |||
| 335 | if (rule->smk_subject == NULL) | 342 | if (rule->smk_subject == NULL) |
| 336 | return -EINVAL; | 343 | return -EINVAL; |
| 337 | 344 | ||
| 338 | rule->smk_object = smk_import(object, len); | 345 | rule->smk_object = smk_import_entry(object, len); |
| 339 | if (rule->smk_object == NULL) | 346 | if (rule->smk_object == NULL) |
| 340 | return -EINVAL; | 347 | return -EINVAL; |
| 341 | } else { | 348 | } else { |
| @@ -355,7 +362,7 @@ static int smk_fill_rule(const char *subject, const char *object, | |||
| 355 | kfree(cp); | 362 | kfree(cp); |
| 356 | if (skp == NULL) | 363 | if (skp == NULL) |
| 357 | return -ENOENT; | 364 | return -ENOENT; |
| 358 | rule->smk_object = skp->smk_known; | 365 | rule->smk_object = skp; |
| 359 | } | 366 | } |
| 360 | 367 | ||
| 361 | rule->smk_access1 = smk_perm_from_str(access1); | 368 | rule->smk_access1 = smk_perm_from_str(access1); |
| @@ -594,13 +601,15 @@ static void smk_rule_show(struct seq_file *s, struct smack_rule *srp, int max) | |||
| 594 | * anything you read back. | 601 | * anything you read back. |
| 595 | */ | 602 | */ |
| 596 | if (strlen(srp->smk_subject->smk_known) >= max || | 603 | if (strlen(srp->smk_subject->smk_known) >= max || |
| 597 | strlen(srp->smk_object) >= max) | 604 | strlen(srp->smk_object->smk_known) >= max) |
| 598 | return; | 605 | return; |
| 599 | 606 | ||
| 600 | if (srp->smk_access == 0) | 607 | if (srp->smk_access == 0) |
| 601 | return; | 608 | return; |
| 602 | 609 | ||
| 603 | seq_printf(s, "%s %s", srp->smk_subject->smk_known, srp->smk_object); | 610 | seq_printf(s, "%s %s", |
| 611 | srp->smk_subject->smk_known, | ||
| 612 | srp->smk_object->smk_known); | ||
| 604 | 613 | ||
| 605 | seq_putc(s, ' '); | 614 | seq_putc(s, ' '); |
| 606 | 615 | ||
| @@ -616,6 +625,8 @@ static void smk_rule_show(struct seq_file *s, struct smack_rule *srp, int max) | |||
| 616 | seq_putc(s, 't'); | 625 | seq_putc(s, 't'); |
| 617 | if (srp->smk_access & MAY_LOCK) | 626 | if (srp->smk_access & MAY_LOCK) |
| 618 | seq_putc(s, 'l'); | 627 | seq_putc(s, 'l'); |
| 628 | if (srp->smk_access & MAY_BRINGUP) | ||
| 629 | seq_putc(s, 'b'); | ||
| 619 | 630 | ||
| 620 | seq_putc(s, '\n'); | 631 | seq_putc(s, '\n'); |
| 621 | } | 632 | } |
| @@ -1067,7 +1078,7 @@ static int netlbladdr_seq_show(struct seq_file *s, void *v) | |||
| 1067 | for (maskn = 0; temp_mask; temp_mask <<= 1, maskn++); | 1078 | for (maskn = 0; temp_mask; temp_mask <<= 1, maskn++); |
| 1068 | 1079 | ||
| 1069 | seq_printf(s, "%u.%u.%u.%u/%d %s\n", | 1080 | seq_printf(s, "%u.%u.%u.%u/%d %s\n", |
| 1070 | hp[0], hp[1], hp[2], hp[3], maskn, skp->smk_label); | 1081 | hp[0], hp[1], hp[2], hp[3], maskn, skp->smk_label->smk_known); |
| 1071 | 1082 | ||
| 1072 | return 0; | 1083 | return 0; |
| 1073 | } | 1084 | } |
| @@ -1147,10 +1158,10 @@ static void smk_netlbladdr_insert(struct smk_netlbladdr *new) | |||
| 1147 | static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf, | 1158 | static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf, |
| 1148 | size_t count, loff_t *ppos) | 1159 | size_t count, loff_t *ppos) |
| 1149 | { | 1160 | { |
| 1150 | struct smk_netlbladdr *skp; | 1161 | struct smk_netlbladdr *snp; |
| 1151 | struct sockaddr_in newname; | 1162 | struct sockaddr_in newname; |
| 1152 | char *smack; | 1163 | char *smack; |
| 1153 | char *sp; | 1164 | struct smack_known *skp; |
| 1154 | char *data; | 1165 | char *data; |
| 1155 | char *host = (char *)&newname.sin_addr.s_addr; | 1166 | char *host = (char *)&newname.sin_addr.s_addr; |
| 1156 | int rc; | 1167 | int rc; |
| @@ -1213,15 +1224,15 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf, | |||
| 1213 | * If smack begins with '-', it is an option, don't import it | 1224 | * If smack begins with '-', it is an option, don't import it |
| 1214 | */ | 1225 | */ |
| 1215 | if (smack[0] != '-') { | 1226 | if (smack[0] != '-') { |
| 1216 | sp = smk_import(smack, 0); | 1227 | skp = smk_import_entry(smack, 0); |
| 1217 | if (sp == NULL) { | 1228 | if (skp == NULL) { |
| 1218 | rc = -EINVAL; | 1229 | rc = -EINVAL; |
| 1219 | goto free_out; | 1230 | goto free_out; |
| 1220 | } | 1231 | } |
| 1221 | } else { | 1232 | } else { |
| 1222 | /* check known options */ | 1233 | /* check known options */ |
| 1223 | if (strcmp(smack, smack_cipso_option) == 0) | 1234 | if (strcmp(smack, smack_cipso_option.smk_known) == 0) |
| 1224 | sp = (char *)smack_cipso_option; | 1235 | skp = &smack_cipso_option; |
| 1225 | else { | 1236 | else { |
| 1226 | rc = -EINVAL; | 1237 | rc = -EINVAL; |
| 1227 | goto free_out; | 1238 | goto free_out; |
| @@ -1244,9 +1255,9 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf, | |||
| 1244 | nsa = newname.sin_addr.s_addr; | 1255 | nsa = newname.sin_addr.s_addr; |
| 1245 | /* try to find if the prefix is already in the list */ | 1256 | /* try to find if the prefix is already in the list */ |
| 1246 | found = 0; | 1257 | found = 0; |
| 1247 | list_for_each_entry_rcu(skp, &smk_netlbladdr_list, list) { | 1258 | list_for_each_entry_rcu(snp, &smk_netlbladdr_list, list) { |
| 1248 | if (skp->smk_host.sin_addr.s_addr == nsa && | 1259 | if (snp->smk_host.sin_addr.s_addr == nsa && |
| 1249 | skp->smk_mask.s_addr == mask.s_addr) { | 1260 | snp->smk_mask.s_addr == mask.s_addr) { |
| 1250 | found = 1; | 1261 | found = 1; |
| 1251 | break; | 1262 | break; |
| 1252 | } | 1263 | } |
| @@ -1254,26 +1265,26 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf, | |||
| 1254 | smk_netlabel_audit_set(&audit_info); | 1265 | smk_netlabel_audit_set(&audit_info); |
| 1255 | 1266 | ||
| 1256 | if (found == 0) { | 1267 | if (found == 0) { |
| 1257 | skp = kzalloc(sizeof(*skp), GFP_KERNEL); | 1268 | snp = kzalloc(sizeof(*snp), GFP_KERNEL); |
| 1258 | if (skp == NULL) | 1269 | if (snp == NULL) |
| 1259 | rc = -ENOMEM; | 1270 | rc = -ENOMEM; |
| 1260 | else { | 1271 | else { |
| 1261 | rc = 0; | 1272 | rc = 0; |
| 1262 | skp->smk_host.sin_addr.s_addr = newname.sin_addr.s_addr; | 1273 | snp->smk_host.sin_addr.s_addr = newname.sin_addr.s_addr; |
| 1263 | skp->smk_mask.s_addr = mask.s_addr; | 1274 | snp->smk_mask.s_addr = mask.s_addr; |
| 1264 | skp->smk_label = sp; | 1275 | snp->smk_label = skp; |
| 1265 | smk_netlbladdr_insert(skp); | 1276 | smk_netlbladdr_insert(snp); |
| 1266 | } | 1277 | } |
| 1267 | } else { | 1278 | } else { |
| 1268 | /* we delete the unlabeled entry, only if the previous label | 1279 | /* we delete the unlabeled entry, only if the previous label |
| 1269 | * wasn't the special CIPSO option */ | 1280 | * wasn't the special CIPSO option */ |
| 1270 | if (skp->smk_label != smack_cipso_option) | 1281 | if (snp->smk_label != &smack_cipso_option) |
| 1271 | rc = netlbl_cfg_unlbl_static_del(&init_net, NULL, | 1282 | rc = netlbl_cfg_unlbl_static_del(&init_net, NULL, |
| 1272 | &skp->smk_host.sin_addr, &skp->smk_mask, | 1283 | &snp->smk_host.sin_addr, &snp->smk_mask, |
| 1273 | PF_INET, &audit_info); | 1284 | PF_INET, &audit_info); |
| 1274 | else | 1285 | else |
| 1275 | rc = 0; | 1286 | rc = 0; |
| 1276 | skp->smk_label = sp; | 1287 | snp->smk_label = skp; |
| 1277 | } | 1288 | } |
| 1278 | 1289 | ||
| 1279 | /* | 1290 | /* |
| @@ -1281,10 +1292,10 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf, | |||
| 1281 | * this host so that incoming packets get labeled. | 1292 | * this host so that incoming packets get labeled. |
| 1282 | * but only if we didn't get the special CIPSO option | 1293 | * but only if we didn't get the special CIPSO option |
| 1283 | */ | 1294 | */ |
| 1284 | if (rc == 0 && sp != smack_cipso_option) | 1295 | if (rc == 0 && skp != &smack_cipso_option) |
| 1285 | rc = netlbl_cfg_unlbl_static_add(&init_net, NULL, | 1296 | rc = netlbl_cfg_unlbl_static_add(&init_net, NULL, |
| 1286 | &skp->smk_host.sin_addr, &skp->smk_mask, PF_INET, | 1297 | &snp->smk_host.sin_addr, &snp->smk_mask, PF_INET, |
| 1287 | smack_to_secid(skp->smk_label), &audit_info); | 1298 | snp->smk_label->smk_secid, &audit_info); |
| 1288 | 1299 | ||
| 1289 | if (rc == 0) | 1300 | if (rc == 0) |
| 1290 | rc = count; | 1301 | rc = count; |
| @@ -1677,7 +1688,7 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf, | |||
| 1677 | if (smack_onlycap != NULL && smack_onlycap != skp) | 1688 | if (smack_onlycap != NULL && smack_onlycap != skp) |
| 1678 | return -EPERM; | 1689 | return -EPERM; |
| 1679 | 1690 | ||
| 1680 | data = kzalloc(count, GFP_KERNEL); | 1691 | data = kzalloc(count + 1, GFP_KERNEL); |
| 1681 | if (data == NULL) | 1692 | if (data == NULL) |
| 1682 | return -ENOMEM; | 1693 | return -ENOMEM; |
| 1683 | 1694 | ||
| @@ -1880,7 +1891,10 @@ static ssize_t smk_user_access(struct file *file, const char __user *buf, | |||
| 1880 | else if (res != -ENOENT) | 1891 | else if (res != -ENOENT) |
| 1881 | return -EINVAL; | 1892 | return -EINVAL; |
| 1882 | 1893 | ||
| 1883 | data[0] = res == 0 ? '1' : '0'; | 1894 | /* |
| 1895 | * smk_access() can return a value > 0 in the "bringup" case. | ||
| 1896 | */ | ||
| 1897 | data[0] = res >= 0 ? '1' : '0'; | ||
| 1884 | data[1] = '\0'; | 1898 | data[1] = '\0'; |
| 1885 | 1899 | ||
| 1886 | simple_transaction_set(file, 2); | 1900 | simple_transaction_set(file, 2); |
| @@ -2228,7 +2242,7 @@ static ssize_t smk_write_syslog(struct file *file, const char __user *buf, | |||
| 2228 | if (!smack_privileged(CAP_MAC_ADMIN)) | 2242 | if (!smack_privileged(CAP_MAC_ADMIN)) |
| 2229 | return -EPERM; | 2243 | return -EPERM; |
| 2230 | 2244 | ||
| 2231 | data = kzalloc(count, GFP_KERNEL); | 2245 | data = kzalloc(count + 1, GFP_KERNEL); |
| 2232 | if (data == NULL) | 2246 | if (data == NULL) |
| 2233 | return -ENOMEM; | 2247 | return -ENOMEM; |
| 2234 | 2248 | ||
diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c index a3386d119425..bed745c8b1a3 100644 --- a/security/tomoyo/realpath.c +++ b/security/tomoyo/realpath.c | |||
| @@ -173,7 +173,7 @@ static char *tomoyo_get_local_path(struct dentry *dentry, char * const buffer, | |||
| 173 | * Use filesystem name if filesystem does not support rename() | 173 | * Use filesystem name if filesystem does not support rename() |
| 174 | * operation. | 174 | * operation. |
| 175 | */ | 175 | */ |
| 176 | if (!inode->i_op->rename) | 176 | if (!inode->i_op->rename && !inode->i_op->rename2) |
| 177 | goto prepend_filesystem_name; | 177 | goto prepend_filesystem_name; |
| 178 | } | 178 | } |
| 179 | /* Prepend device name. */ | 179 | /* Prepend device name. */ |
| @@ -282,7 +282,8 @@ char *tomoyo_realpath_from_path(struct path *path) | |||
| 282 | * Get local name for filesystems without rename() operation | 282 | * Get local name for filesystems without rename() operation |
| 283 | * or dentry without vfsmount. | 283 | * or dentry without vfsmount. |
| 284 | */ | 284 | */ |
| 285 | if (!path->mnt || !inode->i_op->rename) | 285 | if (!path->mnt || |
| 286 | (!inode->i_op->rename && !inode->i_op->rename2)) | ||
| 286 | pos = tomoyo_get_local_path(path->dentry, buf, | 287 | pos = tomoyo_get_local_path(path->dentry, buf, |
| 287 | buf_len - 1); | 288 | buf_len - 1); |
| 288 | /* Get absolute name for the rest. */ | 289 | /* Get absolute name for the rest. */ |
