Re: [PATCH V3fix ghak120] audit: initialize context values in case of mandatory events
On 2020-07-27 22:14, Paul Moore wrote: > On Mon, Jul 27, 2020 at 5:30 PM Richard Guy Briggs wrote: > > Issue ghak120 enabled syscall records to accompany required records when > > no rules are present to trigger the storage of syscall context. A > > reported issue showed that the cwd was not always initialized. That > > issue was already resolved ... > > Yes and no. Yes, it appears to be resolved in v5.8-rc1 and above, but > the problematic commit is in v5.7 and I'm not sure backporting the fix > in v5.8-rcX plus this patch is the right thing to do for a released > kernel. The lowest risk fix for v5.7 at this point is to do a revert; Ok, fair enough. I don't understand why you didn't do the revert since it appears so trivial to you and this review and fix turned out to be marginally more work. I didn't understand what you wanted when you referred to stable. > regardless of what happens with this patch and v5.8-rcX please post a > revert for the audit/stable-5.7 tree as soon as you can. (more below...) > > ... but a review of all other records that could > > be triggered at the time of a syscall record revealed other potential > > values that could be missing or misleading. Initialize them. > > > > The fds array is reset to -1 after the first syscall to indicate it > > isn't valid any more, but was never set to -1 when the context was > > allocated to indicate it wasn't yet valid. > > > > The audit_inode* functions can be called without going through > > getname_flags() or getname_kernel() that sets audit_names and cwd, so > > set the cwd if it has not already been done so due to audit_names being > > valid. > > > > The LSM dump_common_audit_data() LSM_AUDIT_DATA_NET:AF_UNIX case was > > missed with the ghak96 patch, so add that case here. > > > > Please see issue https://github.com/linux-audit/audit-kernel/issues/120 > > Please see issue https://github.com/linux-audit/audit-kernel/issues/96 > > Passes audit-testsuite. > > > > Signed-off-by: Richard Guy Briggs > > --- > > kernel/auditsc.c | 3 +++ > > security/lsm_audit.c | 1 + > > 2 files changed, 4 insertions(+) > > > > diff --git a/kernel/auditsc.c b/kernel/auditsc.c > > index 6884b50069d1..2f97618e6a34 100644 > > --- a/kernel/auditsc.c > > +++ b/kernel/auditsc.c > > @@ -929,6 +929,7 @@ static inline struct audit_context > > *audit_alloc_context(enum audit_state state) > > context->prio = state == AUDIT_RECORD_CONTEXT ? ~0ULL : 0; > > INIT_LIST_HEAD(&context->killed_trees); > > INIT_LIST_HEAD(&context->names_list); > > + context->fds[0] = -1; > > return context; > > } > > > > @@ -2076,6 +2077,7 @@ void __audit_inode(struct filename *name, const > > struct dentry *dentry, > > } > > handle_path(dentry); > > audit_copy_inode(n, dentry, inode, flags & AUDIT_INODE_NOEVAL); > > + _audit_getcwd(context); > > } > > > > void __audit_file(const struct file *file) > > @@ -2194,6 +2196,7 @@ void __audit_inode_child(struct inode *parent, > > audit_copy_inode(found_child, dentry, inode, 0); > > else > > found_child->ino = AUDIT_INO_UNSET; > > + _audit_getcwd(context); > > } > > EXPORT_SYMBOL_GPL(__audit_inode_child); > > > > diff --git a/security/lsm_audit.c b/security/lsm_audit.c > > index 53d0d183db8f..e93077612246 100644 > > --- a/security/lsm_audit.c > > +++ b/security/lsm_audit.c > > @@ -369,6 +369,7 @@ static void dump_common_audit_data(struct audit_buffer > > *ab, > > audit_log_untrustedstring(ab, p); > > else > > audit_log_n_hex(ab, p, len); > > + audit_getcwd(); > > break; > > } > > } > > I understand the "fds[0] = -1" fix in audit_alloc_context() > (ironically, the kzalloc() which is supposed to help with cases like > this, hurts us with this particular field), but I'm still not quite > seeing why we need to sprinkle audit_getcwd() calls everywhere to fix > this bug (this seems more like a feature add than a bigfix). Yes, > they may fix the problem but it seems like simply adding a > context->pwd test in audit_log_name() similar to what we do in > audit_log_exit() is the correct fix. Well, considering that ghak96 ended up being a bugfix (that wasn't its intent), I figured these audit_getcwd() were also bugfixes to prevent the same BUG under different calling conditions. > We are currently at -rc7 and this really needs to land before v5.8 is > released, presumably this weekend; this means a small and limited bug > fix patch is what is needed. Ok, so it sounds like rather than just fix it now, it would be better to revert it, then submit *one* patch for ghak120 plus this fix that will go tentatively upstream in 3 months, fully in 5. Arguably the last chunk above should be added to ghak96, so that should b
Re: [PATCH V3fix ghak120] audit: initialize context values in case of mandatory events
On Tue, Jul 28, 2020 at 12:27 PM Richard Guy Briggs wrote: > On 2020-07-27 22:14, Paul Moore wrote: > > On Mon, Jul 27, 2020 at 5:30 PM Richard Guy Briggs wrote: > > > Issue ghak120 enabled syscall records to accompany required records when > > > no rules are present to trigger the storage of syscall context. A > > > reported issue showed that the cwd was not always initialized. That > > > issue was already resolved ... > > > > Yes and no. Yes, it appears to be resolved in v5.8-rc1 and above, but > > the problematic commit is in v5.7 and I'm not sure backporting the fix > > in v5.8-rcX plus this patch is the right thing to do for a released > > kernel. The lowest risk fix for v5.7 at this point is to do a revert; > > Ok, fair enough. I don't understand why you didn't do the revert since > it appears so trivial to you and this review and fix turned out to be > marginally more work. I didn't understand what you wanted when you > referred to stable. I held off on the revert because I thought you might want the chance to submit the revert with your authorship. I made an assumption that it meant the same to you as it does to me; that's my mistake, I should have known better. I'll do the revert myself for stable-5.8 (which should trickle down to v5.7.z with the right metadata), don't bother with it. > > regardless of what happens with this patch and v5.8-rcX please post a > > revert for the audit/stable-5.7 tree as soon as you can. > > (more below...) > > > > ... but a review of all other records that could > > > be triggered at the time of a syscall record revealed other potential > > > values that could be missing or misleading. Initialize them. > > > > > > The fds array is reset to -1 after the first syscall to indicate it > > > isn't valid any more, but was never set to -1 when the context was > > > allocated to indicate it wasn't yet valid. > > > > > > The audit_inode* functions can be called without going through > > > getname_flags() or getname_kernel() that sets audit_names and cwd, so > > > set the cwd if it has not already been done so due to audit_names being > > > valid. > > > > > > The LSM dump_common_audit_data() LSM_AUDIT_DATA_NET:AF_UNIX case was > > > missed with the ghak96 patch, so add that case here. > > > > > > Please see issue https://github.com/linux-audit/audit-kernel/issues/120 > > > Please see issue https://github.com/linux-audit/audit-kernel/issues/96 > > > Passes audit-testsuite. > > > > > > Signed-off-by: Richard Guy Briggs > > > --- > > > kernel/auditsc.c | 3 +++ > > > security/lsm_audit.c | 1 + > > > 2 files changed, 4 insertions(+) > > > > > > diff --git a/kernel/auditsc.c b/kernel/auditsc.c > > > index 6884b50069d1..2f97618e6a34 100644 > > > --- a/kernel/auditsc.c > > > +++ b/kernel/auditsc.c > > > @@ -929,6 +929,7 @@ static inline struct audit_context > > > *audit_alloc_context(enum audit_state state) > > > context->prio = state == AUDIT_RECORD_CONTEXT ? ~0ULL : 0; > > > INIT_LIST_HEAD(&context->killed_trees); > > > INIT_LIST_HEAD(&context->names_list); > > > + context->fds[0] = -1; > > > return context; > > > } > > > > > > @@ -2076,6 +2077,7 @@ void __audit_inode(struct filename *name, const > > > struct dentry *dentry, > > > } > > > handle_path(dentry); > > > audit_copy_inode(n, dentry, inode, flags & AUDIT_INODE_NOEVAL); > > > + _audit_getcwd(context); > > > } > > > > > > void __audit_file(const struct file *file) > > > @@ -2194,6 +2196,7 @@ void __audit_inode_child(struct inode *parent, > > > audit_copy_inode(found_child, dentry, inode, 0); > > > else > > > found_child->ino = AUDIT_INO_UNSET; > > > + _audit_getcwd(context); > > > } > > > EXPORT_SYMBOL_GPL(__audit_inode_child); > > > > > > diff --git a/security/lsm_audit.c b/security/lsm_audit.c > > > index 53d0d183db8f..e93077612246 100644 > > > --- a/security/lsm_audit.c > > > +++ b/security/lsm_audit.c > > > @@ -369,6 +369,7 @@ static void dump_common_audit_data(struct > > > audit_buffer *ab, > > > audit_log_untrustedstring(ab, p); > > > else > > > audit_log_n_hex(ab, p, len); > > > + audit_getcwd(); > > > break; > > > } > > > } > > > > I understand the "fds[0] = -1" fix in audit_alloc_context() > > (ironically, the kzalloc() which is supposed to help with cases like > > this, hurts us with this particular field), but I'm still not quite > > seeing why we need to sprinkle audit_getcwd() calls everywhere to fix > > this bug (this seems more like a feature add than a bigfix). Yes, > > they may fix the problem but it seems like simply adding a > > context->pwd test in audit_log_name() similar to what we do in > > audit_log_exit() is the correct fix. > > Well, considering tha
Re: [PATCH v19 16/23] LSM: Use lsmcontext in security_inode_getsecctx
On 7/24/20 1:32 PM, Casey Schaufler wrote: > Change the security_inode_getsecctx() interface to fill > a lsmcontext structure instead of data and length pointers. > This provides the information about which LSM created the > context so that security_release_secctx() can use the > correct hook. > Reviewed-by: John Johansen > Acked-by: Stephen Smalley > Signed-off-by: Casey Schaufler > --- > fs/nfsd/nfs4xdr.c| 23 +-- > include/linux/security.h | 5 +++-- > security/security.c | 13 +++-- > 3 files changed, 23 insertions(+), 18 deletions(-) > > diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c > index 61d6b8a0e8f0..6673221d5606 100644 > --- a/fs/nfsd/nfs4xdr.c > +++ b/fs/nfsd/nfs4xdr.c > @@ -2379,11 +2379,11 @@ nfsd4_encode_layout_types(struct xdr_stream *xdr, u32 > layout_types) > #ifdef CONFIG_NFSD_V4_SECURITY_LABEL > static inline __be32 > nfsd4_encode_security_label(struct xdr_stream *xdr, struct svc_rqst *rqstp, > - void *context, int len) > + struct lsmcontext *context) > { > __be32 *p; > > - p = xdr_reserve_space(xdr, len + 4 + 4 + 4); > + p = xdr_reserve_space(xdr, context->len + 4 + 4 + 4); > if (!p) > return nfserr_resource; > > @@ -2393,13 +2393,13 @@ nfsd4_encode_security_label(struct xdr_stream *xdr, > struct svc_rqst *rqstp, >*/ > *p++ = cpu_to_be32(0); /* lfs */ > *p++ = cpu_to_be32(0); /* pi */ > - p = xdr_encode_opaque(p, context, len); > + p = xdr_encode_opaque(p, context->context, context->len); > return 0; > } > #else > static inline __be32 > nfsd4_encode_security_label(struct xdr_stream *xdr, struct svc_rqst *rqstp, > - void *context, int len) > + struct lsmcontext *context) > { return 0; } > #endif > > @@ -2496,9 +2496,7 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct > svc_fh *fhp, > int err; > struct nfs4_acl *acl = NULL; > #ifdef CONFIG_NFSD_V4_SECURITY_LABEL > - struct lsmcontext scaff; /* scaffolding */ > - void *context = NULL; > - int contextlen; > + struct lsmcontext context = { }; > #endif > bool contextsupport = false; > struct nfsd4_compoundres *resp = rqstp->rq_resp; > @@ -2556,7 +2554,7 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct > svc_fh *fhp, >bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) { > if (exp->ex_flags & NFSEXP_SECURITY_LABEL) > err = security_inode_getsecctx(d_inode(dentry), > - &context, &contextlen); > +&context); > else > err = -EOPNOTSUPP; > contextsupport = (err == 0); > @@ -2986,8 +2984,7 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct > svc_fh *fhp, > > #ifdef CONFIG_NFSD_V4_SECURITY_LABEL > if (bmval2 & FATTR4_WORD2_SECURITY_LABEL) { > - status = nfsd4_encode_security_label(xdr, rqstp, context, > - contextlen); > + status = nfsd4_encode_security_label(xdr, rqstp, &context); > if (status) > goto out; > } > @@ -2999,10 +2996,8 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct > svc_fh *fhp, > > out: > #ifdef CONFIG_NFSD_V4_SECURITY_LABEL > - if (context) { > - lsmcontext_init(&scaff, context, contextlen, 0); /*scaffolding*/ > - security_release_secctx(&scaff); > - } > + if (context.context) > + security_release_secctx(&context); > #endif /* CONFIG_NFSD_V4_SECURITY_LABEL */ > kfree(acl); > if (tempfh) { > diff --git a/include/linux/security.h b/include/linux/security.h > index 43f8a2660d37..02dc3b5ef57b 100644 > --- a/include/linux/security.h > +++ b/include/linux/security.h > @@ -560,7 +560,7 @@ void security_release_secctx(struct lsmcontext *cp); > void security_inode_invalidate_secctx(struct inode *inode); > int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen); > int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen); > -int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen); > +int security_inode_getsecctx(struct inode *inode, struct lsmcontext *cp); > int security_locked_down(enum lockdown_reason what); > #else /* CONFIG_SECURITY */ > > @@ -1399,7 +1399,8 @@ static inline int security_inode_setsecctx(struct > dentry *dentry, void *ctx, u32 > { > return -EOPNOTSUPP; > } > -static inline int security_inode_getsecctx(struct inode *inode, void **ctx, > u32 *ctxlen) > +static inline int security_inode_getsecctx(struct inode *inode, > +struct lsmcontext *cp) > { > return -EOPNOTSUPP; > } > diff --git a/security/security.c b/security/security.c > index 862f0bc
Re: [PATCH v19 15/23] LSM: Use lsmcontext in security_secid_to_secctx
On 7/24/20 1:32 PM, Casey Schaufler wrote: > Replace the (secctx,seclen) pointer pair with a single > lsmcontext pointer to allow return of the LSM identifier > along with the context and context length. This allows > security_release_secctx() to know how to release the > context. Callers have been modified to use or save the > returned data from the new structure. > > Reviewed-by: Kees Cook > Acked-by: Stephen Smalley > Acked-by: Paul Moore > Signed-off-by: Casey Schaufler > Cc: net...@vger.kernel.org > --- > drivers/android/binder.c| 26 +++- > include/linux/security.h| 4 +-- > include/net/scm.h | 10 ++- > kernel/audit.c | 35 -- > kernel/auditsc.c| 31 +++ > net/ipv4/ip_sockglue.c | 7 ++--- > net/netfilter/nf_conntrack_netlink.c| 18 +-- > net/netfilter/nf_conntrack_standalone.c | 7 ++--- > net/netfilter/nfnetlink_queue.c | 5 +++- > net/netlabel/netlabel_unlabeled.c | 40 - > net/netlabel/netlabel_user.c| 7 ++--- > security/security.c | 10 +-- > 12 files changed, 76 insertions(+), 124 deletions(-) > > diff --git a/drivers/android/binder.c b/drivers/android/binder.c > index b7ab206f8bb3..ceb5987c7d76 100644 > --- a/drivers/android/binder.c > +++ b/drivers/android/binder.c > @@ -2861,9 +2861,7 @@ static void binder_transaction(struct binder_proc *proc, > binder_size_t last_fixup_min_off = 0; > struct binder_context *context = proc->context; > int t_debug_id = atomic_inc_return(&binder_last_id); > - char *secctx = NULL; > - u32 secctx_sz = 0; > - struct lsmcontext scaff; /* scaffolding */ > + struct lsmcontext lsmctx = { }; > > e = binder_transaction_log_add(&binder_transaction_log); > e->debug_id = t_debug_id; > @@ -3111,14 +3109,14 @@ static void binder_transaction(struct binder_proc > *proc, > size_t added_size; > > security_task_getsecid(proc->tsk, &blob); > - ret = security_secid_to_secctx(&blob, &secctx, &secctx_sz); > + ret = security_secid_to_secctx(&blob, &lsmctx); > if (ret) { > return_error = BR_FAILED_REPLY; > return_error_param = ret; > return_error_line = __LINE__; > goto err_get_secctx_failed; > } > - added_size = ALIGN(secctx_sz, sizeof(u64)); > + added_size = ALIGN(lsmctx.len, sizeof(u64)); > extra_buffers_size += added_size; > if (extra_buffers_size < added_size) { > /* integer overflow of extra_buffers_size */ > @@ -3145,24 +3143,22 @@ static void binder_transaction(struct binder_proc > *proc, > t->buffer = NULL; > goto err_binder_alloc_buf_failed; > } > - if (secctx) { > + if (lsmctx.context) { > int err; > size_t buf_offset = ALIGN(tr->data_size, sizeof(void *)) + > ALIGN(tr->offsets_size, sizeof(void *)) + > ALIGN(extra_buffers_size, sizeof(void *)) - > - ALIGN(secctx_sz, sizeof(u64)); > + ALIGN(lsmctx.len, sizeof(u64)); > > t->security_ctx = (uintptr_t)t->buffer->user_data + buf_offset; > err = binder_alloc_copy_to_buffer(&target_proc->alloc, > t->buffer, buf_offset, > - secctx, secctx_sz); > + lsmctx.context, lsmctx.len); > if (err) { > t->security_ctx = 0; > WARN_ON(1); > } > - lsmcontext_init(&scaff, secctx, secctx_sz, 0); > - security_release_secctx(&scaff); > - secctx = NULL; > + security_release_secctx(&lsmctx); > } > t->buffer->debug_id = t->debug_id; > t->buffer->transaction = t; > @@ -3218,7 +3214,7 @@ static void binder_transaction(struct binder_proc *proc, > off_end_offset = off_start_offset + tr->offsets_size; > sg_buf_offset = ALIGN(off_end_offset, sizeof(void *)); > sg_buf_end_offset = sg_buf_offset + extra_buffers_size - > - ALIGN(secctx_sz, sizeof(u64)); > + ALIGN(lsmctx.len, sizeof(u64)); > off_min = 0; > for (buffer_offset = off_start_offset; buffer_offset < off_end_offset; >buffer_offset += sizeof(binder_size_t)) { > @@ -3494,10 +3490,8 @@ static void binder_transaction(struct binder_proc > *proc, > binder_alloc_free_buf(&target_proc->alloc, t->buffer); > err_binder_alloc_buf_failed: > err_bad_extra_size: > - if (secctx) { > -
Re: [PATCH v19 04/23] LSM: Use lsmblob in security_kernel_act_as
On 7/24/20 1:32 PM, Casey Schaufler wrote: > Change the security_kernel_act_as interface to use a lsmblob > structure in place of the single u32 secid in support of > module stacking. Change its only caller, set_security_override, > to do the same. Change that one's only caller, > set_security_override_from_ctx, to call it with the new > parameter type. > > The security module hook is unchanged, still taking a secid. > The infrastructure passes the correct entry from the lsmblob. > lsmblob_init() is used to fill the lsmblob structure, however > this will be removed later in the series when security_secctx_to_secid() > is undated to provide a lsmblob instead of a secid. > fix ^ "undated" to updated > Reviewed-by: Kees Cook > Reviewed-by: John Johansen > Acked-by: Stephen Smalley > Signed-off-by: Casey Schaufler > --- > include/linux/cred.h | 3 ++- > include/linux/security.h | 5 +++-- > kernel/cred.c| 10 ++ > security/security.c | 14 -- > 4 files changed, 23 insertions(+), 9 deletions(-) > > diff --git a/include/linux/cred.h b/include/linux/cred.h > index 18639c069263..03ae0182cba6 100644 > --- a/include/linux/cred.h > +++ b/include/linux/cred.h > @@ -18,6 +18,7 @@ > > struct cred; > struct inode; > +struct lsmblob; > > /* > * COW Supplementary groups list > @@ -165,7 +166,7 @@ extern const struct cred *override_creds(const struct > cred *); > extern void revert_creds(const struct cred *); > extern struct cred *prepare_kernel_cred(struct task_struct *); > extern int change_create_files_as(struct cred *, struct inode *); > -extern int set_security_override(struct cred *, u32); > +extern int set_security_override(struct cred *, struct lsmblob *); > extern int set_security_override_from_ctx(struct cred *, const char *); > extern int set_create_files_as(struct cred *, struct inode *); > extern int cred_fscmp(const struct cred *, const struct cred *); > diff --git a/include/linux/security.h b/include/linux/security.h > index 294410533b51..6d403a522918 100644 > --- a/include/linux/security.h > +++ b/include/linux/security.h > @@ -441,7 +441,7 @@ void security_cred_free(struct cred *cred); > int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t > gfp); > void security_transfer_creds(struct cred *new, const struct cred *old); > void security_cred_getsecid(const struct cred *c, u32 *secid); > -int security_kernel_act_as(struct cred *new, u32 secid); > +int security_kernel_act_as(struct cred *new, struct lsmblob *blob); > int security_kernel_create_files_as(struct cred *new, struct inode *inode); > int security_kernel_module_request(char *kmod_name); > int security_kernel_load_data(enum kernel_load_data_id id); > @@ -1055,7 +1055,8 @@ static inline void security_transfer_creds(struct cred > *new, > { > } > > -static inline int security_kernel_act_as(struct cred *cred, u32 secid) > +static inline int security_kernel_act_as(struct cred *cred, > + struct lsmblob *blob) > { > return 0; > } > diff --git a/kernel/cred.c b/kernel/cred.c > index 421b1149c651..22e0e7cbefde 100644 > --- a/kernel/cred.c > +++ b/kernel/cred.c > @@ -733,14 +733,14 @@ EXPORT_SYMBOL(prepare_kernel_cred); > /** > * set_security_override - Set the security ID in a set of credentials > * @new: The credentials to alter > - * @secid: The LSM security ID to set > + * @blob: The LSM security information to set > * > * Set the LSM security ID in a set of credentials so that the subjective > * security is overridden when an alternative set of credentials is used. > */ > -int set_security_override(struct cred *new, u32 secid) > +int set_security_override(struct cred *new, struct lsmblob *blob) > { > - return security_kernel_act_as(new, secid); > + return security_kernel_act_as(new, blob); > } > EXPORT_SYMBOL(set_security_override); > > @@ -756,6 +756,7 @@ EXPORT_SYMBOL(set_security_override); > */ > int set_security_override_from_ctx(struct cred *new, const char *secctx) > { > + struct lsmblob blob; > u32 secid; > int ret; > > @@ -763,7 +764,8 @@ int set_security_override_from_ctx(struct cred *new, > const char *secctx) > if (ret < 0) > return ret; > > - return set_security_override(new, secid); > + lsmblob_init(&blob, secid); > + return set_security_override(new, &blob); > } > EXPORT_SYMBOL(set_security_override_from_ctx); > > diff --git a/security/security.c b/security/security.c > index f9a249a93215..d6d882b1f7d5 100644 > --- a/security/security.c > +++ b/security/security.c > @@ -1692,9 +1692,19 @@ void security_cred_getsecid(const struct cred *c, u32 > *secid) > } > EXPORT_SYMBOL(security_cred_getsecid); > > -int security_kernel_act_as(struct cred *new, u32 secid) > +int security_kernel_act_as(struct cred *new, struct lsmblob *blob) > { > - return call_int_hook(kernel_act_as, 0, new, secid); > + struct se
Re: [PATCH v19 05/23] net: Prepare UDS for security module stacking
On 7/24/20 1:32 PM, Casey Schaufler wrote: > Change the data used in UDS SO_PEERSEC processing from a > secid to a more general struct lsmblob. Update the > security_socket_getpeersec_dgram() interface to use the > lsmblob. There is a small amount of scaffolding code > that will come out when the security_secid_to_secctx() > code is brought in line with the lsmblob. > > Signed-off-by: Casey Schaufler Reviewed-by: John Johansen > --- > include/linux/security.h | 7 +-- > include/net/af_unix.h| 2 +- > include/net/scm.h| 8 +--- > net/ipv4/ip_sockglue.c | 8 +--- > net/unix/af_unix.c | 6 +++--- > security/security.c | 18 +++--- > 6 files changed, 34 insertions(+), 15 deletions(-) > > diff --git a/include/linux/security.h b/include/linux/security.h > index 6d403a522918..d81e8886d799 100644 > --- a/include/linux/security.h > +++ b/include/linux/security.h > @@ -1397,7 +1397,8 @@ int security_socket_shutdown(struct socket *sock, int > how); > int security_sock_rcv_skb(struct sock *sk, struct sk_buff *skb); > int security_socket_getpeersec_stream(struct socket *sock, char __user > *optval, > int __user *optlen, unsigned len); > -int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff > *skb, u32 *secid); > +int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff > *skb, > + struct lsmblob *blob); > int security_sk_alloc(struct sock *sk, int family, gfp_t priority); > void security_sk_free(struct sock *sk); > void security_sk_clone(const struct sock *sk, struct sock *newsk); > @@ -1535,7 +1536,9 @@ static inline int > security_socket_getpeersec_stream(struct socket *sock, char __ > return -ENOPROTOOPT; > } > > -static inline int security_socket_getpeersec_dgram(struct socket *sock, > struct sk_buff *skb, u32 *secid) > +static inline int security_socket_getpeersec_dgram(struct socket *sock, > +struct sk_buff *skb, > +struct lsmblob *blob) > { > return -ENOPROTOOPT; > } > diff --git a/include/net/af_unix.h b/include/net/af_unix.h > index f42fdddecd41..a86da0cb5ec1 100644 > --- a/include/net/af_unix.h > +++ b/include/net/af_unix.h > @@ -36,7 +36,7 @@ struct unix_skb_parms { > kgid_t gid; > struct scm_fp_list *fp;/* Passed files */ > #ifdef CONFIG_SECURITY_NETWORK > - u32 secid; /* Security ID */ > + struct lsmblob lsmblob;/* Security LSM data*/ > #endif > u32 consumed; > } __randomize_layout; > diff --git a/include/net/scm.h b/include/net/scm.h > index 1ce365f4c256..e2e71c4bf9d0 100644 > --- a/include/net/scm.h > +++ b/include/net/scm.h > @@ -33,7 +33,7 @@ struct scm_cookie { > struct scm_fp_list *fp;/* Passed files */ > struct scm_credscreds; /* Skb credentials */ > #ifdef CONFIG_SECURITY_NETWORK > - u32 secid; /* Passed security ID */ > + struct lsmblob lsmblob;/* Passed LSM data */ > #endif > }; > > @@ -46,7 +46,7 @@ struct scm_fp_list *scm_fp_dup(struct scm_fp_list *fpl); > #ifdef CONFIG_SECURITY_NETWORK > static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct > scm_cookie *scm) > { > - security_socket_getpeersec_dgram(sock, NULL, &scm->secid); > + security_socket_getpeersec_dgram(sock, NULL, &scm->lsmblob); > } > #else > static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct > scm_cookie *scm) > @@ -97,7 +97,9 @@ static inline void scm_passec(struct socket *sock, struct > msghdr *msg, struct sc > int err; > > if (test_bit(SOCK_PASSSEC, &sock->flags)) { > - err = security_secid_to_secctx(scm->secid, &secdata, &seclen); > + /* Scaffolding - it has to be element 0 for now */ > + err = security_secid_to_secctx(scm->lsmblob.secid[0], > +&secdata, &seclen); > > if (!err) { > put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, seclen, > secdata); > diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c > index 84ec3703c909..3ea1103b4c29 100644 > --- a/net/ipv4/ip_sockglue.c > +++ b/net/ipv4/ip_sockglue.c > @@ -130,15 +130,17 @@ static void ip_cmsg_recv_checksum(struct msghdr *msg, > struct sk_buff *skb, > > static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb) > { > + struct lsmblob lb; > char *secdata; > - u32 seclen, secid; > + u32 seclen; > int err; > > - err = security_socket_getpeersec_dgram(NULL, skb, &secid); > + err = security_socket_getpeersec_dgram(NULL, skb, &lb); > if (err) > return; > > -
Re: [PATCH v19 06/23] LSM: Use lsmblob in security_secctx_to_secid
On 7/24/20 1:32 PM, Casey Schaufler wrote: > Change security_secctx_to_secid() to fill in a lsmblob instead > of a u32 secid. Multiple LSMs may be able to interpret the > string, and this allows for setting whichever secid is > appropriate. Change security_secmark_relabel_packet() to use a > lsmblob instead of a u32 secid. In some other cases there is > scaffolding where interfaces have yet to be converted. > > Reviewed-by: Kees Cook > Signed-off-by: Casey Schaufler > Cc: net...@vger.kernel.org one comment below, but its a nice to have so Reviewed-by: John Johansen > --- > include/linux/security.h | 30 +++ > include/net/scm.h | 7 +-- > kernel/cred.c | 4 +--- > net/ipv4/ip_sockglue.c| 6 -- > net/netfilter/nft_meta.c | 18 +--- > net/netfilter/xt_SECMARK.c| 9 ++-- > net/netlabel/netlabel_unlabeled.c | 23 + > security/security.c | 34 ++- > 8 files changed, 98 insertions(+), 33 deletions(-) > > diff --git a/include/linux/security.h b/include/linux/security.h > index d81e8886d799..98176faaaba5 100644 > --- a/include/linux/security.h > +++ b/include/linux/security.h > @@ -189,6 +189,27 @@ static inline bool lsmblob_equal(struct lsmblob *bloba, > struct lsmblob *blobb) > return !memcmp(bloba, blobb, sizeof(*bloba)); > } > > +/** > + * lsmblob_value - find the first non-zero value in an lsmblob structure. > + * @blob: Pointer to the data > + * > + * This needs to be used with extreme caution, as the cases where > + * it is appropriate are rare. > + * > + * Return the first secid value set in the lsmblob. > + * There should only be one. It would be really nice if we could have an LSM debug config, that would do things like checking there is indeed only one value when this fn is called. > + */ > +static inline u32 lsmblob_value(const struct lsmblob *blob) > +{ > + int i; > + > + for (i = 0; i < LSMBLOB_ENTRIES; i++) > + if (blob->secid[i]) > + return blob->secid[i]; > + > + return 0; > +} > + > /* These functions are in security/commoncap.c */ > extern int cap_capable(const struct cred *cred, struct user_namespace *ns, > int cap, unsigned int opts); > @@ -502,7 +523,8 @@ int security_setprocattr(const char *lsm, const char > *name, void *value, > int security_netlink_send(struct sock *sk, struct sk_buff *skb); > int security_ismaclabel(const char *name); > int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen); > -int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid); > +int security_secctx_to_secid(const char *secdata, u32 seclen, > + struct lsmblob *blob); > void security_release_secctx(char *secdata, u32 seclen); > void security_inode_invalidate_secctx(struct inode *inode); > int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen); > @@ -1321,7 +1343,7 @@ static inline int security_secid_to_secctx(u32 secid, > char **secdata, u32 *secle > > static inline int security_secctx_to_secid(const char *secdata, > u32 seclen, > -u32 *secid) > +struct lsmblob *blob) > { > return -EOPNOTSUPP; > } > @@ -1411,7 +1433,7 @@ void security_inet_csk_clone(struct sock *newsk, > const struct request_sock *req); > void security_inet_conn_established(struct sock *sk, > struct sk_buff *skb); > -int security_secmark_relabel_packet(u32 secid); > +int security_secmark_relabel_packet(struct lsmblob *blob); > void security_secmark_refcount_inc(void); > void security_secmark_refcount_dec(void); > int security_tun_dev_alloc_security(void **security); > @@ -1584,7 +1606,7 @@ static inline void > security_inet_conn_established(struct sock *sk, > { > } > > -static inline int security_secmark_relabel_packet(u32 secid) > +static inline int security_secmark_relabel_packet(struct lsmblob *blob) > { > return 0; > } > diff --git a/include/net/scm.h b/include/net/scm.h > index e2e71c4bf9d0..c09f2dfeec88 100644 > --- a/include/net/scm.h > +++ b/include/net/scm.h > @@ -97,8 +97,11 @@ static inline void scm_passec(struct socket *sock, struct > msghdr *msg, struct sc > int err; > > if (test_bit(SOCK_PASSSEC, &sock->flags)) { > - /* Scaffolding - it has to be element 0 for now */ > - err = security_secid_to_secctx(scm->lsmblob.secid[0], > + /* There can currently be only one value in the lsmblob, > + * so getting it from lsmblob_value is appropriate until > + * security_secid_to_secctx() is converted to taking a > + * lsmblob directly. */ > + err = security_secid_to_secctx(lsmblob_value(&scm->lsmblob), >
Re: [PATCH v19 02/23] LSM: Create and manage the lsmblob data structure.
On 7/24/20 1:32 PM, Casey Schaufler wrote: > When more than one security module is exporting data to > audit and networking sub-systems a single 32 bit integer > is no longer sufficient to represent the data. Add a > structure to be used instead. > > The lsmblob structure is currently an array of > u32 "secids". There is an entry for each of the > security modules built into the system that would > use secids if active. The system assigns the module > a "slot" when it registers hooks. If modules are > compiled in but not registered there will be unused > slots. > > A new lsm_id structure, which contains the name > of the LSM and its slot number, is created. There > is an instance for each LSM, which assigns the name > and passes it to the infrastructure to set the slot. > > The audit rules data is expanded to use an array of > security module data rather than a single instance. > Because IMA uses the audit rule functions it is > affected as well. > assuming the config issue Stephan found is fixed you can have my Acked-by: John Johansen > Acked-by: Stephen Smalley > Acked-by: Paul Moore > Signed-off-by: Casey Schaufler > --- > include/linux/audit.h | 4 +- > include/linux/lsm_hooks.h | 12 - > include/linux/security.h| 66 -- > kernel/auditfilter.c| 24 +- > kernel/auditsc.c| 12 ++--- > security/apparmor/lsm.c | 7 ++- > security/commoncap.c| 7 ++- > security/integrity/ima/ima_policy.c | 40 +++- > security/loadpin/loadpin.c | 8 +++- > security/lockdown/lockdown.c| 7 ++- > security/safesetid/lsm.c| 8 +++- > security/security.c | 72 - > security/selinux/hooks.c| 8 +++- > security/smack/smack_lsm.c | 7 ++- > security/tomoyo/tomoyo.c| 8 +++- > security/yama/yama_lsm.c| 7 ++- > 16 files changed, 242 insertions(+), 55 deletions(-) > > diff --git a/include/linux/audit.h b/include/linux/audit.h > index 3fcd9ee49734..aabbbe6d9296 100644 > --- a/include/linux/audit.h > +++ b/include/linux/audit.h > @@ -11,6 +11,7 @@ > > #include > #include > +#include > #include > > #define AUDIT_INO_UNSET ((unsigned long)-1) > @@ -64,8 +65,9 @@ struct audit_field { > kuid_t uid; > kgid_t gid; > struct { > + boollsm_isset; > char*lsm_str; > - void*lsm_rule; > + void*lsm_rules[LSMBLOB_ENTRIES]; > }; > }; > u32 op; > diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h > index b4bcafc79e0b..c9f792066d86 100644 > --- a/include/linux/lsm_hooks.h > +++ b/include/linux/lsm_hooks.h > @@ -1532,6 +1532,14 @@ struct security_hook_heads { > #undef LSM_HOOK > } __randomize_layout; > > +/* > + * Information that identifies a security module. > + */ > +struct lsm_id { > + const char *lsm; /* Name of the LSM */ > + int slot; /* Slot in lsmblob if one is allocated */ > +}; > + > /* > * Security module hook list structure. > * For use with generic list macros for common operations. > @@ -1540,7 +1548,7 @@ struct security_hook_list { > struct hlist_node list; > struct hlist_head *head; > union security_list_options hook; > - char*lsm; > + struct lsm_id *lsmid; > } __randomize_layout; > > /* > @@ -1575,7 +1583,7 @@ extern struct security_hook_heads security_hook_heads; > extern char *lsm_names; > > extern void security_add_hooks(struct security_hook_list *hooks, int count, > - char *lsm); > +struct lsm_id *lsmid); > > #define LSM_FLAG_LEGACY_MAJORBIT(0) > #define LSM_FLAG_EXCLUSIVE BIT(1) > diff --git a/include/linux/security.h b/include/linux/security.h > index 0a0a03b36a3b..591dae299c6f 100644 > --- a/include/linux/security.h > +++ b/include/linux/security.h > @@ -131,6 +131,64 @@ enum lockdown_reason { > > extern const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1]; > > +/* > + * Data exported by the security modules > + * > + * Any LSM that provides secid or secctx based hooks must be included. > + */ > +#define LSMBLOB_ENTRIES ( \ > + (IS_ENABLED(CONFIG_SECURITY_SELINUX) ? 1 : 0) + \ > + (IS_ENABLED(CONFIG_SECURITY_SMACK) ? 1 : 0) + \ > + (IS_ENABLED(CONFIG_SECURITY_APPARMOR) ? 1 : 0)) > + > +struct lsmblob { > + u32 secid[LSMBLOB_ENTRIES]; > +}; > + > +#define LSMBLOB_INVALID -1 /* Not a valid LSM slot number > */ > +#define LSMBLOB_NEEDED -2 /* Slot requested on > initializa
Re: [PATCH v19 13/23] LSM: Specify which LSM to display
On 7/24/20 1:32 PM, Casey Schaufler wrote: > Create a new entry "display" in the procfs attr directory for > controlling which LSM security information is displayed for a > process. A process can only read or write its own display value. > > The name of an active LSM that supplies hooks for > human readable data may be written to "display" to set the > value. The name of the LSM currently in use can be read from > "display". At this point there can only be one LSM capable > of display active. A helper function lsm_task_display() is > provided to get the display slot for a task_struct. > > Setting the "display" requires that all security modules using > setprocattr hooks allow the action. Each security module is > responsible for defining its policy. > > AppArmor hook provided by John Johansen > SELinux hook provided by Stephen Smalley > > Reviewed-by: Kees Cook > Acked-by: Stephen Smalley > Acked-by: Paul Moore > Signed-off-by: Casey Schaufler > --- > fs/proc/base.c | 1 + > include/linux/lsm_hooks.h| 17 +++ > security/apparmor/include/apparmor.h | 3 +- > security/apparmor/lsm.c | 32 + > security/security.c | 167 --- > security/selinux/hooks.c | 11 ++ > security/selinux/include/classmap.h | 2 +- > security/smack/smack_lsm.c | 7 ++ > 8 files changed, 221 insertions(+), 19 deletions(-) > > diff --git a/fs/proc/base.c b/fs/proc/base.c > index d86c0afc8a85..40471a12ced2 100644 > --- a/fs/proc/base.c > +++ b/fs/proc/base.c > @@ -2794,6 +2794,7 @@ static const struct pid_entry attr_dir_stuff[] = { > ATTR(NULL, "fscreate", 0666), > ATTR(NULL, "keycreate", 0666), > ATTR(NULL, "sockcreate",0666), > + ATTR(NULL, "display", 0666), > #ifdef CONFIG_SECURITY_SMACK > DIR("smack",0555, > proc_smack_attr_dir_inode_ops, proc_smack_attr_dir_ops), > diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h > index c9f792066d86..6908fa03cf31 100644 > --- a/include/linux/lsm_hooks.h > +++ b/include/linux/lsm_hooks.h > @@ -1647,4 +1647,21 @@ static inline void security_delete_hooks(struct > security_hook_list *hooks, > > extern int lsm_inode_alloc(struct inode *inode); > > +/** > + * lsm_task_display - the "display" LSM for this task > + * @task: The task to report on > + * > + * Returns the task's display LSM slot. > + */ > +static inline int lsm_task_display(struct task_struct *task) > +{ > +#ifdef CONFIG_SECURITY > + int *display = task->security; > + > + if (display) > + return *display; > +#endif > + return LSMBLOB_INVALID; > +} > + > #endif /* ! __LINUX_LSM_HOOKS_H */ > diff --git a/security/apparmor/include/apparmor.h > b/security/apparmor/include/apparmor.h > index 1fbabdb565a8..b1622fcb4394 100644 > --- a/security/apparmor/include/apparmor.h > +++ b/security/apparmor/include/apparmor.h > @@ -28,8 +28,9 @@ > #define AA_CLASS_SIGNAL 10 > #define AA_CLASS_NET 14 > #define AA_CLASS_LABEL 16 > +#define AA_CLASS_DISPLAY_LSM 17 > > -#define AA_CLASS_LASTAA_CLASS_LABEL > +#define AA_CLASS_LASTAA_CLASS_DISPLAY_LSM > > /* Control parameters settable through module/boot flags */ > extern enum audit_mode aa_g_audit; > diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c > index 432915c1d427..31a6f11890f1 100644 > --- a/security/apparmor/lsm.c > +++ b/security/apparmor/lsm.c > @@ -612,6 +612,25 @@ static int apparmor_getprocattr(struct task_struct > *task, char *name, > return error; > } > > + > +static int profile_display_lsm(struct aa_profile *profile, > +struct common_audit_data *sa) > +{ > + struct aa_perms perms = { }; > + unsigned int state; > + > + state = PROFILE_MEDIATES(profile, AA_CLASS_DISPLAY_LSM); > + if (state) { > + aa_compute_perms(profile->policy.dfa, state, &perms); > + aa_apply_modes_to_perms(profile, &perms); > + aad(sa)->label = &profile->label; > + > + return aa_check_perms(profile, &perms, AA_MAY_WRITE, sa, NULL); > + } > + > + return 0; > +} > + > static int apparmor_setprocattr(const char *name, void *value, > size_t size) > { > @@ -623,6 +642,19 @@ static int apparmor_setprocattr(const char *name, void > *value, > if (size == 0) > return -EINVAL; > > + /* LSM infrastructure does actual setting of display if allowed */ > + if (!strcmp(name, "display")) { > + struct aa_profile *profile; > + struct aa_label *label; > + > + aad(&sa)->info = "set display lsm"; > + label = begin_current_label_crit_section(); > + error = fn_for_each_confined(label, profile, > + profile_display_lsm(prof
[PATCH] revert: 1320a4052ea1 ("audit: trigger accompanying records when no rules present")
Unfortunately the commit listed in the subject line above failed to ensure that the task's audit_context was properly initialized/set before enabling the "accompanying records". Depending on the sitation, the resulting audit_context could have invalid values in some of it's fields which could cause a kernel panic/oops when the task/syscall exists and the audit records are generated. We will revisit the original patch, with the necessary fixes, in a future kernel but right now we just want to fix the kernel panic with the least amount of added risk. Cc: sta...@vger.kernel.org Fixes: 1320a4052ea1 ("audit: trigger accompanying records when no rules present") Reported-by: j24...@googlemail.com Signed-off-by: Paul Moore --- kernel/audit.c |1 - kernel/audit.h |8 kernel/auditsc.c |3 +++ 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/kernel/audit.c b/kernel/audit.c index e33460e01b3b..9bf2b08b051f 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -1848,7 +1848,6 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, } audit_get_stamp(ab->ctx, &t, &serial); - audit_clear_dummy(ab->ctx); audit_log_format(ab, "audit(%llu.%03lu:%u): ", (unsigned long long)t.tv_sec, t.tv_nsec/100, serial); diff --git a/kernel/audit.h b/kernel/audit.h index f0233dc40b17..ddc22878433d 100644 --- a/kernel/audit.h +++ b/kernel/audit.h @@ -290,13 +290,6 @@ extern int audit_signal_info_syscall(struct task_struct *t); extern void audit_filter_inodes(struct task_struct *tsk, struct audit_context *ctx); extern struct list_head *audit_killed_trees(void); - -static inline void audit_clear_dummy(struct audit_context *ctx) -{ - if (ctx) - ctx->dummy = 0; -} - #else /* CONFIG_AUDITSYSCALL */ #define auditsc_get_stamp(c, t, s) 0 #define audit_put_watch(w) {} @@ -330,7 +323,6 @@ static inline int audit_signal_info_syscall(struct task_struct *t) } #define audit_filter_inodes(t, c) AUDIT_DISABLED -#define audit_clear_dummy(c) {} #endif /* CONFIG_AUDITSYSCALL */ extern char *audit_unpack_string(void **bufp, size_t *remain, size_t len); diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 468a23390457..fd840c40abf7 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -1417,6 +1417,9 @@ static void audit_log_proctitle(void) struct audit_context *context = audit_context(); struct audit_buffer *ab; + if (!context || context->dummy) + return; + ab = audit_log_start(context, GFP_KERNEL, AUDIT_PROCTITLE); if (!ab) return; /* audit_panic or being filtered */ -- Linux-audit mailing list Linux-audit@redhat.com https://www.redhat.com/mailman/listinfo/linux-audit
[RFC PATCH v5 10/11] documentation: add ipe documentation
Add IPE's documentation to the kernel tree. Signed-off-by: Deven Bowers Acked-by: Jonathan Corbet --- Documentation/admin-guide/LSM/index.rst | 1 + Documentation/admin-guide/LSM/ipe.rst | 508 ++ .../admin-guide/kernel-parameters.txt | 12 + MAINTAINERS | 1 + 4 files changed, 522 insertions(+) create mode 100644 Documentation/admin-guide/LSM/ipe.rst diff --git a/Documentation/admin-guide/LSM/index.rst b/Documentation/admin-guide/LSM/index.rst index a6ba95fbaa9f..ce63be6d64ad 100644 --- a/Documentation/admin-guide/LSM/index.rst +++ b/Documentation/admin-guide/LSM/index.rst @@ -47,3 +47,4 @@ subdirectories. tomoyo Yama SafeSetID + ipe diff --git a/Documentation/admin-guide/LSM/ipe.rst b/Documentation/admin-guide/LSM/ipe.rst new file mode 100644 index ..2e6610c4a134 --- /dev/null +++ b/Documentation/admin-guide/LSM/ipe.rst @@ -0,0 +1,508 @@ +.. SPDX-License-Identifier: GPL-2.0 + +Integrity Policy Enforcement (IPE) +== + +Overview + + +IPE is a Linux Security Module which allows for a configurable policy +to enforce integrity requirements on the whole system. It attempts to +solve the issue of Code Integrity: that any code being executed (or +files being read), are identical to the version that was built by a +trusted source. + +There are multiple implementations within the Linux kernel that solve +some measure of integrity verification. For instance, device-mapper +verity, which ensures integrity for a block device, and fs-verity which +is a system that ensures integrity for a filesystem. What these +implementations lack is a measure of run-time verification that binaries +are sourced from these locations. IPE aims to address this gap. + +IPE is separated between two major components: A configurable policy, +provided by the LSM ("IPE Core"), and deterministic attributes provided +by the kernel to evaluate files against, ("IPE Properties"). + +Use Cases +- + +IPE is designed for use is an embedded device with a specific purpose +(e.g. network firewall device in a data center), where all software and +configuration is built and provisioned by the owner. + +Ideally, a system which leverages IPE is not intended for general +purpose computing and does not utilize any software or configuration +built by a third party. An ideal system to leverage IPE has both mutable +and immutable components, however, all binary executable code is +immutable. + +For the highest level of security, platform firmware should verify the +the kernel and optionally the root filesystem (e.g. via U-Boot verified +boot). This allows the entire system to be integrity verified. + +Known Gaps +-- + +IPE cannot verify the integrity of anonymous executable memory, such as +the trampolines created by gcc closures and libffi, or JIT'd code. +Unfortunately, as this is dynamically generated code, there is no way +for IPE to detect that this code has not been tampered with in +transition from where it was built, to where it is running. As a result, +IPE is incapable of tackling this problem for dynamically generated +code. + +IPE cannot verify the integrity of interpreted languages' programs when +these scripts invoked via `` ``. This is because the +way interpreters execute these files, the scripts themselves are not +evaluated as executable code through one of IPE's hooks. Interpreters +can be enlightened to the usage of IPE by trying to mmap a file into +executable memory (+X), after opening the file and responding to the +error code appropriately. This also applies to included files, or high +value files, such as configuration files of critical system components. +This specific gap is planned on being addressed within IPE. + +Threat Model + + +The threat type addressed by IPE is tampering of executable user-land +code beyond the initially booted kernel, and the initial verification of +kernel modules that are loaded in userland through ``modprobe`` or +``insmod``. + +Tampering violates the property of integrity. IPE's role in mitigating +this threat is to verify the integrity (and authenticity) of all +executable code and to deny their use if integrity verification fails. +IPE generates audit logs which may be utilized to detect integrity +verification failures. + +Tampering threat scenarios include modification or replacement of +executable code by a range of actors including: + +- Insiders with physical access to the hardware +- Insiders with local network access to the system +- Insiders with access to the deployment system +- Compromised internal systems under external control +- Malicious end users of the system +- Compromised end users of the system +- Remote (external) compromise of the system + +IPE does not mitigate threats arising from malicious authorized +developers, or compromised developer tools used by authorized +developers. Additionally, IPE draw
[RFC PATCH v5 09/11] dm-verity: add bdev_setsecurity hook for root-hash
Add a security hook call to set a security property of a block_device in dm-verity with the root-hash that was verified to match the merkel-tree. Signed-off-by: Deven Bowers --- drivers/md/dm-verity-target.c | 8 + include/linux/device-mapper.h | 1 + security/ipe/ipe-blobs.c| 11 ++ security/ipe/ipe-engine.h | 3 + security/ipe/ipe.c | 4 + security/ipe/properties/Kconfig | 13 +- security/ipe/properties/Makefile| 1 + security/ipe/properties/dmverity-roothash.c | 153 security/ipe/properties/prop-entry.h| 9 ++ 9 files changed, 202 insertions(+), 1 deletion(-) create mode 100644 security/ipe/properties/dmverity-roothash.c diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c index fabc173aa7b3..7f609906af16 100644 --- a/drivers/md/dm-verity-target.c +++ b/drivers/md/dm-verity-target.c @@ -16,8 +16,10 @@ #include "dm-verity.h" #include "dm-verity-fec.h" #include "dm-verity-verify-sig.h" +#include "dm-core.h" #include #include +#include #define DM_MSG_PREFIX "verity" @@ -530,6 +532,12 @@ static int verity_verify_io(struct dm_verity_io *io) return -EIO; } + r = security_bdev_setsecurity(dm_table_get_md(v->ti->table)->bdev, + DM_VERITY_ROOTHASH_SEC_NAME, + v->root_digest, v->digest_size); + if (unlikely(r < 0)) + return r; + /* * At this point, the merkel tree has finished validating. * if signature was specified, validate the signature here. diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h index 02be0be21d38..b82e8223d52a 100644 --- a/include/linux/device-mapper.h +++ b/include/linux/device-mapper.h @@ -625,5 +625,6 @@ static inline unsigned long to_bytes(sector_t n) } #define DM_VERITY_SIGNATURE_SEC_NAME DM_NAME ".verity-sig" +#define DM_VERITY_ROOTHASH_SEC_NAME DM_NAME".verity-rh" #endif /* _LINUX_DEVICE_MAPPER_H */ diff --git a/security/ipe/ipe-blobs.c b/security/ipe/ipe-blobs.c index 041d7d47b723..6a09d5c6dea8 100644 --- a/security/ipe/ipe-blobs.c +++ b/security/ipe/ipe-blobs.c @@ -46,6 +46,7 @@ void ipe_bdev_free_security(struct block_device *bdev) struct ipe_bdev_blob *bdev_sec = ipe_bdev(bdev); kfree(bdev_sec->dmverity_rh_sig); + kfree(bdev_sec->dmverity_rh); memset(bdev_sec, 0x0, sizeof(*bdev_sec)); } @@ -80,5 +81,15 @@ int ipe_bdev_setsecurity(struct block_device *bdev, const char *key, return 0; } + if (!strcmp(key, DM_VERITY_ROOTHASH_SEC_NAME)) { + bdev_sec->dmverity_rh = kmemdup(value, len, GFP_KERNEL); + if (!bdev_sec->dmverity_rh) + return -ENOMEM; + + bdev_sec->rh_size = len; + + return 0; + } + return -ENOSYS; } diff --git a/security/ipe/ipe-engine.h b/security/ipe/ipe-engine.h index 038c39a8973e..696baaa423ff 100644 --- a/security/ipe/ipe-engine.h +++ b/security/ipe/ipe-engine.h @@ -18,6 +18,9 @@ struct ipe_bdev_blob { u8 *dmverity_rh_sig; size_t dmv_rh_sig_len; + + u8 *dmverity_rh; + size_t rh_size; }; struct ipe_engine_ctx { diff --git a/security/ipe/ipe.c b/security/ipe/ipe.c index 8a612eb62879..8f4dfb8c547f 100644 --- a/security/ipe/ipe.c +++ b/security/ipe/ipe.c @@ -47,6 +47,10 @@ static int __init ipe_load_properties(void) if (rc != 0) return rc; + rc = ipe_init_dm_verity_rh(); + if (rc != 0) + return rc; + return rc; } diff --git a/security/ipe/properties/Kconfig b/security/ipe/properties/Kconfig index 4046f7e5eaef..4f09092522d9 100644 --- a/security/ipe/properties/Kconfig +++ b/security/ipe/properties/Kconfig @@ -14,8 +14,19 @@ config IPE_BOOT_PROP if unsure, answer N. +config IPE_DM_VERITY_ROOTHASH + bool "Enable property for authorizing dm-verity volumes via root-hash" + depends on DM_VERITY + help + This option enables IPE's integration with Device-Mapper Verity. + This enables the usage of the property "dmverity_roothash" in IPE's + policy. This property allows authorization or revocation via a + a hex-string representing the roothash of a dmverity volume. + + if unsure, answer Y. + config IPE_DM_VERITY_SIGNATURE - bool "Enable property for signature verified dm-verity volumes" + bool "Enable property for verified dm-verity volumes" depends on DM_VERITY_VERIFY_ROOTHASH_SIG help This option enables IPE's integration with Device-Mapper Verity's diff --git a/security/ipe/properties/Makefile b/security/ipe/properties/Makefile index 6b67cbe36e31..d9a3807797f4 100644 --- a/security/ipe/properties/Makefile +++ b/sec
[RFC PATCH v5 07/11] dm-verity: add bdev_setsecurity hook for dm-verity signature
Add a security hook call to set a security property of a block_device in dm-verity with the results of a verified, signed root-hash. Signed-off-by: Deven Bowers --- drivers/md/dm-verity-verify-sig.c | 7 +++ include/linux/device-mapper.h | 2 ++ 2 files changed, 9 insertions(+) diff --git a/drivers/md/dm-verity-verify-sig.c b/drivers/md/dm-verity-verify-sig.c index 27dac8aa2e5a..242e2421d3c8 100644 --- a/drivers/md/dm-verity-verify-sig.c +++ b/drivers/md/dm-verity-verify-sig.c @@ -8,7 +8,10 @@ #include #include #include +#include +#include #include +#include "dm-core.h" #include "dm-verity.h" #include "dm-verity-verify-sig.h" @@ -182,6 +185,10 @@ int verity_verify_root_hash(const struct dm_verity *v) goto cleanup; sig_target->passed = true; + + ret = security_bdev_setsecurity(dm_table_get_md(v->ti->table)->bdev, + DM_VERITY_SIGNATURE_SEC_NAME, + v->sig->sig, v->sig->sig_size); cleanup: kfree(root_hash); return ret; diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h index 8750f2dc5613..02be0be21d38 100644 --- a/include/linux/device-mapper.h +++ b/include/linux/device-mapper.h @@ -624,4 +624,6 @@ static inline unsigned long to_bytes(sector_t n) return (n << SECTOR_SHIFT); } +#define DM_VERITY_SIGNATURE_SEC_NAME DM_NAME ".verity-sig" + #endif /* _LINUX_DEVICE_MAPPER_H */ -- 2.27.0 -- Linux-audit mailing list Linux-audit@redhat.com https://www.redhat.com/mailman/listinfo/linux-audit
[RFC PATCH v5 00/11] Integrity Policy Enforcement LSM (IPE)
Overview: IPE is a Linux Security Module which allows for a configurable policy to enforce integrity requirements on the whole system. It attempts to solve the issue of Code Integrity: that any code being executed (or files being read), are identical to the version that was built by a trusted source. The type of system for which IPE is designed for use is an embedded device with a specific purpose (e.g. network firewall device in a data center), where all software and configuration is built and provisioned by the owner. Specifically, a system which leverages IPE is not intended for general purpose computing and does not utilize any software or configuration built by a third party. An ideal system to leverage IPE has both mutable and immutable components, however, all binary executable code is immutable. The scope of IPE is constrained to the OS. It is assumed that platform firmware verifies the the kernel and optionally the root filesystem (e.g. via U-Boot verified boot). IPE then utilizes LSM hooks to enforce a flexible, kernel-resident integrity verification policy. IPE differs from other LSMs which provide integrity checking (for instance, IMA), as it has no dependency on the filesystem metadata itself. The attributes that IPE checks are deterministic properties that exist solely in the kernel. Additionally, IPE provides no additional mechanisms of verifying these files (e.g. IMA Signatures) - all of the attributes of verifying files are existing features within the kernel, such as dm-verity or fsverity. IPE provides a policy that allows owners of the system to easily specify integrity requirements and uses dm-verity signatures to simplify the authentication of allowed objects like authorized code and data. IPE supports two modes, permissive (similar to SELinux's permissive mode) and enforce. Permissive mode performs the same checks, and logs policy violations as enforce mode, but will not enforce the policy. This allows users to test policies before enforcing them. The default mode is enforce, and can be changed via the kernel commandline parameter `ipe.enforce=(0|1)`, or the securityfs node `/sys/kernel/security/ipe/enforce`. The ability to switch modes can be compiled out of the LSM via setting the config CONFIG_SECURITY_IPE_PERMISSIVE_SWITCH to N. IPE additionally supports success auditing. When enabled, all events that pass IPE policy and are not blocked will emit an audit event. This is disabled by default, and can be enabled via the kernel commandline `ipe.success_audit=(0|1)` or the securityfs node `/sys/kernel/security/ipe/success_audit`. Policies can be staged at runtime through securityfs and activated through sysfs. Please see the Deploying Policies section of this cover letter for more information. The IPE LSM is compiled under CONFIG_SECURITY_IPE. Policy: IPE policy is designed to be both forward compatible and backwards compatible. There is one required line, at the top of the policy, indicating the policy name, and the policy version, for instance: policy_name="Ex Policy" policy_version=0.0.0 The policy version indicates the current version of the policy (NOT the policy syntax version). This is used to prevent roll-back of policy to potentially insecure previous versions of the policy. The next portion of IPE policy, are rules. Rules are formed by key=value pairs, known as properties. IPE rules require two properties: "action", which determines what IPE does when it encounters a match against the policy, and "op", which determines when that rule should be evaluated. Thus, a minimal rule is: op=EXECUTE action=ALLOW This example will allow any execution. Additional properties are used to restrict attributes about the files being evaluated. These properties are intended to be deterministic attributes that are resident in the kernel. Available properties for IPE described in the properties section of this cover-letter, the repository available in Appendix A, and the kernel documentation page. Order does not matter for the rule's properties - they can be listed in any order, however it is encouraged to have the "op" property be first, and the "action" property be last, for readability. Additionally, rules are evaluated top-to-bottom. As a result, any revocation rules, or denies should be placed early in the file to ensure that these rules are evaluated before a rule with "action=ALLOW" is hit. Any unknown syntax in IPE policy will result in a fatal error to parse the policy. User mode can interrogate the kernel to understand what properties and the associated versions through the securityfs node, $securityfs/ipe/property_config, which will return a string of form: key1=version1 key2=version2 . . . keyN=versionN User-mode should correlate these versions with the supported values identified in the documentation to determine whether a policy should be accepted by the system. Addition
[RFC PATCH v5 11/11] cleanup: uapi/linux/audit.h
Remove trailing whitespaces and align the integrity #defines in linux/uapi/audit.h Signed-off-by: Deven Bowers --- include/uapi/linux/audit.h | 32 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index 5a634cca1d42..609b4a5e8a80 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -48,7 +48,7 @@ * 2500 - 2999 future user space (maybe integrity labels and related events) * * Messages from 1000-1199 are bi-directional. 1200-1299 & 2100 - 2999 are - * exclusively user space. 1300-2099 is kernel --> user space + * exclusively user space. 1300-2099 is kernel --> user space * communication. */ #define AUDIT_GET 1000/* Get status */ @@ -78,7 +78,7 @@ #define AUDIT_LAST_USER_MSG1199 #define AUDIT_FIRST_USER_MSG2 2100/* More user space messages */ #define AUDIT_LAST_USER_MSG2 2999 - + #define AUDIT_DAEMON_START 1200/* Daemon startup record */ #define AUDIT_DAEMON_END1201/* Daemon normal stop record */ #define AUDIT_DAEMON_ABORT 1202/* Daemon error stop record */ @@ -140,20 +140,20 @@ #define AUDIT_MAC_CALIPSO_ADD 1418/* NetLabel: add CALIPSO DOI entry */ #define AUDIT_MAC_CALIPSO_DEL 1419/* NetLabel: del CALIPSO DOI entry */ -#define AUDIT_FIRST_KERN_ANOM_MSG 1700 -#define AUDIT_LAST_KERN_ANOM_MSG1799 -#define AUDIT_ANOM_PROMISCUOUS 1700 /* Device changed promiscuous mode */ -#define AUDIT_ANOM_ABEND1701 /* Process ended abnormally */ -#define AUDIT_ANOM_LINK1702 /* Suspicious use of file links */ -#define AUDIT_ANOM_CREAT 1703 /* Suspicious file creation */ -#define AUDIT_INTEGRITY_DATA 1800 /* Data integrity verification */ -#define AUDIT_INTEGRITY_METADATA1801 /* Metadata integrity verification */ -#define AUDIT_INTEGRITY_STATUS 1802 /* Integrity enable status */ -#define AUDIT_INTEGRITY_HASH 1803 /* Integrity HASH type */ -#define AUDIT_INTEGRITY_PCR1804 /* PCR invalidation msgs */ -#define AUDIT_INTEGRITY_RULE 1805 /* policy rule */ -#define AUDIT_INTEGRITY_EVM_XATTR 1806 /* New EVM-covered xattr */ -#define AUDIT_INTEGRITY_POLICY_RULE 1807 /* IMA policy rules */ +#define AUDIT_FIRST_KERN_ANOM_MSG 1700 +#define AUDIT_LAST_KERN_ANOM_MSG 1799 +#define AUDIT_ANOM_PROMISCUOUS 1700 /* Device changed promiscuous mode */ +#define AUDIT_ANOM_ABEND 1701 /* Process ended abnormally */ +#define AUDIT_ANOM_LINK1702 /* Suspicious use of file links */ +#define AUDIT_ANOM_CREAT 1703 /* Suspicious file creation */ +#define AUDIT_INTEGRITY_DATA 1800 /* Data integrity verification */ +#define AUDIT_INTEGRITY_METADATA 1801 /* Metadata integrity verification */ +#define AUDIT_INTEGRITY_STATUS 1802 /* Integrity enable status */ +#define AUDIT_INTEGRITY_HASH 1803 /* Integrity HASH type */ +#define AUDIT_INTEGRITY_PCR1804 /* PCR invalidation msgs */ +#define AUDIT_INTEGRITY_RULE 1805 /* policy rule */ +#define AUDIT_INTEGRITY_EVM_XATTR 1806 /* New EVM-covered xattr */ +#define AUDIT_INTEGRITY_POLICY_RULE1807 /* IMA policy rules */ #define AUDIT_INTEGRITY_POLICY_LOAD1808 /* IPE Policy Load */ #define AUDIT_INTEGRITY_POLICY_ACTIVATE1809 /* IPE Policy Activation */ #define AUDIT_INTEGRITY_EVENT 1810 /* IPE Evaluation Event */ -- 2.27.0 -- Linux-audit mailing list Linux-audit@redhat.com https://www.redhat.com/mailman/listinfo/linux-audit
[RFC PATCH v5 05/11] fs: add security blob and hooks for block_device
Add a security blob and associated allocation, deallocation and set hooks for a block_device structure. Signed-off-by: Deven Bowers --- fs/block_dev.c| 8 include/linux/fs.h| 1 + include/linux/lsm_hook_defs.h | 5 +++ include/linux/lsm_hooks.h | 12 ++ include/linux/security.h | 22 +++ security/security.c | 74 +++ 6 files changed, 122 insertions(+) diff --git a/fs/block_dev.c b/fs/block_dev.c index 0ae656e022fd..8602dd62c3e2 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -34,6 +34,7 @@ #include #include #include +#include #include "internal.h" struct bdev_inode { @@ -768,11 +769,18 @@ static struct inode *bdev_alloc_inode(struct super_block *sb) struct bdev_inode *ei = kmem_cache_alloc(bdev_cachep, GFP_KERNEL); if (!ei) return NULL; + + if (unlikely(security_bdev_alloc(&ei->bdev))) { + kmem_cache_free(bdev_cachep, ei); + return NULL; + } + return &ei->vfs_inode; } static void bdev_free_inode(struct inode *inode) { + security_bdev_free(&BDEV_I(inode)->bdev); kmem_cache_free(bdev_cachep, BDEV_I(inode)); } diff --git a/include/linux/fs.h b/include/linux/fs.h index f5abba86107d..42d7e3ce7712 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -509,6 +509,7 @@ struct block_device { int bd_fsfreeze_count; /* Mutex for freeze */ struct mutexbd_fsfreeze_mutex; + void*security; } __randomize_layout; /* XArray tags, for tagging dirty and writeback pages in the pagecache. */ diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index af998f93d256..f3c0da0db4e8 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -391,3 +391,8 @@ LSM_HOOK(void, LSM_RET_VOID, perf_event_free, struct perf_event *event) LSM_HOOK(int, 0, perf_event_read, struct perf_event *event) LSM_HOOK(int, 0, perf_event_write, struct perf_event *event) #endif /* CONFIG_PERF_EVENTS */ + +LSM_HOOK(int, 0, bdev_alloc_security, struct block_device *bdev) +LSM_HOOK(void, LSM_RET_VOID, bdev_free_security, struct block_device *bdev) +LSM_HOOK(int, 0, bdev_setsecurity, struct block_device *bdev, const char *name, +const void *value, size_t size) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 95b7c1d32062..8670c19a8cef 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -1507,6 +1507,17 @@ * * @what: kernel feature being accessed * + * @bdev_alloc_security: + * Initialize the security field inside a block_device structure. + * + * @bdev_free_security: + * Cleanup the security information stored inside a block_device structure. + * + * @bdev_setsecurity: + * Set a security property associated with @name for @bdev with + * value @value. @size indicates the size of @value in bytes. + * If a @name is not implemented, return -ENOSYS. + * * Security hooks for perf events * * @perf_event_open: @@ -1553,6 +1564,7 @@ struct lsm_blob_sizes { int lbs_ipc; int lbs_msg_msg; int lbs_task; + int lbs_bdev; }; /* diff --git a/include/linux/security.h b/include/linux/security.h index 0a0a03b36a3b..8f83fdc6c65d 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -451,6 +451,11 @@ int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen); int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen); int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen); int security_locked_down(enum lockdown_reason what); +int security_bdev_alloc(struct block_device *bdev); +void security_bdev_free(struct block_device *bdev); +int security_bdev_setsecurity(struct block_device *bdev, + const char *name, const void *value, + size_t size); #else /* CONFIG_SECURITY */ static inline int call_blocking_lsm_notifier(enum lsm_event event, void *data) @@ -1291,6 +1296,23 @@ static inline int security_locked_down(enum lockdown_reason what) { return 0; } + +static inline int security_bdev_alloc(struct block_device *bdev) +{ + return 0; +} + +static inline void security_bdev_free(struct block_device *bdev) +{ +} + +static inline int security_bdev_setsecurity(struct block_device *bdev, + const char *name, + const void *value, size_t size) +{ + return 0; +} + #endif /* CONFIG_SECURITY */ #if defined(CONFIG_SECURITY) && defined(CONFIG_WATCH_QUEUE) diff --git a/security/security.c b/security/security.c index 70a7ad357bc6..fff445eba400 100644 --- a/security/security.c +++ b/security/security.c @@ -28,6 +28,7 @@ #include #include #include +#include #define
[RFC PATCH v5 11/12] documentation: add ipe documentation
Add IPE's documentation to the kernel tree. Signed-off-by: Deven Bowers Acked-by: Jonathan Corbet --- Documentation/admin-guide/LSM/index.rst | 1 + Documentation/admin-guide/LSM/ipe.rst | 508 MAINTAINERS | 1 + 3 files changed, 510 insertions(+) create mode 100644 Documentation/admin-guide/LSM/ipe.rst diff --git a/Documentation/admin-guide/LSM/index.rst b/Documentation/admin-guide/LSM/index.rst index a6ba95fbaa9f..ce63be6d64ad 100644 --- a/Documentation/admin-guide/LSM/index.rst +++ b/Documentation/admin-guide/LSM/index.rst @@ -47,3 +47,4 @@ subdirectories. tomoyo Yama SafeSetID + ipe diff --git a/Documentation/admin-guide/LSM/ipe.rst b/Documentation/admin-guide/LSM/ipe.rst new file mode 100644 index ..2e6610c4a134 --- /dev/null +++ b/Documentation/admin-guide/LSM/ipe.rst @@ -0,0 +1,508 @@ +.. SPDX-License-Identifier: GPL-2.0 + +Integrity Policy Enforcement (IPE) +== + +Overview + + +IPE is a Linux Security Module which allows for a configurable policy +to enforce integrity requirements on the whole system. It attempts to +solve the issue of Code Integrity: that any code being executed (or +files being read), are identical to the version that was built by a +trusted source. + +There are multiple implementations within the Linux kernel that solve +some measure of integrity verification. For instance, device-mapper +verity, which ensures integrity for a block device, and fs-verity which +is a system that ensures integrity for a filesystem. What these +implementations lack is a measure of run-time verification that binaries +are sourced from these locations. IPE aims to address this gap. + +IPE is separated between two major components: A configurable policy, +provided by the LSM ("IPE Core"), and deterministic attributes provided +by the kernel to evaluate files against, ("IPE Properties"). + +Use Cases +- + +IPE is designed for use is an embedded device with a specific purpose +(e.g. network firewall device in a data center), where all software and +configuration is built and provisioned by the owner. + +Ideally, a system which leverages IPE is not intended for general +purpose computing and does not utilize any software or configuration +built by a third party. An ideal system to leverage IPE has both mutable +and immutable components, however, all binary executable code is +immutable. + +For the highest level of security, platform firmware should verify the +the kernel and optionally the root filesystem (e.g. via U-Boot verified +boot). This allows the entire system to be integrity verified. + +Known Gaps +-- + +IPE cannot verify the integrity of anonymous executable memory, such as +the trampolines created by gcc closures and libffi, or JIT'd code. +Unfortunately, as this is dynamically generated code, there is no way +for IPE to detect that this code has not been tampered with in +transition from where it was built, to where it is running. As a result, +IPE is incapable of tackling this problem for dynamically generated +code. + +IPE cannot verify the integrity of interpreted languages' programs when +these scripts invoked via `` ``. This is because the +way interpreters execute these files, the scripts themselves are not +evaluated as executable code through one of IPE's hooks. Interpreters +can be enlightened to the usage of IPE by trying to mmap a file into +executable memory (+X), after opening the file and responding to the +error code appropriately. This also applies to included files, or high +value files, such as configuration files of critical system components. +This specific gap is planned on being addressed within IPE. + +Threat Model + + +The threat type addressed by IPE is tampering of executable user-land +code beyond the initially booted kernel, and the initial verification of +kernel modules that are loaded in userland through ``modprobe`` or +``insmod``. + +Tampering violates the property of integrity. IPE's role in mitigating +this threat is to verify the integrity (and authenticity) of all +executable code and to deny their use if integrity verification fails. +IPE generates audit logs which may be utilized to detect integrity +verification failures. + +Tampering threat scenarios include modification or replacement of +executable code by a range of actors including: + +- Insiders with physical access to the hardware +- Insiders with local network access to the system +- Insiders with access to the deployment system +- Compromised internal systems under external control +- Malicious end users of the system +- Compromised end users of the system +- Remote (external) compromise of the system + +IPE does not mitigate threats arising from malicious authorized +developers, or compromised developer tools used by authorized +developers. Additionally, IPE draws hard security boundary between user +mode and kernel mode. As a r
[RFC PATCH v5 10/12] ipe: add property for dmverity roothash
Add a property to allow IPE policy to express rules around a specific root-hash of a dm-verity volume. This can be used for revocation, (when combined with the previous dm-verity property) or the authorization of a single dm-verity volume. Signed-off-by: Deven Bowers --- security/ipe/ipe-blobs.c| 11 ++ security/ipe/ipe-engine.h | 3 + security/ipe/ipe.c | 4 + security/ipe/properties/Kconfig | 13 +- security/ipe/properties/Makefile| 1 + security/ipe/properties/dmverity-roothash.c | 153 security/ipe/properties/prop-entry.h| 9 ++ 7 files changed, 193 insertions(+), 1 deletion(-) create mode 100644 security/ipe/properties/dmverity-roothash.c diff --git a/security/ipe/ipe-blobs.c b/security/ipe/ipe-blobs.c index 9d67b63497fc..18d5bf689c54 100644 --- a/security/ipe/ipe-blobs.c +++ b/security/ipe/ipe-blobs.c @@ -46,6 +46,7 @@ void ipe_bdev_free_security(struct block_device *bdev) struct ipe_bdev_blob *bdev_sec = ipe_bdev(bdev); kfree(bdev_sec->dmverity_rh_sig); + kfree(bdev_sec->dmverity_rh); memset(bdev_sec, 0x0, sizeof(*bdev_sec)); } @@ -80,5 +81,15 @@ int ipe_bdev_setsecurity(struct block_device *bdev, const char *key, return 0; } + if (!strcmp(key, DM_VERITY_ROOTHASH_SEC_NAME)) { + bdev_sec->dmverity_rh = kmemdup(value, len, GFP_KERNEL); + if (!bdev_sec->dmverity_rh) + return -ENOMEM; + + bdev_sec->rh_size = len; + + return 0; + } + return -EOPNOTSUPP; } diff --git a/security/ipe/ipe-engine.h b/security/ipe/ipe-engine.h index 038c39a8973e..696baaa423ff 100644 --- a/security/ipe/ipe-engine.h +++ b/security/ipe/ipe-engine.h @@ -18,6 +18,9 @@ struct ipe_bdev_blob { u8 *dmverity_rh_sig; size_t dmv_rh_sig_len; + + u8 *dmverity_rh; + size_t rh_size; }; struct ipe_engine_ctx { diff --git a/security/ipe/ipe.c b/security/ipe/ipe.c index ad25ac3f2a4f..5d2535503c20 100644 --- a/security/ipe/ipe.c +++ b/security/ipe/ipe.c @@ -47,6 +47,10 @@ static int __init ipe_load_properties(void) if (rc != 0) return rc; + rc = ipe_init_dm_verity_rh(); + if (rc != 0) + return rc; + return rc; } diff --git a/security/ipe/properties/Kconfig b/security/ipe/properties/Kconfig index 4046f7e5eaef..4f09092522d9 100644 --- a/security/ipe/properties/Kconfig +++ b/security/ipe/properties/Kconfig @@ -14,8 +14,19 @@ config IPE_BOOT_PROP if unsure, answer N. +config IPE_DM_VERITY_ROOTHASH + bool "Enable property for authorizing dm-verity volumes via root-hash" + depends on DM_VERITY + help + This option enables IPE's integration with Device-Mapper Verity. + This enables the usage of the property "dmverity_roothash" in IPE's + policy. This property allows authorization or revocation via a + a hex-string representing the roothash of a dmverity volume. + + if unsure, answer Y. + config IPE_DM_VERITY_SIGNATURE - bool "Enable property for signature verified dm-verity volumes" + bool "Enable property for verified dm-verity volumes" depends on DM_VERITY_VERIFY_ROOTHASH_SIG help This option enables IPE's integration with Device-Mapper Verity's diff --git a/security/ipe/properties/Makefile b/security/ipe/properties/Makefile index 6b67cbe36e31..d9a3807797f4 100644 --- a/security/ipe/properties/Makefile +++ b/security/ipe/properties/Makefile @@ -10,3 +10,4 @@ obj-$(CONFIG_SECURITY_IPE) += properties.o properties-$(CONFIG_IPE_BOOT_PROP) += boot-verified.o properties-$(CONFIG_IPE_DM_VERITY_SIGNATURE) += dmverity-signature.o +properties-$(CONFIG_IPE_DM_VERITY_ROOTHASH) += dmverity-roothash.o diff --git a/security/ipe/properties/dmverity-roothash.c b/security/ipe/properties/dmverity-roothash.c new file mode 100644 index ..09112e1af753 --- /dev/null +++ b/security/ipe/properties/dmverity-roothash.c @@ -0,0 +1,153 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) Microsoft Corporation. All rights reserved. + */ + +#include "../ipe.h" +#include "../ipe-pin.h" +#include "../ipe-property.h" +#include "../utility.h" + +#include +#include +#include +#include +#include +#include + +#define PROPERTY_NAME "dmverity_roothash" + +struct counted_array { + u8 *arr; + size_t len; +}; + +static void audit(struct audit_buffer *ab, const void *value) +{ + const struct counted_array *a = (const struct counted_array *)value; + + if (!a || a->len == 0) + audit_log_format(ab, "NULL"); + else + audit_log_n_hex(ab, a->arr, a->len); +} + +static inline void audit_rule_value(struct audit_buffer *ab, + const void *value) +{ + audit(ab, value); +} + +static
[RFC PATCH v5 04/11] ipe: add property for trust of boot volume
Add a property for IPE policy to express trust of the first superblock where a file would be evaluated to determine trust. Signed-off-by: Deven Bowers --- security/ipe/Kconfig| 2 + security/ipe/Makefile | 4 ++ security/ipe/ipe-engine.c | 4 ++ security/ipe/ipe-hooks.c| 19 + security/ipe/ipe-hooks.h| 2 + security/ipe/ipe-pin.c | 93 + security/ipe/ipe-pin.h | 36 ++ security/ipe/ipe.c | 28 +++- security/ipe/properties/Kconfig | 15 security/ipe/properties/Makefile| 11 +++ security/ipe/properties/boot-verified.c | 82 ++ security/ipe/properties/prop-entry.h| 20 ++ security/ipe/utility.h | 22 ++ 13 files changed, 337 insertions(+), 1 deletion(-) create mode 100644 security/ipe/ipe-pin.c create mode 100644 security/ipe/ipe-pin.h create mode 100644 security/ipe/properties/Kconfig create mode 100644 security/ipe/properties/Makefile create mode 100644 security/ipe/properties/boot-verified.c create mode 100644 security/ipe/properties/prop-entry.h create mode 100644 security/ipe/utility.h diff --git a/security/ipe/Kconfig b/security/ipe/Kconfig index 665524fc3ca4..469ef78c2f4f 100644 --- a/security/ipe/Kconfig +++ b/security/ipe/Kconfig @@ -43,4 +43,6 @@ config SECURITY_IPE_PERMISSIVE_SWITCH If unsure, answer Y. +source "security/ipe/properties/Kconfig" + endif diff --git a/security/ipe/Makefile b/security/ipe/Makefile index 7d6da33dd0c4..7e98982c5035 100644 --- a/security/ipe/Makefile +++ b/security/ipe/Makefile @@ -26,3 +26,7 @@ obj-$(CONFIG_SECURITY_IPE) += \ ipe-secfs.o \ clean-files := ipe-bp.c + +obj-$(CONFIG_IPE_BOOT_PROP) += ipe-pin.o + +obj-$(CONFIG_SECURITY_IPE) += properties/ diff --git a/security/ipe/ipe-engine.c b/security/ipe/ipe-engine.c index ac526d4ea5e6..0291ced99d64 100644 --- a/security/ipe/ipe-engine.c +++ b/security/ipe/ipe-engine.c @@ -9,6 +9,8 @@ #include "ipe-policy.h" #include "ipe-engine.h" #include "ipe-audit.h" +#include "ipe-pin.h" +#include "utility.h" #include #include @@ -197,6 +199,8 @@ int ipe_process_event(const struct file *file, enum ipe_op op, if (IS_ERR(ctx)) goto cleanup; + ipe_pin_superblock(ctx->file); + rc = evaluate(ctx); cleanup: diff --git a/security/ipe/ipe-hooks.c b/security/ipe/ipe-hooks.c index 071c4af23a3d..45efe022be04 100644 --- a/security/ipe/ipe-hooks.c +++ b/security/ipe/ipe-hooks.c @@ -6,6 +6,7 @@ #include "ipe.h" #include "ipe-hooks.h" #include "ipe-engine.h" +#include "ipe-pin.h" #include #include @@ -147,3 +148,21 @@ int ipe_on_kernel_load_data(enum kernel_load_data_id id) ipe_hook_kernel_load); } } + +/** + * ipe_sb_free_security: LSM hook called on sb_free_security. + * @mnt_sb: Super block that is being freed. + * + * IPE does not currently utilize the super block security hook, + * it utilizes this hook to invalidate the saved super block for + * the boot_verified property. + * + * For more information, see the LSM hook, sb_free_security. + * + * Return: + * 0 - OK + */ +void ipe_sb_free_security(struct super_block *mnt_sb) +{ + ipe_invalidate_pinned_sb(mnt_sb); +} diff --git a/security/ipe/ipe-hooks.h b/security/ipe/ipe-hooks.h index 806659b7cdbe..5e46726f2562 100644 --- a/security/ipe/ipe-hooks.h +++ b/security/ipe/ipe-hooks.h @@ -58,4 +58,6 @@ int ipe_on_kernel_read(struct file *file, enum kernel_read_file_id id); int ipe_on_kernel_load_data(enum kernel_load_data_id id); +void ipe_sb_free_security(struct super_block *mnt_sb); + #endif /* IPE_HOOK_H */ diff --git a/security/ipe/ipe-pin.c b/security/ipe/ipe-pin.c new file mode 100644 index ..a963be8e5321 --- /dev/null +++ b/security/ipe/ipe-pin.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * This file has been heavily adapted from the source code of the + * loadpin LSM. The source code for loadpin is co-located in the linux + * tree under security/loadpin/loadpin.c. + * + * Please see loadpin.c for up-to-date information about + * loadpin. + */ + +#include "ipe.h" + +#include +#include +#include +#include +#include +#include +#include + +static DEFINE_SPINLOCK(pinned_sb_spinlock); + +static struct super_block *pinned_sb; + +/** + * ipe_is_from_pinned_sb: Determine if @file originates from the initial + * super block that a file was executed from. + * @file: File to check if it originates from the super block. + * + * Return: + * true - File originates from the initial super block + * false - File does not originate from the initial super block + */ +bool ipe_is_from_pinned_sb(const struct file *file) +{ + bool rv = false; + + spin_lock(&pinned_sb_spinlock); + + /* +* Check if pinned_sb is set: +*
[RFC PATCH v5 06/11] dm-verity: move signature check after tree validation
The CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG introduced by Jaskaran was intended to be used to allow an LSM to enforce verifications for all dm-verity volumes. However, with it's current implementation, this signature verification occurs after the merkel-tree is validated, as a result the signature can pass initial verification by passing a matching root-hash and signature. This results in an unreadable block_device, but that has passed signature validation (and subsequently, would be marked as verified). This change moves the signature verification to after the merkel-tree has finished validation. Signed-off-by: Deven Bowers --- drivers/md/dm-verity-target.c | 44 -- drivers/md/dm-verity-verify-sig.c | 140 ++ drivers/md/dm-verity-verify-sig.h | 24 +++-- drivers/md/dm-verity.h| 2 +- 4 files changed, 134 insertions(+), 76 deletions(-) diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c index eec9f252e935..fabc173aa7b3 100644 --- a/drivers/md/dm-verity-target.c +++ b/drivers/md/dm-verity-target.c @@ -471,9 +471,9 @@ static int verity_verify_io(struct dm_verity_io *io) struct bvec_iter start; unsigned b; struct crypto_wait wait; + int r; for (b = 0; b < io->n_blocks; b++) { - int r; sector_t cur_block = io->block + b; struct ahash_request *req = verity_io_hash_req(v, io); @@ -530,6 +530,16 @@ static int verity_verify_io(struct dm_verity_io *io) return -EIO; } + /* +* At this point, the merkel tree has finished validating. +* if signature was specified, validate the signature here. +*/ + r = verity_verify_root_hash(v); + if (r < 0) { + DMERR_LIMIT("signature mismatch"); + return r; + } + return 0; } @@ -728,7 +738,7 @@ static void verity_status(struct dm_target *ti, status_type_t type, args++; if (v->validated_blocks) args++; - if (v->signature_key_desc) + if (v->sig) args += DM_VERITY_ROOT_HASH_VERIFICATION_OPTS; if (!args) return; @@ -751,9 +761,9 @@ static void verity_status(struct dm_target *ti, status_type_t type, if (v->validated_blocks) DMEMIT(" " DM_VERITY_OPT_AT_MOST_ONCE); sz = verity_fec_status_table(v, sz, result, maxlen); - if (v->signature_key_desc) + if (v->sig) DMEMIT(" " DM_VERITY_ROOT_HASH_VERIFICATION_OPT_SIG_KEY - " %s", v->signature_key_desc); + " %s", v->sig->signature_key_desc); break; } } @@ -819,7 +829,7 @@ static void verity_dtr(struct dm_target *ti) verity_fec_dtr(v); - kfree(v->signature_key_desc); + verity_verify_dtr(v); kfree(v); } @@ -876,8 +886,7 @@ static int verity_alloc_zero_digest(struct dm_verity *v) return r; } -static int verity_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v, -struct dm_verity_sig_opts *verify_args) +static int verity_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v) { int r; unsigned argc; @@ -927,9 +936,7 @@ static int verity_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v, return r; continue; } else if (verity_verify_is_sig_opt_arg(arg_name)) { - r = verity_verify_sig_parse_opt_args(as, v, -verify_args, -&argc, arg_name); + r = verity_verify_sig_parse_opt_args(as, v, &argc); if (r) return r; continue; @@ -960,7 +967,6 @@ static int verity_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v, static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv) { struct dm_verity *v; - struct dm_verity_sig_opts verify_args = {0}; struct dm_arg_set as; unsigned int num; unsigned long long num_ll; @@ -968,7 +974,6 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv) int i; sector_t hash_position; char dummy; - char *root_hash_digest_to_validate; v = kzalloc(sizeof(struct dm_verity), GFP_KERNEL); if (!v) { @@ -1102,7 +1107,6 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv) r = -EINVAL; goto bad; } - root_hash_digest_to_validate = argv[8]; if (strcmp(argv[9], "-")) { v->salt_siz
[RFC PATCH v5 02/11] security: add ipe lsm evaluation loop and audit system
Add the core logic of the IPE LSM, the evaluation loop (engine), a portion of the audit system, and the skeleton of the policy structure. Signed-off-by: Deven Bowers --- MAINTAINERS | 1 + include/uapi/linux/audit.h | 4 + security/Kconfig | 12 +- security/Makefile| 2 + security/ipe/.gitignore | 2 + security/ipe/Kconfig | 44 ++ security/ipe/Makefile| 25 security/ipe/ipe-audit.c | 231 +++ security/ipe/ipe-audit.h | 18 +++ security/ipe/ipe-engine.c| 205 +++ security/ipe/ipe-engine.h| 37 + security/ipe/ipe-hooks.c | 149 security/ipe/ipe-hooks.h | 61 security/ipe/ipe-policy.h| 62 + security/ipe/ipe-prop-internal.h | 37 + security/ipe/ipe-property.c | 142 +++ security/ipe/ipe-property.h | 99 + security/ipe/ipe.c | 67 + security/ipe/ipe.h | 20 +++ 19 files changed, 1212 insertions(+), 6 deletions(-) create mode 100644 security/ipe/.gitignore create mode 100644 security/ipe/Kconfig create mode 100644 security/ipe/Makefile create mode 100644 security/ipe/ipe-audit.c create mode 100644 security/ipe/ipe-audit.h create mode 100644 security/ipe/ipe-engine.c create mode 100644 security/ipe/ipe-engine.h create mode 100644 security/ipe/ipe-hooks.c create mode 100644 security/ipe/ipe-hooks.h create mode 100644 security/ipe/ipe-policy.h create mode 100644 security/ipe/ipe-prop-internal.h create mode 100644 security/ipe/ipe-property.c create mode 100644 security/ipe/ipe-property.h create mode 100644 security/ipe/ipe.c create mode 100644 security/ipe/ipe.h diff --git a/MAINTAINERS b/MAINTAINERS index 86450be5437b..bed30cc1cfd7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8584,6 +8584,7 @@ M:Deven Bowers L: linux-integr...@vger.kernel.org S: Supported F: scripts/ipe/ +F: security/ipe/ INTEL 810/815 FRAMEBUFFER DRIVER M: Antonino Daplas diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index 9b6a973f4cc3..5a634cca1d42 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -154,6 +154,10 @@ #define AUDIT_INTEGRITY_RULE 1805 /* policy rule */ #define AUDIT_INTEGRITY_EVM_XATTR 1806 /* New EVM-covered xattr */ #define AUDIT_INTEGRITY_POLICY_RULE 1807 /* IMA policy rules */ +#define AUDIT_INTEGRITY_POLICY_LOAD1808 /* IPE Policy Load */ +#define AUDIT_INTEGRITY_POLICY_ACTIVATE1809 /* IPE Policy Activation */ +#define AUDIT_INTEGRITY_EVENT 1810 /* IPE Evaluation Event */ +#define AUDIT_INTEGRITY_MODE 1811 /* IPE Mode Switch */ #define AUDIT_KERNEL 2000/* Asynchronous audit record. NOT A REQUEST. */ diff --git a/security/Kconfig b/security/Kconfig index cd3cc7da3a55..94924556b637 100644 --- a/security/Kconfig +++ b/security/Kconfig @@ -238,6 +238,7 @@ source "security/loadpin/Kconfig" source "security/yama/Kconfig" source "security/safesetid/Kconfig" source "security/lockdown/Kconfig" +source "security/ipe/Kconfig" source "security/integrity/Kconfig" @@ -277,11 +278,11 @@ endchoice config LSM string "Ordered list of enabled LSMs" - default "lockdown,yama,loadpin,safesetid,integrity,smack,selinux,tomoyo,apparmor,bpf" if DEFAULT_SECURITY_SMACK - default "lockdown,yama,loadpin,safesetid,integrity,apparmor,selinux,smack,tomoyo,bpf" if DEFAULT_SECURITY_APPARMOR - default "lockdown,yama,loadpin,safesetid,integrity,tomoyo,bpf" if DEFAULT_SECURITY_TOMOYO - default "lockdown,yama,loadpin,safesetid,integrity,bpf" if DEFAULT_SECURITY_DAC - default "lockdown,yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor,bpf" + default "lockdown,yama,loadpin,ipe,safesetid,integrity,smack,selinux,tomoyo,apparmor,bpf" if DEFAULT_SECURITY_SMACK + default "lockdown,yama,loadpin,ipe,safesetid,integrity,apparmor,selinux,smack,tomoyo,bpf" if DEFAULT_SECURITY_APPARMOR + default "lockdown,yama,loadpin,ipe,safesetid,integrity,tomoyo,bpf" if DEFAULT_SECURITY_TOMOYO + default "lockdown,yama,loadpin,ipe,safesetid,integrity,bpf" if DEFAULT_SECURITY_DAC + default "lockdown,yama,loadpin,ipe,safesetid,integrity,selinux,smack,tomoyo,apparmor,bpf" help A comma-separated list of LSMs, in initialization order. Any LSMs left off this list will be ignored. This can be @@ -292,4 +293,3 @@ config LSM source "security/Kconfig.hardening" endmenu - diff --git a/security/Makefile b/security/Makefile index 3baf435de541..48bd063d66e1 100644 --- a/security/Makefile +++ b/security/Makefile @@ -13,6 +13,7 @@ subdir-$(CONFIG_SECURITY_LOADPIN) += loadpin subdir-$(CONFIG_SECURITY_SAFESETID)+= safesetid subdir-$(CONFIG_SECURITY_LOCKDOWN_
[RFC PATCH v5 01/11] scripts: add ipe tooling to generate boot policy
Add a tool for the generation of an IPE policy to be compiled into the kernel. This policy will be enforced until userland deploys and activates a new policy. Signed-off-by: Deven Bowers --- MAINTAINERS | 6 ++ scripts/Makefile | 1 + scripts/ipe/Makefile | 2 + scripts/ipe/polgen/.gitignore | 1 + scripts/ipe/polgen/Makefile | 7 ++ scripts/ipe/polgen/polgen.c | 136 ++ 6 files changed, 153 insertions(+) create mode 100644 scripts/ipe/Makefile create mode 100644 scripts/ipe/polgen/.gitignore create mode 100644 scripts/ipe/polgen/Makefile create mode 100644 scripts/ipe/polgen/polgen.c diff --git a/MAINTAINERS b/MAINTAINERS index d53db30d1365..86450be5437b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8579,6 +8579,12 @@ S: Supported T: git git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity.git F: security/integrity/ima/ +INTEGRITY POLICY ENFORCEMENT (IPE) +M: Deven Bowers +L: linux-integr...@vger.kernel.org +S: Supported +F: scripts/ipe/ + INTEL 810/815 FRAMEBUFFER DRIVER M: Antonino Daplas L: linux-fb...@vger.kernel.org diff --git a/scripts/Makefile b/scripts/Makefile index 95ecf970c74c..b3c1882fd6dd 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -34,6 +34,7 @@ hostprogs += unifdef subdir-$(CONFIG_GCC_PLUGINS) += gcc-plugins subdir-$(CONFIG_MODVERSIONS) += genksyms subdir-$(CONFIG_SECURITY_SELINUX) += selinux +subdir-$(CONFIG_SECURITY_IPE) += ipe # Let clean descend into subdirs subdir-+= basic dtc gdb kconfig mod diff --git a/scripts/ipe/Makefile b/scripts/ipe/Makefile new file mode 100644 index ..e87553fbb8d6 --- /dev/null +++ b/scripts/ipe/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0-only +subdir-y := polgen diff --git a/scripts/ipe/polgen/.gitignore b/scripts/ipe/polgen/.gitignore new file mode 100644 index ..80f32f25d200 --- /dev/null +++ b/scripts/ipe/polgen/.gitignore @@ -0,0 +1 @@ +polgen diff --git a/scripts/ipe/polgen/Makefile b/scripts/ipe/polgen/Makefile new file mode 100644 index ..a519b594e13c --- /dev/null +++ b/scripts/ipe/polgen/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0 +hostprogs-y:= polgen +HOST_EXTRACFLAGS += \ + -I$(srctree)/include \ + -I$(srctree)/include/uapi \ + +always := $(hostprogs-y) diff --git a/scripts/ipe/polgen/polgen.c b/scripts/ipe/polgen/polgen.c new file mode 100644 index ..a80fffe1b27c --- /dev/null +++ b/scripts/ipe/polgen/polgen.c @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) Microsoft Corporation. All rights reserved. + */ + +#include +#include +#include +#include +#include + +static void usage(const char *const name) +{ + printf("Usage: %s OutputFile (PolicyFile)\n", name); + exit(EINVAL); +} + +static int policy_to_buffer(const char *pathname, char **buffer, size_t *size) +{ + int rc = 0; + FILE *fd; + char *lbuf; + size_t fsize; + size_t read; + + fd = fopen(pathname, "r"); + if (!fd) { + rc = errno; + goto out; + } + + fseek(fd, 0, SEEK_END); + fsize = ftell(fd); + rewind(fd); + + lbuf = malloc(fsize); + if (!lbuf) { + rc = ENOMEM; + goto out_close; + } + + read = fread((void *)lbuf, sizeof(*lbuf), fsize, fd); + if (read != fsize) { + rc = -1; + goto out_free; + } + + *buffer = lbuf; + *size = fsize; + fclose(fd); + + return rc; + +out_free: + free(lbuf); +out_close: + fclose(fd); +out: + return rc; +} + +static int write_boot_policy(const char *pathname, const char *buf, size_t size) +{ + FILE *fd; + size_t i; + + fd = fopen(pathname, "w"); + if (!fd) + goto err; + + fprintf(fd, "/* This file is automatically generated."); + fprintf(fd, " Do not edit. */\n"); + fprintf(fd, "#include \n"); + fprintf(fd, "const char *const ipe_boot_policy =\n"); + + if (!buf || size == 0) { + fprintf(fd, "\tNULL;\n"); + fclose(fd); + return 0; + } + + for (i = 0; i < size; ++i) { + if (i == 0) + fprintf(fd, "\t\""); + + switch (buf[i]) { + case '"': + fprintf(fd, "\\\""); + break; + case '\'': + fprintf(fd, "'"); + break; + case '\n': + fprintf(fd, "\\n\"\n\t\""); + break; + case '\\': + fprintf(fd, ""); + break; + default: + fprintf(fd, "%c", buf[i]); + } + } +
[RFC PATCH v5 08/11] ipe: add property for signed dmverity volumes
Allow IPE to leverage the stacked security blob infrastructure, and enlighten IPE to the block_device security blob. This allows IPE to have a property to express rules around a device-mapper verity volume whose root-hash has been signed, and the signature has been verified against the system keyring. This is property is also added in this patch. Signed-off-by: Deven Bowers --- security/ipe/Kconfig | 2 +- security/ipe/Makefile| 1 + security/ipe/ipe-blobs.c | 84 security/ipe/ipe-blobs.h | 18 + security/ipe/ipe-engine.c| 4 + security/ipe/ipe-engine.h| 9 +++ security/ipe/ipe-hooks.c | 1 + security/ipe/ipe-hooks.h | 7 ++ security/ipe/ipe.c | 18 + security/ipe/ipe.h | 2 + security/ipe/properties/Kconfig | 10 +++ security/ipe/properties/Makefile | 1 + security/ipe/properties/dmverity-signature.c | 82 +++ security/ipe/properties/prop-entry.h | 9 +++ security/ipe/utility.h | 10 +++ 15 files changed, 257 insertions(+), 1 deletion(-) create mode 100644 security/ipe/ipe-blobs.c create mode 100644 security/ipe/ipe-blobs.h create mode 100644 security/ipe/properties/dmverity-signature.c diff --git a/security/ipe/Kconfig b/security/ipe/Kconfig index 469ef78c2f4f..11b50ef9abca 100644 --- a/security/ipe/Kconfig +++ b/security/ipe/Kconfig @@ -5,7 +5,7 @@ menuconfig SECURITY_IPE bool "Integrity Policy Enforcement (IPE)" - depends on SECURITY && AUDIT + depends on SECURITY && AUDIT && BLOCK select SYSTEM_DATA_VERIFICATION select SECURITYFS select CRYPTO_SHA1 diff --git a/security/ipe/Makefile b/security/ipe/Makefile index 7e98982c5035..98a2245b6956 100644 --- a/security/ipe/Makefile +++ b/security/ipe/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_SECURITY_IPE) += \ ipe-property.o \ ipe-hooks.o \ ipe-secfs.o \ + ipe-blobs.o \ clean-files := ipe-bp.c diff --git a/security/ipe/ipe-blobs.c b/security/ipe/ipe-blobs.c new file mode 100644 index ..041d7d47b723 --- /dev/null +++ b/security/ipe/ipe-blobs.c @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) Microsoft Corporation. All rights reserved. + */ + +#include "ipe.h" +#include "ipe-engine.h" +#include "ipe-blobs.h" + +#include +#include +#include + +/** + * ipe_bdev_alloc_security: Performs the initialization of IPE's security blob. + * @bdev: The block device to source the security blob from. + * + * The allocation is performed earlier by the LSM infrastructure, + * (on behalf of all LSMs) in lsm_alloc_bdev. At the moment, IPE uses + * this time to zero out the region of memory reserved for IPE. + * + * Return: + * 0 - OK + */ +int ipe_bdev_alloc_security(struct block_device *bdev) +{ + struct ipe_bdev_blob *bdev_sec = ipe_bdev(bdev); + + memset(bdev_sec, 0x0, sizeof(*bdev_sec)); + + return 0; +} + +/** + * ipe_bdev_free_security: Frees all fields of IPE's block dev security blob. + * @bdev: The block device to source the security blob from. + * + * The deallocation of the blob itself is performed later by the LSM + * infrastructure, (on behalf of all LSMs) in lsm_free_bdev. + * + * Pointers allocated by the bdev_setsecurity hook and alloc_security + * hook need to be deallocated here. + */ +void ipe_bdev_free_security(struct block_device *bdev) +{ + struct ipe_bdev_blob *bdev_sec = ipe_bdev(bdev); + + kfree(bdev_sec->dmverity_rh_sig); + + memset(bdev_sec, 0x0, sizeof(*bdev_sec)); +} + +/** + * ipe_bdev_setsecurity: Sets the a certain field of a block device security + * blob, based on @key. + * @bdev: The block device to source the security blob from. + * @key: The key representing the information to be stored. + * @value: The value to be stored. + * @len: The length of @value. + * + * As block-devices are a generic implementation across specific stacks, + * this allows information to be stored from various stacks. + * + * Return: + * 0 - OK + * !0 - Error + */ +int ipe_bdev_setsecurity(struct block_device *bdev, const char *key, +const void *value, size_t len) +{ + struct ipe_bdev_blob *bdev_sec = ipe_bdev(bdev); + + if (!strcmp(key, DM_VERITY_SIGNATURE_SEC_NAME)) { + bdev_sec->dmverity_rh_sig = kmemdup(value, len, GFP_KERNEL); + if (!bdev_sec->dmverity_rh_sig) + return -ENOMEM; + + bdev_sec->dmv_rh_sig_len = len; + + return 0; + } + + return -ENOSYS; +} diff --git a/security/ipe/ipe-blobs.h b/security/ipe/ipe-blobs.h new file mode 100644 index ..7561f4cef558 --- /dev/null +++ b/security/ipe/ipe-blobs.h @@ -0,0 +1,18 @@ +/*
[RFC PATCH v5 03/11] security: add ipe lsm policy parser and policy loading
Adds the policy parser and the policy loading to IPE, along with the related securityfs entries and audit events. Signed-off-by: Deven Bowers --- security/ipe/Kconfig |2 + security/ipe/Makefile|3 + security/ipe/ipe-audit.c | 74 +- security/ipe/ipe-audit.h |6 + security/ipe/ipe-parse.c | 889 security/ipe/ipe-parse.h | 17 + security/ipe/ipe-policy.c| 149 security/ipe/ipe-policy.h| 13 +- security/ipe/ipe-prop-internal.h | 18 +- security/ipe/ipe-property.c |9 +- security/ipe/ipe-property.h |1 + security/ipe/ipe-secfs.c | 1309 ++ security/ipe/ipe-secfs.h | 14 + 13 files changed, 2493 insertions(+), 11 deletions(-) create mode 100644 security/ipe/ipe-parse.c create mode 100644 security/ipe/ipe-parse.h create mode 100644 security/ipe/ipe-policy.c create mode 100644 security/ipe/ipe-secfs.c create mode 100644 security/ipe/ipe-secfs.h diff --git a/security/ipe/Kconfig b/security/ipe/Kconfig index 7615109a19ca..665524fc3ca4 100644 --- a/security/ipe/Kconfig +++ b/security/ipe/Kconfig @@ -7,6 +7,8 @@ menuconfig SECURITY_IPE bool "Integrity Policy Enforcement (IPE)" depends on SECURITY && AUDIT select SYSTEM_DATA_VERIFICATION + select SECURITYFS + select CRYPTO_SHA1 help This option enables the Integrity Policy Enforcement subsystem allowing systems to enforce integrity having no dependencies diff --git a/security/ipe/Makefile b/security/ipe/Makefile index 40565b73fac2..7d6da33dd0c4 100644 --- a/security/ipe/Makefile +++ b/security/ipe/Makefile @@ -19,7 +19,10 @@ obj-$(CONFIG_SECURITY_IPE) += \ ipe-audit.o \ ipe-bp.o \ ipe-engine.o \ + ipe-parse.o \ + ipe-policy.o \ ipe-property.o \ ipe-hooks.o \ + ipe-secfs.o \ clean-files := ipe-bp.c diff --git a/security/ipe/ipe-audit.c b/security/ipe/ipe-audit.c index 2c754851bd40..0e731025f2f5 100644 --- a/security/ipe/ipe-audit.c +++ b/security/ipe/ipe-audit.c @@ -17,7 +17,8 @@ #include #define ACTION_STR(a) ((a) == ipe_action_allow ? "ALLOW" : "DENY") - +#define POLICY_LOAD_FSTR "IPE policy_name=\"%s\" policy_version=%hu.%hu.%hu sha1=" +#define POLICY_ACTIVATE_STR"IPE policy_name=\"%s\" policy_version=%hu.%hu.%hu" #define IPE_UNKNOWN"UNKNOWN" /* Keep in sync with ipe_op in ipe-hooks.h */ @@ -229,3 +230,74 @@ void ipe_audit_match(const struct ipe_engine_ctx *ctx, audit_log_end(ab); } + +/** + * ipe_audit_policy_load: Emit an audit event that an IPE policy has been + * loaded, with the name of the policy, the policy + * version triple, and a flat hash of the content. + * @pol: The parsed policy to derive the policy_name and policy_version + * triple. + * @raw: The raw content that was passed to the ipe.policy sysctl to derive + * the sha1 hash. + * @raw_size: the length of @raw. + * @tfm: shash structure allocated by the caller, used to fingerprint the + * policy being deployed + */ +void ipe_audit_policy_load(const struct ipe_policy *pol, const uint8_t *raw, + size_t raw_size, struct crypto_shash *tfm) +{ + int rc = 0; + struct audit_buffer *ab; + u8 digest[SHA1_DIGEST_SIZE]; + SHASH_DESC_ON_STACK(desc, tfm); + + ab = audit_log_start(audit_context(), GFP_KERNEL, +AUDIT_INTEGRITY_POLICY_LOAD); + if (!ab) + return; + + audit_log_format(ab, POLICY_LOAD_FSTR, pol->policy_name, +pol->policy_version.major, pol->policy_version.minor, +pol->policy_version.rev); + + desc->tfm = tfm; + + if (crypto_shash_init(desc) != 0) + goto err; + + if (crypto_shash_update(desc, raw, raw_size) != 0) + goto err; + + if (crypto_shash_final(desc, digest) != 0) + goto err; + + audit_log_n_hex(ab, digest, crypto_shash_digestsize(tfm)); + +err: + if (rc != 0) + audit_log_format(ab, "ERR(%d)", rc); + + audit_log_end(ab); +} + +/** + * ipe_audit_policy_activation: Emit an audit event that a specific policy + * was activated as the active policy. + * @pol: policy that is being activated + */ +void ipe_audit_policy_activation(const struct ipe_policy *pol) +{ + struct audit_buffer *ab; + + ab = audit_log_start(audit_context(), GFP_KERNEL, +AUDIT_INTEGRITY_POLICY_ACTIVATE); + + if (!ab) + return; + + audit_log_format(ab, POLICY_ACTIVATE_STR, pol->policy_name, +pol->policy_version.major, pol->policy_version.minor, +pol->policy_version.rev); + + audit_log_end(ab); +} diff --git a/security/ipe/i
[RFC PATCH v5 12/12] cleanup: uapi/linux/audit.h
Remove trailing whitespaces and align the integrity #defines in linux/uapi/audit.h Signed-off-by: Deven Bowers --- include/uapi/linux/audit.h | 32 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index 5a634cca1d42..609b4a5e8a80 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -48,7 +48,7 @@ * 2500 - 2999 future user space (maybe integrity labels and related events) * * Messages from 1000-1199 are bi-directional. 1200-1299 & 2100 - 2999 are - * exclusively user space. 1300-2099 is kernel --> user space + * exclusively user space. 1300-2099 is kernel --> user space * communication. */ #define AUDIT_GET 1000/* Get status */ @@ -78,7 +78,7 @@ #define AUDIT_LAST_USER_MSG1199 #define AUDIT_FIRST_USER_MSG2 2100/* More user space messages */ #define AUDIT_LAST_USER_MSG2 2999 - + #define AUDIT_DAEMON_START 1200/* Daemon startup record */ #define AUDIT_DAEMON_END1201/* Daemon normal stop record */ #define AUDIT_DAEMON_ABORT 1202/* Daemon error stop record */ @@ -140,20 +140,20 @@ #define AUDIT_MAC_CALIPSO_ADD 1418/* NetLabel: add CALIPSO DOI entry */ #define AUDIT_MAC_CALIPSO_DEL 1419/* NetLabel: del CALIPSO DOI entry */ -#define AUDIT_FIRST_KERN_ANOM_MSG 1700 -#define AUDIT_LAST_KERN_ANOM_MSG1799 -#define AUDIT_ANOM_PROMISCUOUS 1700 /* Device changed promiscuous mode */ -#define AUDIT_ANOM_ABEND1701 /* Process ended abnormally */ -#define AUDIT_ANOM_LINK1702 /* Suspicious use of file links */ -#define AUDIT_ANOM_CREAT 1703 /* Suspicious file creation */ -#define AUDIT_INTEGRITY_DATA 1800 /* Data integrity verification */ -#define AUDIT_INTEGRITY_METADATA1801 /* Metadata integrity verification */ -#define AUDIT_INTEGRITY_STATUS 1802 /* Integrity enable status */ -#define AUDIT_INTEGRITY_HASH 1803 /* Integrity HASH type */ -#define AUDIT_INTEGRITY_PCR1804 /* PCR invalidation msgs */ -#define AUDIT_INTEGRITY_RULE 1805 /* policy rule */ -#define AUDIT_INTEGRITY_EVM_XATTR 1806 /* New EVM-covered xattr */ -#define AUDIT_INTEGRITY_POLICY_RULE 1807 /* IMA policy rules */ +#define AUDIT_FIRST_KERN_ANOM_MSG 1700 +#define AUDIT_LAST_KERN_ANOM_MSG 1799 +#define AUDIT_ANOM_PROMISCUOUS 1700 /* Device changed promiscuous mode */ +#define AUDIT_ANOM_ABEND 1701 /* Process ended abnormally */ +#define AUDIT_ANOM_LINK1702 /* Suspicious use of file links */ +#define AUDIT_ANOM_CREAT 1703 /* Suspicious file creation */ +#define AUDIT_INTEGRITY_DATA 1800 /* Data integrity verification */ +#define AUDIT_INTEGRITY_METADATA 1801 /* Metadata integrity verification */ +#define AUDIT_INTEGRITY_STATUS 1802 /* Integrity enable status */ +#define AUDIT_INTEGRITY_HASH 1803 /* Integrity HASH type */ +#define AUDIT_INTEGRITY_PCR1804 /* PCR invalidation msgs */ +#define AUDIT_INTEGRITY_RULE 1805 /* policy rule */ +#define AUDIT_INTEGRITY_EVM_XATTR 1806 /* New EVM-covered xattr */ +#define AUDIT_INTEGRITY_POLICY_RULE1807 /* IMA policy rules */ #define AUDIT_INTEGRITY_POLICY_LOAD1808 /* IPE Policy Load */ #define AUDIT_INTEGRITY_POLICY_ACTIVATE1809 /* IPE Policy Activation */ #define AUDIT_INTEGRITY_EVENT 1810 /* IPE Evaluation Event */ -- 2.27.0 -- Linux-audit mailing list Linux-audit@redhat.com https://www.redhat.com/mailman/listinfo/linux-audit
Re: [RFC PATCH v5 06/11] dm-verity: move signature check after tree validation
On Tue, Jul 28, 2020 at 02:36:06PM -0700, Deven Bowers wrote: > The CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG introduced by Jaskaran was > intended to be used to allow an LSM to enforce verifications for all > dm-verity volumes. > > However, with it's current implementation, this signature verification > occurs after the merkel-tree is validated, as a result the signature can > pass initial verification by passing a matching root-hash and signature. > This results in an unreadable block_device, but that has passed signature > validation (and subsequently, would be marked as verified). > > This change moves the signature verification to after the merkel-tree has > finished validation. > > Signed-off-by: Deven Bowers > --- > drivers/md/dm-verity-target.c | 44 -- > drivers/md/dm-verity-verify-sig.c | 140 ++ > drivers/md/dm-verity-verify-sig.h | 24 +++-- > drivers/md/dm-verity.h| 2 +- > 4 files changed, 134 insertions(+), 76 deletions(-) > > diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c > index eec9f252e935..fabc173aa7b3 100644 > --- a/drivers/md/dm-verity-target.c > +++ b/drivers/md/dm-verity-target.c > @@ -471,9 +471,9 @@ static int verity_verify_io(struct dm_verity_io *io) > struct bvec_iter start; > unsigned b; > struct crypto_wait wait; > + int r; > > for (b = 0; b < io->n_blocks; b++) { > - int r; > sector_t cur_block = io->block + b; > struct ahash_request *req = verity_io_hash_req(v, io); > > @@ -530,6 +530,16 @@ static int verity_verify_io(struct dm_verity_io *io) > return -EIO; > } > > + /* > + * At this point, the merkel tree has finished validating. > + * if signature was specified, validate the signature here. > + */ > + r = verity_verify_root_hash(v); > + if (r < 0) { > + DMERR_LIMIT("signature mismatch"); > + return r; > + } > + > return 0; > } This doesn't make any sense. This just moves the signature verification to some random I/O. The whole point of dm-verity is that data is verified on demand. You can't know whether any particular data or hash block is consistent with the root hash or not until it is read and verified. When the first I/O completes it might have just checked one block of a billion. Not to mention that you didn't consider locking at all. - Eric -- Linux-audit mailing list Linux-audit@redhat.com https://www.redhat.com/mailman/listinfo/linux-audit
Re: [RFC PATCH v5 05/11] fs: add security blob and hooks for block_device
On 7/28/2020 2:36 PM, Deven Bowers wrote: > Add a security blob and associated allocation, deallocation and set hooks > for a block_device structure. > > Signed-off-by: Deven Bowers > --- > fs/block_dev.c| 8 > include/linux/fs.h| 1 + > include/linux/lsm_hook_defs.h | 5 +++ > include/linux/lsm_hooks.h | 12 ++ > include/linux/security.h | 22 +++ > security/security.c | 74 +++ > 6 files changed, 122 insertions(+) > > diff --git a/fs/block_dev.c b/fs/block_dev.c > index 0ae656e022fd..8602dd62c3e2 100644 > --- a/fs/block_dev.c > +++ b/fs/block_dev.c > @@ -34,6 +34,7 @@ > #include > #include > #include > +#include > #include "internal.h" > > struct bdev_inode { > @@ -768,11 +769,18 @@ static struct inode *bdev_alloc_inode(struct > super_block *sb) > struct bdev_inode *ei = kmem_cache_alloc(bdev_cachep, GFP_KERNEL); > if (!ei) > return NULL; > + > + if (unlikely(security_bdev_alloc(&ei->bdev))) { > + kmem_cache_free(bdev_cachep, ei); > + return NULL; > + } > + > return &ei->vfs_inode; > } > > static void bdev_free_inode(struct inode *inode) > { > + security_bdev_free(&BDEV_I(inode)->bdev); > kmem_cache_free(bdev_cachep, BDEV_I(inode)); > } > > diff --git a/include/linux/fs.h b/include/linux/fs.h > index f5abba86107d..42d7e3ce7712 100644 > --- a/include/linux/fs.h > +++ b/include/linux/fs.h > @@ -509,6 +509,7 @@ struct block_device { > int bd_fsfreeze_count; > /* Mutex for freeze */ > struct mutexbd_fsfreeze_mutex; > + void*security; > } __randomize_layout; > > /* XArray tags, for tagging dirty and writeback pages in the pagecache. */ > diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h > index af998f93d256..f3c0da0db4e8 100644 > --- a/include/linux/lsm_hook_defs.h > +++ b/include/linux/lsm_hook_defs.h > @@ -391,3 +391,8 @@ LSM_HOOK(void, LSM_RET_VOID, perf_event_free, struct > perf_event *event) > LSM_HOOK(int, 0, perf_event_read, struct perf_event *event) > LSM_HOOK(int, 0, perf_event_write, struct perf_event *event) > #endif /* CONFIG_PERF_EVENTS */ > + > +LSM_HOOK(int, 0, bdev_alloc_security, struct block_device *bdev) > +LSM_HOOK(void, LSM_RET_VOID, bdev_free_security, struct block_device *bdev) > +LSM_HOOK(int, 0, bdev_setsecurity, struct block_device *bdev, const char > *name, > + const void *value, size_t size) > diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h > index 95b7c1d32062..8670c19a8cef 100644 > --- a/include/linux/lsm_hooks.h > +++ b/include/linux/lsm_hooks.h > @@ -1507,6 +1507,17 @@ > * > * @what: kernel feature being accessed > * > + * @bdev_alloc_security: > + * Initialize the security field inside a block_device structure. > + * > + * @bdev_free_security: > + * Cleanup the security information stored inside a block_device structure. > + * > + * @bdev_setsecurity: > + * Set a security property associated with @name for @bdev with > + * value @value. @size indicates the size of @value in bytes. > + * If a @name is not implemented, return -ENOSYS. > + * > * Security hooks for perf events > * > * @perf_event_open: > @@ -1553,6 +1564,7 @@ struct lsm_blob_sizes { > int lbs_ipc; > int lbs_msg_msg; > int lbs_task; > + int lbs_bdev; > }; > > /* > diff --git a/include/linux/security.h b/include/linux/security.h > index 0a0a03b36a3b..8f83fdc6c65d 100644 > --- a/include/linux/security.h > +++ b/include/linux/security.h > @@ -451,6 +451,11 @@ int security_inode_notifysecctx(struct inode *inode, > void *ctx, u32 ctxlen); > int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen); > int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen); > int security_locked_down(enum lockdown_reason what); > +int security_bdev_alloc(struct block_device *bdev); > +void security_bdev_free(struct block_device *bdev); > +int security_bdev_setsecurity(struct block_device *bdev, > + const char *name, const void *value, > + size_t size); > #else /* CONFIG_SECURITY */ > > static inline int call_blocking_lsm_notifier(enum lsm_event event, void > *data) > @@ -1291,6 +1296,23 @@ static inline int security_locked_down(enum > lockdown_reason what) > { > return 0; > } > + > +static inline int security_bdev_alloc(struct block_device *bdev) > +{ > + return 0; > +} > + > +static inline void security_bdev_free(struct block_device *bdev) > +{ > +} > + > +static inline int security_bdev_setsecurity(struct block_device *bdev, > + const char *name, > + const void *value, size_t size) > +{ > + return 0; > +} > + > #endif /* CONFIG_SECURITY */ > > #if
Re: [PATCH v19 06/23] LSM: Use lsmblob in security_secctx_to_secid
On 7/28/2020 4:11 AM, John Johansen wrote: > On 7/24/20 1:32 PM, Casey Schaufler wrote: >> Change security_secctx_to_secid() to fill in a lsmblob instead >> of a u32 secid. Multiple LSMs may be able to interpret the >> string, and this allows for setting whichever secid is >> appropriate. Change security_secmark_relabel_packet() to use a >> lsmblob instead of a u32 secid. In some other cases there is >> scaffolding where interfaces have yet to be converted. >> >> Reviewed-by: Kees Cook >> Signed-off-by: Casey Schaufler >> Cc: net...@vger.kernel.org > one comment below, but its a nice to have so > > Reviewed-by: John Johansen > > >> --- >> include/linux/security.h | 30 +++ >> include/net/scm.h | 7 +-- >> kernel/cred.c | 4 +--- >> net/ipv4/ip_sockglue.c| 6 -- >> net/netfilter/nft_meta.c | 18 +--- >> net/netfilter/xt_SECMARK.c| 9 ++-- >> net/netlabel/netlabel_unlabeled.c | 23 + >> security/security.c | 34 ++- >> 8 files changed, 98 insertions(+), 33 deletions(-) >> >> diff --git a/include/linux/security.h b/include/linux/security.h >> index d81e8886d799..98176faaaba5 100644 >> --- a/include/linux/security.h >> +++ b/include/linux/security.h >> @@ -189,6 +189,27 @@ static inline bool lsmblob_equal(struct lsmblob *bloba, >> struct lsmblob *blobb) >> return !memcmp(bloba, blobb, sizeof(*bloba)); >> } >> >> +/** >> + * lsmblob_value - find the first non-zero value in an lsmblob structure. >> + * @blob: Pointer to the data >> + * >> + * This needs to be used with extreme caution, as the cases where >> + * it is appropriate are rare. >> + * >> + * Return the first secid value set in the lsmblob. >> + * There should only be one. > It would be really nice if we could have an LSM debug config, that would > do things like checking there is indeed only one value when this fn > is called. I can't see a CONFIG_LSM_DEBUG for this alone, but if you have other places you'd like to see it I'm open to it. -- Linux-audit mailing list Linux-audit@redhat.com https://www.redhat.com/mailman/listinfo/linux-audit
Re: [PATCH V3fix ghak120] audit: initialize context values in case of mandatory events
On 2020-07-28 14:47, Paul Moore wrote: > On Tue, Jul 28, 2020 at 12:27 PM Richard Guy Briggs wrote: > > I know you like only really minimal fixes this late, but this seemed > > pretty minimal to me... > > Minimal is a one (two?) line NULL check in audit_log_name(), this > patch is not that. I didn't try and test that since I'm not sure that would have worked because there appeared to be a low non-NULL value in it. brauer1's trace had 0x60 and mine had 0xd0. Or am I missing something obvious? The patch provided the information rather than ignoring the problem (which maybe should have been caught by WARN_ONCE?). > paul moore - RGB -- Richard Guy Briggs Sr. S/W Engineer, Kernel Security, Base Operating Systems Remote, Ottawa, Red Hat Canada IRC: rgb, SunRaycer Voice: +1.647.777.2635, Internal: (81) 32635 -- Linux-audit mailing list Linux-audit@redhat.com https://www.redhat.com/mailman/listinfo/linux-audit