From b7410951809f5eee6c2cbd73c44dab41e8f71def Mon Sep 17 00:00:00 2001 From: SuchAFuriousDeath <48620541+SuchAFuriousDeath@users.noreply.github.com> Date: Fri, 5 Apr 2024 23:05:05 +0200 Subject: [PATCH] Implements sys_dynlib_get_info (#672) --- src/elf/src/info.rs | 21 +++- src/elf/src/lib.rs | 4 + src/kernel/src/budget/mod.rs | 10 ++ src/kernel/src/dev/dmem.rs | 13 +-- src/kernel/src/dmem/blockpool.rs | 6 + src/kernel/src/dmem/mod.rs | 32 +++--- src/kernel/src/fs/file.rs | 2 +- src/kernel/src/fs/ioctl.rs | 2 +- src/kernel/src/fs/mod.rs | 2 +- src/kernel/src/main.rs | 4 +- src/kernel/src/process/mod.rs | 2 +- src/kernel/src/regmgr/mod.rs | 2 +- src/kernel/src/rtld/mem.rs | 12 +- src/kernel/src/rtld/mod.rs | 181 ++++++++++++++++++++++++------ src/kernel/src/rtld/module.rs | 34 ++++-- src/kernel/src/ucred/auth.rs | 23 ++-- src/kernel/src/ucred/mod.rs | 45 ++++++-- src/kernel/src/ucred/privilege.rs | 3 +- src/kernel/src/vm/mod.rs | 8 +- 19 files changed, 303 insertions(+), 103 deletions(-) diff --git a/src/elf/src/info.rs b/src/elf/src/info.rs index b677bc7e9..8cb0a2074 100644 --- a/src/elf/src/info.rs +++ b/src/elf/src/info.rs @@ -279,7 +279,7 @@ impl FileInfo { let id = LE::read_u16(&data[6..]); // Lookup name. - let name = match self.read_str(name.try_into().unwrap()) { + let name = match self.read_str(name as usize) { Ok(v) => v.to_owned(), Err(e) => return Err(ReadModuleError::InvalidNameOffset(name, e)), }; @@ -301,6 +301,15 @@ impl FileInfo { Ok(LibraryInfo::new(id, name, LibraryFlags::empty())) } + pub fn read_fingerprint(&self, offset: usize) -> [u8; 20] { + let offset = offset + self.dynoff; + + let mut fingerprint = [0u8; 20]; + fingerprint.copy_from_slice(&self.data[offset..(offset + 20)]); + + fingerprint + } + pub fn read_str(&self, offset: usize) -> Result<&str, StringTableError> { // Get raw string. let tab = &self.data[self.strtab..(self.strtab + self.strsz)]; @@ -316,7 +325,9 @@ impl FileInfo { }; // Get Rust string. - std::str::from_utf8(raw).map_err(|_| StringTableError::NotUtf8) + let string = std::str::from_utf8(raw)?; + + Ok(string) } } @@ -419,3 +430,9 @@ pub enum StringTableError { #[error("the offset is not a UTF-8 string")] NotUtf8, } + +impl From for StringTableError { + fn from(_: std::str::Utf8Error) -> Self { + Self::NotUtf8 + } +} diff --git a/src/elf/src/lib.rs b/src/elf/src/lib.rs index 604ad296d..29487e001 100644 --- a/src/elf/src/lib.rs +++ b/src/elf/src/lib.rs @@ -336,6 +336,10 @@ impl Elf { self.programs.as_slice() } + pub fn relro(&self) -> Option { + self.relro + } + pub fn dynamic(&self) -> Option { self.dynamic } diff --git a/src/kernel/src/budget/mod.rs b/src/kernel/src/budget/mod.rs index 924755333..449f17fb4 100644 --- a/src/kernel/src/budget/mod.rs +++ b/src/kernel/src/budget/mod.rs @@ -90,3 +90,13 @@ pub enum ProcType { MiniApp, System, // TODO: Verify this. } + +impl Into for ProcType { + fn into(self) -> u32 { + match self { + ProcType::BigApp => 0, + ProcType::MiniApp => 1, + ProcType::System => 2, + } + } +} diff --git a/src/kernel/src/dev/dmem.rs b/src/kernel/src/dev/dmem.rs index 95caf5dd0..6270b5398 100644 --- a/src/kernel/src/dev/dmem.rs +++ b/src/kernel/src/dev/dmem.rs @@ -43,18 +43,10 @@ impl TryInto for i32 { } } -impl TryInto for usize { - type Error = SysErr; - - fn try_into(self) -> Result { - (self as i32).try_into() - } -} - impl DeviceDriver for Dmem { fn ioctl( &self, - dev: &Arc, + _: &Arc, cmd: IoCmd, td: Option<&VThread>, ) -> Result<(), Box> { @@ -76,7 +68,8 @@ impl DeviceDriver for Dmem { } match cmd { - IoCmd::DMEM10(size) => *size = self.total_size, + // TODO: properly implement this + IoCmd::DMEMTOTAL(size) => *size = self.total_size, IoCmd::DMEMGETPRT(_prt) => todo!(), IoCmd::DMEMGETAVAIL(_avail) => todo!(), IoCmd::DMEMALLOC(_alloc) => todo!(), diff --git a/src/kernel/src/dmem/blockpool.rs b/src/kernel/src/dmem/blockpool.rs index 9de601fe1..53b8f5bfe 100644 --- a/src/kernel/src/dmem/blockpool.rs +++ b/src/kernel/src/dmem/blockpool.rs @@ -6,6 +6,12 @@ use std::sync::Arc; #[derive(Debug)] pub struct BlockPool {} +impl BlockPool { + pub fn new() -> Arc { + Arc::new(Self {}) + } +} + impl FileBackend for BlockPool { #[allow(unused_variables)] // TODO: remove when implementing fn ioctl( diff --git a/src/kernel/src/dmem/mod.rs b/src/kernel/src/dmem/mod.rs index 5ddd3e815..b26afc621 100644 --- a/src/kernel/src/dmem/mod.rs +++ b/src/kernel/src/dmem/mod.rs @@ -1,14 +1,15 @@ -use thiserror::Error; - use crate::dev::{Dmem, DmemContainer}; use crate::errno::EINVAL; -use crate::fs::{make_dev, CharacterDevice, DriverFlags, Fs, MakeDevError, MakeDevFlags, Mode}; +use crate::fs::{ + make_dev, CharacterDevice, DriverFlags, Fs, MakeDevError, MakeDevFlags, Mode, VFile, VFileType, +}; use crate::info; -use crate::process::{VProc, VThread}; +use crate::process::VThread; use crate::syscalls::{SysErr, SysIn, SysOut, Syscalls}; -use crate::ucred::{Gid, Privilege, Uid}; +use crate::ucred::{Gid, Uid}; use std::ops::Index; use std::sync::Arc; +use thiserror::Error; pub use self::blockpool::*; @@ -112,24 +113,31 @@ impl DmemManager { fn sys_dmem_container(self: &Arc, td: &VThread, i: &SysIn) -> Result { let dmem_id: i32 = i.args[0].try_into().unwrap(); - let mut dmem_container = td.proc().dmem_container_mut(); - let old_dmem_container = *dmem_container; + let dmem_container = td.proc().dmem_container_mut(); + let current_container = *dmem_container; if dmem_id != -1 { todo!() } - Ok(old_dmem_container.into()) + Ok(current_container.into()) } - fn sys_blockpool_open(self: &Arc, _td: &VThread, i: &SysIn) -> Result { + fn sys_blockpool_open(self: &Arc, td: &VThread, i: &SysIn) -> Result { let flags: u32 = i.args[0].try_into().unwrap(); if flags & 0xffafffff != 0 { return Err(SysErr::Raw(EINVAL)); } - todo!("sys_blockpool_open on new FS") + let bp = BlockPool::new(); + + let fd = td + .proc() + .files() + .alloc(Arc::new(VFile::new(VFileType::Blockpool(bp)))); + + Ok(fd.into()) } fn sys_blockpool_map(self: &Arc, _: &VThread, i: &SysIn) -> Result { @@ -158,10 +166,6 @@ impl DmemManager { fn sys_blockpool_move(self: &Arc, _: &VThread, _i: &SysIn) -> Result { todo!() } - - fn get_dmem_device<'a>(self: &'a Arc, dmem: DmemContainer) -> &'a DmemDevice { - self.index(dmem) - } } impl Index for DmemManager { diff --git a/src/kernel/src/fs/file.rs b/src/kernel/src/fs/file.rs index 9eb82052c..60c4f4098 100644 --- a/src/kernel/src/fs/file.rs +++ b/src/kernel/src/fs/file.rs @@ -24,7 +24,7 @@ pub struct VFile { } impl VFile { - pub(super) fn new(ty: VFileType) -> Self { + pub fn new(ty: VFileType) -> Self { let gg = GutexGroup::new(); Self { diff --git a/src/kernel/src/fs/ioctl.rs b/src/kernel/src/fs/ioctl.rs index dbabdef1a..57fd72b71 100644 --- a/src/kernel/src/fs/ioctl.rs +++ b/src/kernel/src/fs/ioctl.rs @@ -112,7 +112,7 @@ commands! { DIPSWCHECK2(&mut i32) = 0x40048806, /// Get total size? - DMEM10(&mut usize) = 0x4008800a, + DMEMTOTAL(&mut usize) = 0x4008800a, /// Get PRT aperture DMEMGETPRT(&mut PrtAperture) = 0xC018800C, /// Get available memory size diff --git a/src/kernel/src/fs/mod.rs b/src/kernel/src/fs/mod.rs index c5747ae20..a2534722e 100644 --- a/src/kernel/src/fs/mod.rs +++ b/src/kernel/src/fs/mod.rs @@ -443,7 +443,7 @@ impl Fs { // Our IoCmd contains both the command and the argument (if there is one). let cmd = IoCmd::try_from_raw_parts(i.args[1].into(), i.args[2].into())?; - info!("Executing ioctl({cmd:?}) on file descriptor {fd}."); + info!("Executing ioctl {cmd:?} on file descriptor {fd}."); self.ioctl(fd, cmd, td)?; diff --git a/src/kernel/src/main.rs b/src/kernel/src/main.rs index 8c37651ad..96b9e0180 100644 --- a/src/kernel/src/main.rs +++ b/src/kernel/src/main.rs @@ -434,7 +434,7 @@ fn run() -> Result<(), KernelError> { .load(path, flags, false, true, &main) .map_err(|e| KernelError::FailedToLoadLibkernel(e.into()))?; - libkernel.flags_mut().remove(ModuleFlags::UNK2); + libkernel.flags_mut().remove(ModuleFlags::IS_NEW); libkernel.print(info!()); ld.set_kernel(libkernel); @@ -448,7 +448,7 @@ fn run() -> Result<(), KernelError> { .load(path, flags, false, true, &main) .map_err(|e| KernelError::FailedToLoadLibSceLibcInternal(e.into()))?; - libc.flags_mut().remove(ModuleFlags::UNK2); + libc.flags_mut().remove(ModuleFlags::IS_NEW); libc.print(info!()); drop(libc); diff --git a/src/kernel/src/process/mod.rs b/src/kernel/src/process/mod.rs index cb172d505..2b4b12be5 100644 --- a/src/kernel/src/process/mod.rs +++ b/src/kernel/src/process/mod.rs @@ -783,7 +783,7 @@ impl VProc { ProcTypeInfo { len: size_of::(), - ty: self.budget_ptype as u32, + ty: self.budget_ptype.into(), flags, } } diff --git a/src/kernel/src/regmgr/mod.rs b/src/kernel/src/regmgr/mod.rs index 4679837d4..ad2a95a93 100644 --- a/src/kernel/src/regmgr/mod.rs +++ b/src/kernel/src/regmgr/mod.rs @@ -132,7 +132,7 @@ impl RegMgr { // Lookup the entry. let key = RegKey::new(key); let entry = self.lookup(key).ok_or(RegError::NotFound(key))?; - let web = if cred.is_webcore_process() || cred.is_diskplayerui_process() { + let web = if cred.is_libkernel_web() || cred.is_webprocess_webapp_or_webmas() { 1 } else { 0 diff --git a/src/kernel/src/rtld/mem.rs b/src/kernel/src/rtld/mem.rs index 2f7ec0319..96194801a 100644 --- a/src/kernel/src/rtld/mem.rs +++ b/src/kernel/src/rtld/mem.rs @@ -20,6 +20,7 @@ pub struct Memory { base: usize, text: usize, data: usize, + relro: Option, obcode: usize, obcode_sealed: Gutex, obdata: usize, @@ -61,10 +62,8 @@ impl Memory { } } ProgramType::PT_SCE_RELRO => { - if relro.is_some() { + if relro.replace(segments.len()).is_some() { return Err(MapError::MultipleRelroProgram); - } else { - relro = Some(segments.len()); } } _ => continue, @@ -132,7 +131,7 @@ impl Memory { len += segment.len; segments.push(segment); - // Create workspace for our data. We cannot mix this the code because the executable-space + // Create workspace for our data. We cannot mix this with the code because the executable-space // protection on some system don't allow execution on writable page. let obdata = segments.len(); let segment = MemorySegment { @@ -180,6 +179,7 @@ impl Memory { base, text, data, + relro, obcode, obcode_sealed: gg.spawn(0), obdata, @@ -212,6 +212,10 @@ impl Memory { &self.segments[self.data] } + pub fn relro_segment(&self) -> Option<&MemorySegment> { + self.relro.as_ref().map(|i| &self.segments[*i]) + } + /// # Safety /// Some part of the returned slice may not readable. pub unsafe fn as_bytes(&self) -> &[u8] { diff --git a/src/kernel/src/rtld/mod.rs b/src/kernel/src/rtld/mod.rs index 68aed61fd..ce1eaf89f 100644 --- a/src/kernel/src/rtld/mod.rs +++ b/src/kernel/src/rtld/mod.rs @@ -129,7 +129,7 @@ impl RuntimeLinker { ) .map_err(ExecError::MapFailed)?; - *app.flags_mut() |= ModuleFlags::MAIN_PROG; + *app.flags_mut() |= ModuleFlags::MAINPROG; self.ee .setup_module(&mut app) @@ -270,7 +270,7 @@ impl RuntimeLinker { // TODO: Check the call to sceSblAuthMgrIsLoadable in the self_load_shared_object on the PS4 // to see how it is return the value. if name != "libc.sprx" && name != "libSceFios2.sprx" { - *md.flags_mut() |= ModuleFlags::UNK1; + *md.flags_mut() |= ModuleFlags::IS_SYSTEM; } if let Err(e) = self.ee.setup_module(&mut md) { @@ -335,7 +335,7 @@ impl RuntimeLinker { // Resolve. let dags = md.dag_static(); - let sym = if md.flags().intersects(ModuleFlags::MAIN_PROG) { + let sym = if md.flags().intersects(ModuleFlags::MAINPROG) { todo!("do_dlsym on MAIN_PROG"); } else { resolver.resolve_from_list( @@ -451,8 +451,95 @@ impl RuntimeLinker { Ok(SysOut::ZERO) } - fn sys_dynlib_get_info(self: &Arc, _td: &VThread, _i: &SysIn) -> Result { - todo!() + fn sys_dynlib_get_info(self: &Arc, td: &VThread, i: &SysIn) -> Result { + let handle: u32 = i.args[0].try_into().unwrap(); + let info = { + let info_out: *mut DynlibInfo = i.args[1].into(); + + unsafe { &mut *info_out } + }; + + info!("Getting info for module id = {}.", handle); + + let bin = td.proc().bin(); + + let bin = match bin.as_ref() { + Some(bin) if bin.app().file_info().is_some() => bin, + _ => return Err(SysErr::Raw(EPERM)), + }; + + if info.size != size_of::() { + return Err(SysErr::Raw(EINVAL)); + } + + *info = self.dynlib_get_info(handle, bin, true)?; + + Ok(SysOut::ZERO) + } + + fn dynlib_get_info( + &self, + handle: u32, + bin: &Binaries, + no_system: bool, + ) -> Result { + let mut info: DynlibInfo = unsafe { zeroed() }; + + let mut modules = bin.list(); + + let md = modules + .find(|m| m.id() == handle) + .ok_or(SysErr::Raw(ESRCH))?; + + if no_system && md.flags().intersects(ModuleFlags::IS_SYSTEM) { + return Err(SysErr::Raw(EPERM)); + } + + let name = md.path().file_name().unwrap(); + + let mem = md.memory(); + let addr = mem.addr(); + + info.name[..name.len()].copy_from_slice(name.as_bytes()); + info.name[0xff] = 0; + info.segment_count = 2; + + info.text_segment.addr = mem.base(); + info.text_segment.size = mem.text_segment().len().try_into().unwrap(); + info.text_segment.prot = 5; + + info.data_segment.addr = addr + mem.data_segment().start(); + info.data_segment.size = mem.data_segment().len().try_into().unwrap(); + info.data_segment.prot = 3; + + if let Some(seg) = mem.relro_segment() { + info.relro_segment.addr = addr + seg.start(); + info.relro_segment.size = seg.len().try_into().unwrap(); + info.relro_segment.prot = 1; + + info.segment_count += 1; + }; + + info.fingerprint = md.fingerprint(); + + let mut e = info!(); + + writeln!( + e, + "Retrieved info for module {} (ID = {}).", + md.path(), + handle + ) + .unwrap(); + + writeln!(e, "mapbase : {:#x}", info.text_segment.addr).unwrap(); + writeln!(e, "textsize: {:#x}", info.text_segment.size).unwrap(); + writeln!(e, "database: {:#x}", info.data_segment.addr).unwrap(); + writeln!(e, "datasize: {:#x}", info.data_segment.size).unwrap(); + + print(e); + + Ok(info) } fn sys_dynlib_load_prx(self: &Arc, td: &VThread, i: &SysIn) -> Result { @@ -703,7 +790,7 @@ impl RuntimeLinker { self.relocate_rela(md, mem.as_mut(), &mut relocated, resolver)?; - if !md.flags().contains(ModuleFlags::UNK4) { + if !md.flags().contains(ModuleFlags::JMPSLOTS_DONE) { self.relocate_plt(md, mem.as_mut(), &mut relocated, resolver)?; } @@ -892,6 +979,8 @@ impl RuntimeLinker { let flags: u32 = i.args[1].try_into().unwrap(); let info: *mut DynlibInfoEx = i.args[2].into(); + info!("Getting info_ex for module id = {}.", handle); + // Check if application is dynamic linking. let bin = td.proc().bin(); let bin = bin.as_ref().ok_or(SysErr::Raw(EPERM))?; @@ -901,9 +990,8 @@ impl RuntimeLinker { } // Check buffer size. - let size: usize = unsafe { (*info).size.try_into().unwrap() }; - if size != size_of::() { + if unsafe { (*info).size } != size_of::() { return Err(SysErr::Raw(EINVAL)); } @@ -920,17 +1008,20 @@ impl RuntimeLinker { *info = unsafe { zeroed() }; info.handle = md.id(); - info.mapbase = addr + mem.base(); - info.textsize = mem.text_segment().len().try_into().unwrap(); - info.unk3 = 5; - info.database = addr + mem.data_segment().start(); - info.datasize = mem.data_segment().len().try_into().unwrap(); - info.unk4 = 3; - info.unk6 = 2; + + info.text_segment.addr = addr + mem.base(); + info.text_segment.size = mem.text_segment().len().try_into().unwrap(); + info.text_segment.prot = 5; + + info.data_segment.addr = addr + mem.data_segment().start(); + info.data_segment.size = mem.data_segment().len().try_into().unwrap(); + info.data_segment.prot = 3; + + info.segment_count = 2; info.refcount = *md.ref_count(); // Copy module name. - if flags & 2 == 0 || !md.flags().contains(ModuleFlags::UNK1) { + if flags & 2 == 0 || !md.flags().contains(ModuleFlags::IS_SYSTEM) { let name = md.path().file_name().unwrap(); info.name[..name.len()].copy_from_slice(name.as_bytes()); @@ -941,13 +1032,13 @@ impl RuntimeLinker { // Let's keep the same behavior as the PS4 for now. info.tlsindex = if flags & 1 != 0 { let flags = md.flags(); - let mut upper = if flags.contains(ModuleFlags::UNK1) { + let mut upper = if flags.contains(ModuleFlags::IS_SYSTEM) { 1 } else { 0 }; - if flags.contains(ModuleFlags::MAIN_PROG) { + if flags.contains(ModuleFlags::MAINPROG) { upper += 2; } @@ -968,7 +1059,7 @@ impl RuntimeLinker { info.tlsoffset = (*md.tls_offset()).try_into().unwrap(); // Initialization and finalization functions. - if !md.flags().contains(ModuleFlags::UNK5) { + if !md.flags().contains(ModuleFlags::NOT_GET_PROC) { info.init = md.init().map(|v| addr + v).unwrap_or(0); info.fini = md.fini().map(|v| addr + v).unwrap_or(0); } @@ -987,15 +1078,16 @@ impl RuntimeLinker { writeln!( e, - "Retrieved info for module {} (ID = {}).", + "Retrieved info_ex for module {} (ID = {}).", md.path(), handle ) .unwrap(); - writeln!(e, "mapbase : {:#x}", info.mapbase).unwrap(); - writeln!(e, "textsize : {:#x}", info.textsize).unwrap(); - writeln!(e, "database : {:#x}", info.database).unwrap(); - writeln!(e, "datasize : {:#x}", info.datasize).unwrap(); + + writeln!(e, "mapbase : {:#x}", info.text_segment.addr).unwrap(); + writeln!(e, "textsize : {:#x}", info.text_segment.size).unwrap(); + writeln!(e, "database : {:#x}", info.data_segment.addr).unwrap(); + writeln!(e, "datasize : {:#x}", info.data_segment.size).unwrap(); writeln!(e, "tlsindex : {}", info.tlsindex).unwrap(); writeln!(e, "tlsinit : {:#x}", info.tlsinit).unwrap(); writeln!(e, "tlsoffset : {:#x}", info.tlsoffset).unwrap(); @@ -1043,9 +1135,33 @@ impl RuntimeLinker { } } +#[derive(Debug)] +#[repr(C)] +struct SegmentInfo { + addr: usize, + size: u32, + prot: u32, +} + +#[derive(Debug)] +#[repr(C)] +struct DynlibInfo { + size: usize, + name: [u8; 256], + text_segment: SegmentInfo, + data_segment: SegmentInfo, + relro_segment: SegmentInfo, + unk_segment: SegmentInfo, + segment_count: u32, + fingerprint: [u8; 0x14], +} + +const _: () = assert!(size_of::() == 0x160); + +#[derive(Debug)] #[repr(C)] struct DynlibInfoEx { - size: u64, + size: usize, name: [u8; 256], handle: u32, tlsindex: u32, @@ -1062,17 +1178,16 @@ struct DynlibInfoEx { eh_frame: usize, eh_frame_hdr_size: u32, eh_frame_size: u32, - mapbase: usize, - textsize: u32, - unk3: u32, // Always 5. - database: usize, - datasize: u32, - unk4: u32, // Always 3. - unk5: [u8; 0x20], // Always zeroes. - unk6: u32, // Always 2. + text_segment: SegmentInfo, + data_segment: SegmentInfo, + relro_segment: SegmentInfo, + unk_segment: SegmentInfo, + segment_count: u32, // Always 2. refcount: u32, } +const _: () = assert!(size_of::() == 0x1a8); + /// Contains how TLS was allocated so far. #[derive(Debug)] pub struct TlsAlloc { diff --git a/src/kernel/src/rtld/module.rs b/src/kernel/src/rtld/module.rs index 6b31b3609..c17f7ff5a 100644 --- a/src/kernel/src/rtld/module.rs +++ b/src/kernel/src/rtld/module.rs @@ -39,6 +39,7 @@ pub struct Module { needed: Vec, modules: Vec, libraries: Vec, + fingerprint: [u8; 20], memory: Memory, relocated: Gutex>>, file_info: Option, @@ -173,13 +174,14 @@ impl Module { proc_param, mod_param, sdk_ver, - flags: gg.spawn(ModuleFlags::UNK2), + flags: gg.spawn(ModuleFlags::IS_NEW), names, dag_static: gg.spawn(Vec::new()), dag_dynamic: gg.spawn(Vec::new()), needed: Vec::new(), modules: Vec::new(), libraries: Vec::new(), + fingerprint: [0; 20], memory, relocated: gg.spawn(Vec::new()), file_info: None, @@ -284,6 +286,10 @@ impl Module { self.libraries.as_ref() } + pub fn fingerprint(&self) -> [u8; 20] { + self.fingerprint + } + pub fn memory(&self) -> &Memory { &self.memory } @@ -550,6 +556,8 @@ impl Module { /// See `digest_dynamic` on the PS4 for a reference. fn digest_dynamic(&mut self, base: usize, info: &FileInfo) -> Result<(), MapError> { // TODO: Implement the remaining tags. + let mut fingerprint_offset = None; + for (i, (tag, value)) in info.dynamic().enumerate() { match tag { DynamicTag::DT_NULL => break, @@ -579,6 +587,9 @@ impl Module { DynamicTag::DT_SONAME => self.digest_soname(info, i, value)?, DynamicTag::DT_TEXTREL => *self.flags.get_mut() |= ModuleFlags::TEXT_REL, DynamicTag::DT_FLAGS => self.digest_flags(value)?, + DynamicTag::DT_SCE_FINGERPRINT => { + fingerprint_offset = Some(u64::from_le_bytes(value) as usize) + } DynamicTag::DT_SCE_MODULE_INFO | DynamicTag::DT_SCE_NEEDED_MODULE => { self.digest_module_info(info, i, value)?; } @@ -589,6 +600,8 @@ impl Module { } } + self.digest_fingerprint(info, fingerprint_offset.unwrap_or(0)); + Ok(()) } @@ -645,6 +658,12 @@ impl Module { Ok(()) } + fn digest_fingerprint(&mut self, info: &FileInfo, offset: usize) { + let fingerprint = info.read_fingerprint(offset); + + self.fingerprint = fingerprint; + } + fn digest_module_info( &mut self, info: &FileInfo, @@ -739,18 +758,17 @@ bitflags! { /// Flags for [`Module`]. #[derive(Debug, Clone, Copy, PartialEq)] pub struct ModuleFlags: u16 { - const MAIN_PROG = 0x0001; + const MAINPROG = 0x0001; const TEXT_REL = 0x0002; - const JMPSLOTS_DONE = 0x0004; // TODO: This seems incorrect. const TLS_DONE = 0x0008; const INIT_SCANNED = 0x0010; const ON_FINI_LIST = 0x0020; const DAG_INITED = 0x0040; - const UNK1 = 0x0100; // TODO: Rename this. - const UNK2 = 0x0200; // TODO: Rename this. - const UNK3 = 0x0400; // TODO: Rename this. - const UNK4 = 0x0800; // TODO: It seems like this is actually JMPSLOTS_DONE. - const UNK5 = 0x1000; // TODO: Rename this. + const IS_SYSTEM = 0x0100; + const IS_NEW = 0x0200; + const LIBC_FIOS = 0x0400; + const JMPSLOTS_DONE = 0x0800; + const NOT_GET_PROC = 0x1000; } } diff --git a/src/kernel/src/ucred/auth.rs b/src/kernel/src/ucred/auth.rs index 4fb7c525f..f47b4c918 100644 --- a/src/kernel/src/ucred/auth.rs +++ b/src/kernel/src/ucred/auth.rs @@ -72,7 +72,7 @@ impl AuthPaid { /// A wrapper type for `caps` field of [`AuthInfo`]. #[repr(transparent)] #[derive(Debug, Clone)] -pub struct AuthCaps([u64; 4]); +pub struct AuthCaps(pub(super) [u64; 4]); impl AuthCaps { pub fn new(raw: [u64; 4]) -> Self { @@ -87,14 +87,6 @@ impl AuthCaps { (self.0[0] & 0x2000000000000000) != 0 } - pub fn is_jit_compiler_process(&self) -> bool { - todo!() - } - - pub fn is_jit_application_process(&self) -> bool { - todo!() - } - pub fn has_use_video_service_capability(&self) -> bool { self.0[0] >> 0x39 & 1 != 0 } @@ -126,11 +118,20 @@ impl AuthAttrs { } pub fn has_sce_program_attribute(&self) -> bool { - todo!() + (self.0[0] & 0x80000000) != 0 } pub fn is_debuggable_process(&self) -> bool { - todo!() + if self.0[0] & 0x1000000 == 0 { + if self.0[0] & 0x2000000 != 0 { + true + } else { + // TODO: properly implement this branch. + false + } + } else { + todo!() + } } pub fn is_unk1(&self) -> bool { diff --git a/src/kernel/src/ucred/mod.rs b/src/kernel/src/ucred/mod.rs index ac81a087c..343cbb012 100644 --- a/src/kernel/src/ucred/mod.rs +++ b/src/kernel/src/ucred/mod.rs @@ -57,13 +57,13 @@ impl Ucred { self.groups[1..].binary_search(&gid).is_ok() } - pub fn is_unknown1(&self) -> bool { + pub fn is_libkernel_web(&self) -> bool { // TODO: Refactor this for readability. - let id = self.auth.paid.get().wrapping_add(0xc7ffffffeffffffc); - (id < 0xf) && ((0x6001 >> (id & 0x3f) & 1) != 0) + let val = self.auth.paid.get().wrapping_add(0xc7ffffffeffffffc); + (val < 0xf) && ((0x6001 >> (val & 0x3f) & 1) != 0) } - pub fn is_unknown2(&self) -> bool { + pub fn is_webprocess_webapp_or_webmas(&self) -> bool { matches!( self.auth.paid.get(), 0x380000001000000f | 0x3800000010000013 @@ -77,12 +77,36 @@ impl Ucred { /// See `sceSblACMgrIsJitCompilerProcess` on the PS4 for a reference. pub fn is_jit_compiler_process(&self) -> bool { - self.auth.caps.is_jit_compiler_process() + let val = self.auth.caps.0[1]; + + if val >> 0x3e & 1 == 0 { + if val >> 0x38 & 1 != 0 && !todo!() { + true + } else if (self.auth.paid.get() >> 56) == 0x31 && !todo!() { + true + } else { + false + } + } else { + true + } } - /// See `sceSblACMgrIsJitCompilerProcess` on the PS4 for a reference. + /// See `sceSblACMgrIsJitApplicationProcess` on the PS4 for a reference. pub fn is_jit_application_process(&self) -> bool { - self.auth.caps.is_jit_application_process() + let val = self.auth.caps.0[1]; + + if val >> 0x3d & 1 == 0 { + if val >> 0x38 & 1 != 0 && !todo!() { + true + } else if (self.auth.paid.get() >> 56) == 0x31 && !todo!() { + true + } else { + false + } + } else { + true + } } /// See `sceSblACMgrIsVideoplayerProcess` on the PS4 for a reference. @@ -97,14 +121,17 @@ impl Ucred { /// See `sceSblACMgrIsWebcoreProcess` on the PS4 for a reference. pub fn is_webcore_process(&self) -> bool { - todo!() + let val = self.auth.paid.get().wrapping_add(0xc7ffffffeffffffd); + + (val < 0x11) && (0x1d003 >> (val & 0x3f) & 1 != 0) } + /// See `sceSblACMgrHasSceProgramAttribute` on the PS4 for a reference. pub fn has_sce_program_attribute(&self) -> bool { self.auth.attrs.has_sce_program_attribute() } - /// See `sceSblACMgrHasSceProgramAttribute` on the PS4 for a reference. + /// See `sceSblACMgrIsDebuggableProcess` on the PS4 for a reference. pub fn is_debuggable_process(&self) -> bool { self.auth.attrs.is_debuggable_process() } diff --git a/src/kernel/src/ucred/privilege.rs b/src/kernel/src/ucred/privilege.rs index 06e1cbc17..5916aad42 100644 --- a/src/kernel/src/ucred/privilege.rs +++ b/src/kernel/src/ucred/privilege.rs @@ -35,7 +35,7 @@ privileges! { /// See https://github.com/freebsd/freebsd-src/blob/release/9.1.0/sys/sys/priv.h for standard /// FreeBSD privileges. #[repr(i32)] - #[derive(Clone, Copy, PartialEq, Eq)] + #[derive(PartialEq, Eq)] pub enum Privilege { /// Exceed system open files limit. #[allow(unused)] @@ -57,6 +57,7 @@ privileges! { /// Currently unknown. SCE683 = 683, /// Currently unknown. + #[allow(unused)] SCE685 = 685, /// Currently unknown. SCE686 = 686, diff --git a/src/kernel/src/vm/mod.rs b/src/kernel/src/vm/mod.rs index 3e0508d1a..a160ef5bb 100644 --- a/src/kernel/src/vm/mod.rs +++ b/src/kernel/src/vm/mod.rs @@ -295,11 +295,11 @@ impl Vm { } /// See `vm_map_set_name` on the PS4 for a reference. - pub fn mname>( + pub fn mname( &self, addr: *mut u8, len: usize, - name: N, + name: impl AsRef, ) -> Result<(), MemoryUpdateError> { let name = name.as_ref(); let sname = CString::new(name); @@ -310,7 +310,7 @@ impl Vm { |i| i.name != name, |i| { if let Ok(name) = &sname { - i.storage.set_name(i.addr, i.len, name).ok(); + let _ = i.storage.set_name(i.addr, i.len, name); } i.name = name.to_owned(); @@ -510,7 +510,7 @@ impl Vm { // Set storage name if supported. if let Ok(name) = CString::new(name.as_str()) { - storage.set_name(addr, len, &name).ok(); + let _ = storage.set_name(addr, len, &name); } Ok(Alloc {