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
|
|
@ -591,7 +591,7 @@ extern unsigned long kpi_strnlen(const char *s, unsigned long max);
|
|||
extern long kpi_sized_strscpy(char *d, const char *s, unsigned long n);
|
||||
extern void kpi_memcpy_fromio(void *d, const void *s, unsigned long n);
|
||||
extern void kpi_memcpy_toio(void *d, const void *s, unsigned long n);
|
||||
extern void kpi_fortify_panic(void);
|
||||
extern void kpi_fortify_panic(unsigned int, unsigned long, unsigned long);
|
||||
|
||||
const struct kpi_sym kpi_table[] = {
|
||||
// PCI
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ extern struct kpi_ctx kpi;
|
|||
struct kpi_layout {
|
||||
unsigned int nd_netdev_ops;
|
||||
unsigned int nd_dev_addr, nd_perm_addr, nd_addr_len;
|
||||
unsigned int nd_priv_len; // 0 when this kernel has none (before 6.17)
|
||||
unsigned int nd_mc, nd_uc;
|
||||
unsigned int nd_tx, nd_num_tx, nd_real_num_tx;
|
||||
unsigned int nq_size, nq_dev;
|
||||
|
|
|
|||
|
|
@ -79,6 +79,15 @@ kpi_alloc_etherdev_mqs(int priv, unsigned int txqs, unsigned int rxqs)
|
|||
kpi_log("kpi: no net_device.dev_addr offset -- the driver will fault\n");
|
||||
}
|
||||
|
||||
// How big the private area is, which a driver's own bounds checks read:
|
||||
// netdev_priv() is `dev->priv`, a flexible array counted by `priv_len`, so
|
||||
// fortify sees the area as exactly that long. Zero, as left by mmap, made
|
||||
// r8169's memset of its descriptor-ring bookkeeping -- tp->tx_skb, 4K at
|
||||
// offset 0xa48 -- look like writing past the end of nothing, and it called
|
||||
// __fortify_panic in rtl_open.
|
||||
if (kpi_l.nd_priv_len)
|
||||
*(unsigned int *)((unsigned char *)p + kpi_l.nd_priv_len) = (unsigned int)priv;
|
||||
|
||||
// The address lists have to be *empty*, not zeroed.
|
||||
//
|
||||
// A Linux list_head is empty when it points at itself; zeroed means a null
|
||||
|
|
|
|||
|
|
@ -136,10 +136,19 @@ kpi_memcpy_toio(void *dst, const void *s, unsigned long n)
|
|||
// they detect an overflow. Reaching it means the driver found a bug in itself,
|
||||
// and the honest thing is to say so rather than return.
|
||||
void
|
||||
kpi_fortify_panic(void)
|
||||
kpi_fortify_panic(unsigned int reason, unsigned long avail, unsigned long size)
|
||||
{
|
||||
kpi_log("kpi: the driver called __fortify_panic -- it detected an "
|
||||
"overflow in itself\n");
|
||||
// Which check, how much it thought it had, how much it wanted, and where
|
||||
// from -- the address is in the driver's own text, so subtract the load
|
||||
// address logged for it and look the offset up with nm. This took a
|
||||
// hardware round trip to find the last time it said nothing.
|
||||
kpi_log(" reason "); kpi_lognum(reason);
|
||||
kpi_log(", available "); kpi_lognum((long long)avail);
|
||||
kpi_log(", wanted "); kpi_lognum((long long)size);
|
||||
kpi_log(", from 0x"); kpi_loghex((unsigned long)__builtin_return_address(0), 16);
|
||||
kpi_log("\n");
|
||||
for (;;)
|
||||
;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue