diff options
author | Ian Moffett <ian@osmora.org> | 2025-07-07 02:17:23 +0000 |
---|---|---|
committer | Ian Moffett <ian@osmora.org> | 2025-07-07 02:33:53 +0000 |
commit | 7f7535710b23ec984f1f0fa3dab8ea4a081a0bab (patch) | |
tree | 7236dfd38c406e5b9ad1e99ed3e6cb6c01895dff /sys/dev/cons | |
parent | 4a004fd4eb1f6d7616e38b1ccb0ec0bf8346d204 (diff) |
kernel: cons: Introduce /ctl/console/attr
In a lot of existing systems, ANSI escape sequences are used to
control console attributes such as cursor position, style, etc. However,
too many sequences for too many things are implemented at once. If a
program has neglected to properly sanitize input coming in (e.g., from a
network). Stray sequences may be injected into the receiving console.
One may disable the ANSI state machine using the 'ansi_esc' bit within
/ctl/console/feat, completely eradicating such issues, while being able
to still control various console attributes through /ctl/console/attr.
This commit also keeps the builtin ANSI escape sequence parser as simple
as possible.
Signed-off-by: Ian Moffett <ian@osmora.org>
Diffstat (limited to 'sys/dev/cons')
-rw-r--r-- | sys/dev/cons/cons.c | 66 |
1 files changed, 65 insertions, 1 deletions
diff --git a/sys/dev/cons/cons.c b/sys/dev/cons/cons.c index 9921ff8..5a59e3d 100644 --- a/sys/dev/cons/cons.c +++ b/sys/dev/cons/cons.c @@ -64,6 +64,7 @@ struct cons_screen g_root_scr = {0}; static struct cdevsw cons_cdevsw; static struct ctlops cons_feat_ctl; +static struct ctlops cons_attr_ctl; static void cons_draw_cursor(struct cons_screen *scr, uint32_t color); static int cons_handle_special(struct cons_screen *scr, char c); @@ -469,6 +470,57 @@ ctl_feat_write(struct ctlfs_dev *cdp, struct sio_txn *sio) return sio->len; } +static int +ctl_attr_read(struct ctlfs_dev *cdp, struct sio_txn *sio) +{ + struct cons_screen *scr = &g_root_scr; + struct console_attr *attrp; + + if (sio->buf == NULL || sio->len == 0) { + return -EINVAL; + } + + attrp = &scr->attr; + if (sio->len > sizeof(*attrp)) { + sio->len = sizeof(*attrp); + } + + memcpy(sio->buf, attrp, sio->len); + return sio->len; +} + +static int +ctl_attr_write(struct ctlfs_dev *cdp, struct sio_txn *sio) +{ + struct cons_screen *scr = &g_root_scr; + struct console_attr *attrp; + + attrp = &scr->attr; + if (sio->len > sizeof(*attrp)) { + sio->len = sizeof(*attrp); + } + + memcpy(attrp, sio->buf, sio->len); + spinlock_acquire(&scr->lock); + + /* Clip the x/y positions */ + if (attrp->cursor_x >= scr->ncols) + attrp->cursor_x = scr->ncols - 1; + if (attrp->cursor_y >= scr->nrows) + attrp->cursor_y = scr->nrows - 1; + + /* Update cursor */ + HIDE_CURSOR(scr); + scr->curs_col = attrp->cursor_x; + scr->curs_row = attrp->cursor_y; + scr->ch_col = attrp->cursor_x; + scr->ch_row = attrp->cursor_y; + SHOW_CURSOR(scr); + + spinlock_release(&scr->lock); + return sio->len; +} + /* * Detach the currently running process from the * console. @@ -654,12 +706,19 @@ cons_expose(void) dev_register(major, dev, &cons_cdevsw); devfs_create_entry(devname, major, dev, 0444); - /* Register the control file */ + /* Register feat ctl */ ctl.mode = 0666; ctlfs_create_node(devname, &ctl); ctl.devname = devname; ctl.ops = &cons_feat_ctl; ctlfs_create_entry("feat", &ctl); + + /* Register attr ctl */ + ctl.mode = 0666; + ctlfs_create_node(devname, &ctl); + ctl.devname = devname; + ctl.ops = &cons_attr_ctl; + ctlfs_create_entry("attr", &ctl); once ^= 1; } @@ -672,3 +731,8 @@ static struct ctlops cons_feat_ctl = { .read = ctl_feat_read, .write = ctl_feat_write }; + +static struct ctlops cons_attr_ctl = { + .read = ctl_attr_read, + .write = ctl_attr_write +}; |