mirror of
https://github.com/dynup/kpatch
synced 2025-05-05 17:37:56 +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
|
### Use a shadow variable
|
||||||
|
|
||||||
If you need to add a field to an existing data structure, or even many existing
|
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
|
Data semantic changes
|
||||||
---------------------
|
---------------------
|
||||||
|
Loading…
Reference in New Issue
Block a user