A canary for timer-expiration functions
A canary for timer-expiration functions
Posted Aug 20, 2017 10:16 UTC (Sun) by jzbiciak (guest, #5246)In reply to: A canary for timer-expiration functions by Sesse
Parent article: A canary for timer-expiration functions
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.