diff options
author | 2021-04-08 02:10:35 -0700 | |
---|---|---|
committer | 2021-04-08 02:10:35 -0700 | |
commit | 523296c4ecfad57ef26aabdde1446c788dbc668e (patch) | |
tree | 910cea9953116816b41c67f9550e807a2eb39cda | |
parent | e9fd841a6b89133f6afe46a8ce608af2f2e4b57e (diff) | |
download | rust-x86-523296c4ecfad57ef26aabdde1446c788dbc668e.tar.gz rust-x86-523296c4ecfad57ef26aabdde1446c788dbc668e.tar.zst rust-x86-523296c4ecfad57ef26aabdde1446c788dbc668e.zip |
Fix clippy warnings.
Diffstat (limited to '')
-rw-r--r-- | src/bits64/segmentation.rs | 30 | ||||
-rw-r--r-- | src/bits64/sgx.rs | 109 | ||||
-rw-r--r-- | src/bits64/syscall.rs | 28 | ||||
-rw-r--r-- | src/bits64/vmx.rs | 29 | ||||
-rw-r--r-- | src/controlregs.rs | 30 | ||||
-rw-r--r-- | src/dtables.rs | 18 | ||||
-rw-r--r-- | src/io.rs | 18 | ||||
-rw-r--r-- | src/msr.rs | 6 | ||||
-rw-r--r-- | src/random.rs | 41 | ||||
-rw-r--r-- | src/segmentation.rs | 31 | ||||
-rw-r--r-- | src/task.rs | 3 |
11 files changed, 296 insertions, 47 deletions
diff --git a/src/bits64/segmentation.rs b/src/bits64/segmentation.rs index 2c83f3c..c4420d8 100644 --- a/src/bits64/segmentation.rs +++ b/src/bits64/segmentation.rs @@ -26,10 +26,12 @@ impl Descriptor64 { pub(crate) fn apply_builder_settings(&mut self, builder: &DescriptorBuilder) { self.desc32.apply_builder_settings(builder); - if let Some((base, limit)) = builder - .base_limit { self.set_base_limit(base, limit) } - if let Some((selector, offset)) = builder - .selector_offset { self.set_selector_offset(selector, offset) } + if let Some((base, limit)) = builder.base_limit { + self.set_base_limit(base, limit) + } + if let Some((selector, offset)) = builder.selector_offset { + self.set_selector_offset(selector, offset) + } } /// Create a new segment, TSS or LDT descriptor @@ -129,10 +131,14 @@ impl BuildDescriptor<Descriptor64> for DescriptorBuilder { } /// Reload code segment register. +/// /// Note this is special since we can not directly move /// to %cs. Instead we push the new segment selector /// and return value on the stack and use lretq /// to reload cs and continue at 1:. +/// +/// # Safety +/// Can cause a GP-fault with a bad `sel` value. #[cfg(target_arch = "x86_64")] pub unsafe fn load_cs(sel: SegmentSelector) { llvm_asm!("pushq $0; \ @@ -143,6 +149,8 @@ pub unsafe fn load_cs(sel: SegmentSelector) { } /// Write GS Segment Base +/// +/// # Safety /// Needs FSGSBASE-Enable Bit (bit 16 of CR4) set. #[cfg(target_arch = "x86_64")] pub unsafe fn wrgsbase(base: u64) { @@ -150,6 +158,8 @@ pub unsafe fn wrgsbase(base: u64) { } /// Write FS Segment Base +/// +/// # Safety /// Needs FSGSBASE-Enable Bit (bit 16 of CR4) set. #[cfg(target_arch = "x86_64")] pub unsafe fn wrfsbase(base: u64) { @@ -157,6 +167,8 @@ pub unsafe fn wrfsbase(base: u64) { } /// Read GS Segment Base +/// +/// # Safety /// Needs FSGSBASE-Enable Bit (bit 16 of CR4) set. #[cfg(target_arch = "x86_64")] pub unsafe fn rdgsbase() -> u64 { @@ -166,6 +178,8 @@ pub unsafe fn rdgsbase() -> u64 { } /// Read FS Segment Base +/// +/// # Safety /// Needs FSGSBASE-Enable Bit (bit 16 of CR4) set. #[cfg(target_arch = "x86_64")] pub unsafe fn rdfsbase() -> u64 { @@ -175,6 +189,9 @@ pub unsafe fn rdfsbase() -> u64 { } /// "Dereferences" the fs register at offset 0. +/// +/// # Safety +/// fs needs to point to valid address. #[cfg(target_arch = "x86_64")] pub unsafe fn fs_deref() -> u64 { let fs: u64; @@ -183,6 +200,9 @@ pub unsafe fn fs_deref() -> u64 { } /// "Dereferences" the gs register at offset 0. +/// +/// # Safety +/// gs needs to point to valid address. #[cfg(target_arch = "x86_64")] pub unsafe fn gs_deref() -> u64 { let gs: u64; @@ -197,7 +217,7 @@ pub unsafe fn gs_deref() -> u64 { /// /// The SWAPGS instruction is available only in 64-bit mode. /// -/// # Unsafe +/// # Safety /// The SWAPGS instruction is a privileged instruction intended for use by system software. #[cfg(target_arch = "x86_64")] pub unsafe fn swapgs() { diff --git a/src/bits64/sgx.rs b/src/bits64/sgx.rs index aa302c1..3d018b3 100644 --- a/src/bits64/sgx.rs +++ b/src/bits64/sgx.rs @@ -45,6 +45,7 @@ unsafe fn encls4(rax: u64, rbx: u64, rcx: u64, rdx: u64) -> (u32, u64) { (eax, out_rbx) } +#[allow(clippy::upper_case_acronyms)] enum EnclsCommand { EADD = 0x01, EAUG = 0x0D, @@ -69,6 +70,9 @@ enum EnclsCommand { /// # Arguments /// * Address of a PAGEINFO. /// * Address of the destination EPC page. +/// +/// # Safety +/// Requires SGX support. pub unsafe fn encls_eadd(pageinfo: u64, epc_page: u64) { encls!(EnclsCommand::EADD as u64, pageinfo, epc_page); } @@ -78,6 +82,9 @@ pub unsafe fn encls_eadd(pageinfo: u64, epc_page: u64) { /// # Arguments /// * Address of a SECINFO /// * Address of the destination EPC page +/// +/// # Safety +/// Requires SGX support. pub unsafe fn encls_eaug(secinfo_address: u64, epc_page: u64) { encls!(EnclsCommand::EAUG as u64, secinfo_address, epc_page); } @@ -86,6 +93,9 @@ pub unsafe fn encls_eaug(secinfo_address: u64, epc_page: u64) { /// /// # Arguments /// * Effective address of the EPC page +/// +/// # Safety +/// Requires SGX support. pub unsafe fn encls_eblock(epc_page: u64) -> u32 { encls!(EnclsCommand::EBLOCK as u64, epc_page).0 } @@ -95,6 +105,9 @@ pub unsafe fn encls_eblock(epc_page: u64) -> u32 { /// # Arguments /// * Address of a PAGEINFO /// * Address of the destination SECS page +/// +/// # Safety +/// Requires SGX support. pub unsafe fn encls_create(pageinfo: u64, secs_page: u64) { encls!(EnclsCommand::ECREATE as u64, pageinfo, secs_page); } @@ -106,6 +119,9 @@ pub unsafe fn encls_create(pageinfo: u64, secs_page: u64) { /// /// # Arguments /// * Address of source memory in the EPC +/// +/// # Safety +/// Requires SGX support. pub unsafe fn encls_edbgrd(source_address: u64) -> u64 { encls!(EnclsCommand::EDBGRD as u64, source_address).1 } @@ -115,6 +131,9 @@ pub unsafe fn encls_edbgrd(source_address: u64) -> u64 { /// # Arguments /// * Data to be written to a debug enclave /// * Address of Target memory in the EPC +/// +/// # Safety +/// Requires SGX support. pub unsafe fn encls_edbgwr(data: u64, target_address: u64) { encls!(EnclsCommand::EDBGWR as u64, data, target_address); } @@ -124,6 +143,9 @@ pub unsafe fn encls_edbgwr(data: u64, target_address: u64) { /// # Arguments /// * Effective address of the SECS of the data chunk /// * Effective address of a 256-byte chunk in the EPC +/// +/// # Safety +/// Requires SGX support. pub unsafe fn encls_eextend(secs_chunk: u64, epc_chunk: u64) { encls!(EnclsCommand::EEXTEND as u64, secs_chunk, epc_chunk); } @@ -134,6 +156,9 @@ pub unsafe fn encls_eextend(secs_chunk: u64, epc_chunk: u64) { /// * Address of SIGSTRUCT /// * Address of SECS /// * Address of EINITTOKEN +/// +/// # Safety +/// Requires SGX support. pub unsafe fn encls_einit(sigstruct: u64, secs: u64, einittoken: u64) -> u32 { encls!(EnclsCommand::EINIT as u64, sigstruct, secs, einittoken).0 } @@ -144,6 +169,9 @@ pub unsafe fn encls_einit(sigstruct: u64, secs: u64, einittoken: u64) -> u32 { /// * Address of the PAGEINFO /// * Address of the EPC page /// * Address of the version-array slot +/// +/// # Safety +/// Requires SGX support. pub unsafe fn encls_eldb(pageinfo: u64, epc_page: u64, verion_array_slot: u64) -> u32 { encls!( EnclsCommand::ELDB as u64, @@ -160,6 +188,9 @@ pub unsafe fn encls_eldb(pageinfo: u64, epc_page: u64, verion_array_slot: u64) - /// * Address of the PAGEINFO /// * Address of the EPC page /// * Address of the version-array slot +/// +/// # Safety +/// Requires SGX support. pub unsafe fn encls_eldu(pageinfo: u64, epc_page: u64, verion_array_slot: u64) -> u32 { encls!( EnclsCommand::ELDU as u64, @@ -175,6 +206,9 @@ pub unsafe fn encls_eldu(pageinfo: u64, epc_page: u64, verion_array_slot: u64) - /// # Arguments /// * Address of a SECINFO /// * Address of the destination EPC page +/// +/// # Safety +/// Requires SGX support. pub unsafe fn encls_emodpr(secinfo: u64, epc_page: u64) -> u32 { encls!(EnclsCommand::EMODPR as u64, secinfo, epc_page).0 } @@ -184,6 +218,9 @@ pub unsafe fn encls_emodpr(secinfo: u64, epc_page: u64) -> u32 { /// # Arguments /// * Address of a SECINFO /// * Address of the destination EPC page +/// +/// # Safety +/// Requires SGX support. pub unsafe fn encls_emodt(secinfo: u64, epc_page: u64) -> u32 { encls!(EnclsCommand::EMODT as u64, secinfo, epc_page).0 } @@ -193,6 +230,9 @@ pub unsafe fn encls_emodt(secinfo: u64, epc_page: u64) -> u32 { /// # Arguments /// * PT_VA Constant /// * Effective address of the EPC page +/// +/// # Safety +/// Requires SGX support. pub unsafe fn encls_epa(pt_va: u64, epc_page: u64) { encls!(EnclsCommand::EPA as u64, pt_va, epc_page); } @@ -201,6 +241,9 @@ pub unsafe fn encls_epa(pt_va: u64, epc_page: u64) { /// /// # Arguments /// * Effective address of the EPC page +/// +/// # Safety +/// Requires SGX support. pub unsafe fn encls_eremove(epc_page: u64) { encls!(EnclsCommand::EREMOVE as u64, epc_page); } @@ -209,6 +252,9 @@ pub unsafe fn encls_eremove(epc_page: u64) { /// /// # Arguments /// * Pointer to the SECS of the EPC page. +/// +/// # Safety +/// Requires SGX support. pub unsafe fn encls_etrack(secs_pointer: u64) -> u32 { encls!(EnclsCommand::ETRACK as u64, secs_pointer).0 } @@ -218,6 +264,9 @@ pub unsafe fn encls_etrack(secs_pointer: u64) -> u32 { /// # Arguments /// * Address of the EPC page. /// * Address of a VA slot. +/// +/// # Safety +/// Requires SGX support. pub unsafe fn encls_ewb(pageinfo: u64, epc_page: u64, va_slot: u64) -> u32 { encls!(EnclsCommand::EWB as u64, pageinfo, epc_page, va_slot).0 } @@ -255,14 +304,14 @@ unsafe fn enclu4(rax: u64, rbx: u64, rcx: u64, rdx: u64) -> (u32, u64) { } enum EncluCommand { - EACCEPT = 0x05, - EACCEPTCOPY = 0x07, - EENTER = 0x02, - EEXIT = 0x04, - EGETKEY = 0x01, - EMODEPE = 0x06, - EREPORT = 0x00, - ERESUME = 0x03, + EAccept = 0x05, + EAcceptCopy = 0x07, + EEnter = 0x02, + EExit = 0x04, + EGetKey = 0x01, + EModePE = 0x06, + EReport = 0x00, + EResume = 0x03, } /// Accept Changes to an EPC Page. @@ -272,8 +321,11 @@ enum EncluCommand { /// * Address of the destination EPC page. /// /// Returns an error code. +/// +/// # Safety +/// Requires SGX support. pub unsafe fn enclu_eaccept(secinfo: u64, epc_page: u64) -> u32 { - enclu!(EncluCommand::EACCEPT as u64, secinfo, epc_page).0 + enclu!(EncluCommand::EAccept as u64, secinfo, epc_page).0 } /// Initialize a Pending Page. @@ -284,13 +336,16 @@ pub unsafe fn enclu_eaccept(secinfo: u64, epc_page: u64) -> u32 { /// * Address of the source EPC page. /// /// Returns an error code. +/// +/// # Safety +/// Requires SGX support. pub unsafe fn enclu_eacceptcopy( secinfo: u64, destination_epc_page: u64, source_epc_page: u64, ) -> u32 { enclu!( - EncluCommand::EACCEPTCOPY as u64, + EncluCommand::EAcceptCopy as u64, secinfo, destination_epc_page, source_epc_page @@ -303,11 +358,14 @@ pub unsafe fn enclu_eacceptcopy( /// # Arguments /// * Address of a TCS. /// * Address of AEP. -/// * Address of IP following EENTER. +/// * Address of IP following EEnter. /// -/// Returns content of RBX.CSSA and Address of IP following EENTER. +/// Returns content of RBX.CSSA and Address of IP following EEnter. +/// +/// # Safety +/// Requires SGX support. pub unsafe fn enclu_eenter(tcs: u64, aep: u64) -> (u32, u64) { - enclu!(EncluCommand::EENTER as u64, tcs, aep) + enclu!(EncluCommand::EEnter as u64, tcs, aep) } /// Exits an Enclave. @@ -315,8 +373,11 @@ pub unsafe fn enclu_eenter(tcs: u64, aep: u64) -> (u32, u64) { /// # Arguments /// * Target address outside the enclave /// * Address of the current AEP +/// +/// # Safety +/// Requires SGX support. pub unsafe fn enclu_eexit(ip: u64, aep: u64) { - enclu!(EncluCommand::EEXIT as u64, ip, aep); + enclu!(EncluCommand::EExit as u64, ip, aep); } /// Retrieves a Cryptographic Key. @@ -324,8 +385,11 @@ pub unsafe fn enclu_eexit(ip: u64, aep: u64) { /// # Arguments /// * Address to a KEYREQUEST /// * Address of the OUTPUTDATA +/// +/// # Safety +/// Requires SGX support. pub unsafe fn enclu_egetkey(keyrequest: u64, outputdata: u64) { - enclu!(EncluCommand::EGETKEY as u64, keyrequest, outputdata); + enclu!(EncluCommand::EGetKey as u64, keyrequest, outputdata); } /// Extend an EPC Page Permissions. @@ -333,8 +397,11 @@ pub unsafe fn enclu_egetkey(keyrequest: u64, outputdata: u64) { /// # Arguments /// * Address of a SECINFO /// * Address of the destination EPC page +/// +/// # Safety +/// Requires SGX support. pub unsafe fn enclu_emodepe(secinfo: u64, epc_page: u64) { - enclu!(EncluCommand::EMODEPE as u64, secinfo, epc_page); + enclu!(EncluCommand::EModePE as u64, secinfo, epc_page); } /// Create a Cryptographic Report of the Enclave. @@ -343,9 +410,12 @@ pub unsafe fn enclu_emodepe(secinfo: u64, epc_page: u64) { /// * Address of TARGETINFO /// * Address of REPORTDATA /// * Address where the REPORT is written to in an OUTPUTDATA +/// +/// # Safety +/// Requires SGX support. pub unsafe fn enclu_ereport(targetinfo: u64, reportdata: u64, outputdata: u64) { enclu!( - EncluCommand::EREPORT as u64, + EncluCommand::EReport as u64, targetinfo, reportdata, outputdata @@ -357,6 +427,9 @@ pub unsafe fn enclu_ereport(targetinfo: u64, reportdata: u64, outputdata: u64) { /// # Arguments /// * Address of a TCS. /// * Address of AEP. +/// +/// # Safety +/// Requires SGX support. pub unsafe fn enclu_eresume(tcs: u64, aep: u64) { - enclu!(EncluCommand::ERESUME as u64, tcs, aep); + enclu!(EncluCommand::EResume as u64, tcs, aep); } diff --git a/src/bits64/syscall.rs b/src/bits64/syscall.rs index b370282..63c7c30 100644 --- a/src/bits64/syscall.rs +++ b/src/bits64/syscall.rs @@ -88,6 +88,10 @@ macro_rules! syscall { }; } +/// Invoke a syscall. +/// +/// # Safety +/// Throws `#UD` if IA32_EFER.SCE = 0. #[cfg(target_arch = "x86_64")] #[inline(always)] #[allow(unused_mut)] @@ -97,6 +101,10 @@ pub unsafe fn syscall0(arg0: u64) -> u64 { ret } +/// Invoke a syscall. +/// +/// # Safety +/// Throws `#UD` if IA32_EFER.SCE = 0. #[cfg(target_arch = "x86_64")] #[inline(always)] #[allow(unused_mut)] @@ -107,6 +115,10 @@ pub unsafe fn syscall1(arg0: u64, arg1: u64) -> u64 { ret } +/// Invoke a syscall. +/// +/// # Safety +/// Throws `#UD` if IA32_EFER.SCE = 0. #[cfg(target_arch = "x86_64")] #[inline(always)] #[allow(unused_mut)] @@ -117,6 +129,10 @@ pub unsafe fn syscall2(arg0: u64, arg1: u64, arg2: u64) -> u64 { ret } +/// Invoke a syscall. +/// +/// # Safety +/// Throws `#UD` if IA32_EFER.SCE = 0. #[cfg(target_arch = "x86_64")] #[inline(always)] #[allow(unused_mut)] @@ -127,6 +143,10 @@ pub unsafe fn syscall3(arg0: u64, arg1: u64, arg2: u64, arg3: u64) -> u64 { ret } +/// Invoke a syscall. +/// +/// # Safety +/// Throws `#UD` if IA32_EFER.SCE = 0. #[cfg(target_arch = "x86_64")] #[inline(always)] #[allow(unused_mut)] @@ -138,6 +158,10 @@ pub unsafe fn syscall4(arg0: u64, arg1: u64, arg2: u64, arg3: u64, arg4: u64) -> ret } +/// Invoke a syscall. +/// +/// # Safety +/// Throws `#UD` if IA32_EFER.SCE = 0. #[cfg(target_arch = "x86_64")] #[inline(always)] #[allow(unused_mut)] @@ -150,6 +174,10 @@ pub unsafe fn syscall5(arg0: u64, arg1: u64, arg2: u64, arg3: u64, arg4: u64, ar ret } +/// Invoke a syscall. +/// +/// # Safety +/// Throws `#UD` if IA32_EFER.SCE = 0. #[cfg(target_arch = "x86_64")] #[inline(always)] #[allow(unused_mut)] diff --git a/src/bits64/vmx.rs b/src/bits64/vmx.rs index f64ece7..5535d36 100644 --- a/src/bits64/vmx.rs +++ b/src/bits64/vmx.rs @@ -11,7 +11,7 @@ use crate::vmx::{Result, VmFail}; // see https://github.com/gz/rust-x86/pull/50. #[inline(always)] fn vmx_capture_status() -> Result<()> { - let flags = unsafe { rflags::read() }; + let flags = rflags::read(); if flags.contains(RFlags::FLAGS_ZF) { Err(VmFail::VmFailValid) @@ -26,12 +26,18 @@ fn vmx_capture_status() -> Result<()> { /// /// `addr` specifies a 4KB-aligned physical address of VMXON region initialized /// in accordance with Intel SDM, Volume 3C, Section 24.11.5. +/// +/// # Safety +/// Needs CPL 0. pub unsafe fn vmxon(addr: u64) -> Result<()> { llvm_asm!("vmxon $0" : /* no outputs */ : "m"(addr)); vmx_capture_status() } /// Disable VMX operation. +/// +/// # Safety +/// Needs CPL 0. pub unsafe fn vmxoff() -> Result<()> { llvm_asm!("vmxoff"); vmx_capture_status() @@ -41,6 +47,9 @@ pub unsafe fn vmxoff() -> Result<()> { /// /// Ensures that VMCS data maintained on the processor is copied to the VMCS region /// located at 4KB-aligned physical address `addr` and initializes some parts of it. +/// +/// # Safety +/// Needs CPL 0. pub unsafe fn vmclear(addr: u64) -> Result<()> { llvm_asm!("vmclear $0" : /* no outputs */ : "m"(addr)); vmx_capture_status() @@ -49,12 +58,18 @@ pub unsafe fn vmclear(addr: u64) -> Result<()> { /// Load current VMCS pointer. /// /// Marks the current-VMCS pointer valid and loads it with the physical address `addr`. +/// +/// # Safety +/// Needs CPL 0. pub unsafe fn vmptrld(addr: u64) -> Result<()> { llvm_asm!("vmptrld $0" : /* no outputs */ : "m"(addr)); vmx_capture_status() } /// Return current VMCS pointer. +/// +/// # Safety +/// Needs CPL 0. pub unsafe fn vmptrst() -> Result<u64> { let value: u64 = 0; llvm_asm!("vmptrst ($0)" : /* no outputs */ : "r"(&value) : "memory"); @@ -62,6 +77,9 @@ pub unsafe fn vmptrst() -> Result<u64> { } /// Read a specified field from a VMCS. +/// +/// # Safety +/// Needs CPL 0. pub unsafe fn vmread(field: u32) -> Result<u64> { let field: u64 = field.into(); let value: u64; @@ -70,6 +88,9 @@ pub unsafe fn vmread(field: u32) -> Result<u64> { } /// Write to a specified field in a VMCS. +/// +/// # Safety +/// Needs CPL 0. pub unsafe fn vmwrite(field: u32, value: u64) -> Result<()> { let field: u64 = field.into(); llvm_asm!("vmwrite $1, $0" : /* no outputs */ : "r"(field), "r"(value)); @@ -77,6 +98,9 @@ pub unsafe fn vmwrite(field: u32, value: u64) -> Result<()> { } /// Launch virtual machine. +/// +/// # Safety +/// Needs CPL 0. #[inline(always)] pub unsafe fn vmlaunch() -> Result<()> { llvm_asm!("vmlaunch"); @@ -84,6 +108,9 @@ pub unsafe fn vmlaunch() -> Result<()> { } /// Resume virtual machine. +/// +/// # Safety +/// Needs CPL 0. #[inline(always)] pub unsafe fn vmresume() -> Result<()> { llvm_asm!("vmresume"); diff --git a/src/controlregs.rs b/src/controlregs.rs index 00117ea..c9457f7 100644 --- a/src/controlregs.rs +++ b/src/controlregs.rs @@ -88,6 +88,9 @@ bitflags! { } /// Read cr0 +/// +/// # Safety +/// Needs CPL 0. pub unsafe fn cr0() -> Cr0 { let ret: usize; llvm_asm!("mov %cr0, $0" : "=r" (ret)); @@ -95,11 +98,17 @@ pub unsafe fn cr0() -> Cr0 { } /// Write cr0. +/// +/// # Safety +/// Needs CPL 0. pub unsafe fn cr0_write(val: Cr0) { llvm_asm!("mov $0, %cr0" :: "r" (val.bits) : "memory"); } /// Contains page-fault linear address. +/// +/// # Safety +/// Needs CPL 0. pub unsafe fn cr2() -> usize { let ret: usize; llvm_asm!("mov %cr2, $0" : "=r" (ret)); @@ -107,11 +116,17 @@ pub unsafe fn cr2() -> usize { } /// Write cr2, for instance to reset cr2 +/// +/// # Safety +/// Needs CPL 0. pub unsafe fn cr2_write(val: u64) { llvm_asm!("mov $0, %cr2" :: "r" (val) : "memory"); } /// Contains page-table root pointer. +/// +/// # Safety +/// Needs CPL 0. pub unsafe fn cr3() -> u64 { let ret: u64; llvm_asm!("mov %cr3, $0" : "=r" (ret)); @@ -119,11 +134,17 @@ pub unsafe fn cr3() -> u64 { } /// Switch page-table PML4 pointer. +/// +/// # Safety +/// Needs CPL 0. pub unsafe fn cr3_write(val: u64) { llvm_asm!("mov $0, %cr3" :: "r" (val) : "memory"); } /// Contains various flags to control operations in protected mode. +/// +/// # Safety +/// Needs CPL 0. pub unsafe fn cr4() -> Cr4 { let ret: usize; llvm_asm!("mov %cr4, $0" : "=r" (ret)); @@ -141,18 +162,27 @@ pub unsafe fn cr4() -> Cr4 { /// cr4_write(cr4); /// } /// ``` +/// +/// # Safety +/// Needs CPL 0. pub unsafe fn cr4_write(val: Cr4) { llvm_asm!("mov $0, %cr4" :: "r" (val.bits) : "memory"); } /// Read Extended Control Register XCR0. /// Only supported if CR4_ENABLE_OS_XSAVE is set. +/// +/// # Safety +/// Needs CPL 0. pub unsafe fn xcr0() -> Xcr0 { Xcr0::from_bits_truncate(_xgetbv(0)) } /// Write to Extended Control Register XCR0. /// Only supported if CR4_ENABLE_OS_XSAVE is set. +/// +/// # Safety +/// Needs CPL 0. pub unsafe fn xcr0_write(val: Xcr0) { _xsetbv(0, val.bits); } diff --git a/src/dtables.rs b/src/dtables.rs index 780d6d4..d53113f 100644 --- a/src/dtables.rs +++ b/src/dtables.rs @@ -55,11 +55,17 @@ impl<T> fmt::Debug for DescriptorTablePointer<T> { } /// Load the GDTR register with the specified base and limit. +/// +/// # Safety +/// Needs CPL 0. pub unsafe fn lgdt<T>(gdt: &DescriptorTablePointer<T>) { llvm_asm!("lgdt ($0)" :: "r" (gdt) : "memory"); } /// Retrieve base and limit from the GDTR register. +/// +/// # Safety +/// Needs CPL 0. pub unsafe fn sgdt<T>(idt: &mut DescriptorTablePointer<T>) { llvm_asm!("sgdt ($0)" : "=r" (idt as *mut DescriptorTablePointer<T>) :: "memory"); } @@ -71,6 +77,9 @@ pub unsafe fn sgdt<T>(idt: &mut DescriptorTablePointer<T>) { /// the processor uses the segment selector to locate /// the segment descriptor for the LDT in the global /// descriptor table (GDT). +/// +/// # Safety +/// Needs CPL 0. pub unsafe fn load_ldtr(selector: SegmentSelector) { llvm_asm!("lldt $0" :: "r" (selector.bits()) : "memory"); } @@ -79,6 +88,9 @@ pub unsafe fn load_ldtr(selector: SegmentSelector) { /// /// The returned segment selector points to the segment descriptor /// (located in the GDT) for the current LDT. +/// +/// # Safety +/// Needs CPL 0. pub unsafe fn ldtr() -> SegmentSelector { let selector: u16; llvm_asm!("sldt $0" : "=r"(selector)); @@ -86,11 +98,17 @@ pub unsafe fn ldtr() -> SegmentSelector { } /// Load the IDTR register with the specified base and limit. +/// +/// # Safety +/// Needs CPL 0. pub unsafe fn lidt<T>(idt: &DescriptorTablePointer<T>) { llvm_asm!("lidt ($0)" :: "r" (idt) : "memory"); } /// Retrieve base and limit from the IDTR register. +/// +/// # Safety +/// Needs CPL 0. pub unsafe fn sidt<T>(idt: &mut DescriptorTablePointer<T>) { llvm_asm!("sidt ($0)" : "=r" (idt as *mut DescriptorTablePointer<T>) :: "memory"); } @@ -1,12 +1,18 @@ //! I/O port functionality. /// Write 8 bits to port +/// +/// # Safety +/// Needs IO privileges. #[inline] pub unsafe fn outb(port: u16, val: u8) { llvm_asm!("outb %al, %dx" :: "{dx}"(port), "{al}"(val)); } /// Read 8 bits from port +/// +/// # Safety +/// Needs IO privileges. #[inline] pub unsafe fn inb(port: u16) -> u8 { let ret: u8; @@ -15,12 +21,18 @@ pub unsafe fn inb(port: u16) -> u8 { } /// Write 16 bits to port +/// +/// # Safety +/// Needs IO privileges. #[inline] pub unsafe fn outw(port: u16, val: u16) { llvm_asm!("outw %ax, %dx" :: "{dx}"(port), "{al}"(val)); } /// Read 16 bits from port +/// +/// # Safety +/// Needs IO privileges. #[inline] pub unsafe fn inw(port: u16) -> u16 { let ret: u16; @@ -29,12 +41,18 @@ pub unsafe fn inw(port: u16) -> u16 { } /// Write 32 bits to port +/// +/// # Safety +/// Needs IO privileges. #[inline] pub unsafe fn outl(port: u16, val: u32) { llvm_asm!("outl %eax, %dx" :: "{dx}"(port), "{al}"(val)); } /// Read 32 bits from port +/// +/// # Safety +/// Needs IO privileges. #[inline] pub unsafe fn inl(port: u16) -> u32 { let ret: u32; @@ -1,6 +1,9 @@ //! MSR value list and function to read and write them. /// Write 64 bits to msr register. +/// +/// # Safety +/// Needs CPL 0. pub unsafe fn wrmsr(msr: u32, value: u64) { let low = value as u32; let high = (value >> 32) as u32; @@ -8,6 +11,9 @@ pub unsafe fn wrmsr(msr: u32, value: u64) { } /// Read 64 bits msr register. +/// +/// # Safety +/// Needs CPL 0. #[allow(unused_mut)] pub unsafe fn rdmsr(msr: u32) -> u64 { let (high, low): (u32, u32); diff --git a/src/random.rs b/src/random.rs index 4388352..a53d724 100644 --- a/src/random.rs +++ b/src/random.rs @@ -6,8 +6,8 @@ //! //! See also: https://software.intel.com/en-us/blogs/2012/11/17/the-difference-between-rdrand-and-rdseed //! -//! * RDRAND: Cryptographically secure pseudorandom number generator NIST:SP 800-90A -//! * RDSEED: Non-deterministic random bit generator NIST: SP 800-90B & C (drafts) +//! * RDRAND: Cryptographically secure pseudorandom number generator NIST:SP 800-90A +//! * RDSEED: Non-deterministic random bit generator NIST: SP 800-90B & C (drafts) #[cfg(target_arch = "x86_64")] use core::arch::x86_64::{ _rdrand16_step, _rdrand32_step, _rdrand64_step, _rdseed16_step, _rdseed32_step, _rdseed64_step, @@ -18,7 +18,7 @@ use core::arch::x86::{_rdrand16_step, _rdrand32_step, _rdseed16_step, _rdseed32_ /// Generates a 16-bit random value and stores it in `e`. /// -/// # Unsafe +/// # Safety /// Will crash if RDRAND instructions are not supported. #[inline(always)] pub unsafe fn rdrand16(e: &mut u16) -> bool { @@ -27,7 +27,7 @@ pub unsafe fn rdrand16(e: &mut u16) -> bool { /// Generates a 32-bit random value and stores it in `e`. /// -/// # Unsafe +/// # Safety /// Will crash if RDRAND instructions are not supported. #[inline(always)] pub unsafe fn rdrand32(e: &mut u32) -> bool { @@ -36,7 +36,7 @@ pub unsafe fn rdrand32(e: &mut u32) -> bool { /// Generates a 64-bit random value and stores it in `e`. /// -/// # Unsafe +/// # Safety /// Will crash if RDRAND instructions are not supported. #[cfg(target_arch = "x86_64")] #[inline(always)] @@ -48,7 +48,7 @@ pub unsafe fn rdrand64(e: &mut u64) -> bool { pub trait RdRand { /// Fills `self` with random bits. Returns true on success or false otherwise /// - /// # Unsafe + /// # Safety /// RDRAND is not supported on all architctures, so using this may crash you. unsafe fn fill_random(&mut self) -> bool; } @@ -56,7 +56,7 @@ pub trait RdRand { impl RdRand for u8 { /// Fills the 16-bit value with a random bit string /// - /// # Unsafe + /// # Safety /// Will crash if RDSEED instructions are not supported. unsafe fn fill_random(&mut self) -> bool { let mut r: u16 = 0; @@ -69,7 +69,7 @@ impl RdRand for u8 { impl RdRand for u16 { /// Fills the 16-bit value with a random bit string /// - /// # Unsafe + /// # Safety /// Will crash if RDRAND instructions are not supported. unsafe fn fill_random(&mut self) -> bool { rdrand16(self) @@ -79,7 +79,7 @@ impl RdRand for u16 { impl RdRand for u32 { /// Fills the 32-bit value with a random bit string /// - /// # Unsafe + /// # Safety /// Will crash if RDRAND instructions are not supported. unsafe fn fill_random(&mut self) -> bool { rdrand32(self) @@ -90,7 +90,7 @@ impl RdRand for u32 { impl RdRand for u64 { /// Fills the 64-bit value with a random bit string /// - /// # Unsafe + /// # Safety /// Will crash if RDRAND instructions are not supported. unsafe fn fill_random(&mut self) -> bool { rdrand64(self) @@ -101,6 +101,8 @@ impl RdRand for u64 { /// /// Returns true if the iterator was successfully filled with /// random values, otherwise false. +/// # Safety +/// Will crash if RDRAND instructions are not supported. pub unsafe fn rdrand_slice<T: RdRand>(buffer: &mut [T]) -> bool { let mut worked = true; for element in buffer { @@ -111,7 +113,7 @@ pub unsafe fn rdrand_slice<T: RdRand>(buffer: &mut [T]) -> bool { /// Generates a 16-bit random value and stores it in `e`. /// -/// # Unsafe +/// # Safety /// Will crash if RDSEED instructions are not supported. #[inline(always)] pub unsafe fn rdseed16(e: &mut u16) -> bool { @@ -120,7 +122,7 @@ pub unsafe fn rdseed16(e: &mut u16) -> bool { /// Generates a 32-bit random value and stores it in `e`. /// -/// # Unsafe +/// # Safety /// Will crash if RDSEED instructions are not supported. #[inline(always)] pub unsafe fn rdseed32(e: &mut u32) -> bool { @@ -129,7 +131,7 @@ pub unsafe fn rdseed32(e: &mut u32) -> bool { /// Generates a 64-bit random value and stores it in `e`. /// -/// # Unsafe +/// # Safety /// Will crash if RDSEED instructions are not supported. #[cfg(target_arch = "x86_64")] #[inline(always)] @@ -141,7 +143,7 @@ pub unsafe fn rdseed64(e: &mut u64) -> bool { pub trait RdSeed { /// Fills `self` with random bits. Returns true on success or false otherwise /// - /// # Unsafe + /// # Safety /// RDSEED is not supported on all architctures, so using this may crash you. unsafe fn fill_random(&mut self) -> bool; } @@ -149,7 +151,7 @@ pub trait RdSeed { impl RdSeed for u8 { /// Fills the 16-bit value with a random bit string /// - /// # Unsafe + /// # Safety /// Will crash if RDSEED instructions are not supported. unsafe fn fill_random(&mut self) -> bool { let mut r: u16 = 0; @@ -162,7 +164,7 @@ impl RdSeed for u8 { impl RdSeed for u16 { /// Fills the 16-bit value with a random bit string /// - /// # Unsafe + /// # Safety /// Will crash if RDSEED instructions are not supported. unsafe fn fill_random(&mut self) -> bool { rdseed16(self) @@ -172,7 +174,7 @@ impl RdSeed for u16 { impl RdSeed for u32 { /// Fills the 32-bit value with a random bit string /// - /// # Unsafe + /// # Safety /// Will crash if RDSEED instructions are not supported. unsafe fn fill_random(&mut self) -> bool { rdseed32(self) @@ -183,7 +185,7 @@ impl RdSeed for u32 { impl RdSeed for u64 { /// Fills the 64-bit value with a random bit string /// - /// # Unsafe + /// # Safety /// Will crash if RDSEED instructions are not supported. unsafe fn fill_random(&mut self) -> bool { rdseed64(self) @@ -194,6 +196,9 @@ impl RdSeed for u64 { /// /// Returns true if the iterator was successfully filled with /// random values, otherwise false. +/// +/// # Safety +/// Will crash if RDSEED instructions are not supported. pub unsafe fn rdseed_slice<T: RdSeed>(buffer: &mut [T]) -> bool { let mut worked = true; for element in buffer { diff --git a/src/segmentation.rs b/src/segmentation.rs index 5ead88c..3ff748a 100644 --- a/src/segmentation.rs +++ b/src/segmentation.rs @@ -87,6 +87,7 @@ impl fmt::Display for SegmentSelector { /// System-Segment and Gate-Descriptor Types 64-bit mode /// See also Intel 3a, Table 3-2 System Segment and Gate-Descriptor Types. +#[allow(clippy::upper_case_acronyms)] #[repr(u8)] #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum SystemDescriptorTypes64 { @@ -110,6 +111,7 @@ pub enum SystemDescriptorTypes64 { /// System-Segment and Gate-Descriptor Types 32-bit mode. /// See also Intel 3a, Table 3-2 System Segment and Gate-Descriptor Types. +#[allow(clippy::upper_case_acronyms)] #[repr(u8)] #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum SystemDescriptorTypes32 { @@ -435,11 +437,15 @@ impl Descriptor { } pub(crate) fn apply_builder_settings(&mut self, builder: &DescriptorBuilder) { - if let Some(ring) = builder.dpl { self.set_dpl(ring) } - if let Some((base, limit)) = builder - .base_limit { self.set_base_limit(base as u32, limit as u32) } - if let Some((selector, offset)) = builder - .selector_offset { self.set_selector_offset(selector, offset as u32) } + if let Some(ring) = builder.dpl { + self.set_dpl(ring) + } + if let Some((base, limit)) = builder.base_limit { + self.set_base_limit(base as u32, limit as u32) + } + if let Some((selector, offset)) = builder.selector_offset { + self.set_selector_offset(selector, offset as u32) + } if builder.present { self.set_p(); @@ -551,26 +557,41 @@ impl Descriptor { } /// Reload stack segment register. +/// +/// # Safety +/// Needs CPL 0. pub unsafe fn load_ss(sel: SegmentSelector) { llvm_asm!("movw $0, %ss " :: "r" (sel.bits()) : "memory"); } /// Reload data segment register. +/// +/// # Safety +/// Needs CPL 0. pub unsafe fn load_ds(sel: SegmentSelector) { llvm_asm!("movw $0, %ds " :: "r" (sel.bits()) : "memory"); } /// Reload es segment register. +/// +/// # Safety +/// Needs CPL 0. pub unsafe fn load_es(sel: SegmentSelector) { llvm_asm!("movw $0, %es " :: "r" (sel.bits()) : "memory"); } /// Reload fs segment register. +/// +/// # Safety +/// Needs CPL 0. pub unsafe fn load_fs(sel: SegmentSelector) { llvm_asm!("movw $0, %fs " :: "r" (sel.bits()) : "memory"); } /// Reload gs segment register. +/// +/// # Safety +/// Needs CPL 0. pub unsafe fn load_gs(sel: SegmentSelector) { llvm_asm!("movw $0, %gs " :: "r" (sel.bits()) : "memory"); } diff --git a/src/task.rs b/src/task.rs index 40fdc2c..a7b3423 100644 --- a/src/task.rs +++ b/src/task.rs @@ -11,6 +11,9 @@ pub fn tr() -> segmentation::SegmentSelector { } /// Loads the task register. +/// +/// # Safety +/// Needs CPL 0. pub unsafe fn load_tr(sel: segmentation::SegmentSelector) { llvm_asm!("ltr $0" :: "r" (sel.bits())); } |