mirror of
				https://gitlab.labs.nic.cz/labs/bird.git
				synced 2024-05-11 16:54:54 +00:00 
			
		
		
		
	Fix use-after free in thread stopping code
This commit is contained in:
		| @@ -294,6 +294,13 @@ pipe_pollin(struct pipe *p, struct pfd *pfd) | |||||||
|   BUFFER_PUSH(pfd->loop) = NULL; |   BUFFER_PUSH(pfd->loop) = NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void | ||||||
|  | pipe_free(struct pipe *p) | ||||||
|  | { | ||||||
|  |   close(p->fd[0]); | ||||||
|  |   close(p->fd[1]); | ||||||
|  | } | ||||||
|  |  | ||||||
| static inline void | static inline void | ||||||
| wakeup_init(struct bird_thread *loop) | wakeup_init(struct bird_thread *loop) | ||||||
| { | { | ||||||
| @@ -312,6 +319,12 @@ wakeup_do_kick(struct bird_thread *loop) | |||||||
|   pipe_kick(&loop->wakeup); |   pipe_kick(&loop->wakeup); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static inline void | ||||||
|  | wakeup_free(struct bird_thread *loop) | ||||||
|  | { | ||||||
|  |   pipe_free(&loop->wakeup); | ||||||
|  | } | ||||||
|  |  | ||||||
| static inline _Bool | static inline _Bool | ||||||
| birdloop_try_ping(struct birdloop *loop, u32 ltt) | birdloop_try_ping(struct birdloop *loop, u32 ltt) | ||||||
| { | { | ||||||
| @@ -918,14 +931,24 @@ static void | |||||||
| bird_thread_cleanup(void *_thr) | bird_thread_cleanup(void *_thr) | ||||||
| { | { | ||||||
|   struct bird_thread *thr = _thr; |   struct bird_thread *thr = _thr; | ||||||
|  |   struct birdloop *meta = thr->meta; | ||||||
|   ASSERT_DIE(birdloop_inside(&main_birdloop)); |   ASSERT_DIE(birdloop_inside(&main_birdloop)); | ||||||
|  |  | ||||||
|   /* Free the meta loop */ |   /* Wait until the thread actually finishes */ | ||||||
|   thr->meta->thread = NULL; |   ASSERT_DIE(meta); | ||||||
|   birdloop_free(thr->meta); |   birdloop_enter(meta); | ||||||
|  |   birdloop_leave(meta); | ||||||
|  |  | ||||||
|  |   /* No more wakeup */ | ||||||
|  |   wakeup_free(thr); | ||||||
|  |  | ||||||
|   /* Thread attributes no longer needed */ |   /* Thread attributes no longer needed */ | ||||||
|   pthread_attr_destroy(&thr->thread_attr); |   pthread_attr_destroy(&thr->thread_attr); | ||||||
|  |  | ||||||
|  |   /* Free the meta loop */ | ||||||
|  |   thr->meta->thread = NULL; | ||||||
|  |   thr->meta = NULL; | ||||||
|  |   birdloop_free(meta); | ||||||
| } | } | ||||||
|  |  | ||||||
| static struct bird_thread * | static struct bird_thread * | ||||||
| @@ -1035,6 +1058,10 @@ bird_thread_shutdown(void * _ UNUSED) | |||||||
|   /* Leave the thread-dropper loop as we aren't going to return. */ |   /* Leave the thread-dropper loop as we aren't going to return. */ | ||||||
|   birdloop_leave(thread_dropper); |   birdloop_leave(thread_dropper); | ||||||
|  |  | ||||||
|  |   /* Last try to run the priority event list; ruin it then to be extra sure */ | ||||||
|  |   ev_run_list(&this_thread->priority_events); | ||||||
|  |   memset(&this_thread->priority_events, 0xa5, sizeof(this_thread->priority_events)); | ||||||
|  |  | ||||||
|   /* Drop loops including the thread dropper itself */ |   /* Drop loops including the thread dropper itself */ | ||||||
|   while (!EMPTY_LIST(thr->loops)) |   while (!EMPTY_LIST(thr->loops)) | ||||||
|   { |   { | ||||||
| @@ -1054,8 +1081,8 @@ bird_thread_shutdown(void * _ UNUSED) | |||||||
|     wakeup_do_kick(SKIP_BACK(struct bird_thread, n, HEAD(group->threads))); |     wakeup_do_kick(SKIP_BACK(struct bird_thread, n, HEAD(group->threads))); | ||||||
|   UNLOCK_DOMAIN(attrs, group->domain); |   UNLOCK_DOMAIN(attrs, group->domain); | ||||||
|  |  | ||||||
|   /* Stop the meta loop */ |   /* Request thread cleanup from main loop */ | ||||||
|   birdloop_leave(thr->meta); |   ev_send_loop(&main_birdloop, &thr->cleanup_event); | ||||||
|  |  | ||||||
|   /* Local pages not needed anymore */ |   /* Local pages not needed anymore */ | ||||||
|   flush_local_pages(); |   flush_local_pages(); | ||||||
| @@ -1063,8 +1090,8 @@ bird_thread_shutdown(void * _ UNUSED) | |||||||
|   /* Unregister from RCU */ |   /* Unregister from RCU */ | ||||||
|   rcu_thread_stop(&thr->rcu); |   rcu_thread_stop(&thr->rcu); | ||||||
|  |  | ||||||
|   /* Request thread cleanup from main loop */ |   /* Now we can be cleaned up */ | ||||||
|   ev_send_loop(&main_birdloop, &thr->cleanup_event); |   birdloop_leave(thr->meta); | ||||||
|  |  | ||||||
|   /* Exit! */ |   /* Exit! */ | ||||||
|   pthread_exit(NULL); |   pthread_exit(NULL); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user