xref: /linux-6.15/kernel/livepatch/shadow.c (revision e91c2518)
1439e7271SJoe Lawrence /*
2439e7271SJoe Lawrence  * shadow.c - Shadow Variables
3439e7271SJoe Lawrence  *
4439e7271SJoe Lawrence  * Copyright (C) 2014 Josh Poimboeuf <[email protected]>
5439e7271SJoe Lawrence  * Copyright (C) 2014 Seth Jennings <[email protected]>
6439e7271SJoe Lawrence  * Copyright (C) 2017 Joe Lawrence <[email protected]>
7439e7271SJoe Lawrence  *
8439e7271SJoe Lawrence  * This program is free software; you can redistribute it and/or
9439e7271SJoe Lawrence  * modify it under the terms of the GNU General Public License
10439e7271SJoe Lawrence  * as published by the Free Software Foundation; either version 2
11439e7271SJoe Lawrence  * of the License, or (at your option) any later version.
12439e7271SJoe Lawrence  *
13439e7271SJoe Lawrence  * This program is distributed in the hope that it will be useful,
14439e7271SJoe Lawrence  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15439e7271SJoe Lawrence  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16439e7271SJoe Lawrence  * GNU General Public License for more details.
17439e7271SJoe Lawrence  *
18439e7271SJoe Lawrence  * You should have received a copy of the GNU General Public License
19439e7271SJoe Lawrence  * along with this program; if not, see <http://www.gnu.org/licenses/>.
20439e7271SJoe Lawrence  */
21439e7271SJoe Lawrence 
22439e7271SJoe Lawrence /**
23439e7271SJoe Lawrence  * DOC: Shadow variable API concurrency notes:
24439e7271SJoe Lawrence  *
25439e7271SJoe Lawrence  * The shadow variable API provides a simple relationship between an
26439e7271SJoe Lawrence  * <obj, id> pair and a pointer value.  It is the responsibility of the
27439e7271SJoe Lawrence  * caller to provide any mutual exclusion required of the shadow data.
28439e7271SJoe Lawrence  *
29439e7271SJoe Lawrence  * Once a shadow variable is attached to its parent object via the
30439e7271SJoe Lawrence  * klp_shadow_*alloc() API calls, it is considered live: any subsequent
31439e7271SJoe Lawrence  * call to klp_shadow_get() may then return the shadow variable's data
32439e7271SJoe Lawrence  * pointer.  Callers of klp_shadow_*alloc() should prepare shadow data
33439e7271SJoe Lawrence  * accordingly.
34439e7271SJoe Lawrence  *
35439e7271SJoe Lawrence  * The klp_shadow_*alloc() API calls may allocate memory for new shadow
36439e7271SJoe Lawrence  * variable structures.  Their implementation does not call kmalloc
37439e7271SJoe Lawrence  * inside any spinlocks, but API callers should pass GFP flags according
38439e7271SJoe Lawrence  * to their specific needs.
39439e7271SJoe Lawrence  *
40439e7271SJoe Lawrence  * The klp_shadow_hash is an RCU-enabled hashtable and is safe against
41439e7271SJoe Lawrence  * concurrent klp_shadow_free() and klp_shadow_get() operations.
42439e7271SJoe Lawrence  */
43439e7271SJoe Lawrence 
44439e7271SJoe Lawrence #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
45439e7271SJoe Lawrence 
46439e7271SJoe Lawrence #include <linux/hashtable.h>
47439e7271SJoe Lawrence #include <linux/slab.h>
48439e7271SJoe Lawrence #include <linux/livepatch.h>
49439e7271SJoe Lawrence 
50439e7271SJoe Lawrence static DEFINE_HASHTABLE(klp_shadow_hash, 12);
51439e7271SJoe Lawrence 
52439e7271SJoe Lawrence /*
53439e7271SJoe Lawrence  * klp_shadow_lock provides exclusive access to the klp_shadow_hash and
54439e7271SJoe Lawrence  * the shadow variables it references.
55439e7271SJoe Lawrence  */
56439e7271SJoe Lawrence static DEFINE_SPINLOCK(klp_shadow_lock);
57439e7271SJoe Lawrence 
58439e7271SJoe Lawrence /**
59439e7271SJoe Lawrence  * struct klp_shadow - shadow variable structure
60439e7271SJoe Lawrence  * @node:	klp_shadow_hash hash table node
61439e7271SJoe Lawrence  * @rcu_head:	RCU is used to safely free this structure
62439e7271SJoe Lawrence  * @obj:	pointer to parent object
63439e7271SJoe Lawrence  * @id:		data identifier
64439e7271SJoe Lawrence  * @data:	data area
65439e7271SJoe Lawrence  */
66439e7271SJoe Lawrence struct klp_shadow {
67439e7271SJoe Lawrence 	struct hlist_node node;
68439e7271SJoe Lawrence 	struct rcu_head rcu_head;
69439e7271SJoe Lawrence 	void *obj;
70439e7271SJoe Lawrence 	unsigned long id;
71439e7271SJoe Lawrence 	char data[];
72439e7271SJoe Lawrence };
73439e7271SJoe Lawrence 
74439e7271SJoe Lawrence /**
75439e7271SJoe Lawrence  * klp_shadow_match() - verify a shadow variable matches given <obj, id>
76439e7271SJoe Lawrence  * @shadow:	shadow variable to match
77439e7271SJoe Lawrence  * @obj:	pointer to parent object
78439e7271SJoe Lawrence  * @id:		data identifier
79439e7271SJoe Lawrence  *
80439e7271SJoe Lawrence  * Return: true if the shadow variable matches.
81439e7271SJoe Lawrence  */
82439e7271SJoe Lawrence static inline bool klp_shadow_match(struct klp_shadow *shadow, void *obj,
83439e7271SJoe Lawrence 				unsigned long id)
84439e7271SJoe Lawrence {
85439e7271SJoe Lawrence 	return shadow->obj == obj && shadow->id == id;
86439e7271SJoe Lawrence }
87439e7271SJoe Lawrence 
88439e7271SJoe Lawrence /**
89439e7271SJoe Lawrence  * klp_shadow_get() - retrieve a shadow variable data pointer
90439e7271SJoe Lawrence  * @obj:	pointer to parent object
91439e7271SJoe Lawrence  * @id:		data identifier
92439e7271SJoe Lawrence  *
93439e7271SJoe Lawrence  * Return: the shadow variable data element, NULL on failure.
94439e7271SJoe Lawrence  */
95439e7271SJoe Lawrence void *klp_shadow_get(void *obj, unsigned long id)
96439e7271SJoe Lawrence {
97439e7271SJoe Lawrence 	struct klp_shadow *shadow;
98439e7271SJoe Lawrence 
99439e7271SJoe Lawrence 	rcu_read_lock();
100439e7271SJoe Lawrence 
101439e7271SJoe Lawrence 	hash_for_each_possible_rcu(klp_shadow_hash, shadow, node,
102439e7271SJoe Lawrence 				   (unsigned long)obj) {
103439e7271SJoe Lawrence 
104439e7271SJoe Lawrence 		if (klp_shadow_match(shadow, obj, id)) {
105439e7271SJoe Lawrence 			rcu_read_unlock();
106439e7271SJoe Lawrence 			return shadow->data;
107439e7271SJoe Lawrence 		}
108439e7271SJoe Lawrence 	}
109439e7271SJoe Lawrence 
110439e7271SJoe Lawrence 	rcu_read_unlock();
111439e7271SJoe Lawrence 
112439e7271SJoe Lawrence 	return NULL;
113439e7271SJoe Lawrence }
114439e7271SJoe Lawrence EXPORT_SYMBOL_GPL(klp_shadow_get);
115439e7271SJoe Lawrence 
116*e91c2518SPetr Mladek static void *__klp_shadow_get_or_alloc(void *obj, unsigned long id,
117*e91c2518SPetr Mladek 				       size_t size, gfp_t gfp_flags,
118*e91c2518SPetr Mladek 				       klp_shadow_ctor_t ctor, void *ctor_data,
119*e91c2518SPetr Mladek 				       bool warn_on_exist)
120439e7271SJoe Lawrence {
121439e7271SJoe Lawrence 	struct klp_shadow *new_shadow;
122439e7271SJoe Lawrence 	void *shadow_data;
123439e7271SJoe Lawrence 	unsigned long flags;
124439e7271SJoe Lawrence 
125439e7271SJoe Lawrence 	/* Check if the shadow variable already exists */
126439e7271SJoe Lawrence 	shadow_data = klp_shadow_get(obj, id);
127439e7271SJoe Lawrence 	if (shadow_data)
128439e7271SJoe Lawrence 		goto exists;
129439e7271SJoe Lawrence 
130*e91c2518SPetr Mladek 	/*
131*e91c2518SPetr Mladek 	 * Allocate a new shadow variable.  Fill it with zeroes by default.
132*e91c2518SPetr Mladek 	 * More complex setting can be done by @ctor function.  But it is
133*e91c2518SPetr Mladek 	 * called only when the buffer is really used (under klp_shadow_lock).
134*e91c2518SPetr Mladek 	 */
135439e7271SJoe Lawrence 	new_shadow = kzalloc(size + sizeof(*new_shadow), gfp_flags);
136439e7271SJoe Lawrence 	if (!new_shadow)
137439e7271SJoe Lawrence 		return NULL;
138439e7271SJoe Lawrence 
139439e7271SJoe Lawrence 	/* Look for <obj, id> again under the lock */
140439e7271SJoe Lawrence 	spin_lock_irqsave(&klp_shadow_lock, flags);
141439e7271SJoe Lawrence 	shadow_data = klp_shadow_get(obj, id);
142439e7271SJoe Lawrence 	if (unlikely(shadow_data)) {
143439e7271SJoe Lawrence 		/*
144439e7271SJoe Lawrence 		 * Shadow variable was found, throw away speculative
145439e7271SJoe Lawrence 		 * allocation.
146439e7271SJoe Lawrence 		 */
147439e7271SJoe Lawrence 		spin_unlock_irqrestore(&klp_shadow_lock, flags);
148439e7271SJoe Lawrence 		kfree(new_shadow);
149439e7271SJoe Lawrence 		goto exists;
150439e7271SJoe Lawrence 	}
151439e7271SJoe Lawrence 
152*e91c2518SPetr Mladek 	new_shadow->obj = obj;
153*e91c2518SPetr Mladek 	new_shadow->id = id;
154*e91c2518SPetr Mladek 
155*e91c2518SPetr Mladek 	if (ctor) {
156*e91c2518SPetr Mladek 		int err;
157*e91c2518SPetr Mladek 
158*e91c2518SPetr Mladek 		err = ctor(obj, new_shadow->data, ctor_data);
159*e91c2518SPetr Mladek 		if (err) {
160*e91c2518SPetr Mladek 			spin_unlock_irqrestore(&klp_shadow_lock, flags);
161*e91c2518SPetr Mladek 			kfree(new_shadow);
162*e91c2518SPetr Mladek 			pr_err("Failed to construct shadow variable <%p, %lx> (%d)\n",
163*e91c2518SPetr Mladek 			       obj, id, err);
164*e91c2518SPetr Mladek 			return NULL;
165*e91c2518SPetr Mladek 		}
166*e91c2518SPetr Mladek 	}
167*e91c2518SPetr Mladek 
168439e7271SJoe Lawrence 	/* No <obj, id> found, so attach the newly allocated one */
169439e7271SJoe Lawrence 	hash_add_rcu(klp_shadow_hash, &new_shadow->node,
170439e7271SJoe Lawrence 		     (unsigned long)new_shadow->obj);
171439e7271SJoe Lawrence 	spin_unlock_irqrestore(&klp_shadow_lock, flags);
172439e7271SJoe Lawrence 
173439e7271SJoe Lawrence 	return new_shadow->data;
174439e7271SJoe Lawrence 
175439e7271SJoe Lawrence exists:
176439e7271SJoe Lawrence 	if (warn_on_exist) {
177439e7271SJoe Lawrence 		WARN(1, "Duplicate shadow variable <%p, %lx>\n", obj, id);
178439e7271SJoe Lawrence 		return NULL;
179439e7271SJoe Lawrence 	}
180439e7271SJoe Lawrence 
181439e7271SJoe Lawrence 	return shadow_data;
182439e7271SJoe Lawrence }
183439e7271SJoe Lawrence 
184439e7271SJoe Lawrence /**
185439e7271SJoe Lawrence  * klp_shadow_alloc() - allocate and add a new shadow variable
186439e7271SJoe Lawrence  * @obj:	pointer to parent object
187439e7271SJoe Lawrence  * @id:		data identifier
188439e7271SJoe Lawrence  * @size:	size of attached data
189439e7271SJoe Lawrence  * @gfp_flags:	GFP mask for allocation
190*e91c2518SPetr Mladek  * @ctor:	custom constructor to initialize the shadow data (optional)
191*e91c2518SPetr Mladek  * @ctor_data:	pointer to any data needed by @ctor (optional)
192439e7271SJoe Lawrence  *
193*e91c2518SPetr Mladek  * Allocates @size bytes for new shadow variable data using @gfp_flags.
194*e91c2518SPetr Mladek  * The data are zeroed by default.  They are further initialized by @ctor
195*e91c2518SPetr Mladek  * function if it is not NULL.  The new shadow variable is then added
196*e91c2518SPetr Mladek  * to the global hashtable.
197439e7271SJoe Lawrence  *
198*e91c2518SPetr Mladek  * If an existing <obj, id> shadow variable can be found, this routine will
199*e91c2518SPetr Mladek  * issue a WARN, exit early and return NULL.
200*e91c2518SPetr Mladek  *
201*e91c2518SPetr Mladek  * This function guarantees that the constructor function is called only when
202*e91c2518SPetr Mladek  * the variable did not exist before.  The cost is that @ctor is called
203*e91c2518SPetr Mladek  * in atomic context under a spin lock.
204439e7271SJoe Lawrence  *
205439e7271SJoe Lawrence  * Return: the shadow variable data element, NULL on duplicate or
206439e7271SJoe Lawrence  * failure.
207439e7271SJoe Lawrence  */
208*e91c2518SPetr Mladek void *klp_shadow_alloc(void *obj, unsigned long id,
209*e91c2518SPetr Mladek 		       size_t size, gfp_t gfp_flags,
210*e91c2518SPetr Mladek 		       klp_shadow_ctor_t ctor, void *ctor_data)
211439e7271SJoe Lawrence {
212*e91c2518SPetr Mladek 	return __klp_shadow_get_or_alloc(obj, id, size, gfp_flags,
213*e91c2518SPetr Mladek 					 ctor, ctor_data, true);
214439e7271SJoe Lawrence }
215439e7271SJoe Lawrence EXPORT_SYMBOL_GPL(klp_shadow_alloc);
216439e7271SJoe Lawrence 
217439e7271SJoe Lawrence /**
218439e7271SJoe Lawrence  * klp_shadow_get_or_alloc() - get existing or allocate a new shadow variable
219439e7271SJoe Lawrence  * @obj:	pointer to parent object
220439e7271SJoe Lawrence  * @id:		data identifier
221439e7271SJoe Lawrence  * @size:	size of attached data
222439e7271SJoe Lawrence  * @gfp_flags:	GFP mask for allocation
223*e91c2518SPetr Mladek  * @ctor:	custom constructor to initialize the shadow data (optional)
224*e91c2518SPetr Mladek  * @ctor_data:	pointer to any data needed by @ctor (optional)
225439e7271SJoe Lawrence  *
226439e7271SJoe Lawrence  * Returns a pointer to existing shadow data if an <obj, id> shadow
227439e7271SJoe Lawrence  * variable is already present.  Otherwise, it creates a new shadow
228439e7271SJoe Lawrence  * variable like klp_shadow_alloc().
229439e7271SJoe Lawrence  *
230*e91c2518SPetr Mladek  * This function guarantees that only one shadow variable exists with the given
231*e91c2518SPetr Mladek  * @id for the given @obj.  It also guarantees that the constructor function
232*e91c2518SPetr Mladek  * will be called only when the variable did not exist before.  The cost is
233*e91c2518SPetr Mladek  * that @ctor is called in atomic context under a spin lock.
234439e7271SJoe Lawrence  *
235439e7271SJoe Lawrence  * Return: the shadow variable data element, NULL on failure.
236439e7271SJoe Lawrence  */
237*e91c2518SPetr Mladek void *klp_shadow_get_or_alloc(void *obj, unsigned long id,
238*e91c2518SPetr Mladek 			      size_t size, gfp_t gfp_flags,
239*e91c2518SPetr Mladek 			      klp_shadow_ctor_t ctor, void *ctor_data)
240439e7271SJoe Lawrence {
241*e91c2518SPetr Mladek 	return __klp_shadow_get_or_alloc(obj, id, size, gfp_flags,
242*e91c2518SPetr Mladek 					 ctor, ctor_data, false);
243439e7271SJoe Lawrence }
244439e7271SJoe Lawrence EXPORT_SYMBOL_GPL(klp_shadow_get_or_alloc);
245439e7271SJoe Lawrence 
246439e7271SJoe Lawrence /**
247439e7271SJoe Lawrence  * klp_shadow_free() - detach and free a <obj, id> shadow variable
248439e7271SJoe Lawrence  * @obj:	pointer to parent object
249439e7271SJoe Lawrence  * @id:		data identifier
250439e7271SJoe Lawrence  *
251439e7271SJoe Lawrence  * This function releases the memory for this <obj, id> shadow variable
252439e7271SJoe Lawrence  * instance, callers should stop referencing it accordingly.
253439e7271SJoe Lawrence  */
254439e7271SJoe Lawrence void klp_shadow_free(void *obj, unsigned long id)
255439e7271SJoe Lawrence {
256439e7271SJoe Lawrence 	struct klp_shadow *shadow;
257439e7271SJoe Lawrence 	unsigned long flags;
258439e7271SJoe Lawrence 
259439e7271SJoe Lawrence 	spin_lock_irqsave(&klp_shadow_lock, flags);
260439e7271SJoe Lawrence 
261439e7271SJoe Lawrence 	/* Delete <obj, id> from hash */
262439e7271SJoe Lawrence 	hash_for_each_possible(klp_shadow_hash, shadow, node,
263439e7271SJoe Lawrence 			       (unsigned long)obj) {
264439e7271SJoe Lawrence 
265439e7271SJoe Lawrence 		if (klp_shadow_match(shadow, obj, id)) {
266439e7271SJoe Lawrence 			hash_del_rcu(&shadow->node);
267439e7271SJoe Lawrence 			kfree_rcu(shadow, rcu_head);
268439e7271SJoe Lawrence 			break;
269439e7271SJoe Lawrence 		}
270439e7271SJoe Lawrence 	}
271439e7271SJoe Lawrence 
272439e7271SJoe Lawrence 	spin_unlock_irqrestore(&klp_shadow_lock, flags);
273439e7271SJoe Lawrence }
274439e7271SJoe Lawrence EXPORT_SYMBOL_GPL(klp_shadow_free);
275439e7271SJoe Lawrence 
276439e7271SJoe Lawrence /**
277439e7271SJoe Lawrence  * klp_shadow_free_all() - detach and free all <*, id> shadow variables
278439e7271SJoe Lawrence  * @id:		data identifier
279439e7271SJoe Lawrence  *
280439e7271SJoe Lawrence  * This function releases the memory for all <*, id> shadow variable
281439e7271SJoe Lawrence  * instances, callers should stop referencing them accordingly.
282439e7271SJoe Lawrence  */
283439e7271SJoe Lawrence void klp_shadow_free_all(unsigned long id)
284439e7271SJoe Lawrence {
285439e7271SJoe Lawrence 	struct klp_shadow *shadow;
286439e7271SJoe Lawrence 	unsigned long flags;
287439e7271SJoe Lawrence 	int i;
288439e7271SJoe Lawrence 
289439e7271SJoe Lawrence 	spin_lock_irqsave(&klp_shadow_lock, flags);
290439e7271SJoe Lawrence 
291439e7271SJoe Lawrence 	/* Delete all <*, id> from hash */
292439e7271SJoe Lawrence 	hash_for_each(klp_shadow_hash, i, shadow, node) {
293439e7271SJoe Lawrence 		if (klp_shadow_match(shadow, shadow->obj, id)) {
294439e7271SJoe Lawrence 			hash_del_rcu(&shadow->node);
295439e7271SJoe Lawrence 			kfree_rcu(shadow, rcu_head);
296439e7271SJoe Lawrence 		}
297439e7271SJoe Lawrence 	}
298439e7271SJoe Lawrence 
299439e7271SJoe Lawrence 	spin_unlock_irqrestore(&klp_shadow_lock, flags);
300439e7271SJoe Lawrence }
301439e7271SJoe Lawrence EXPORT_SYMBOL_GPL(klp_shadow_free_all);
302