{"id":31768826,"url":"https://github.com/tonywu6/ebpf-packet-first-byte","last_synced_at":"2026-05-17T02:48:52.414Z","repository":{"id":318707690,"uuid":"1063057305","full_name":"tonywu6/ebpf-packet-first-byte","owner":"tonywu6","description":null,"archived":false,"fork":false,"pushed_at":"2025-09-24T05:38:30.000Z","size":21,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-11-12T03:27:04.992Z","etag":null,"topics":["ebpf","ebpf-rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tonywu6.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-24T05:38:12.000Z","updated_at":"2025-09-24T05:44:27.000Z","dependencies_parsed_at":"2025-10-09T23:11:41.502Z","dependency_job_id":"5ec2898f-0215-43af-b986-26cf40c13ae5","html_url":"https://github.com/tonywu6/ebpf-packet-first-byte","commit_stats":null,"previous_names":["tonywu6/ebpf-packet-first-byte"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/tonywu6/ebpf-packet-first-byte","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tonywu6%2Febpf-packet-first-byte","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tonywu6%2Febpf-packet-first-byte/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tonywu6%2Febpf-packet-first-byte/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tonywu6%2Febpf-packet-first-byte/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tonywu6","download_url":"https://codeload.github.com/tonywu6/ebpf-packet-first-byte/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tonywu6%2Febpf-packet-first-byte/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33125913,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-16T18:38:32.183Z","status":"online","status_checked_at":"2026-05-17T02:00:05.366Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ebpf","ebpf-rust"],"created_at":"2025-10-10T02:15:15.313Z","updated_at":"2026-05-17T02:48:52.408Z","avatar_url":"https://github.com/tonywu6.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ebpf-packet-first-byte\n\nA corner case with the eBPF verifier when trying to load exactly the first byte of\npacket data via [direct packet access], using [Aya].\n\n## Problem\n\nThe eBPF verifier requires programs to check that pointers are within the range\n`skb.data..skb.data_end` before accessing packet data.\n[The following logic](example1/src/main.rs#L24-35) is commonly used:\n\n```rs\nfn ptr_at\u003cT\u003e(skb: \u0026SkBuff, offset: usize) -\u003e Result\u003c*const T, ()\u003e {\n    let skb = unsafe { \u0026*skb.skb };\n    let ptr = skb.data as usize;\n    let ptr = ptr + offset;\n    let end = skb.data_end as usize;\n    if ptr + size_of::\u003cT\u003e() \u003e end {\n        Err(())\n    } else {\n        Ok(ptr as _)\n    }\n}\n```\n\nHowever, loading from a pointer returned by `ptr_at::\u003cu8\u003e(skb, 0)` (loading only the\nfirst byte) apparently fails the verification:\n\n```\nthe BPF_PROG_LOAD syscall failed. Verifier output: 0: R1=ctx() R10=fp0\n0: (61) r2 = *(u32 *)(r1 +76)         ; R1=ctx() R2_w=pkt(r=0)\n1: (61) r1 = *(u32 *)(r1 +80)         ; R1_w=pkt_end()\n2: (3d) if r2 \u003e= r1 goto pc+11        ; R1_w=pkt_end() R2_w=pkt(r=0)\n3: (71) r6 = *(u8 *)(r2 +0)\ninvalid access to packet, off=0 size=1, R2(id=0,off=0,r=0)\nR2 offset is outside of the packet\n```\n\nThis does not happen when loading more than 1 byte or loading not from the first byte\n(such as `ptr_at::\u003c[u8; 2]\u003e(skb, 0)` or `ptr_at::\u003cu8\u003e(skb, 1)`).\n\nComparing verifier outputs:\n\n```diff\n- ; ptr_at::\u003cu8\u003e(skb, 0)\n- 2: (3d) if r2 \u003e= r1 goto pc+11        ; R1_w=pkt_end() R2_w=pkt(r=0)\n+ ; ptr_at::\u003cu8\u003e(skb, 1)\n+ 3: (07) r3 += 2                       ; R3_w=pkt(off=2,r=0)\n+ 4: (2d) if r3 \u003e r2 goto pc+8          ; R2_w=pkt_end() R3_w=pkt(off=2,r=2)\n```\n\nit appears that the compiler is optimizing the comparison\n`skb.data + 0 + 1 \u003e skb.data_end` into `skb.data \u003e= skb.data_end`, which results in the\nverifier not updating known packet length (`pkt(r=0)` indicates 0 bytes starting from\n`skb.data` is safe to read).\n\n## Solution\n\n[Rewriting](example2/src/main.rs#L24-35) `ptr_at` to use **pointer arithmetic** instead\nof integer arithmetic causes the correct instruction to be generated:\n\n```rs\n#[inline]\nfn ptr_at\u003cT\u003e(skb: \u0026SkBuff, offset: usize) -\u003e Result\u003c*const T, ()\u003e {\n    let skb = unsafe { \u0026*skb.skb };\n    let ptr = skb.data as *const u8;\n    let ptr = unsafe { ptr.add(offset) };\n    let end = skb.data_end as *const u8;\n    if unsafe { ptr.add(size_of::\u003cT\u003e()) } \u003e end {\n        Err(())\n    } else {\n        Ok(ptr as _)\n    }\n}\n```\n\n```diff\n  0: (61) r2 = *(u32 *)(r1 +80)         ; R1=ctx() R2_w=pkt_end()\n  1: (61) r1 = *(u32 *)(r1 +76)         ; R1_w=pkt(r=0)\n  2: (bf) r3 = r1                       ; R1_w=pkt(r=0) R3_w=pkt(r=0)\n+ 3: (07) r3 += 1                       ; R3_w=pkt(off=1,r=0)\n+ 4: (2d) if r3 \u003e r2 goto pc+8          ; R2_w=pkt_end() R3_w=pkt(off=1,r=1)\n```\n\n## Environment\n\n- Linux 6.15.11 ([`mcr.microsoft.com/devcontainers/rust:bookworm`][bookworm])\n- LLVM 21.1.1\n\n## License\n\nWith the exception of eBPF code, ebpf-packet-first-byte is distributed under the terms\nof either the [MIT license][mit] or the [Apache License][apache] (version 2.0), at your\noption.\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for\ninclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual\nlicensed as above, without any additional terms or conditions.\n\n### eBPF\n\nAll eBPF code is distributed under either the terms of the [GNU General Public License,\nVersion 2][gplv2] or the [MIT license][mit], at your option.\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for\ninclusion in this project by you, as defined in the GPL-2 license, shall be dual\nlicensed as above, without any additional terms or conditions.\n\n[apache]: LICENSE-APACHE\n[Aya]: https://aya-rs.dev\n[bookworm]: https://github.com/devcontainers/images/blob/main/src/rust/README.md\n[direct packet access]: https://docs.kernel.org/bpf/verifier.html#direct-packet-access\n[gplv2]: LICENSE-GPL2\n[mit]: LICENSE-MIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftonywu6%2Febpf-packet-first-byte","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftonywu6%2Febpf-packet-first-byte","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftonywu6%2Febpf-packet-first-byte/lists"}