在 2020年07月31日 00:00, crash-utility-requ...@redhat.com 写道:
> Message: 1
> Date: Thu, 30 Jul 2020 15:34:59 +0200
> From: Mathias Krause <mini...@grsecurity.net>
> To: crash-utility@redhat.com
> Subject: [Crash-utility] [PATCH RESEND] Basic support for PaX's split
>       module  layout
> Message-ID: <20200730133459.7868-1-mini...@grsecurity.net>
> Content-Type: text/plain; charset=US-ASCII
> 
> PaX and grsecurity kernels split module memory into dedicated r/x and
> r/w mappings using '*_rw' and '*_rx' named member variables in 'struct
> module'. To add basic support for such kernels detect the split layout
> by testing for the corresponding structure members and use these
> instead.
> 
> So far we limit ourself to only track module code mappings for such
> kernels as adding support for separate data mappings violates lots of
> invariants in the rest of our code base, thereby would require a major
> rework. However, with that patch applied, module code references can be
> resolved in backtraces, memory and code dumps, which makes it already
> very useful for analyzing such kernels.
> 
> Signed-off-by: Mathias Krause <mini...@grsecurity.net>
> ---
> Resend as the original posting got stuck in the mail queue.
> 
>  defs.h    | 13 +++++++++++
>  kernel.c  | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++----
>  symbols.c | 20 ++++++++--------
>  3 files changed, 86 insertions(+), 15 deletions(-)
> 
> diff --git a/defs.h b/defs.h
> index d7adb23b86d5..160974ed554a 100644
> --- a/defs.h
> +++ b/defs.h
> @@ -654,12 +654,15 @@ struct new_utsname {
>  #define TIMER_BASES                (0x20ULL)
>  #define IRQ_DESC_TREE_RADIX        (0x40ULL)
>  #define IRQ_DESC_TREE_XARRAY       (0x80ULL)
> +#define KMOD_PAX                  (0x100ULL)
>  
>  #define XEN()       (kt->flags & ARCH_XEN)
>  #define OPENVZ()    (kt->flags & ARCH_OPENVZ)
>  #define PVOPS()     (kt->flags & ARCH_PVOPS)
>  #define PVOPS_XEN() (kt->flags & ARCH_PVOPS_XEN)
>  
> +#define PAX_MODULE_SPLIT() (kt->flags2 & KMOD_PAX)
> +
>  #define XEN_MACHINE_TO_MFN(m)    ((ulonglong)(m) >> PAGESHIFT())
>  #define XEN_PFN_TO_PSEUDO(p)     ((ulonglong)(p) << PAGESHIFT())
>  
> @@ -1346,7 +1349,11 @@ struct offset_table {                    /* stash of 
> commonly-used offsets */
>       long module_gpl_syms;
>       long module_num_gpl_syms;
>       long module_module_core;
> +     long module_module_core_rw;
> +     long module_module_core_rx;
>       long module_core_size;
> +     long module_core_size_rw;
> +     long module_core_size_rx;
>       long module_core_text_size;
>       long module_num_symtab;
>       long module_symtab;
> @@ -1776,6 +1783,8 @@ struct offset_table {                    /* stash of 
> commonly-used offsets */
>       long mm_struct_rss_stat;
>       long mm_rss_stat_count;
>       long module_module_init;
> +     long module_module_init_rw;
> +     long module_module_init_rx;
>       long module_init_text_size;
>       long cpu_context_save_fp;
>       long cpu_context_save_sp;
> @@ -1793,6 +1802,8 @@ struct offset_table {                    /* stash of 
> commonly-used offsets */
>       long unwind_idx_insn;
>       long signal_struct_nr_threads;
>       long module_init_size;
> +     long module_init_size_rw;
> +     long module_init_size_rx;
>       long module_percpu;
>       long radix_tree_node_slots;
>       long s390_stack_frame_back_chain;
> @@ -2313,6 +2324,8 @@ struct array_table {
>   *  in the offset table, size table or array_table.
>   */
>  #define OFFSET(X)       (OFFSET_verify(offset_table.X, (char *)__FUNCTION__, 
> __FILE__, __LINE__, #X))
> +#define MODULE_OFFSET(X,Y) (PAX_MODULE_SPLIT() ? OFFSET(Y) : OFFSET(X))
> +#define MODULE_OFFSET2(X,T) MODULE_OFFSET(X, X##_##T)
The above definition has a code style issue(space required after that ','), but 
we could correct
it when this patch is applied.

Otherwise, it looks good to me.
Acked-by: Lianbo Jiang <liji...@redhat.com>

Thanks.
Lianbo

>  #define SIZE(X)            (SIZE_verify(size_table.X, (char *)__FUNCTION__, 
> __FILE__, __LINE__, #X))
>  #define INVALID_OFFSET     (-1)
>  #define INVALID_MEMBER(X)  (offset_table.X == INVALID_OFFSET)
> diff --git a/kernel.c b/kernel.c
> index 5ed602108b87..c2b8e0a04a26 100644
> --- a/kernel.c
> +++ b/kernel.c
> @@ -3540,6 +3540,62 @@ module_init(void)
>                                          "module_core");
>                       MEMBER_OFFSET_INIT(module_module_init, "module",
>                                          "module_init");
> +             } else if (MEMBER_EXISTS("module", "module_core_rx")) {
> +                     if (CRASHDEBUG(1))
> +                             error(INFO, "PaX module layout detected.\n");
> +                     kt->flags2 |= KMOD_PAX;
> +
> +                     MEMBER_OFFSET_INIT(module_core_size_rw, "module",
> +                                        "core_size_rw");
> +                     MEMBER_OFFSET_INIT(module_core_size_rx, "module",
> +                                        "core_size_rx");
> +
> +                     MEMBER_OFFSET_INIT(module_init_size_rw, "module",
> +                                        "init_size_rw");
> +                     MEMBER_OFFSET_INIT(module_init_size_rx, "module",
> +                                        "init_size_rx");
> +
> +                     MEMBER_OFFSET_INIT(module_module_core_rw, "module",
> +                                        "module_core_rw");
> +                     MEMBER_OFFSET_INIT(module_module_core_rx, "module",
> +                                        "module_core_rx");
> +
> +                     MEMBER_OFFSET_INIT(module_module_init_rw, "module",
> +                                        "module_init_rw");
> +                     MEMBER_OFFSET_INIT(module_module_init_rx, "module",
> +                                        "module_init_rx");
> +             } else if (MEMBER_EXISTS("module_layout", "base_rx")) {
> +                     if (CRASHDEBUG(1))
> +                             error(INFO, "PaX module layout detected.\n");
> +                     kt->flags2 |= KMOD_PAX;
> +
> +                     ASSIGN_OFFSET(module_core_size_rw) =
> +                             MEMBER_OFFSET("module", "core_layout") +
> +                             MEMBER_OFFSET("module_layout", "size_rw");
> +                     ASSIGN_OFFSET(module_core_size_rx) =
> +                             MEMBER_OFFSET("module", "core_layout") +
> +                             MEMBER_OFFSET("module_layout", "size_rx");
> +
> +                     ASSIGN_OFFSET(module_init_size_rw) =
> +                             MEMBER_OFFSET("module", "init_layout") +
> +                             MEMBER_OFFSET("module_layout", "size_rw");
> +                     ASSIGN_OFFSET(module_init_size_rx) =
> +                             MEMBER_OFFSET("module", "init_layout") +
> +                             MEMBER_OFFSET("module_layout", "size_rx");
> +
> +                     ASSIGN_OFFSET(module_module_core_rw) =
> +                             MEMBER_OFFSET("module", "core_layout") +
> +                             MEMBER_OFFSET("module_layout", "base_rw");
> +                     ASSIGN_OFFSET(module_module_core_rx) =
> +                             MEMBER_OFFSET("module", "core_layout") +
> +                             MEMBER_OFFSET("module_layout", "base_rx");
> +
> +                     ASSIGN_OFFSET(module_module_init_rw) =
> +                             MEMBER_OFFSET("module", "init_layout") +
> +                             MEMBER_OFFSET("module_layout", "base_rw");
> +                     ASSIGN_OFFSET(module_module_init_rx) =
> +                             MEMBER_OFFSET("module", "init_layout") +
> +                             MEMBER_OFFSET("module_layout", "base_rx");
>               } else {
>                       ASSIGN_OFFSET(module_core_size) =
>                               MEMBER_OFFSET("module", "core_layout") +
> @@ -3682,10 +3738,10 @@ module_init(void)
>               case KALLSYMS_V2:
>                       if (THIS_KERNEL_VERSION >= LINUX(2,6,27)) {
>                               numksyms = UINT(modbuf + 
> OFFSET(module_num_symtab));
> -                             size = UINT(modbuf + OFFSET(module_core_size));
> +                             size = UINT(modbuf + 
> MODULE_OFFSET2(module_core_size, rx));
>                       } else {
>                               numksyms = ULONG(modbuf + 
> OFFSET(module_num_symtab));
> -                             size = ULONG(modbuf + OFFSET(module_core_size));
> +                             size = ULONG(modbuf + 
> MODULE_OFFSET2(module_core_size, rx));
>                       }
>  
>                       if (!size) {
> @@ -3792,7 +3848,7 @@ verify_modules(void)
>                               break;
>                       case KMOD_V2:
>                               mod_base = ULONG(modbuf + 
> -                                     OFFSET(module_module_core));
> +                                     MODULE_OFFSET2(module_module_core, rx));
>                               break;
>                       }
>  
> @@ -3816,10 +3872,10 @@ verify_modules(void)
>                                               OFFSET(module_name);
>                                       if (THIS_KERNEL_VERSION >= 
> LINUX(2,6,27))
>                                               mod_size = UINT(modbuf +
> -                                                     
> OFFSET(module_core_size));
> +                                                     
> MODULE_OFFSET2(module_core_size, rx));
>                                       else
>                                               mod_size = ULONG(modbuf +
> -                                                     
> OFFSET(module_core_size));
> +                                                     
> MODULE_OFFSET2(module_core_size, rx));
>                                       if (strlen(module_name) < MAX_MOD_NAME)
>                                               strcpy(buf, module_name);
>                                       else 
> @@ -5989,6 +6045,8 @@ dump_kernel_table(int verbose)
>               fprintf(fp, "%sIRQ_DESC_TREE_RADIX", others++ ? "|" : "");
>       if (kt->flags2 & IRQ_DESC_TREE_XARRAY)
>               fprintf(fp, "%sIRQ_DESC_TREE_XARRAY", others++ ? "|" : "");
> +     if (kt->flags2 & KMOD_PAX)
> +             fprintf(fp, "%sKMOD_PAX", others++ ? "|" : "");
>       fprintf(fp, ")\n");
>  
>          fprintf(fp, "         stext: %lx\n", kt->stext);
> diff --git a/symbols.c b/symbols.c
> index 3b1f08af43ff..be672fcaefd9 100644
> --- a/symbols.c
> +++ b/symbols.c
> @@ -1766,17 +1766,17 @@ store_module_symbols_v2(ulong total, int 
> mods_installed)
>  
>               if (THIS_KERNEL_VERSION >= LINUX(2,6,27)) {
>                       nksyms = UINT(modbuf + OFFSET(module_num_symtab));
> -                     size = UINT(modbuf + OFFSET(module_core_size));
> +                     size = UINT(modbuf + MODULE_OFFSET2(module_core_size, 
> rx));
>               } else {
>                       nksyms = ULONG(modbuf + OFFSET(module_num_symtab));
> -                     size = ULONG(modbuf + OFFSET(module_core_size));
> +                     size = ULONG(modbuf + MODULE_OFFSET2(module_core_size, 
> rx));
>               }
>  
>               mod_name = modbuf + OFFSET(module_name);
>  
>               lm = &st->load_modules[m++];
>               BZERO(lm, sizeof(struct load_module));
> -             lm->mod_base = ULONG(modbuf + OFFSET(module_module_core));
> +             lm->mod_base = ULONG(modbuf + 
> MODULE_OFFSET2(module_module_core, rx));
>               lm->module_struct = mod;
>               lm->mod_size = size;
>               if (strlen(mod_name) < MAX_MOD_NAME)
> @@ -1795,23 +1795,23 @@ store_module_symbols_v2(ulong total, int 
> mods_installed)
>               lm->mod_flags = MOD_EXT_SYMS;
>               lm->mod_ext_symcnt = mcnt;
>               lm->mod_init_module_ptr = ULONG(modbuf + 
> -                     OFFSET(module_module_init));
> +                     MODULE_OFFSET2(module_module_init, rx));
>               if (VALID_MEMBER(module_percpu))
>                       lm->mod_percpu = ULONG(modbuf + OFFSET(module_percpu));
>               if (THIS_KERNEL_VERSION >= LINUX(2,6,27)) {
>                       lm->mod_etext_guess = lm->mod_base +
> -                             UINT(modbuf + OFFSET(module_core_text_size));
> +                             UINT(modbuf + 
> MODULE_OFFSET(module_core_text_size, module_core_size_rx));
>                       lm->mod_init_size =
> -                             UINT(modbuf + OFFSET(module_init_size));
> +                             UINT(modbuf + MODULE_OFFSET2(module_init_size, 
> rx));
>                       lm->mod_init_text_size = 
> -                             UINT(modbuf + OFFSET(module_init_text_size));
> +                             UINT(modbuf + 
> MODULE_OFFSET(module_init_text_size, module_init_size_rx));
>               } else {
>                       lm->mod_etext_guess = lm->mod_base +
> -                             ULONG(modbuf + OFFSET(module_core_text_size));
> +                             ULONG(modbuf + 
> MODULE_OFFSET(module_core_text_size, module_core_size_rx));
>                       lm->mod_init_size =
> -                             ULONG(modbuf + OFFSET(module_init_size));
> +                             ULONG(modbuf + MODULE_OFFSET2(module_init_size, 
> rx));
>                       lm->mod_init_text_size = 
> -                             ULONG(modbuf + OFFSET(module_init_text_size));
> +                             ULONG(modbuf + 
> MODULE_OFFSET(module_init_text_size, module_init_size_rx));
>               }
>               lm->mod_text_start = lm->mod_base;
>  
> -- 2.20.1

--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility

Reply via email to