aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/livepatch/shadow.c
diff options
context:
space:
mode:
authorPetr Mladek <pmladek@suse.com>2018-04-16 07:36:46 -0400
committerJiri Kosina <jkosina@suse.cz>2018-04-17 07:42:48 -0400
commite91c2518a5d22a07642f35d85f39001ad379dae4 (patch)
tree3a794a957564ce90514894263e995fbd27649a8c /kernel/livepatch/shadow.c
parente1c70f32386c4984ed8ca1a7aedb9bbff9ed3414 (diff)
livepatch: Initialize shadow variables safely by a custom callback
The existing API allows to pass a sample data to initialize the shadow data. It works well when the data are position independent. But it fails miserably when we need to set a pointer to the shadow structure itself. Unfortunately, we might need to initialize the pointer surprisingly often because of struct list_head. It is even worse because the list might be hidden in other common structures, for example, struct mutex, struct wait_queue_head. For example, this was needed to fix races in ALSA sequencer. It required to add mutex into struct snd_seq_client. See commit b3defb791b26ea06 ("ALSA: seq: Make ioctls race-free") and commit d15d662e89fc667b9 ("ALSA: seq: Fix racy pool initializations") This patch makes the API more safe. A custom constructor function and data are passed to klp_shadow_*alloc() functions instead of the sample data. Note that ctor_data are no longer a template for shadow->data. It might point to any data that might be necessary when the constructor is called. Also note that the constructor is called under klp_shadow_lock. It is an internal spin_lock that synchronizes alloc() vs. get() operations, see klp_shadow_get_or_alloc(). On one hand, this adds a risk of ABBA deadlocks. On the other hand, it allows to do some operations safely. For example, we could add the new structure into an existing list. This must be done only once when the structure is allocated. Reported-by: Nicolai Stange <nstange@suse.de> Signed-off-by: Petr Mladek <pmladek@suse.com> Acked-by: Josh Poimboeuf <jpoimboe@redhat.com> Acked-by: Miroslav Benes <mbenes@suse.cz> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'kernel/livepatch/shadow.c')
-rw-r--r--kernel/livepatch/shadow.c82
1 files changed, 53 insertions, 29 deletions
diff --git a/kernel/livepatch/shadow.c b/kernel/livepatch/shadow.c
index fdac27588d60..b10a0bbb7f84 100644
--- a/kernel/livepatch/shadow.c
+++ b/kernel/livepatch/shadow.c
@@ -113,8 +113,10 @@ void *klp_shadow_get(void *obj, unsigned long id)
113} 113}
114EXPORT_SYMBOL_GPL(klp_shadow_get); 114EXPORT_SYMBOL_GPL(klp_shadow_get);
115 115
116static void *__klp_shadow_get_or_alloc(void *obj, unsigned long id, void *data, 116static void *__klp_shadow_get_or_alloc(void *obj, unsigned long id,
117 size_t size, gfp_t gfp_flags, bool warn_on_exist) 117 size_t size, gfp_t gfp_flags,
118 klp_shadow_ctor_t ctor, void *ctor_data,
119 bool warn_on_exist)
118{ 120{
119 struct klp_shadow *new_shadow; 121 struct klp_shadow *new_shadow;
120 void *shadow_data; 122 void *shadow_data;
@@ -125,18 +127,15 @@ static void *__klp_shadow_get_or_alloc(void *obj, unsigned long id, void *data,
125 if (shadow_data) 127 if (shadow_data)
126 goto exists; 128 goto exists;
127 129
128 /* Allocate a new shadow variable for use inside the lock below */ 130 /*
131 * Allocate a new shadow variable. Fill it with zeroes by default.
132 * More complex setting can be done by @ctor function. But it is
133 * called only when the buffer is really used (under klp_shadow_lock).
134 */
129 new_shadow = kzalloc(size + sizeof(*new_shadow), gfp_flags); 135 new_shadow = kzalloc(size + sizeof(*new_shadow), gfp_flags);
130 if (!new_shadow) 136 if (!new_shadow)
131 return NULL; 137 return NULL;
132 138
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
140 /* Look for <obj, id> again under the lock */ 139 /* Look for <obj, id> again under the lock */
141 spin_lock_irqsave(&klp_shadow_lock, flags); 140 spin_lock_irqsave(&klp_shadow_lock, flags);
142 shadow_data = klp_shadow_get(obj, id); 141 shadow_data = klp_shadow_get(obj, id);
@@ -150,6 +149,22 @@ static void *__klp_shadow_get_or_alloc(void *obj, unsigned long id, void *data,
150 goto exists; 149 goto exists;
151 } 150 }
152 151
152 new_shadow->obj = obj;
153 new_shadow->id = id;
154
155 if (ctor) {
156 int err;
157
158 err = ctor(obj, new_shadow->data, ctor_data);
159 if (err) {
160 spin_unlock_irqrestore(&klp_shadow_lock, flags);
161 kfree(new_shadow);
162 pr_err("Failed to construct shadow variable <%p, %lx> (%d)\n",
163 obj, id, err);
164 return NULL;
165 }
166 }
167
153 /* No <obj, id> found, so attach the newly allocated one */ 168 /* No <obj, id> found, so attach the newly allocated one */
154 hash_add_rcu(klp_shadow_hash, &new_shadow->node, 169 hash_add_rcu(klp_shadow_hash, &new_shadow->node,
155 (unsigned long)new_shadow->obj); 170 (unsigned long)new_shadow->obj);
@@ -170,26 +185,32 @@ exists:
170 * klp_shadow_alloc() - allocate and add a new shadow variable 185 * klp_shadow_alloc() - allocate and add a new shadow variable
171 * @obj: pointer to parent object 186 * @obj: pointer to parent object
172 * @id: data identifier 187 * @id: data identifier
173 * @data: pointer to data to attach to parent
174 * @size: size of attached data 188 * @size: size of attached data
175 * @gfp_flags: GFP mask for allocation 189 * @gfp_flags: GFP mask for allocation
190 * @ctor: custom constructor to initialize the shadow data (optional)
191 * @ctor_data: pointer to any data needed by @ctor (optional)
192 *
193 * Allocates @size bytes for new shadow variable data using @gfp_flags.
194 * The data are zeroed by default. They are further initialized by @ctor
195 * function if it is not NULL. The new shadow variable is then added
196 * to the global hashtable.
176 * 197 *
177 * Allocates @size bytes for new shadow variable data using @gfp_flags 198 * If an existing <obj, id> shadow variable can be found, this routine will
178 * and copies @size bytes from @data into the new shadow variable's own 199 * issue a WARN, exit early and return NULL.
179 * data space. If @data is NULL, @size bytes are still allocated, but
180 * no copy is performed. The new shadow variable is then added to the
181 * global hashtable.
182 * 200 *
183 * If an existing <obj, id> shadow variable can be found, this routine 201 * This function guarantees that the constructor function is called only when
184 * will issue a WARN, exit early and return NULL. 202 * the variable did not exist before. The cost is that @ctor is called
203 * in atomic context under a spin lock.
185 * 204 *
186 * Return: the shadow variable data element, NULL on duplicate or 205 * Return: the shadow variable data element, NULL on duplicate or
187 * failure. 206 * failure.
188 */ 207 */
189void *klp_shadow_alloc(void *obj, unsigned long id, void *data, 208void *klp_shadow_alloc(void *obj, unsigned long id,
190 size_t size, gfp_t gfp_flags) 209 size_t size, gfp_t gfp_flags,
210 klp_shadow_ctor_t ctor, void *ctor_data)
191{ 211{
192 return __klp_shadow_get_or_alloc(obj, id, data, size, gfp_flags, true); 212 return __klp_shadow_get_or_alloc(obj, id, size, gfp_flags,
213 ctor, ctor_data, true);
193} 214}
194EXPORT_SYMBOL_GPL(klp_shadow_alloc); 215EXPORT_SYMBOL_GPL(klp_shadow_alloc);
195 216
@@ -197,25 +218,28 @@ EXPORT_SYMBOL_GPL(klp_shadow_alloc);
197 * klp_shadow_get_or_alloc() - get existing or allocate a new shadow variable 218 * klp_shadow_get_or_alloc() - get existing or allocate a new shadow variable
198 * @obj: pointer to parent object 219 * @obj: pointer to parent object
199 * @id: data identifier 220 * @id: data identifier
200 * @data: pointer to data to attach to parent
201 * @size: size of attached data 221 * @size: size of attached data
202 * @gfp_flags: GFP mask for allocation 222 * @gfp_flags: GFP mask for allocation
223 * @ctor: custom constructor to initialize the shadow data (optional)
224 * @ctor_data: pointer to any data needed by @ctor (optional)
203 * 225 *
204 * Returns a pointer to existing shadow data if an <obj, id> shadow 226 * Returns a pointer to existing shadow data if an <obj, id> shadow
205 * variable is already present. Otherwise, it creates a new shadow 227 * variable is already present. Otherwise, it creates a new shadow
206 * variable like klp_shadow_alloc(). 228 * variable like klp_shadow_alloc().
207 * 229 *
208 * This function guarantees that only one shadow variable exists with 230 * This function guarantees that only one shadow variable exists with the given
209 * the given @id for the given @obj. It also guarantees that the shadow 231 * @id for the given @obj. It also guarantees that the constructor function
210 * variable will be initialized by the given @data only when it did not 232 * will be called only when the variable did not exist before. The cost is
211 * exist before. 233 * that @ctor is called in atomic context under a spin lock.
212 * 234 *
213 * Return: the shadow variable data element, NULL on failure. 235 * Return: the shadow variable data element, NULL on failure.
214 */ 236 */
215void *klp_shadow_get_or_alloc(void *obj, unsigned long id, void *data, 237void *klp_shadow_get_or_alloc(void *obj, unsigned long id,
216 size_t size, gfp_t gfp_flags) 238 size_t size, gfp_t gfp_flags,
239 klp_shadow_ctor_t ctor, void *ctor_data)
217{ 240{
218 return __klp_shadow_get_or_alloc(obj, id, data, size, gfp_flags, false); 241 return __klp_shadow_get_or_alloc(obj, id, size, gfp_flags,
242 ctor, ctor_data, false);
219} 243}
220EXPORT_SYMBOL_GPL(klp_shadow_get_or_alloc); 244EXPORT_SYMBOL_GPL(klp_shadow_get_or_alloc);
221 245