Skip to content

Commit

Permalink
kmod, bpf: work around a libbpf bug that prevents multiple objects to…
Browse files Browse the repository at this point in the history
… reference the same kfuncs
  • Loading branch information
hack3ric committed Sep 29, 2024
1 parent 860dad0 commit b2bb1ab
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 67 deletions.
5 changes: 5 additions & 0 deletions kmod/crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ int mimic_encrypt_wg_header(struct __sk_buff* skb_bpf, __u32 offset, void* iv, _
int mimic_decrypt_wg_header(struct xdp_md* xdp_bpf, __u32 offset, void* iv, __u32 iv__sz,
struct mimic_crypto_state* state) __ksym;

// HACK: see kfunc/crypto.c
struct mimic_crypto_state* mimic_crypto_state_create2(void) __ksym;
int mimic_crypto_set_key2(struct mimic_crypto_state* state, void* key, __u32 key__sz) __ksym;
void mimic_crypto_state_release2(struct mimic_crypto_state* state) __ksym;

#elif defined(MIMIC_CHECKSUM_HACK_kprobe)
#error to be implemented
#endif
Expand Down
66 changes: 36 additions & 30 deletions kmod/kfunc/crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,49 +15,37 @@
#include <net/xdp.h>

#include "../crypto.h"
#include "crypto.h"

static int skcipher(void* data, size_t size, int (*process)(struct skcipher_request*)) {
static int skcipher(struct mimic_crypto_state* state, void* iv, size_t iv_size, void* data,
size_t data_size, int (*process)(struct skcipher_request*)) {
int ret = 0;
struct crypto_skcipher* tfm = NULL;
struct skcipher_request* req = NULL;
struct scatterlist sg;

if (IS_ERR(tfm = crypto_alloc_skcipher("chacha20", 0, 0))) {
pr_err("error allocating chacha20 handle: %ld\n", PTR_ERR(tfm));
return PTR_ERR(tfm);
}

__u8 iv[16] = {}, key[32] = {};
// get_random_bytes(iv, sizeof(iv));
// get_random_bytes(key, sizeof(key));

if ((ret = crypto_skcipher_setkey(tfm, key, sizeof(key))) < 0) {
pr_err("error setting key: %d\n", ret);
goto cleanup;
}
if (iv_size < crypto_skcipher_ivsize(state->tfm)) return -EINVAL;

req = skcipher_request_alloc(tfm, GFP_ATOMIC);
req = skcipher_request_alloc(state->tfm, GFP_ATOMIC);
if (!req) {
ret = -ENOMEM;
goto cleanup;
}

sg_init_one(&sg, data, size);
skcipher_request_set_crypt(req, &sg, &sg, size, iv);
sg_init_one(&sg, data, data_size);
skcipher_request_set_crypt(req, &sg, &sg, data_size, iv);
if ((ret = process(req)) < 0) {
pr_err("error encrypting/decrypting data: %d\n", ret);
goto cleanup;
}

ret = 0;
cleanup:
crypto_free_skcipher(tfm);
skcipher_request_free(req);
return ret;
}

struct mimic_crypto_state* mimic_crypto_state_create(void) {
__bpf_kfunc_start_defs();

__bpf_kfunc struct mimic_crypto_state* mimic_crypto_state_create(void) {
struct mimic_crypto_state* state = kzalloc(sizeof(*state), GFP_KERNEL);
state->rc = (typeof(state->rc))REFCOUNT_INIT(1);
state->tfm = crypto_alloc_skcipher("chacha20", 0, 0);
Expand All @@ -68,26 +56,44 @@ struct mimic_crypto_state* mimic_crypto_state_create(void) {
return state;
}

int mimic_crypto_set_key(struct mimic_crypto_state* state, void* key, __u32 key__sz) {
__bpf_kfunc int mimic_crypto_set_key(struct mimic_crypto_state* state, void* key, __u32 key__sz) {
return crypto_skcipher_setkey(state->tfm, key, key__sz);
}

void mimic_crypto_state_release(struct mimic_crypto_state* state) {
__bpf_kfunc void mimic_crypto_state_release(struct mimic_crypto_state* state) {
if (refcount_dec_and_test(&state->rc)) {
crypto_free_skcipher(state->tfm);
kfree(state);
}
}

void mimic_crypto_state_dtor(void* p) { mimic_crypto_state_release(p); }
CFI_NOSEAL(mimic_crypto_state_dtor);

int mimic_encrypt_wg_header(struct __sk_buff* skb_bpf, __u32 offset, void* iv, __u32 iv__sz, struct mimic_crypto_state* state) {
__bpf_kfunc int mimic_encrypt_wg_header(struct __sk_buff* skb_bpf, __u32 offset, void* iv,
__u32 iv__sz, struct mimic_crypto_state* state) {
struct sk_buff* skb = (typeof(skb))skb_bpf;
return skcipher(skb->data + offset, 16, crypto_skcipher_encrypt);
return skcipher(state, iv, iv__sz, skb->data + offset, 16, crypto_skcipher_encrypt);
}

int mimic_decrypt_wg_header(struct xdp_md* xdp_bpf, __u32 offset, void* iv, __u32 iv__sz, struct mimic_crypto_state* state) {
__bpf_kfunc int mimic_decrypt_wg_header(struct xdp_md* xdp_bpf, __u32 offset, void* iv,
__u32 iv__sz, struct mimic_crypto_state* state) {
struct xdp_buff* xdp = (typeof(xdp))xdp_bpf;
return skcipher(xdp->data + offset, 16, crypto_skcipher_decrypt);
return skcipher(state, iv, iv__sz, xdp->data + offset, 16, crypto_skcipher_decrypt);
}

__bpf_kfunc void mimic_crypto_state_dtor(void* p) { mimic_crypto_state_release(p); }
CFI_NOSEAL(mimic_crypto_state_dtor);

// HACK: Work around a libbpf bug that prevents multiple objects to reference the same kfuncs.
// Reported and fixed in [1], but we need to maintain compatibility with older versions. This is
// dirty, but vendoring bpftool and libbpf is way dirtier.
// [1]: https://lore.kernel.org/bpf/[email protected]/
__bpf_kfunc struct mimic_crypto_state* mimic_crypto_state_create2(void) {
return mimic_crypto_state_create();
}
__bpf_kfunc int mimic_crypto_set_key2(struct mimic_crypto_state* state, void* key, __u32 key__sz) {
return mimic_crypto_set_key(state, key, key__sz);
}
__bpf_kfunc void mimic_crypto_state_release2(struct mimic_crypto_state* state) {
return mimic_crypto_state_release(state);
}

__bpf_kfunc_end_defs();
21 changes: 0 additions & 21 deletions kmod/kfunc/crypto.h

This file was deleted.

1 change: 0 additions & 1 deletion kmod/kfunc/csum-hack.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

#include "../csum-hack.h"
#include "common.h"
#include "csum-hack.h"

__bpf_kfunc_start_defs();

Expand Down
13 changes: 0 additions & 13 deletions kmod/kfunc/csum-hack.h

This file was deleted.

2 changes: 0 additions & 2 deletions kmod/kfunc/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@

#include "../impl.h"
#include "common.h"
#include "crypto.h"
#include "csum-hack.h"

BTF_ID_LIST(mimic_dtor_ids)
BTF_ID(struct, mimic_crypto_state)
Expand Down
Empty file removed kmod/kprobe/crypto.c
Empty file.

0 comments on commit b2bb1ab

Please sign in to comment.