fc97590668
Perform several tests to ensure the correct implementation of the bpf_verify_pkcs7_signature() kfunc. Do the tests with data signed with a generated testing key (by using sign-file from scripts/) and with the tcp_bic.ko kernel module if it is found in the system. The test does not fail if tcp_bic.ko is not found. First, perform an unsuccessful signature verification without data. Second, perform a successful signature verification with the session keyring and a new one created for testing. Then, ensure that permission and validation checks are done properly on the keyring provided to bpf_verify_pkcs7_signature(), despite those checks were deferred at the time the keyring was retrieved with bpf_lookup_user_key(). The tests expect to encounter an error if the Search permission is removed from the keyring, or the keyring is expired. Finally, perform a successful and unsuccessful signature verification with the keyrings with pre-determined IDs (the last test fails because the key is not in the platform keyring). The test is currently in the deny list for s390x (JIT does not support calling kernel function). Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com> Link: https://lore.kernel.org/r/20220920075951.929132-13-roberto.sassu@huaweicloud.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
91 lines
2.1 KiB
C
91 lines
2.1 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
/*
|
|
* Copyright (C) 2022 Huawei Technologies Duesseldorf GmbH
|
|
*
|
|
* Author: Roberto Sassu <roberto.sassu@huawei.com>
|
|
*/
|
|
|
|
#include "vmlinux.h"
|
|
#include <errno.h>
|
|
#include <bpf/bpf_helpers.h>
|
|
#include <bpf/bpf_tracing.h>
|
|
|
|
#define MAX_DATA_SIZE (1024 * 1024)
|
|
#define MAX_SIG_SIZE 1024
|
|
|
|
extern struct bpf_key *bpf_lookup_user_key(__u32 serial, __u64 flags) __ksym;
|
|
extern struct bpf_key *bpf_lookup_system_key(__u64 id) __ksym;
|
|
extern void bpf_key_put(struct bpf_key *key) __ksym;
|
|
extern int bpf_verify_pkcs7_signature(struct bpf_dynptr *data_ptr,
|
|
struct bpf_dynptr *sig_ptr,
|
|
struct bpf_key *trusted_keyring) __ksym;
|
|
|
|
__u32 monitored_pid;
|
|
__u32 user_keyring_serial;
|
|
__u64 system_keyring_id;
|
|
|
|
struct data {
|
|
__u8 data[MAX_DATA_SIZE];
|
|
__u32 data_len;
|
|
__u8 sig[MAX_SIG_SIZE];
|
|
__u32 sig_len;
|
|
};
|
|
|
|
struct {
|
|
__uint(type, BPF_MAP_TYPE_ARRAY);
|
|
__uint(max_entries, 1);
|
|
__type(key, __u32);
|
|
__type(value, struct data);
|
|
} data_input SEC(".maps");
|
|
|
|
char _license[] SEC("license") = "GPL";
|
|
|
|
SEC("lsm.s/bpf")
|
|
int BPF_PROG(bpf, int cmd, union bpf_attr *attr, unsigned int size)
|
|
{
|
|
struct bpf_dynptr data_ptr, sig_ptr;
|
|
struct data *data_val;
|
|
struct bpf_key *trusted_keyring;
|
|
__u32 pid;
|
|
__u64 value;
|
|
int ret, zero = 0;
|
|
|
|
pid = bpf_get_current_pid_tgid() >> 32;
|
|
if (pid != monitored_pid)
|
|
return 0;
|
|
|
|
data_val = bpf_map_lookup_elem(&data_input, &zero);
|
|
if (!data_val)
|
|
return 0;
|
|
|
|
bpf_probe_read(&value, sizeof(value), &attr->value);
|
|
|
|
bpf_copy_from_user(data_val, sizeof(struct data),
|
|
(void *)(unsigned long)value);
|
|
|
|
if (data_val->data_len > sizeof(data_val->data))
|
|
return -EINVAL;
|
|
|
|
bpf_dynptr_from_mem(data_val->data, data_val->data_len, 0, &data_ptr);
|
|
|
|
if (data_val->sig_len > sizeof(data_val->sig))
|
|
return -EINVAL;
|
|
|
|
bpf_dynptr_from_mem(data_val->sig, data_val->sig_len, 0, &sig_ptr);
|
|
|
|
if (user_keyring_serial)
|
|
trusted_keyring = bpf_lookup_user_key(user_keyring_serial, 0);
|
|
else
|
|
trusted_keyring = bpf_lookup_system_key(system_keyring_id);
|
|
|
|
if (!trusted_keyring)
|
|
return -ENOENT;
|
|
|
|
ret = bpf_verify_pkcs7_signature(&data_ptr, &sig_ptr, trusted_keyring);
|
|
|
|
bpf_key_put(trusted_keyring);
|
|
|
|
return ret;
|
|
}
|