13
13
#include "core.h"
14
14
#include "patch.h"
15
15
#include "transition.h"
16
- #include "../sched/sched.h"
17
16
18
17
#define MAX_STACK_ENTRIES 100
19
18
#define STACK_ERR_BUF_SIZE 128
@@ -240,20 +239,16 @@ static int klp_check_stack_func(struct klp_func *func, unsigned long *entries,
240
239
* Determine whether it's safe to transition the task to the target patch state
241
240
* by looking for any to-be-patched or to-be-unpatched functions on its stack.
242
241
*/
243
- static int klp_check_stack (struct task_struct * task , char * err_buf )
242
+ static int klp_check_stack (struct task_struct * task , const char * * oldname )
244
243
{
245
244
static unsigned long entries [MAX_STACK_ENTRIES ];
246
245
struct klp_object * obj ;
247
246
struct klp_func * func ;
248
247
int ret , nr_entries ;
249
248
250
249
ret = stack_trace_save_tsk_reliable (task , entries , ARRAY_SIZE (entries ));
251
- if (ret < 0 ) {
252
- snprintf (err_buf , STACK_ERR_BUF_SIZE ,
253
- "%s: %s:%d has an unreliable stack\n" ,
254
- __func__ , task -> comm , task -> pid );
255
- return ret ;
256
- }
250
+ if (ret < 0 )
251
+ return - EINVAL ;
257
252
nr_entries = ret ;
258
253
259
254
klp_for_each_object (klp_transition_patch , obj ) {
@@ -262,32 +257,40 @@ static int klp_check_stack(struct task_struct *task, char *err_buf)
262
257
klp_for_each_func (obj , func ) {
263
258
ret = klp_check_stack_func (func , entries , nr_entries );
264
259
if (ret ) {
265
- snprintf (err_buf , STACK_ERR_BUF_SIZE ,
266
- "%s: %s:%d is sleeping on function %s\n" ,
267
- __func__ , task -> comm , task -> pid ,
268
- func -> old_name );
269
- return ret ;
260
+ * oldname = func -> old_name ;
261
+ return - EADDRINUSE ;
270
262
}
271
263
}
272
264
}
273
265
274
266
return 0 ;
275
267
}
276
268
269
+ static int klp_check_and_switch_task (struct task_struct * task , void * arg )
270
+ {
271
+ int ret ;
272
+
273
+ if (task_curr (task ) && task != current )
274
+ return - EBUSY ;
275
+
276
+ ret = klp_check_stack (task , arg );
277
+ if (ret )
278
+ return ret ;
279
+
280
+ clear_tsk_thread_flag (task , TIF_PATCH_PENDING );
281
+ task -> patch_state = klp_target_state ;
282
+ return 0 ;
283
+ }
284
+
277
285
/*
278
286
* Try to safely switch a task to the target patch state. If it's currently
279
287
* running, or it's sleeping on a to-be-patched or to-be-unpatched function, or
280
288
* if the stack is unreliable, return false.
281
289
*/
282
290
static bool klp_try_switch_task (struct task_struct * task )
283
291
{
284
- static char err_buf [STACK_ERR_BUF_SIZE ];
285
- struct rq * rq ;
286
- struct rq_flags flags ;
292
+ const char * old_name ;
287
293
int ret ;
288
- bool success = false;
289
-
290
- err_buf [0 ] = '\0' ;
291
294
292
295
/* check if this task has already switched over */
293
296
if (task -> patch_state == klp_target_state )
@@ -305,36 +308,31 @@ static bool klp_try_switch_task(struct task_struct *task)
305
308
* functions. If all goes well, switch the task to the target patch
306
309
* state.
307
310
*/
308
- rq = task_rq_lock (task , & flags );
311
+ ret = task_call_func (task , klp_check_and_switch_task , & old_name );
312
+ switch (ret ) {
313
+ case 0 : /* success */
314
+ break ;
309
315
310
- if (task_running (rq , task ) && task != current ) {
311
- snprintf (err_buf , STACK_ERR_BUF_SIZE ,
312
- "%s: %s:%d is running\n" , __func__ , task -> comm ,
313
- task -> pid );
314
- goto done ;
316
+ case - EBUSY : /* klp_check_and_switch_task() */
317
+ pr_debug ("%s: %s:%d is running\n" ,
318
+ __func__ , task -> comm , task -> pid );
319
+ break ;
320
+ case - EINVAL : /* klp_check_and_switch_task() */
321
+ pr_debug ("%s: %s:%d has an unreliable stack\n" ,
322
+ __func__ , task -> comm , task -> pid );
323
+ break ;
324
+ case - EADDRINUSE : /* klp_check_and_switch_task() */
325
+ pr_debug ("%s: %s:%d is sleeping on function %s\n" ,
326
+ __func__ , task -> comm , task -> pid , old_name );
327
+ break ;
328
+
329
+ default :
330
+ pr_debug ("%s: Unknown error code (%d) when trying to switch %s:%d\n" ,
331
+ __func__ , ret , task -> comm , task -> pid );
332
+ break ;
315
333
}
316
334
317
- ret = klp_check_stack (task , err_buf );
318
- if (ret )
319
- goto done ;
320
-
321
- success = true;
322
-
323
- clear_tsk_thread_flag (task , TIF_PATCH_PENDING );
324
- task -> patch_state = klp_target_state ;
325
-
326
- done :
327
- task_rq_unlock (rq , task , & flags );
328
-
329
- /*
330
- * Due to console deadlock issues, pr_debug() can't be used while
331
- * holding the task rq lock. Instead we have to use a temporary buffer
332
- * and print the debug message after releasing the lock.
333
- */
334
- if (err_buf [0 ] != '\0' )
335
- pr_debug ("%s" , err_buf );
336
-
337
- return success ;
335
+ return !ret ;
338
336
}
339
337
340
338
/*
0 commit comments