libpnet / libpnet/libpnet

Multiple panics in `DnsQuery::get_qname_parsed` on malformed DNS data

Open
#762 0 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
2.6k
Forks
329
PR merge metrics
No merged PRs in 30d

Description

Description:

Hi, I encountered multiple panics when invoking the DnsQuery::get_qname_parsed method with malformed DNS packet data. The function has two distinct crash paths due to missing input validation, both reachable through normal DnsPacket parsing. As a network packet parsing library, these functions should handle arbitrary/malformed input gracefully instead of panicking. The related source code is shown below:
https://github.com/libpnet/libpnet/blob/49428d3da6d60b506261269a329ca8e6be79b241/pnet_packet/src/dns.rs#L431-L453

Crash 1: Label length exceeds available data — slice out of bounds (line 445)

When a label length byte claims more bytes than are available, the slice name[offset + 1..offset + 1 + label_len] exceeds the vector length.

This panic is reachable through normal DnsPacket parsing: a malformed DNS packet where the query section contains e.g. [0x05, 0x41, 0x00, ...] would produce a qname of [0x05, 0x41, 0x00] (label_len=5, but only 1 data byte follows before the null terminator). Calling get_qname_parsed() on this parsed query will panic.

Panic: range end index 133 out of range for slice of length 5
Location: pnet_packet/src/dns.rs:445:37

stack backtrace:
  0: __rustc::rust_begin_unwind
  1: core::panicking::panic_fmt
  2: core::slice::index::slice_index_fail::do_panic::runtime
  3: core::slice::index::slice_index_fail
  4: <core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index
  5: core::slice::index::<impl core::ops::index::Index<I> for [T]>::index
  6: <alloc::vec::Vec<T,A> as core::ops::index::Index<I>>::index
  7: pnet_packet::dns::DnsQuery::get_qname_parsed
        at pnet_packet/src/dns.rs:445:37

Crash 2: Non-UTF-8 bytes — unwrap on None (line 447)

DNS labels are binary data (RFC 1035 specifies octets, not UTF-8). When qname bytes contain non-UTF-8 data, str::from_utf8 returns Err, .ok() converts to None, and .unwrap() panics.

This panic is also reachable through normal DnsPacket parsing: a DNS packet with a qname like [0x01, 0xFF, 0x00] (a 1-byte label containing 0xFF, which is not valid UTF-8) will trigger it when get_qname_parsed() is called.

Panic: called `Option::unwrap()` on a `None` value
Location: pnet_packet/src/dns.rs:447:22

stack backtrace:
  0: __rustc::rust_begin_unwind
  1: core::panicking::panic_fmt
  2: core::panicking::panic
  3: core::option::unwrap_failed
  4: core::option::Option<T>::unwrap
  5: pnet_packet::dns::DnsQuery::get_qname_parsed
        at pnet_packet/src/dns.rs:447:22

Both crashes can be triggered through normal DnsPacket parsing of a malformed DNS packet followed by calling get_qname_parsed(). For programs that use this method to process DNS packets from untrusted sources, a crafted packet can crash the process (denial-of-service). In safe Rust, panics do not cause memory corruption — only a process abort or thread unwind.

How to reproduce it:

The PoC program is:

use pnet_packet::dns::{DnsQuery, DnsType, DnsClass};

fn main() {
    // Crash 1: label_len exceeds available data
    let query = DnsQuery {
        qname: vec![0x80, 0x01, 0x02, 0x03, 0x04],
        qtype: DnsType(0),
        qclass: DnsClass(0),
        payload: vec![],
    };
    let _ = query.get_qname_parsed(); // panics: range end index out of range

    // Crash 2: non-UTF-8 bytes
    let query = DnsQuery {
        qname: vec![0x02, 0xFF, 0xFE, 0x00],
        qtype: DnsType(0),
        qclass: DnsClass(0),
        payload: vec![],
    };
    let _ = query.get_qname_parsed(); // panics: unwrap on None
}

Environment:

  • Discovered via fuzz testing
  • OS / distro: Ubuntu 24.04

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in pnet_packet/src/dns.rs at DnsQuery::get_qname_parsed, around lines 431-453, and reproduce both malformed-input cases from the issue. Add focused coverage for truncated labels and non-UTF-8 label bytes, then verify the method no longer panics when those inputs are parsed and queried.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
networking
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.