Skip to content

Commit be6da98

Browse files
pmladekJiri Kosina
authored andcommitted
livepatch/samples/selftest: Use klp_shadow_alloc() API correctly
The commit e91c251 ("livepatch: Initialize shadow variables safely by a custom callback") leads to the following static checker warning: samples/livepatch/livepatch-shadow-fix1.c:86 livepatch_fix1_dummy_alloc() error: 'klp_shadow_alloc()' 'leak' too small (4 vs 8) It is because klp_shadow_alloc() is used a wrong way: int *leak; shadow_leak = klp_shadow_alloc(d, SV_LEAK, sizeof(leak), GFP_KERNEL, shadow_leak_ctor, leak); The code is supposed to store the "leak" pointer into the shadow variable. 3rd parameter correctly passes size of the data (size of pointer). But the 5th parameter is wrong. It should pass pointer to the data (pointer to the pointer) but it passes the pointer directly. It works because shadow_leak_ctor() handle "ctor_data" as the data instead of pointer to the data. But it is semantically wrong and confusing. The same problem is also in the module used by selftests. In this case, "pvX" variables are introduced. They represent the data stored in the shadow variables. Reported-by: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: Petr Mladek <pmladek@suse.com> Reviewed-by: Joe Lawrence <joe.lawrence@redhat.com> Acked-by: Miroslav Benes <mbenes@suse.cz> Reviewed-by: Kamalesh Babulal <kamalesh@linux.vnet.ibm.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
1 parent c24c57a commit be6da98

2 files changed

Lines changed: 36 additions & 25 deletions

File tree

lib/livepatch/test_klp_shadow_vars.c

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,13 @@ static void *shadow_alloc(void *obj, unsigned long id, size_t size,
7373
gfp_t gfp_flags, klp_shadow_ctor_t ctor,
7474
void *ctor_data)
7575
{
76-
int *var = ctor_data;
76+
int **var = ctor_data;
7777
int **sv;
7878

7979
sv = klp_shadow_alloc(obj, id, size, gfp_flags, ctor, var);
8080
pr_info("klp_%s(obj=PTR%d, id=0x%lx, size=%zx, gfp_flags=%pGg), ctor=PTR%d, ctor_data=PTR%d = PTR%d\n",
8181
__func__, ptr_id(obj), id, size, &gfp_flags, ptr_id(ctor),
82-
ptr_id(var), ptr_id(sv));
82+
ptr_id(*var), ptr_id(sv));
8383

8484
return sv;
8585
}
@@ -88,13 +88,13 @@ static void *shadow_get_or_alloc(void *obj, unsigned long id, size_t size,
8888
gfp_t gfp_flags, klp_shadow_ctor_t ctor,
8989
void *ctor_data)
9090
{
91-
int *var = ctor_data;
91+
int **var = ctor_data;
9292
int **sv;
9393

9494
sv = klp_shadow_get_or_alloc(obj, id, size, gfp_flags, ctor, var);
9595
pr_info("klp_%s(obj=PTR%d, id=0x%lx, size=%zx, gfp_flags=%pGg), ctor=PTR%d, ctor_data=PTR%d = PTR%d\n",
9696
__func__, ptr_id(obj), id, size, &gfp_flags, ptr_id(ctor),
97-
ptr_id(var), ptr_id(sv));
97+
ptr_id(*var), ptr_id(sv));
9898

9999
return sv;
100100
}
@@ -118,11 +118,14 @@ static void shadow_free_all(unsigned long id, klp_shadow_dtor_t dtor)
118118
static int shadow_ctor(void *obj, void *shadow_data, void *ctor_data)
119119
{
120120
int **sv = shadow_data;
121-
int *var = ctor_data;
121+
int **var = ctor_data;
122122

123-
*sv = var;
123+
if (!var)
124+
return -EINVAL;
125+
126+
*sv = *var;
124127
pr_info("%s: PTR%d -> PTR%d\n",
125-
__func__, ptr_id(sv), ptr_id(var));
128+
__func__, ptr_id(sv), ptr_id(*var));
126129

127130
return 0;
128131
}
@@ -139,19 +142,24 @@ static int test_klp_shadow_vars_init(void)
139142
{
140143
void *obj = THIS_MODULE;
141144
int id = 0x1234;
142-
size_t size = sizeof(int *);
143145
gfp_t gfp_flags = GFP_KERNEL;
144146

145147
int var1, var2, var3, var4;
148+
int *pv1, *pv2, *pv3, *pv4;
146149
int **sv1, **sv2, **sv3, **sv4;
147150

148151
int **sv;
149152

153+
pv1 = &var1;
154+
pv2 = &var2;
155+
pv3 = &var3;
156+
pv4 = &var4;
157+
150158
ptr_id(NULL);
151-
ptr_id(&var1);
152-
ptr_id(&var2);
153-
ptr_id(&var3);
154-
ptr_id(&var4);
159+
ptr_id(pv1);
160+
ptr_id(pv2);
161+
ptr_id(pv3);
162+
ptr_id(pv4);
155163

156164
/*
157165
* With an empty shadow variable hash table, expect not to find
@@ -164,15 +172,15 @@ static int test_klp_shadow_vars_init(void)
164172
/*
165173
* Allocate a few shadow variables with different <obj> and <id>.
166174
*/
167-
sv1 = shadow_alloc(obj, id, size, gfp_flags, shadow_ctor, &var1);
175+
sv1 = shadow_alloc(obj, id, sizeof(pv1), gfp_flags, shadow_ctor, &pv1);
168176
if (!sv1)
169177
return -ENOMEM;
170178

171-
sv2 = shadow_alloc(obj + 1, id, size, gfp_flags, shadow_ctor, &var2);
179+
sv2 = shadow_alloc(obj + 1, id, sizeof(pv2), gfp_flags, shadow_ctor, &pv2);
172180
if (!sv2)
173181
return -ENOMEM;
174182

175-
sv3 = shadow_alloc(obj, id + 1, size, gfp_flags, shadow_ctor, &var3);
183+
sv3 = shadow_alloc(obj, id + 1, sizeof(pv3), gfp_flags, shadow_ctor, &pv3);
176184
if (!sv3)
177185
return -ENOMEM;
178186

@@ -183,35 +191,35 @@ static int test_klp_shadow_vars_init(void)
183191
sv = shadow_get(obj, id);
184192
if (!sv)
185193
return -EINVAL;
186-
if (sv == sv1 && *sv1 == &var1)
194+
if (sv == sv1 && *sv1 == pv1)
187195
pr_info(" got expected PTR%d -> PTR%d result\n",
188196
ptr_id(sv1), ptr_id(*sv1));
189197

190198
sv = shadow_get(obj + 1, id);
191199
if (!sv)
192200
return -EINVAL;
193-
if (sv == sv2 && *sv2 == &var2)
201+
if (sv == sv2 && *sv2 == pv2)
194202
pr_info(" got expected PTR%d -> PTR%d result\n",
195203
ptr_id(sv2), ptr_id(*sv2));
196204
sv = shadow_get(obj, id + 1);
197205
if (!sv)
198206
return -EINVAL;
199-
if (sv == sv3 && *sv3 == &var3)
207+
if (sv == sv3 && *sv3 == pv3)
200208
pr_info(" got expected PTR%d -> PTR%d result\n",
201209
ptr_id(sv3), ptr_id(*sv3));
202210

203211
/*
204212
* Allocate or get a few more, this time with the same <obj>, <id>.
205213
* The second invocation should return the same shadow var.
206214
*/
207-
sv4 = shadow_get_or_alloc(obj + 2, id, size, gfp_flags, shadow_ctor, &var4);
215+
sv4 = shadow_get_or_alloc(obj + 2, id, sizeof(pv4), gfp_flags, shadow_ctor, &pv4);
208216
if (!sv4)
209217
return -ENOMEM;
210218

211-
sv = shadow_get_or_alloc(obj + 2, id, size, gfp_flags, shadow_ctor, &var4);
219+
sv = shadow_get_or_alloc(obj + 2, id, sizeof(pv4), gfp_flags, shadow_ctor, &pv4);
212220
if (!sv)
213221
return -EINVAL;
214-
if (sv == sv4 && *sv4 == &var4)
222+
if (sv == sv4 && *sv4 == pv4)
215223
pr_info(" got expected PTR%d -> PTR%d result\n",
216224
ptr_id(sv4), ptr_id(*sv4));
217225

@@ -240,7 +248,7 @@ static int test_klp_shadow_vars_init(void)
240248
sv = shadow_get(obj, id + 1);
241249
if (!sv)
242250
return -EINVAL;
243-
if (sv == sv3 && *sv3 == &var3)
251+
if (sv == sv3 && *sv3 == pv3)
244252
pr_info(" got expected PTR%d -> PTR%d result\n",
245253
ptr_id(sv3), ptr_id(*sv3));
246254

samples/livepatch/livepatch-shadow-fix1.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,12 @@ struct dummy {
5353
static int shadow_leak_ctor(void *obj, void *shadow_data, void *ctor_data)
5454
{
5555
int **shadow_leak = shadow_data;
56-
int *leak = ctor_data;
56+
int **leak = ctor_data;
5757

58-
*shadow_leak = leak;
58+
if (!ctor_data)
59+
return -EINVAL;
60+
61+
*shadow_leak = *leak;
5962
return 0;
6063
}
6164

@@ -83,7 +86,7 @@ static struct dummy *livepatch_fix1_dummy_alloc(void)
8386
}
8487

8588
klp_shadow_alloc(d, SV_LEAK, sizeof(leak), GFP_KERNEL,
86-
shadow_leak_ctor, leak);
89+
shadow_leak_ctor, &leak);
8790

8891
pr_info("%s: dummy @ %p, expires @ %lx\n",
8992
__func__, d, d->jiffies_expire);

0 commit comments

Comments
 (0)