|
|
|
@ -13,10 +13,10 @@ use aya_obj::{
|
|
|
|
|
FuncLinkage, FuncProto, FuncSecInfo, Int, IntEncoding, LineSecInfo, Ptr, TypeTag, Var,
|
|
|
|
|
VarLinkage,
|
|
|
|
|
},
|
|
|
|
|
copy_instructions,
|
|
|
|
|
generated::{
|
|
|
|
|
bpf_attach_type, bpf_attr, bpf_btf_info, bpf_cmd, bpf_insn, bpf_link_info, bpf_map_info,
|
|
|
|
|
bpf_map_type, bpf_prog_info, bpf_prog_type, bpf_stats_type, BPF_F_REPLACE,
|
|
|
|
|
bpf_map_type, bpf_prog_info, bpf_prog_type, bpf_stats_type, BPF_ALU64, BPF_CALL, BPF_DW,
|
|
|
|
|
BPF_F_REPLACE, BPF_JMP, BPF_K, BPF_LD, BPF_PSEUDO_MAP_VALUE, BPF_ST,
|
|
|
|
|
},
|
|
|
|
|
maps::{bpf_map_def, LegacyMap},
|
|
|
|
|
EbpfSectionKind, VerifierLog,
|
|
|
|
@ -741,6 +741,16 @@ pub(crate) fn is_prog_name_supported() -> bool {
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn new_insn(code: u8, dst_reg: u8, src_reg: u8, offset: i16, imm: i32) -> bpf_insn {
|
|
|
|
|
let mut insn = unsafe { mem::zeroed::<bpf_insn>() };
|
|
|
|
|
insn.code = code;
|
|
|
|
|
insn.set_dst_reg(dst_reg);
|
|
|
|
|
insn.set_src_reg(src_reg);
|
|
|
|
|
insn.off = offset;
|
|
|
|
|
insn.imm = imm;
|
|
|
|
|
insn
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn with_trivial_prog<T, F>(op: F) -> T
|
|
|
|
|
where
|
|
|
|
|
F: FnOnce(&mut bpf_attr) -> T,
|
|
|
|
@ -748,20 +758,13 @@ where
|
|
|
|
|
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
|
|
|
|
|
let u = unsafe { &mut attr.__bindgen_anon_3 };
|
|
|
|
|
|
|
|
|
|
// The fields conforming an encoded basic instruction are stored in the following order:
|
|
|
|
|
// opcode:8 src_reg:4 dst_reg:4 offset:16 imm:32 - In little-endian BPF.
|
|
|
|
|
// opcode:8 dst_reg:4 src_reg:4 offset:16 imm:32 - In big-endian BPF.
|
|
|
|
|
// Multi-byte fields ('imm' and 'offset') are stored using endian order.
|
|
|
|
|
// https://www.kernel.org/doc/html/v6.4-rc7/bpf/instruction-set.html#instruction-encoding
|
|
|
|
|
let prog: &[u8] = &[
|
|
|
|
|
0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov64 r0 = 0
|
|
|
|
|
0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exit
|
|
|
|
|
];
|
|
|
|
|
let mov64_imm = (BPF_ALU64 | BPF_MOV | BPF_K).try_into().unwrap();
|
|
|
|
|
let exit = (BPF_JMP | BPF_EXIT).try_into().unwrap();
|
|
|
|
|
let insns = [new_insn(mov64_imm, 0, 0, 0, 0), new_insn(exit, 0, 0, 0, 0)];
|
|
|
|
|
|
|
|
|
|
let gpl = c"GPL";
|
|
|
|
|
u.license = gpl.as_ptr() as u64;
|
|
|
|
|
|
|
|
|
|
let insns = copy_instructions(prog).unwrap();
|
|
|
|
|
u.insn_cnt = insns.len() as u32;
|
|
|
|
|
u.insns = insns.as_ptr() as u64;
|
|
|
|
|
u.prog_type = bpf_prog_type::BPF_PROG_TYPE_TRACEPOINT as u32;
|
|
|
|
@ -797,38 +800,38 @@ pub(crate) fn is_info_gpl_compatible_supported() -> bool {
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO(tamird): remove when these are generated on the userspace side.
|
|
|
|
|
const BPF_SUB: u32 = 16;
|
|
|
|
|
const BPF_EXIT: u32 = 144;
|
|
|
|
|
const BPF_IMM: u32 = 0;
|
|
|
|
|
const BPF_MEM: u32 = 96;
|
|
|
|
|
const BPF_MOV: u32 = 176;
|
|
|
|
|
const BPF_X: u32 = 8;
|
|
|
|
|
|
|
|
|
|
const BPF_FUNC_PROBE_READ_KERNEL: i32 = 113;
|
|
|
|
|
const BPF_FUNC_GET_ATTACH_COOKIE: i32 = 174;
|
|
|
|
|
|
|
|
|
|
pub(crate) fn is_probe_read_kernel_supported() -> bool {
|
|
|
|
|
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
|
|
|
|
|
let u = unsafe { &mut attr.__bindgen_anon_3 };
|
|
|
|
|
|
|
|
|
|
// The fields conforming an encoded basic instruction are stored in the following order:
|
|
|
|
|
// opcode:8 src_reg:4 dst_reg:4 offset:16 imm:32 - In little-endian BPF.
|
|
|
|
|
// opcode:8 dst_reg:4 src_reg:4 offset:16 imm:32 - In big-endian BPF.
|
|
|
|
|
// Multi-byte fields ('imm' and 'offset') are stored using endian order.
|
|
|
|
|
// https://www.kernel.org/doc/html/v6.4-rc7/bpf/instruction-set.html#instruction-encoding
|
|
|
|
|
#[cfg(target_endian = "little")]
|
|
|
|
|
let prog: &[u8] = &[
|
|
|
|
|
0xbf, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // r1 = r10
|
|
|
|
|
0x07, 0x01, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, // r1 -= 8
|
|
|
|
|
0xb7, 0x02, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, // r2 = 8
|
|
|
|
|
0xb7, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // r3 = 0
|
|
|
|
|
0x85, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, // call 113
|
|
|
|
|
0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exit
|
|
|
|
|
];
|
|
|
|
|
#[cfg(target_endian = "big")]
|
|
|
|
|
let prog: &[u8] = &[
|
|
|
|
|
0xbf, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // r1 = r10
|
|
|
|
|
0x07, 0x10, 0x00, 0x00, 0xff, 0xff, 0xff, 0xf8, // r1 -= 8
|
|
|
|
|
0xb7, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, // r2 = 8
|
|
|
|
|
0xb7, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // r3 = 0
|
|
|
|
|
0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, // call 113
|
|
|
|
|
0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exit
|
|
|
|
|
let mov64_reg = (BPF_ALU64 | BPF_MOV | BPF_X).try_into().unwrap();
|
|
|
|
|
let sub64_imm = (BPF_ALU64 | BPF_SUB | BPF_K).try_into().unwrap();
|
|
|
|
|
let mov64_imm = (BPF_ALU64 | BPF_MOV | BPF_K).try_into().unwrap();
|
|
|
|
|
let call = (BPF_JMP | BPF_CALL).try_into().unwrap();
|
|
|
|
|
let exit = (BPF_JMP | BPF_EXIT).try_into().unwrap();
|
|
|
|
|
let insns = [
|
|
|
|
|
new_insn(mov64_reg, 1, 10, 0, 0),
|
|
|
|
|
new_insn(sub64_imm, 1, 0, 0, 8),
|
|
|
|
|
new_insn(mov64_imm, 2, 0, 0, 8),
|
|
|
|
|
new_insn(mov64_imm, 3, 0, 0, 0),
|
|
|
|
|
new_insn(call, 0, 0, 0, BPF_FUNC_PROBE_READ_KERNEL),
|
|
|
|
|
new_insn(exit, 0, 0, 0, 0),
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
let gpl = c"GPL";
|
|
|
|
|
u.license = gpl.as_ptr() as u64;
|
|
|
|
|
|
|
|
|
|
let insns = copy_instructions(prog).unwrap();
|
|
|
|
|
u.insn_cnt = insns.len() as u32;
|
|
|
|
|
u.insns = insns.as_ptr() as u64;
|
|
|
|
|
u.prog_type = bpf_prog_type::BPF_PROG_TYPE_TRACEPOINT as u32;
|
|
|
|
@ -860,30 +863,6 @@ pub(crate) fn is_bpf_global_data_supported() -> bool {
|
|
|
|
|
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
|
|
|
|
|
let u = unsafe { &mut attr.__bindgen_anon_3 };
|
|
|
|
|
|
|
|
|
|
// The fields conforming an encoded basic instruction are stored in the following order:
|
|
|
|
|
// opcode:8 src_reg:4 dst_reg:4 offset:16 imm:32 - In little-endian BPF.
|
|
|
|
|
// opcode:8 dst_reg:4 src_reg:4 offset:16 imm:32 - In big-endian BPF.
|
|
|
|
|
// Multi-byte fields ('imm' and 'offset') are stored using endian order.
|
|
|
|
|
// https://www.kernel.org/doc/html/v6.4-rc7/bpf/instruction-set.html#instruction-encoding
|
|
|
|
|
#[cfg(target_endian = "little")]
|
|
|
|
|
let prog: &[u8] = &[
|
|
|
|
|
0x18, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ld_pseudo r1, 0x2, 0x0
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, //
|
|
|
|
|
0x7a, 0x01, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, // stdw [r1 + 0x0], 0x2a
|
|
|
|
|
0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov64 r0 = 0
|
|
|
|
|
0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exit
|
|
|
|
|
];
|
|
|
|
|
#[cfg(target_endian = "big")]
|
|
|
|
|
let prog: &[u8] = &[
|
|
|
|
|
0x18, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, // ld_pseudo r1, 0x2, 0x0
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
|
|
|
|
|
0x7a, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, // stdw [r1 + 0x0], 0x2a
|
|
|
|
|
0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov64 r0 = 0
|
|
|
|
|
0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exit
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
let mut insns = copy_instructions(prog).unwrap();
|
|
|
|
|
|
|
|
|
|
let map = MapData::create(
|
|
|
|
|
aya_obj::Map::Legacy(LegacyMap {
|
|
|
|
|
def: bpf_map_def {
|
|
|
|
@ -903,7 +882,19 @@ pub(crate) fn is_bpf_global_data_supported() -> bool {
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if let Ok(map) = map {
|
|
|
|
|
insns[0].imm = map.fd().as_fd().as_raw_fd();
|
|
|
|
|
let ld_map_value = (BPF_LD | BPF_DW | BPF_IMM).try_into().unwrap();
|
|
|
|
|
let pseudo_map_value = BPF_PSEUDO_MAP_VALUE.try_into().unwrap();
|
|
|
|
|
let fd = map.fd().as_fd().as_raw_fd();
|
|
|
|
|
let st_mem = (BPF_ST | BPF_DW | BPF_MEM).try_into().unwrap();
|
|
|
|
|
let mov64_imm = (BPF_ALU64 | BPF_MOV | BPF_K).try_into().unwrap();
|
|
|
|
|
let exit = (BPF_JMP | BPF_EXIT).try_into().unwrap();
|
|
|
|
|
let insns = [
|
|
|
|
|
new_insn(ld_map_value, 1, pseudo_map_value, 0, fd),
|
|
|
|
|
new_insn(0, 0, 0, 0, 0),
|
|
|
|
|
new_insn(st_mem, 1, 0, 0, 42),
|
|
|
|
|
new_insn(mov64_imm, 0, 0, 0, 0),
|
|
|
|
|
new_insn(exit, 0, 0, 0, 0),
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
let gpl = c"GPL";
|
|
|
|
|
u.license = gpl.as_ptr() as u64;
|
|
|
|
@ -921,26 +912,16 @@ pub(crate) fn is_bpf_cookie_supported() -> bool {
|
|
|
|
|
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
|
|
|
|
|
let u = unsafe { &mut attr.__bindgen_anon_3 };
|
|
|
|
|
|
|
|
|
|
// The fields conforming an encoded basic instruction are stored in the following order:
|
|
|
|
|
// opcode:8 src_reg:4 dst_reg:4 offset:16 imm:32 - In little-endian BPF.
|
|
|
|
|
// opcode:8 dst_reg:4 src_reg:4 offset:16 imm:32 - In big-endian BPF.
|
|
|
|
|
// Multi-byte fields ('imm' and 'offset') are stored using endian order.
|
|
|
|
|
// https://www.kernel.org/doc/html/v6.4-rc7/bpf/instruction-set.html#instruction-encoding
|
|
|
|
|
#[cfg(target_endian = "little")]
|
|
|
|
|
let prog: &[u8] = &[
|
|
|
|
|
0x85, 0x00, 0x00, 0x00, 0xae, 0x00, 0x00, 0x00, // call bpf_get_attach_cookie
|
|
|
|
|
0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exit
|
|
|
|
|
];
|
|
|
|
|
#[cfg(target_endian = "big")]
|
|
|
|
|
let prog: &[u8] = &[
|
|
|
|
|
0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xae, // call bpf_get_attach_cookie
|
|
|
|
|
0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exit
|
|
|
|
|
let call = (BPF_JMP | BPF_CALL).try_into().unwrap();
|
|
|
|
|
let exit = (BPF_JMP | BPF_EXIT).try_into().unwrap();
|
|
|
|
|
let insns = [
|
|
|
|
|
new_insn(call, 0, 0, 0, BPF_FUNC_GET_ATTACH_COOKIE),
|
|
|
|
|
new_insn(exit, 0, 0, 0, 0),
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
let gpl = c"GPL";
|
|
|
|
|
u.license = gpl.as_ptr() as u64;
|
|
|
|
|
|
|
|
|
|
let insns = copy_instructions(prog).unwrap();
|
|
|
|
|
u.insn_cnt = insns.len() as u32;
|
|
|
|
|
u.insns = insns.as_ptr() as u64;
|
|
|
|
|
u.prog_type = bpf_prog_type::BPF_PROG_TYPE_KPROBE as u32;
|
|
|
|
|