| @@ -1857,10 +1857,11 @@ static void mod_sysfs_teardown(struct module *mod) · 1856 unmodified lines |
| 1857 | 1857 | * from modification and any data from execution. |
| 1858 | 1858 | * |
| 1859 | 1859 | * General layout of module is: |
| 1860 | | − * [text] [read-only-data] [writable data] |
| 1861 | | − * text_size -----^ ^ ^ |
| 1862 | | − * ro_size ------------------------| | |
| 1863 | | − * size -------------------------------------------| |
| 1860 | + * [text] [read-only-data] [ro-after-init] [writable data] |
| 1861 | + * text_size -----^ ^ ^ ^ |
| 1862 | + * ro_size ------------------------| | | |
| 1863 | + * ro_after_init_size -----------------------------| | |
| 1864 | + * size -----------------------------------------------------------| |
| 1864 | 1865 | * |
| 1865 | 1866 | * These values are always page-aligned (as is base) |
| 1866 | 1867 | */ |
| @@ -1883,14 +1884,24 @@ static void frob_rodata(const struct module_layout *layout, · 16 unmodified lines |
| 1883 | 1884 | (layout->ro_size - layout->text_size) >> PAGE_SHIFT); |
| 1884 | 1885 | } |
| 1885 | 1886 | |
| 1887 | +static void frob_ro_after_init(const struct module_layout *layout, |
| 1888 | + int (*set_memory)(unsigned long start, int num_pages)) |
| 1889 | +{ |
| 1890 | + BUG_ON((unsigned long)layout->base & (PAGE_SIZE-1)); |
| 1891 | + BUG_ON((unsigned long)layout->ro_size & (PAGE_SIZE-1)); |
| 1892 | + BUG_ON((unsigned long)layout->ro_after_init_size & (PAGE_SIZE-1)); |
| 1893 | + set_memory((unsigned long)layout->base + layout->ro_size, |
| 1894 | + (layout->ro_after_init_size - layout->ro_size) >> PAGE_SHIFT); |
| 1895 | +} |
| 1896 | + |
| 1886 | 1897 | static void frob_writable_data(const struct module_layout *layout, |
| 1887 | 1898 | int (*set_memory)(unsigned long start, int num_pages)) |
| 1888 | 1899 | { |
| 1889 | 1900 | BUG_ON((unsigned long)layout->base & (PAGE_SIZE-1)); |
| 1890 | | − BUG_ON((unsigned long)layout->ro_size & (PAGE_SIZE-1)); |
| 1901 | + BUG_ON((unsigned long)layout->ro_after_init_size & (PAGE_SIZE-1)); |
| 1891 | 1902 | BUG_ON((unsigned long)layout->size & (PAGE_SIZE-1)); |
| 1892 | | − set_memory((unsigned long)layout->base + layout->ro_size, |
| 1893 | | − (layout->size - layout->ro_size) >> PAGE_SHIFT); |
| 1903 | + set_memory((unsigned long)layout->base + layout->ro_after_init_size, |
| 1904 | + (layout->size - layout->ro_after_init_size) >> PAGE_SHIFT); |
| 1894 | 1905 | } |
| 1895 | 1906 | |
| 1896 | 1907 | /* livepatching wants to disable read-only so it can frob module. */ |
| @@ -1898,21 +1909,26 @@ void module_disable_ro(const struct module *mod) · 1 unmodified line |
| 1898 | 1909 | { |
| 1899 | 1910 | frob_text(&mod->core_layout, set_memory_rw); |
| 1900 | 1911 | frob_rodata(&mod->core_layout, set_memory_rw); |
| 1912 | + frob_ro_after_init(&mod->core_layout, set_memory_rw); |
| 1901 | 1913 | frob_text(&mod->init_layout, set_memory_rw); |
| 1902 | 1914 | frob_rodata(&mod->init_layout, set_memory_rw); |
| 1903 | 1915 | } |
| 1904 | 1916 | |
| 1905 | | −void module_enable_ro(const struct module *mod) |
| 1917 | +void module_enable_ro(const struct module *mod, bool after_init) |
| 1906 | 1918 | { |
| 1907 | 1919 | frob_text(&mod->core_layout, set_memory_ro); |
| 1908 | 1920 | frob_rodata(&mod->core_layout, set_memory_ro); |
| 1909 | 1921 | frob_text(&mod->init_layout, set_memory_ro); |
| 1910 | 1922 | frob_rodata(&mod->init_layout, set_memory_ro); |
| 1923 | + |
| 1924 | + if (after_init) |
| 1925 | + frob_ro_after_init(&mod->core_layout, set_memory_ro); |
| 1911 | 1926 | } |
| 1912 | 1927 | |
| 1913 | 1928 | static void module_enable_nx(const struct module *mod) |
| 1914 | 1929 | { |
| 1915 | 1930 | frob_rodata(&mod->core_layout, set_memory_nx); |
| 1931 | + frob_ro_after_init(&mod->core_layout, set_memory_nx); |
| 1916 | 1932 | frob_writable_data(&mod->core_layout, set_memory_nx); |
| 1917 | 1933 | frob_rodata(&mod->init_layout, set_memory_nx); |
| 1918 | 1934 | frob_writable_data(&mod->init_layout, set_memory_nx); |
| @@ -1921,6 +1937,7 @@ static void module_enable_nx(const struct module *mod) · 2 unmodified lines |
| 1921 | 1937 | static void module_disable_nx(const struct module *mod) |
| 1922 | 1938 | { |
| 1923 | 1939 | frob_rodata(&mod->core_layout, set_memory_x); |
| 1940 | + frob_ro_after_init(&mod->core_layout, set_memory_x); |
| 1924 | 1941 | frob_writable_data(&mod->core_layout, set_memory_x); |
| 1925 | 1942 | frob_rodata(&mod->init_layout, set_memory_x); |
| 1926 | 1943 | frob_writable_data(&mod->init_layout, set_memory_x); |
| @@ -1963,6 +1980,8 @@ static void disable_ro_nx(const struct module_layout *layout) · 36 unmodified lines |
| 1963 | 1980 | frob_text(layout, set_memory_rw); |
| 1964 | 1981 | frob_rodata(layout, set_memory_rw); |
| 1965 | 1982 | frob_rodata(layout, set_memory_x); |
| 1983 | + frob_ro_after_init(layout, set_memory_rw); |
| 1984 | + frob_ro_after_init(layout, set_memory_x); |
| 1966 | 1985 | frob_writable_data(layout, set_memory_x); |
| 1967 | 1986 | } |
| 1968 | 1987 | |
| @@ -2305,6 +2324,7 @@ static void layout_sections(struct module *mod, struct load_info *info) · 336 unmodified lines |
| 2305 | 2324 | * finder in the two loops below */ |
| 2306 | 2325 | { SHF_EXECINSTR | SHF_ALLOC, ARCH_SHF_SMALL }, |
| 2307 | 2326 | { SHF_ALLOC, SHF_WRITE | ARCH_SHF_SMALL }, |
| 2327 | + { SHF_RO_AFTER_INIT | SHF_ALLOC, ARCH_SHF_SMALL }, |
| 2308 | 2328 | { SHF_WRITE | SHF_ALLOC, ARCH_SHF_SMALL }, |
| 2309 | 2329 | { ARCH_SHF_SMALL | SHF_ALLOC, 0 } |
| 2310 | 2330 | }; |
| @@ -2336,7 +2356,11 @@ static void layout_sections(struct module *mod, struct load_info *info) · 25 unmodified lines |
| 2336 | 2356 | mod->core_layout.size = debug_align(mod->core_layout.size); |
| 2337 | 2357 | mod->core_layout.ro_size = mod->core_layout.size; |
| 2338 | 2358 | break; |
| 2339 | | − case 3: /* whole core */ |
| 2359 | + case 2: /* RO after init */ |
| 2360 | + mod->core_layout.size = debug_align(mod->core_layout.size); |
| 2361 | + mod->core_layout.ro_after_init_size = mod->core_layout.size; |
| 2362 | + break; |
| 2363 | + case 4: /* whole core */ |
| 2340 | 2364 | mod->core_layout.size = debug_align(mod->core_layout.size); |
| 2341 | 2365 | break; |
| 2342 | 2366 | } |
| @@ -2366,7 +2390,14 @@ static void layout_sections(struct module *mod, struct load_info *info) · 23 unmodified lines |
| 2366 | 2390 | mod->init_layout.size = debug_align(mod->init_layout.size); |
| 2367 | 2391 | mod->init_layout.ro_size = mod->init_layout.size; |
| 2368 | 2392 | break; |
| 2369 | | − case 3: /* whole init */ |
| 2393 | + case 2: |
| 2394 | + /* |
| 2395 | + * RO after init doesn't apply to init_layout (only |
| 2396 | + * core_layout), so it just takes the value of ro_size. |
| 2397 | + */ |
| 2398 | + mod->init_layout.ro_after_init_size = mod->init_layout.ro_size; |
| 2399 | + break; |
| 2400 | + case 4: /* whole init */ |
| 2370 | 2401 | mod->init_layout.size = debug_align(mod->init_layout.size); |
| 2371 | 2402 | break; |
| 2372 | 2403 | } |
| @@ -3193,6 +3224,7 @@ static struct module *layout_and_allocate(struct load_info *info, int flags) · 820 unmodified lines |
| 3193 | 3224 | { |
| 3194 | 3225 | /* Module within temporary copy. */ |
| 3195 | 3226 | struct module *mod; |
| 3227 | + unsigned int ndx; |
| 3196 | 3228 | int err; |
| 3197 | 3229 | |
| 3198 | 3230 | mod = setup_load_info(info, flags); |
| @@ -3215,6 +3247,15 @@ static struct module *layout_and_allocate(struct load_info *info, int flags) · 16 unmodified lines |
| 3215 | 3247 | /* We will do a special allocation for per-cpu sections later. */ |
| 3216 | 3248 | info->sechdrs[info->index.pcpu].sh_flags &= ~(unsigned long)SHF_ALLOC; |
| 3217 | 3249 | |
| 3250 | + /* |
| 3251 | + * Mark ro_after_init section with SHF_RO_AFTER_INIT so that |
| 3252 | + * layout_sections() can put it in the right place. |
| 3253 | + * Note: ro_after_init sections also have SHF_{WRITE,ALLOC} set. |
| 3254 | + */ |
| 3255 | + ndx = find_sec(info, ".data..ro_after_init"); |
| 3256 | + if (ndx) |
| 3257 | + info->sechdrs[ndx].sh_flags |= SHF_RO_AFTER_INIT; |
| 3258 | + |
| 3218 | 3259 | /* Determine total sizes, and put offsets in sh_entsize. For now |
| 3219 | 3260 | this is done generically; there doesn't appear to be any |
| 3220 | 3261 | special cases for the architectures. */ |
| @@ -3381,12 +3422,14 @@ static noinline int do_init_module(struct module *mod) · 160 unmodified lines |
| 3381 | 3422 | /* Switch to core kallsyms now init is done: kallsyms may be walking! */ |
| 3382 | 3423 | rcu_assign_pointer(mod->kallsyms, &mod->core_kallsyms); |
| 3383 | 3424 | #endif |
| 3425 | + module_enable_ro(mod, true); |
| 3384 | 3426 | mod_tree_remove_init(mod); |
| 3385 | 3427 | disable_ro_nx(&mod->init_layout); |
| 3386 | 3428 | module_arch_freeing_init(mod); |
| 3387 | 3429 | mod->init_layout.base = NULL; |
| 3388 | 3430 | mod->init_layout.size = 0; |
| 3389 | 3431 | mod->init_layout.ro_size = 0; |
| 3432 | + mod->init_layout.ro_after_init_size = 0; |
| 3390 | 3433 | mod->init_layout.text_size = 0; |
| 3391 | 3434 | /* |
| 3392 | 3435 | * We want to free module_init, but be aware that kallsyms may be |
| @@ -3478,8 +3521,7 @@ static int complete_formation(struct module *mod, struct load_info *info) · 85 unmodified lines |
| 3478 | 3521 | /* This relies on module_mutex for list integrity. */ |
| 3479 | 3522 | module_bug_finalize(info->hdr, info->sechdrs, mod); |
| 3480 | 3523 | |
| 3481 | | − /* Set RO and NX regions */ |
| 3482 | | − module_enable_ro(mod); |
| 3524 | + module_enable_ro(mod, false); |
| 3483 | 3525 | module_enable_nx(mod); |
| 3484 | 3526 | |
| 3485 | 3527 | /* Mark state as coming so strong_try_module_get() ignores us, |