mirror of
https://github.com/dynup/kpatch
synced 2025-01-27 15:22:46 +00:00
doc: add shadow variable example to patch author guide
Add shadow variable examples and text.
This commit is contained in:
parent
d7aae34a0d
commit
d90b9afbd9
@ -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
|
||||
---------------------
|
||||
|
Loading…
Reference in New Issue
Block a user