summaryrefslogtreecommitdiff
path: root/sys/dev/cons
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 /sys/dev/cons
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>
Diffstat (limited to 'sys/dev/cons')
-rw-r--r--sys/dev/cons/cons.c70
1 files changed, 70 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);