Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
110c1466
Commit
110c1466
authored
Jun 22, 2015
by
Jiri Kosina
Browse files
Options
Browse Files
Download
Plain Diff
Merge branches 'for-4.1/upstream-fixes', 'for-4.2/kaslr' and 'for-4.2/upstream' into for-linus
parents
9a1bd63c
535b3ddc
26029d88
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
66 additions
and
33 deletions
+66
-33
arch/x86/include/asm/livepatch.h
arch/x86/include/asm/livepatch.h
+1
-0
arch/x86/include/asm/setup.h
arch/x86/include/asm/setup.h
+7
-0
arch/x86/kernel/machine_kexec_64.c
arch/x86/kernel/machine_kexec_64.c
+2
-1
arch/x86/kernel/setup.c
arch/x86/kernel/setup.c
+1
-1
include/linux/livepatch.h
include/linux/livepatch.h
+7
-1
kernel/livepatch/core.c
kernel/livepatch/core.c
+48
-30
No files found.
arch/x86/include/asm/livepatch.h
View file @
110c1466
...
@@ -21,6 +21,7 @@
...
@@ -21,6 +21,7 @@
#ifndef _ASM_X86_LIVEPATCH_H
#ifndef _ASM_X86_LIVEPATCH_H
#define _ASM_X86_LIVEPATCH_H
#define _ASM_X86_LIVEPATCH_H
#include <asm/setup.h>
#include <linux/module.h>
#include <linux/module.h>
#include <linux/ftrace.h>
#include <linux/ftrace.h>
...
...
arch/x86/include/asm/setup.h
View file @
110c1466
...
@@ -60,17 +60,24 @@ static inline void x86_ce4100_early_setup(void) { }
...
@@ -60,17 +60,24 @@ static inline void x86_ce4100_early_setup(void) { }
#ifndef _SETUP
#ifndef _SETUP
#include <asm/espfix.h>
#include <asm/espfix.h>
#include <linux/kernel.h>
/*
/*
* This is set up by the setup-routine at boot-time
* This is set up by the setup-routine at boot-time
*/
*/
extern
struct
boot_params
boot_params
;
extern
struct
boot_params
boot_params
;
extern
char
_text
[];
static
inline
bool
kaslr_enabled
(
void
)
static
inline
bool
kaslr_enabled
(
void
)
{
{
return
!!
(
boot_params
.
hdr
.
loadflags
&
KASLR_FLAG
);
return
!!
(
boot_params
.
hdr
.
loadflags
&
KASLR_FLAG
);
}
}
static
inline
unsigned
long
kaslr_offset
(
void
)
{
return
(
unsigned
long
)
&
_text
-
__START_KERNEL
;
}
/*
/*
* Do NOT EVER look at the BIOS memory size location.
* Do NOT EVER look at the BIOS memory size location.
* It does not work on many machines.
* It does not work on many machines.
...
...
arch/x86/kernel/machine_kexec_64.c
View file @
110c1466
...
@@ -25,6 +25,7 @@
...
@@ -25,6 +25,7 @@
#include <asm/io_apic.h>
#include <asm/io_apic.h>
#include <asm/debugreg.h>
#include <asm/debugreg.h>
#include <asm/kexec-bzimage64.h>
#include <asm/kexec-bzimage64.h>
#include <asm/setup.h>
#ifdef CONFIG_KEXEC_FILE
#ifdef CONFIG_KEXEC_FILE
static
struct
kexec_file_ops
*
kexec_file_loaders
[]
=
{
static
struct
kexec_file_ops
*
kexec_file_loaders
[]
=
{
...
@@ -334,7 +335,7 @@ void arch_crash_save_vmcoreinfo(void)
...
@@ -334,7 +335,7 @@ void arch_crash_save_vmcoreinfo(void)
VMCOREINFO_LENGTH
(
node_data
,
MAX_NUMNODES
);
VMCOREINFO_LENGTH
(
node_data
,
MAX_NUMNODES
);
#endif
#endif
vmcoreinfo_append_str
(
"KERNELOFFSET=%lx
\n
"
,
vmcoreinfo_append_str
(
"KERNELOFFSET=%lx
\n
"
,
(
unsigned
long
)
&
_text
-
__START_KERNEL
);
kaslr_offset
()
);
}
}
/* arch-dependent functionality related to kexec file-based syscall */
/* arch-dependent functionality related to kexec file-based syscall */
...
...
arch/x86/kernel/setup.c
View file @
110c1466
...
@@ -834,7 +834,7 @@ dump_kernel_offset(struct notifier_block *self, unsigned long v, void *p)
...
@@ -834,7 +834,7 @@ dump_kernel_offset(struct notifier_block *self, unsigned long v, void *p)
{
{
if
(
kaslr_enabled
())
{
if
(
kaslr_enabled
())
{
pr_emerg
(
"Kernel Offset: 0x%lx from 0x%lx (relocation range: 0x%lx-0x%lx)
\n
"
,
pr_emerg
(
"Kernel Offset: 0x%lx from 0x%lx (relocation range: 0x%lx-0x%lx)
\n
"
,
(
unsigned
long
)
&
_text
-
__START_KERNEL
,
kaslr_offset
()
,
__START_KERNEL
,
__START_KERNEL
,
__START_KERNEL_map
,
__START_KERNEL_map
,
MODULES_VADDR
-
1
);
MODULES_VADDR
-
1
);
...
...
include/linux/livepatch.h
View file @
110c1466
...
@@ -99,7 +99,7 @@ struct klp_object {
...
@@ -99,7 +99,7 @@ struct klp_object {
struct
klp_func
*
funcs
;
struct
klp_func
*
funcs
;
/* internal */
/* internal */
struct
kobject
*
kobj
;
struct
kobject
kobj
;
struct
module
*
mod
;
struct
module
*
mod
;
enum
klp_state
state
;
enum
klp_state
state
;
};
};
...
@@ -123,6 +123,12 @@ struct klp_patch {
...
@@ -123,6 +123,12 @@ struct klp_patch {
enum
klp_state
state
;
enum
klp_state
state
;
};
};
#define klp_for_each_object(patch, obj) \
for (obj = patch->objs; obj->funcs; obj++)
#define klp_for_each_func(obj, func) \
for (func = obj->funcs; func->old_name; func++)
int
klp_register_patch
(
struct
klp_patch
*
);
int
klp_register_patch
(
struct
klp_patch
*
);
int
klp_unregister_patch
(
struct
klp_patch
*
);
int
klp_unregister_patch
(
struct
klp_patch
*
);
int
klp_enable_patch
(
struct
klp_patch
*
);
int
klp_enable_patch
(
struct
klp_patch
*
);
...
...
kernel/livepatch/core.c
View file @
110c1466
...
@@ -128,7 +128,7 @@ static bool klp_is_patch_registered(struct klp_patch *patch)
...
@@ -128,7 +128,7 @@ static bool klp_is_patch_registered(struct klp_patch *patch)
static
bool
klp_initialized
(
void
)
static
bool
klp_initialized
(
void
)
{
{
return
klp_root_kobj
;
return
!!
klp_root_kobj
;
}
}
struct
klp_find_arg
{
struct
klp_find_arg
{
...
@@ -242,8 +242,9 @@ static int klp_find_verify_func_addr(struct klp_object *obj,
...
@@ -242,8 +242,9 @@ static int klp_find_verify_func_addr(struct klp_object *obj,
int
ret
;
int
ret
;
#if defined(CONFIG_RANDOMIZE_BASE)
#if defined(CONFIG_RANDOMIZE_BASE)
/* KASLR is enabled, disregard old_addr from user */
/* If KASLR has been enabled, adjust old_addr accordingly */
func
->
old_addr
=
0
;
if
(
kaslr_enabled
()
&&
func
->
old_addr
)
func
->
old_addr
+=
kaslr_offset
();
#endif
#endif
if
(
!
func
->
old_addr
||
klp_is_module
(
obj
))
if
(
!
func
->
old_addr
||
klp_is_module
(
obj
))
...
@@ -430,7 +431,7 @@ static void klp_disable_object(struct klp_object *obj)
...
@@ -430,7 +431,7 @@ static void klp_disable_object(struct klp_object *obj)
{
{
struct
klp_func
*
func
;
struct
klp_func
*
func
;
for
(
func
=
obj
->
funcs
;
func
->
old_name
;
func
++
)
klp_for_each_func
(
obj
,
func
)
if
(
func
->
state
==
KLP_ENABLED
)
if
(
func
->
state
==
KLP_ENABLED
)
klp_disable_func
(
func
);
klp_disable_func
(
func
);
...
@@ -448,7 +449,7 @@ static int klp_enable_object(struct klp_object *obj)
...
@@ -448,7 +449,7 @@ static int klp_enable_object(struct klp_object *obj)
if
(
WARN_ON
(
!
klp_is_object_loaded
(
obj
)))
if
(
WARN_ON
(
!
klp_is_object_loaded
(
obj
)))
return
-
EINVAL
;
return
-
EINVAL
;
for
(
func
=
obj
->
funcs
;
func
->
old_name
;
func
++
)
{
klp_for_each_func
(
obj
,
func
)
{
ret
=
klp_enable_func
(
func
);
ret
=
klp_enable_func
(
func
);
if
(
ret
)
{
if
(
ret
)
{
klp_disable_object
(
obj
);
klp_disable_object
(
obj
);
...
@@ -471,7 +472,7 @@ static int __klp_disable_patch(struct klp_patch *patch)
...
@@ -471,7 +472,7 @@ static int __klp_disable_patch(struct klp_patch *patch)
pr_notice
(
"disabling patch '%s'
\n
"
,
patch
->
mod
->
name
);
pr_notice
(
"disabling patch '%s'
\n
"
,
patch
->
mod
->
name
);
for
(
obj
=
patch
->
objs
;
obj
->
funcs
;
obj
++
)
{
klp_for_each_object
(
patch
,
obj
)
{
if
(
obj
->
state
==
KLP_ENABLED
)
if
(
obj
->
state
==
KLP_ENABLED
)
klp_disable_object
(
obj
);
klp_disable_object
(
obj
);
}
}
...
@@ -531,7 +532,7 @@ static int __klp_enable_patch(struct klp_patch *patch)
...
@@ -531,7 +532,7 @@ static int __klp_enable_patch(struct klp_patch *patch)
pr_notice
(
"enabling patch '%s'
\n
"
,
patch
->
mod
->
name
);
pr_notice
(
"enabling patch '%s'
\n
"
,
patch
->
mod
->
name
);
for
(
obj
=
patch
->
objs
;
obj
->
funcs
;
obj
++
)
{
klp_for_each_object
(
patch
,
obj
)
{
if
(
!
klp_is_object_loaded
(
obj
))
if
(
!
klp_is_object_loaded
(
obj
))
continue
;
continue
;
...
@@ -659,6 +660,15 @@ static struct kobj_type klp_ktype_patch = {
...
@@ -659,6 +660,15 @@ static struct kobj_type klp_ktype_patch = {
.
default_attrs
=
klp_patch_attrs
,
.
default_attrs
=
klp_patch_attrs
,
};
};
static
void
klp_kobj_release_object
(
struct
kobject
*
kobj
)
{
}
static
struct
kobj_type
klp_ktype_object
=
{
.
release
=
klp_kobj_release_object
,
.
sysfs_ops
=
&
kobj_sysfs_ops
,
};
static
void
klp_kobj_release_func
(
struct
kobject
*
kobj
)
static
void
klp_kobj_release_func
(
struct
kobject
*
kobj
)
{
{
}
}
...
@@ -688,7 +698,7 @@ static void klp_free_object_loaded(struct klp_object *obj)
...
@@ -688,7 +698,7 @@ static void klp_free_object_loaded(struct klp_object *obj)
obj
->
mod
=
NULL
;
obj
->
mod
=
NULL
;
for
(
func
=
obj
->
funcs
;
func
->
old_name
;
func
++
)
klp_for_each_func
(
obj
,
func
)
func
->
old_addr
=
0
;
func
->
old_addr
=
0
;
}
}
...
@@ -703,7 +713,7 @@ static void klp_free_objects_limited(struct klp_patch *patch,
...
@@ -703,7 +713,7 @@ static void klp_free_objects_limited(struct klp_patch *patch,
for
(
obj
=
patch
->
objs
;
obj
->
funcs
&&
obj
!=
limit
;
obj
++
)
{
for
(
obj
=
patch
->
objs
;
obj
->
funcs
&&
obj
!=
limit
;
obj
++
)
{
klp_free_funcs_limited
(
obj
,
NULL
);
klp_free_funcs_limited
(
obj
,
NULL
);
kobject_put
(
obj
->
kobj
);
kobject_put
(
&
obj
->
kobj
);
}
}
}
}
...
@@ -721,7 +731,7 @@ static int klp_init_func(struct klp_object *obj, struct klp_func *func)
...
@@ -721,7 +731,7 @@ static int klp_init_func(struct klp_object *obj, struct klp_func *func)
func
->
state
=
KLP_DISABLED
;
func
->
state
=
KLP_DISABLED
;
return
kobject_init_and_add
(
&
func
->
kobj
,
&
klp_ktype_func
,
return
kobject_init_and_add
(
&
func
->
kobj
,
&
klp_ktype_func
,
obj
->
kobj
,
"%s"
,
func
->
old_name
);
&
obj
->
kobj
,
"%s"
,
func
->
old_name
);
}
}
/* parts of the initialization that is done only when the object is loaded */
/* parts of the initialization that is done only when the object is loaded */
...
@@ -737,7 +747,7 @@ static int klp_init_object_loaded(struct klp_patch *patch,
...
@@ -737,7 +747,7 @@ static int klp_init_object_loaded(struct klp_patch *patch,
return
ret
;
return
ret
;
}
}
for
(
func
=
obj
->
funcs
;
func
->
old_name
;
func
++
)
{
klp_for_each_func
(
obj
,
func
)
{
ret
=
klp_find_verify_func_addr
(
obj
,
func
);
ret
=
klp_find_verify_func_addr
(
obj
,
func
);
if
(
ret
)
if
(
ret
)
return
ret
;
return
ret
;
...
@@ -761,11 +771,12 @@ static int klp_init_object(struct klp_patch *patch, struct klp_object *obj)
...
@@ -761,11 +771,12 @@ static int klp_init_object(struct klp_patch *patch, struct klp_object *obj)
klp_find_object_module
(
obj
);
klp_find_object_module
(
obj
);
name
=
klp_is_module
(
obj
)
?
obj
->
name
:
"vmlinux"
;
name
=
klp_is_module
(
obj
)
?
obj
->
name
:
"vmlinux"
;
obj
->
kobj
=
kobject_create_and_add
(
name
,
&
patch
->
kobj
);
ret
=
kobject_init_and_add
(
&
obj
->
kobj
,
&
klp_ktype_object
,
if
(
!
obj
->
kobj
)
&
patch
->
kobj
,
"%s"
,
name
);
return
-
ENOMEM
;
if
(
ret
)
return
ret
;
for
(
func
=
obj
->
funcs
;
func
->
old_name
;
func
++
)
{
klp_for_each_func
(
obj
,
func
)
{
ret
=
klp_init_func
(
obj
,
func
);
ret
=
klp_init_func
(
obj
,
func
);
if
(
ret
)
if
(
ret
)
goto
free
;
goto
free
;
...
@@ -781,7 +792,7 @@ static int klp_init_object(struct klp_patch *patch, struct klp_object *obj)
...
@@ -781,7 +792,7 @@ static int klp_init_object(struct klp_patch *patch, struct klp_object *obj)
free:
free:
klp_free_funcs_limited
(
obj
,
func
);
klp_free_funcs_limited
(
obj
,
func
);
kobject_put
(
obj
->
kobj
);
kobject_put
(
&
obj
->
kobj
);
return
ret
;
return
ret
;
}
}
...
@@ -802,7 +813,7 @@ static int klp_init_patch(struct klp_patch *patch)
...
@@ -802,7 +813,7 @@ static int klp_init_patch(struct klp_patch *patch)
if
(
ret
)
if
(
ret
)
goto
unlock
;
goto
unlock
;
for
(
obj
=
patch
->
objs
;
obj
->
funcs
;
obj
++
)
{
klp_for_each_object
(
patch
,
obj
)
{
ret
=
klp_init_object
(
patch
,
obj
);
ret
=
klp_init_object
(
patch
,
obj
);
if
(
ret
)
if
(
ret
)
goto
free
;
goto
free
;
...
@@ -891,7 +902,7 @@ int klp_register_patch(struct klp_patch *patch)
...
@@ -891,7 +902,7 @@ int klp_register_patch(struct klp_patch *patch)
}
}
EXPORT_SYMBOL_GPL
(
klp_register_patch
);
EXPORT_SYMBOL_GPL
(
klp_register_patch
);
static
void
klp_module_notify_coming
(
struct
klp_patch
*
patch
,
static
int
klp_module_notify_coming
(
struct
klp_patch
*
patch
,
struct
klp_object
*
obj
)
struct
klp_object
*
obj
)
{
{
struct
module
*
pmod
=
patch
->
mod
;
struct
module
*
pmod
=
patch
->
mod
;
...
@@ -899,22 +910,23 @@ static void klp_module_notify_coming(struct klp_patch *patch,
...
@@ -899,22 +910,23 @@ static void klp_module_notify_coming(struct klp_patch *patch,
int
ret
;
int
ret
;
ret
=
klp_init_object_loaded
(
patch
,
obj
);
ret
=
klp_init_object_loaded
(
patch
,
obj
);
if
(
ret
)
if
(
ret
)
{
goto
err
;
pr_warn
(
"failed to initialize patch '%s' for module '%s' (%d)
\n
"
,
pmod
->
name
,
mod
->
name
,
ret
);
return
ret
;
}
if
(
patch
->
state
==
KLP_DISABLED
)
if
(
patch
->
state
==
KLP_DISABLED
)
return
;
return
0
;
pr_notice
(
"applying patch '%s' to loading module '%s'
\n
"
,
pr_notice
(
"applying patch '%s' to loading module '%s'
\n
"
,
pmod
->
name
,
mod
->
name
);
pmod
->
name
,
mod
->
name
);
ret
=
klp_enable_object
(
obj
);
ret
=
klp_enable_object
(
obj
);
if
(
!
ret
)
if
(
ret
)
return
;
pr_warn
(
"failed to apply patch '%s' to module '%s' (%d)
\n
"
,
pmod
->
name
,
mod
->
name
,
ret
);
err:
return
ret
;
pr_warn
(
"failed to apply patch '%s' to module '%s' (%d)
\n
"
,
pmod
->
name
,
mod
->
name
,
ret
);
}
}
static
void
klp_module_notify_going
(
struct
klp_patch
*
patch
,
static
void
klp_module_notify_going
(
struct
klp_patch
*
patch
,
...
@@ -938,6 +950,7 @@ static void klp_module_notify_going(struct klp_patch *patch,
...
@@ -938,6 +950,7 @@ static void klp_module_notify_going(struct klp_patch *patch,
static
int
klp_module_notify
(
struct
notifier_block
*
nb
,
unsigned
long
action
,
static
int
klp_module_notify
(
struct
notifier_block
*
nb
,
unsigned
long
action
,
void
*
data
)
void
*
data
)
{
{
int
ret
;
struct
module
*
mod
=
data
;
struct
module
*
mod
=
data
;
struct
klp_patch
*
patch
;
struct
klp_patch
*
patch
;
struct
klp_object
*
obj
;
struct
klp_object
*
obj
;
...
@@ -957,13 +970,18 @@ static int klp_module_notify(struct notifier_block *nb, unsigned long action,
...
@@ -957,13 +970,18 @@ static int klp_module_notify(struct notifier_block *nb, unsigned long action,
mod
->
klp_alive
=
false
;
mod
->
klp_alive
=
false
;
list_for_each_entry
(
patch
,
&
klp_patches
,
list
)
{
list_for_each_entry
(
patch
,
&
klp_patches
,
list
)
{
for
(
obj
=
patch
->
objs
;
obj
->
funcs
;
obj
++
)
{
klp_for_each_object
(
patch
,
obj
)
{
if
(
!
klp_is_module
(
obj
)
||
strcmp
(
obj
->
name
,
mod
->
name
))
if
(
!
klp_is_module
(
obj
)
||
strcmp
(
obj
->
name
,
mod
->
name
))
continue
;
continue
;
if
(
action
==
MODULE_STATE_COMING
)
{
if
(
action
==
MODULE_STATE_COMING
)
{
obj
->
mod
=
mod
;
obj
->
mod
=
mod
;
klp_module_notify_coming
(
patch
,
obj
);
ret
=
klp_module_notify_coming
(
patch
,
obj
);
if
(
ret
)
{
obj
->
mod
=
NULL
;
pr_warn
(
"patch '%s' is in an inconsistent state!
\n
"
,
patch
->
mod
->
name
);
}
}
else
/* MODULE_STATE_GOING */
}
else
/* MODULE_STATE_GOING */
klp_module_notify_going
(
patch
,
obj
);
klp_module_notify_going
(
patch
,
obj
);
...
@@ -981,7 +999,7 @@ static struct notifier_block klp_module_nb = {
...
@@ -981,7 +999,7 @@ static struct notifier_block klp_module_nb = {
.
priority
=
INT_MIN
+
1
,
/* called late but before ftrace notifier */
.
priority
=
INT_MIN
+
1
,
/* called late but before ftrace notifier */
};
};
static
int
klp_init
(
void
)
static
int
__init
klp_init
(
void
)
{
{
int
ret
;
int
ret
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment