[Crash-utility] [PATCH v3] Basic support for PaX's split module layout

HAGIO KAZUHITO(萩尾 一仁) k-hagio-ab at nec.com
Wed Sep 2 23:43:53 UTC 2020


Hi Lianbo,

-----Original Message-----
> Does this need further input from my site to get merged? Lianbo acked an
> earlier version[1], so this should be fine as is?

as you commented after the ack, I thought you would check the new version
again.  Can I merge the v3 patch?

Thanks,
Kazu

> 
> Thanks,
> Mathias
> 
> [1] https://www.redhat.com/archives/crash-utility/2020-August/msg00021.html
> 
> Am 25.08.20 um 04:09 schrieb HAGIO KAZUHITO(萩尾 一仁):
> > -----Original Message-----
> >> 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 <minipli at grsecurity.net>
> >> ---
> >> v3:
> >> - dump offsets unconditional
> >> - fix indention of 'module_init_size' offset dump
> >
> > Thanks for the update.  The v3 patch looks good to me.
> >
> > Acked-by: Kazuhito Hagio <k-hagio-ab at nec.com>
> >
> > Thanks,
> > Kazu
> >
> >>
> >> v2:
> >> - add members to end of struct offset_table
> >> - add offsets to dump_offset_table()
> >>
> >>  defs.h    | 13 +++++++++++
> >>  kernel.c  | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++----
> >>  symbols.c | 38 ++++++++++++++++++++++---------
> >>  3 files changed, 103 insertions(+), 16 deletions(-)
> >>
> >> diff --git a/defs.h b/defs.h
> >> index 17e98763362b..ae860448ab15 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())
> >>
> >> @@ -2089,6 +2092,14 @@ struct offset_table {                    /* stash of commonly-used offsets */
> >>  	long size_class_size;
> >>  	long gendisk_private_data;
> >>  	long zram_table_entry;
> >> +	long module_core_size_rw;
> >> +	long module_core_size_rx;
> >> +	long module_init_size_rw;
> >> +	long module_init_size_rx;
> >> +	long module_module_core_rw;
> >> +	long module_module_core_rx;
> >> +	long module_module_init_rw;
> >> +	long module_module_init_rx;
> >>  };
> >>
> >>  struct size_table {         /* stash of commonly-used sizes */
> >> @@ -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)
> >>  #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 f179375f2d3d..f0268adccd4a 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
> >> @@ -5997,6 +6053,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 2fecaee093a2..311fdb7df29e 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;
> >>
> >> @@ -9119,12 +9119,28 @@ dump_offset_table(char *spec, ulong makestruct)
> >>  		OFFSET(module_core_size));
> >>  	fprintf(fp, "         module_core_text_size: %ld\n",
> >>  		OFFSET(module_core_text_size));
> >> -	fprintf(fp, "         module_init_size: %ld\n",
> >> +	fprintf(fp, "              module_init_size: %ld\n",
> >>  		OFFSET(module_init_size));
> >>  	fprintf(fp, "         module_init_text_size: %ld\n",
> >>  		OFFSET(module_init_text_size));
> >>  	fprintf(fp, "            module_module_init: %ld\n",
> >>  		OFFSET(module_module_init));
> >> +	fprintf(fp, "         module_module_core_rx: %ld\n",
> >> +		OFFSET(module_module_core_rx));
> >> +	fprintf(fp, "         module_module_core_rw: %ld\n",
> >> +		OFFSET(module_module_core_rw));
> >> +	fprintf(fp, "           module_core_size_rx: %ld\n",
> >> +		OFFSET(module_core_size_rx));
> >> +	fprintf(fp, "           module_core_size_rw: %ld\n",
> >> +		OFFSET(module_core_size_rw));
> >> +	fprintf(fp, "         module_module_init_rx: %ld\n",
> >> +		OFFSET(module_module_init_rx));
> >> +	fprintf(fp, "         module_module_init_rw: %ld\n",
> >> +		OFFSET(module_module_init_rw));
> >> +	fprintf(fp, "           module_init_size_rx: %ld\n",
> >> +		OFFSET(module_init_size_rx));
> >> +	fprintf(fp, "           module_init_size_rw: %ld\n",
> >> +		OFFSET(module_init_size_rw));
> >>  	fprintf(fp, "             module_num_symtab: %ld\n",
> >>  		OFFSET(module_num_symtab));
> >>  	fprintf(fp, "                 module_symtab: %ld\n",
> >> --
> >> 2.20.1
> >>
> >>
> >> --
> >> Crash-utility mailing list
> >> Crash-utility at redhat.com
> >> https://www.redhat.com/mailman/listinfo/crash-utility
> >
> >
> > --
> > Crash-utility mailing list
> > Crash-utility at redhat.com
> > https://www.redhat.com/mailman/listinfo/crash-utility
> >




More information about the Crash-utility mailing list