Re: [PATCH V3fix ghak120] audit: initialize context values in case of mandatory events

2020-07-28 Thread Richard Guy Briggs
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

2020-07-28 Thread Paul Moore
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

2020-07-28 Thread John Johansen
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

2020-07-28 Thread John Johansen
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

2020-07-28 Thread John Johansen
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

2020-07-28 Thread John Johansen
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

2020-07-28 Thread John Johansen
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.

2020-07-28 Thread John Johansen
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

2020-07-28 Thread John Johansen
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")

2020-07-28 Thread Paul Moore
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

2020-07-28 Thread Deven Bowers
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

2020-07-28 Thread Deven Bowers
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

2020-07-28 Thread Deven Bowers
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)

2020-07-28 Thread Deven Bowers
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

2020-07-28 Thread Deven Bowers
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

2020-07-28 Thread Deven Bowers
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

2020-07-28 Thread Deven Bowers
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

2020-07-28 Thread Deven Bowers
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

2020-07-28 Thread Deven Bowers
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

2020-07-28 Thread Deven Bowers
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

2020-07-28 Thread Deven Bowers
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

2020-07-28 Thread Deven Bowers
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

2020-07-28 Thread Deven Bowers
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

2020-07-28 Thread Deven Bowers
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

2020-07-28 Thread Deven Bowers
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

2020-07-28 Thread Eric Biggers
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

2020-07-28 Thread Casey Schaufler
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

2020-07-28 Thread Casey Schaufler
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

2020-07-28 Thread Richard Guy Briggs
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