diff --git a/src/header/grp/mod.rs b/src/header/grp/mod.rs index 4958791cd9..700db8df74 100644 --- a/src/header/grp/mod.rs +++ b/src/header/grp/mod.rs @@ -187,8 +187,8 @@ fn parse_grp(line: String, destbuf: Option) -> Result) -> Result) -> Result(); + 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) -> Result { 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 f5ecaf12fe..b787a8e857 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()`. + } } } }