From 6827b9bbb3b0a0d95025fcb72772a8fa5a568068 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Fri, 28 Jul 2023 09:54:32 -0400 Subject: [PATCH] Do not escape newlines on Err(LoadError).unwrap() Wrap verifier logs in a newtype whose `Debug` impl emits unescaped newlines. This improves ergonomics in tests where we `Result::unwrap()` those load errors; when these fail today they emit the errors with newlines escaped, making them incredibly difficult to read. --- aya-obj/src/btf/btf.rs | 3 ++- aya-obj/src/lib.rs | 25 +++++++++++++++++++++++++ aya/src/programs/mod.rs | 4 ++-- aya/src/sys/bpf.rs | 5 +++-- 4 files changed, 32 insertions(+), 5 deletions(-) diff --git a/aya-obj/src/btf/btf.rs b/aya-obj/src/btf/btf.rs index a9049b1e..7268cea1 100644 --- a/aya-obj/src/btf/btf.rs +++ b/aya-obj/src/btf/btf.rs @@ -13,6 +13,7 @@ use log::debug; use object::{Endianness, SectionIndex}; use crate::{ + VerifierLog, btf::{ info::{FuncSecInfo, LineSecInfo}, relocation::Relocation, @@ -135,7 +136,7 @@ pub enum BtfError { #[source] io_error: std::io::Error, /// The error log produced by the kernel verifier. - verifier_log: String, + verifier_log: VerifierLog, }, /// offset not found for symbol diff --git a/aya-obj/src/lib.rs b/aya-obj/src/lib.rs index 3a33a014..d6d2a8a5 100644 --- a/aya-obj/src/lib.rs +++ b/aya-obj/src/lib.rs @@ -89,3 +89,28 @@ mod util; pub use maps::Map; pub use obj::*; + +/// An error returned from the verifier. +/// +/// Provides a [`Debug`] implementation that doesn't escape newlines. +pub struct VerifierLog(alloc::string::String); + +impl VerifierLog { + /// Create a new verifier log. + pub fn new(log: alloc::string::String) -> Self { + Self(log) + } +} + +impl std::fmt::Debug for VerifierLog { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let Self(log) = self; + f.write_str(log) + } +} + +impl std::fmt::Display for VerifierLog { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + ::fmt(self, f) + } +} diff --git a/aya/src/programs/mod.rs b/aya/src/programs/mod.rs index f868dfc8..6fe3907e 100644 --- a/aya/src/programs/mod.rs +++ b/aya/src/programs/mod.rs @@ -106,7 +106,7 @@ pub use xdp::{Xdp, XdpError, XdpFlags}; use crate::{ generated::{bpf_attach_type, bpf_prog_info, bpf_prog_type}, maps::MapError, - obj::{self, btf::BtfError, Function}, + obj::{self, btf::BtfError, Function, VerifierLog}, pin::PinError, sys::{ bpf_btf_get_fd_by_id, bpf_get_object, bpf_load_program, bpf_pin_object, @@ -142,7 +142,7 @@ pub enum ProgramError { #[source] io_error: io::Error, /// The error log produced by the kernel verifier. - verifier_log: String, + verifier_log: VerifierLog, }, /// A syscall failed. diff --git a/aya/src/sys/bpf.rs b/aya/src/sys/bpf.rs index e9f2eba8..dfda7755 100644 --- a/aya/src/sys/bpf.rs +++ b/aya/src/sys/bpf.rs @@ -10,6 +10,7 @@ use std::{ use crate::util::KernelVersion; use libc::{c_char, c_long, close, ENOENT, ENOSPC}; use obj::{ + VerifierLog, maps::{bpf_map_def, LegacyMap}, BpfSectionKind, }; @@ -1005,7 +1006,7 @@ pub(crate) fn bpf_prog_get_next_id(id: u32) -> Result, (c_long, io:: pub(crate) fn retry_with_verifier_logs( max_retries: usize, f: impl Fn(&mut [u8]) -> SysResult, -) -> (SysResult, String) { +) -> (SysResult, VerifierLog) { const MIN_LOG_BUF_SIZE: usize = 1024 * 10; const MAX_LOG_BUF_SIZE: usize = (std::u32::MAX >> 8) as usize; @@ -1031,7 +1032,7 @@ pub(crate) fn retry_with_verifier_logs( } let log_buf = String::from_utf8(log_buf).unwrap(); - break (ret, log_buf); + break (ret, VerifierLog::new(log_buf)); } }