All of lore.kernel.org
 help / color / mirror / Atom feed
From: Josh Poimboeuf <jpoimboe@redhat.com>
To: Jessica Yu <jeyu@redhat.com>
Cc: Rusty Russell <rusty@rustcorp.com.au>,
	Seth Jennings <sjenning@redhat.com>,
	Jiri Kosina <jikos@kernel.org>, Vojtech Pavlik <vojtech@suse.com>,
	Jonathan Corbet <corbet@lwn.net>, Miroslav Benes <mbenes@suse.cz>,
	linux-api@vger.kernel.org, live-patching@vger.kernel.org,
	x86@kernel.org, linux-kernel@vger.kernel.org,
	linux-s390@vger.kernel.org, linux-doc@vger.kernel.org
Subject: Re: [RFC PATCH v2 4/6] livepatch: reuse module loader code to write relocations
Date: Tue, 8 Dec 2015 12:38:44 -0600	[thread overview]
Message-ID: <20151208183844.GC14846@treble.redhat.com> (raw)
In-Reply-To: <1448943679-3412-5-git-send-email-jeyu@redhat.com>

On Mon, Nov 30, 2015 at 11:21:17PM -0500, Jessica Yu wrote:
> Reuse module loader code to write relocations, thereby eliminating the need
> for architecture specific relocation code in livepatch. Namely, we reuse
> apply_relocate_add() in the module loader to write relocations instead of
> duplicating functionality in livepatch's klp_write_module_reloc(). To apply
> relocation sections, remaining SHN_LIVEPATCH symbols referenced by relocs
> are resolved and then apply_relocate_add() is called to apply those
> relocations.
> 
> In addition, remove x86 livepatch relocation code. It is no longer needed
> since symbol resolution and relocation work have been offloaded to module
> loader.   
> 
> Signed-off-by: Jessica Yu <jeyu@redhat.com>
> ---
>  arch/x86/include/asm/livepatch.h |  2 -
>  arch/x86/kernel/Makefile         |  1 -
>  arch/x86/kernel/livepatch.c      | 91 --------------------------------------
>  include/linux/livepatch.h        | 30 ++++++-------
>  include/linux/module.h           |  6 +++
>  kernel/livepatch/core.c          | 94 ++++++++++++++++++++++------------------
>  6 files changed, 70 insertions(+), 154 deletions(-)
>  delete mode 100644 arch/x86/kernel/livepatch.c
> 
> diff --git a/arch/x86/include/asm/livepatch.h b/arch/x86/include/asm/livepatch.h
> index 19c099a..7312e25 100644
> --- a/arch/x86/include/asm/livepatch.h
> +++ b/arch/x86/include/asm/livepatch.h
> @@ -33,8 +33,6 @@ static inline int klp_check_compiler_support(void)
>  #endif
>  	return 0;
>  }
> -int klp_write_module_reloc(struct module *mod, unsigned long type,
> -			   unsigned long loc, unsigned long value);
>  
>  static inline void klp_arch_set_pc(struct pt_regs *regs, unsigned long ip)
>  {
> diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
> index b1b78ff..c5e9a5c 100644
> --- a/arch/x86/kernel/Makefile
> +++ b/arch/x86/kernel/Makefile
> @@ -67,7 +67,6 @@ obj-$(CONFIG_X86_MPPARSE)	+= mpparse.o
>  obj-y				+= apic/
>  obj-$(CONFIG_X86_REBOOTFIXUPS)	+= reboot_fixups_32.o
>  obj-$(CONFIG_DYNAMIC_FTRACE)	+= ftrace.o
> -obj-$(CONFIG_LIVEPATCH)		+= livepatch.o
>  obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
>  obj-$(CONFIG_FTRACE_SYSCALLS)	+= ftrace.o
>  obj-$(CONFIG_X86_TSC)		+= trace_clock.o
> diff --git a/arch/x86/kernel/livepatch.c b/arch/x86/kernel/livepatch.c
> deleted file mode 100644
> index d1d35cc..0000000
> --- a/arch/x86/kernel/livepatch.c
> +++ /dev/null
> @@ -1,91 +0,0 @@
> -/*
> - * livepatch.c - x86-specific Kernel Live Patching Core
> - *
> - * Copyright (C) 2014 Seth Jennings <sjenning@redhat.com>
> - * Copyright (C) 2014 SUSE
> - *
> - * This program is free software; you can redistribute it and/or
> - * modify it under the terms of the GNU General Public License
> - * as published by the Free Software Foundation; either version 2
> - * of the License, or (at your option) any later version.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> - * GNU General Public License for more details.
> - *
> - * You should have received a copy of the GNU General Public License
> - * along with this program; if not, see <http://www.gnu.org/licenses/>.
> - */
> -
> -#include <linux/module.h>
> -#include <linux/uaccess.h>
> -#include <asm/cacheflush.h>
> -#include <asm/page_types.h>
> -#include <asm/elf.h>
> -#include <asm/livepatch.h>
> -
> -/**
> - * klp_write_module_reloc() - write a relocation in a module
> - * @mod:	module in which the section to be modified is found
> - * @type:	ELF relocation type (see asm/elf.h)
> - * @loc:	address that the relocation should be written to
> - * @value:	relocation value (sym address + addend)
> - *
> - * This function writes a relocation to the specified location for
> - * a particular module.
> - */
> -int klp_write_module_reloc(struct module *mod, unsigned long type,
> -			   unsigned long loc, unsigned long value)
> -{
> -	int ret, numpages, size = 4;
> -	bool readonly;
> -	unsigned long val;
> -	unsigned long core = (unsigned long)mod->module_core;
> -	unsigned long core_size = mod->core_size;
> -
> -	switch (type) {
> -	case R_X86_64_NONE:
> -		return 0;
> -	case R_X86_64_64:
> -		val = value;
> -		size = 8;
> -		break;
> -	case R_X86_64_32:
> -		val = (u32)value;
> -		break;
> -	case R_X86_64_32S:
> -		val = (s32)value;
> -		break;
> -	case R_X86_64_PC32:
> -		val = (u32)(value - loc);
> -		break;
> -	default:
> -		/* unsupported relocation type */
> -		return -EINVAL;
> -	}
> -
> -	if (loc < core || loc >= core + core_size)
> -		/* loc does not point to any symbol inside the module */
> -		return -EINVAL;
> -
> -	readonly = false;
> -
> -#ifdef CONFIG_DEBUG_SET_MODULE_RONX
> -	if (loc < core + mod->core_ro_size)
> -		readonly = true;
> -#endif
> -
> -	/* determine if the relocation spans a page boundary */
> -	numpages = ((loc & PAGE_MASK) == ((loc + size) & PAGE_MASK)) ? 1 : 2;
> -
> -	if (readonly)
> -		set_memory_rw(loc & PAGE_MASK, numpages);
> -
> -	ret = probe_kernel_write((void *)loc, &val, size);
> -
> -	if (readonly)
> -		set_memory_ro(loc & PAGE_MASK, numpages);
> -
> -	return ret;
> -}
> diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h
> index 31db7a0..54f62a6 100644
> --- a/include/linux/livepatch.h
> +++ b/include/linux/livepatch.h
> @@ -64,28 +64,21 @@ struct klp_func {
>  };
>  
>  /**
> - * struct klp_reloc - relocation structure for live patching
> - * @loc:	address where the relocation will be written
> - * @val:	address of the referenced symbol (optional,
> - *		vmlinux	patches only)
> - * @type:	ELF relocation type
> - * @name:	name of the referenced symbol (for lookup/verification)
> - * @addend:	offset from the referenced symbol
> - * @external:	symbol is either exported or within the live patch module itself
> + * struct klp_reloc_sec - relocation section struct for live patching
> + * @index:	Elf section index of the relocation section
> + * @name:	name of the relocation section
> + * @objname:	name of the object associated with the klp reloc section
>   */
> -struct klp_reloc {
> -	unsigned long loc;
> -	unsigned long val;
> -	unsigned long type;
> -	const char *name;
> -	int addend;
> -	int external;
> +struct klp_reloc_sec {
> +	unsigned int index;
> +	char *name;
> +	char *objname;
>  };
>  
>  /**
>   * struct klp_object - kernel object structure for live patching
>   * @name:	module name (or NULL for vmlinux)
> - * @relocs:	relocation entries to be applied at load time
> + * @reloc_secs:	relocation sections to be applied at load time
>   * @funcs:	function entries for functions to be patched in the object
>   * @kobj:	kobject for sysfs resources
>   * @mod:	kernel module associated with the patched object
> @@ -95,7 +88,7 @@ struct klp_reloc {
>  struct klp_object {
>  	/* external */
>  	const char *name;
> -	struct klp_reloc *relocs;
> +	struct klp_reloc_sec *reloc_secs;

There was a lot of discussion for v1, so I'm not sure, but I thought we
ended up deciding to get rid of the klp_reloc_sec struct?  Instead I
think the symbol table can be walked directly looking for klp rela
sections?

The benefits of doing so would be to make the interface simpler -- no
need to "cache" the section metadata when it's already easily and
quickly available in the module struct elf section headers.

>  	struct klp_func *funcs;
>  
>  	/* internal */
> @@ -129,6 +122,9 @@ struct klp_patch {
>  #define klp_for_each_func(obj, func) \
>  	for (func = obj->funcs; func->old_name; func++)
>  
> +#define klp_for_each_reloc_sec(obj, reloc_sec) \
> +	for (reloc_sec = obj->reloc_secs; reloc_sec->name; reloc_sec++)
> +
>  int klp_register_patch(struct klp_patch *);
>  int klp_unregister_patch(struct klp_patch *);
>  int klp_enable_patch(struct klp_patch *);
> diff --git a/include/linux/module.h b/include/linux/module.h
> index 9b46256..ea61147 100644
> --- a/include/linux/module.h
> +++ b/include/linux/module.h
> @@ -777,9 +777,15 @@ extern int module_sysfs_initialized;
>  #ifdef CONFIG_DEBUG_SET_MODULE_RONX
>  extern void set_all_modules_text_rw(void);
>  extern void set_all_modules_text_ro(void);
> +extern void
> +set_page_attributes(void *start, void *end,
> +		    int (*set)(unsigned long start, int num_pages));
>  #else
>  static inline void set_all_modules_text_rw(void) { }
>  static inline void set_all_modules_text_ro(void) { }
> +static inline void
> +set_page_attributes(void *start, void *end,
> +		    int (*set)(unsigned long start, int num_pages)) { }
>  #endif
>  
>  #ifdef CONFIG_GENERIC_BUG
> diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
> index db545cb..17b7278 100644
> --- a/kernel/livepatch/core.c
> +++ b/kernel/livepatch/core.c
> @@ -28,6 +28,9 @@
>  #include <linux/list.h>
>  #include <linux/kallsyms.h>
>  #include <linux/livepatch.h>
> +#include <linux/elf.h>
> +#include <asm/cacheflush.h>
> +#include <linux/moduleloader.h>
>  
>  /**
>   * struct klp_ops - structure for tracking registered ftrace ops structs
> @@ -281,52 +284,48 @@ static int klp_find_external_symbol(struct module *pmod, const char *name,
>  }
>  
>  static int klp_write_object_relocations(struct module *pmod,
> -					struct klp_object *obj)
> +					struct klp_object *obj,
> +					struct klp_patch *patch)
>  {
> -	int ret;
> -	struct klp_reloc *reloc;
> +	int relindex, num_relas;
> +	int i, ret = 0;
> +	unsigned long addr;
> +	char *symname;
> +	struct klp_reloc_sec *reloc_sec;
> +	Elf_Rela *rela;
> +	Elf_Sym *sym, *symtab;
>  
>  	if (WARN_ON(!klp_is_object_loaded(obj)))
>  		return -EINVAL;
>  
> -	if (WARN_ON(!obj->relocs))
> -		return -EINVAL;
> -
> -	for (reloc = obj->relocs; reloc->name; reloc++) {
> -		if (!klp_is_module(obj)) {
> -
> -#if defined(CONFIG_RANDOMIZE_BASE)
> -			/* If KASLR has been enabled, adjust old value accordingly */
> -			if (kaslr_enabled())
> -				reloc->val += kaslr_offset();
> -#endif
> -			ret = klp_verify_vmlinux_symbol(reloc->name,
> -							reloc->val);
> -			if (ret)
> -				return ret;
> -		} else {
> -			/* module, reloc->val needs to be discovered */
> -			if (reloc->external)
> -				ret = klp_find_external_symbol(pmod,
> -							       reloc->name,
> -							       &reloc->val);
> -			else
> -				ret = klp_find_object_symbol(obj->mod->name,
> -							     reloc->name,
> -							     &reloc->val);
> -			if (ret)
> -				return ret;
> -		}
> -		ret = klp_write_module_reloc(pmod, reloc->type, reloc->loc,
> -					     reloc->val + reloc->addend);
> -		if (ret) {
> -			pr_err("relocation failed for symbol '%s' at 0x%016lx (%d)\n",
> -			       reloc->name, reloc->val, ret);
> -			return ret;
> +	symtab = (void *)pmod->core_symtab;
> +
> +	/* For each __klp_rela section for this object */
> +	klp_for_each_reloc_sec(obj, reloc_sec) {
> +		relindex = reloc_sec->index;
> +		num_relas = pmod->sechdrs[relindex].sh_size / sizeof(Elf_Rela);
> +		rela = (Elf_Rela *) pmod->sechdrs[relindex].sh_addr;
> +
> +		/* For each rela in this __klp_rela section */
> +		for (i = 0; i < num_relas; i++, rela++) {
> +			sym = symtab + ELF_R_SYM(rela->r_info);
> +			symname = pmod->core_strtab + sym->st_name;
> +
> +			if (sym->st_shndx == SHN_LIVEPATCH) {
> +				if (sym->st_info == 'K')
> +					ret = klp_find_external_symbol(pmod, symname, &addr);
> +				else
> +					ret = klp_find_object_symbol(obj->name, symname, &addr);
> +				if (ret)
> +					return ret;
> +				sym->st_value = addr;

So I think you're also working on removing the 'external' stuff.  Any
idea how this code will handle that?  Specifically I'm wondering how the
objname and sympos of the rela's symbol will be specified.  Maybe it can
be encoded somehow in one of the symbol fields (st_value)?

> +			}
>  		}
> +		ret = apply_relocate_add(pmod->sechdrs, pmod->core_strtab,
> +					 pmod->index.sym, relindex, pmod);
>  	}
>  
> -	return 0;
> +	return ret;
>  }
>  
>  static void notrace klp_ftrace_handler(unsigned long ip,
> @@ -747,13 +746,22 @@ static int klp_init_object_loaded(struct klp_patch *patch,
>  				  struct klp_object *obj)
>  {
>  	struct klp_func *func;
> +	struct module *pmod;
>  	int ret;
>  
> -	if (obj->relocs) {
> -		ret = klp_write_object_relocations(patch->mod, obj);
> -		if (ret)
> -			return ret;
> -	}
> +	pmod = patch->mod;
> +
> +	set_page_attributes(pmod->module_core,
> +			    pmod->module_core + pmod->core_text_size,
> +			    set_memory_rw);
> +
> +	ret = klp_write_object_relocations(pmod, obj, patch);
> +	if (ret)
> +		return ret;
> +
> +	set_page_attributes(pmod->module_core,
> +			    pmod->module_core + pmod->core_text_size,
> +			    set_memory_ro);
>  
>  	klp_for_each_func(obj, func) {
>  		ret = klp_find_verify_func_addr(obj, func);
> -- 
> 2.4.3
> 
> --
> To unsubscribe from this list: send the line "unsubscribe live-patching" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Josh

  parent reply	other threads:[~2015-12-08 18:38 UTC|newest]

Thread overview: 52+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-12-01  4:21 [RFC PATCH v2 0/6] (mostly) Arch-independent livepatch Jessica Yu
2015-12-01  4:21 ` Jessica Yu
2015-12-01  4:21 ` [RFC PATCH v2 1/6] Elf: add livepatch-specific Elf constants Jessica Yu
2015-12-01  4:21 ` [RFC PATCH v2 2/6] module: preserve Elf information for livepatch modules Jessica Yu
     [not found]   ` <1448943679-3412-3-git-send-email-jeyu-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2015-12-01  8:48     ` Jessica Yu
2015-12-01  8:48       ` Jessica Yu
2015-12-01 21:06   ` Jessica Yu
2015-12-08 18:32   ` [RFC PATCH v2 2/6] " Josh Poimboeuf
     [not found]     ` <20151208183212.GB14846-8wJ5/zUtDR0XGNroddHbYwC/G2K4zDHf@public.gmane.org>
2015-12-09 20:05       ` Jessica Yu
2015-12-09 20:05         ` Jessica Yu
2015-12-10 14:38         ` Josh Poimboeuf
     [not found]           ` <20151210143817.GB29872-8wJ5/zUtDR0XGNroddHbYwC/G2K4zDHf@public.gmane.org>
2015-12-16 10:46             ` Miroslav Benes
2015-12-16 10:46               ` Miroslav Benes
2015-12-17 16:28     ` [RFC PATCH v2 2/6] " Petr Mladek
2015-12-16 10:58   ` Miroslav Benes
2015-12-17  0:40     ` Jessica Yu
2015-12-17 16:26   ` [RFC PATCH v2 2/6] " Petr Mladek
2015-12-21  5:44     ` Jessica Yu
2015-12-01  4:21 ` [RFC PATCH v2 3/6] module: s390: keep mod_arch_specific " Jessica Yu
2015-12-16 12:02   ` Miroslav Benes
     [not found]     ` <alpine.LNX.2.00.1512161257170.25787-ztGlSCb7Y1iN3ZZ/Hiejyg@public.gmane.org>
2015-12-16 23:48       ` Jessica Yu
2015-12-16 23:48         ` Jessica Yu
2015-12-17 11:39         ` Miroslav Benes
2015-12-01  4:21 ` [RFC PATCH v2 4/6] livepatch: reuse module loader code to write relocations Jessica Yu
     [not found]   ` <1448943679-3412-5-git-send-email-jeyu-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2015-12-01  8:43     ` Jessica Yu
2015-12-01  8:43       ` Jessica Yu
2015-12-10 14:20     ` [RFC PATCH v2 4/6] " Minfei Huang
2015-12-10 14:20       ` Minfei Huang
     [not found]       ` <20151210142032.GA2399-4afrMIaGpRkhWf4U84eJi3gqWNq4x99MuOMsETyM3/Q@public.gmane.org>
2015-12-10 19:56         ` Jiri Kosina
2015-12-10 19:56           ` Jiri Kosina
     [not found]           ` <alpine.LNX.2.00.1512102055180.9922-YHPUNQjx9ReKbouaWp301Q@public.gmane.org>
2015-12-10 21:12             ` Josh Poimboeuf
2015-12-10 21:12               ` Josh Poimboeuf
2015-12-08 18:38   ` Josh Poimboeuf [this message]
     [not found]     ` <20151208183844.GC14846-8wJ5/zUtDR0XGNroddHbYwC/G2K4zDHf@public.gmane.org>
2015-12-09 19:10       ` Jessica Yu
2015-12-09 19:10         ` Jessica Yu
     [not found]         ` <20151209191013.GA25387-N0bYjD2NfQ6k4hzjq3hgyGTy53QMssKEsp+A89P3RPuQWHG76I6BsA@public.gmane.org>
2015-12-10 14:28           ` Josh Poimboeuf
2015-12-10 14:28             ` Josh Poimboeuf
2015-12-10 21:33             ` Jessica Yu
     [not found]               ` <20151210213328.GA6553-N0bYjD2NfQ6k4hzjq3hgyGTy53QMssKEsp+A89P3RPuQWHG76I6BsA@public.gmane.org>
2015-12-10 21:41                 ` Josh Poimboeuf
2015-12-10 21:41                   ` Josh Poimboeuf
     [not found]                   ` <20151210214115.GD4934-8wJ5/zUtDR0XGNroddHbYwC/G2K4zDHf@public.gmane.org>
2015-12-10 22:07                     ` Jessica Yu
2015-12-10 22:07                       ` Jessica Yu
2015-12-16  5:40           ` Jessica Yu
2015-12-16  5:40             ` Jessica Yu
2015-12-16 12:59             ` Miroslav Benes
2015-12-16 19:14               ` Jessica Yu
     [not found]             ` <20151216054048.GA28258-N0bYjD2NfQ6k4hzjq3hgyGTy53QMssKEsp+A89P3RPuQWHG76I6BsA@public.gmane.org>
2015-12-17 15:45               ` Petr Mladek
2015-12-17 15:45                 ` Petr Mladek
2015-12-21  5:57                 ` Jessica Yu
2015-12-01  4:21 ` [RFC PATCH v2 5/6] samples: livepatch: init reloc section array and mark as klp module Jessica Yu
2015-12-08 18:41   ` Josh Poimboeuf
2015-12-01  4:21 ` [RFC PATCH v2 6/6] Documentation: livepatch: outline the Elf format of a livepatch module Jessica Yu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20151208183844.GC14846@treble.redhat.com \
    --to=jpoimboe@redhat.com \
    --cc=corbet@lwn.net \
    --cc=jeyu@redhat.com \
    --cc=jikos@kernel.org \
    --cc=linux-api@vger.kernel.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-s390@vger.kernel.org \
    --cc=live-patching@vger.kernel.org \
    --cc=mbenes@suse.cz \
    --cc=rusty@rustcorp.com.au \
    --cc=sjenning@redhat.com \
    --cc=vojtech@suse.com \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.