~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/kernel/livepatch/shadow.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /kernel/livepatch/shadow.c (Version linux-6.11.5) and /kernel/livepatch/shadow.c (Version linux-4.16.18)


  1 // SPDX-License-Identifier: GPL-2.0-or-later   << 
  2 /*                                                  1 /*
  3  * shadow.c - Shadow Variables                      2  * shadow.c - Shadow Variables
  4  *                                                  3  *
  5  * Copyright (C) 2014 Josh Poimboeuf <jpoimboe      4  * Copyright (C) 2014 Josh Poimboeuf <jpoimboe@redhat.com>
  6  * Copyright (C) 2014 Seth Jennings <sjenning@      5  * Copyright (C) 2014 Seth Jennings <sjenning@redhat.com>
  7  * Copyright (C) 2017 Joe Lawrence <joe.lawren      6  * Copyright (C) 2017 Joe Lawrence <joe.lawrence@redhat.com>
                                                   >>   7  *
                                                   >>   8  * This program is free software; you can redistribute it and/or
                                                   >>   9  * modify it under the terms of the GNU General Public License
                                                   >>  10  * as published by the Free Software Foundation; either version 2
                                                   >>  11  * of the License, or (at your option) any later version.
                                                   >>  12  *
                                                   >>  13  * This program is distributed in the hope that it will be useful,
                                                   >>  14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                                                   >>  15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                                                   >>  16  * GNU General Public License for more details.
                                                   >>  17  *
                                                   >>  18  * You should have received a copy of the GNU General Public License
                                                   >>  19  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  8  */                                                20  */
  9                                                    21 
 10 /**                                                22 /**
 11  * DOC: Shadow variable API concurrency notes:     23  * DOC: Shadow variable API concurrency notes:
 12  *                                                 24  *
 13  * The shadow variable API provides a simple r     25  * The shadow variable API provides a simple relationship between an
 14  * <obj, id> pair and a pointer value.  It is      26  * <obj, id> pair and a pointer value.  It is the responsibility of the
 15  * caller to provide any mutual exclusion requ     27  * caller to provide any mutual exclusion required of the shadow data.
 16  *                                                 28  *
 17  * Once a shadow variable is attached to its p     29  * Once a shadow variable is attached to its parent object via the
 18  * klp_shadow_*alloc() API calls, it is consid     30  * klp_shadow_*alloc() API calls, it is considered live: any subsequent
 19  * call to klp_shadow_get() may then return th     31  * call to klp_shadow_get() may then return the shadow variable's data
 20  * pointer.  Callers of klp_shadow_*alloc() sh     32  * pointer.  Callers of klp_shadow_*alloc() should prepare shadow data
 21  * accordingly.                                    33  * accordingly.
 22  *                                                 34  *
 23  * The klp_shadow_*alloc() API calls may alloc     35  * The klp_shadow_*alloc() API calls may allocate memory for new shadow
 24  * variable structures.  Their implementation      36  * variable structures.  Their implementation does not call kmalloc
 25  * inside any spinlocks, but API callers shoul     37  * inside any spinlocks, but API callers should pass GFP flags according
 26  * to their specific needs.                        38  * to their specific needs.
 27  *                                                 39  *
 28  * The klp_shadow_hash is an RCU-enabled hasht     40  * The klp_shadow_hash is an RCU-enabled hashtable and is safe against
 29  * concurrent klp_shadow_free() and klp_shadow     41  * concurrent klp_shadow_free() and klp_shadow_get() operations.
 30  */                                                42  */
 31                                                    43 
 32 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt        44 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 33                                                    45 
 34 #include <linux/hashtable.h>                       46 #include <linux/hashtable.h>
 35 #include <linux/slab.h>                            47 #include <linux/slab.h>
 36 #include <linux/livepatch.h>                       48 #include <linux/livepatch.h>
 37                                                    49 
 38 static DEFINE_HASHTABLE(klp_shadow_hash, 12);      50 static DEFINE_HASHTABLE(klp_shadow_hash, 12);
 39                                                    51 
 40 /*                                                 52 /*
 41  * klp_shadow_lock provides exclusive access t     53  * klp_shadow_lock provides exclusive access to the klp_shadow_hash and
 42  * the shadow variables it references.             54  * the shadow variables it references.
 43  */                                                55  */
 44 static DEFINE_SPINLOCK(klp_shadow_lock);           56 static DEFINE_SPINLOCK(klp_shadow_lock);
 45                                                    57 
 46 /**                                                58 /**
 47  * struct klp_shadow - shadow variable structu     59  * struct klp_shadow - shadow variable structure
 48  * @node:       klp_shadow_hash hash table nod     60  * @node:       klp_shadow_hash hash table node
 49  * @rcu_head:   RCU is used to safely free thi     61  * @rcu_head:   RCU is used to safely free this structure
 50  * @obj:        pointer to parent object           62  * @obj:        pointer to parent object
 51  * @id:         data identifier                    63  * @id:         data identifier
 52  * @data:       data area                          64  * @data:       data area
 53  */                                                65  */
 54 struct klp_shadow {                                66 struct klp_shadow {
 55         struct hlist_node node;                    67         struct hlist_node node;
 56         struct rcu_head rcu_head;                  68         struct rcu_head rcu_head;
 57         void *obj;                                 69         void *obj;
 58         unsigned long id;                          70         unsigned long id;
 59         char data[];                               71         char data[];
 60 };                                                 72 };
 61                                                    73 
 62 /**                                                74 /**
 63  * klp_shadow_match() - verify a shadow variab     75  * klp_shadow_match() - verify a shadow variable matches given <obj, id>
 64  * @shadow:     shadow variable to match           76  * @shadow:     shadow variable to match
 65  * @obj:        pointer to parent object           77  * @obj:        pointer to parent object
 66  * @id:         data identifier                    78  * @id:         data identifier
 67  *                                                 79  *
 68  * Return: true if the shadow variable matches     80  * Return: true if the shadow variable matches.
 69  */                                                81  */
 70 static inline bool klp_shadow_match(struct klp     82 static inline bool klp_shadow_match(struct klp_shadow *shadow, void *obj,
 71                                 unsigned long      83                                 unsigned long id)
 72 {                                                  84 {
 73         return shadow->obj == obj && shadow->i     85         return shadow->obj == obj && shadow->id == id;
 74 }                                                  86 }
 75                                                    87 
 76 /**                                                88 /**
 77  * klp_shadow_get() - retrieve a shadow variab     89  * klp_shadow_get() - retrieve a shadow variable data pointer
 78  * @obj:        pointer to parent object           90  * @obj:        pointer to parent object
 79  * @id:         data identifier                    91  * @id:         data identifier
 80  *                                                 92  *
 81  * Return: the shadow variable data element, N     93  * Return: the shadow variable data element, NULL on failure.
 82  */                                                94  */
 83 void *klp_shadow_get(void *obj, unsigned long      95 void *klp_shadow_get(void *obj, unsigned long id)
 84 {                                                  96 {
 85         struct klp_shadow *shadow;                 97         struct klp_shadow *shadow;
 86                                                    98 
 87         rcu_read_lock();                           99         rcu_read_lock();
 88                                                   100 
 89         hash_for_each_possible_rcu(klp_shadow_    101         hash_for_each_possible_rcu(klp_shadow_hash, shadow, node,
 90                                    (unsigned l    102                                    (unsigned long)obj) {
 91                                                   103 
 92                 if (klp_shadow_match(shadow, o    104                 if (klp_shadow_match(shadow, obj, id)) {
 93                         rcu_read_unlock();        105                         rcu_read_unlock();
 94                         return shadow->data;      106                         return shadow->data;
 95                 }                                 107                 }
 96         }                                         108         }
 97                                                   109 
 98         rcu_read_unlock();                        110         rcu_read_unlock();
 99                                                   111 
100         return NULL;                              112         return NULL;
101 }                                                 113 }
102 EXPORT_SYMBOL_GPL(klp_shadow_get);                114 EXPORT_SYMBOL_GPL(klp_shadow_get);
103                                                   115 
104 static void *__klp_shadow_get_or_alloc(void *o !! 116 static void *__klp_shadow_get_or_alloc(void *obj, unsigned long id, void *data,
105                                        size_t  !! 117                        size_t size, gfp_t gfp_flags, bool warn_on_exist)
106                                        klp_sha << 
107                                        bool wa << 
108 {                                                 118 {
109         struct klp_shadow *new_shadow;            119         struct klp_shadow *new_shadow;
110         void *shadow_data;                        120         void *shadow_data;
111         unsigned long flags;                      121         unsigned long flags;
112                                                   122 
113         /* Check if the shadow variable alread    123         /* Check if the shadow variable already exists */
114         shadow_data = klp_shadow_get(obj, id);    124         shadow_data = klp_shadow_get(obj, id);
115         if (shadow_data)                          125         if (shadow_data)
116                 goto exists;                      126                 goto exists;
117                                                   127 
118         /*                                     !! 128         /* Allocate a new shadow variable for use inside the lock below */
119          * Allocate a new shadow variable.  Fi << 
120          * More complex setting can be done by << 
121          * called only when the buffer is real << 
122          */                                    << 
123         new_shadow = kzalloc(size + sizeof(*ne    129         new_shadow = kzalloc(size + sizeof(*new_shadow), gfp_flags);
124         if (!new_shadow)                          130         if (!new_shadow)
125                 return NULL;                      131                 return NULL;
126                                                   132 
                                                   >> 133         new_shadow->obj = obj;
                                                   >> 134         new_shadow->id = id;
                                                   >> 135 
                                                   >> 136         /* Initialize the shadow variable if data provided */
                                                   >> 137         if (data)
                                                   >> 138                 memcpy(new_shadow->data, data, size);
                                                   >> 139 
127         /* Look for <obj, id> again under the     140         /* Look for <obj, id> again under the lock */
128         spin_lock_irqsave(&klp_shadow_lock, fl    141         spin_lock_irqsave(&klp_shadow_lock, flags);
129         shadow_data = klp_shadow_get(obj, id);    142         shadow_data = klp_shadow_get(obj, id);
130         if (unlikely(shadow_data)) {              143         if (unlikely(shadow_data)) {
131                 /*                                144                 /*
132                  * Shadow variable was found,     145                  * Shadow variable was found, throw away speculative
133                  * allocation.                    146                  * allocation.
134                  */                               147                  */
135                 spin_unlock_irqrestore(&klp_sh    148                 spin_unlock_irqrestore(&klp_shadow_lock, flags);
136                 kfree(new_shadow);                149                 kfree(new_shadow);
137                 goto exists;                      150                 goto exists;
138         }                                         151         }
139                                                   152 
140         new_shadow->obj = obj;                 << 
141         new_shadow->id = id;                   << 
142                                                << 
143         if (ctor) {                            << 
144                 int err;                       << 
145                                                << 
146                 err = ctor(obj, new_shadow->da << 
147                 if (err) {                     << 
148                         spin_unlock_irqrestore << 
149                         kfree(new_shadow);     << 
150                         pr_err("Failed to cons << 
151                                obj, id, err);  << 
152                         return NULL;           << 
153                 }                              << 
154         }                                      << 
155                                                << 
156         /* No <obj, id> found, so attach the n    153         /* No <obj, id> found, so attach the newly allocated one */
157         hash_add_rcu(klp_shadow_hash, &new_sha    154         hash_add_rcu(klp_shadow_hash, &new_shadow->node,
158                      (unsigned long)new_shadow    155                      (unsigned long)new_shadow->obj);
159         spin_unlock_irqrestore(&klp_shadow_loc    156         spin_unlock_irqrestore(&klp_shadow_lock, flags);
160                                                   157 
161         return new_shadow->data;                  158         return new_shadow->data;
162                                                   159 
163 exists:                                           160 exists:
164         if (warn_on_exist) {                      161         if (warn_on_exist) {
165                 WARN(1, "Duplicate shadow vari    162                 WARN(1, "Duplicate shadow variable <%p, %lx>\n", obj, id);
166                 return NULL;                      163                 return NULL;
167         }                                         164         }
168                                                   165 
169         return shadow_data;                       166         return shadow_data;
170 }                                                 167 }
171                                                   168 
172 /**                                               169 /**
173  * klp_shadow_alloc() - allocate and add a new    170  * klp_shadow_alloc() - allocate and add a new shadow variable
174  * @obj:        pointer to parent object          171  * @obj:        pointer to parent object
175  * @id:         data identifier                   172  * @id:         data identifier
                                                   >> 173  * @data:       pointer to data to attach to parent
176  * @size:       size of attached data             174  * @size:       size of attached data
177  * @gfp_flags:  GFP mask for allocation           175  * @gfp_flags:  GFP mask for allocation
178  * @ctor:       custom constructor to initiali << 
179  * @ctor_data:  pointer to any data needed by  << 
180  *                                                176  *
181  * Allocates @size bytes for new shadow variab !! 177  * Allocates @size bytes for new shadow variable data using @gfp_flags
182  * The data are zeroed by default.  They are f !! 178  * and copies @size bytes from @data into the new shadow variable's own
183  * function if it is not NULL.  The new shadow !! 179  * data space.  If @data is NULL, @size bytes are still allocated, but
184  * to the global hashtable.                    !! 180  * no copy is performed.  The new shadow variable is then added to the
185  *                                             !! 181  * global hashtable.
186  * If an existing <obj, id> shadow variable ca !! 182  *
187  * issue a WARN, exit early and return NULL.   !! 183  * If an existing <obj, id> shadow variable can be found, this routine
188  *                                             !! 184  * will issue a WARN, exit early and return NULL.
189  * This function guarantees that the construct << 
190  * the variable did not exist before.  The cos << 
191  * in atomic context under a spin lock.        << 
192  *                                                185  *
193  * Return: the shadow variable data element, N    186  * Return: the shadow variable data element, NULL on duplicate or
194  * failure.                                       187  * failure.
195  */                                               188  */
196 void *klp_shadow_alloc(void *obj, unsigned lon !! 189 void *klp_shadow_alloc(void *obj, unsigned long id, void *data,
197                        size_t size, gfp_t gfp_ !! 190                        size_t size, gfp_t gfp_flags)
198                        klp_shadow_ctor_t ctor, << 
199 {                                                 191 {
200         return __klp_shadow_get_or_alloc(obj,  !! 192         return __klp_shadow_get_or_alloc(obj, id, data, size, gfp_flags, true);
201                                          ctor, << 
202 }                                                 193 }
203 EXPORT_SYMBOL_GPL(klp_shadow_alloc);              194 EXPORT_SYMBOL_GPL(klp_shadow_alloc);
204                                                   195 
205 /**                                               196 /**
206  * klp_shadow_get_or_alloc() - get existing or    197  * klp_shadow_get_or_alloc() - get existing or allocate a new shadow variable
207  * @obj:        pointer to parent object          198  * @obj:        pointer to parent object
208  * @id:         data identifier                   199  * @id:         data identifier
                                                   >> 200  * @data:       pointer to data to attach to parent
209  * @size:       size of attached data             201  * @size:       size of attached data
210  * @gfp_flags:  GFP mask for allocation           202  * @gfp_flags:  GFP mask for allocation
211  * @ctor:       custom constructor to initiali << 
212  * @ctor_data:  pointer to any data needed by  << 
213  *                                                203  *
214  * Returns a pointer to existing shadow data i    204  * Returns a pointer to existing shadow data if an <obj, id> shadow
215  * variable is already present.  Otherwise, it    205  * variable is already present.  Otherwise, it creates a new shadow
216  * variable like klp_shadow_alloc().              206  * variable like klp_shadow_alloc().
217  *                                                207  *
218  * This function guarantees that only one shad !! 208  * This function guarantees that only one shadow variable exists with
219  * @id for the given @obj.  It also guarantees !! 209  * the given @id for the given @obj.  It also guarantees that the shadow
220  * will be called only when the variable did n !! 210  * variable will be initialized by the given @data only when it did not
221  * that @ctor is called in atomic context unde !! 211  * exist before.
222  *                                                212  *
223  * Return: the shadow variable data element, N    213  * Return: the shadow variable data element, NULL on failure.
224  */                                               214  */
225 void *klp_shadow_get_or_alloc(void *obj, unsig !! 215 void *klp_shadow_get_or_alloc(void *obj, unsigned long id, void *data,
226                               size_t size, gfp !! 216                                size_t size, gfp_t gfp_flags)
227                               klp_shadow_ctor_ << 
228 {                                                 217 {
229         return __klp_shadow_get_or_alloc(obj,  !! 218         return __klp_shadow_get_or_alloc(obj, id, data, size, gfp_flags, false);
230                                          ctor, << 
231 }                                                 219 }
232 EXPORT_SYMBOL_GPL(klp_shadow_get_or_alloc);       220 EXPORT_SYMBOL_GPL(klp_shadow_get_or_alloc);
233                                                   221 
234 static void klp_shadow_free_struct(struct klp_ << 
235                                    klp_shadow_ << 
236 {                                              << 
237         hash_del_rcu(&shadow->node);           << 
238         if (dtor)                              << 
239                 dtor(shadow->obj, shadow->data << 
240         kfree_rcu(shadow, rcu_head);           << 
241 }                                              << 
242                                                << 
243 /**                                               222 /**
244  * klp_shadow_free() - detach and free a <obj,    223  * klp_shadow_free() - detach and free a <obj, id> shadow variable
245  * @obj:        pointer to parent object          224  * @obj:        pointer to parent object
246  * @id:         data identifier                   225  * @id:         data identifier
247  * @dtor:       custom callback that can be us << 
248  *              and/or free data that the shad << 
249  *                                                226  *
250  * This function releases the memory for this     227  * This function releases the memory for this <obj, id> shadow variable
251  * instance, callers should stop referencing i    228  * instance, callers should stop referencing it accordingly.
252  */                                               229  */
253 void klp_shadow_free(void *obj, unsigned long  !! 230 void klp_shadow_free(void *obj, unsigned long id)
254 {                                                 231 {
255         struct klp_shadow *shadow;                232         struct klp_shadow *shadow;
256         unsigned long flags;                      233         unsigned long flags;
257                                                   234 
258         spin_lock_irqsave(&klp_shadow_lock, fl    235         spin_lock_irqsave(&klp_shadow_lock, flags);
259                                                   236 
260         /* Delete <obj, id> from hash */          237         /* Delete <obj, id> from hash */
261         hash_for_each_possible(klp_shadow_hash    238         hash_for_each_possible(klp_shadow_hash, shadow, node,
262                                (unsigned long)    239                                (unsigned long)obj) {
263                                                   240 
264                 if (klp_shadow_match(shadow, o    241                 if (klp_shadow_match(shadow, obj, id)) {
265                         klp_shadow_free_struct !! 242                         hash_del_rcu(&shadow->node);
                                                   >> 243                         kfree_rcu(shadow, rcu_head);
266                         break;                    244                         break;
267                 }                                 245                 }
268         }                                         246         }
269                                                   247 
270         spin_unlock_irqrestore(&klp_shadow_loc    248         spin_unlock_irqrestore(&klp_shadow_lock, flags);
271 }                                                 249 }
272 EXPORT_SYMBOL_GPL(klp_shadow_free);               250 EXPORT_SYMBOL_GPL(klp_shadow_free);
273                                                   251 
274 /**                                               252 /**
275  * klp_shadow_free_all() - detach and free all !! 253  * klp_shadow_free_all() - detach and free all <*, id> shadow variables
276  * @id:         data identifier                   254  * @id:         data identifier
277  * @dtor:       custom callback that can be us << 
278  *              and/or free data that the shad << 
279  *                                                255  *
280  * This function releases the memory for all < !! 256  * This function releases the memory for all <*, id> shadow variable
281  * instances, callers should stop referencing     257  * instances, callers should stop referencing them accordingly.
282  */                                               258  */
283 void klp_shadow_free_all(unsigned long id, klp !! 259 void klp_shadow_free_all(unsigned long id)
284 {                                                 260 {
285         struct klp_shadow *shadow;                261         struct klp_shadow *shadow;
286         unsigned long flags;                      262         unsigned long flags;
287         int i;                                    263         int i;
288                                                   264 
289         spin_lock_irqsave(&klp_shadow_lock, fl    265         spin_lock_irqsave(&klp_shadow_lock, flags);
290                                                   266 
291         /* Delete all <_, id> from hash */     !! 267         /* Delete all <*, id> from hash */
292         hash_for_each(klp_shadow_hash, i, shad    268         hash_for_each(klp_shadow_hash, i, shadow, node) {
293                 if (klp_shadow_match(shadow, s !! 269                 if (klp_shadow_match(shadow, shadow->obj, id)) {
294                         klp_shadow_free_struct !! 270                         hash_del_rcu(&shadow->node);
                                                   >> 271                         kfree_rcu(shadow, rcu_head);
                                                   >> 272                 }
295         }                                         273         }
296                                                   274 
297         spin_unlock_irqrestore(&klp_shadow_loc    275         spin_unlock_irqrestore(&klp_shadow_lock, flags);
298 }                                                 276 }
299 EXPORT_SYMBOL_GPL(klp_shadow_free_all);           277 EXPORT_SYMBOL_GPL(klp_shadow_free_all);
300                                                   278 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php