Przeglądaj źródła

Fix stat stack corruption and link test

jD91mZM2 6 lat temu
rodzic
commit
5697ac0f84

+ 2 - 2
src/arpainet/src/lib.rs

@@ -14,9 +14,9 @@ extern crate sys_socket;
 use core::str::FromStr;
 use core::{mem, ptr, slice, str};
 use errno::*;
-pub use netinet::in_h::*;
+use netinet::in_h::in_addr;
 use platform::types::*;
-use platform::{c_str, socklen_t, AF_INET};
+use platform::c_str;
 
 #[no_mangle]
 pub extern "C" fn htonl(hostlong: u32) -> u32 {

+ 1 - 34
src/platform/src/lib.rs

@@ -36,46 +36,13 @@ mod sys;
 pub mod types;
 
 use alloc::Vec;
-use core::{fmt, mem, ptr};
+use core::{fmt, ptr};
 
 use types::*;
 
 #[global_allocator]
 static ALLOCATOR: Allocator = Allocator;
 
-pub const AF_INET: c_int = 2;
-pub const SOCK_STREAM: c_int = 1;
-pub const SOCK_DGRAM: c_int = 2;
-pub const SOCK_NONBLOCK: c_int = 0o4000;
-pub const SOCK_CLOEXEC: c_int = 0o2000000;
-
-pub const SIG_BLOCK: c_int = 0;
-pub const SIG_UNBLOCK: c_int = 1;
-pub const SIG_SETMASK: c_int = 2;
-
-pub type in_addr_t = [u8; 4];
-pub type in_port_t = u16;
-pub type sa_family_t = u16;
-pub type socklen_t = u32;
-
-#[repr(C)]
-pub struct sockaddr {
-    pub sa_family: sa_family_t,
-    pub data: [c_char; 14],
-}
-
-#[repr(C)]
-pub struct sigaction {
-    pub sa_handler: extern "C" fn(c_int),
-    pub sa_flags: c_ulong,
-    pub sa_restorer: unsafe extern "C" fn(),
-    pub sa_mask: sigset_t
-}
-
-const NSIG: usize = 64;
-
-pub type sigset_t = [c_ulong; NSIG / (8 * mem::size_of::<c_ulong>())];
-
 //TODO #[thread_local]
 #[allow(non_upper_case_globals)]
 #[no_mangle]

+ 1 - 14
src/platform/src/linux/mod.rs

@@ -1,26 +1,13 @@
 use core::{mem, ptr};
 
+use errno;
 use types::*;
-use *;
 
 const AT_FDCWD: c_int = -100;
 const AT_EMPTY_PATH: c_int = 0x1000;
 const AT_REMOVEDIR: c_int = 0x200;
 const AT_SYMLINK_NOFOLLOW: c_int = 0x100;
 
-// Also in sys_utsname. Has to be both because cbindgen
-const UTSLENGTH: usize = 65;
-
-#[repr(C)]
-pub struct utsname {
-    pub sysname: [c_char; UTSLENGTH],
-    pub nodename: [c_char; UTSLENGTH],
-    pub release: [c_char; UTSLENGTH],
-    pub version: [c_char; UTSLENGTH],
-    pub machine: [c_char; UTSLENGTH],
-    pub domainname: [c_char; UTSLENGTH],
-}
-
 fn e(sys: usize) -> usize {
     if (sys as isize) < 0 && (sys as isize) >= -256 {
         unsafe {

+ 0 - 1
src/platform/src/redox/mod.rs

@@ -10,7 +10,6 @@ use syscall::flag::*;
 use syscall::{self, Result};
 
 use types::*;
-use *;
 
 #[thread_local]
 static mut SIG_HANDLER: Option<extern "C" fn(c_int)> = None;

+ 54 - 1
src/platform/src/types.rs

@@ -1,3 +1,5 @@
+use core::mem;
+
 #[cfg(target_os = "redox")]
 use syscall::data::TimeSpec as redox_timespec;
 // Use repr(u8) as LLVM expects `void*` to be the same as `i8*` to help enable
@@ -96,8 +98,59 @@ pub struct stat {
     pub st_rdev: dev_t,
     pub st_size: off_t,
     pub st_blksize: blksize_t,
+    pub st_blocks: blkcnt_t,
+
     pub st_atim: time_t,
     pub st_mtim: time_t,
     pub st_ctim: time_t,
-    pub st_blocks: blkcnt_t,
+
+    // Compared to glibc, our struct is for some reason 48 bytes too small.
+    // Accessing atime works, so clearly the struct isn't incorrect...
+    // This works.
+    pub _pad: [u8; 48]
+}
+
+pub const AF_INET: c_int = 2;
+pub const SOCK_STREAM: c_int = 1;
+pub const SOCK_DGRAM: c_int = 2;
+pub const SOCK_NONBLOCK: c_int = 0o4000;
+pub const SOCK_CLOEXEC: c_int = 0o2000000;
+
+pub const SIG_BLOCK: c_int = 0;
+pub const SIG_UNBLOCK: c_int = 1;
+pub const SIG_SETMASK: c_int = 2;
+
+pub type in_addr_t = [u8; 4];
+pub type in_port_t = u16;
+pub type sa_family_t = u16;
+pub type socklen_t = u32;
+
+#[repr(C)]
+pub struct sockaddr {
+    pub sa_family: sa_family_t,
+    pub data: [c_char; 14],
+}
+
+#[repr(C)]
+pub struct sigaction {
+    pub sa_handler: extern "C" fn(c_int),
+    pub sa_flags: c_ulong,
+    pub sa_restorer: unsafe extern "C" fn(),
+    pub sa_mask: sigset_t
+}
+
+const NSIG: usize = 64;
+
+pub type sigset_t = [c_ulong; NSIG / (8 * mem::size_of::<c_ulong>())];
+
+const UTSLENGTH: usize = 65;
+
+#[repr(C)]
+pub struct utsname {
+    pub sysname: [c_char; UTSLENGTH],
+    pub nodename: [c_char; UTSLENGTH],
+    pub release: [c_char; UTSLENGTH],
+    pub version: [c_char; UTSLENGTH],
+    pub machine: [c_char; UTSLENGTH],
+    pub domainname: [c_char; UTSLENGTH],
 }

+ 2 - 3
src/signal/src/lib.rs

@@ -36,7 +36,6 @@ pub use sys::*;
 
 use core::{mem, ptr};
 use platform::types::*;
-use platform::sigset_t;
 
 #[no_mangle]
 pub extern "C" fn kill(pid: pid_t, sig: c_int) -> c_int {
@@ -59,11 +58,11 @@ pub unsafe extern "C" fn sigaction(sig: c_int, act: *const sigaction, oact: *mut
     let ptr = if !act.is_null() {
         _sigaction = Some((*act).clone());
         _sigaction.as_mut().unwrap().sa_flags |= SA_RESTORER as c_ulong;
-        _sigaction.as_mut().unwrap() as *mut _ as *mut platform::sigaction
+        _sigaction.as_mut().unwrap() as *mut _ as *mut platform::types::sigaction
     } else {
         ptr::null_mut()
     };
-    platform::sigaction(sig, ptr, oact as *mut platform::sigaction)
+    platform::sigaction(sig, ptr, oact as *mut platform::types::sigaction)
 }
 
 // #[no_mangle]

+ 7 - 7
src/sys_socket/src/lib.rs

@@ -28,7 +28,7 @@ pub unsafe extern "C" fn accept(
     address: *mut sockaddr,
     address_len: *mut socklen_t,
 ) -> c_int {
-    platform::accept(socket, address as *mut platform::sockaddr, address_len)
+    platform::accept(socket, address as *mut platform::types::sockaddr, address_len)
 }
 
 #[no_mangle]
@@ -37,7 +37,7 @@ pub unsafe extern "C" fn bind(
     address: *const sockaddr,
     address_len: socklen_t,
 ) -> c_int {
-    platform::bind(socket, address as *const platform::sockaddr, address_len)
+    platform::bind(socket, address as *const platform::types::sockaddr, address_len)
 }
 
 #[no_mangle]
@@ -46,7 +46,7 @@ pub unsafe extern "C" fn connect(
     address: *const sockaddr,
     address_len: socklen_t,
 ) -> c_int {
-    platform::connect(socket, address as *const platform::sockaddr, address_len)
+    platform::connect(socket, address as *const platform::types::sockaddr, address_len)
 }
 
 #[no_mangle]
@@ -55,7 +55,7 @@ pub unsafe extern "C" fn getpeername(
     address: *mut sockaddr,
     address_len: *mut socklen_t,
 ) -> c_int {
-    platform::getpeername(socket, address as *mut platform::sockaddr, address_len)
+    platform::getpeername(socket, address as *mut platform::types::sockaddr, address_len)
 }
 
 #[no_mangle]
@@ -64,7 +64,7 @@ pub unsafe extern "C" fn getsockname(
     address: *mut sockaddr,
     address_len: *mut socklen_t,
 ) -> c_int {
-    platform::getsockname(socket, address as *mut platform::sockaddr, address_len)
+    platform::getsockname(socket, address as *mut platform::types::sockaddr, address_len)
 }
 
 #[no_mangle]
@@ -114,7 +114,7 @@ pub unsafe extern "C" fn recvfrom(
         buffer,
         length,
         flags,
-        address as *mut platform::sockaddr,
+        address as *mut platform::types::sockaddr,
         address_len,
     )
 }
@@ -143,7 +143,7 @@ pub unsafe extern "C" fn sendto(
         message,
         length,
         flags,
-        dest_addr as *const platform::sockaddr,
+        dest_addr as *const platform::types::sockaddr,
         dest_len,
     )
 }

+ 10 - 4
src/sys_stat/src/lib.rs

@@ -6,7 +6,7 @@ extern crate platform;
 
 use platform::types::*;
 
-pub const S_IFMT: c_int = 0o0170000;
+pub const S_IFMT:  c_int = 0o0170000;
 pub const S_IFBLK: c_int = 0o060000;
 pub const S_IFCHR: c_int = 0o020000;
 pub const S_IFIFO: c_int = 0o010000;
@@ -43,10 +43,16 @@ pub struct stat {
     pub st_rdev: dev_t,
     pub st_size: off_t,
     pub st_blksize: blksize_t,
-    pub st_atime: time_t,
-    pub st_mtime: time_t,
-    pub st_ctime: time_t,
     pub st_blocks: blkcnt_t,
+
+    pub st_atim: time_t,
+    pub st_mtim: time_t,
+    pub st_ctim: time_t,
+
+    // Compared to glibc, our struct is for some reason 48 bytes too small.
+    // Accessing atime works, so clearly the struct isn't incorrect...
+    // This works.
+    pub _pad: [u8; 48]
 }
 
 #[no_mangle]

+ 8 - 8
src/sys_utsname/src/lib.rs

@@ -8,22 +8,22 @@ mod inner {
 
     use self::platform::types::*;
 
-    const LENGTH: usize = 65;
+    const UTSLENGTH: usize = 65;
 
     #[no_mangle]
     #[repr(C)]
     pub struct utsname {
-        pub sysname: [c_char; LENGTH],
-        pub nodename: [c_char; LENGTH],
-        pub release: [c_char; LENGTH],
-        pub version: [c_char; LENGTH],
-        pub machine: [c_char; LENGTH],
-        pub domainname: [c_char; LENGTH],
+        pub sysname: [c_char; UTSLENGTH],
+        pub nodename: [c_char; UTSLENGTH],
+        pub release: [c_char; UTSLENGTH],
+        pub version: [c_char; UTSLENGTH],
+        pub machine: [c_char; UTSLENGTH],
+        pub domainname: [c_char; UTSLENGTH],
     }
 
     #[no_mangle]
     pub unsafe extern "C" fn uname(uts: *mut utsname) -> c_int {
-        platform::uname(uts as *mut platform::utsname)
+        platform::uname(uts as *mut platform::types::utsname)
     }
 }
 #[cfg(target_os = "linux")]

+ 1 - 1
tests/.gitignore

@@ -56,6 +56,7 @@ unistd/getopt
 unistd/pipe
 unistd/rmdir
 unistd/sleep
+unistd/stat
 unistd/write
 waitpid
 wchar/mbrtowc
@@ -70,4 +71,3 @@ unistd/gethostname
 unistd/getid
 unistd/link
 unistd/setid
-unistd/unlink

+ 2 - 2
tests/Makefile

@@ -55,6 +55,7 @@ EXPECT_BINS=\
 	unistd/pipe \
 	unistd/rmdir \
 	unistd/sleep \
+	unistd/stat \
 	unistd/write \
 	waitpid \
 	wchar/mbrtowc \
@@ -72,8 +73,7 @@ BINS=\
 	unistd/gethostname \
 	unistd/getid \
 	unistd/link \
-	unistd/setid \
-	unistd/unlink
+	unistd/setid
 
 all: $(BINS)
 

+ 0 - 0
tests/expected/unistd/stat.stderr


+ 4 - 0
tests/expected/unistd/stat.stdout

@@ -0,0 +1,4 @@
+144
+st_mode: 33188
+st_size: 383
+st_blksize: 4096

+ 41 - 3
tests/unistd/link.c

@@ -1,8 +1,46 @@
+#include <errno.h>
 #include <stdio.h>
+#include <sys/stat.h>
 #include <unistd.h>
 
 int main(int argc, char** argv) {
-    link("./link.c", "./link.out");
-    perror("link");
-    return 0;
+    printf("%ld\n", sizeof(struct stat));
+
+    struct stat buf;
+
+    // Stat for the inode
+    if (stat("unistd/link.c", &buf)) {
+        perror("stat");
+        return 1;
+    }
+    unsigned long inode = buf.st_ino;
+    printf("%ld\n", inode);
+
+    // Create the link
+    if (link("unistd/link.c", "link.out")) {
+        perror("link");
+        return 1;
+    }
+
+    // Make sure inodes match
+    if (stat("link.out", &buf)) {
+        perror("stat");
+    }
+    printf("%ld\n", inode);
+    printf("%ld\n", buf.st_ino);
+    if (inode != buf.st_ino) {
+        puts("Created file is not a link.");
+        printf("unistd/link.c inode: %ld\n", inode);
+        printf("link.out inode: %ld\n", buf.st_ino);
+    }
+
+    // Remove link
+    if (unlink("link.out")) {
+        perror("unlink");
+        return 1;
+    }
+    if (!stat("link.out", &buf) || errno != ENOENT) {
+        perror("stat");
+        return 1;
+    }
 }

+ 19 - 0
tests/unistd/stat.c

@@ -0,0 +1,19 @@
+#include <errno.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+int main() {
+    printf("%ld\n", sizeof(struct stat));
+
+    struct stat buf;
+
+    if (stat("unistd/stat.c", &buf)) {
+        perror("stat");
+        return 1;
+    }
+
+    printf("st_mode: %u\n", buf.st_mode);
+    printf("st_size: %lu\n", buf.st_size);
+    printf("st_blksize: %lu\n", buf.st_blksize);
+}

+ 0 - 8
tests/unistd/unlink.c

@@ -1,8 +0,0 @@
-#include <unistd.h>
-#include <stdio.h>
-
-int main(int argc, char** argv) {
-    link("./unlink.c", "./unlink.out");
-    perror("unlink");
-    return 0;
-}