diff options
Diffstat (limited to 'security')
-rw-r--r-- | security/Kconfig.hardening | 23 | ||||
-rw-r--r-- | security/apparmor/apparmorfs.c | 11 | ||||
-rw-r--r-- | security/apparmor/policy_unpack.c | 11 | ||||
-rw-r--r-- | security/inode.c | 2 | ||||
-rw-r--r-- | security/integrity/ima/ima_policy.c | 4 | ||||
-rw-r--r-- | security/integrity/platform_certs/load_ipl_s390.c | 4 | ||||
-rw-r--r-- | security/loadpin/loadpin.c | 3 | ||||
-rw-r--r-- | security/security.c | 14 | ||||
-rw-r--r-- | security/selinux/hooks.c | 22 | ||||
-rw-r--r-- | security/selinux/selinuxfs.c | 2 | ||||
-rw-r--r-- | security/selinux/ss/policydb.c | 2 | ||||
-rw-r--r-- | security/smack/smack_lsm.c | 51 |
12 files changed, 132 insertions, 17 deletions
diff --git a/security/Kconfig.hardening b/security/Kconfig.hardening index 0f295961e773..2cff851ebfd7 100644 --- a/security/Kconfig.hardening +++ b/security/Kconfig.hardening @@ -279,6 +279,29 @@ config ZERO_CALL_USED_REGS endmenu +menu "Hardening of kernel data structures" + +config LIST_HARDENED + bool "Check integrity of linked list manipulation" + help + Minimal integrity checking in the linked-list manipulation routines + to catch memory corruptions that are not guaranteed to result in an + immediate access fault. + + If unsure, say N. + +config BUG_ON_DATA_CORRUPTION + bool "Trigger a BUG when data corruption is detected" + select LIST_HARDENED + help + Select this option if the kernel should BUG when it encounters + data corruption in kernel memory structures when they get checked + for validity. + + If unsure, say N. + +endmenu + config CC_HAS_RANDSTRUCT def_bool $(cc-option,-frandomize-layout-seed-file=/dev/null) # Randstruct was first added in Clang 15, but it isn't safe to use until diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c index db7a51acf9db..bd6a910f6528 100644 --- a/security/apparmor/apparmorfs.c +++ b/security/apparmor/apparmorfs.c @@ -226,7 +226,7 @@ static int __aafs_setup_d_inode(struct inode *dir, struct dentry *dentry, inode->i_ino = get_next_ino(); inode->i_mode = mode; - inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode); + inode->i_atime = inode->i_mtime = inode_set_ctime_current(inode); inode->i_private = data; if (S_ISDIR(mode)) { inode->i_op = iops ? iops : &simple_dir_inode_operations; @@ -1554,8 +1554,11 @@ void __aafs_profile_migrate_dents(struct aa_profile *old, for (i = 0; i < AAFS_PROF_SIZEOF; i++) { new->dents[i] = old->dents[i]; - if (new->dents[i]) - new->dents[i]->d_inode->i_mtime = current_time(new->dents[i]->d_inode); + if (new->dents[i]) { + struct inode *inode = d_inode(new->dents[i]); + + inode->i_mtime = inode_set_ctime_current(inode); + } old->dents[i] = NULL; } } @@ -2540,7 +2543,7 @@ static int aa_mk_null_file(struct dentry *parent) inode->i_ino = get_next_ino(); inode->i_mode = S_IFCHR | S_IRUGO | S_IWUGO; - inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode); + inode->i_atime = inode->i_mtime = inode_set_ctime_current(inode); init_special_inode(inode, S_IFCHR | S_IRUGO | S_IWUGO, MKDEV(MEM_MAJOR, 3)); d_instantiate(dentry, inode); diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c index 694fb7a09962..8b8846073e14 100644 --- a/security/apparmor/policy_unpack.c +++ b/security/apparmor/policy_unpack.c @@ -86,10 +86,13 @@ void __aa_loaddata_update(struct aa_loaddata *data, long revision) data->revision = revision; if ((data->dents[AAFS_LOADDATA_REVISION])) { - d_inode(data->dents[AAFS_LOADDATA_DIR])->i_mtime = - current_time(d_inode(data->dents[AAFS_LOADDATA_DIR])); - d_inode(data->dents[AAFS_LOADDATA_REVISION])->i_mtime = - current_time(d_inode(data->dents[AAFS_LOADDATA_REVISION])); + struct inode *inode; + + inode = d_inode(data->dents[AAFS_LOADDATA_DIR]); + inode->i_mtime = inode_set_ctime_current(inode); + + inode = d_inode(data->dents[AAFS_LOADDATA_REVISION]); + inode->i_mtime = inode_set_ctime_current(inode); } } diff --git a/security/inode.c b/security/inode.c index 6c326939750d..3aa75fffa8c9 100644 --- a/security/inode.c +++ b/security/inode.c @@ -145,7 +145,7 @@ static struct dentry *securityfs_create_dentry(const char *name, umode_t mode, inode->i_ino = get_next_ino(); inode->i_mode = mode; - inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode); + inode->i_atime = inode->i_mtime = inode_set_ctime_current(inode); inode->i_private = data; if (S_ISDIR(mode)) { inode->i_op = &simple_dir_inode_operations; diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index c9b3bd8f1bb9..7a0420cf1a6a 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -68,7 +68,7 @@ enum policy_rule_list { IMA_DEFAULT_POLICY = 1, IMA_CUSTOM_POLICY }; struct ima_rule_opt_list { size_t count; - char *items[]; + char *items[] __counted_by(count); }; /* @@ -342,6 +342,7 @@ static struct ima_rule_opt_list *ima_alloc_rule_opt_list(const substring_t *src) kfree(src_copy); return ERR_PTR(-ENOMEM); } + opt_list->count = count; /* * strsep() has already replaced all instances of '|' with '\0', @@ -357,7 +358,6 @@ static struct ima_rule_opt_list *ima_alloc_rule_opt_list(const substring_t *src) opt_list->items[i] = cur; cur = strchr(cur, '\0') + 1; } - opt_list->count = count; return opt_list; } diff --git a/security/integrity/platform_certs/load_ipl_s390.c b/security/integrity/platform_certs/load_ipl_s390.c index e769dcb7ea94..c7c381a9ddaa 100644 --- a/security/integrity/platform_certs/load_ipl_s390.c +++ b/security/integrity/platform_certs/load_ipl_s390.c @@ -22,8 +22,8 @@ static int __init load_ipl_certs(void) if (!ipl_cert_list_addr) return 0; - /* Copy the certificates to the system keyring */ - ptr = (void *) ipl_cert_list_addr; + /* Copy the certificates to the platform keyring */ + ptr = __va(ipl_cert_list_addr); end = ptr + ipl_cert_list_size; while ((void *) ptr < end) { len = *(unsigned int *) ptr; diff --git a/security/loadpin/loadpin.c b/security/loadpin/loadpin.c index ebae964f7cc9..a9d40456a064 100644 --- a/security/loadpin/loadpin.c +++ b/security/loadpin/loadpin.c @@ -336,6 +336,7 @@ static int read_trusted_verity_root_digests(unsigned int fd) rc = -ENOMEM; goto err; } + trd->len = len; if (hex2bin(trd->data, d, len)) { kfree(trd); @@ -343,8 +344,6 @@ static int read_trusted_verity_root_digests(unsigned int fd) goto err; } - trd->len = len; - list_add_tail(&trd->node, &dm_verity_loadpin_trusted_root_digests); } diff --git a/security/security.c b/security/security.c index b720424ca37d..549104a447e3 100644 --- a/security/security.c +++ b/security/security.c @@ -1139,6 +1139,20 @@ void security_bprm_committed_creds(struct linux_binprm *bprm) } /** + * security_fs_context_submount() - Initialise fc->security + * @fc: new filesystem context + * @reference: dentry reference for submount/remount + * + * Fill out the ->security field for a new fs_context. + * + * Return: Returns 0 on success or negative error code on failure. + */ +int security_fs_context_submount(struct fs_context *fc, struct super_block *reference) +{ + return call_int_hook(fs_context_submount, 0, fc, reference); +} + +/** * security_fs_context_dup() - Duplicate a fs_context LSM blob * @fc: destination filesystem context * @src_fc: source filesystem context diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index d06e350fedee..afd663744041 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2745,6 +2745,27 @@ static int selinux_umount(struct vfsmount *mnt, int flags) FILESYSTEM__UNMOUNT, NULL); } +static int selinux_fs_context_submount(struct fs_context *fc, + struct super_block *reference) +{ + const struct superblock_security_struct *sbsec; + struct selinux_mnt_opts *opts; + + opts = kzalloc(sizeof(*opts), GFP_KERNEL); + if (!opts) + return -ENOMEM; + + sbsec = selinux_superblock(reference); + if (sbsec->flags & FSCONTEXT_MNT) + opts->fscontext_sid = sbsec->sid; + if (sbsec->flags & CONTEXT_MNT) + opts->context_sid = sbsec->mntpoint_sid; + if (sbsec->flags & DEFCONTEXT_MNT) + opts->defcontext_sid = sbsec->def_sid; + fc->security = opts; + return 0; +} + static int selinux_fs_context_dup(struct fs_context *fc, struct fs_context *src_fc) { @@ -7182,6 +7203,7 @@ static struct security_hook_list selinux_hooks[] __ro_after_init = { /* * PUT "CLONING" (ACCESSING + ALLOCATING) HOOKS HERE */ + LSM_HOOK_INIT(fs_context_submount, selinux_fs_context_submount), LSM_HOOK_INIT(fs_context_dup, selinux_fs_context_dup), LSM_HOOK_INIT(fs_context_parse_param, selinux_fs_context_parse_param), LSM_HOOK_INIT(sb_eat_lsm_opts, selinux_sb_eat_lsm_opts), diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index bad1f6b685fd..9dafb6ff110d 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -1197,7 +1197,7 @@ static struct inode *sel_make_inode(struct super_block *sb, int mode) if (ret) { ret->i_mode = mode; - ret->i_atime = ret->i_mtime = ret->i_ctime = current_time(ret); + ret->i_atime = ret->i_mtime = inode_set_ctime_current(ret); } return ret; } diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 31b08b34c722..dc904865af58 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -2005,6 +2005,7 @@ static int filename_trans_read_helper(struct policydb *p, void *fp) if (!datum) goto out; + datum->next = NULL; *dst = datum; /* ebitmap_read() will at least init the bitmap */ @@ -2017,7 +2018,6 @@ static int filename_trans_read_helper(struct policydb *p, void *fp) goto out; datum->otype = le32_to_cpu(buf[0]); - datum->next = NULL; dst = &datum->next; } diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 6e270cf3fd30..a8201cf22f20 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -615,6 +615,56 @@ out_opt_err: } /** + * smack_fs_context_submount - Initialise security data for a filesystem context + * @fc: The filesystem context. + * @reference: reference superblock + * + * Returns 0 on success or -ENOMEM on error. + */ +static int smack_fs_context_submount(struct fs_context *fc, + struct super_block *reference) +{ + struct superblock_smack *sbsp; + struct smack_mnt_opts *ctx; + struct inode_smack *isp; + + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + fc->security = ctx; + + sbsp = smack_superblock(reference); + isp = smack_inode(reference->s_root->d_inode); + + if (sbsp->smk_default) { + ctx->fsdefault = kstrdup(sbsp->smk_default->smk_known, GFP_KERNEL); + if (!ctx->fsdefault) + return -ENOMEM; + } + + if (sbsp->smk_floor) { + ctx->fsfloor = kstrdup(sbsp->smk_floor->smk_known, GFP_KERNEL); + if (!ctx->fsfloor) + return -ENOMEM; + } + + if (sbsp->smk_hat) { + ctx->fshat = kstrdup(sbsp->smk_hat->smk_known, GFP_KERNEL); + if (!ctx->fshat) + return -ENOMEM; + } + + if (isp->smk_flags & SMK_INODE_TRANSMUTE) { + if (sbsp->smk_root) { + ctx->fstransmute = kstrdup(sbsp->smk_root->smk_known, GFP_KERNEL); + if (!ctx->fstransmute) + return -ENOMEM; + } + } + return 0; +} + +/** * smack_fs_context_dup - Duplicate the security data on fs_context duplication * @fc: The new filesystem context. * @src_fc: The source filesystem context being duplicated. @@ -4876,6 +4926,7 @@ static struct security_hook_list smack_hooks[] __ro_after_init = { LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme), LSM_HOOK_INIT(syslog, smack_syslog), + LSM_HOOK_INIT(fs_context_submount, smack_fs_context_submount), LSM_HOOK_INIT(fs_context_dup, smack_fs_context_dup), LSM_HOOK_INIT(fs_context_parse_param, smack_fs_context_parse_param), |