public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Roberto Sassu <roberto.sassu@huawei.com>
To: KP Singh <kpsingh@kernel.org>, Daniel Borkmann <daniel@iogearbox.net>
Cc: "ast@kernel.org" <ast@kernel.org>,
	"andrii@kernel.org" <andrii@kernel.org>,
	"john.fastabend@gmail.com" <john.fastabend@gmail.com>,
	"songliubraving@fb.com" <songliubraving@fb.com>,
	"kafai@fb.com" <kafai@fb.com>, "yhs@fb.com" <yhs@fb.com>,
	"dhowells@redhat.com" <dhowells@redhat.com>,
	"keyrings@vger.kernel.org" <keyrings@vger.kernel.org>,
	"bpf@vger.kernel.org" <bpf@vger.kernel.org>,
	"netdev@vger.kernel.org" <netdev@vger.kernel.org>,
	"linux-kselftest@vger.kernel.org"
	<linux-kselftest@vger.kernel.org>,
	"linux-security-module@vger.kernel.org" 
	<linux-security-module@vger.kernel.org>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>
Subject: RE: [PATCH v6 4/5] bpf: Add bpf_verify_pkcs7_signature() helper
Date: Thu, 7 Jul 2022 11:00:58 +0000	[thread overview]
Message-ID: <52aa81c8037640a7935cdfd6f363a07d@huawei.com> (raw)
In-Reply-To: <CACYkzJ4iR=FurW2UZdgycTdu54kNoFrw4uvmDrpTd3xuvpvVTw@mail.gmail.com>

> From: KP Singh [mailto:kpsingh@kernel.org]
> Sent: Thursday, July 7, 2022 1:49 AM
> On Wed, Jul 6, 2022 at 6:04 PM Daniel Borkmann <daniel@iogearbox.net>
> wrote:
> >
> > On 6/28/22 2:27 PM, Roberto Sassu wrote:
> > > Add the bpf_verify_pkcs7_signature() helper, to give eBPF security modules
> > > the ability to check the validity of a signature against supplied data, by
> > > using user-provided or system-provided keys as trust anchor.
> > >
> > > The new helper makes it possible to enforce mandatory policies, as eBPF
> > > programs might be allowed to make security decisions only based on data
> > > sources the system administrator approves.
> > >
> > > The caller should provide both the data to be verified and the signature as
> > > eBPF dynamic pointers (to minimize the number of parameters).
> > >
> > > The caller should also provide a trusted keyring serial, together with key
> > > lookup-specific flags, to determine which keys can be used for signature
> > > verification. Alternatively, the caller could specify zero as serial value
> > > (not valid, serials must be positive), and provide instead a special
> > > keyring ID.
> > >
> > > Key lookup flags are defined in include/linux/key.h and can be: 1, to
> > > request that special keyrings be created if referred to directly; 2 to
> > > permit partially constructed keys to be found.
> > >
> > > Special IDs are defined in include/linux/verification.h and can be: 0 for
> > > the primary keyring (immutable keyring of system keys); 1 for both the
> > > primary and secondary keyring (where keys can be added only if they are
> > > vouched for by existing keys in those keyrings); 2 for the platform keyring
> > > (primarily used by the integrity subsystem to verify a kexec'ed kerned
> > > image and, possibly, the initramfs signature).
> > >
> > > Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
> > > Reported-by: kernel test robot <lkp@intel.com> (cast warning)
> >
> > nit: Given this a new feature not a fix to existing code, there is no need to
> >       add the above reported-by from kbuild bot.

Ok.

> > > ---
> > >   include/uapi/linux/bpf.h       | 24 +++++++++++++
> > >   kernel/bpf/bpf_lsm.c           | 63 ++++++++++++++++++++++++++++++++++
> > >   tools/include/uapi/linux/bpf.h | 24 +++++++++++++
> > >   3 files changed, 111 insertions(+)
> > >
> > > diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> > > index e81362891596..b4f5ad863281 100644
> > > --- a/include/uapi/linux/bpf.h
> > > +++ b/include/uapi/linux/bpf.h
> > > @@ -5325,6 +5325,29 @@ union bpf_attr {
> > >    *          **-EACCES** if the SYN cookie is not valid.
> > >    *
> > >    *          **-EPROTONOSUPPORT** if CONFIG_IPV6 is not builtin.
> > > + *
> > > + * long bpf_verify_pkcs7_signature(struct bpf_dynptr *data_ptr, struct
> bpf_dynptr *sig_ptr, u32 trusted_keyring_serial, unsigned long lookup_flags,
> unsigned long trusted_keyring_id)
> >
> > nit: for the args instead of ulong, just do u64

Ok.

> > > + *   Description
> > > + *           Verify the PKCS#7 signature *sig_ptr* against the supplied
> > > + *           *data_ptr* with keys in a keyring with serial
> > > + *           *trusted_keyring_serial*, searched with *lookup_flags*, if the
> > > + *           parameter value is positive, or alternatively in a keyring with
> > > + *           special ID *trusted_keyring_id* if *trusted_keyring_serial* is
> > > + *           zero.
> > > + *
> > > + *           *lookup_flags* are defined in include/linux/key.h and can be: 1,
> > > + *           to request that special keyrings be created if referred to
> > > + *           directly; 2 to permit partially constructed keys to be found.
> > > + *
> > > + *           Special IDs are defined in include/linux/verification.h and can
> > > + *           be: 0 for the primary keyring (immutable keyring of system
> > > + *           keys); 1 for both the primary and secondary keyring (where keys
> > > + *           can be added only if they are vouched for by existing keys in
> > > + *           those keyrings); 2 for the platform keyring (primarily used by
> > > + *           the integrity subsystem to verify a kexec'ed kerned image and,
> > > + *           possibly, the initramfs signature).
> > > + *   Return
> > > + *           0 on success, a negative value on error.
> > >    */
> > >   #define __BPF_FUNC_MAPPER(FN)               \
> > >       FN(unspec),                     \
> > > @@ -5535,6 +5558,7 @@ union bpf_attr {
> > >       FN(tcp_raw_gen_syncookie_ipv6), \
> > >       FN(tcp_raw_check_syncookie_ipv4),       \
> > >       FN(tcp_raw_check_syncookie_ipv6),       \
> > > +     FN(verify_pkcs7_signature),     \
> >
> > (Needs rebase)
> >
> > >       /* */
> > >
> > >   /* integer value in 'imm' field of BPF_CALL instruction selects which helper
> > > diff --git a/kernel/bpf/bpf_lsm.c b/kernel/bpf/bpf_lsm.c
> > > index c1351df9f7ee..401bda01ad84 100644
> > > --- a/kernel/bpf/bpf_lsm.c
> > > +++ b/kernel/bpf/bpf_lsm.c
> > > @@ -16,6 +16,8 @@
> > >   #include <linux/bpf_local_storage.h>
> > >   #include <linux/btf_ids.h>
> > >   #include <linux/ima.h>
> > > +#include <linux/verification.h>
> > > +#include <linux/key.h>
> > >
> > >   /* For every LSM hook that allows attachment of BPF programs, declare a
> nop
> > >    * function where a BPF program can be attached.
> > > @@ -132,6 +134,62 @@ static const struct bpf_func_proto
> bpf_get_attach_cookie_proto = {
> > >       .arg1_type      = ARG_PTR_TO_CTX,
> > >   };
> > >
> > > +#ifdef CONFIG_SYSTEM_DATA_VERIFICATION
> > > +BPF_CALL_5(bpf_verify_pkcs7_signature, struct bpf_dynptr_kern *,
> data_ptr,
> > > +        struct bpf_dynptr_kern *, sig_ptr, u32, trusted_keyring_serial,
> > > +        unsigned long, lookup_flags, unsigned long, trusted_keyring_id)
> > > +{
> > > +     key_ref_t trusted_keyring_ref;
> > > +     struct key *trusted_keyring;
> > > +     int ret;
> > > +
> > > +     /* Keep in sync with defs in include/linux/key.h. */
> > > +     if (lookup_flags > KEY_LOOKUP_PARTIAL)
> > > +             return -EINVAL;
> >
> > iiuc, the KEY_LOOKUP_* is a mask, so you could also combine the two, e.g.
> > KEY_LOOKUP_CREATE | KEY_LOOKUP_PARTIAL. I haven't seen you
> mentioning anything
> > specific on why it is not allowed. What's the rationale, if it's intentional
> > if should probably be documented?

It was a mistake. Will fix it.

> I think this was a part of the digilim threat model (only allow
> limited lookup operations),
> but this seems to be conflating the policy into the implementation of
> the helper.

Uhm, yes, but these flags should not affect that requirement.

As long as I can select the primary or secondary keyring reliably
with the pre-determined IDs, that should be fine.

> Roberto, can this not be implemented in digilim as a BPF LSM check
> that attaches to the key_permission LSM hook?
> 
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/li
> nux/lsm_hooks.h#n1158

The pre-determined IDs handled by verify_pkcs7_signature() are
more effective in selecting the proper key.

> > At minimum I also think the helper description needs to be improved for
> people
> > to understand enough w/o reading through the kernel source, e.g. wrt
> lookup_flags
> > since I haven't seen it in your selftests either ... when does a user need to
> > use the given flags.
> >
> > nit: when both trusted_keyring_serial and trusted_keyring_id are passed to the
> > helper, then this should be rejected as invalid argument? (Kind of feels a bit
> > like we're cramming two things in one helper.. KP, thoughts? :))
> 
> EINVAL when both are passed seems reasonable. The signature (pun?) of the
> does seem to get bloated, but I am not sure if it's worth adding two
> helpers here.

Ok for EINVAL. Should I change the trusted_keyring_id type to signed,
and use -1 when it should not be specified?

Thanks

Roberto

> > > +     /* Keep in sync with defs in include/linux/verification.h. */
> > > +     if (trusted_keyring_id > (unsigned
> long)VERIFY_USE_PLATFORM_KEYRING)
> > > +             return -EINVAL;
> > > +
> > > +     if (trusted_keyring_serial) {
> > > +             trusted_keyring_ref = lookup_user_key(trusted_keyring_serial,
> > > +                                                   lookup_flags,
> > > +                                                   KEY_NEED_SEARCH);
> > > +             if (IS_ERR(trusted_keyring_ref))
> > > +                     return PTR_ERR(trusted_keyring_ref);
> > > +
> > > +             trusted_keyring = key_ref_to_ptr(trusted_keyring_ref);
> > > +             goto verify;
> > > +     }
> > > +
> > > +     trusted_keyring = (struct key *)trusted_keyring_id;
> > > +verify:
> > > +     ret = verify_pkcs7_signature(data_ptr->data,
> > > +                                  bpf_dynptr_get_size(data_ptr),
> > > +                                  sig_ptr->data,
> > > +                                  bpf_dynptr_get_size(sig_ptr),
> > > +                                  trusted_keyring,
> > > +                                  VERIFYING_UNSPECIFIED_SIGNATURE, NULL,
> > > +                                  NULL);
> > > +     if (trusted_keyring_serial)
> > > +             key_put(trusted_keyring);
> > > +
> > > +     return ret;
> > > +}
> > > +
> > > +static const struct bpf_func_proto bpf_verify_pkcs7_signature_proto = {
> > > +     .func           = bpf_verify_pkcs7_signature,
> > > +     .gpl_only       = false,
> > > +     .ret_type       = RET_INTEGER,
> > > +     .arg1_type      = ARG_PTR_TO_DYNPTR | DYNPTR_TYPE_LOCAL,
> > > +     .arg2_type      = ARG_PTR_TO_DYNPTR | DYNPTR_TYPE_LOCAL,
> > > +     .arg3_type      = ARG_ANYTHING,
> > > +     .arg4_type      = ARG_ANYTHING,
> > > +     .arg5_type      = ARG_ANYTHING,
> > > +     .allowed        = bpf_ima_inode_hash_allowed,
> > > +};
> > > +#endif /* CONFIG_SYSTEM_DATA_VERIFICATION */
> > > +

  reply	other threads:[~2022-07-07 11:01 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-06-28 12:27 [PATCH v6 0/5] bpf: Add bpf_verify_pkcs7_signature() helper Roberto Sassu
2022-06-28 12:27 ` [PATCH v6 1/5] bpf: Export bpf_dynptr_get_size() Roberto Sassu
2022-06-28 12:27 ` [PATCH v6 2/5] KEYS: Move KEY_LOOKUP_ to include/linux/key.h Roberto Sassu
2022-06-28 12:27 ` [PATCH v6 3/5] scripts: Handle unsigned type prefix in bpf_doc.py Roberto Sassu
2022-06-28 12:27 ` [PATCH v6 4/5] bpf: Add bpf_verify_pkcs7_signature() helper Roberto Sassu
2022-07-06 16:03   ` Daniel Borkmann
2022-07-06 23:49     ` KP Singh
2022-07-07 11:00       ` Roberto Sassu [this message]
2022-07-08 12:12         ` Roberto Sassu
2022-06-28 12:27 ` [PATCH v6 5/5] selftests/bpf: Add test for " Roberto Sassu
2022-06-28 12:32   ` Roberto Sassu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=52aa81c8037640a7935cdfd6f363a07d@huawei.com \
    --to=roberto.sassu@huawei.com \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=dhowells@redhat.com \
    --cc=john.fastabend@gmail.com \
    --cc=kafai@fb.com \
    --cc=keyrings@vger.kernel.org \
    --cc=kpsingh@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=songliubraving@fb.com \
    --cc=yhs@fb.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox