diff options
Diffstat (limited to 'security')
-rw-r--r-- | security/integrity/digsig.c | 2 | ||||
-rw-r--r-- | security/integrity/evm/evm_main.c | 18 | ||||
-rw-r--r-- | security/integrity/iint.c | 3 | ||||
-rw-r--r-- | security/integrity/ima/ima.h | 27 | ||||
-rw-r--r-- | security/integrity/ima/ima_api.c | 20 | ||||
-rw-r--r-- | security/integrity/ima/ima_appraise.c | 8 | ||||
-rw-r--r-- | security/integrity/ima/ima_init.c | 13 | ||||
-rw-r--r-- | security/integrity/ima/ima_main.c | 5 | ||||
-rw-r--r-- | security/integrity/ima/ima_policy.c | 18 | ||||
-rw-r--r-- | security/integrity/ima/ima_template_lib.c | 71 | ||||
-rw-r--r-- | security/integrity/ima/ima_template_lib.h | 22 | ||||
-rw-r--r-- | security/integrity/integrity.h | 2 | ||||
-rw-r--r-- | security/selinux/hooks.c | 77 | ||||
-rw-r--r-- | security/selinux/include/classmap.h | 44 | ||||
-rw-r--r-- | security/selinux/include/security.h | 1 |
15 files changed, 175 insertions, 156 deletions
diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c index 5e3bd72b299a..36fb6b527829 100644 --- a/security/integrity/digsig.c +++ b/security/integrity/digsig.c @@ -85,7 +85,7 @@ int __init integrity_init_keyring(const unsigned int id) return err; } -int __init integrity_load_x509(const unsigned int id, char *path) +int __init integrity_load_x509(const unsigned int id, const char *path) { key_ref_t key; char *data; diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c index 10f994307a04..1334e02ae8f4 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c @@ -296,6 +296,17 @@ static int evm_protect_xattr(struct dentry *dentry, const char *xattr_name, iint = integrity_iint_find(d_backing_inode(dentry)); if (iint && (iint->flags & IMA_NEW_FILE)) return 0; + + /* exception for pseudo filesystems */ + if (dentry->d_inode->i_sb->s_magic == TMPFS_MAGIC + || dentry->d_inode->i_sb->s_magic == SYSFS_MAGIC) + return 0; + + integrity_audit_msg(AUDIT_INTEGRITY_METADATA, + dentry->d_inode, dentry->d_name.name, + "update_metadata", + integrity_status_msg[evm_status], + -EPERM, 0); } out: if (evm_status != INTEGRITY_PASS) @@ -376,17 +387,16 @@ void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name, * @xattr_name: pointer to the affected extended attribute name * * Update the HMAC stored in 'security.evm' to reflect removal of the xattr. + * + * No need to take the i_mutex lock here, as this function is called from + * vfs_removexattr() which takes the i_mutex. */ void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name) { - struct inode *inode = d_backing_inode(dentry); - if (!evm_initialized || !evm_protected_xattr(xattr_name)) return; - mutex_lock(&inode->i_mutex); evm_update_evmxattr(dentry, xattr_name, NULL, 0); - mutex_unlock(&inode->i_mutex); } /** diff --git a/security/integrity/iint.c b/security/integrity/iint.c index dbb6d141c3db..3d2f5b45c8cb 100644 --- a/security/integrity/iint.c +++ b/security/integrity/iint.c @@ -213,6 +213,9 @@ int __init integrity_read_file(const char *path, char **data) char *buf; int rc = -EINVAL; + if (!path || !*path) + return -EINVAL; + file = filp_open(path, O_RDONLY, 0); if (IS_ERR(file)) { rc = PTR_ERR(file); diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 8ee997dff139..c996f7edff3a 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -52,6 +52,16 @@ extern int ima_used_chip; extern int ima_hash_algo; extern int ima_appraise; +/* IMA event related data */ +struct ima_event_data { + struct integrity_iint_cache *iint; + struct file *file; + const unsigned char *filename; + struct evm_ima_xattr_data *xattr_value; + int xattr_len; + const char *violation; +}; + /* IMA template field data definition */ struct ima_field_data { u8 *data; @@ -61,12 +71,10 @@ struct ima_field_data { /* IMA template field definition */ struct ima_template_field { const char field_id[IMA_TEMPLATE_FIELD_ID_MAX_LEN]; - int (*field_init) (struct integrity_iint_cache *iint, struct file *file, - const unsigned char *filename, - struct evm_ima_xattr_data *xattr_value, - int xattr_len, struct ima_field_data *field_data); - void (*field_show) (struct seq_file *m, enum ima_show_type show, - struct ima_field_data *field_data); + int (*field_init)(struct ima_event_data *event_data, + struct ima_field_data *field_data); + void (*field_show)(struct seq_file *m, enum ima_show_type show, + struct ima_field_data *field_data); }; /* IMA template descriptor definition */ @@ -103,6 +111,7 @@ int ima_calc_field_array_hash(struct ima_field_data *field_data, struct ima_digest_data *hash); int __init ima_calc_boot_aggregate(struct ima_digest_data *hash); void ima_add_violation(struct file *file, const unsigned char *filename, + struct integrity_iint_cache *iint, const char *op, const char *cause); int ima_init_crypto(void); void ima_putc(struct seq_file *m, void *data, int datalen); @@ -140,10 +149,8 @@ void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file, int xattr_len); void ima_audit_measurement(struct integrity_iint_cache *iint, const unsigned char *filename); -int ima_alloc_init_template(struct integrity_iint_cache *iint, - struct file *file, const unsigned char *filename, - struct evm_ima_xattr_data *xattr_value, - int xattr_len, struct ima_template_entry **entry); +int ima_alloc_init_template(struct ima_event_data *event_data, + struct ima_template_entry **entry); int ima_store_template(struct ima_template_entry *entry, int violation, struct inode *inode, const unsigned char *filename); void ima_free_template_entry(struct ima_template_entry *entry); diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index b8a27c5052d4..1d950fbb2aec 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c @@ -37,10 +37,8 @@ void ima_free_template_entry(struct ima_template_entry *entry) /* * ima_alloc_init_template - create and initialize a new template entry */ -int ima_alloc_init_template(struct integrity_iint_cache *iint, - struct file *file, const unsigned char *filename, - struct evm_ima_xattr_data *xattr_value, - int xattr_len, struct ima_template_entry **entry) +int ima_alloc_init_template(struct ima_event_data *event_data, + struct ima_template_entry **entry) { struct ima_template_desc *template_desc = ima_template_desc_current(); int i, result = 0; @@ -55,8 +53,7 @@ int ima_alloc_init_template(struct integrity_iint_cache *iint, struct ima_template_field *field = template_desc->fields[i]; u32 len; - result = field->field_init(iint, file, filename, - xattr_value, xattr_len, + result = field->field_init(event_data, &((*entry)->template_data[i])); if (result != 0) goto out; @@ -129,18 +126,20 @@ int ima_store_template(struct ima_template_entry *entry, * value is invalidated. */ void ima_add_violation(struct file *file, const unsigned char *filename, + struct integrity_iint_cache *iint, const char *op, const char *cause) { struct ima_template_entry *entry; struct inode *inode = file_inode(file); + struct ima_event_data event_data = {iint, file, filename, NULL, 0, + cause}; int violation = 1; int result; /* can overflow, only indicator */ atomic_long_inc(&ima_htable.violations); - result = ima_alloc_init_template(NULL, file, filename, - NULL, 0, &entry); + result = ima_alloc_init_template(&event_data, &entry); if (result < 0) { result = -ENOMEM; goto err_out; @@ -267,13 +266,14 @@ void ima_store_measurement(struct integrity_iint_cache *iint, int result = -ENOMEM; struct inode *inode = file_inode(file); struct ima_template_entry *entry; + struct ima_event_data event_data = {iint, file, filename, xattr_value, + xattr_len, NULL}; int violation = 0; if (iint->flags & IMA_MEASURED) return; - result = ima_alloc_init_template(iint, file, filename, - xattr_value, xattr_len, &entry); + result = ima_alloc_init_template(&event_data, &entry); if (result < 0) { integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename, op, audit_cause, result, 0); diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index 4df493e4b3c9..1873b5536f80 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -378,10 +378,14 @@ int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name, result = ima_protect_xattr(dentry, xattr_name, xattr_value, xattr_value_len); if (result == 1) { + bool digsig; + if (!xattr_value_len || (xvalue->type >= IMA_XATTR_LAST)) return -EINVAL; - ima_reset_appraise_flags(d_backing_inode(dentry), - (xvalue->type == EVM_IMA_XATTR_DIGSIG) ? 1 : 0); + digsig = (xvalue->type == EVM_IMA_XATTR_DIGSIG); + if (!digsig && (ima_appraise & IMA_APPRAISE_ENFORCE)) + return -EPERM; + ima_reset_appraise_flags(d_backing_inode(dentry), digsig); result = 0; } return result; diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index 5e4c29d174ee..e600cadd231c 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -24,12 +24,6 @@ #include <crypto/hash_info.h> #include "ima.h" -#ifdef CONFIG_IMA_X509_PATH -#define IMA_X509_PATH CONFIG_IMA_X509_PATH -#else -#define IMA_X509_PATH "/etc/keys/x509_ima.der" -#endif - /* name for boot aggregate entry */ static const char *boot_aggregate_name = "boot_aggregate"; int ima_used_chip; @@ -55,6 +49,8 @@ static int __init ima_add_boot_aggregate(void) const char *audit_cause = "ENOMEM"; struct ima_template_entry *entry; struct integrity_iint_cache tmp_iint, *iint = &tmp_iint; + struct ima_event_data event_data = {iint, NULL, boot_aggregate_name, + NULL, 0, NULL}; int result = -ENOMEM; int violation = 0; struct { @@ -76,8 +72,7 @@ static int __init ima_add_boot_aggregate(void) } } - result = ima_alloc_init_template(iint, NULL, boot_aggregate_name, - NULL, 0, &entry); + result = ima_alloc_init_template(&event_data, &entry); if (result < 0) { audit_cause = "alloc_entry"; goto err_out; @@ -103,7 +98,7 @@ void __init ima_load_x509(void) int unset_flags = ima_policy_flag & IMA_APPRAISE; ima_policy_flag &= ~unset_flags; - integrity_load_x509(INTEGRITY_KEYRING_IMA, IMA_X509_PATH); + integrity_load_x509(INTEGRITY_KEYRING_IMA, CONFIG_IMA_X509_PATH); ima_policy_flag |= unset_flags; } #endif diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index eeee00dce729..c21f09bf8b99 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -106,9 +106,10 @@ static void ima_rdwr_violation_check(struct file *file, *pathname = ima_d_path(&file->f_path, pathbuf); if (send_tomtou) - ima_add_violation(file, *pathname, "invalid_pcr", "ToMToU"); + ima_add_violation(file, *pathname, iint, + "invalid_pcr", "ToMToU"); if (send_writers) - ima_add_violation(file, *pathname, + ima_add_violation(file, *pathname, iint, "invalid_pcr", "open_writers"); } diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index d1eefb9d65fb..f2421f7fa3c8 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -79,6 +79,9 @@ static struct ima_rule_entry default_rules[] = { {.action = DONT_MEASURE, .fsmagic = BINFMTFS_MAGIC, .flags = IMA_FSMAGIC}, {.action = DONT_MEASURE, .fsmagic = SECURITYFS_MAGIC, .flags = IMA_FSMAGIC}, {.action = DONT_MEASURE, .fsmagic = SELINUX_MAGIC, .flags = IMA_FSMAGIC}, + {.action = DONT_MEASURE, .fsmagic = CGROUP_SUPER_MAGIC, + .flags = IMA_FSMAGIC}, + {.action = DONT_MEASURE, .fsmagic = NSFS_MAGIC, .flags = IMA_FSMAGIC}, {.action = MEASURE, .func = MMAP_CHECK, .mask = MAY_EXEC, .flags = IMA_FUNC | IMA_MASK}, {.action = MEASURE, .func = BPRM_CHECK, .mask = MAY_EXEC, @@ -99,6 +102,7 @@ static struct ima_rule_entry default_appraise_rules[] = { {.action = DONT_APPRAISE, .fsmagic = BINFMTFS_MAGIC, .flags = IMA_FSMAGIC}, {.action = DONT_APPRAISE, .fsmagic = SECURITYFS_MAGIC, .flags = IMA_FSMAGIC}, {.action = DONT_APPRAISE, .fsmagic = SELINUX_MAGIC, .flags = IMA_FSMAGIC}, + {.action = DONT_APPRAISE, .fsmagic = NSFS_MAGIC, .flags = IMA_FSMAGIC}, {.action = DONT_APPRAISE, .fsmagic = CGROUP_SUPER_MAGIC, .flags = IMA_FSMAGIC}, #ifndef CONFIG_IMA_APPRAISE_SIGNED_INIT {.action = APPRAISE, .fowner = GLOBAL_ROOT_UID, .flags = IMA_FOWNER}, @@ -338,16 +342,12 @@ void __init ima_init_policy(void) appraise_entries = ima_use_appraise_tcb ? ARRAY_SIZE(default_appraise_rules) : 0; - for (i = 0; i < measure_entries + appraise_entries; i++) { - if (i < measure_entries) - list_add_tail(&default_rules[i].list, - &ima_default_rules); - else { - int j = i - measure_entries; + for (i = 0; i < measure_entries; i++) + list_add_tail(&default_rules[i].list, &ima_default_rules); - list_add_tail(&default_appraise_rules[j].list, - &ima_default_rules); - } + for (i = 0; i < appraise_entries; i++) { + list_add_tail(&default_appraise_rules[i].list, + &ima_default_rules); } ima_rules = &ima_default_rules; diff --git a/security/integrity/ima/ima_template_lib.c b/security/integrity/ima/ima_template_lib.c index bcfc36cbde6a..de0ce4fbdf69 100644 --- a/security/integrity/ima/ima_template_lib.c +++ b/security/integrity/ima/ima_template_lib.c @@ -195,9 +195,7 @@ static int ima_eventdigest_init_common(u8 *digest, u32 digestsize, u8 hash_algo, /* * This function writes the digest of an event (with size limit). */ -int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file, - const unsigned char *filename, - struct evm_ima_xattr_data *xattr_value, int xattr_len, +int ima_eventdigest_init(struct ima_event_data *event_data, struct ima_field_data *field_data) { struct { @@ -211,25 +209,25 @@ int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file, memset(&hash, 0, sizeof(hash)); - if (!iint) /* recording a violation. */ + if (event_data->violation) /* recording a violation. */ goto out; - if (ima_template_hash_algo_allowed(iint->ima_hash->algo)) { - cur_digest = iint->ima_hash->digest; - cur_digestsize = iint->ima_hash->length; + if (ima_template_hash_algo_allowed(event_data->iint->ima_hash->algo)) { + cur_digest = event_data->iint->ima_hash->digest; + cur_digestsize = event_data->iint->ima_hash->length; goto out; } - if (!file) /* missing info to re-calculate the digest */ + if (!event_data->file) /* missing info to re-calculate the digest */ return -EINVAL; - inode = file_inode(file); + inode = file_inode(event_data->file); hash.hdr.algo = ima_template_hash_algo_allowed(ima_hash_algo) ? ima_hash_algo : HASH_ALGO_SHA1; - result = ima_calc_file_hash(file, &hash.hdr); + result = ima_calc_file_hash(event_data->file, &hash.hdr); if (result) { integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, - filename, "collect_data", + event_data->filename, "collect_data", "failed", result, 0); return result; } @@ -243,48 +241,43 @@ out: /* * This function writes the digest of an event (without size limit). */ -int ima_eventdigest_ng_init(struct integrity_iint_cache *iint, - struct file *file, const unsigned char *filename, - struct evm_ima_xattr_data *xattr_value, - int xattr_len, struct ima_field_data *field_data) +int ima_eventdigest_ng_init(struct ima_event_data *event_data, + struct ima_field_data *field_data) { u8 *cur_digest = NULL, hash_algo = HASH_ALGO_SHA1; u32 cur_digestsize = 0; - /* If iint is NULL, we are recording a violation. */ - if (!iint) + if (event_data->violation) /* recording a violation. */ goto out; - cur_digest = iint->ima_hash->digest; - cur_digestsize = iint->ima_hash->length; + cur_digest = event_data->iint->ima_hash->digest; + cur_digestsize = event_data->iint->ima_hash->length; - hash_algo = iint->ima_hash->algo; + hash_algo = event_data->iint->ima_hash->algo; out: return ima_eventdigest_init_common(cur_digest, cur_digestsize, hash_algo, field_data); } -static int ima_eventname_init_common(struct integrity_iint_cache *iint, - struct file *file, - const unsigned char *filename, +static int ima_eventname_init_common(struct ima_event_data *event_data, struct ima_field_data *field_data, bool size_limit) { const char *cur_filename = NULL; u32 cur_filename_len = 0; - BUG_ON(filename == NULL && file == NULL); + BUG_ON(event_data->filename == NULL && event_data->file == NULL); - if (filename) { - cur_filename = filename; - cur_filename_len = strlen(filename); + if (event_data->filename) { + cur_filename = event_data->filename; + cur_filename_len = strlen(event_data->filename); if (!size_limit || cur_filename_len <= IMA_EVENT_NAME_LEN_MAX) goto out; } - if (file) { - cur_filename = file->f_path.dentry->d_name.name; + if (event_data->file) { + cur_filename = event_data->file->f_path.dentry->d_name.name; cur_filename_len = strlen(cur_filename); } else /* @@ -300,36 +293,30 @@ out: /* * This function writes the name of an event (with size limit). */ -int ima_eventname_init(struct integrity_iint_cache *iint, struct file *file, - const unsigned char *filename, - struct evm_ima_xattr_data *xattr_value, int xattr_len, +int ima_eventname_init(struct ima_event_data *event_data, struct ima_field_data *field_data) { - return ima_eventname_init_common(iint, file, filename, - field_data, true); + return ima_eventname_init_common(event_data, field_data, true); } /* * This function writes the name of an event (without size limit). */ -int ima_eventname_ng_init(struct integrity_iint_cache *iint, struct file *file, - const unsigned char *filename, - struct evm_ima_xattr_data *xattr_value, int xattr_len, +int ima_eventname_ng_init(struct ima_event_data *event_data, struct ima_field_data *field_data) { - return ima_eventname_init_common(iint, file, filename, - field_data, false); + return ima_eventname_init_common(event_data, field_data, false); } /* * ima_eventsig_init - include the file signature as part of the template data */ -int ima_eventsig_init(struct integrity_iint_cache *iint, struct file *file, - const unsigned char *filename, - struct evm_ima_xattr_data *xattr_value, int xattr_len, +int ima_eventsig_init(struct ima_event_data *event_data, struct ima_field_data *field_data) { enum data_formats fmt = DATA_FMT_HEX; + struct evm_ima_xattr_data *xattr_value = event_data->xattr_value; + int xattr_len = event_data->xattr_len; int rc = 0; if ((!xattr_value) || (xattr_value->type != EVM_IMA_XATTR_DIGSIG)) diff --git a/security/integrity/ima/ima_template_lib.h b/security/integrity/ima/ima_template_lib.h index 63f6b52cb1c2..c344530c1d69 100644 --- a/security/integrity/ima/ima_template_lib.h +++ b/security/integrity/ima/ima_template_lib.h @@ -26,24 +26,14 @@ void ima_show_template_string(struct seq_file *m, enum ima_show_type show, struct ima_field_data *field_data); void ima_show_template_sig(struct seq_file *m, enum ima_show_type show, struct ima_field_data *field_data); -int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file, - const unsigned char *filename, - struct evm_ima_xattr_data *xattr_value, int xattr_len, +int ima_eventdigest_init(struct ima_event_data *event_data, struct ima_field_data *field_data); -int ima_eventname_init(struct integrity_iint_cache *iint, struct file *file, - const unsigned char *filename, - struct evm_ima_xattr_data *xattr_value, int xattr_len, +int ima_eventname_init(struct ima_event_data *event_data, struct ima_field_data *field_data); -int ima_eventdigest_ng_init(struct integrity_iint_cache *iint, - struct file *file, const unsigned char *filename, - struct evm_ima_xattr_data *xattr_value, - int xattr_len, struct ima_field_data *field_data); -int ima_eventname_ng_init(struct integrity_iint_cache *iint, struct file *file, - const unsigned char *filename, - struct evm_ima_xattr_data *xattr_value, int xattr_len, +int ima_eventdigest_ng_init(struct ima_event_data *event_data, + struct ima_field_data *field_data); +int ima_eventname_ng_init(struct ima_event_data *event_data, struct ima_field_data *field_data); -int ima_eventsig_init(struct integrity_iint_cache *iint, struct file *file, - const unsigned char *filename, - struct evm_ima_xattr_data *xattr_value, int xattr_len, +int ima_eventsig_init(struct ima_event_data *event_data, struct ima_field_data *field_data); #endif /* __LINUX_IMA_TEMPLATE_LIB_H */ diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h index 0fc9519fefa9..9c6168709d3b 100644 --- a/security/integrity/integrity.h +++ b/security/integrity/integrity.h @@ -135,7 +135,7 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, const char *digest, int digestlen); int __init integrity_init_keyring(const unsigned int id); -int __init integrity_load_x509(const unsigned int id, char *path); +int __init integrity_load_x509(const unsigned int id, const char *path); #else static inline int integrity_digsig_verify(const unsigned int id, diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 06c9dd962c3c..312537d48050 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -403,6 +403,7 @@ static int selinux_is_sblabel_mnt(struct super_block *sb) return sbsec->behavior == SECURITY_FS_USE_XATTR || sbsec->behavior == SECURITY_FS_USE_TRANS || sbsec->behavior == SECURITY_FS_USE_TASK || + sbsec->behavior == SECURITY_FS_USE_NATIVE || /* Special handling. Genfs but also in-core setxattr handler */ !strcmp(sb->s_type->name, "sysfs") || !strcmp(sb->s_type->name, "pstore") || @@ -724,7 +725,12 @@ static int selinux_set_mnt_opts(struct super_block *sb, } if (strcmp(sb->s_type->name, "proc") == 0) - sbsec->flags |= SE_SBPROC; + sbsec->flags |= SE_SBPROC | SE_SBGENFS; + + if (!strcmp(sb->s_type->name, "debugfs") || + !strcmp(sb->s_type->name, "sysfs") || + !strcmp(sb->s_type->name, "pstore")) + sbsec->flags |= SE_SBGENFS; if (!sbsec->behavior) { /* @@ -1188,8 +1194,6 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc switch (protocol) { case NETLINK_ROUTE: return SECCLASS_NETLINK_ROUTE_SOCKET; - case NETLINK_FIREWALL: - return SECCLASS_NETLINK_FIREWALL_SOCKET; case NETLINK_SOCK_DIAG: return SECCLASS_NETLINK_TCPDIAG_SOCKET; case NETLINK_NFLOG: @@ -1198,14 +1202,28 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc return SECCLASS_NETLINK_XFRM_SOCKET; case NETLINK_SELINUX: return SECCLASS_NETLINK_SELINUX_SOCKET; + case NETLINK_ISCSI: + return SECCLASS_NETLINK_ISCSI_SOCKET; case NETLINK_AUDIT: return SECCLASS_NETLINK_AUDIT_SOCKET; - case NETLINK_IP6_FW: - return SECCLASS_NETLINK_IP6FW_SOCKET; + case NETLINK_FIB_LOOKUP: + return SECCLASS_NETLINK_FIB_LOOKUP_SOCKET; + case NETLINK_CONNECTOR: + return SECCLASS_NETLINK_CONNECTOR_SOCKET; + case NETLINK_NETFILTER: + return SECCLASS_NETLINK_NETFILTER_SOCKET; case NETLINK_DNRTMSG: return SECCLASS_NETLINK_DNRT_SOCKET; case NETLINK_KOBJECT_UEVENT: return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET; + case NETLINK_GENERIC: + return SECCLASS_NETLINK_GENERIC_SOCKET; + case NETLINK_SCSITRANSPORT: + return SECCLASS_NETLINK_SCSITRANSPORT_SOCKET; + case NETLINK_RDMA: + return SECCLASS_NETLINK_RDMA_SOCKET; + case NETLINK_CRYPTO: + return SECCLASS_NETLINK_CRYPTO_SOCKET; default: return SECCLASS_NETLINK_SOCKET; } @@ -1220,12 +1238,13 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc return SECCLASS_SOCKET; } -#ifdef CONFIG_PROC_FS -static int selinux_proc_get_sid(struct dentry *dentry, - u16 tclass, - u32 *sid) +static int selinux_genfs_get_sid(struct dentry *dentry, + u16 tclass, + u16 flags, + u32 *sid) { int rc; + struct super_block *sb = dentry->d_inode->i_sb; char *buffer, *path; buffer = (char *)__get_free_page(GFP_KERNEL); @@ -1236,26 +1255,20 @@ static int selinux_proc_get_sid(struct dentry *dentry, if (IS_ERR(path)) rc = PTR_ERR(path); else { - /* each process gets a /proc/PID/ entry. Strip off the - * PID part to get a valid selinux labeling. - * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */ - while (path[1] >= '0' && path[1] <= '9') { - path[1] = '/'; - path++; + if (flags & SE_SBPROC) { + /* each process gets a /proc/PID/ entry. Strip off the + * PID part to get a valid selinux labeling. + * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */ + while (path[1] >= '0' && path[1] <= '9') { + path[1] = '/'; + path++; + } } - rc = security_genfs_sid("proc", path, tclass, sid); + rc = security_genfs_sid(sb->s_type->name, path, tclass, sid); } free_page((unsigned long)buffer); return rc; } -#else -static int selinux_proc_get_sid(struct dentry *dentry, - u16 tclass, - u32 *sid) -{ - return -EINVAL; -} -#endif /* The inode's security attributes must be initialized before first use. */ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry) @@ -1412,7 +1425,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent /* Default to the fs superblock SID. */ isec->sid = sbsec->sid; - if ((sbsec->flags & SE_SBPROC) && !S_ISLNK(inode->i_mode)) { + if ((sbsec->flags & SE_SBGENFS) && !S_ISLNK(inode->i_mode)) { /* We must have a dentry to determine the label on * procfs inodes */ if (opt_dentry) @@ -1435,7 +1448,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent if (!dentry) goto out_unlock; isec->sclass = inode_mode_to_security_class(inode->i_mode); - rc = selinux_proc_get_sid(dentry, isec->sclass, &sid); + rc = selinux_genfs_get_sid(dentry, isec->sclass, + sbsec->flags, &sid); dput(dentry); if (rc) goto out_unlock; @@ -2416,10 +2430,12 @@ static void selinux_bprm_committed_creds(struct linux_binprm *bprm) for (i = 0; i < 3; i++) do_setitimer(i, &itimer, NULL); spin_lock_irq(¤t->sighand->siglock); - if (!(current->signal->flags & SIGNAL_GROUP_EXIT)) { - __flush_signals(current); + if (!fatal_signal_pending(current)) { + flush_sigqueue(¤t->pending); + flush_sigqueue(¤t->signal->shared_pending); flush_signal_handlers(current, 1); sigemptyset(¤t->blocked); + recalc_sigpending(); } spin_unlock_irq(¤t->sighand->siglock); } @@ -4713,8 +4729,9 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) if (err == -EINVAL) { printk(KERN_WARNING "SELinux: unrecognized netlink message:" - " protocol=%hu nlmsg_type=%hu sclass=%hu\n", - sk->sk_protocol, nlh->nlmsg_type, sksec->sclass); + " protocol=%hu nlmsg_type=%hu sclass=%s\n", + sk->sk_protocol, nlh->nlmsg_type, + secclass_map[sksec->sclass - 1].name); if (!selinux_enforcing || security_get_allow_unknown()) err = 0; } diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h index eccd61b3de8a..5a4eef59aeff 100644 --- a/security/selinux/include/classmap.h +++ b/security/selinux/include/classmap.h @@ -2,12 +2,12 @@ "getattr", "setattr", "lock", "relabelfrom", "relabelto", "append" #define COMMON_FILE_PERMS COMMON_FILE_SOCK_PERMS, "unlink", "link", \ - "rename", "execute", "swapon", "quotaon", "mounton", "audit_access", \ + "rename", "execute", "quotaon", "mounton", "audit_access", \ "open", "execmod" #define COMMON_SOCK_PERMS COMMON_FILE_SOCK_PERMS, "bind", "connect", \ "listen", "accept", "getopt", "setopt", "shutdown", "recvfrom", \ - "sendto", "recv_msg", "send_msg", "name_bind" + "sendto", "name_bind" #define COMMON_IPC_PERMS "create", "destroy", "getattr", "setattr", "read", \ "write", "associate", "unix_read", "unix_write" @@ -44,7 +44,7 @@ struct security_class_mapping secclass_map[] = { "audit_control", "setfcap", NULL } }, { "filesystem", { "mount", "remount", "unmount", "getattr", - "relabelfrom", "relabelto", "transition", "associate", "quotamod", + "relabelfrom", "relabelto", "associate", "quotamod", "quotaget", NULL } }, { "file", { COMMON_FILE_PERMS, @@ -67,7 +67,7 @@ struct security_class_mapping secclass_map[] = { { COMMON_SOCK_PERMS, NULL } }, { "tcp_socket", { COMMON_SOCK_PERMS, - "connectto", "newconn", "acceptfrom", "node_bind", "name_connect", + "node_bind", "name_connect", NULL } }, { "udp_socket", { COMMON_SOCK_PERMS, @@ -76,13 +76,9 @@ struct security_class_mapping secclass_map[] = { { COMMON_SOCK_PERMS, "node_bind", NULL } }, { "node", - { "tcp_recv", "tcp_send", "udp_recv", "udp_send", - "rawip_recv", "rawip_send", "enforce_dest", - "dccp_recv", "dccp_send", "recvfrom", "sendto", NULL } }, + { "recvfrom", "sendto", NULL } }, { "netif", - { "tcp_recv", "tcp_send", "udp_recv", "udp_send", - "rawip_recv", "rawip_send", "dccp_recv", "dccp_send", - "ingress", "egress", NULL } }, + { "ingress", "egress", NULL } }, { "netlink_socket", { COMMON_SOCK_PERMS, NULL } }, { "packet_socket", @@ -90,11 +86,9 @@ struct security_class_mapping secclass_map[] = { { "key_socket", { COMMON_SOCK_PERMS, NULL } }, { "unix_stream_socket", - { COMMON_SOCK_PERMS, "connectto", "newconn", "acceptfrom", NULL - } }, + { COMMON_SOCK_PERMS, "connectto", NULL } }, { "unix_dgram_socket", - { COMMON_SOCK_PERMS, NULL - } }, + { COMMON_SOCK_PERMS, NULL } }, { "sem", { COMMON_IPC_PERMS, NULL } }, { "msg", { "send", "receive", NULL } }, @@ -107,9 +101,6 @@ struct security_class_mapping secclass_map[] = { { "netlink_route_socket", { COMMON_SOCK_PERMS, "nlmsg_read", "nlmsg_write", NULL } }, - { "netlink_firewall_socket", - { COMMON_SOCK_PERMS, - "nlmsg_read", "nlmsg_write", NULL } }, { "netlink_tcpdiag_socket", { COMMON_SOCK_PERMS, "nlmsg_read", "nlmsg_write", NULL } }, @@ -120,19 +111,32 @@ struct security_class_mapping secclass_map[] = { "nlmsg_read", "nlmsg_write", NULL } }, { "netlink_selinux_socket", { COMMON_SOCK_PERMS, NULL } }, + { "netlink_iscsi_socket", + { COMMON_SOCK_PERMS, NULL } }, { "netlink_audit_socket", { COMMON_SOCK_PERMS, "nlmsg_read", "nlmsg_write", "nlmsg_relay", "nlmsg_readpriv", "nlmsg_tty_audit", NULL } }, - { "netlink_ip6fw_socket", - { COMMON_SOCK_PERMS, - "nlmsg_read", "nlmsg_write", NULL } }, + { "netlink_fib_lookup_socket", + { COMMON_SOCK_PERMS, NULL } }, + { "netlink_connector_socket", + { COMMON_SOCK_PERMS, NULL } }, + { "netlink_netfilter_socket", + { COMMON_SOCK_PERMS, NULL } }, { "netlink_dnrt_socket", { COMMON_SOCK_PERMS, NULL } }, { "association", { "sendto", "recvfrom", "setcontext", "polmatch", NULL } }, { "netlink_kobject_uevent_socket", { COMMON_SOCK_PERMS, NULL } }, + { "netlink_generic_socket", + { COMMON_SOCK_PERMS, NULL } }, + { "netlink_scsitransport_socket", + { COMMON_SOCK_PERMS, NULL } }, + { "netlink_rdma_socket", + { COMMON_SOCK_PERMS, NULL } }, + { "netlink_crypto_socket", + { COMMON_SOCK_PERMS, NULL } }, { "appletalk_socket", { COMMON_SOCK_PERMS, NULL } }, { "packet", diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index d1e0b239b602..36993ad1c067 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -56,6 +56,7 @@ /* Non-mount related flags */ #define SE_SBINITIALIZED 0x0100 #define SE_SBPROC 0x0200 +#define SE_SBGENFS 0x0400 #define CONTEXT_STR "context=" #define FSCONTEXT_STR "fscontext=" |