Skip to content

Commit 8cd189e

Browse files
sinkapAlexei Starovoitov
authored andcommitted
bpf: Move the signature kfuncs to helpers.c
No functional changes, except for the addition of the headers for the kfuncs so that they can be used for signature verification. Signed-off-by: KP Singh <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent ea2e646 commit 8cd189e

File tree

3 files changed

+198
-183
lines changed

3 files changed

+198
-183
lines changed

include/linux/bpf.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3424,6 +3424,38 @@ static inline int bpf_fd_reuseport_array_update_elem(struct bpf_map *map,
34243424
#endif /* CONFIG_BPF_SYSCALL */
34253425
#endif /* defined(CONFIG_INET) && defined(CONFIG_BPF_SYSCALL) */
34263426

3427+
#if defined(CONFIG_KEYS) && defined(CONFIG_BPF_SYSCALL)
3428+
3429+
struct bpf_key *bpf_lookup_user_key(s32 serial, u64 flags);
3430+
struct bpf_key *bpf_lookup_system_key(u64 id);
3431+
void bpf_key_put(struct bpf_key *bkey);
3432+
int bpf_verify_pkcs7_signature(struct bpf_dynptr *data_p,
3433+
struct bpf_dynptr *sig_p,
3434+
struct bpf_key *trusted_keyring);
3435+
3436+
#else
3437+
static inline struct bpf_key *bpf_lookup_user_key(u32 serial, u64 flags)
3438+
{
3439+
return NULL;
3440+
}
3441+
3442+
static inline struct bpf_key *bpf_lookup_system_key(u64 id)
3443+
{
3444+
return NULL;
3445+
}
3446+
3447+
static inline void bpf_key_put(struct bpf_key *bkey)
3448+
{
3449+
}
3450+
3451+
static inline int bpf_verify_pkcs7_signature(struct bpf_dynptr *data_p,
3452+
struct bpf_dynptr *sig_p,
3453+
struct bpf_key *trusted_keyring)
3454+
{
3455+
return -EOPNOTSUPP;
3456+
}
3457+
#endif /* defined(CONFIG_KEYS) && defined(CONFIG_BPF_SYSCALL) */
3458+
34273459
/* verifier prototypes for helper functions called from eBPF programs */
34283460
extern const struct bpf_func_proto bpf_map_lookup_elem_proto;
34293461
extern const struct bpf_func_proto bpf_map_update_elem_proto;

kernel/bpf/helpers.c

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <linux/kasan.h>
2626
#include <linux/bpf_verifier.h>
2727
#include <linux/uaccess.h>
28+
#include <linux/verification.h>
2829

2930
#include "../../lib/kstrtox.h"
3031

@@ -3747,6 +3748,163 @@ __bpf_kfunc int bpf_strstr(const char *s1__ign, const char *s2__ign)
37473748
{
37483749
return bpf_strnstr(s1__ign, s2__ign, XATTR_SIZE_MAX);
37493750
}
3751+
#ifdef CONFIG_KEYS
3752+
/**
3753+
* bpf_lookup_user_key - lookup a key by its serial
3754+
* @serial: key handle serial number
3755+
* @flags: lookup-specific flags
3756+
*
3757+
* Search a key with a given *serial* and the provided *flags*.
3758+
* If found, increment the reference count of the key by one, and
3759+
* return it in the bpf_key structure.
3760+
*
3761+
* The bpf_key structure must be passed to bpf_key_put() when done
3762+
* with it, so that the key reference count is decremented and the
3763+
* bpf_key structure is freed.
3764+
*
3765+
* Permission checks are deferred to the time the key is used by
3766+
* one of the available key-specific kfuncs.
3767+
*
3768+
* Set *flags* with KEY_LOOKUP_CREATE, to attempt creating a requested
3769+
* special keyring (e.g. session keyring), if it doesn't yet exist.
3770+
* Set *flags* with KEY_LOOKUP_PARTIAL, to lookup a key without waiting
3771+
* for the key construction, and to retrieve uninstantiated keys (keys
3772+
* without data attached to them).
3773+
*
3774+
* Return: a bpf_key pointer with a valid key pointer if the key is found, a
3775+
* NULL pointer otherwise.
3776+
*/
3777+
__bpf_kfunc struct bpf_key *bpf_lookup_user_key(s32 serial, u64 flags)
3778+
{
3779+
key_ref_t key_ref;
3780+
struct bpf_key *bkey;
3781+
3782+
if (flags & ~KEY_LOOKUP_ALL)
3783+
return NULL;
3784+
3785+
/*
3786+
* Permission check is deferred until the key is used, as the
3787+
* intent of the caller is unknown here.
3788+
*/
3789+
key_ref = lookup_user_key(serial, flags, KEY_DEFER_PERM_CHECK);
3790+
if (IS_ERR(key_ref))
3791+
return NULL;
3792+
3793+
bkey = kmalloc(sizeof(*bkey), GFP_KERNEL);
3794+
if (!bkey) {
3795+
key_put(key_ref_to_ptr(key_ref));
3796+
return NULL;
3797+
}
3798+
3799+
bkey->key = key_ref_to_ptr(key_ref);
3800+
bkey->has_ref = true;
3801+
3802+
return bkey;
3803+
}
3804+
3805+
/**
3806+
* bpf_lookup_system_key - lookup a key by a system-defined ID
3807+
* @id: key ID
3808+
*
3809+
* Obtain a bpf_key structure with a key pointer set to the passed key ID.
3810+
* The key pointer is marked as invalid, to prevent bpf_key_put() from
3811+
* attempting to decrement the key reference count on that pointer. The key
3812+
* pointer set in such way is currently understood only by
3813+
* verify_pkcs7_signature().
3814+
*
3815+
* Set *id* to one of the values defined in include/linux/verification.h:
3816+
* 0 for the primary keyring (immutable keyring of system keys);
3817+
* VERIFY_USE_SECONDARY_KEYRING for both the primary and secondary keyring
3818+
* (where keys can be added only if they are vouched for by existing keys
3819+
* in those keyrings); VERIFY_USE_PLATFORM_KEYRING for the platform
3820+
* keyring (primarily used by the integrity subsystem to verify a kexec'ed
3821+
* kerned image and, possibly, the initramfs signature).
3822+
*
3823+
* Return: a bpf_key pointer with an invalid key pointer set from the
3824+
* pre-determined ID on success, a NULL pointer otherwise
3825+
*/
3826+
__bpf_kfunc struct bpf_key *bpf_lookup_system_key(u64 id)
3827+
{
3828+
struct bpf_key *bkey;
3829+
3830+
if (system_keyring_id_check(id) < 0)
3831+
return NULL;
3832+
3833+
bkey = kmalloc(sizeof(*bkey), GFP_ATOMIC);
3834+
if (!bkey)
3835+
return NULL;
3836+
3837+
bkey->key = (struct key *)(unsigned long)id;
3838+
bkey->has_ref = false;
3839+
3840+
return bkey;
3841+
}
3842+
3843+
/**
3844+
* bpf_key_put - decrement key reference count if key is valid and free bpf_key
3845+
* @bkey: bpf_key structure
3846+
*
3847+
* Decrement the reference count of the key inside *bkey*, if the pointer
3848+
* is valid, and free *bkey*.
3849+
*/
3850+
__bpf_kfunc void bpf_key_put(struct bpf_key *bkey)
3851+
{
3852+
if (bkey->has_ref)
3853+
key_put(bkey->key);
3854+
3855+
kfree(bkey);
3856+
}
3857+
3858+
/**
3859+
* bpf_verify_pkcs7_signature - verify a PKCS#7 signature
3860+
* @data_p: data to verify
3861+
* @sig_p: signature of the data
3862+
* @trusted_keyring: keyring with keys trusted for signature verification
3863+
*
3864+
* Verify the PKCS#7 signature *sig_ptr* against the supplied *data_ptr*
3865+
* with keys in a keyring referenced by *trusted_keyring*.
3866+
*
3867+
* Return: 0 on success, a negative value on error.
3868+
*/
3869+
__bpf_kfunc int bpf_verify_pkcs7_signature(struct bpf_dynptr *data_p,
3870+
struct bpf_dynptr *sig_p,
3871+
struct bpf_key *trusted_keyring)
3872+
{
3873+
#ifdef CONFIG_SYSTEM_DATA_VERIFICATION
3874+
struct bpf_dynptr_kern *data_ptr = (struct bpf_dynptr_kern *)data_p;
3875+
struct bpf_dynptr_kern *sig_ptr = (struct bpf_dynptr_kern *)sig_p;
3876+
const void *data, *sig;
3877+
u32 data_len, sig_len;
3878+
int ret;
3879+
3880+
if (trusted_keyring->has_ref) {
3881+
/*
3882+
* Do the permission check deferred in bpf_lookup_user_key().
3883+
* See bpf_lookup_user_key() for more details.
3884+
*
3885+
* A call to key_task_permission() here would be redundant, as
3886+
* it is already done by keyring_search() called by
3887+
* find_asymmetric_key().
3888+
*/
3889+
ret = key_validate(trusted_keyring->key);
3890+
if (ret < 0)
3891+
return ret;
3892+
}
3893+
3894+
data_len = __bpf_dynptr_size(data_ptr);
3895+
data = __bpf_dynptr_data(data_ptr, data_len);
3896+
sig_len = __bpf_dynptr_size(sig_ptr);
3897+
sig = __bpf_dynptr_data(sig_ptr, sig_len);
3898+
3899+
return verify_pkcs7_signature(data, data_len, sig, sig_len,
3900+
trusted_keyring->key,
3901+
VERIFYING_UNSPECIFIED_SIGNATURE, NULL,
3902+
NULL);
3903+
#else
3904+
return -EOPNOTSUPP;
3905+
#endif /* CONFIG_SYSTEM_DATA_VERIFICATION */
3906+
}
3907+
#endif /* CONFIG_KEYS */
37503908

37513909
__bpf_kfunc_end_defs();
37523910

@@ -3788,6 +3946,14 @@ BTF_ID_FLAGS(func, bpf_throw)
37883946
#ifdef CONFIG_BPF_EVENTS
37893947
BTF_ID_FLAGS(func, bpf_send_signal_task, KF_TRUSTED_ARGS)
37903948
#endif
3949+
#ifdef CONFIG_KEYS
3950+
BTF_ID_FLAGS(func, bpf_lookup_user_key, KF_ACQUIRE | KF_RET_NULL | KF_SLEEPABLE)
3951+
BTF_ID_FLAGS(func, bpf_lookup_system_key, KF_ACQUIRE | KF_RET_NULL)
3952+
BTF_ID_FLAGS(func, bpf_key_put, KF_RELEASE)
3953+
#ifdef CONFIG_SYSTEM_DATA_VERIFICATION
3954+
BTF_ID_FLAGS(func, bpf_verify_pkcs7_signature, KF_SLEEPABLE)
3955+
#endif
3956+
#endif
37913957
BTF_KFUNCS_END(generic_btf_ids)
37923958

37933959
static const struct btf_kfunc_id_set generic_kfunc_set = {

0 commit comments

Comments
 (0)