A text cursor in the tty; LDLS sets net_device.priv_len
The virtual terminals never drew a cursor. Each now paints a steady block (the cell with its colours swapped), erased before and redrawn after every output byte, redrawn by a repaint, and hidden by ESC [ ? 25 l as curses programs ask. r8169 under LDLS on the TUF A15 got through probe and died in ndo_open on __fortify_panic. netdev_priv() is `dev->priv` now, a flexible array counted by net_device.priv_len, and rtl_open's memset of its ring bookkeeping is bounds-checked against it. The allocator left priv_len zero, so the driver saw an area of no bytes. It is set from BTF when the kernel has the member. __fortify_panic also says which check, how many bytes it had and wanted, and where from. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015f73FesGZGYPkmDvUcj6QX
This commit is contained in:
parent
a9d2e14004
commit
96389ada8f
7 changed files with 86 additions and 5 deletions
|
|
@ -235,11 +235,46 @@ vt_current(void)
|
|||
// Output
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// The text cursor. See struct vt. Drawn as the cell with its colours swapped
|
||||
// -- relative to what the cell would show, so a cursor on reverse-video text
|
||||
// is the plain text and every cursor on screen is visible against its cell.
|
||||
static void
|
||||
cursor_erase(struct vt *v)
|
||||
{
|
||||
if (!v->curs_drawn)
|
||||
return;
|
||||
v->curs_drawn = 0;
|
||||
if (v->curs_x < v->cols && v->curs_y < v->rows)
|
||||
show(v, v->curs_x, v->curs_y);
|
||||
}
|
||||
|
||||
static void
|
||||
cursor_draw(struct vt *v)
|
||||
{
|
||||
if (v->curs_hidden || !is_active(v))
|
||||
return;
|
||||
// A glyph in the last column leaves the cursor *on* it with the wrap
|
||||
// pending, and that is where it is drawn.
|
||||
int col = v->cx >= v->cols ? v->cols - 1 : v->cx;
|
||||
int row = v->cy >= v->rows ? v->rows - 1 : v->cy;
|
||||
if (col < 0 || row < 0)
|
||||
return;
|
||||
struct vtcell *k = cell_at(v, col, row);
|
||||
if (k->attr & VT_ATTR_REVERSE)
|
||||
gfx_draw_cell(col, row, k->ch, vt_rgb(k->fg), vt_rgb(k->bg));
|
||||
else
|
||||
gfx_draw_cell(col, row, k->ch, vt_rgb(k->bg), vt_rgb(k->fg));
|
||||
v->curs_x = col;
|
||||
v->curs_y = row;
|
||||
v->curs_drawn = 1;
|
||||
}
|
||||
|
||||
void
|
||||
vt_repaint(struct vt *v)
|
||||
{
|
||||
if (!is_active(v))
|
||||
return;
|
||||
v->curs_drawn = 0; // the repaint below paints over it
|
||||
|
||||
// The margins first: the screen is rarely a whole number of cells, and the
|
||||
// strip right of the last column and below the last row belongs to nobody.
|
||||
|
|
@ -263,6 +298,7 @@ vt_repaint(struct vt *v)
|
|||
else
|
||||
gfx_draw_cell(c, r, k->ch, vt_rgb(k->fg), vt_rgb(k->bg));
|
||||
}
|
||||
cursor_draw(v);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -906,7 +942,7 @@ vt_feed_1(struct vt *v, int c)
|
|||
switch (v->esc_state) {
|
||||
case VE_ESC:
|
||||
if (c == '[') { v->esc_state = VE_CSI;
|
||||
v->esc_nparm = 0; v->esc_private = 0;
|
||||
v->esc_nparm = 0; v->esc_private = 0; v->esc_qmark = 0;
|
||||
for (int i = 0; i < VT_MAXPARM; i++) v->esc_parm[i] = 0;
|
||||
return; }
|
||||
if (c == ']') { v->esc_state = VE_OSC; return; }
|
||||
|
|
@ -962,7 +998,11 @@ vt_feed_1(struct vt *v, int c)
|
|||
// this terminal does not speak, but must still consume to the final byte.
|
||||
// Ending at the marker instead printed the rest -- tmux asking for
|
||||
// extended keys as ESC [ > 4 ; 1 m left "4;1m" on the screen.
|
||||
if (c >= '<' && c <= '?') { v->esc_private = 1; return; }
|
||||
if (c >= '<' && c <= '?') {
|
||||
v->esc_private = 1;
|
||||
if (c == '?') v->esc_qmark = 1;
|
||||
return;
|
||||
}
|
||||
if (c >= 0x20 && c <= 0x2F) { v->esc_private = 1; return; }
|
||||
if (c >= '0' && c <= '9') {
|
||||
if (v->esc_nparm == 0) v->esc_nparm = 1;
|
||||
|
|
@ -975,8 +1015,15 @@ vt_feed_1(struct vt *v, int c)
|
|||
return;
|
||||
}
|
||||
v->esc_state = VE_NORMAL;
|
||||
if (!v->esc_private)
|
||||
if (!v->esc_private) {
|
||||
vt_csi(v, c);
|
||||
} else if (v->esc_qmark && (c == 'h' || c == 'l')) {
|
||||
// DECSET/DECRST. Only the cursor's visibility is ours; the rest of
|
||||
// ?1049 and its kin are still ignored, as before.
|
||||
for (int i = 0; i < v->esc_nparm && i < VT_MAXPARM; i++)
|
||||
if (v->esc_parm[i] == 25)
|
||||
v->curs_hidden = (c == 'l');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1194,5 +1241,7 @@ vt_cycle(int dir)
|
|||
void
|
||||
vt_feed(struct vt *v, int c)
|
||||
{
|
||||
cursor_erase(v);
|
||||
vt_feed_1(v, c);
|
||||
cursor_draw(v);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue