@@ -109,8 +109,7 @@ static void shadow_free(void *obj, unsigned long id, klp_shadow_dtor_t dtor)
109109static void shadow_free_all (unsigned long id , klp_shadow_dtor_t dtor )
110110{
111111 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 ));
114113}
115114
116115
@@ -124,12 +123,16 @@ static int shadow_ctor(void *obj, void *shadow_data, void *ctor_data)
124123 return - EINVAL ;
125124
126125 * 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 ));
129127
130128 return 0 ;
131129}
132130
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+ */
133136static void shadow_dtor (void * obj , void * shadow_data )
134137{
135138 int * * sv = shadow_data ;
@@ -138,132 +141,153 @@ static void shadow_dtor(void *obj, void *shadow_data)
138141 __func__ , ptr_id (obj ), ptr_id (sv ));
139142}
140143
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
146146
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
150150
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 ;
152160
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 ;
157175
158176 ptr_id (NULL );
159- ptr_id (pv1 );
160- ptr_id (pv2 );
161- ptr_id (pv3 );
162- ptr_id (pv4 );
163177
164178 /*
165179 * With an empty shadow variable hash table, expect not to find
166180 * any matches.
167181 */
168- sv = shadow_get (obj , id );
182+ sv = shadow_get (& objs [ 0 ], SV_ID1 );
169183 if (!sv )
170184 pr_info (" got expected NULL result\n" );
171185
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+ }
234214
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+ }
239237
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+ }
244253
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+ }
254261
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+ }
262273
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+ }
263281
264282 free_ptr_list ();
265283
266284 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 ;
267291}
268292
269293static void test_klp_shadow_vars_exit (void )
0 commit comments