Reputation: 23
I'm attempting to implement an eBPF code where I have a BPF MAP with the key of type struct inode *
and some value.
Please see the below sample code
struct value {
char data[10];
};
struct bpf_map_def info SEC("maps") ={
.type = BPF_MAP_TYPE_HASH,
.max_entries = 100,
.key_size = sizeof(struct inode *),
.value_size = sizeof(struct value),
.map_flags = BPF_F_NO_PREALLOC,
};
SEC("fexit/vfs_unlink")
int BPF_PROG(
vfs_unlink_exit,
const struct user_namespace *mnt_userns,
const struct inode *dir,
const struct dentry *dentry,
const struct inode **delegated_inode,
int ret)
{
struct inode * p = BPF_CORE_READ(dentry,d_inode);
struct value *val = bpf_map_lookup_elem(&info, p);
if (val == NULL)
{
bpf_printk("not handling");
return 0;
}
return 0;
}
The verifier does not like this :
libbpf: -- BEGIN DUMP LOG ---
libbpf:
R1 type=ctx expected=fp
; int BPF_PROG(
0: (b7) r2 = 48
; int BPF_PROG(
1: (79) r3 = *(u64 *)(r1 +16)
func 'vfs_unlink' arg2 has btf_id 691 type STRUCT 'dentry'
2: (0f) r3 += r2
last_idx 2 first_idx 0
regs=4 stack=0 before 1: (79) r3 = *(u64 *)(r1 +16)
regs=4 stack=0 before 0: (b7) r2 = 48
3: (bf) r1 = r10
;
4: (07) r1 += -16
; struct inode * p = BPF_CORE_READ(dentry,d_inode);
5: (b7) r2 = 8
6: (85) call bpf_probe_read_kernel#113
last_idx 6 first_idx 0
regs=4 stack=0 before 5: (b7) r2 = 8
; struct inode * p = BPF_CORE_READ(dentry,d_inode);
7: (79) r2 = *(u64 *)(r10 -16)
; struct value *val = bpf_map_lookup_elem(&info, p);
8: (18) r1 = 0xffff93c9f43fc000
10: (85) call bpf_map_lookup_elem#1
R2 type=inv expected=fp, pkt, pkt_meta, map_key, map_value
processed 10 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0
libbpf: -- END LOG --
Im also not able to pass directly the parameter ptr as the key eg :
SEC("fexit/vfs_unlink")
int BPF_PROG(
vfs_unlink_exit,
const struct user_namespace *mnt_userns,
const struct inode *dir,
const struct dentry *dentry,
const struct inode **delegated_inode,
int ret)
{
struct value *val = bpf_map_lookup_elem(&info, dir);
if (val == NULL)
{
bpf_printk("not handling");
return 0;
}
return 0;
}
produces:
libbpf: -- BEGIN DUMP LOG ---
libbpf:
R1 type=ctx expected=fp
; int BPF_PROG(
0: (79) r2 = *(u64 *)(r1 +8)
func 'vfs_unlink' arg1 has btf_id 694 type STRUCT 'inode'
; struct value *val = bpf_map_lookup_elem(&info, dir);
1: (18) r1 = 0xffff93caed64c400
3: (85) call bpf_map_lookup_elem#1
R2 type=ptr_ expected=fp, pkt, pkt_meta, map_key, map_value
processed 3 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0
libbpf: -- END LOG --
I don't understand why, as similar approach with eg struct socket *
works fine.
Any help would be greatly appreciated.
Kernel v 5.13.0-051300-generic
Upvotes: 2
Views: 1384
Reputation: 9174
R2 type=inv expected=fp, pkt, pkt_meta, map_key, map_value
The verifier tells you that the second argument (in R2
) to your call to bpf_map_lookup_elem()
is not of the expected type. It can point to the stack (fp
), to packet data (pkt
) or metadata (pkt_meta
), or to another map key or value (map_key
, map_value
).
In your case, BPF_CORE_READ()
returns a scalar (inv
), and dir
to a BTF id (ptr_
), and neither is suitable. You could try copying the data for your key to the eBPF stack first (assign it to a temporary variable, and pass a reference to that variable to the helper). You probably don't want to use the full struct inode
as a key anyway.
Upvotes: 2