summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Moffett <ian@osmora.org>2025-07-03 19:59:45 -0400
committerIan Moffett <ian@osmora.org>2025-07-03 19:59:45 -0400
commit23a8e1b78063c0276d987e835434700267b9c8f8 (patch)
tree19886b291f9c56fb2c90068aece37aee991cca79
parent9c7fcf89f9ec234dd55ace2c48f4fcc84069c5ac (diff)
kernel: Ensure mutually exclusive console accessexpt
If multiple processes try to write to the console, a race condition of sorts may occur. Similarly, if multiple processes try to read from the console and contend with the console input buffer. One process may steal keys from the other. Prevent this by implementing a mutex within the console descriptor. Each time a process reads or writes the console, it attaches itself. Any other processes attempting to read or write the console while another is attached will be yielded to the scheduler until the resource is free. Signed-off-by: Ian Moffett <ian@osmora.org>
-rw-r--r--sys/dev/cons/cons.c70
-rw-r--r--sys/include/dev/cons/cons.h6
-rw-r--r--sys/kern/kern_sched.c2
3 files changed, 78 insertions, 0 deletions
diff --git a/sys/dev/cons/cons.c b/sys/dev/cons/cons.c
index 2cef071..9921ff8 100644
--- a/sys/dev/cons/cons.c
+++ b/sys/dev/cons/cons.c
@@ -343,6 +343,7 @@ cons_fast_putch(struct cons_screen *scr, char c)
static int
dev_write(dev_t dev, struct sio_txn *sio, int flags)
{
+ cons_attach();
cons_putstr(&g_root_scr, sio->buf, sio->len);
cons_flush(&g_root_scr);
return sio->len;
@@ -372,6 +373,7 @@ dev_read(dev_t dev, struct sio_txn *sio, int flags)
return -EAGAIN;
}
+ cons_attach();
spinlock_acquire(&g_root_scr.lock);
for (;;) {
/* Buffer too small */
@@ -468,6 +470,69 @@ ctl_feat_write(struct ctlfs_dev *cdp, struct sio_txn *sio)
}
/*
+ * Detach the currently running process from the
+ * console.
+ */
+int
+cons_detach(void)
+{
+ struct cons_screen *scr;
+
+ scr = &g_root_scr;
+ if (scr->atproc == NULL) {
+ return 0;
+ }
+ if (scr->atproc_lock == NULL) {
+ return 0;
+ }
+
+ scr = &g_root_scr;
+ scr->atproc = NULL;
+ mutex_release(scr->atproc_lock);
+ return 0;
+}
+
+/*
+ * Attach the current process to the
+ * console.
+ */
+int
+cons_attach(void)
+{
+ struct cons_screen *scr;
+ struct proc *td, *atproc;
+
+ td = this_td();
+ if (td == NULL) {
+ return -1;
+ }
+
+ scr = &g_root_scr;
+ if (scr->atproc_lock == NULL) {
+ return 0;
+ }
+
+ scr = &g_root_scr;
+ atproc = scr->atproc;
+
+ if (atproc != NULL) {
+ if (atproc->pid == td->pid) {
+ return 0;
+ }
+
+ /*
+ * Do not release this here as we want
+ * any other process that tries to attach
+ * to wait.
+ */
+ mutex_acquire(scr->atproc_lock, 0);
+ }
+
+ scr->atproc = td;
+ return 0;
+}
+
+/*
* Reset console color.
*/
void
@@ -556,6 +621,8 @@ cons_init(void)
g_root_scr.nrows = fbdev.height / FONT_HEIGHT;
g_root_scr.ncols = fbdev.width / FONT_WIDTH;
g_root_scr.fbdev = fbdev;
+ g_root_scr.atproc = NULL;
+ g_root_scr.atproc_lock = NULL;
memset(&g_root_scr.lock, 0, sizeof(g_root_scr.lock));
cons_init_bufs(&g_root_scr);
SHOW_CURSOR(&g_root_scr);
@@ -578,6 +645,9 @@ cons_expose(void)
return;
}
+ /* Init the attached proc mutex lock */
+ g_root_scr.atproc_lock = mutex_new("console0");
+
/* Register the device here */
major = dev_alloc_major();
dev = dev_alloc(major);
diff --git a/sys/include/dev/cons/cons.h b/sys/include/dev/cons/cons.h
index aa9d8e3..c82c3c5 100644
--- a/sys/include/dev/cons/cons.h
+++ b/sys/include/dev/cons/cons.h
@@ -32,6 +32,8 @@
#include <sys/types.h>
#include <sys/spinlock.h>
+#include <sys/proc.h>
+#include <sys/mutex.h>
#include <sys/console.h>
#include <dev/video/fbdev.h>
#include <dev/cons/consvar.h>
@@ -49,6 +51,8 @@ struct cons_screen {
struct fbdev fbdev;
struct ansi_state ansi_s;
struct console_feat feat; /* Features */
+ struct proc *atproc; /* Attached proc */
+ struct mutex *atproc_lock;
uint32_t fg;
uint32_t bg;
@@ -72,6 +76,8 @@ void cons_update_color(struct cons_screen *scr, uint32_t fg, uint32_t bg);
void cons_clear_scr(struct cons_screen *scr, uint32_t bg);
void cons_reset_color(struct cons_screen *scr);
void cons_reset_cursor(struct cons_screen *scr);
+int cons_attach(void);
+int cons_detach(void);
int cons_putch(struct cons_screen *scr, char c);
int cons_putstr(struct cons_screen *scr, const char *s, size_t len);
diff --git a/sys/kern/kern_sched.c b/sys/kern/kern_sched.c
index ec5592e..774ba71 100644
--- a/sys/kern/kern_sched.c
+++ b/sys/kern/kern_sched.c
@@ -34,6 +34,7 @@
#include <sys/param.h>
#include <sys/syslog.h>
#include <sys/atomic.h>
+#include <dev/cons/cons.h>
#include <machine/frame.h>
#include <machine/cpu.h>
#include <machine/cdefs.h>
@@ -221,6 +222,7 @@ sched_switch(struct trapframe *tf)
ci = this_cpu();
td = ci->curtd;
+ cons_detach();
if (td != NULL) {
if (td->pid == 0)