Jukka Ruohonen <jruoho...@iki.fi> wrote: > +/* > + * sysmon_task_queue_cancel: > + * > + * Cancel a scheduled task. > + */ > +int > +sysmon_task_queue_cancel(void (*func)(void *)) > +{ > + struct sysmon_task *st; > + > + if (func == NULL) > + return EINVAL; > + > + mutex_enter(&sysmon_task_queue_mtx); > + TAILQ_FOREACH(st, &sysmon_task_queue, st_list) { > + if (st->st_func == func) { > + TAILQ_REMOVE(&sysmon_task_queue, st, st_list); > + mutex_exit(&sysmon_task_queue_mtx); > + free(st, M_TEMP); > + mutex_enter(&sysmon_task_queue_mtx); > + } > + } > + mutex_exit(&sysmon_task_queue_mtx);
1) There is a use-after-free. Hint: TAILQ_FOREACH_SAFE(). 2) It is not safe; while lock is dropped, the 'next' entry may also be removed and freed. Hint: have a local list and avoid relocking. -- Mindaugas