diff --git a/src/header/grp/mod.rs b/src/header/grp/mod.rs index 4958791cd96a7ec8852a481521507dedb220dae2..700db8df74f54367a0d4f7c597e8bc00b6cdfc6c 100644 --- a/src/header/grp/mod.rs +++ b/src/header/grp/mod.rs @@ -187,8 +187,8 @@ fn parse_grp(line: String, destbuf: Option<DestBuffer>) -> Result<OwnedGrp, Erro let members = buffer.next().ok_or(Error::EOF)?; - // Get the pointer to the members array - let member_array_ptr = unsafe { vec.as_mut_ptr().add(vec.len()) as *mut usize }; + // Get the offset of the members array + let member_array_start = vec.len(); // Push enough null pointers to fit all members for _member in members @@ -197,6 +197,7 @@ fn parse_grp(line: String, destbuf: Option<DestBuffer>) -> Result<OwnedGrp, Erro { vec.extend(0usize.to_ne_bytes()); } + let member_array_end = vec.len(); // Push a null pointer to terminate the members array vec.extend(0usize.to_ne_bytes()); @@ -206,10 +207,20 @@ fn parse_grp(line: String, destbuf: Option<DestBuffer>) -> Result<OwnedGrp, Erro .filter(|member| !member.is_empty()) .enumerate() { + let cur_offset = vec.len(); + + // This must be recomputed each time, because `vec` is undergoing extensions and so + // its backing memory might be reallocated and moved and its old memory deallocated. + let member_array = &mut vec[member_array_start..member_array_end]; + let member_ptr = { + const SIZEOF_PTR: usize = mem::size_of::<*mut c_void>(); + let start = i * SIZEOF_PTR; + let end = start + SIZEOF_PTR; + &mut member_array[start..end] + }; + // Store offset to start of member, MUST BE ADJUSTED LATER BASED ON THE ADDRESS OF THE BUFFER - unsafe { - *member_array_ptr.add(i) = vec.len(); - } + member_ptr.copy_from_slice(&cur_offset.to_ne_bytes()); vec.extend(member); vec.push(0); @@ -223,7 +234,7 @@ fn parse_grp(line: String, destbuf: Option<DestBuffer>) -> Result<OwnedGrp, Erro Some(buf) => { let mut buf = MaybeAllocated::Borrowed(buf); - if buf.len() < buf.len() { + if buf.len() < strings.len() { platform::ERRNO.set(errno::ERANGE); return Err(Error::BufTooSmall); } @@ -299,20 +310,38 @@ pub unsafe extern "C" fn getgrgid_r( buflen: usize, result: *mut *mut group, ) -> c_int { + // In case of error or the requested entry is not found. + *result = ptr::null_mut(); + let Ok(db) = File::open(c_str!("/etc/group"), fcntl::O_RDONLY) else { return ENOENT; }; for line in BufReader::new(db).lines() { let Ok(line) = line else { return EINVAL }; - let Ok(mut grp) = parse_grp( + let grp = match parse_grp( line, Some(DestBuffer { ptr: buffer as *mut u8, len: buflen, }), - ) else { - return EINVAL; + ) { + Ok(grp) => grp, + Err(err) => { + return match err { + Error::BufTooSmall => ERANGE, + Error::EOF + | Error::SyntaxError + | Error::FromUtf8Error(_) + | Error::ParseIntError(_) + | Error::Other => EINVAL, + Error::Misc(io_err) => match io_err.kind() { + io::ErrorKind::InvalidData | io::ErrorKind::UnexpectedEof => EINVAL, + io::ErrorKind::NotFound => ENOENT, + _ => EIO, + }, + } + } }; if grp.reference.gr_gid == gid { @@ -323,7 +352,8 @@ pub unsafe extern "C" fn getgrgid_r( } } - return ENOENT; + // The requested entry was not found. + return 0; } // MT-Safe locale diff --git a/src/sync/rwlock.rs b/src/sync/rwlock.rs index f5ecaf12fe601ecdfaf8d022b8ec1d6d21ae2394..b787a8e85747f9e531d574e422bbde90b927368b 100644 --- a/src/sync/rwlock.rs +++ b/src/sync/rwlock.rs @@ -45,7 +45,15 @@ impl Rwlock { }; waiting_wr = expected & WAITING_WR; - let _ = crate::sync::futex_wait(&self.state, expected, deadline); + if actual & COUNT_MASK > 0 { + let _ = crate::sync::futex_wait(&self.state, expected, deadline); + } else { + // We must avoid blocking indefinitely in our `futex_wait()`, in this case + // where it's possible that `self.state == expected` but our futex might + // never be woken again, because it's possible that all other threads + // already did their `futex_wake()` before we would've done our + // `futex_wait()`. + } } } }