[go: up one dir, main page]

|
|
Log in / Subscribe / Register

A canary for timer-expiration functions

A canary for timer-expiration functions

Posted Aug 20, 2017 9:53 UTC (Sun) by Sesse (subscriber, #53779)
In reply to: A canary for timer-expiration functions by jzbiciak
Parent article: A canary for timer-expiration functions

No, my question is; how can you make sure a good out-of-tree module can register a timer in such a scheme? That won't work if the tables are locked and live in read-only memory.


to post comments

A canary for timer-expiration functions

Posted Aug 20, 2017 10:16 UTC (Sun) by jzbiciak (guest, #5246) [Link]

I'm saying that each module provides its own table in an rodata type of section that can be mapped read-only. The only dynamic run-time bit, then, is a module ID, which indexes a writable table of pointers to read-only tables of function pointers. All of the tables of function pointers at least are read-only.

Something like this very rough sketch:

/* This part lives in the kernel */
void *const kernel_fxn_ptrs[] = { ... };  /* this is read-only */
void *const *module_fxn_table_ptrs[MAX_MODULES];  /* this is read-write */

/* This part lives in each module */
void *const module_fxn_ptrs[] = { ... }; /* this is read-only */

Now, since module_fxn_table_ptrs only needs modification at module load time, you could imagine spending the cost of establishing a writeable mapping to it during module load, and then discarding that writeable mapping once the module's table is registered. That means you'd only have read-only tables for these function pointers under normal circumstances, with a small window during module load where a writeable mapping exists.

Of course, that idea assumes we don't have a full MMU to work with (as was the case on that embedded processor). We do have a full MMU at our disposal.

So here's an even better idea that keeps every table read-only the entire time. Put the function pointer tables in their own dedicated multiple-of-the-page sized section. Let's call it .rodata.fxn_ptr. The kernel maps its own .rodata.fxn_ptr read-only at some virtual address determined at runtime (ASLR). As modules get loaded, map their .rodata.fxn_ptr pages directly after the kernel's, also read-only. The module ID now just becomes "how many pages to skip to get to the start of my module's table." That also removes the indirection. When a module gets unloaded, unmap its table.

Now, you do have a new resource to manage. But, if you force everyone into no more than, say, 8K, that still gives you 1024 entry points on a 64-bit machine.


Copyright © 2026, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds