Minor refactors
This commit is contained in:
parent
30aef698bb
commit
c35c83a4b2
|
@ -8,7 +8,7 @@ use {
|
||||||
std::os::raw::{c_char, c_int, c_void},
|
std::os::raw::{c_char, c_int, c_void},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub async unsafe fn gethostbyaddr2_r(
|
pub async unsafe fn with(
|
||||||
_addr: *const c_void,
|
_addr: *const c_void,
|
||||||
_len: socklen_t,
|
_len: socklen_t,
|
||||||
_af: c_int,
|
_af: c_int,
|
||||||
|
|
|
@ -2,15 +2,19 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
use {
|
use {
|
||||||
crate::helpers::{records_to_gaih_addr, records_to_hostent, set_if_valid, DnsResult},
|
crate::helpers::{set_if_valid, write_record_name_to_buf, write_vector_to_buf},
|
||||||
crate::nss_bindings::{gaih_addrtuple, nss_status, HErrno},
|
crate::nss_bindings::{gaih_addrtuple, nss_status, HErrno},
|
||||||
crate::policy_checker::{PolicyChecker as _, POLICY_CHECKER},
|
crate::policy_checker::{PolicyChecker as _, POLICY_CHECKER},
|
||||||
libc::{c_char, c_int, hostent, size_t},
|
libc::{c_char, c_int, hostent, size_t, AF_INET, AF_INET6},
|
||||||
nix::errno,
|
nix::errno,
|
||||||
nix::errno::Errno,
|
nix::errno::Errno,
|
||||||
std::ffi::CStr,
|
std::ffi::CStr,
|
||||||
|
std::mem::{align_of, discriminant, size_of},
|
||||||
|
std::sync::Arc,
|
||||||
trust_dns_proto::rr::record_type::RecordType,
|
trust_dns_proto::rr::record_type::RecordType,
|
||||||
|
trust_dns_proto::rr::{RData, Record},
|
||||||
trust_dns_proto::xfer::dns_request::DnsRequestOptions,
|
trust_dns_proto::xfer::dns_request::DnsRequestOptions,
|
||||||
|
trust_dns_resolver::TokioAsyncResolver,
|
||||||
trust_dns_resolver::{lookup::Lookup, lookup_ip::LookupIp},
|
trust_dns_resolver::{lookup::Lookup, lookup_ip::LookupIp},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -33,6 +37,11 @@ pub enum Result {
|
||||||
V4(*mut *mut gaih_addrtuple),
|
V4(*mut *mut gaih_addrtuple),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum DnsResult {
|
||||||
|
NxDomain,
|
||||||
|
Found,
|
||||||
|
}
|
||||||
|
|
||||||
pub async unsafe fn with(args: &mut Args) -> nss_status {
|
pub async unsafe fn with(args: &mut Args) -> nss_status {
|
||||||
set_if_valid(args.errnop, errno::from_i32(0));
|
set_if_valid(args.errnop, errno::from_i32(0));
|
||||||
set_if_valid(args.h_errnop, HErrno::Success);
|
set_if_valid(args.h_errnop, HErrno::Success);
|
||||||
|
@ -42,7 +51,18 @@ pub async unsafe fn with(args: &mut Args) -> nss_status {
|
||||||
// no restrictions for user, the next NSS module will decide
|
// no restrictions for user, the next NSS module will decide
|
||||||
nss_status::NSS_STATUS_NOTFOUND
|
nss_status::NSS_STATUS_NOTFOUND
|
||||||
}
|
}
|
||||||
Ok(Some(resolver)) => {
|
Ok(Some(resolver)) => resolve_hostname_through(resolver, args).await,
|
||||||
|
Err(err) => {
|
||||||
|
log::error!("{}", err);
|
||||||
|
nss_status::NSS_STATUS_UNAVAIL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async unsafe fn resolve_hostname_through(
|
||||||
|
resolver: Arc<TokioAsyncResolver>,
|
||||||
|
args: &mut Args,
|
||||||
|
) -> nss_status {
|
||||||
let name = match CStr::from_ptr(args.name).to_str() {
|
let name = match CStr::from_ptr(args.name).to_str() {
|
||||||
Ok(name) => name,
|
Ok(name) => name,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
|
@ -52,8 +72,6 @@ pub async unsafe fn with(args: &mut Args) -> nss_status {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// disable application-based DNS for those applications
|
|
||||||
// (notably, Firefox) that support it
|
|
||||||
if name == CANARY_HOSTNAME {
|
if name == CANARY_HOSTNAME {
|
||||||
set_if_valid(args.h_errnop, HErrno::HostNotFound);
|
set_if_valid(args.h_errnop, HErrno::HostNotFound);
|
||||||
return nss_status::NSS_STATUS_SUCCESS;
|
return nss_status::NSS_STATUS_SUCCESS;
|
||||||
|
@ -81,12 +99,6 @@ pub async unsafe fn with(args: &mut Args) -> nss_status {
|
||||||
nss_status::NSS_STATUS_UNAVAIL
|
nss_status::NSS_STATUS_UNAVAIL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
log::error!("{}", err);
|
|
||||||
nss_status::NSS_STATUS_UNAVAIL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn prepare_response(
|
unsafe fn prepare_response(
|
||||||
|
@ -167,3 +179,147 @@ unsafe fn prepare_response(
|
||||||
|
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: refactor to be less ugly
|
||||||
|
pub unsafe fn records_to_hostent(
|
||||||
|
lookup: Lookup,
|
||||||
|
host: &mut hostent,
|
||||||
|
buf: &mut [u8],
|
||||||
|
) -> std::io::Result<DnsResult> {
|
||||||
|
// In C struct hostent:
|
||||||
|
//
|
||||||
|
// - for the type of queries we perform, we can assume h_aliases
|
||||||
|
// is an empty array.
|
||||||
|
// - hostent is limited to just one address type for all addresses
|
||||||
|
// in the list. We pick the type of first result, and only
|
||||||
|
// append addresses of the same type.
|
||||||
|
|
||||||
|
let first_record = match lookup.record_iter().peekable().peek() {
|
||||||
|
Some(record) => *record,
|
||||||
|
None => return Ok(DnsResult::NxDomain),
|
||||||
|
};
|
||||||
|
|
||||||
|
let first_rdata = match first_record.data() {
|
||||||
|
Some(rdata) => rdata,
|
||||||
|
None => return Err(Errno::ENODATA.into()),
|
||||||
|
};
|
||||||
|
|
||||||
|
// First put the name in the buffer
|
||||||
|
let (buf, name_dest) = write_record_name_to_buf(first_record, buf)?;
|
||||||
|
|
||||||
|
// Then the empty aliases array (just a null pointer)
|
||||||
|
let (mut buf, aliases_ptr) = write_vector_to_buf(buf, vec![std::ptr::null_mut()])?;
|
||||||
|
|
||||||
|
// Then the address list
|
||||||
|
let offset = buf.as_ptr().align_offset(align_of::<*mut c_char>());
|
||||||
|
buf = &mut buf[offset..];
|
||||||
|
|
||||||
|
let records = lookup
|
||||||
|
.record_iter()
|
||||||
|
.flat_map(Record::data)
|
||||||
|
.filter(|r| discriminant(*r) == discriminant(first_rdata));
|
||||||
|
|
||||||
|
let mut addresses = vec![];
|
||||||
|
for record in records {
|
||||||
|
let offset = buf.as_ptr().align_offset(align_of::<*mut c_char>());
|
||||||
|
buf = &mut buf[offset..];
|
||||||
|
addresses.push(buf.as_mut_ptr());
|
||||||
|
|
||||||
|
let l = match record {
|
||||||
|
RData::A(addr) => {
|
||||||
|
let octets = addr.octets();
|
||||||
|
let l = octets.len();
|
||||||
|
if buf.len() < l {
|
||||||
|
return Err(Errno::ERANGE.into());
|
||||||
|
}
|
||||||
|
buf[..l].copy_from_slice(&octets);
|
||||||
|
l
|
||||||
|
}
|
||||||
|
RData::AAAA(addr) => {
|
||||||
|
let octets = addr.octets();
|
||||||
|
let l = octets.len();
|
||||||
|
if buf.len() < l {
|
||||||
|
return Err(Errno::ERANGE.into());
|
||||||
|
}
|
||||||
|
buf[..l].copy_from_slice(&octets);
|
||||||
|
l
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
buf = &mut buf[l..];
|
||||||
|
}
|
||||||
|
|
||||||
|
addresses.push(std::ptr::null_mut());
|
||||||
|
let (_, addr_list) = write_vector_to_buf(buf, addresses)?;
|
||||||
|
|
||||||
|
// Finally, populate the hostent structure
|
||||||
|
host.h_name = name_dest;
|
||||||
|
host.h_aliases = aliases_ptr;
|
||||||
|
host.h_addr_list = addr_list as *mut *mut c_char;
|
||||||
|
match first_rdata {
|
||||||
|
RData::A(_) => {
|
||||||
|
host.h_addrtype = AF_INET;
|
||||||
|
host.h_length = 4;
|
||||||
|
}
|
||||||
|
RData::AAAA(_) => {
|
||||||
|
host.h_addrtype = AF_INET6;
|
||||||
|
host.h_length = 16;
|
||||||
|
}
|
||||||
|
_ => return Err(Errno::EBADMSG.into()),
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(DnsResult::Found)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: error handling codes chosen a bit sloppily
|
||||||
|
pub unsafe fn records_to_gaih_addr(
|
||||||
|
lookup: Lookup,
|
||||||
|
mut buf: &mut [u8],
|
||||||
|
) -> std::io::Result<*mut gaih_addrtuple> {
|
||||||
|
const GAIH_ADDRTUPLE_SZ: usize = size_of::<gaih_addrtuple>();
|
||||||
|
|
||||||
|
let mut ret = std::ptr::null_mut();
|
||||||
|
let mut prev_link: *mut *mut gaih_addrtuple = std::ptr::null_mut();
|
||||||
|
|
||||||
|
let mut name_dest;
|
||||||
|
for record in lookup.record_iter() {
|
||||||
|
// First add the name to the buffer
|
||||||
|
(buf, name_dest) = write_record_name_to_buf(record, buf)?;
|
||||||
|
|
||||||
|
// Then add the tuple with the address
|
||||||
|
let offset = buf.as_ptr().align_offset(align_of::<gaih_addrtuple>());
|
||||||
|
let l = GAIH_ADDRTUPLE_SZ;
|
||||||
|
if buf.len() < offset + l {
|
||||||
|
return Err(Errno::ERANGE.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
let tuple = &mut *(buf.as_mut_ptr().add(offset) as *mut gaih_addrtuple);
|
||||||
|
tuple.next = std::ptr::null_mut();
|
||||||
|
tuple.name = name_dest;
|
||||||
|
tuple.scopeid = 0; // how to set tuple.scopeid correctly??? Use a custom trust_dns_resolver::ConnectionProvider?
|
||||||
|
set_if_valid(prev_link, &mut *tuple); // link from previous tuple to this tuple
|
||||||
|
prev_link = &mut (*tuple).next;
|
||||||
|
|
||||||
|
match record.data() {
|
||||||
|
Some(RData::A(addr)) => {
|
||||||
|
tuple.family = AF_INET;
|
||||||
|
tuple.addr[0] = std::mem::transmute_copy(&addr.octets());
|
||||||
|
}
|
||||||
|
Some(RData::AAAA(addr)) => {
|
||||||
|
tuple.family = AF_INET6;
|
||||||
|
tuple.addr = std::mem::transmute_copy(&addr.octets());
|
||||||
|
}
|
||||||
|
Some(_) => return Err(Errno::EBADMSG.into()),
|
||||||
|
None => return Err(Errno::ENODATA.into()),
|
||||||
|
}
|
||||||
|
|
||||||
|
if ret == std::ptr::null_mut() {
|
||||||
|
ret = tuple;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = &mut buf[(offset + l)..];
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(ret)
|
||||||
|
}
|
||||||
|
|
200
src/helpers.rs
200
src/helpers.rs
|
@ -2,16 +2,12 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
use {
|
use {
|
||||||
crate::nss_bindings::gaih_addrtuple,
|
libc::c_char,
|
||||||
anyhow::{bail, Result},
|
|
||||||
libc::{c_char, hostent, AF_INET, AF_INET6},
|
|
||||||
nix::errno::Errno,
|
nix::errno::Errno,
|
||||||
once_cell::sync::Lazy,
|
once_cell::sync::Lazy,
|
||||||
std::ffi::CString,
|
std::ffi::CString,
|
||||||
std::mem::{align_of, discriminant, size_of},
|
std::mem::{align_of, size_of},
|
||||||
trust_dns_proto::rr::resource::Record,
|
trust_dns_proto::rr::resource::Record,
|
||||||
trust_dns_proto::rr::RData,
|
|
||||||
trust_dns_resolver::lookup::Lookup,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static RUNTIME: Lazy<std::io::Result<tokio::runtime::Runtime>> = Lazy::new(|| {
|
static RUNTIME: Lazy<std::io::Result<tokio::runtime::Runtime>> = Lazy::new(|| {
|
||||||
|
@ -24,171 +20,7 @@ static RUNTIME: Lazy<std::io::Result<tokio::runtime::Runtime>> = Lazy::new(|| {
|
||||||
Ok(rt)
|
Ok(rt)
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: error handling codes chosen a bit sloppily
|
pub fn write_record_name_to_buf<'a>(
|
||||||
pub unsafe fn records_to_gaih_addr(
|
|
||||||
lookup: Lookup,
|
|
||||||
mut buf: &mut [u8],
|
|
||||||
) -> std::io::Result<*mut gaih_addrtuple> {
|
|
||||||
const GAIH_ADDRTUPLE_SZ: usize = size_of::<gaih_addrtuple>();
|
|
||||||
|
|
||||||
let mut ret = std::ptr::null_mut();
|
|
||||||
let mut prev_link: *mut *mut gaih_addrtuple = std::ptr::null_mut();
|
|
||||||
|
|
||||||
let mut name_dest;
|
|
||||||
for record in lookup.record_iter() {
|
|
||||||
// First add the name to the buffer
|
|
||||||
(buf, name_dest) = write_record_name_to_buf(record, buf)?;
|
|
||||||
|
|
||||||
// Then add the tuple with the address
|
|
||||||
let offset = buf.as_ptr().align_offset(align_of::<gaih_addrtuple>());
|
|
||||||
let l = GAIH_ADDRTUPLE_SZ;
|
|
||||||
if buf.len() < offset + l {
|
|
||||||
return Err(Errno::ERANGE.into());
|
|
||||||
}
|
|
||||||
|
|
||||||
let tuple = &mut *(buf.as_mut_ptr().add(offset) as *mut gaih_addrtuple);
|
|
||||||
tuple.next = std::ptr::null_mut();
|
|
||||||
tuple.name = name_dest;
|
|
||||||
tuple.scopeid = 0; // how to set tuple.scopeid ????
|
|
||||||
set_if_valid(prev_link, &mut *tuple); // link from previous tuple to this tuple
|
|
||||||
prev_link = &mut (*tuple).next;
|
|
||||||
|
|
||||||
match record.data() {
|
|
||||||
Some(RData::A(addr)) => {
|
|
||||||
tuple.family = AF_INET;
|
|
||||||
tuple.addr[0] = std::mem::transmute_copy(&addr.octets());
|
|
||||||
}
|
|
||||||
Some(RData::AAAA(addr)) => {
|
|
||||||
tuple.family = AF_INET6;
|
|
||||||
tuple.addr = std::mem::transmute_copy(&addr.octets());
|
|
||||||
}
|
|
||||||
Some(_) => return Err(Errno::EBADMSG.into()),
|
|
||||||
None => return Err(Errno::ENODATA.into()),
|
|
||||||
}
|
|
||||||
|
|
||||||
if ret == std::ptr::null_mut() {
|
|
||||||
ret = tuple;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf = &mut buf[(offset + l)..];
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(ret)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum DnsResult {
|
|
||||||
NxDomain,
|
|
||||||
Found,
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: refactor to be less ugly
|
|
||||||
pub unsafe fn records_to_hostent(
|
|
||||||
lookup: Lookup,
|
|
||||||
host: &mut hostent,
|
|
||||||
mut buf: &mut [u8],
|
|
||||||
) -> std::io::Result<DnsResult> {
|
|
||||||
// In C struct hostent:
|
|
||||||
//
|
|
||||||
// - for the type of queries we perform, we can assume h_aliases
|
|
||||||
// is an empty array.
|
|
||||||
// - hostent is limited to just one address type for all addresses
|
|
||||||
// in the list. We pick the type of first result, and only
|
|
||||||
// append addresses of the same type.
|
|
||||||
|
|
||||||
let first_record = match lookup.record_iter().peekable().peek() {
|
|
||||||
Some(record) => *record,
|
|
||||||
None => return Ok(DnsResult::NxDomain),
|
|
||||||
};
|
|
||||||
|
|
||||||
let first_rdata = match first_record.data() {
|
|
||||||
Some(rdata) => rdata,
|
|
||||||
None => return Err(Errno::ENODATA.into()),
|
|
||||||
};
|
|
||||||
|
|
||||||
// First put the name in the buffer
|
|
||||||
let name_dest;
|
|
||||||
(buf, name_dest) = write_record_name_to_buf(first_record, buf)?;
|
|
||||||
|
|
||||||
// Then the empty aliases array (just a null pointer)
|
|
||||||
let offset = buf.as_ptr().align_offset(align_of::<*mut c_char>());
|
|
||||||
let l = size_of::<*mut c_char>();
|
|
||||||
if buf.len() < offset + l {
|
|
||||||
return Err(Errno::ERANGE.into());
|
|
||||||
}
|
|
||||||
let aliases_ptr = buf[offset..].as_mut_ptr().cast::<*mut c_char>();
|
|
||||||
aliases_ptr.write(std::ptr::null_mut());
|
|
||||||
buf = &mut buf[(offset + l)..];
|
|
||||||
|
|
||||||
// Then the address list
|
|
||||||
let offset = buf.as_ptr().align_offset(align_of::<*mut c_char>());
|
|
||||||
buf = &mut buf[offset..];
|
|
||||||
|
|
||||||
let records = lookup
|
|
||||||
.record_iter()
|
|
||||||
.flat_map(Record::data)
|
|
||||||
.filter(|r| discriminant(*r) == discriminant(first_rdata));
|
|
||||||
|
|
||||||
let mut addresses = vec![];
|
|
||||||
for record in records {
|
|
||||||
let offset = buf.as_ptr().align_offset(align_of::<*mut c_char>());
|
|
||||||
buf = &mut buf[offset..];
|
|
||||||
addresses.push(buf.as_ptr());
|
|
||||||
|
|
||||||
let l = match record {
|
|
||||||
RData::A(addr) => {
|
|
||||||
let octets = addr.octets();
|
|
||||||
let l = octets.len();
|
|
||||||
if buf.len() < l {
|
|
||||||
return Err(Errno::ERANGE.into());
|
|
||||||
}
|
|
||||||
buf[..l].copy_from_slice(&octets);
|
|
||||||
l
|
|
||||||
}
|
|
||||||
RData::AAAA(addr) => {
|
|
||||||
let octets = addr.octets();
|
|
||||||
let l = octets.len();
|
|
||||||
if buf.len() < l {
|
|
||||||
return Err(Errno::ERANGE.into());
|
|
||||||
}
|
|
||||||
buf[..l].copy_from_slice(&octets);
|
|
||||||
l
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
|
|
||||||
buf = &mut buf[l..];
|
|
||||||
}
|
|
||||||
|
|
||||||
addresses.push(std::ptr::null_mut());
|
|
||||||
|
|
||||||
let offset = buf.as_ptr().align_offset(align_of::<*mut *mut c_char>());
|
|
||||||
let l = size_of::<*mut c_char>() * addresses.len();
|
|
||||||
if buf.len() < offset + l {
|
|
||||||
return Err(Errno::ERANGE.into());
|
|
||||||
}
|
|
||||||
let addr_list = buf[offset..].as_mut_ptr().cast::<*mut c_char>();
|
|
||||||
std::ptr::copy_nonoverlapping(addresses.as_ptr() as *const *mut c_char, addr_list, l);
|
|
||||||
|
|
||||||
// Finally, populate the hostent structure
|
|
||||||
host.h_name = name_dest;
|
|
||||||
host.h_aliases = aliases_ptr;
|
|
||||||
host.h_addr_list = addr_list;
|
|
||||||
match first_rdata {
|
|
||||||
RData::A(_) => {
|
|
||||||
host.h_addrtype = AF_INET;
|
|
||||||
host.h_length = 4;
|
|
||||||
}
|
|
||||||
RData::AAAA(_) => {
|
|
||||||
host.h_addrtype = AF_INET6;
|
|
||||||
host.h_length = 16;
|
|
||||||
}
|
|
||||||
_ => return Err(Errno::EBADMSG.into()),
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(DnsResult::Found)
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn write_record_name_to_buf<'a>(
|
|
||||||
record: &Record,
|
record: &Record,
|
||||||
buf: &'a mut [u8],
|
buf: &'a mut [u8],
|
||||||
) -> std::io::Result<(&'a mut [u8], *mut c_char)> {
|
) -> std::io::Result<(&'a mut [u8], *mut c_char)> {
|
||||||
|
@ -203,18 +35,38 @@ unsafe fn write_record_name_to_buf<'a>(
|
||||||
return Err(Errno::ERANGE.into());
|
return Err(Errno::ERANGE.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let name_dest = buf.as_mut_ptr().add(offset);
|
let name_dest = unsafe { buf.as_mut_ptr().add(offset) };
|
||||||
|
unsafe {
|
||||||
std::ptr::copy_nonoverlapping(name_src.as_ptr(), name_dest, l);
|
std::ptr::copy_nonoverlapping(name_src.as_ptr(), name_dest, l);
|
||||||
|
}
|
||||||
Ok((&mut buf[(offset + l)..], name_dest as *mut c_char))
|
Ok((&mut buf[(offset + l)..], name_dest as *mut c_char))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn write_vector_to_buf<'a, T>(
|
||||||
|
buf: &'a mut [u8],
|
||||||
|
v: Vec<T>,
|
||||||
|
) -> std::io::Result<(&'a mut [u8], *mut T)> {
|
||||||
|
let offset = buf.as_ptr().align_offset(align_of::<*mut T>());
|
||||||
|
let l = size_of::<*mut c_char>() * v.len();
|
||||||
|
if buf.len() < offset + l {
|
||||||
|
return Err(Errno::ERANGE.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
let buf = &mut buf[offset..];
|
||||||
|
let dest = buf.as_mut_ptr().cast::<T>();
|
||||||
|
unsafe {
|
||||||
|
std::ptr::copy_nonoverlapping(v.as_ptr() as *const T, dest, l);
|
||||||
|
}
|
||||||
|
Ok((&mut buf[l..], dest))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_if_valid<T>(ptr: *mut T, val: T) {
|
pub fn set_if_valid<T>(ptr: *mut T, val: T) {
|
||||||
if !ptr.is_null() {
|
if !ptr.is_null() {
|
||||||
unsafe { *ptr = val };
|
unsafe { *ptr = val };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn block_on<F>(f: F) -> Result<F::Output>
|
pub fn block_on<F>(f: F) -> anyhow::Result<F::Output>
|
||||||
where
|
where
|
||||||
F: std::future::Future,
|
F: std::future::Future,
|
||||||
{
|
{
|
||||||
|
@ -224,6 +76,6 @@ where
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
match RUNTIME.deref() {
|
match RUNTIME.deref() {
|
||||||
Ok(rt) => Ok(rt.block_on(async { f.await })),
|
Ok(rt) => Ok(rt.block_on(async { f.await })),
|
||||||
Err(e) => bail!("Unable to start tokio runtime: {}", e),
|
Err(e) => anyhow::bail!("Unable to start tokio runtime: {}", e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,9 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
use {
|
use {
|
||||||
crate::gethostbyaddr::gethostbyaddr2_r,
|
|
||||||
crate::gethostbyname,
|
|
||||||
crate::helpers::{block_on, set_if_valid},
|
crate::helpers::{block_on, set_if_valid},
|
||||||
crate::nss_bindings::{gaih_addrtuple, nss_status, HErrno},
|
crate::nss_bindings::{gaih_addrtuple, nss_status, HErrno},
|
||||||
|
crate::{gethostbyaddr, gethostbyname},
|
||||||
libc::{hostent, size_t, socklen_t, AF_INET},
|
libc::{hostent, size_t, socklen_t, AF_INET},
|
||||||
nix::errno::Errno,
|
nix::errno::Errno,
|
||||||
std::os::raw::{c_char, c_int, c_void},
|
std::os::raw::{c_char, c_int, c_void},
|
||||||
|
@ -146,7 +145,7 @@ pub unsafe extern "C" fn _nss_malcontent_gethostbyaddr2_r(
|
||||||
set_if_valid(h_errnop, HErrno::Success);
|
set_if_valid(h_errnop, HErrno::Success);
|
||||||
|
|
||||||
match block_on(async {
|
match block_on(async {
|
||||||
gethostbyaddr2_r(addr, len, af, host, buffer, buflen, errnop, h_errnop, ttlp).await
|
gethostbyaddr::with(addr, len, af, host, buffer, buflen, errnop, h_errnop, ttlp).await
|
||||||
}) {
|
}) {
|
||||||
Ok(status) => status,
|
Ok(status) => status,
|
||||||
Err(runtime_error) => {
|
Err(runtime_error) => {
|
||||||
|
|
|
@ -151,6 +151,7 @@ fork_test! {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[ignore]
|
||||||
fn privileged_user_bypasses_restrictions() -> Result<()> {
|
fn privileged_user_bypasses_restrictions() -> Result<()> {
|
||||||
common::setup()?;
|
common::setup()?;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue