Skip to content

Commit 78a1b6c

Browse files
Merge branch 'main' into copilot/fix-119
2 parents b37ced8 + 89075c2 commit 78a1b6c

File tree

6 files changed

+375
-18
lines changed

6 files changed

+375
-18
lines changed

.github/copilot-instructions.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
This repository contains a Rust-based, security-focused sandboxing library OS. To maintain high code quality and consistency, please adhere to the following guidelines when contributing.
2+
3+
## Code Standards
4+
5+
### Required Before Each Commit
6+
- Run `cargo fmt` to format all Rust files using `rustfmt`.
7+
- This ensures consistent code style across the codebase.
8+
9+
### Development Workflow
10+
The recommended sequence during development is:
11+
1. **Format**: `cargo fmt`
12+
2. **Build**: `cargo build`
13+
3. **Lint**: `cargo clippy --all-targets --all-features`
14+
4. **Test**: `cargo nextest run`
15+
16+
- Full CI checks are defined in `.github/workflows/ci.yml`.
17+
18+
## Key Guidelines
19+
20+
1. Follow Rust best practices and idiomatic patterns.
21+
2. Preserve the existing code structure and organization.
22+
3. Minimize use of `unsafe` code. Every `unsafe` block **must** include a clear safety comment explaining why it's sound. Always prefer safe abstractions and code where possible.
23+
4. Write unit tests for new functionality, especially if it affects public interfaces.
24+
- Extremely simple changes do not require explicit unit tests.
25+
5. Document all public APIs and non-trivial implementation details.
26+
6. Avoid introducing new dependencies unless strictly necessary. If a dependency is added:
27+
- It must be justified.
28+
- Prefer `default-features = false` in `Cargo.toml`.
29+
7. Favor `no_std` compatibility wherever feasible.
30+
- Some crates in the workspace may use `std`, but this should be deliberate and justified.
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Customize GitHub Copilot coding agent development environment
2+
name: "Copilot Setup Steps"
3+
4+
# Automatically run the setup steps when they are changed to allow for easy validation, and
5+
# allow manual testing through the repository's "Actions" tab
6+
on:
7+
workflow_dispatch:
8+
push:
9+
paths:
10+
- .github/workflows/copilot-setup-steps.yml
11+
pull_request:
12+
paths:
13+
- .github/workflows/copilot-setup-steps.yml
14+
15+
jobs:
16+
# The job MUST be called `copilot-setup-steps` or it will not be picked up by Copilot.
17+
copilot-setup-steps:
18+
runs-on: ubuntu-latest
19+
20+
# Set the permissions to the lowest permissions possible needed for your steps.
21+
# Copilot will be given its own token for its operations.
22+
permissions:
23+
# Needed to clone the repository
24+
contents: read
25+
26+
# You can define any steps you want, and they will run before the agent starts.
27+
# If you do not check out your code, Copilot will do this for you.
28+
steps:
29+
- name: Checkout code
30+
uses: actions/checkout@v4
31+
- name: Set up Rust
32+
run: |
33+
rustup toolchain install $(awk -F'"' '/channel/{print $2}' rust-toolchain.toml) --profile minimal --no-self-update --component rustfmt,clippy
34+
- name: Set up Nextest
35+
run: |
36+
curl -LsSf https://get.nexte.st/latest/linux | tar zxf - -C ${CARGO_HOME:-~/.cargo}/bin
37+
- name: Set up tun device for Linux userland testing
38+
run: |
39+
sudo ./litebox_platform_linux_userland/scripts/tun-setup.sh

litebox/src/platform/mod.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,3 +539,33 @@ pub trait SystemInfoProvider {
539539
/// execution context and transfer control to the syscall handler.
540540
fn get_syscall_entry_point(&self) -> usize;
541541
}
542+
543+
/// A provider for thread-local storage.
544+
pub trait ThreadLocalStorageProvider {
545+
type ThreadLocalStorage;
546+
547+
/// Set a thread-local storage value for the current thread.
548+
///
549+
/// # Panics
550+
///
551+
/// Panics if TLS is set already.
552+
fn set_thread_local_storage(&self, value: Self::ThreadLocalStorage);
553+
554+
/// Invokes the provided callback function with the thread-local storage value for the current thread.
555+
///
556+
/// # Panics
557+
///
558+
/// Panics if TLS is not set yet.
559+
/// Panics if TLS is borrowed already (e.g., recursive call).
560+
fn with_thread_local_storage_mut<F, R>(&self, f: F) -> R
561+
where
562+
F: FnOnce(&mut Self::ThreadLocalStorage) -> R;
563+
564+
/// Release the thread-local storage value for the current thread
565+
///
566+
/// # Panics
567+
///
568+
/// Panics if TLS is not set yet.
569+
/// Panics if TLS is being used by [`Self::with_thread_local_storage_mut`].
570+
fn release_thread_local_storage(&self) -> Self::ThreadLocalStorage;
571+
}

litebox_common_linux/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ version = "0.1.0"
44
edition = "2024"
55

66
[dependencies]
7+
bitfield = "0.19.1"
78
bitflags = "2.9.0"
89
cfg-if = "1.0.0"
910
litebox = { path = "../litebox/", version = "0.1.0" }

litebox_common_linux/src/lib.rs

Lines changed: 95 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ use syscalls::Sysno;
1414

1515
pub mod errno;
1616

17+
extern crate alloc;
18+
1719
// TODO(jayb): Should errno::Errno be publicly re-exported?
1820

1921
bitflags::bitflags! {
@@ -681,13 +683,102 @@ pub unsafe fn wrfsbase(fs_base: usize) {
681683
}
682684
}
683685

686+
/// Reads the GS segment base address
687+
///
688+
/// ## Safety
689+
///
690+
/// If `CR4.FSGSBASE` is not set, this instruction will throw an `#UD`.
691+
#[cfg(target_arch = "x86_64")]
692+
pub unsafe fn rdgsbase() -> usize {
693+
let ret: usize;
694+
unsafe {
695+
core::arch::asm!(
696+
"rdgsbase {}",
697+
out(reg) ret,
698+
options(nostack, nomem)
699+
);
700+
}
701+
ret
702+
}
703+
704+
/// Writes the GS segment base address
705+
///
706+
/// ## Safety
707+
///
708+
/// If `CR4.FSGSBASE` is not set, this instruction will throw an `#UD`.
709+
///
710+
/// The caller must ensure that this write operation has no unsafe side
711+
/// effects, as the GS segment base address might be in use.
712+
#[cfg(target_arch = "x86_64")]
713+
pub unsafe fn wrgsbase(gs_base: usize) {
714+
unsafe {
715+
core::arch::asm!(
716+
"wrgsbase {}",
717+
in(reg) gs_base,
718+
options(nostack, nomem)
719+
);
720+
}
721+
}
722+
723+
/// Linux's `user_desc` struct used by the `set_thread_area` syscall.
684724
#[repr(C, packed)]
685725
#[derive(Debug, Clone)]
686726
pub struct UserDesc {
687-
pub entry_number: i32,
688-
pub base_addr: i32,
689-
pub limit: i32,
690-
pub flags: i32,
727+
pub entry_number: u32,
728+
pub base_addr: u32,
729+
pub limit: u32,
730+
pub flags: UserDescFlags,
731+
}
732+
733+
bitfield::bitfield! {
734+
/// Flags for the `user_desc` struct.
735+
#[derive(Clone, Copy)]
736+
pub struct UserDescFlags(u32);
737+
impl Debug;
738+
/// 1 if the segment is 32-bit
739+
pub seg_32bit, set_seg_32bit: 0;
740+
/// Contents of the segment
741+
pub contents, set_contents: 1, 2;
742+
/// Read-exec only
743+
pub read_exec_only, set_read_exec_only: 3;
744+
/// Limit in pages
745+
pub limit_in_pages, set_limit_in_pages: 4;
746+
/// Segment not present
747+
pub seg_not_present, set_seg_not_present: 5;
748+
/// Usable by userland
749+
pub useable, set_useable: 6;
750+
/// 1 if the segment is 64-bit (x86_64 only)
751+
pub lm, set_lm: 7;
752+
}
753+
754+
/// Struct for thread-local storage.
755+
pub struct ThreadLocalStorage<Platform: litebox::platform::RawPointerProvider> {
756+
/// Indicates whether the TLS is being borrowed.
757+
pub borrowed: bool,
758+
759+
#[cfg(target_arch = "x86")]
760+
pub self_ptr: *mut ThreadLocalStorage<Platform>,
761+
pub current_task: alloc::boxed::Box<Task>,
762+
763+
pub __phantom: core::marker::PhantomData<Platform>,
764+
}
765+
766+
impl<Platform: litebox::platform::RawPointerProvider> ThreadLocalStorage<Platform> {
767+
pub const fn new(task: alloc::boxed::Box<Task>) -> Self {
768+
Self {
769+
borrowed: false,
770+
#[cfg(target_arch = "x86")]
771+
self_ptr: core::ptr::null_mut(),
772+
current_task: task,
773+
__phantom: core::marker::PhantomData,
774+
}
775+
}
776+
}
777+
778+
/// A task associated with a thread in LiteBox.
779+
pub struct Task {
780+
/// Thread identifier
781+
pub tid: u32,
691782
}
692783

693784
#[repr(C)]

0 commit comments

Comments
 (0)