Skip to content

Commit 1b52790

Browse files
committed
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.
1 parent f1e3d2a commit 1b52790

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
@@ -3412,6 +3412,38 @@ static inline int bpf_fd_reuseport_array_update_elem(struct bpf_map *map,
34123412
#endif /* CONFIG_BPF_SYSCALL */
34133413
#endif /* defined(CONFIG_INET) && defined(CONFIG_BPF_SYSCALL) */
34143414

3415+
#if defined(CONFIG_KEYS) && defined(CONFIG_BPF_SYSCALL)
3416+
3417+
struct bpf_key *bpf_lookup_user_key(s32 serial, u64 flags);
3418+
struct bpf_key *bpf_lookup_system_key(u64 id);
3419+
void bpf_key_put(struct bpf_key *bkey);
3420+
int bpf_verify_pkcs7_signature(struct bpf_dynptr *data_p,
3421+
struct bpf_dynptr *sig_p,
3422+
struct bpf_key *trusted_keyring);
3423+
3424+
#else
3425+
static inline struct bpf_key *bpf_lookup_user_key(u32 serial, u64 flags)
3426+
{
3427+
return NULL;
3428+
}
3429+
3430+
static inline struct bpf_key *bpf_lookup_system_key(u64 id)
3431+
{
3432+
return NULL;
3433+
}
3434+
3435+
static inline void bpf_key_put(struct bpf_key *bkey)
3436+
{
3437+
}
3438+
3439+
static inline int bpf_verify_pkcs7_signature(struct bpf_dynptr *data_p,
3440+
struct bpf_dynptr *sig_p,
3441+
struct bpf_key *trusted_keyring)
3442+
{
3443+
return -EOPNOTSUPP;
3444+
}
3445+
#endif /* defined(CONFIG_KEYS) && defined(CONFIG_BPF_SYSCALL) */
3446+
34153447
/* verifier prototypes for helper functions called from eBPF programs */
34163448
extern const struct bpf_func_proto bpf_map_lookup_elem_proto;
34173449
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

@@ -3702,6 +3703,163 @@ __bpf_kfunc int bpf_strstr(const char *s1__ign, const char *s2__ign)
37023703
{
37033704
return bpf_strnstr(s1__ign, s2__ign, XATTR_SIZE_MAX);
37043705
}
3706+
#ifdef CONFIG_KEYS
3707+
/**
3708+
* bpf_lookup_user_key - lookup a key by its serial
3709+
* @serial: key handle serial number
3710+
* @flags: lookup-specific flags
3711+
*
3712+
* Search a key with a given *serial* and the provided *flags*.
3713+
* If found, increment the reference count of the key by one, and
3714+
* return it in the bpf_key structure.
3715+
*
3716+
* The bpf_key structure must be passed to bpf_key_put() when done
3717+
* with it, so that the key reference count is decremented and the
3718+
* bpf_key structure is freed.
3719+
*
3720+
* Permission checks are deferred to the time the key is used by
3721+
* one of the available key-specific kfuncs.
3722+
*
3723+
* Set *flags* with KEY_LOOKUP_CREATE, to attempt creating a requested
3724+
* special keyring (e.g. session keyring), if it doesn't yet exist.
3725+
* Set *flags* with KEY_LOOKUP_PARTIAL, to lookup a key without waiting
3726+
* for the key construction, and to retrieve uninstantiated keys (keys
3727+
* without data attached to them).
3728+
*
3729+
* Return: a bpf_key pointer with a valid key pointer if the key is found, a
3730+
* NULL pointer otherwise.
3731+
*/
3732+
__bpf_kfunc struct bpf_key *bpf_lookup_user_key(s32 serial, u64 flags)
3733+
{
3734+
key_ref_t key_ref;
3735+
struct bpf_key *bkey;
3736+
3737+
if (flags & ~KEY_LOOKUP_ALL)
3738+
return NULL;
3739+
3740+
/*
3741+
* Permission check is deferred until the key is used, as the
3742+
* intent of the caller is unknown here.
3743+
*/
3744+
key_ref = lookup_user_key(serial, flags, KEY_DEFER_PERM_CHECK);
3745+
if (IS_ERR(key_ref))
3746+
return NULL;
3747+
3748+
bkey = kmalloc(sizeof(*bkey), GFP_KERNEL);
3749+
if (!bkey) {
3750+
key_put(key_ref_to_ptr(key_ref));
3751+
return NULL;
3752+
}
3753+
3754+
bkey->key = key_ref_to_ptr(key_ref);
3755+
bkey->has_ref = true;
3756+
3757+
return bkey;
3758+
}
3759+
3760+
/**
3761+
* bpf_lookup_system_key - lookup a key by a system-defined ID
3762+
* @id: key ID
3763+
*
3764+
* Obtain a bpf_key structure with a key pointer set to the passed key ID.
3765+
* The key pointer is marked as invalid, to prevent bpf_key_put() from
3766+
* attempting to decrement the key reference count on that pointer. The key
3767+
* pointer set in such way is currently understood only by
3768+
* verify_pkcs7_signature().
3769+
*
3770+
* Set *id* to one of the values defined in include/linux/verification.h:
3771+
* 0 for the primary keyring (immutable keyring of system keys);
3772+
* VERIFY_USE_SECONDARY_KEYRING for both the primary and secondary keyring
3773+
* (where keys can be added only if they are vouched for by existing keys
3774+
* in those keyrings); VERIFY_USE_PLATFORM_KEYRING for the platform
3775+
* keyring (primarily used by the integrity subsystem to verify a kexec'ed
3776+
* kerned image and, possibly, the initramfs signature).
3777+
*
3778+
* Return: a bpf_key pointer with an invalid key pointer set from the
3779+
* pre-determined ID on success, a NULL pointer otherwise
3780+
*/
3781+
__bpf_kfunc struct bpf_key *bpf_lookup_system_key(u64 id)
3782+
{
3783+
struct bpf_key *bkey;
3784+
3785+
if (system_keyring_id_check(id) < 0)
3786+
return NULL;
3787+
3788+
bkey = kmalloc(sizeof(*bkey), GFP_ATOMIC);
3789+
if (!bkey)
3790+
return NULL;
3791+
3792+
bkey->key = (struct key *)(unsigned long)id;
3793+
bkey->has_ref = false;
3794+
3795+
return bkey;
3796+
}
3797+
3798+
/**
3799+
* bpf_key_put - decrement key reference count if key is valid and free bpf_key
3800+
* @bkey: bpf_key structure
3801+
*
3802+
* Decrement the reference count of the key inside *bkey*, if the pointer
3803+
* is valid, and free *bkey*.
3804+
*/
3805+
__bpf_kfunc void bpf_key_put(struct bpf_key *bkey)
3806+
{
3807+
if (bkey->has_ref)
3808+
key_put(bkey->key);
3809+
3810+
kfree(bkey);
3811+
}
3812+
3813+
/**
3814+
* bpf_verify_pkcs7_signature - verify a PKCS#7 signature
3815+
* @data_p: data to verify
3816+
* @sig_p: signature of the data
3817+
* @trusted_keyring: keyring with keys trusted for signature verification
3818+
*
3819+
* Verify the PKCS#7 signature *sig_ptr* against the supplied *data_ptr*
3820+
* with keys in a keyring referenced by *trusted_keyring*.
3821+
*
3822+
* Return: 0 on success, a negative value on error.
3823+
*/
3824+
__bpf_kfunc int bpf_verify_pkcs7_signature(struct bpf_dynptr *data_p,
3825+
struct bpf_dynptr *sig_p,
3826+
struct bpf_key *trusted_keyring)
3827+
{
3828+
#ifdef CONFIG_SYSTEM_DATA_VERIFICATION
3829+
struct bpf_dynptr_kern *data_ptr = (struct bpf_dynptr_kern *)data_p;
3830+
struct bpf_dynptr_kern *sig_ptr = (struct bpf_dynptr_kern *)sig_p;
3831+
const void *data, *sig;
3832+
u32 data_len, sig_len;
3833+
int ret;
3834+
3835+
if (trusted_keyring->has_ref) {
3836+
/*
3837+
* Do the permission check deferred in bpf_lookup_user_key().
3838+
* See bpf_lookup_user_key() for more details.
3839+
*
3840+
* A call to key_task_permission() here would be redundant, as
3841+
* it is already done by keyring_search() called by
3842+
* find_asymmetric_key().
3843+
*/
3844+
ret = key_validate(trusted_keyring->key);
3845+
if (ret < 0)
3846+
return ret;
3847+
}
3848+
3849+
data_len = __bpf_dynptr_size(data_ptr);
3850+
data = __bpf_dynptr_data(data_ptr, data_len);
3851+
sig_len = __bpf_dynptr_size(sig_ptr);
3852+
sig = __bpf_dynptr_data(sig_ptr, sig_len);
3853+
3854+
return verify_pkcs7_signature(data, data_len, sig, sig_len,
3855+
trusted_keyring->key,
3856+
VERIFYING_UNSPECIFIED_SIGNATURE, NULL,
3857+
NULL);
3858+
#else
3859+
return -EOPNOTSUPP;
3860+
#endif /* CONFIG_SYSTEM_DATA_VERIFICATION */
3861+
}
3862+
#endif /* CONFIG_KEYS */
37053863

37063864
__bpf_kfunc_end_defs();
37073865

@@ -3743,6 +3901,14 @@ BTF_ID_FLAGS(func, bpf_throw)
37433901
#ifdef CONFIG_BPF_EVENTS
37443902
BTF_ID_FLAGS(func, bpf_send_signal_task, KF_TRUSTED_ARGS)
37453903
#endif
3904+
#ifdef CONFIG_KEYS
3905+
BTF_ID_FLAGS(func, bpf_lookup_user_key, KF_ACQUIRE | KF_RET_NULL | KF_SLEEPABLE)
3906+
BTF_ID_FLAGS(func, bpf_lookup_system_key, KF_ACQUIRE | KF_RET_NULL)
3907+
BTF_ID_FLAGS(func, bpf_key_put, KF_RELEASE)
3908+
#ifdef CONFIG_SYSTEM_DATA_VERIFICATION
3909+
BTF_ID_FLAGS(func, bpf_verify_pkcs7_signature, KF_SLEEPABLE)
3910+
#endif
3911+
#endif
37463912
BTF_KFUNCS_END(generic_btf_ids)
37473913

37483914
static const struct btf_kfunc_id_set generic_kfunc_set = {

0 commit comments

Comments
 (0)