From 2f7f296f8e7eae3944bc34e9dfe51a262b7f7149 Mon Sep 17 00:00:00 2001
From: Ian Moffett <ian@osmora.org>
Date: Sat, 22 Feb 2025 02:18:16 -0500
Subject: libc: Add __stack_chk_fail() stub

Signed-off-by: Ian Moffett <ian@osmora.org>
---
 lib/libc/src/debug/stack_chk_fail.c | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)
 create mode 100644 lib/libc/src/debug/stack_chk_fail.c

(limited to 'lib/libc')

diff --git a/lib/libc/src/debug/stack_chk_fail.c b/lib/libc/src/debug/stack_chk_fail.c
new file mode 100644
index 0000000..7abf5eb
--- /dev/null
+++ b/lib/libc/src/debug/stack_chk_fail.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Hyra nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+__attribute__((noreturn)) void
+__stack_chk_fail(void)
+{
+    /* TODO: Write a message here, don't hang */
+    for (;;);
+}
-- 
cgit v1.2.3


From d68537c1ca22d58f1c219d970d5aa462df9e0c6b Mon Sep 17 00:00:00 2001
From: Ian Moffett <ian@osmora.org>
Date: Sat, 22 Feb 2025 02:18:33 -0500
Subject: kernel: vfs: Add support for write()

Signed-off-by: Ian Moffett <ian@osmora.org>
---
 lib/libc/include/unistd.h   |  1 +
 lib/libc/src/unistd/write.c | 38 ++++++++++++++++++++++++++++++++++
 sys/fs/initramfs.c          |  1 +
 sys/include/sys/fcntl.h     |  5 +++++
 sys/include/sys/filedesc.h  |  2 ++
 sys/include/sys/syscall.h   |  1 +
 sys/include/sys/vfs.h       |  1 +
 sys/include/sys/vnode.h     |  2 ++
 sys/kern/kern_descrip.c     | 50 ++++++++++++++++++++++++++++++++++++++-------
 sys/kern/kern_syscall.c     |  1 +
 sys/kern/vfs_subr.c         | 13 ++++++++++++
 sys/kern/vfs_syscalls.c     | 12 +++++++++++
 12 files changed, 120 insertions(+), 7 deletions(-)
 create mode 100644 lib/libc/src/unistd/write.c

(limited to 'lib/libc')

diff --git a/lib/libc/include/unistd.h b/lib/libc/include/unistd.h
index 50d6800..c487d38 100644
--- a/lib/libc/include/unistd.h
+++ b/lib/libc/include/unistd.h
@@ -36,6 +36,7 @@
 __BEGIN_DECLS
 
 ssize_t read(int fd, void *buf, size_t count);
+ssize_t write(int fd, const void *buf, size_t count);
 int close(int fd);
 
 __END_DECLS
diff --git a/lib/libc/src/unistd/write.c b/lib/libc/src/unistd/write.c
new file mode 100644
index 0000000..2672016
--- /dev/null
+++ b/lib/libc/src/unistd/write.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Hyra nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+ssize_t
+write(int fd, const void *buf, size_t count)
+{
+    return syscall(SYS_write, fd, (uintptr_t)buf, count);
+}
diff --git a/sys/fs/initramfs.c b/sys/fs/initramfs.c
index acef462..fd746ef 100644
--- a/sys/fs/initramfs.c
+++ b/sys/fs/initramfs.c
@@ -275,6 +275,7 @@ initramfs_init(struct fs_info *fip)
 const struct vops g_initramfs_vops = {
     .lookup = initramfs_lookup,
     .read = initramfs_read,
+    .write = NULL,
     .reclaim = initramfs_reclaim,
     .getattr = initramfs_getattr
 };
diff --git a/sys/include/sys/fcntl.h b/sys/include/sys/fcntl.h
index 7a62cdd..122a378 100644
--- a/sys/include/sys/fcntl.h
+++ b/sys/include/sys/fcntl.h
@@ -34,4 +34,9 @@
 #define O_WRONLY    0x0001
 #define O_RDWR      0x0002
 
+/* Makes seal checking easier */
+#if defined(_KERNEL)
+#define O_ALLOW_WR (O_RDWR | O_WRONLY)
+#endif
+
 #endif  /* !_SYS_FCTNL_H_ */
diff --git a/sys/include/sys/filedesc.h b/sys/include/sys/filedesc.h
index 9a6230a..a544811 100644
--- a/sys/include/sys/filedesc.h
+++ b/sys/include/sys/filedesc.h
@@ -39,12 +39,14 @@ struct filedesc {
     off_t offset;
     bool is_dir;
     int refcnt;
+    int flags;
     struct vnode *vp;
     struct spinlock lock;
 };
 
 int fd_close(unsigned int fd);
 int fd_read(unsigned int fd, void *buf, size_t count);
+int fd_write(unsigned int fd, void *buf, size_t count);
 
 int fd_alloc(struct filedesc **fd_out);
 int fd_open(const char *pathname, int flags);
diff --git a/sys/include/sys/syscall.h b/sys/include/sys/syscall.h
index b724e8b..41d1e78 100644
--- a/sys/include/sys/syscall.h
+++ b/sys/include/sys/syscall.h
@@ -42,6 +42,7 @@
 #define SYS_close   4
 #define SYS_stat    5
 #define SYS_sysctl  6
+#define SYS_write   7
 
 #if defined(_KERNEL)
 /* Syscall return value and arg type */
diff --git a/sys/include/sys/vfs.h b/sys/include/sys/vfs.h
index 61f6673..1ff722a 100644
--- a/sys/include/sys/vfs.h
+++ b/sys/include/sys/vfs.h
@@ -38,6 +38,7 @@
 scret_t sys_open(struct syscall_args *scargs);
 scret_t sys_close(struct syscall_args *args);
 scret_t sys_read(struct syscall_args *scargs);
+scret_t sys_write(struct syscall_args *sargs);
 scret_t sys_stat(struct syscall_args *scargs);
 
 #endif  /* _KERNEL */
diff --git a/sys/include/sys/vnode.h b/sys/include/sys/vnode.h
index 5cbaa15..33092f9 100644
--- a/sys/include/sys/vnode.h
+++ b/sys/include/sys/vnode.h
@@ -101,6 +101,7 @@ struct vops {
     int(*lookup)(struct vop_lookup_args *args);
     int(*getattr)(struct vop_getattr_args *args);
     int(*read)(struct vnode *vp, struct sio_txn *sio);
+    int(*write)(struct vnode *vp, struct sio_txn *sio);
     int(*reclaim)(struct vnode *vp);
 };
 
@@ -117,6 +118,7 @@ int vfs_release_vnode(struct vnode *vp);
 
 int vfs_vop_lookup(struct vnode *vp, struct vop_lookup_args *args);
 int vfs_vop_read(struct vnode *vp, struct sio_txn *sio);
+int vfs_vop_write(struct vnode *vp, struct sio_txn *sio);
 int vfs_vop_getattr(struct vnode *vp, struct vop_getattr_args *args);
 
 #endif  /* _KERNEL */
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index d1ed044..201db3e 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -31,6 +31,7 @@
 #include <sys/errno.h>
 #include <sys/proc.h>
 #include <sys/limits.h>
+#include <sys/fcntl.h>
 #include <sys/namei.h>
 #include <sys/filedesc.h>
 #include <sys/systm.h>
@@ -135,15 +136,16 @@ fd_close(unsigned int fd)
 }
 
 /*
- * Read bytes from a file using a file
+ * Read/write bytes to/from a file using a file
  * descriptor number.
  *
  * @fd: File descriptor number.
- * @buf: Buffer to read into.
+ * @buf: Buffer with data to read/write
  * @count: Number of bytes to read.
+ * @write: Set to 1 for writes
  */
-int
-fd_read(unsigned int fd, void *buf, size_t count)
+static int
+fd_rw(unsigned int fd, void *buf, size_t count, uint8_t write)
 {
     char *kbuf = NULL;
     struct filedesc *filedes;
@@ -173,13 +175,34 @@ fd_read(unsigned int fd, void *buf, size_t count)
         goto done;
     }
 
+    /* Check if this violates the file seal */
+    if (!ISSET(filedes->flags, O_ALLOW_WR) && write) {
+        return -EPERM;
+    } else if (ISSET(O_RDONLY, filedes->flags) && write) {
+        return -EPERM;
+    }
+
     sio.len = count;
     sio.buf = kbuf;
     sio.offset = filedes->offset;
 
-    if ((count = vfs_vop_read(filedes->vp, &sio)) < 0) {
-        retval = -EIO;
-        goto done;
+    if (write) {
+        /* Copy in user buffer */
+        if (copyin(buf, kbuf, count) < 0) {
+            retval = -EFAULT;
+            goto done;
+        }
+
+        /* Call VFS write hook */
+        if ((count = vfs_vop_write(filedes->vp, &sio)) < 0) {
+            retval = -EIO;
+            goto done;
+        }
+    } else {
+        if ((count = vfs_vop_read(filedes->vp, &sio)) < 0) {
+            retval = -EIO;
+            goto done;
+        }
     }
 
     if (copyout(kbuf, buf, count) < 0) {
@@ -195,6 +218,18 @@ done:
     return retval;
 }
 
+int
+fd_read(unsigned int fd, void *buf, size_t count)
+{
+    return fd_rw(fd, buf, count, 0);
+}
+
+int
+fd_write(unsigned int fd, void *buf, size_t count)
+{
+    return fd_rw(fd, buf, count, 1);
+}
+
 /*
  * Open a file and get a file descriptor
  * number.
@@ -224,6 +259,7 @@ fd_open(const char *pathname, int flags)
     }
 
     filedes->vp = nd.vp;
+    filedes->flags = flags;
     return filedes->fdno;
 }
 
diff --git a/sys/kern/kern_syscall.c b/sys/kern/kern_syscall.c
index 1d961a7..986d82a 100644
--- a/sys/kern/kern_syscall.c
+++ b/sys/kern/kern_syscall.c
@@ -41,6 +41,7 @@ scret_t(*g_sctab[])(struct syscall_args *) = {
     sys_close,  /* SYS_close */
     sys_stat,   /* SYS_stat */
     sys_sysctl, /* SYS_sysctl */
+    sys_write,  /* SYS_write */
 };
 
 const size_t MAX_SYSCALLS = NELEM(g_sctab);
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index f67bcfe..da0a4f9 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -166,6 +166,19 @@ vfs_vop_read(struct vnode *vp, struct sio_txn *sio)
     return vops->read(vp, sio);
 }
 
+int
+vfs_vop_write(struct vnode *vp, struct sio_txn *sio)
+{
+    const struct vops *vops = vp->vops;
+
+    if (vops == NULL)
+        return -EIO;
+    if (vops->write == NULL)
+        return -EIO;
+
+    return vops->write(vp, sio);
+}
+
 int
 vfs_vop_getattr(struct vnode *vp, struct vop_getattr_args *args)
 {
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index fa613c2..6f2d683 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -128,6 +128,18 @@ sys_read(struct syscall_args *scargs)
         scargs->arg2);
 }
 
+/*
+ * arg0: fd
+ * arg1: buf
+ * arg2: count
+ */
+scret_t
+sys_write(struct syscall_args *scargs)
+{
+    return fd_write(scargs->arg0, (void *)scargs->arg1,
+        scargs->arg2);
+}
+
 /*
  * arg0: path
  * arg1: buf
-- 
cgit v1.2.3