foniod / redbpf

Rust library for building and running BPF/eBPF modules
Apache License 2.0
1.71k stars 136 forks source link

Segmentation fault today, yesterday it was not happening. #192

Closed sebastiaoamaro closed 3 years ago

sebastiaoamaro commented 3 years ago

Hello, Today I woke up and now there is a segmentation fault on my bpf kernel space code program. Code below:

![no_std]

![no_main]

/// tc map sharing example. This program is loaded by tc filter add ... /// command which is executed by cargo run --example tc-map-share <port>... use core::{ mem::{self, MaybeUninit}, ptr, }; use memoffset::offset_of; use redbpf_macros::map; use redbpf_probes::tc::prelude::*; use clsact::usagemonitor::{SocketAddr};

program!(0xFFFFFFFE, "GPL");

/// A section name of tc map should be maps. You can define up to 64 tc maps /// in the section (tc sets that constraints). /// /// key = port, value = blocked packet count

[map(link_section = "maps")]

static mut usagePID: TcHashMap<u32, u32> = TcHashMap::<u32, u32>::with_max_entries(1024, TcMapPinning::GlobalNamespace);

/// BPF program type is BPF_PROG_TYPE_SCHED_CLS

[tc_action]

fn check_usage(skb: SkBuff) -> TcActionResult {

let eth_len = mem::size_of::<ethhdr>();
let eth_proto = skb.load::<__be16>(offset_of!(ethhdr, h_proto))? as u32;
if eth_proto != ETH_P_IP {
    return Ok(TcAction::Ok);
}

let ip_proto = skb.load::<__u8>(eth_len + offset_of!(iphdr, protocol))? as u32;
if ip_proto != IPPROTO_TCP {
    return Ok(TcAction::Ok);
}

let mut ip_hdr = unsafe { MaybeUninit::<iphdr>::zeroed().assume_init() };
ip_hdr._bitfield_1 = __BindgenBitfieldUnit::new([skb.load::<u8>(eth_len)?]);
if ip_hdr.version() != 4 {
    return Ok(TcAction::Ok);
}

let ihl = ip_hdr.ihl() as usize;
let dst = SocketAddr::new(
    skb.load::<__be32>(eth_len + offset_of!(iphdr, daddr))?,
    skb.load::<__be16>(eth_len + ihl * 4 + offset_of!(tcphdr, dest))?,
);

unsafe{
    let len:u32 = (*skb.skb).len;
    match usagePID.get(&dst.addr){
        None => usagePID.set(&dst.addr,&len),
        Some(value) =>{
            let newvalue = value + len;
            usagePID.set(&dst.addr,&newvalue);
            //trace_print(b"new value is: ", newvalue);

        }
    };

}

return Ok(TcAction::Ok);

}

fn _hex_u8(v: u8, buf: &mut [u8]) { let w = v / 0x10; buf[0] = if w < 0xa { w + b'0' } else { w - 0xa + b'a' }; let u = v % 0x10; buf[1] = if u < 0xa { u + b'0' } else { u - 0xa + b'a' }; }

fn _hex_bytes(arr: &[u8], buf: &mut [u8]) -> usize { let mut pos = 0; for (i, b) in arr.iter().enumerate() { if i != 0 { buf[pos] = b' '; pos += 1; } _hex_u8(*b, &mut buf[pos..pos + 2]); pos += 2; } pos }

fn trace_print(msg: &[u8], x: T) { let mut buf = [0u8; 128]; let mut pos = 0; for c in msg { buf[pos] = *c; pos += 1; }

let ptr = &x as *const T as *const usize as usize;
let sz = mem::size_of::<T>();
let mut arr = [0u8; 64];
for i in 0..sz {
    arr[i] = unsafe { ptr::read((ptr + i) as *const usize as *const u8) };
}

pos += _hex_bytes(&arr[..sz], &mut buf[pos..]);
buf[pos] = b'\n';
pos += 2;

bpf_trace_printk(&buf[..pos]);

}

Don't know the reason, just a warning that is happening for some reason.

sebastiaoamaro commented 3 years ago

Problem on my end.