diff options
Diffstat (limited to 'security')
33 files changed, 215 insertions, 159 deletions
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c index 5fd4a64e431f..f95c6bfa8b8e 100644 --- a/security/apparmor/apparmorfs.c +++ b/security/apparmor/apparmorfs.c @@ -2046,9 +2046,6 @@ fail2: return error; } - -#define list_entry_is_head(pos, head, member) (&pos->member == (head)) - /** * __next_ns - find the next namespace to list * @root: root namespace to stop search at (NOT NULL) diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h index 2431c011800d..aadb4b29fb66 100644 --- a/security/apparmor/include/net.h +++ b/security/apparmor/include/net.h @@ -107,6 +107,6 @@ int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request, struct socket *sock); int apparmor_secmark_check(struct aa_label *label, char *op, u32 request, - u32 secid, struct sock *sk); + u32 secid, const struct sock *sk); #endif /* __AA_NET_H */ diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index ffeaee5ed968..1b0aba8eb723 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -1147,7 +1147,7 @@ static void apparmor_sock_graft(struct sock *sk, struct socket *parent) } #ifdef CONFIG_NETWORK_SECMARK -static int apparmor_inet_conn_request(struct sock *sk, struct sk_buff *skb, +static int apparmor_inet_conn_request(const struct sock *sk, struct sk_buff *skb, struct request_sock *req) { struct aa_sk_ctx *ctx = SK_CTX(sk); diff --git a/security/apparmor/net.c b/security/apparmor/net.c index fa0e85568450..e0c1b50d6edd 100644 --- a/security/apparmor/net.c +++ b/security/apparmor/net.c @@ -211,7 +211,7 @@ static int apparmor_secmark_init(struct aa_secmark *secmark) } static int aa_secmark_perm(struct aa_profile *profile, u32 request, u32 secid, - struct common_audit_data *sa, struct sock *sk) + struct common_audit_data *sa) { int i, ret; struct aa_perms perms = { }; @@ -244,13 +244,13 @@ static int aa_secmark_perm(struct aa_profile *profile, u32 request, u32 secid, } int apparmor_secmark_check(struct aa_label *label, char *op, u32 request, - u32 secid, struct sock *sk) + u32 secid, const struct sock *sk) { struct aa_profile *profile; DEFINE_AUDIT_SK(sa, op, sk); return fn_for_each_confined(label, profile, aa_secmark_perm(profile, request, secid, - &sa, sk)); + &sa)); } #endif diff --git a/security/bpf/hooks.c b/security/bpf/hooks.c index 788667d582ae..e5971fa74fd7 100644 --- a/security/bpf/hooks.c +++ b/security/bpf/hooks.c @@ -12,6 +12,7 @@ static struct security_hook_list bpf_lsm_hooks[] __lsm_ro_after_init = { #include <linux/lsm_hook_defs.h> #undef LSM_HOOK LSM_HOOK_INIT(inode_free_security, bpf_inode_storage_free), + LSM_HOOK_INIT(task_free, bpf_task_storage_free), }; static int __init bpf_lsm_init(void) @@ -23,6 +24,7 @@ static int __init bpf_lsm_init(void) struct lsm_blob_sizes bpf_lsm_blob_sizes __lsm_ro_after_init = { .lbs_inode = sizeof(struct bpf_storage_blob), + .lbs_task = sizeof(struct bpf_storage_blob), }; DEFINE_LSM(bpf) = { diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 38043074ce5e..8e8b1e3cb847 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -101,7 +101,7 @@ struct ima_template_entry { struct tpm_digest *digests; struct ima_template_desc *template_desc; /* template descriptor */ u32 template_data_len; - struct ima_field_data template_data[0]; /* template related data */ + struct ima_field_data template_data[]; /* template related data */ }; struct ima_queue_entry { @@ -156,6 +156,7 @@ int template_desc_init_fields(const char *template_fmt, const struct ima_template_field ***fields, int *num_fields); struct ima_template_desc *ima_template_desc_current(void); +struct ima_template_desc *ima_template_desc_buf(void); struct ima_template_desc *lookup_template_desc(const char *name); bool ima_template_has_modsig(const struct ima_template_desc *ima_template); int ima_restore_measurement_entry(struct ima_template_entry *entry); diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index 3dd8c2e4314e..8361941ee0a1 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -5,6 +5,7 @@ * Author: * Mimi Zohar <zohar@us.ibm.com> */ +#include <linux/module.h> #include <linux/init.h> #include <linux/file.h> #include <linux/fs.h> @@ -16,12 +17,19 @@ #include "ima.h" -static int __init default_appraise_setup(char *str) -{ #ifdef CONFIG_IMA_APPRAISE_BOOTPARAM +static char *ima_appraise_cmdline_default __initdata; +core_param(ima_appraise, ima_appraise_cmdline_default, charp, 0); + +void __init ima_appraise_parse_cmdline(void) +{ + const char *str = ima_appraise_cmdline_default; bool sb_state = arch_ima_get_secureboot(); int appraisal_state = ima_appraise; + if (!str) + return; + if (strncmp(str, "off", 3) == 0) appraisal_state = 0; else if (strncmp(str, "log", 3) == 0) @@ -42,11 +50,8 @@ static int __init default_appraise_setup(char *str) } else { ima_appraise = appraisal_state; } -#endif - return 1; } - -__setup("ima_appraise=", default_appraise_setup); +#endif /* * is_ima_appraise_enabled - return appraise status diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c index 21989fa0c107..f6a7e9643b54 100644 --- a/security/integrity/ima/ima_crypto.c +++ b/security/integrity/ima/ima_crypto.c @@ -537,7 +537,7 @@ int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash) loff_t i_size; int rc; struct file *f = file; - bool new_file_instance = false, modified_mode = false; + bool new_file_instance = false; /* * For consistency, fail file's opened with the O_DIRECT flag on @@ -555,18 +555,10 @@ int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash) O_TRUNC | O_CREAT | O_NOCTTY | O_EXCL); flags |= O_RDONLY; f = dentry_open(&file->f_path, flags, file->f_cred); - if (IS_ERR(f)) { - /* - * Cannot open the file again, lets modify f_mode - * of original and continue - */ - pr_info_ratelimited("Unable to reopen file for reading.\n"); - f = file; - f->f_mode |= FMODE_READ; - modified_mode = true; - } else { - new_file_instance = true; - } + if (IS_ERR(f)) + return PTR_ERR(f); + + new_file_instance = true; } i_size = i_size_read(file_inode(f)); @@ -581,8 +573,6 @@ int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash) out: if (new_file_instance) fput(f); - else if (modified_mode) - f->f_mode &= ~FMODE_READ; return rc; } diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 2d1af8899cab..f87cb29329e9 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -413,7 +413,7 @@ int ima_file_mmap(struct file *file, unsigned long prot) */ int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot) { - struct ima_template_desc *template; + struct ima_template_desc *template = NULL; struct file *file = vma->vm_file; char filename[NAME_MAX]; char *pathbuf = NULL; @@ -501,37 +501,14 @@ int ima_file_check(struct file *file, int mask) } EXPORT_SYMBOL_GPL(ima_file_check); -/** - * ima_file_hash - return the stored measurement if a file has been hashed and - * is in the iint cache. - * @file: pointer to the file - * @buf: buffer in which to store the hash - * @buf_size: length of the buffer - * - * On success, return the hash algorithm (as defined in the enum hash_algo). - * If buf is not NULL, this function also outputs the hash into buf. - * If the hash is larger than buf_size, then only buf_size bytes will be copied. - * It generally just makes sense to pass a buffer capable of holding the largest - * possible hash: IMA_MAX_DIGEST_SIZE. - * The file hash returned is based on the entire file, including the appended - * signature. - * - * If IMA is disabled or if no measurement is available, return -EOPNOTSUPP. - * If the parameters are incorrect, return -EINVAL. - */ -int ima_file_hash(struct file *file, char *buf, size_t buf_size) +static int __ima_inode_hash(struct inode *inode, char *buf, size_t buf_size) { - struct inode *inode; struct integrity_iint_cache *iint; int hash_algo; - if (!file) - return -EINVAL; - if (!ima_policy_flag) return -EOPNOTSUPP; - inode = file_inode(file); iint = integrity_iint_find(inode); if (!iint) return -EOPNOTSUPP; @@ -558,9 +535,62 @@ int ima_file_hash(struct file *file, char *buf, size_t buf_size) return hash_algo; } + +/** + * ima_file_hash - return the stored measurement if a file has been hashed and + * is in the iint cache. + * @file: pointer to the file + * @buf: buffer in which to store the hash + * @buf_size: length of the buffer + * + * On success, return the hash algorithm (as defined in the enum hash_algo). + * If buf is not NULL, this function also outputs the hash into buf. + * If the hash is larger than buf_size, then only buf_size bytes will be copied. + * It generally just makes sense to pass a buffer capable of holding the largest + * possible hash: IMA_MAX_DIGEST_SIZE. + * The file hash returned is based on the entire file, including the appended + * signature. + * + * If IMA is disabled or if no measurement is available, return -EOPNOTSUPP. + * If the parameters are incorrect, return -EINVAL. + */ +int ima_file_hash(struct file *file, char *buf, size_t buf_size) +{ + if (!file) + return -EINVAL; + + return __ima_inode_hash(file_inode(file), buf, buf_size); +} EXPORT_SYMBOL_GPL(ima_file_hash); /** + * ima_inode_hash - return the stored measurement if the inode has been hashed + * and is in the iint cache. + * @inode: pointer to the inode + * @buf: buffer in which to store the hash + * @buf_size: length of the buffer + * + * On success, return the hash algorithm (as defined in the enum hash_algo). + * If buf is not NULL, this function also outputs the hash into buf. + * If the hash is larger than buf_size, then only buf_size bytes will be copied. + * It generally just makes sense to pass a buffer capable of holding the largest + * possible hash: IMA_MAX_DIGEST_SIZE. + * The hash returned is based on the entire contents, including the appended + * signature. + * + * If IMA is disabled or if no measurement is available, return -EOPNOTSUPP. + * If the parameters are incorrect, return -EINVAL. + */ +int ima_inode_hash(struct inode *inode, char *buf, size_t buf_size) +{ + if (!inode) + return -EINVAL; + + return __ima_inode_hash(inode, buf, buf_size); +} +EXPORT_SYMBOL_GPL(ima_inode_hash); + +/** * ima_post_create_tmpfile - mark newly created tmpfile as new * @file : newly created tmpfile * @@ -802,7 +832,7 @@ void process_buffer_measurement(struct inode *inode, const void *buf, int size, .filename = eventname, .buf = buf, .buf_len = size}; - struct ima_template_desc *template = NULL; + struct ima_template_desc *template; struct { struct ima_digest_data hdr; char digest[IMA_MAX_DIGEST_SIZE]; @@ -814,6 +844,13 @@ void process_buffer_measurement(struct inode *inode, const void *buf, int size, if (!ima_policy_flag) return; + template = ima_template_desc_buf(); + if (!template) { + ret = -EINVAL; + audit_cause = "ima_template_desc_buf"; + goto out; + } + /* * Both LSM hooks and auxilary based buffer measurements are * based on policy. To avoid code duplication, differentiate @@ -832,19 +869,6 @@ void process_buffer_measurement(struct inode *inode, const void *buf, int size, if (!pcr) pcr = CONFIG_IMA_MEASURE_PCR_IDX; - if (!template) { - template = lookup_template_desc("ima-buf"); - ret = template_desc_init_fields(template->fmt, - &(template->fields), - &(template->num_fields)); - if (ret < 0) { - pr_err("template %s init failed, result: %d\n", - (strlen(template->name) ? - template->name : template->fmt), ret); - return; - } - } - iint.ima_hash = &hash.hdr; iint.ima_hash->algo = ima_hash_algo; iint.ima_hash->length = hash_digest_size[ima_hash_algo]; @@ -904,6 +928,7 @@ static int __init init_ima(void) { int error; + ima_appraise_parse_cmdline(); ima_init_template_list(); hash_setup(CONFIG_IMA_DEFAULT_HASH); error = ima_init(); diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 9b5adeaa47fc..823a0c1379cb 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -628,7 +628,7 @@ int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid, struct ima_rule_entry *entry; int action = 0, actmask = flags | (flags << 1); - if (template_desc) + if (template_desc && !*template_desc) *template_desc = ima_template_desc_current(); rcu_read_lock(); diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c index 1e89e2d3851f..e22e510ae92d 100644 --- a/security/integrity/ima/ima_template.c +++ b/security/integrity/ima/ima_template.c @@ -55,6 +55,7 @@ static const struct ima_template_field supported_fields[] = { #define MAX_TEMPLATE_NAME_LEN sizeof("d-ng|n-ng|sig|buf|d-modisg|modsig") static struct ima_template_desc *ima_template; +static struct ima_template_desc *ima_buf_template; /** * ima_template_has_modsig - Check whether template has modsig-related fields. @@ -252,6 +253,15 @@ struct ima_template_desc *ima_template_desc_current(void) return ima_template; } +struct ima_template_desc *ima_template_desc_buf(void) +{ + if (!ima_buf_template) { + ima_init_template_list(); + ima_buf_template = lookup_template_desc("ima-buf"); + } + return ima_buf_template; +} + int __init ima_init_template(void) { struct ima_template_desc *template = ima_template_desc_current(); @@ -260,6 +270,22 @@ int __init ima_init_template(void) result = template_desc_init_fields(template->fmt, &(template->fields), &(template->num_fields)); + if (result < 0) { + pr_err("template %s init failed, result: %d\n", + (strlen(template->name) ? + template->name : template->fmt), result); + return result; + } + + template = ima_template_desc_buf(); + if (!template) { + pr_err("Failed to get ima-buf template\n"); + return -EINVAL; + } + + result = template_desc_init_fields(template->fmt, + &(template->fields), + &(template->num_fields)); if (result < 0) pr_err("template %s init failed, result: %d\n", (strlen(template->name) ? diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h index 413c803c5208..547425c20e11 100644 --- a/security/integrity/integrity.h +++ b/security/integrity/integrity.h @@ -14,7 +14,7 @@ #include <linux/types.h> #include <linux/integrity.h> -#include <crypto/sha.h> +#include <crypto/sha1.h> #include <linux/key.h> #include <linux/audit.h> diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c index 192e531c146f..87432b35d771 100644 --- a/security/keys/encrypted-keys/encrypted.c +++ b/security/keys/encrypted-keys/encrypted.c @@ -29,7 +29,7 @@ #include <crypto/aes.h> #include <crypto/algapi.h> #include <crypto/hash.h> -#include <crypto/sha.h> +#include <crypto/sha2.h> #include <crypto/skcipher.h> #include "encrypted.h" diff --git a/security/keys/key.c b/security/keys/key.c index e282c6179b21..ebe752b137aa 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -504,6 +504,7 @@ int key_instantiate_and_link(struct key *key, int ret; memset(&prep, 0, sizeof(prep)); + prep.orig_description = key->description; prep.data = data; prep.datalen = datalen; prep.quotalen = key->type->def_datalen; @@ -854,6 +855,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, goto error_put_type; memset(&prep, 0, sizeof(prep)); + prep.orig_description = description; prep.data = payload; prep.datalen = plen; prep.quotalen = index_key.type->def_datalen; diff --git a/security/keys/trusted-keys/trusted_tpm1.c b/security/keys/trusted-keys/trusted_tpm1.c index b9fe02e5f84f..74d82093cbaa 100644 --- a/security/keys/trusted-keys/trusted_tpm1.c +++ b/security/keys/trusted-keys/trusted_tpm1.c @@ -22,7 +22,7 @@ #include <linux/rcupdate.h> #include <linux/crypto.h> #include <crypto/hash.h> -#include <crypto/sha.h> +#include <crypto/sha1.h> #include <linux/capability.h> #include <linux/tpm.h> #include <linux/tpm_command.h> diff --git a/security/lsm_audit.c b/security/lsm_audit.c index 53d0d183db8f..7d8026f3f377 100644 --- a/security/lsm_audit.c +++ b/security/lsm_audit.c @@ -183,7 +183,7 @@ int ipv6_skb_to_auditdata(struct sk_buff *skb, static inline void print_ipv6_addr(struct audit_buffer *ab, - struct in6_addr *addr, __be16 port, + const struct in6_addr *addr, __be16 port, char *name1, char *name2) { if (!ipv6_addr_any(addr)) @@ -241,7 +241,6 @@ static void dump_common_audit_data(struct audit_buffer *ab, audit_log_untrustedstring(ab, inode->i_sb->s_id); audit_log_format(ab, " ino=%lu", inode->i_ino); } - audit_getcwd(); break; } case LSM_AUDIT_DATA_FILE: { @@ -255,7 +254,6 @@ static void dump_common_audit_data(struct audit_buffer *ab, audit_log_untrustedstring(ab, inode->i_sb->s_id); audit_log_format(ab, " ino=%lu", inode->i_ino); } - audit_getcwd(); break; } case LSM_AUDIT_DATA_IOCTL_OP: { @@ -271,7 +269,6 @@ static void dump_common_audit_data(struct audit_buffer *ab, } audit_log_format(ab, " ioctlcmd=0x%hx", a->u.op->cmd); - audit_getcwd(); break; } case LSM_AUDIT_DATA_DENTRY: { @@ -286,7 +283,6 @@ static void dump_common_audit_data(struct audit_buffer *ab, audit_log_untrustedstring(ab, inode->i_sb->s_id); audit_log_format(ab, " ino=%lu", inode->i_ino); } - audit_getcwd(); break; } case LSM_AUDIT_DATA_INODE: { @@ -304,7 +300,6 @@ static void dump_common_audit_data(struct audit_buffer *ab, audit_log_format(ab, " dev="); audit_log_untrustedstring(ab, inode->i_sb->s_id); audit_log_format(ab, " ino=%lu", inode->i_ino); - audit_getcwd(); break; } case LSM_AUDIT_DATA_TASK: { @@ -322,7 +317,7 @@ static void dump_common_audit_data(struct audit_buffer *ab, } case LSM_AUDIT_DATA_NET: if (a->u.net->sk) { - struct sock *sk = a->u.net->sk; + const struct sock *sk = a->u.net->sk; struct unix_sock *u; struct unix_address *addr; int len = 0; diff --git a/security/security.c b/security/security.c index a28045dc9e7f..7b09cfbae94f 100644 --- a/security/security.c +++ b/security/security.c @@ -65,6 +65,7 @@ const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1] = { [LOCKDOWN_PERF] = "unsafe use of perf", [LOCKDOWN_TRACEFS] = "use of tracefs", [LOCKDOWN_XMON_RW] = "xmon read and write access", + [LOCKDOWN_XFRM_SECRET] = "xfrm SA secret", [LOCKDOWN_CONFIDENTIALITY_MAX] = "confidentiality", }; @@ -2207,15 +2208,16 @@ void security_sk_clone(const struct sock *sk, struct sock *newsk) } EXPORT_SYMBOL(security_sk_clone); -void security_sk_classify_flow(struct sock *sk, struct flowi *fl) +void security_sk_classify_flow(struct sock *sk, struct flowi_common *flic) { - call_void_hook(sk_getsecid, sk, &fl->flowi_secid); + call_void_hook(sk_getsecid, sk, &flic->flowic_secid); } EXPORT_SYMBOL(security_sk_classify_flow); -void security_req_classify_flow(const struct request_sock *req, struct flowi *fl) +void security_req_classify_flow(const struct request_sock *req, + struct flowi_common *flic) { - call_void_hook(req_classify_flow, req, fl); + call_void_hook(req_classify_flow, req, flic); } EXPORT_SYMBOL(security_req_classify_flow); @@ -2225,7 +2227,7 @@ void security_sock_graft(struct sock *sk, struct socket *parent) } EXPORT_SYMBOL(security_sock_graft); -int security_inet_conn_request(struct sock *sk, +int security_inet_conn_request(const struct sock *sk, struct sk_buff *skb, struct request_sock *req) { return call_int_hook(inet_conn_request, 0, sk, skb, req); @@ -2407,7 +2409,7 @@ int security_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir) int security_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy *xp, - const struct flowi *fl) + const struct flowi_common *flic) { struct security_hook_list *hp; int rc = LSM_RET_DEFAULT(xfrm_state_pol_flow_match); @@ -2423,7 +2425,7 @@ int security_xfrm_state_pol_flow_match(struct xfrm_state *x, */ hlist_for_each_entry(hp, &security_hook_heads.xfrm_state_pol_flow_match, list) { - rc = hp->hook.xfrm_state_pol_flow_match(x, xp, fl); + rc = hp->hook.xfrm_state_pol_flow_match(x, xp, flic); break; } return rc; @@ -2434,9 +2436,9 @@ int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid) return call_int_hook(xfrm_decode_session, 0, skb, secid, 1); } -void security_skb_classify_flow(struct sk_buff *skb, struct flowi *fl) +void security_skb_classify_flow(struct sk_buff *skb, struct flowi_common *flic) { - int rc = call_int_hook(xfrm_decode_session, 0, skb, &fl->flowi_secid, + int rc = call_int_hook(xfrm_decode_session, 0, skb, &flic->flowic_secid, 0); BUG_ON(rc); diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 6b1826fc3658..644b17ec9e63 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -600,7 +600,7 @@ static int selinux_set_mnt_opts(struct super_block *sb, { const struct cred *cred = current_cred(); struct superblock_security_struct *sbsec = sb->s_security; - struct dentry *root = sbsec->sb->s_root; + struct dentry *root = sb->s_root; struct selinux_mnt_opts *opts = mnt_opts; struct inode_security_struct *root_isec; u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0; @@ -1080,7 +1080,7 @@ static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb) return rc; } if (sbsec->flags & ROOTCONTEXT_MNT) { - struct dentry *root = sbsec->sb->s_root; + struct dentry *root = sb->s_root; struct inode_security_struct *isec = backing_inode_security(root); seq_putc(m, ','); seq_puts(m, ROOTCONTEXT_STR); @@ -1451,7 +1451,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent * inode_doinit with a dentry, before these inodes could * be used again by userspace. */ - goto out; + goto out_invalid; } rc = inode_doinit_use_xattr(inode, dentry, sbsec->def_sid, @@ -1508,7 +1508,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent * could be used again by userspace. */ if (!dentry) - goto out; + goto out_invalid; rc = selinux_genfs_get_sid(dentry, sclass, sbsec->flags, &sid); if (rc) { @@ -1533,11 +1533,10 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent out: spin_lock(&isec->lock); if (isec->initialized == LABEL_PENDING) { - if (!sid || rc) { + if (rc) { isec->initialized = LABEL_INVALID; goto out_unlock; } - isec->initialized = LABEL_INITIALIZED; isec->sid = sid; } @@ -1545,6 +1544,15 @@ out: out_unlock: spin_unlock(&isec->lock); return rc; + +out_invalid: + spin_lock(&isec->lock); + if (isec->initialized == LABEL_PENDING) { + isec->initialized = LABEL_INVALID; + isec->sid = sid; + } + spin_unlock(&isec->lock); + return 0; } /* Convert a Linux signal to an access vector. */ @@ -2560,7 +2568,6 @@ static int selinux_sb_alloc_security(struct super_block *sb) mutex_init(&sbsec->lock); INIT_LIST_HEAD(&sbsec->isec_head); spin_lock_init(&sbsec->isec_lock); - sbsec->sb = sb; sbsec->sid = SECINITSID_UNLABELED; sbsec->def_sid = SECINITSID_FILE; sbsec->mntpoint_sid = SECINITSID_UNLABELED; @@ -4029,6 +4036,7 @@ static int selinux_kernel_load_data(enum kernel_load_data_id id, bool contents) switch (id) { case LOADING_MODULE: rc = selinux_kernel_module_from_file(NULL); + break; default: break; } @@ -5355,7 +5363,7 @@ static void selinux_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *sk, selinux_netlbl_sctp_sk_clone(sk, newsk); } -static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, +static int selinux_inet_conn_request(const struct sock *sk, struct sk_buff *skb, struct request_sock *req) { struct sk_security_struct *sksec = sk->sk_security; @@ -5429,9 +5437,9 @@ static void selinux_secmark_refcount_dec(void) } static void selinux_req_classify_flow(const struct request_sock *req, - struct flowi *fl) + struct flowi_common *flic) { - fl->flowi_secid = req->secid; + flic->flowic_secid = req->secid; } static int selinux_tun_dev_alloc_security(void **security) diff --git a/security/selinux/ibpkey.c b/security/selinux/ibpkey.c index f68a7617cfb9..3a63a989e55e 100644 --- a/security/selinux/ibpkey.c +++ b/security/selinux/ibpkey.c @@ -151,8 +151,10 @@ static int sel_ib_pkey_sid_slow(u64 subnet_prefix, u16 pkey_num, u32 *sid) * is valid, it just won't be added to the cache. */ new = kzalloc(sizeof(*new), GFP_ATOMIC); - if (!new) + if (!new) { + ret = -ENOMEM; goto out; + } new->psec.subnet_prefix = subnet_prefix; new->psec.pkey = pkey_num; diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index 330b7b6d44e0..ca4d7ab6a835 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -61,7 +61,6 @@ struct file_security_struct { }; struct superblock_security_struct { - struct super_block *sb; /* back pointer to sb object */ u32 sid; /* SID of file system superblock */ u32 def_sid; /* default SID for labeling */ u32 mntpoint_sid; /* SECURITY_FS_USE_MNTPOINT context for files */ diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h index a0b465316292..0a6f34a7a971 100644 --- a/security/selinux/include/xfrm.h +++ b/security/selinux/include/xfrm.h @@ -26,7 +26,7 @@ int selinux_xfrm_state_delete(struct xfrm_state *x); int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir); int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy *xp, - const struct flowi *fl); + const struct flowi_common *flic); #ifdef CONFIG_SECURITY_NETWORK_XFRM extern atomic_t selinux_xfrm_refcount; diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 9704c8a32303..597b79703584 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -596,9 +596,7 @@ void services_compute_xperms_drivers( node->datum.u.xperms->driver); } - /* If no ioctl commands are allowed, ignore auditallow and auditdeny */ - if (node->key.specified & AVTAB_XPERMS_ALLOWED) - xperms->len = 1; + xperms->len = 1; } /* diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c index 7314196185d1..c367d36965d4 100644 --- a/security/selinux/xfrm.c +++ b/security/selinux/xfrm.c @@ -175,9 +175,10 @@ int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir) */ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy *xp, - const struct flowi *fl) + const struct flowi_common *flic) { u32 state_sid; + u32 flic_sid; if (!xp->security) if (x->security) @@ -196,17 +197,17 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, return 0; state_sid = x->security->ctx_sid; + flic_sid = flic->flowic_secid; - if (fl->flowi_secid != state_sid) + if (flic_sid != state_sid) return 0; /* We don't need a separate SA Vs. policy polmatch check since the SA * is now of the same label as the flow and a flow Vs. policy polmatch * check had already happened in selinux_xfrm_policy_lookup() above. */ - return (avc_has_perm(&selinux_state, - fl->flowi_secid, state_sid, - SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, - NULL) ? 0 : 1); + return (avc_has_perm(&selinux_state, flic_sid, state_sid, + SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, + NULL) ? 0 : 1); } static u32 selinux_xfrm_skb_sid_egress(struct sk_buff *skb) diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 5c90b9fa4d40..f69c3dd9a0c6 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -3864,13 +3864,12 @@ static inline struct smack_known *smack_from_skb(struct sk_buff *skb) * * Returns smack_known of the IP options or NULL if that won't work. */ -static struct smack_known *smack_from_netlbl(struct sock *sk, u16 family, +static struct smack_known *smack_from_netlbl(const struct sock *sk, u16 family, struct sk_buff *skb) { struct netlbl_lsm_secattr secattr; struct socket_smack *ssp = NULL; struct smack_known *skp = NULL; - int rc; netlbl_secattr_init(&secattr); @@ -3880,7 +3879,7 @@ static struct smack_known *smack_from_netlbl(struct sock *sk, u16 family, if (netlbl_skbuff_getattr(skb, family, &secattr) == 0) { skp = smack_from_secattr(&secattr, ssp); if (secattr.flags & NETLBL_SECATTR_CACHEABLE) - rc = netlbl_cache_add(skb, family, &skp->smk_netlabel); + netlbl_cache_add(skb, family, &skp->smk_netlabel); } netlbl_secattr_destroy(&secattr); @@ -4114,7 +4113,7 @@ static void smack_sock_graft(struct sock *sk, struct socket *parent) * Returns 0 if a task with the packet label could write to * the socket, otherwise an error code */ -static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, +static int smack_inet_conn_request(const struct sock *sk, struct sk_buff *skb, struct request_sock *req) { u16 family = sk->sk_family; diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index e567b4baf3a0..5d44b7d258ef 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c @@ -1942,7 +1942,7 @@ static void smk_list_swap_rcu(struct list_head *public, * smk_parse_label_list - parse list of Smack labels, separated by spaces * * @data: the string to parse - * @private: destination list + * @list: destination list * * Returns zero on success or error code, as appropriate */ @@ -1973,7 +1973,7 @@ static int smk_parse_label_list(char *data, struct list_head *list) /** * smk_destroy_label_list - destroy a list of smack_known_list_elem - * @head: header pointer of the list to destroy + * @list: header pointer of the list to destroy */ void smk_destroy_label_list(struct list_head *list) { @@ -2131,7 +2131,7 @@ static const struct file_operations smk_unconfined_ops = { * smk_read_logging - read() for /smack/logging * @filp: file pointer, not actually used * @buf: where to put the result - * @cn: maximum to send along + * @count: maximum to send along * @ppos: where to start * * Returns number of bytes read or error code, as appropriate @@ -2272,6 +2272,7 @@ static const struct file_operations smk_load_self_ops = { * @buf: data from user space * @count: bytes sent * @ppos: where to start - must be 0 + * @format: /smack/load or /smack/load2 or /smack/change-rule format. */ static ssize_t smk_user_access(struct file *file, const char __user *buf, size_t count, loff_t *ppos, int format) diff --git a/security/tomoyo/audit.c b/security/tomoyo/audit.c index 3c96e8402e94..b51bad121c11 100644 --- a/security/tomoyo/audit.c +++ b/security/tomoyo/audit.c @@ -311,7 +311,7 @@ static LIST_HEAD(tomoyo_log); /* Lock for "struct list_head tomoyo_log". */ static DEFINE_SPINLOCK(tomoyo_log_lock); -/* Length of "stuct list_head tomoyo_log". */ +/* Length of "struct list_head tomoyo_log". */ static unsigned int tomoyo_log_count; /** diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 4bee32bfe16d..5c64927bf2b3 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -498,7 +498,7 @@ static struct tomoyo_profile *tomoyo_assign_profile ptr = ns->profile_ptr[profile]; if (ptr) return ptr; - entry = kzalloc(sizeof(*entry), GFP_NOFS); + entry = kzalloc(sizeof(*entry), GFP_NOFS | __GFP_NOWARN); if (mutex_lock_interruptible(&tomoyo_policy_lock)) goto out; ptr = ns->profile_ptr[profile]; @@ -635,7 +635,7 @@ static int tomoyo_set_mode(char *name, const char *value, if (strstr(value, tomoyo_mode[mode])) /* * Update lower 3 bits in order to distinguish - * 'config' from 'TOMOYO_CONFIG_USE_DEAFULT'. + * 'config' from 'TOMOYO_CONFIG_USE_DEFAULT'. */ config = (config & ~7) | mode; if (config != TOMOYO_CONFIG_USE_DEFAULT) { @@ -2574,7 +2574,7 @@ static inline bool tomoyo_has_more_namespace(struct tomoyo_io_buffer *head) * tomoyo_read_control - read() for /sys/kernel/security/tomoyo/ interface. * * @head: Pointer to "struct tomoyo_io_buffer". - * @buffer: Poiner to buffer to write to. + * @buffer: Pointer to buffer to write to. * @buffer_len: Size of @buffer. * * Returns bytes read on success, negative value otherwise. @@ -2608,7 +2608,7 @@ ssize_t tomoyo_read_control(struct tomoyo_io_buffer *head, char __user *buffer, /** * tomoyo_parse_policy - Parse a policy line. * - * @head: Poiter to "struct tomoyo_io_buffer". + * @head: Pointer to "struct tomoyo_io_buffer". * @line: Line to parse. * * Returns 0 on success, negative value otherwise. diff --git a/security/tomoyo/condition.c b/security/tomoyo/condition.c index 8f6d57c15df6..f8bcc083bb0d 100644 --- a/security/tomoyo/condition.c +++ b/security/tomoyo/condition.c @@ -98,7 +98,7 @@ static bool tomoyo_envp(const char *env_name, const char *env_value, * @argc: Length of @argc. * @argv: Pointer to "struct tomoyo_argv". * @envc: Length of @envp. - * @envp: Poiner to "struct tomoyo_envp". + * @envp: Pointer to "struct tomoyo_envp". * * Returns true on success, false otherwise. */ diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index dc4ecc0b2038..98d985895ec8 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -473,9 +473,7 @@ struct tomoyo_policy_namespace *tomoyo_assign_namespace(const char *domainname) return ptr; if (len >= TOMOYO_EXEC_TMPSIZE - 10 || !tomoyo_domain_def(domainname)) return NULL; - entry = kzalloc(sizeof(*entry) + len + 1, GFP_NOFS); - if (!entry) - return NULL; + entry = kzalloc(sizeof(*entry) + len + 1, GFP_NOFS | __GFP_NOWARN); if (mutex_lock_interruptible(&tomoyo_policy_lock)) goto out; ptr = tomoyo_find_namespace(domainname, len); @@ -891,7 +889,7 @@ force_jump_domain: * * @bprm: Pointer to "struct linux_binprm". * @pos: Location to dump. - * @dump: Poiner to "struct tomoyo_page_dump". + * @dump: Pointer to "struct tomoyo_page_dump". * * Returns true on success, false otherwise. */ diff --git a/security/tomoyo/gc.c b/security/tomoyo/gc.c index 9537832fca18..026e29ea3796 100644 --- a/security/tomoyo/gc.c +++ b/security/tomoyo/gc.c @@ -463,7 +463,7 @@ static void tomoyo_try_to_gc(const enum tomoyo_policy_id type, return; reinject: /* - * We can safely reinject this element here bacause + * We can safely reinject this element here because * (1) Appending list elements and removing list elements are protected * by tomoyo_policy_lock mutex. * (2) Only this function removes list elements and this function is diff --git a/security/tomoyo/memory.c b/security/tomoyo/memory.c index 2e7fcfa923c9..1b570bde7a3b 100644 --- a/security/tomoyo/memory.c +++ b/security/tomoyo/memory.c @@ -73,7 +73,7 @@ bool tomoyo_memory_ok(void *ptr) */ void *tomoyo_commit_ok(void *data, const unsigned int size) { - void *ptr = kzalloc(size, GFP_NOFS); + void *ptr = kzalloc(size, GFP_NOFS | __GFP_NOWARN); if (tomoyo_memory_ok(ptr)) { memmove(ptr, data, size); @@ -170,7 +170,7 @@ const struct tomoyo_path_info *tomoyo_get_name(const char *name) atomic_inc(&ptr->head.users); goto out; } - ptr = kzalloc(sizeof(*ptr) + len, GFP_NOFS); + ptr = kzalloc(sizeof(*ptr) + len, GFP_NOFS | __GFP_NOWARN); if (tomoyo_memory_ok(ptr)) { ptr->entry.name = ((char *) ptr) + sizeof(*ptr); memmove((char *) ptr->entry.name, name, len); diff --git a/security/tomoyo/securityfs_if.c b/security/tomoyo/securityfs_if.c index 546281c5b233..065f4941c4d8 100644 --- a/security/tomoyo/securityfs_if.c +++ b/security/tomoyo/securityfs_if.c @@ -131,8 +131,8 @@ static const struct file_operations tomoyo_self_operations = { */ static int tomoyo_open(struct inode *inode, struct file *file) { - const int key = ((u8 *) file_inode(file)->i_private) - - ((u8 *) NULL); + const u8 key = (uintptr_t) file_inode(file)->i_private; + return tomoyo_open_control(key, file); } @@ -223,7 +223,7 @@ static const struct file_operations tomoyo_operations = { static void __init tomoyo_create_entry(const char *name, const umode_t mode, struct dentry *parent, const u8 key) { - securityfs_create_file(name, mode, parent, ((u8 *) NULL) + key, + securityfs_create_file(name, mode, parent, (void *) (uintptr_t) key, &tomoyo_operations); } diff --git a/security/tomoyo/util.c b/security/tomoyo/util.c index a40abb0b91ee..176b803ebcfc 100644 --- a/security/tomoyo/util.c +++ b/security/tomoyo/util.c @@ -434,59 +434,64 @@ void tomoyo_normalize_line(unsigned char *buffer) */ static bool tomoyo_correct_word2(const char *string, size_t len) { + u8 recursion = 20; const char *const start = string; bool in_repetition = false; - unsigned char c; - unsigned char d; - unsigned char e; if (!len) goto out; while (len--) { - c = *string++; + unsigned char c = *string++; + if (c == '\\') { if (!len--) goto out; c = *string++; + if (c >= '0' && c <= '3') { + unsigned char d; + unsigned char e; + + if (!len-- || !len--) + goto out; + d = *string++; + e = *string++; + if (d < '0' || d > '7' || e < '0' || e > '7') + goto out; + c = tomoyo_make_byte(c, d, e); + if (c <= ' ' || c >= 127) + continue; + goto out; + } switch (c) { case '\\': /* "\\" */ - continue; - case '$': /* "\$" */ case '+': /* "\+" */ case '?': /* "\?" */ + case 'x': /* "\x" */ + case 'a': /* "\a" */ + case '-': /* "\-" */ + continue; + } + if (!recursion--) + goto out; + switch (c) { case '*': /* "\*" */ case '@': /* "\@" */ - case 'x': /* "\x" */ + case '$': /* "\$" */ case 'X': /* "\X" */ - case 'a': /* "\a" */ case 'A': /* "\A" */ - case '-': /* "\-" */ continue; case '{': /* "/\{" */ if (string - 3 < start || *(string - 3) != '/') - break; + goto out; in_repetition = true; continue; case '}': /* "\}/" */ if (*string != '/') - break; + goto out; if (!in_repetition) - break; + goto out; in_repetition = false; continue; - case '0': /* "\ooo" */ - case '1': - case '2': - case '3': - if (!len-- || !len--) - break; - d = *string++; - e = *string++; - if (d < '0' || d > '7' || e < '0' || e > '7') - break; - c = tomoyo_make_byte(c, d, e); - if (c <= ' ' || c >= 127) - continue; } goto out; } else if (in_repetition && c == '/') { |