diff --git a/doc/patch-author-guide.md b/doc/patch-author-guide.md index f33d027..eea636e 100644 --- a/doc/patch-author-guide.md +++ b/doc/patch-author-guide.md @@ -149,9 +149,63 @@ to prevent patch B from writing to X, if A is already loaded. ### Use a shadow variable If you need to add a field to an existing data structure, or even many existing -data structures, you can use the `kpatch_shadow_*()` functions. +data structures, you can use the `kpatch_shadow_*()` functions: -Example needed (see shadow-newpid.patch in the integration tests directory). +* `kpatch_shadow_alloc` - allocates a new shadow variable associated with a + given object. +* `kpatch_shadow_get` - find and return a pointer to a shadow variable +* `kpatch_shadow_free` - find and free a shadow variable + +Example: The `shadow-newpid.patch` integration test demonstrates the usage of +these functions. + +A shadow PID variable is allocated in `do_fork()` : it is associated with the +current `struct task_struct *p` value, given a string lookup key of "newpid", +sized accordingly, and allocated as per `GFP_KERNEL` flag rules. + +`kpatch_shadow_alloc` returns a pointer to the shadow variable, so we can +dereference and make assignments as usual. In this patch chunk, the shadow +`newpid` is allocated then assigned to a rolling `ctr` counter value: +``` ++ int *newpid; ++ static int ctr = 0; ++ ++ newpid = kpatch_shadow_alloc(p, "newpid", sizeof(*newpid), ++ GFP_KERNEL); ++ if (newpid) ++ *newpid = ctr++; +``` + +A shadow variable may also be accessed via `kpatch_shadow_get`. Here the +patch modifies `task_context_switch_counts()` to fetch the shadow variable +associated with the current `struct task_struct *p` object and a "newpid" tag. +As in the previous patch chunk, the shadow variable pointer may be accessed +as an ordinary pointer type: +``` ++ int *newpid; ++ + seq_put_decimal_ull(m, "voluntary_ctxt_switches:\t", p->nvcsw); + seq_put_decimal_ull(m, "\nnonvoluntary_ctxt_switches:\t", p->nivcsw); + seq_putc(m, '\n'); ++ ++ newpid = kpatch_shadow_get(p, "newpid"); ++ if (newpid) ++ seq_printf(m, "newpid:\t%d\n", *newpid); +``` + +A shadow variable is freed by calling `kpatch_shadow_free` and providing +the object / string key combination. Once freed, the shadow variable is not +safe to access: +``` + exit_task_work(tsk); + exit_thread(tsk); + ++ kpatch_shadow_free(tsk, "newpid"); ++ + /* + * Flush inherited counters to the parent - before the parent + * gets woken up by child-exit notifications. +``` Data semantic changes ---------------------