Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/livepatch: fix mem leaks in test-klp-shadow-vars

In some cases, when an error occurs during testing and the main test
routine returns, a memory leak occurs via leaving previously registered
shadow variables allocated in the kernel as well as shadow_ptr list
elements. From now on, in case of error, remove all allocated shadow
variables and shadow_ptr struct elements.

Signed-off-by: Yannick Cote <ycote@redhat.com>
Reviewed-by: Petr Mladek <pmladek@suse.com>
Reviewed-by: Kamalesh Babulal <kamalesh@linux.vnet.ibm.com>
Acked-by: Miroslav Benes <mbenes@suse.cz>
Acked-by: Joe Lawrence <joe.lawrence@redhat.com>
Signed-off-by: Petr Mladek <pmladek@suse.com>
Link: https://lore.kernel.org/r/20200603182058.109470-5-ycote@redhat.com

authored by

Yannick Cote and committed by
Petr Mladek
270f7806 76efe6da

+31 -12
+31 -12
lib/livepatch/test_klp_shadow_vars.c
··· 170 170 char *pndup[NUM_OBJS]; 171 171 int nfields2[NUM_OBJS], *pnfields2[NUM_OBJS], **sv2[NUM_OBJS]; 172 172 void **sv; 173 + int ret; 173 174 int i; 174 175 175 176 ptr_id(NULL); ··· 197 196 sizeof(pnfields1[i]), GFP_KERNEL, 198 197 shadow_ctor, &pnfields1[i]); 199 198 } 200 - if (!sv1[i]) 201 - return -ENOMEM; 199 + if (!sv1[i]) { 200 + ret = -ENOMEM; 201 + goto out; 202 + } 202 203 203 204 pnfields2[i] = &nfields2[i]; 204 205 ptr_id(pnfields2[i]); 205 206 sv2[i] = shadow_alloc(&objs[i], SV_ID2, sizeof(pnfields2[i]), 206 207 GFP_KERNEL, shadow_ctor, &pnfields2[i]); 207 - if (!sv2[i]) 208 - return -ENOMEM; 208 + if (!sv2[i]) { 209 + ret = -ENOMEM; 210 + goto out; 211 + } 209 212 } 210 213 211 214 /* pass 2: verify we find allocated svars and where they point to */ 212 215 for (i = 0; i < NUM_OBJS; i++) { 213 216 /* check the "char" svar for all objects */ 214 217 sv = shadow_get(&objs[i], SV_ID1); 215 - if (!sv) 216 - return -EINVAL; 218 + if (!sv) { 219 + ret = -EINVAL; 220 + goto out; 221 + } 217 222 if ((char **)sv == sv1[i] && *sv1[i] == pnfields1[i]) 218 223 pr_info(" got expected PTR%d -> PTR%d result\n", 219 224 ptr_id(sv1[i]), ptr_id(*sv1[i])); 220 225 221 226 /* check the "int" svar for all objects */ 222 227 sv = shadow_get(&objs[i], SV_ID2); 223 - if (!sv) 224 - return -EINVAL; 228 + if (!sv) { 229 + ret = -EINVAL; 230 + goto out; 231 + } 225 232 if ((int **)sv == sv2[i] && *sv2[i] == pnfields2[i]) 226 233 pr_info(" got expected PTR%d -> PTR%d result\n", 227 234 ptr_id(sv2[i]), ptr_id(*sv2[i])); ··· 242 233 243 234 sv = shadow_get_or_alloc(&objs[i], SV_ID1, sizeof(pndup[i]), 244 235 GFP_KERNEL, shadow_ctor, &pndup[i]); 245 - if (!sv) 246 - return -EINVAL; 236 + if (!sv) { 237 + ret = -EINVAL; 238 + goto out; 239 + } 247 240 if ((char **)sv == sv1[i] && *sv1[i] == pnfields1[i]) 248 241 pr_info(" got expected PTR%d -> PTR%d result\n", 249 242 ptr_id(sv1[i]), ptr_id(*sv1[i])); ··· 262 251 /* pass 5: check we still find <objs[*], SV_ID2> svar pairs */ 263 252 for (i = 0; i < NUM_OBJS; i++) { 264 253 sv = shadow_get(&objs[i], SV_ID2); /* 'int' pairs */ 265 - if (!sv) 266 - return -EINVAL; 254 + if (!sv) { 255 + ret = -EINVAL; 256 + goto out; 257 + } 267 258 if ((int **)sv == sv2[i] && *sv2[i] == pnfields2[i]) 268 259 pr_info(" got expected PTR%d -> PTR%d result\n", 269 260 ptr_id(sv2[i]), ptr_id(*sv2[i])); ··· 282 269 free_ptr_list(); 283 270 284 271 return 0; 272 + out: 273 + shadow_free_all(SV_ID1, NULL); /* 'char' pairs */ 274 + shadow_free_all(SV_ID2, NULL); /* 'int' pairs */ 275 + free_ptr_list(); 276 + 277 + return ret; 285 278 } 286 279 287 280 static void test_klp_shadow_vars_exit(void)