History

modules: add ro_after_init support

Add ro_after_init support for modules by adding a new page-aligned section in the module layout (after rodata) for ro_after_init data and enabling RO protection for that section after module init runs.

Jessica Yu committed 10 years ago

Commit 444d13f1 parent bdc9f374 files · +60 −15Browse files

Unified · Split

4 files
  1. include/linux/module.h +4 −2
  2. include/uapi/linux/elf.h +1 −0
  3. kernel/livepatch/core.c +1 −1
  4. kernel/module.c +54 −12
include/linux/module.h+4−2
@@ -298,6 +298,8 @@ struct module_layout { · 297 unmodified lines
298 unsigned int text_size;298 unsigned int text_size;
299 /* Size of RO section of the module (text+rodata) */299 /* Size of RO section of the module (text+rodata) */
300 unsigned int ro_size;300 unsigned int ro_size;
301 /* Size of RO after init section */
302 unsigned int ro_after_init_size;
301 303
302#ifdef CONFIG_MODULES_TREE_LOOKUP304#ifdef CONFIG_MODULES_TREE_LOOKUP
303 struct mod_tree_node mtn;305 struct mod_tree_node mtn;
@@ -765,12 +767,12 @@ extern int module_sysfs_initialized; · 461 unmodified lines
765#ifdef CONFIG_DEBUG_SET_MODULE_RONX767#ifdef CONFIG_DEBUG_SET_MODULE_RONX
766extern void set_all_modules_text_rw(void);768extern void set_all_modules_text_rw(void);
767extern void set_all_modules_text_ro(void);769extern void set_all_modules_text_ro(void);
768extern void module_enable_ro(const struct module *mod);770extern void module_enable_ro(const struct module *mod, bool after_init);
769extern void module_disable_ro(const struct module *mod);771extern void module_disable_ro(const struct module *mod);
770#else772#else
771static inline void set_all_modules_text_rw(void) { }773static inline void set_all_modules_text_rw(void) { }
772static inline void set_all_modules_text_ro(void) { }774static inline void set_all_modules_text_ro(void) { }
773static inline void module_enable_ro(const struct module *mod) { }775static inline void module_enable_ro(const struct module *mod, bool after_init) { }
774static inline void module_disable_ro(const struct module *mod) { }776static inline void module_disable_ro(const struct module *mod) { }
775#endif777#endif
776 778
include/uapi/linux/elf.h+1−0
@@ -286,6 +286,7 @@ typedef struct elf64_phdr { · 285 unmodified lines
286#define SHF_ALLOC 0x2286#define SHF_ALLOC 0x2
287#define SHF_EXECINSTR 0x4287#define SHF_EXECINSTR 0x4
288#define SHF_RELA_LIVEPATCH 0x00100000288#define SHF_RELA_LIVEPATCH 0x00100000
289#define SHF_RO_AFTER_INIT 0x00200000
289#define SHF_MASKPROC 0xf0000000290#define SHF_MASKPROC 0xf0000000
290 291
291/* special section indexes */292/* special section indexes */
kernel/livepatch/core.c+1−1
@@ -309,7 +309,7 @@ static int klp_write_object_relocations(struct module *pmod, · 308 unmodified lines
309 break;309 break;
310 }310 }
311 311
312 module_enable_ro(pmod);312 module_enable_ro(pmod, true);
313 return ret;313 return ret;
314}314}
315 315
kernel/module.c+54−12
@@ -1857,10 +1857,11 @@ static void mod_sysfs_teardown(struct module *mod) · 1856 unmodified lines
1857 * from modification and any data from execution.1857 * from modification and any data from execution.
1858 *1858 *
1859 * General layout of module is:1859 * General layout of module is:
1860 * [text] [read-only-data] [writable data]1860 * [text] [read-only-data] [ro-after-init] [writable data]
1861 * text_size -----^ ^ ^1861 * text_size -----^ ^ ^ ^
1862 * ro_size ------------------------| |1862 * ro_size ------------------------| | |
1863 * size -------------------------------------------|1863 * ro_after_init_size -----------------------------| |
1864 * size -----------------------------------------------------------|
1864 *1865 *
1865 * These values are always page-aligned (as is base)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 (layout->ro_size - layout->text_size) >> PAGE_SHIFT);1884 (layout->ro_size - layout->text_size) >> PAGE_SHIFT);
1884}1885}
1885 1886
1887static 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
1886static void frob_writable_data(const struct module_layout *layout,1897static void frob_writable_data(const struct module_layout *layout,
1887 int (*set_memory)(unsigned long start, int num_pages))1898 int (*set_memory)(unsigned long start, int num_pages))
1888{1899{
1889 BUG_ON((unsigned long)layout->base & (PAGE_SIZE-1));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 BUG_ON((unsigned long)layout->size & (PAGE_SIZE-1));1902 BUG_ON((unsigned long)layout->size & (PAGE_SIZE-1));
1892 set_memory((unsigned long)layout->base + layout->ro_size,1903 set_memory((unsigned long)layout->base + layout->ro_after_init_size,
1893 (layout->size - layout->ro_size) >> PAGE_SHIFT);1904 (layout->size - layout->ro_after_init_size) >> PAGE_SHIFT);
1894}1905}
1895 1906
1896/* livepatching wants to disable read-only so it can frob module. */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 frob_text(&mod->core_layout, set_memory_rw);1910 frob_text(&mod->core_layout, set_memory_rw);
1900 frob_rodata(&mod->core_layout, set_memory_rw);1911 frob_rodata(&mod->core_layout, set_memory_rw);
1912 frob_ro_after_init(&mod->core_layout, set_memory_rw);
1901 frob_text(&mod->init_layout, set_memory_rw);1913 frob_text(&mod->init_layout, set_memory_rw);
1902 frob_rodata(&mod->init_layout, set_memory_rw);1914 frob_rodata(&mod->init_layout, set_memory_rw);
1903}1915}
1904 1916
1905void module_enable_ro(const struct module *mod)1917void module_enable_ro(const struct module *mod, bool after_init)
1906{1918{
1907 frob_text(&mod->core_layout, set_memory_ro);1919 frob_text(&mod->core_layout, set_memory_ro);
1908 frob_rodata(&mod->core_layout, set_memory_ro);1920 frob_rodata(&mod->core_layout, set_memory_ro);
1909 frob_text(&mod->init_layout, set_memory_ro);1921 frob_text(&mod->init_layout, set_memory_ro);
1910 frob_rodata(&mod->init_layout, set_memory_ro);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
1913static void module_enable_nx(const struct module *mod)1928static void module_enable_nx(const struct module *mod)
1914{1929{
1915 frob_rodata(&mod->core_layout, set_memory_nx);1930 frob_rodata(&mod->core_layout, set_memory_nx);
1931 frob_ro_after_init(&mod->core_layout, set_memory_nx);
1916 frob_writable_data(&mod->core_layout, set_memory_nx);1932 frob_writable_data(&mod->core_layout, set_memory_nx);
1917 frob_rodata(&mod->init_layout, set_memory_nx);1933 frob_rodata(&mod->init_layout, set_memory_nx);
1918 frob_writable_data(&mod->init_layout, set_memory_nx);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
1921static void module_disable_nx(const struct module *mod)1937static void module_disable_nx(const struct module *mod)
1922{1938{
1923 frob_rodata(&mod->core_layout, set_memory_x);1939 frob_rodata(&mod->core_layout, set_memory_x);
1940 frob_ro_after_init(&mod->core_layout, set_memory_x);
1924 frob_writable_data(&mod->core_layout, set_memory_x);1941 frob_writable_data(&mod->core_layout, set_memory_x);
1925 frob_rodata(&mod->init_layout, set_memory_x);1942 frob_rodata(&mod->init_layout, set_memory_x);
1926 frob_writable_data(&mod->init_layout, set_memory_x);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 frob_text(layout, set_memory_rw);1980 frob_text(layout, set_memory_rw);
1964 frob_rodata(layout, set_memory_rw);1981 frob_rodata(layout, set_memory_rw);
1965 frob_rodata(layout, set_memory_x);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 frob_writable_data(layout, set_memory_x);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 * finder in the two loops below */2324 * finder in the two loops below */
2306 { SHF_EXECINSTR | SHF_ALLOC, ARCH_SHF_SMALL },2325 { SHF_EXECINSTR | SHF_ALLOC, ARCH_SHF_SMALL },
2307 { SHF_ALLOC, SHF_WRITE | ARCH_SHF_SMALL },2326 { SHF_ALLOC, SHF_WRITE | ARCH_SHF_SMALL },
2327 { SHF_RO_AFTER_INIT | SHF_ALLOC, ARCH_SHF_SMALL },
2308 { SHF_WRITE | SHF_ALLOC, ARCH_SHF_SMALL },2328 { SHF_WRITE | SHF_ALLOC, ARCH_SHF_SMALL },
2309 { ARCH_SHF_SMALL | SHF_ALLOC, 0 }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 mod->core_layout.size = debug_align(mod->core_layout.size);2356 mod->core_layout.size = debug_align(mod->core_layout.size);
2337 mod->core_layout.ro_size = mod->core_layout.size;2357 mod->core_layout.ro_size = mod->core_layout.size;
2338 break;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 mod->core_layout.size = debug_align(mod->core_layout.size);2364 mod->core_layout.size = debug_align(mod->core_layout.size);
2341 break;2365 break;
2342 }2366 }
@@ -2366,7 +2390,14 @@ static void layout_sections(struct module *mod, struct load_info *info) · 23 unmodified lines
2366 mod->init_layout.size = debug_align(mod->init_layout.size);2390 mod->init_layout.size = debug_align(mod->init_layout.size);
2367 mod->init_layout.ro_size = mod->init_layout.size;2391 mod->init_layout.ro_size = mod->init_layout.size;
2368 break;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 mod->init_layout.size = debug_align(mod->init_layout.size);2401 mod->init_layout.size = debug_align(mod->init_layout.size);
2371 break;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 /* Module within temporary copy. */3225 /* Module within temporary copy. */
3195 struct module *mod;3226 struct module *mod;
3227 unsigned int ndx;
3196 int err;3228 int err;
3197 3229
3198 mod = setup_load_info(info, flags);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 /* We will do a special allocation for per-cpu sections later. */3247 /* We will do a special allocation for per-cpu sections later. */
3216 info->sechdrs[info->index.pcpu].sh_flags &= ~(unsigned long)SHF_ALLOC;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 /* Determine total sizes, and put offsets in sh_entsize. For now3259 /* Determine total sizes, and put offsets in sh_entsize. For now
3219 this is done generically; there doesn't appear to be any3260 this is done generically; there doesn't appear to be any
3220 special cases for the architectures. */3261 special cases for the architectures. */
@@ -3381,12 +3422,14 @@ static noinline int do_init_module(struct module *mod) · 160 unmodified lines
3381 /* Switch to core kallsyms now init is done: kallsyms may be walking! */3422 /* Switch to core kallsyms now init is done: kallsyms may be walking! */
3382 rcu_assign_pointer(mod->kallsyms, &mod->core_kallsyms);3423 rcu_assign_pointer(mod->kallsyms, &mod->core_kallsyms);
3383#endif3424#endif
3425 module_enable_ro(mod, true);
3384 mod_tree_remove_init(mod);3426 mod_tree_remove_init(mod);
3385 disable_ro_nx(&mod->init_layout);3427 disable_ro_nx(&mod->init_layout);
3386 module_arch_freeing_init(mod);3428 module_arch_freeing_init(mod);
3387 mod->init_layout.base = NULL;3429 mod->init_layout.base = NULL;
3388 mod->init_layout.size = 0;3430 mod->init_layout.size = 0;
3389 mod->init_layout.ro_size = 0;3431 mod->init_layout.ro_size = 0;
3432 mod->init_layout.ro_after_init_size = 0;
3390 mod->init_layout.text_size = 0;3433 mod->init_layout.text_size = 0;
3391 /*3434 /*
3392 * We want to free module_init, but be aware that kallsyms may be3435 * 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 /* This relies on module_mutex for list integrity. */3521 /* This relies on module_mutex for list integrity. */
3479 module_bug_finalize(info->hdr, info->sechdrs, mod);3522 module_bug_finalize(info->hdr, info->sechdrs, mod);
3480 3523
3481 /* Set RO and NX regions */3524 module_enable_ro(mod, false);
3482 module_enable_ro(mod);
3483 module_enable_nx(mod);3525 module_enable_nx(mod);
3484 3526
3485 /* Mark state as coming so strong_try_module_get() ignores us,3527 /* Mark state as coming so strong_try_module_get() ignores us,