@@ -109,8 +109,7 @@ static void shadow_free(void *obj, unsigned long id, klp_shadow_dtor_t dtor)
109
109
static void shadow_free_all (unsigned long id , klp_shadow_dtor_t dtor )
110
110
{
111
111
klp_shadow_free_all (id , dtor );
112
- pr_info ("klp_%s(id=0x%lx, dtor=PTR%d)\n" ,
113
- __func__ , id , ptr_id (dtor ));
112
+ pr_info ("klp_%s(id=0x%lx, dtor=PTR%d)\n" , __func__ , id , ptr_id (dtor ));
114
113
}
115
114
116
115
@@ -124,12 +123,16 @@ static int shadow_ctor(void *obj, void *shadow_data, void *ctor_data)
124
123
return - EINVAL ;
125
124
126
125
* sv = * var ;
127
- pr_info ("%s: PTR%d -> PTR%d\n" ,
128
- __func__ , ptr_id (sv ), ptr_id (* var ));
126
+ pr_info ("%s: PTR%d -> PTR%d\n" , __func__ , ptr_id (sv ), ptr_id (* var ));
129
127
130
128
return 0 ;
131
129
}
132
130
131
+ /*
132
+ * With more than one item to free in the list, order is not determined and
133
+ * shadow_dtor will not be passed to shadow_free_all() which would make the
134
+ * test fail. (see pass 6)
135
+ */
133
136
static void shadow_dtor (void * obj , void * shadow_data )
134
137
{
135
138
int * * sv = shadow_data ;
@@ -138,132 +141,153 @@ static void shadow_dtor(void *obj, void *shadow_data)
138
141
__func__ , ptr_id (obj ), ptr_id (sv ));
139
142
}
140
143
141
- static int test_klp_shadow_vars_init (void )
142
- {
143
- void * obj = THIS_MODULE ;
144
- int id = 0x1234 ;
145
- gfp_t gfp_flags = GFP_KERNEL ;
144
+ /* number of objects we simulate that need shadow vars */
145
+ #define NUM_OBJS 3
146
146
147
- int var1 , var2 , var3 , var4 ;
148
- int * pv1 , * pv2 , * pv3 , * pv4 ;
149
- int * * sv1 , * * sv2 , * * sv3 , * * sv4 ;
147
+ /* dynamically created obj fields have the following shadow var id values */
148
+ #define SV_ID1 0x1234
149
+ #define SV_ID2 0x1235
150
150
151
- int * * sv ;
151
+ /*
152
+ * The main test case adds/removes new fields (shadow var) to each of these
153
+ * test structure instances. The last group of fields in the struct represent
154
+ * the idea that shadow variables may be added and removed to and from the
155
+ * struct during execution.
156
+ */
157
+ struct test_object {
158
+ /* add anything here below and avoid to define an empty struct */
159
+ struct shadow_ptr sp ;
152
160
153
- pv1 = & var1 ;
154
- pv2 = & var2 ;
155
- pv3 = & var3 ;
156
- pv4 = & var4 ;
161
+ /* these represent shadow vars added and removed with SV_ID{1,2} */
162
+ /* char nfield1; */
163
+ /* int nfield2; */
164
+ };
165
+
166
+ static int test_klp_shadow_vars_init (void )
167
+ {
168
+ struct test_object objs [NUM_OBJS ];
169
+ char nfields1 [NUM_OBJS ], * pnfields1 [NUM_OBJS ], * * sv1 [NUM_OBJS ];
170
+ char * pndup [NUM_OBJS ];
171
+ int nfields2 [NUM_OBJS ], * pnfields2 [NUM_OBJS ], * * sv2 [NUM_OBJS ];
172
+ void * * sv ;
173
+ int ret ;
174
+ int i ;
157
175
158
176
ptr_id (NULL );
159
- ptr_id (pv1 );
160
- ptr_id (pv2 );
161
- ptr_id (pv3 );
162
- ptr_id (pv4 );
163
177
164
178
/*
165
179
* With an empty shadow variable hash table, expect not to find
166
180
* any matches.
167
181
*/
168
- sv = shadow_get (obj , id );
182
+ sv = shadow_get (& objs [ 0 ], SV_ID1 );
169
183
if (!sv )
170
184
pr_info (" got expected NULL result\n" );
171
185
172
- /*
173
- * Allocate a few shadow variables with different <obj> and <id>.
174
- */
175
- sv1 = shadow_alloc (obj , id , sizeof (pv1 ), gfp_flags , shadow_ctor , & pv1 );
176
- if (!sv1 )
177
- return - ENOMEM ;
178
-
179
- sv2 = shadow_alloc (obj + 1 , id , sizeof (pv2 ), gfp_flags , shadow_ctor , & pv2 );
180
- if (!sv2 )
181
- return - ENOMEM ;
182
-
183
- sv3 = shadow_alloc (obj , id + 1 , sizeof (pv3 ), gfp_flags , shadow_ctor , & pv3 );
184
- if (!sv3 )
185
- return - ENOMEM ;
186
-
187
- /*
188
- * Verify we can find our new shadow variables and that they point
189
- * to expected data.
190
- */
191
- sv = shadow_get (obj , id );
192
- if (!sv )
193
- return - EINVAL ;
194
- if (sv == sv1 && * sv1 == pv1 )
195
- pr_info (" got expected PTR%d -> PTR%d result\n" ,
196
- ptr_id (sv1 ), ptr_id (* sv1 ));
197
-
198
- sv = shadow_get (obj + 1 , id );
199
- if (!sv )
200
- return - EINVAL ;
201
- if (sv == sv2 && * sv2 == pv2 )
202
- pr_info (" got expected PTR%d -> PTR%d result\n" ,
203
- ptr_id (sv2 ), ptr_id (* sv2 ));
204
- sv = shadow_get (obj , id + 1 );
205
- if (!sv )
206
- return - EINVAL ;
207
- if (sv == sv3 && * sv3 == pv3 )
208
- pr_info (" got expected PTR%d -> PTR%d result\n" ,
209
- ptr_id (sv3 ), ptr_id (* sv3 ));
210
-
211
- /*
212
- * Allocate or get a few more, this time with the same <obj>, <id>.
213
- * The second invocation should return the same shadow var.
214
- */
215
- sv4 = shadow_get_or_alloc (obj + 2 , id , sizeof (pv4 ), gfp_flags , shadow_ctor , & pv4 );
216
- if (!sv4 )
217
- return - ENOMEM ;
218
-
219
- sv = shadow_get_or_alloc (obj + 2 , id , sizeof (pv4 ), gfp_flags , shadow_ctor , & pv4 );
220
- if (!sv )
221
- return - EINVAL ;
222
- if (sv == sv4 && * sv4 == pv4 )
223
- pr_info (" got expected PTR%d -> PTR%d result\n" ,
224
- ptr_id (sv4 ), ptr_id (* sv4 ));
225
-
226
- /*
227
- * Free the <obj=*, id> shadow variables and check that we can no
228
- * longer find them.
229
- */
230
- shadow_free (obj , id , shadow_dtor ); /* sv1 */
231
- sv = shadow_get (obj , id );
232
- if (!sv )
233
- pr_info (" got expected NULL result\n" );
186
+ /* pass 1: init & alloc a char+int pair of svars for each objs */
187
+ for (i = 0 ; i < NUM_OBJS ; i ++ ) {
188
+ pnfields1 [i ] = & nfields1 [i ];
189
+ ptr_id (pnfields1 [i ]);
190
+
191
+ if (i % 2 ) {
192
+ sv1 [i ] = shadow_alloc (& objs [i ], SV_ID1 ,
193
+ sizeof (pnfields1 [i ]), GFP_KERNEL ,
194
+ shadow_ctor , & pnfields1 [i ]);
195
+ } else {
196
+ sv1 [i ] = shadow_get_or_alloc (& objs [i ], SV_ID1 ,
197
+ sizeof (pnfields1 [i ]), GFP_KERNEL ,
198
+ shadow_ctor , & pnfields1 [i ]);
199
+ }
200
+ if (!sv1 [i ]) {
201
+ ret = - ENOMEM ;
202
+ goto out ;
203
+ }
204
+
205
+ pnfields2 [i ] = & nfields2 [i ];
206
+ ptr_id (pnfields2 [i ]);
207
+ sv2 [i ] = shadow_alloc (& objs [i ], SV_ID2 , sizeof (pnfields2 [i ]),
208
+ GFP_KERNEL , shadow_ctor , & pnfields2 [i ]);
209
+ if (!sv2 [i ]) {
210
+ ret = - ENOMEM ;
211
+ goto out ;
212
+ }
213
+ }
234
214
235
- shadow_free (obj + 1 , id , shadow_dtor ); /* sv2 */
236
- sv = shadow_get (obj + 1 , id );
237
- if (!sv )
238
- pr_info (" got expected NULL result\n" );
215
+ /* pass 2: verify we find allocated svars and where they point to */
216
+ for (i = 0 ; i < NUM_OBJS ; i ++ ) {
217
+ /* check the "char" svar for all objects */
218
+ sv = shadow_get (& objs [i ], SV_ID1 );
219
+ if (!sv ) {
220
+ ret = - EINVAL ;
221
+ goto out ;
222
+ }
223
+ if ((char * * )sv == sv1 [i ] && * sv1 [i ] == pnfields1 [i ])
224
+ pr_info (" got expected PTR%d -> PTR%d result\n" ,
225
+ ptr_id (sv1 [i ]), ptr_id (* sv1 [i ]));
226
+
227
+ /* check the "int" svar for all objects */
228
+ sv = shadow_get (& objs [i ], SV_ID2 );
229
+ if (!sv ) {
230
+ ret = - EINVAL ;
231
+ goto out ;
232
+ }
233
+ if ((int * * )sv == sv2 [i ] && * sv2 [i ] == pnfields2 [i ])
234
+ pr_info (" got expected PTR%d -> PTR%d result\n" ,
235
+ ptr_id (sv2 [i ]), ptr_id (* sv2 [i ]));
236
+ }
239
237
240
- shadow_free (obj + 2 , id , shadow_dtor ); /* sv4 */
241
- sv = shadow_get (obj + 2 , id );
242
- if (!sv )
243
- pr_info (" got expected NULL result\n" );
238
+ /* pass 3: verify that 'get_or_alloc' returns already allocated svars */
239
+ for (i = 0 ; i < NUM_OBJS ; i ++ ) {
240
+ pndup [i ] = & nfields1 [i ];
241
+ ptr_id (pndup [i ]);
242
+
243
+ sv = shadow_get_or_alloc (& objs [i ], SV_ID1 , sizeof (pndup [i ]),
244
+ GFP_KERNEL , shadow_ctor , & pndup [i ]);
245
+ if (!sv ) {
246
+ ret = - EINVAL ;
247
+ goto out ;
248
+ }
249
+ if ((char * * )sv == sv1 [i ] && * sv1 [i ] == pnfields1 [i ])
250
+ pr_info (" got expected PTR%d -> PTR%d result\n" ,
251
+ ptr_id (sv1 [i ]), ptr_id (* sv1 [i ]));
252
+ }
244
253
245
- /*
246
- * We should still find an <id+1> variable.
247
- */
248
- sv = shadow_get (obj , id + 1 );
249
- if (!sv )
250
- return - EINVAL ;
251
- if (sv == sv3 && * sv3 == pv3 )
252
- pr_info (" got expected PTR%d -> PTR%d result\n" ,
253
- ptr_id (sv3 ), ptr_id (* sv3 ));
254
+ /* pass 4: free <objs[*], SV_ID1> pairs of svars, verify removal */
255
+ for (i = 0 ; i < NUM_OBJS ; i ++ ) {
256
+ shadow_free (& objs [i ], SV_ID1 , shadow_dtor ); /* 'char' pairs */
257
+ sv = shadow_get (& objs [i ], SV_ID1 );
258
+ if (!sv )
259
+ pr_info (" got expected NULL result\n" );
260
+ }
254
261
255
- /*
256
- * Free all the <id+1> variables, too.
257
- */
258
- shadow_free_all (id + 1 , shadow_dtor ); /* sv3 */
259
- sv = shadow_get (obj , id );
260
- if (!sv )
261
- pr_info (" shadow_get() got expected NULL result\n" );
262
+ /* pass 5: check we still find <objs[*], SV_ID2> svar pairs */
263
+ for (i = 0 ; i < NUM_OBJS ; i ++ ) {
264
+ sv = shadow_get (& objs [i ], SV_ID2 ); /* 'int' pairs */
265
+ if (!sv ) {
266
+ ret = - EINVAL ;
267
+ goto out ;
268
+ }
269
+ if ((int * * )sv == sv2 [i ] && * sv2 [i ] == pnfields2 [i ])
270
+ pr_info (" got expected PTR%d -> PTR%d result\n" ,
271
+ ptr_id (sv2 [i ]), ptr_id (* sv2 [i ]));
272
+ }
262
273
274
+ /* pass 6: free all the <objs[*], SV_ID2> svar pairs too. */
275
+ shadow_free_all (SV_ID2 , NULL ); /* 'int' pairs */
276
+ for (i = 0 ; i < NUM_OBJS ; i ++ ) {
277
+ sv = shadow_get (& objs [i ], SV_ID2 );
278
+ if (!sv )
279
+ pr_info (" got expected NULL result\n" );
280
+ }
263
281
264
282
free_ptr_list ();
265
283
266
284
return 0 ;
285
+ out :
286
+ shadow_free_all (SV_ID1 , NULL ); /* 'char' pairs */
287
+ shadow_free_all (SV_ID2 , NULL ); /* 'int' pairs */
288
+ free_ptr_list ();
289
+
290
+ return ret ;
267
291
}
268
292
269
293
static void test_klp_shadow_vars_exit (void )
0 commit comments