Changeset 18858


Ignore:
Timestamp:
2009-12-20T05:41:10+01:00 (8 years ago)
Author:
nbd
Message:

kernel: fix plt fixup related crashes when loading kernel modules on mips, (happened when there was not enough physically contiguous memory available)

Location:
trunk/target/linux/generic-2.6
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/target/linux/generic-2.6/patches-2.6.30/027-mips_module_reloc.patch

    r17268 r18858  
    1717        const struct exception_table_entry *dbe_end; 
    1818+ 
    19 +       void *plt_tbl; 
    20 +       unsigned int core_plt_offset; 
    21 +       unsigned int core_plt_size; 
    22 +       unsigned int init_plt_offset; 
     19+       void *phys_plt_tbl; 
     20+       void *virt_plt_tbl; 
     21+       unsigned int phys_plt_offset; 
     22+       unsigned int virt_plt_offset; 
    2323 }; 
    2424  
     
    143143 { 
    144144 #ifdef MODULE_START 
    145 @@ -58,16 +168,45 @@ void *module_alloc(unsigned long size) 
     145@@ -58,23 +168,101 @@ void *module_alloc(unsigned long size) 
    146146  
    147147        return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL); 
     
    191191            table entries. */ 
    192192 } 
    193 @@ -75,6 +214,24 @@ void module_free(struct module *mod, voi 
     193  
     194+static void *__module_alloc(int size, bool phys) 
     195+{ 
     196+       void *ptr; 
     197+ 
     198+       if (phys) 
     199+               ptr = kmalloc(size, GFP_KERNEL); 
     200+       else 
     201+               ptr = vmalloc(size); 
     202+       return ptr; 
     203+} 
     204+ 
     205+static void __module_free(void *ptr) 
     206+{ 
     207+       if (is_phys_addr(ptr)) 
     208+               kfree(ptr); 
     209+       else 
     210+               vfree(ptr); 
     211+} 
     212+ 
    194213 int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, 
    195214                              char *secstrings, struct module *mod) 
     
    206225+       init_size = get_plt_size(hdr, sechdrs, secstrings, symindex, true); 
    207226+ 
    208 +       mod->arch.core_plt_offset = 0; 
    209 +       mod->arch.core_plt_size = core_size; 
    210 +       mod->arch.init_plt_offset = core_size; 
    211 +       mod->arch.plt_tbl = kmalloc(core_size + init_size, GFP_KERNEL); 
    212 +       if (!mod->arch.plt_tbl) 
     227+       mod->arch.phys_plt_offset = 0; 
     228+       mod->arch.virt_plt_offset = 0; 
     229+       mod->arch.phys_plt_tbl = NULL; 
     230+       mod->arch.virt_plt_tbl = NULL; 
     231+ 
     232+       if ((core_size + init_size) == 0) 
     233+               return 0; 
     234+ 
     235+       mod->arch.phys_plt_tbl = __module_alloc(core_size + init_size, 1); 
     236+       if (!mod->arch.phys_plt_tbl) 
    213237+               return -ENOMEM; 
    214238+ 
     239+       mod->arch.virt_plt_tbl = __module_alloc(core_size + init_size, 0); 
     240+       if (!mod->arch.virt_plt_tbl) { 
     241+               __module_free(mod->arch.phys_plt_tbl); 
     242+               mod->arch.phys_plt_tbl = NULL; 
     243+               return -ENOMEM; 
     244+       } 
     245+ 
    215246        return 0; 
    216247 } 
    217248  
    218 @@ -97,27 +254,41 @@ static int apply_r_mips_32_rela(struct m 
     249@@ -97,27 +285,37 @@ static int apply_r_mips_32_rela(struct m 
    219250        return 0; 
    220251 } 
     
    237268-       } 
    238269+       *plt_offset += 4 * sizeof(int); 
    239 + 
     270  
     271-       *location = (*location & ~0x03ffffff) | 
     272-                   ((*location + (v >> 2)) & 0x03ffffff); 
    240273+       /* adjust carry for addiu */ 
    241274+       if (v & 0x00008000) 
    242275+               v += 0x10000; 
    243 + 
     276  
     277-       return 0; 
    244278+       tramp[0] = 0x3c190000 | (v >> 16);      /* lui t9, hi16 */ 
    245279+       tramp[1] = 0x27390000 | (v & 0xffff);   /* addiu t9, t9, lo16 */ 
    246280+       tramp[2] = 0x03200008;                  /* jr t9 */ 
    247281+       tramp[3] = 0x00000000;                  /* nop */ 
    248   
    249 -       *location = (*location & ~0x03ffffff) | 
    250 -                   ((*location + (v >> 2)) & 0x03ffffff); 
     282+ 
    251283+       return (Elf_Addr) tramp; 
    252 +} 
    253 + 
     284 } 
     285  
     286-static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v) 
    254287+static Elf_Addr add_plt_entry(struct module *me, void *location, Elf_Addr v) 
    255288+{ 
    256 +       if (location >= me->module_core && 
    257 +           location < me->module_core + me->core_size) 
    258 +               return add_plt_entry_to(&me->arch.core_plt_offset, 
    259 +                               me->arch.plt_tbl, v); 
    260 + 
    261 +       if (location >= me->module_init && 
    262 +           location < me->module_init + me->init_size) 
    263 +               return add_plt_entry_to(&me->arch.init_plt_offset, 
    264 +                               me->arch.plt_tbl, v); 
    265   
    266         return 0; 
    267  } 
    268   
    269 -static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v) 
     289+       if (is_phys_addr(location)) 
     290+               return add_plt_entry_to(&me->arch.phys_plt_offset, 
     291+                               me->arch.phys_plt_tbl, v); 
     292+       else 
     293+               return add_plt_entry_to(&me->arch.virt_plt_offset, 
     294+                               me->arch.virt_plt_tbl, v); 
     295+ 
     296+} 
     297+ 
    270298+static int set_r_mips_26(struct module *me, u32 *location, u32 ofs, Elf_Addr v) 
    271299 { 
    272300        if (v % 4) { 
    273301                printk(KERN_ERR "module %s: dangerous relocation\n", me->name); 
    274 @@ -125,17 +296,31 @@ static int apply_r_mips_26_rela(struct m 
     302@@ -125,17 +323,31 @@ static int apply_r_mips_26_rela(struct m 
    275303        } 
    276304  
     
    307335 { 
    308336        struct mips_hi16 *n; 
    309 @@ -400,11 +585,23 @@ int module_finalize(const Elf_Ehdr *hdr, 
     337@@ -400,11 +612,32 @@ int module_finalize(const Elf_Ehdr *hdr, 
    310338                list_add(&me->arch.dbe_list, &dbe_list); 
    311339                spin_unlock_irq(&dbe_lock); 
     
    314342+       /* Get rid of the fixup trampoline if we're running the module 
    315343+        * from physically mapped address space */ 
    316 +       if (me->arch.core_plt_offset == 0 && 
    317 +           me->arch.init_plt_offset == me->arch.core_plt_size && 
    318 +           is_phys_addr(me->module_core)) { 
    319 +               kfree(me->arch.plt_tbl); 
    320 +               me->arch.plt_tbl = NULL; 
     344+       if (me->arch.phys_plt_offset == 0) { 
     345+               __module_free(me->arch.phys_plt_tbl); 
     346+               me->arch.phys_plt_tbl = NULL; 
     347+       } 
     348+       if (me->arch.virt_plt_offset == 0) { 
     349+               __module_free(me->arch.virt_plt_tbl); 
     350+               me->arch.virt_plt_tbl = NULL; 
    321351+       } 
    322352+ 
     
    326356 void module_arch_cleanup(struct module *mod) 
    327357 { 
    328 +       if (mod->arch.plt_tbl) 
    329 +               kfree(mod->arch.plt_tbl); 
     358+       if (mod->arch.phys_plt_tbl) { 
     359+               __module_free(mod->arch.phys_plt_tbl); 
     360+               mod->arch.phys_plt_tbl = NULL; 
     361+       } 
     362+       if (mod->arch.virt_plt_tbl) { 
     363+               __module_free(mod->arch.virt_plt_tbl); 
     364+               mod->arch.virt_plt_tbl = NULL; 
     365+       } 
     366+ 
    330367        spin_lock_irq(&dbe_lock); 
    331368        list_del(&mod->arch.dbe_list); 
  • trunk/target/linux/generic-2.6/patches-2.6.31/027-mips_module_reloc.patch

    r17351 r18858  
    1717        const struct exception_table_entry *dbe_end; 
    1818+ 
    19 +       void *plt_tbl; 
    20 +       unsigned int core_plt_offset; 
    21 +       unsigned int core_plt_size; 
    22 +       unsigned int init_plt_offset; 
     19+       void *phys_plt_tbl; 
     20+       void *virt_plt_tbl; 
     21+       unsigned int phys_plt_offset; 
     22+       unsigned int virt_plt_offset; 
    2323 }; 
    2424  
     
    144144 { 
    145145 #ifdef MODULE_START 
    146 @@ -58,21 +169,68 @@ void *module_alloc(unsigned long size) 
     146@@ -58,21 +169,99 @@ void *module_alloc(unsigned long size) 
    147147  
    148148        return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL); 
     
    189189+               vfree(module_region); 
    190190+       } 
     191+} 
     192+ 
     193+static void *__module_alloc(int size, bool phys) 
     194+{ 
     195+       void *ptr; 
     196+ 
     197+       if (phys) 
     198+               ptr = kmalloc(size, GFP_KERNEL); 
     199+       else 
     200+               ptr = vmalloc(size); 
     201+       return ptr; 
     202+} 
     203+ 
     204+static void __module_free(void *ptr) 
     205+{ 
     206+       if (is_phys_addr(ptr)) 
     207+               kfree(ptr); 
     208+       else 
     209+               vfree(ptr); 
    191210 } 
    192211  
     
    205224+       init_size = get_plt_size(hdr, sechdrs, secstrings, symindex, true); 
    206225+ 
    207 +       mod->arch.core_plt_offset = 0; 
    208 +       mod->arch.core_plt_size = core_size; 
    209 +       mod->arch.init_plt_offset = core_size; 
    210 +       mod->arch.plt_tbl = kmalloc(core_size + init_size, GFP_KERNEL); 
    211 +       if (!mod->arch.plt_tbl) 
     226+       mod->arch.phys_plt_offset = 0; 
     227+       mod->arch.virt_plt_offset = 0; 
     228+       mod->arch.phys_plt_tbl = NULL; 
     229+       mod->arch.virt_plt_tbl = NULL; 
     230+ 
     231+       if ((core_size + init_size) == 0) 
     232+               return 0; 
     233+ 
     234+       mod->arch.phys_plt_tbl = __module_alloc(core_size + init_size, 1); 
     235+       if (!mod->arch.phys_plt_tbl) 
    212236+               return -ENOMEM; 
    213237+ 
     238+       mod->arch.virt_plt_tbl = __module_alloc(core_size + init_size, 0); 
     239+       if (!mod->arch.virt_plt_tbl) { 
     240+               __module_free(mod->arch.phys_plt_tbl); 
     241+               mod->arch.phys_plt_tbl = NULL; 
     242+               return -ENOMEM; 
     243+       } 
     244+ 
    214245        return 0; 
    215246 } 
    216247  
    217 @@ -95,28 +253,40 @@ static int apply_r_mips_32_rela(struct m 
     248@@ -95,28 +284,36 @@ static int apply_r_mips_32_rela(struct m 
    218249        return 0; 
    219250 } 
     
    240271+       if (v & 0x00008000) 
    241272+               v += 0x10000; 
    242 + 
     273  
     274-       *location = (*location & ~0x03ffffff) | 
     275-                   ((*location + (v >> 2)) & 0x03ffffff); 
    243276+       tramp[0] = 0x3c190000 | (v >> 16);      /* lui t9, hi16 */ 
    244277+       tramp[1] = 0x27390000 | (v & 0xffff);   /* addiu t9, t9, lo16 */ 
     
    246279+       tramp[3] = 0x00000000;                  /* nop */ 
    247280  
    248 -       *location = (*location & ~0x03ffffff) | 
    249 -                   ((*location + (v >> 2)) & 0x03ffffff); 
     281-       return 0; 
    250282+       return (Elf_Addr) tramp; 
    251 +} 
    252 + 
     283 } 
     284  
     285-static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v) 
    253286+static Elf_Addr add_plt_entry(struct module *me, void *location, Elf_Addr v) 
    254287+{ 
    255 +       if (location >= me->module_core && 
    256 +           location < me->module_core + me->core_size) 
    257 +               return add_plt_entry_to(&me->arch.core_plt_offset, 
    258 +                               me->arch.plt_tbl, v); 
    259 + 
    260 +       if (location >= me->module_init && 
    261 +           location < me->module_init + me->init_size) 
    262 +               return add_plt_entry_to(&me->arch.init_plt_offset, 
    263 +                               me->arch.plt_tbl, v); 
    264   
    265         return 0; 
    266  } 
    267   
    268 -static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v) 
     288+       if (is_phys_addr(location)) 
     289+               return add_plt_entry_to(&me->arch.phys_plt_offset, 
     290+                               me->arch.phys_plt_tbl, v); 
     291+       else 
     292+               return add_plt_entry_to(&me->arch.virt_plt_offset, 
     293+                               me->arch.virt_plt_tbl, v); 
     294+ 
     295+} 
     296+ 
    269297+static int set_r_mips_26(struct module *me, u32 *location, u32 ofs, Elf_Addr v) 
    270298 { 
    271299        if (v % 4) { 
    272300                pr_err("module %s: dangerous R_MIPS_26 RELArelocation\n", 
    273 @@ -125,17 +295,31 @@ static int apply_r_mips_26_rela(struct m 
     301@@ -125,17 +322,31 @@ static int apply_r_mips_26_rela(struct m 
    274302        } 
    275303  
     
    306334 { 
    307335        struct mips_hi16 *n; 
    308 @@ -400,11 +584,23 @@ int module_finalize(const Elf_Ehdr *hdr, 
     336@@ -400,11 +611,32 @@ int module_finalize(const Elf_Ehdr *hdr, 
    309337                list_add(&me->arch.dbe_list, &dbe_list); 
    310338                spin_unlock_irq(&dbe_lock); 
     
    313341+       /* Get rid of the fixup trampoline if we're running the module 
    314342+        * from physically mapped address space */ 
    315 +       if (me->arch.core_plt_offset == 0 && 
    316 +           me->arch.init_plt_offset == me->arch.core_plt_size && 
    317 +           is_phys_addr(me->module_core)) { 
    318 +               kfree(me->arch.plt_tbl); 
    319 +               me->arch.plt_tbl = NULL; 
     343+       if (me->arch.phys_plt_offset == 0) { 
     344+               __module_free(me->arch.phys_plt_tbl); 
     345+               me->arch.phys_plt_tbl = NULL; 
     346+       } 
     347+       if (me->arch.virt_plt_offset == 0) { 
     348+               __module_free(me->arch.virt_plt_tbl); 
     349+               me->arch.virt_plt_tbl = NULL; 
    320350+       } 
    321351+ 
     
    325355 void module_arch_cleanup(struct module *mod) 
    326356 { 
    327 +       if (mod->arch.plt_tbl) 
    328 +               kfree(mod->arch.plt_tbl); 
     357+       if (mod->arch.phys_plt_tbl) { 
     358+               __module_free(mod->arch.phys_plt_tbl); 
     359+               mod->arch.phys_plt_tbl = NULL; 
     360+       } 
     361+       if (mod->arch.virt_plt_tbl) { 
     362+               __module_free(mod->arch.virt_plt_tbl); 
     363+               mod->arch.virt_plt_tbl = NULL; 
     364+       } 
     365+ 
    329366        spin_lock_irq(&dbe_lock); 
    330367        list_del(&mod->arch.dbe_list); 
  • trunk/target/linux/generic-2.6/patches-2.6.32/027-mips_module_reloc.patch

    r17351 r18858  
    1717        const struct exception_table_entry *dbe_end; 
    1818+ 
    19 +       void *plt_tbl; 
    20 +       unsigned int core_plt_offset; 
    21 +       unsigned int core_plt_size; 
    22 +       unsigned int init_plt_offset; 
     19+       void *phys_plt_tbl; 
     20+       void *virt_plt_tbl; 
     21+       unsigned int phys_plt_offset; 
     22+       unsigned int virt_plt_offset; 
    2323 }; 
    2424  
     
    144144 { 
    145145 #ifdef MODULE_START 
    146 @@ -58,21 +169,68 @@ void *module_alloc(unsigned long size) 
     146@@ -58,21 +169,99 @@ void *module_alloc(unsigned long size) 
    147147  
    148148        return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL); 
     
    189189+               vfree(module_region); 
    190190+       } 
     191+} 
     192+ 
     193+static void *__module_alloc(int size, bool phys) 
     194+{ 
     195+       void *ptr; 
     196+ 
     197+       if (phys) 
     198+               ptr = kmalloc(size, GFP_KERNEL); 
     199+       else 
     200+               ptr = vmalloc(size); 
     201+       return ptr; 
     202+} 
     203+ 
     204+static void __module_free(void *ptr) 
     205+{ 
     206+       if (is_phys_addr(ptr)) 
     207+               kfree(ptr); 
     208+       else 
     209+               vfree(ptr); 
    191210 } 
    192211  
     
    205224+       init_size = get_plt_size(hdr, sechdrs, secstrings, symindex, true); 
    206225+ 
    207 +       mod->arch.core_plt_offset = 0; 
    208 +       mod->arch.core_plt_size = core_size; 
    209 +       mod->arch.init_plt_offset = core_size; 
    210 +       mod->arch.plt_tbl = kmalloc(core_size + init_size, GFP_KERNEL); 
    211 +       if (!mod->arch.plt_tbl) 
     226+       mod->arch.phys_plt_offset = 0; 
     227+       mod->arch.virt_plt_offset = 0; 
     228+       mod->arch.phys_plt_tbl = NULL; 
     229+       mod->arch.virt_plt_tbl = NULL; 
     230+ 
     231+       if ((core_size + init_size) == 0) 
     232+               return 0; 
     233+ 
     234+       mod->arch.phys_plt_tbl = __module_alloc(core_size + init_size, 1); 
     235+       if (!mod->arch.phys_plt_tbl) 
    212236+               return -ENOMEM; 
    213237+ 
     238+       mod->arch.virt_plt_tbl = __module_alloc(core_size + init_size, 0); 
     239+       if (!mod->arch.virt_plt_tbl) { 
     240+               __module_free(mod->arch.phys_plt_tbl); 
     241+               mod->arch.phys_plt_tbl = NULL; 
     242+               return -ENOMEM; 
     243+       } 
     244+ 
    214245        return 0; 
    215246 } 
    216247  
    217 @@ -95,28 +253,40 @@ static int apply_r_mips_32_rela(struct m 
     248@@ -95,28 +284,36 @@ static int apply_r_mips_32_rela(struct m 
    218249        return 0; 
    219250 } 
     
    240271+       if (v & 0x00008000) 
    241272+               v += 0x10000; 
    242 + 
     273  
     274-       *location = (*location & ~0x03ffffff) | 
     275-                   ((*location + (v >> 2)) & 0x03ffffff); 
    243276+       tramp[0] = 0x3c190000 | (v >> 16);      /* lui t9, hi16 */ 
    244277+       tramp[1] = 0x27390000 | (v & 0xffff);   /* addiu t9, t9, lo16 */ 
     
    246279+       tramp[3] = 0x00000000;                  /* nop */ 
    247280  
    248 -       *location = (*location & ~0x03ffffff) | 
    249 -                   ((*location + (v >> 2)) & 0x03ffffff); 
     281-       return 0; 
    250282+       return (Elf_Addr) tramp; 
    251 +} 
    252 + 
     283 } 
     284  
     285-static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v) 
    253286+static Elf_Addr add_plt_entry(struct module *me, void *location, Elf_Addr v) 
    254287+{ 
    255 +       if (location >= me->module_core && 
    256 +           location < me->module_core + me->core_size) 
    257 +               return add_plt_entry_to(&me->arch.core_plt_offset, 
    258 +                               me->arch.plt_tbl, v); 
    259 + 
    260 +       if (location >= me->module_init && 
    261 +           location < me->module_init + me->init_size) 
    262 +               return add_plt_entry_to(&me->arch.init_plt_offset, 
    263 +                               me->arch.plt_tbl, v); 
    264   
    265         return 0; 
    266  } 
    267   
    268 -static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v) 
     288+       if (is_phys_addr(location)) 
     289+               return add_plt_entry_to(&me->arch.phys_plt_offset, 
     290+                               me->arch.phys_plt_tbl, v); 
     291+       else 
     292+               return add_plt_entry_to(&me->arch.virt_plt_offset, 
     293+                               me->arch.virt_plt_tbl, v); 
     294+ 
     295+} 
     296+ 
    269297+static int set_r_mips_26(struct module *me, u32 *location, u32 ofs, Elf_Addr v) 
    270298 { 
    271299        if (v % 4) { 
    272300                pr_err("module %s: dangerous R_MIPS_26 RELArelocation\n", 
    273 @@ -125,17 +295,31 @@ static int apply_r_mips_26_rela(struct m 
     301@@ -125,17 +322,31 @@ static int apply_r_mips_26_rela(struct m 
    274302        } 
    275303  
     
    306334 { 
    307335        struct mips_hi16 *n; 
    308 @@ -400,11 +584,23 @@ int module_finalize(const Elf_Ehdr *hdr, 
     336@@ -400,11 +611,32 @@ int module_finalize(const Elf_Ehdr *hdr, 
    309337                list_add(&me->arch.dbe_list, &dbe_list); 
    310338                spin_unlock_irq(&dbe_lock); 
     
    313341+       /* Get rid of the fixup trampoline if we're running the module 
    314342+        * from physically mapped address space */ 
    315 +       if (me->arch.core_plt_offset == 0 && 
    316 +           me->arch.init_plt_offset == me->arch.core_plt_size && 
    317 +           is_phys_addr(me->module_core)) { 
    318 +               kfree(me->arch.plt_tbl); 
    319 +               me->arch.plt_tbl = NULL; 
     343+       if (me->arch.phys_plt_offset == 0) { 
     344+               __module_free(me->arch.phys_plt_tbl); 
     345+               me->arch.phys_plt_tbl = NULL; 
     346+       } 
     347+       if (me->arch.virt_plt_offset == 0) { 
     348+               __module_free(me->arch.virt_plt_tbl); 
     349+               me->arch.virt_plt_tbl = NULL; 
    320350+       } 
    321351+ 
     
    325355 void module_arch_cleanup(struct module *mod) 
    326356 { 
    327 +       if (mod->arch.plt_tbl) 
    328 +               kfree(mod->arch.plt_tbl); 
     357+       if (mod->arch.phys_plt_tbl) { 
     358+               __module_free(mod->arch.phys_plt_tbl); 
     359+               mod->arch.phys_plt_tbl = NULL; 
     360+       } 
     361+       if (mod->arch.virt_plt_tbl) { 
     362+               __module_free(mod->arch.virt_plt_tbl); 
     363+               mod->arch.virt_plt_tbl = NULL; 
     364+       } 
     365+ 
    329366        spin_lock_irq(&dbe_lock); 
    330367        list_del(&mod->arch.dbe_list); 
Note: See TracChangeset for help on using the changeset viewer.