ARG_PTR_TO_DYNPTR is akin to ARG_PTR_TO_TIMER, ARG_PTR_TO_KPTR, where the underlying register type is subjected to more special checks to determine the type of object represented by the pointer and its state consistency. Move dynptr checks to their own 'process_dynptr_func' function so that is consistent and in-line with existing code. This also makes it easier to reuse this code for kfunc handling. Then, reuse this consolidated function in kfunc dynptr handling too. Note that for kfuncs, the arg_type constraint of DYNPTR_TYPE_LOCAL has been lifted. Acked-by: David Vernet <void@manifault.com> Acked-by: Joanne Koong <joannelkoong@gmail.com> Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com> Link: https://lore.kernel.org/r/20221207204141.308952-2-memxor@gmail.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
82 lines
1.9 KiB
C
82 lines
1.9 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>
|
|
|
|
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;
|
|
|
|
struct {
|
|
__uint(type, BPF_MAP_TYPE_RINGBUF);
|
|
} ringbuf SEC(".maps");
|
|
|
|
struct {
|
|
__uint(type, BPF_MAP_TYPE_ARRAY);
|
|
__uint(max_entries, 1);
|
|
__type(key, __u32);
|
|
__type(value, __u32);
|
|
} array_map SEC(".maps");
|
|
|
|
int err, pid;
|
|
|
|
char _license[] SEC("license") = "GPL";
|
|
|
|
SEC("?lsm.s/bpf")
|
|
int BPF_PROG(not_valid_dynptr, int cmd, union bpf_attr *attr, unsigned int size)
|
|
{
|
|
unsigned long val;
|
|
|
|
return bpf_verify_pkcs7_signature((struct bpf_dynptr *)&val,
|
|
(struct bpf_dynptr *)&val, NULL);
|
|
}
|
|
|
|
SEC("?lsm.s/bpf")
|
|
int BPF_PROG(not_ptr_to_stack, int cmd, union bpf_attr *attr, unsigned int size)
|
|
{
|
|
unsigned long val;
|
|
|
|
return bpf_verify_pkcs7_signature((struct bpf_dynptr *)val,
|
|
(struct bpf_dynptr *)val, NULL);
|
|
}
|
|
|
|
SEC("lsm.s/bpf")
|
|
int BPF_PROG(dynptr_data_null, int cmd, union bpf_attr *attr, unsigned int size)
|
|
{
|
|
struct bpf_key *trusted_keyring;
|
|
struct bpf_dynptr ptr;
|
|
__u32 *value;
|
|
int ret, zero = 0;
|
|
|
|
if (bpf_get_current_pid_tgid() >> 32 != pid)
|
|
return 0;
|
|
|
|
value = bpf_map_lookup_elem(&array_map, &zero);
|
|
if (!value)
|
|
return 0;
|
|
|
|
/* Pass invalid flags. */
|
|
ret = bpf_dynptr_from_mem(value, sizeof(*value), ((__u64)~0ULL), &ptr);
|
|
if (ret != -EINVAL)
|
|
return 0;
|
|
|
|
trusted_keyring = bpf_lookup_system_key(0);
|
|
if (!trusted_keyring)
|
|
return 0;
|
|
|
|
err = bpf_verify_pkcs7_signature(&ptr, &ptr, trusted_keyring);
|
|
|
|
bpf_key_put(trusted_keyring);
|
|
|
|
return 0;
|
|
}
|