diff options
author | Ian Moffett <ian@osmora.org> | 2025-07-03 19:59:45 -0400 |
---|---|---|
committer | Ian Moffett <ian@osmora.org> | 2025-07-03 19:59:45 -0400 |
commit | 23a8e1b78063c0276d987e835434700267b9c8f8 (patch) | |
tree | 19886b291f9c56fb2c90068aece37aee991cca79 /sys/dev | |
parent | 9c7fcf89f9ec234dd55ace2c48f4fcc84069c5ac (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')
-rw-r--r-- | sys/dev/cons/cons.c | 70 |
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); |