dynup/kpatch — pull request #380 by jpoimboe (2014-08-29 17:07:46+00:00)
Title: RFC: add support for shadow variables

This adds support for shadow variables, which allow you to add new
"shadow" fields to existing data structures.

NOTICE: To use this feature, you have to tell kpatch-build exactly which
object files are affected by using the -t option. For example, if the
patch modifies fs/proc/array.c, kernel/exit.c, and kernel/fork.c:

kpatch-build -t fs/proc/array.o -t kernel/exit.o -t kernel/fork.o my.patch

This limitation is caused by the fact that the kpatch core module
(kpatch.ko) is a module, so the link step of the patched kernel fails
when it can't link to the kpatch_shadow_* functions. If the core module
gets statically compiled into the kernel, this limitation goes away.

Fixes #314.

It works with the following test patch:
```
Index: src/kernel/fork.c
===================================================================
--- src.orig/kernel/fork.c
+++ src/kernel/fork.c
@@ -1572,6 +1572,7 @@ struct task_struct *fork_idle(int cpu)
* It copies the process, and if successful kick-starts
* it and waits for it to finish using the VM if required.
*/
+#include "kpatch-macros.h"
long do_fork(unsigned long clone_flags,
unsigned long stack_start,
unsigned long stack_size,
@@ -1622,6 +1623,12 @@ long do_fork(unsigned long clone_flags,
if (!IS_ERR(p)) {
struct completion vfork;
struct pid *pid;
+	int *newpid;
+	static int ctr = 0;
+
+	KPATCH_SHADOW_CREATE(p, newpid, GFP_KERNEL);
+	if (newpid)
+	*newpid = ctr++;

trace_sched_process_fork(current, p);

Index: src/fs/proc/array.c
===================================================================
--- src.orig/fs/proc/array.c
+++ src/fs/proc/array.c
@@ -337,13 +337,20 @@ static inline void task_seccomp(struct s
#endif
}

+#include "kpatch-macros.h"
static inline void task_context_switch_counts(struct seq_file *m,
struct task_struct *p)
{
+	int *newpid;
+
seq_printf(m,	"voluntary_ctxt_switches:\t%lu\n"
"nonvoluntary_ctxt_switches:\t%lu\n",
p->nvcsw,
p->nivcsw);
+
+	KPATCH_SHADOW_GET(p, newpid);
+	if (newpid)
+	seq_printf(m, "newpid:\t%d\n", *newpid);
}

static void task_cpus_allowed(struct seq_file *m, struct task_struct *task)
Index: src/kernel/exit.c
===================================================================
--- src.orig/kernel/exit.c
+++ src/kernel/exit.c
@@ -694,10 +694,12 @@ static void check_stack_usage(void)
static inline void check_stack_usage(void) {}
#endif

+#include "kpatch-macros.h"
void do_exit(long code)
{
struct task_struct *tsk = current;
int group_dead;
+	int *newpid;

profile_task_exit(tsk);

@@ -790,6 +792,8 @@ void do_exit(long code)
exit_task_work(tsk);
exit_thread();

+	KPATCH_SHADOW_DESTROY(tsk, newpid);
+
/*
* Flush inherited counters to the parent - before the parent
* gets woken up by child-exit notifications.
```
With the following arguments to kpatch-build:
```
kpatch-build -t fs/proc/array.o -t kernel/exit.o -t kernel/fork.o fork-shadow.patch
```
With this patch loaded, any new tasks get a new "newpid" field which can be seen in `/proc//status`.