Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@v4

- name: Set up Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
uses: dtolnay/rust-toolchain@stable

- name: Build tests
run: cargo test --no-run
Expand All @@ -36,3 +34,9 @@ jobs:

- name: Run tests
run: cargo test -- --show-output

- name: Check without logging feature
run: cargo check --no-default-features

- name: Run clippy
run: cargo clippy --all-targets -- -D warnings
Comment on lines 37 to +45
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's ok, but could be nice also run tests without logging feature.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great idea! I've added a dedicated step to run tests without the logging feature. The CI now includes both cargo check --no-default-features and cargo test --no-default-features to ensure the crate works properly in both configurations. (3571bbf)

6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,8 @@ exclude = [

[dependencies]
libc = "^0.2"
log = "^0.4"
log = { version = "^0.4", optional = true }

[features]
default = ["logging"]
logging = ["log"]
13 changes: 8 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@ Set a user id and group id, using the names, to drop root privileges.
```rust
use drop_root::set_user_group;

fn main() {
// ...
set_user_group("nobody", "nogroup");
// ...
}
// ...
set_user_group("nobody", "nogroup");
// ...
```

## Features

- `logging` (default): Enable logging via the `log` crate
- To use without logging: `drop-root = { version = "1.0", default-features = false }`

## Testing

It's tested on Linux. Tests that require run as root are ignored by default, and executed
Expand Down
12 changes: 8 additions & 4 deletions src/group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ fn get_group_id_of(group_name: &str) -> Result<libc::gid_t, DropRootError> {
let group_record = unsafe { libc::getgrnam(CString::new(group_name)?.as_ptr()) };

if group_record.is_null() {
log::error!("Unable to getgrnam of the group {}", group_name);
#[cfg(feature = "logging")]
log::error!("Unable to getgrnam of the group {group_name}");
return Err(DropRootError::last_os_error());
}

Expand All @@ -19,15 +20,18 @@ pub fn set_group<T: AsRef<str>>(group_name: T) -> Result<(), DropRootError> {
let group_id = get_group_id_of(group_name)?;

if unsafe { libc::setgid(group_id) } != 0 {
log::error!("Unable to setgid of group {}", group_name);
#[cfg(feature = "logging")]
log::error!("Unable to setgid of group {group_name}");
return Err(DropRootError::last_os_error());
}

if unsafe { libc::setgroups(1, &group_id) } != 0 {
log::error!("Unable to setgid of group {}", group_name);
#[cfg(feature = "logging")]
log::error!("Unable to setgroups for group {group_name}");
return Err(DropRootError::last_os_error());
}

log::info!("Set process effective group to {}", group_name);
#[cfg(feature = "logging")]
log::info!("Set process effective group to {group_name}");
Ok(())
}
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#![cfg(unix)]
#[doc = include_str!("../README.md")]
#![doc = include_str!("../README.md")]

mod error;
mod user;
Expand Down
11 changes: 7 additions & 4 deletions src/user.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use std::ffi::CString;
use crate::DropRootError;

fn get_user_id_of(user_name: &str) -> Result<libc::gid_t, DropRootError> {
fn get_user_id_of(user_name: &str) -> Result<libc::uid_t, DropRootError> {
let passwd_record = unsafe { libc::getpwnam(CString::new(user_name)?.as_ptr()) };

if passwd_record.is_null() {
log::error!("Unable to getpwnam of the user {}", user_name);
#[cfg(feature = "logging")]
log::error!("Unable to getpwnam of the user {user_name}");
return Err(DropRootError::last_os_error());
}

Expand All @@ -19,10 +20,12 @@ pub fn set_user<T: AsRef<str>>(user_name: T) -> Result<(), DropRootError> {
let user_id = get_user_id_of(user_name)?;

if unsafe { libc::setuid(user_id) } != 0 {
log::error!("Unable to setuid of user {}", user_name);
#[cfg(feature = "logging")]
log::error!("Unable to setuid of user {user_name}");
return Err(DropRootError::last_os_error());
}

log::info!("Set process effective user to {}", user_name);
#[cfg(feature = "logging")]
log::info!("Set process effective user to {user_name}");
Ok(())
}