Skip to content

Commit 6e07375

Browse files
committed
bpf: Implement exclusive map creation
Exclusive maps allow maps to only be accessed by program with a program with a matching hash which is specified in the excl_prog_hash attr. For the signing use-case, this allows the trusted loader program to load the map and verify the integrity Signed-off-by: KP Singh <[email protected]>
1 parent 7a87d53 commit 6e07375

File tree

5 files changed

+39
-4
lines changed

5 files changed

+39
-4
lines changed

include/linux/bpf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ struct bpf_map {
329329
atomic64_t sleepable_refcnt;
330330
s64 __percpu *elem_count;
331331
u64 cookie; /* write-once */
332+
char *excl_prog_sha;
332333
};
333334

334335
static inline const char *btf_field_type_name(enum btf_field_type type)

include/uapi/linux/bpf.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1522,6 +1522,8 @@ union bpf_attr {
15221522
* If provided, map_flags should have BPF_F_TOKEN_FD flag set.
15231523
*/
15241524
__s32 map_token_fd;
1525+
__u32 excl_prog_hash_size;
1526+
__aligned_u64 excl_prog_hash;
15251527
};
15261528

15271529
struct { /* anonymous struct used by BPF_MAP_*_ELEM and BPF_MAP_FREEZE commands */

kernel/bpf/syscall.c

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -860,6 +860,7 @@ static void bpf_map_free(struct bpf_map *map)
860860
* the free of values or special fields allocated from bpf memory
861861
* allocator.
862862
*/
863+
kfree(map->excl_prog_sha);
863864
migrate_disable();
864865
map->ops->map_free(map);
865866
migrate_enable();
@@ -1338,9 +1339,9 @@ static bool bpf_net_capable(void)
13381339
return capable(CAP_NET_ADMIN) || capable(CAP_SYS_ADMIN);
13391340
}
13401341

1341-
#define BPF_MAP_CREATE_LAST_FIELD map_token_fd
1342+
#define BPF_MAP_CREATE_LAST_FIELD excl_prog_hash
13421343
/* called via syscall */
1343-
static int map_create(union bpf_attr *attr, bool kernel)
1344+
static int map_create(union bpf_attr *attr, bpfptr_t uattr)
13441345
{
13451346
const struct bpf_map_ops *ops;
13461347
struct bpf_token *token = NULL;
@@ -1534,7 +1535,30 @@ static int map_create(union bpf_attr *attr, bool kernel)
15341535
attr->btf_vmlinux_value_type_id;
15351536
}
15361537

1537-
err = security_bpf_map_create(map, attr, token, kernel);
1538+
if (attr->excl_prog_hash) {
1539+
bpfptr_t uprog_hash = make_bpfptr(attr->excl_prog_hash, uattr.is_kernel);
1540+
1541+
if (attr->excl_prog_hash_size != SHA256_DIGEST_SIZE) {
1542+
err = -EINVAL;
1543+
goto free_map;
1544+
}
1545+
1546+
map->excl_prog_sha = kzalloc(SHA256_DIGEST_SIZE, GFP_KERNEL);
1547+
if (!map->excl_prog_sha) {
1548+
err = -ENOMEM;
1549+
goto free_map;
1550+
}
1551+
1552+
if (copy_from_bpfptr(map->excl_prog_sha, uprog_hash,
1553+
SHA256_DIGEST_SIZE)) {
1554+
err = -EFAULT;
1555+
goto free_map;
1556+
}
1557+
} else if (attr->excl_prog_hash_size) {
1558+
return -EINVAL;
1559+
}
1560+
1561+
err = security_bpf_map_create(map, attr, token, uattr.is_kernel);
15381562
if (err)
15391563
goto free_map_sec;
15401564

@@ -6008,7 +6032,7 @@ static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t uattr, unsigned int size)
60086032

60096033
switch (cmd) {
60106034
case BPF_MAP_CREATE:
6011-
err = map_create(&attr, uattr.is_kernel);
6035+
err = map_create(&attr, uattr);
60126036
break;
60136037
case BPF_MAP_LOOKUP_ELEM:
60146038
err = map_lookup_elem(&attr);

kernel/bpf/verifier.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20360,6 +20360,12 @@ static int check_map_prog_compatibility(struct bpf_verifier_env *env,
2036020360
{
2036120361
enum bpf_prog_type prog_type = resolve_prog_type(prog);
2036220362

20363+
if (map->excl_prog_sha &&
20364+
memcmp(map->excl_prog_sha, prog->digest, SHA256_DIGEST_SIZE)) {
20365+
verbose(env, "program's hash doesn't match map's excl_prog_hash\n");
20366+
return -EACCES;
20367+
}
20368+
2036320369
if (btf_record_has_field(map->record, BPF_LIST_HEAD) ||
2036420370
btf_record_has_field(map->record, BPF_RB_ROOT)) {
2036520371
if (is_tracing_prog_type(prog_type)) {

tools/include/uapi/linux/bpf.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1522,6 +1522,8 @@ union bpf_attr {
15221522
* If provided, map_flags should have BPF_F_TOKEN_FD flag set.
15231523
*/
15241524
__s32 map_token_fd;
1525+
__u32 excl_prog_hash_size;
1526+
__aligned_u64 excl_prog_hash;
15251527
};
15261528

15271529
struct { /* anonymous struct used by BPF_MAP_*_ELEM and BPF_MAP_FREEZE commands */

0 commit comments

Comments
 (0)