libopenbsd(3): adds pledge(2) and unveil(2) support for Rust; Makefile, include: adds conditional compilation

This commit is contained in:
Emma Tebibyte 2024-08-10 12:49:35 -06:00
parent b76ff8fd90
commit c7c71c725b
Signed by: emma
GPG Key ID: 06FA419A1698C270
5 changed files with 124 additions and 4 deletions

View File

@ -16,6 +16,9 @@
DESTDIR ?= dist
PREFIX ?= /usr/local
# for conditionally compiling OS features
OS != uname
# normalized prefix
PREFIX_N != dirname $(PREFIX)/.
MANDIR != test $(PREFIX_N) = / && printf '/usr/share/man\n' \
@ -26,8 +29,8 @@ SYSEXITS != printf '\043include <sysexits.h>\n' | cpp -M - | tr ' ' '\n' \
CC ?= cc
RUSTC ?= rustc
RUSTFLAGS += --extern getopt=build/o/libgetopt.rlib \
--extern sysexits=build/o/libsysexits.rlib \
--extern strerror=build/o/libstrerror.rlib
--extern strerror=build/o/libstrerror.rlib \
--extern sysexits=build/o/libsysexits.rlib
CFLAGS += -I$(SYSEXITS)
# testing requires the absolute path to the bin directory set
@ -74,9 +77,13 @@ docs: docs/ build
"s/X\.X\.X/$$(git describe --tags --long | cut -d'-' -f1)/g")"; \
sed "s/$$original/$$title/g" <"$$file" >"build/$$file"; done
# include OS feature libraries for compilation
include include/$(OS).mk
.PHONY: rustlibs
rustlibs: build/o/libsysexits.rlib build/o/libgetopt.rlib \
build/o/libstrerror.rlib
rustlibs: build/o/libgetopt.rlib build/o/libstrerror.rlib \
build/o/libsysexits.rlib $(OSLIB)
build/o/libgetopt.rlib: build src/libgetopt.rs
$(RUSTC) $(RUSTFLAGS) --crate-type=lib --crate-name=getopt \

6
include/FreeBSD.mk Normal file
View File

@ -0,0 +1,6 @@
# Copyright (c) 2024 Emma Tebibyte <emma@tebibyte.media>
# SPDX-License-Identifier: FSFAP
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice and this
# notice are preserved. This file is offered as-is, without any warranty.

6
include/Linux.mk Normal file
View File

@ -0,0 +1,6 @@
# Copyright (c) 2024 Emma Tebibyte <emma@tebibyte.media>
# SPDX-License-Identifier: FSFAP
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice and this
# notice are preserved. This file is offered as-is, without any warranty.

13
include/OpenBSD.mk Normal file
View File

@ -0,0 +1,13 @@
# Copyright (c) 2024 Emma Tebibyte <emma@tebibyte.media>
# SPDX-License-Identifier: FSFAP
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice and this
# notice are preserved. This file is offered as-is, without any warranty.
OSLIB = build/o/libopenbsd.rlib
RUSTFLAGS += --extern openbsd=$(OSLIB)
$(OSLIB): src/libopenbsd.rs
$(RUSTC) $(RUSTFLAGS) --crate-type=lib --crate-name=openbsd \
-o $@ src/libopenbsd.rs

88
src/libopenbsd.rs Normal file
View File

@ -0,0 +1,88 @@
/*
* Copyright (c) 2024 Emma Tebibyte <emma@tebibyte.media>
* SPDX-License-Identifier: AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
use std::{
ffi::{ CString, c_int },
io::Error,
ptr::null,
};
mod openbsd {
use std::ffi::{ c_char, c_int };
extern "C" {
pub fn pledge(arg1: *const c_char, arg2: *const c_char) -> c_int;
pub fn unveil(arg1: *const c_char, arg2: *const c_char) -> c_int;
pub fn __errno() -> *mut c_int;
}
}
pub struct Promises(*const i8);
impl Promises {
pub fn new(promises: &str) -> Self {
let p = CString::new(promises).unwrap();
Promises(p.into_raw() as *const i8)
}
}
pub fn pledge(
promises: Option<Promises>, execpromises: Option<Promises>
) -> Result<(), Error> {
/* From pledge(2):
*
* Passing NULL to promises or execpromises specifies to not change
* the current value. */
let arg1 = promises.unwrap_or(Promises(null())).0;
let arg2 = execpromises.unwrap_or(Promises(null())).0;
unsafe {
match openbsd::pledge(arg1, arg2) {
-1 => Err(Error::from_raw_os_error(*openbsd::__errno())),
0 => Ok(()),
_ => panic!(), /* unreachable */
}
}
}
pub struct UnveilPerms(CString);
impl UnveilPerms {
pub fn new(permissions: Vec<char>) -> Self {
if permissions.is_empty() {
return UnveilPerms(CString::new("").unwrap());
}
UnveilPerms(
CString::new(permissions.iter().collect::<String>()).unwrap()
)
}
}
pub fn unveil(path: Option<&str>, permissions: Option<UnveilPerms>) -> c_int {
let path_c = path.map(CString::new).map(Result::unwrap);
let arg1 = path_c.map(|p| p.into_raw() as *const i8).unwrap_or(null());
let arg2 = permissions
.map(|p| p.0.into_raw() as *const i8)
.unwrap_or(null());
unsafe { openbsd::unveil(arg1, arg2) }
}