Skip to content

Commit fb2b0e2

Browse files
sinkapAlexei Starovoitov
authored andcommitted
libbpf: Update light skeleton for signing
* The metadata map is created with as an exclusive map (with an excl_prog_hash) This restricts map access exclusively to the signed loader program, preventing tampering by other processes. * The map is then frozen, making it read-only from userspace. * BPF_OBJ_GET_INFO_BY_ID instructs the kernel to compute the hash of the metadata map (H') and store it in bpf_map->sha. * The loader is then loaded with the signature which is then verified by the kernel. loading signed programs prebuilt into the kernel are not currently supported. These can supported by enabling BPF_OBJ_GET_INFO_BY_ID to be called from the kernel. Signed-off-by: KP Singh <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent 3492715 commit fb2b0e2

File tree

1 file changed

+72
-4
lines changed

1 file changed

+72
-4
lines changed

tools/lib/bpf/skel_internal.h

Lines changed: 72 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,15 @@
1313
#include <unistd.h>
1414
#include <sys/syscall.h>
1515
#include <sys/mman.h>
16+
#include <linux/keyctl.h>
1617
#include <stdlib.h>
1718
#include "bpf.h"
1819
#endif
1920

21+
#ifndef SHA256_DIGEST_LENGTH
22+
#define SHA256_DIGEST_LENGTH 32
23+
#endif
24+
2025
#ifndef __NR_bpf
2126
# if defined(__mips__) && defined(_ABIO32)
2227
# define __NR_bpf 4355
@@ -64,6 +69,11 @@ struct bpf_load_and_run_opts {
6469
__u32 data_sz;
6570
__u32 insns_sz;
6671
const char *errstr;
72+
void *signature;
73+
__u32 signature_sz;
74+
__s32 keyring_id;
75+
void *excl_prog_hash;
76+
__u32 excl_prog_hash_sz;
6777
};
6878

6979
long kern_sys_bpf(__u32 cmd, void *attr, __u32 attr_size);
@@ -220,14 +230,19 @@ static inline int skel_map_create(enum bpf_map_type map_type,
220230
const char *map_name,
221231
__u32 key_size,
222232
__u32 value_size,
223-
__u32 max_entries)
233+
__u32 max_entries,
234+
const void *excl_prog_hash,
235+
__u32 excl_prog_hash_sz)
224236
{
225-
const size_t attr_sz = offsetofend(union bpf_attr, map_extra);
237+
const size_t attr_sz = offsetofend(union bpf_attr, excl_prog_hash_size);
226238
union bpf_attr attr;
227239

228240
memset(&attr, 0, attr_sz);
229241

230242
attr.map_type = map_type;
243+
attr.excl_prog_hash = (unsigned long) excl_prog_hash;
244+
attr.excl_prog_hash_size = excl_prog_hash_sz;
245+
231246
strncpy(attr.map_name, map_name, sizeof(attr.map_name));
232247
attr.key_size = key_size;
233248
attr.value_size = value_size;
@@ -300,6 +315,35 @@ static inline int skel_link_create(int prog_fd, int target_fd,
300315
return skel_sys_bpf(BPF_LINK_CREATE, &attr, attr_sz);
301316
}
302317

318+
static inline int skel_obj_get_info_by_fd(int fd)
319+
{
320+
const size_t attr_sz = offsetofend(union bpf_attr, info);
321+
__u8 sha[SHA256_DIGEST_LENGTH];
322+
struct bpf_map_info info;
323+
__u32 info_len = sizeof(info);
324+
union bpf_attr attr;
325+
326+
memset(&info, 0, sizeof(info));
327+
info.hash = (long) &sha;
328+
info.hash_size = SHA256_DIGEST_LENGTH;
329+
330+
memset(&attr, 0, attr_sz);
331+
attr.info.bpf_fd = fd;
332+
attr.info.info = (long) &info;
333+
attr.info.info_len = info_len;
334+
return skel_sys_bpf(BPF_OBJ_GET_INFO_BY_FD, &attr, attr_sz);
335+
}
336+
337+
static inline int skel_map_freeze(int fd)
338+
{
339+
const size_t attr_sz = offsetofend(union bpf_attr, map_fd);
340+
union bpf_attr attr;
341+
342+
memset(&attr, 0, attr_sz);
343+
attr.map_fd = fd;
344+
345+
return skel_sys_bpf(BPF_MAP_FREEZE, &attr, attr_sz);
346+
}
303347
#ifdef __KERNEL__
304348
#define set_err
305349
#else
@@ -308,12 +352,13 @@ static inline int skel_link_create(int prog_fd, int target_fd,
308352

309353
static inline int bpf_load_and_run(struct bpf_load_and_run_opts *opts)
310354
{
311-
const size_t prog_load_attr_sz = offsetofend(union bpf_attr, fd_array);
355+
const size_t prog_load_attr_sz = offsetofend(union bpf_attr, keyring_id);
312356
const size_t test_run_attr_sz = offsetofend(union bpf_attr, test);
313357
int map_fd = -1, prog_fd = -1, key = 0, err;
314358
union bpf_attr attr;
315359

316-
err = map_fd = skel_map_create(BPF_MAP_TYPE_ARRAY, "__loader.map", 4, opts->data_sz, 1);
360+
err = map_fd = skel_map_create(BPF_MAP_TYPE_ARRAY, "__loader.map", 4, opts->data_sz, 1,
361+
opts->excl_prog_hash, opts->excl_prog_hash_sz);
317362
if (map_fd < 0) {
318363
opts->errstr = "failed to create loader map";
319364
set_err;
@@ -327,11 +372,34 @@ static inline int bpf_load_and_run(struct bpf_load_and_run_opts *opts)
327372
goto out;
328373
}
329374

375+
#ifndef __KERNEL__
376+
err = skel_map_freeze(map_fd);
377+
if (err < 0) {
378+
opts->errstr = "failed to freeze map";
379+
set_err;
380+
goto out;
381+
}
382+
err = skel_obj_get_info_by_fd(map_fd);
383+
if (err < 0) {
384+
opts->errstr = "failed to fetch obj info";
385+
set_err;
386+
goto out;
387+
}
388+
#endif
389+
330390
memset(&attr, 0, prog_load_attr_sz);
331391
attr.prog_type = BPF_PROG_TYPE_SYSCALL;
332392
attr.insns = (long) opts->insns;
333393
attr.insn_cnt = opts->insns_sz / sizeof(struct bpf_insn);
334394
attr.license = (long) "Dual BSD/GPL";
395+
#ifndef __KERNEL__
396+
attr.signature = (long) opts->signature;
397+
attr.signature_size = opts->signature_sz;
398+
#else
399+
if (opts->signature || opts->signature_sz)
400+
pr_warn("signatures are not supported from bpf_preload\n");
401+
#endif
402+
attr.keyring_id = opts->keyring_id;
335403
memcpy(attr.prog_name, "__loader.prog", sizeof("__loader.prog"));
336404
attr.fd_array = (long) &map_fd;
337405
attr.log_level = opts->ctx->log_level;

0 commit comments

Comments
 (0)