mirror of
				https://github.com/clearml/dropbear
				synced 2025-06-26 18:17:32 +00:00 
			
		
		
		
	Split ChanType closehandler() and cleanup() so that dbclient doesn't
lose exit status messages
This commit is contained in:
		
							parent
							
								
									ffde4a524f
								
							
						
					
					
						commit
						fe992bf4ea
					
				
							
								
								
									
										11
									
								
								channel.h
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								channel.h
									
									
									
									
									
								
							| @ -69,10 +69,6 @@ struct Channel { | |||||||
| 	int sent_close, recv_close; | 	int sent_close, recv_close; | ||||||
| 	int recv_eof, sent_eof; | 	int recv_eof, sent_eof; | ||||||
| 
 | 
 | ||||||
| 	/* Set after running the ChanType-specific close hander
 |  | ||||||
| 	 * to ensure we don't run it twice (nor type->checkclose()). */ |  | ||||||
| 	int close_handler_done; |  | ||||||
| 
 |  | ||||||
| 	struct dropbear_progress_connection *conn_pending; | 	struct dropbear_progress_connection *conn_pending; | ||||||
| 	int initconn; /* used for TCP forwarding, whether the channel has been
 | 	int initconn; /* used for TCP forwarding, whether the channel has been
 | ||||||
| 					 fully initialised */ | 					 fully initialised */ | ||||||
| @ -95,10 +91,17 @@ struct ChanType { | |||||||
| 
 | 
 | ||||||
| 	int sepfds; /* Whether this channel has separate pipes for in/out or not */ | 	int sepfds; /* Whether this channel has separate pipes for in/out or not */ | ||||||
| 	const char *name; | 	const char *name; | ||||||
|  | 	/* Sets up the channel */ | ||||||
| 	int (*inithandler)(struct Channel*); | 	int (*inithandler)(struct Channel*); | ||||||
|  | 	/* Called to check whether a channel should close, separately from the FD being closed.
 | ||||||
|  | 	Used for noticing process exiting */ | ||||||
| 	int (*check_close)(const struct Channel*); | 	int (*check_close)(const struct Channel*); | ||||||
|  | 	/* Handler for ssh_msg_channel_request */ | ||||||
| 	void (*reqhandler)(struct Channel*); | 	void (*reqhandler)(struct Channel*); | ||||||
|  | 	/* Called prior to sending ssh_msg_channel_close, used for sending exit status */ | ||||||
| 	void (*closehandler)(const struct Channel*); | 	void (*closehandler)(const struct Channel*); | ||||||
|  | 	/* Frees resources, called just prior to channel being removed */ | ||||||
|  | 	void (*cleanup)(const struct Channel*); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /* Callback for connect_remote */ | /* Callback for connect_remote */ | ||||||
|  | |||||||
| @ -52,6 +52,7 @@ const struct ChanType cli_chan_agent = { | |||||||
| 	new_agent_chan, | 	new_agent_chan, | ||||||
| 	NULL, | 	NULL, | ||||||
| 	NULL, | 	NULL, | ||||||
|  | 	NULL, | ||||||
| 	NULL | 	NULL | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -35,7 +35,7 @@ | |||||||
| #include "chansession.h" | #include "chansession.h" | ||||||
| #include "agentfwd.h" | #include "agentfwd.h" | ||||||
| 
 | 
 | ||||||
| static void cli_closechansess(const struct Channel *channel); | static void cli_cleanupchansess(const struct Channel *channel); | ||||||
| static int cli_initchansess(struct Channel *channel); | static int cli_initchansess(struct Channel *channel); | ||||||
| static void cli_chansessreq(struct Channel *channel); | static void cli_chansessreq(struct Channel *channel); | ||||||
| static void send_chansess_pty_req(const struct Channel *channel); | static void send_chansess_pty_req(const struct Channel *channel); | ||||||
| @ -51,7 +51,8 @@ const struct ChanType clichansess = { | |||||||
| 	cli_initchansess, /* inithandler */ | 	cli_initchansess, /* inithandler */ | ||||||
| 	NULL, /* checkclosehandler */ | 	NULL, /* checkclosehandler */ | ||||||
| 	cli_chansessreq, /* reqhandler */ | 	cli_chansessreq, /* reqhandler */ | ||||||
| 	cli_closechansess, /* closehandler */ | 	NULL, /* closehandler */ | ||||||
|  | 	cli_cleanupchansess, /* cleanup */ | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static void cli_chansessreq(struct Channel *channel) { | static void cli_chansessreq(struct Channel *channel) { | ||||||
| @ -83,7 +84,7 @@ out: | |||||||
| 	 | 	 | ||||||
| 
 | 
 | ||||||
| /* If the main session goes, we close it up */ | /* If the main session goes, we close it up */ | ||||||
| static void cli_closechansess(const struct Channel *UNUSED(channel)) { | static void cli_cleanupchansess(const struct Channel *UNUSED(channel)) { | ||||||
| 	cli_tty_cleanup(); /* Restore tty modes etc */ | 	cli_tty_cleanup(); /* Restore tty modes etc */ | ||||||
| 
 | 
 | ||||||
| 	/* This channel hasn't gone yet, so we have > 1 */ | 	/* This channel hasn't gone yet, so we have > 1 */ | ||||||
| @ -387,7 +388,8 @@ static const struct ChanType cli_chan_netcat = { | |||||||
| 	cli_init_netcat, /* inithandler */ | 	cli_init_netcat, /* inithandler */ | ||||||
| 	NULL, | 	NULL, | ||||||
| 	NULL, | 	NULL, | ||||||
| 	cli_closechansess | 	NULL, | ||||||
|  | 	cli_cleanupchansess | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void cli_send_netcat_request() { | void cli_send_netcat_request() { | ||||||
|  | |||||||
| @ -356,6 +356,7 @@ static void cli_session_cleanup(void) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void cli_finished() { | static void cli_finished() { | ||||||
|  | 	TRACE(("cli_finised()")) | ||||||
| 
 | 
 | ||||||
| 	session_cleanup(); | 	session_cleanup(); | ||||||
| 	fprintf(stderr, "Connection to %s@%s:%s closed.\n", cli_opts.username, | 	fprintf(stderr, "Connection to %s@%s:%s closed.\n", cli_opts.username, | ||||||
|  | |||||||
| @ -40,6 +40,7 @@ const struct ChanType cli_chan_tcpremote = { | |||||||
| 	newtcpforwarded, | 	newtcpforwarded, | ||||||
| 	NULL, | 	NULL, | ||||||
| 	NULL, | 	NULL, | ||||||
|  | 	NULL, | ||||||
| 	NULL | 	NULL | ||||||
| }; | }; | ||||||
| #endif | #endif | ||||||
| @ -55,6 +56,7 @@ static const struct ChanType cli_chan_tcplocal = { | |||||||
| 	tcp_prio_inithandler, | 	tcp_prio_inithandler, | ||||||
| 	NULL, | 	NULL, | ||||||
| 	NULL, | 	NULL, | ||||||
|  | 	NULL, | ||||||
| 	NULL | 	NULL | ||||||
| }; | }; | ||||||
| #endif | #endif | ||||||
|  | |||||||
| @ -144,7 +144,6 @@ static struct Channel* newchannel(unsigned int remotechan, | |||||||
| 	newchan->index = i; | 	newchan->index = i; | ||||||
| 	newchan->sent_close = newchan->recv_close = 0; | 	newchan->sent_close = newchan->recv_close = 0; | ||||||
| 	newchan->sent_eof = newchan->recv_eof = 0; | 	newchan->sent_eof = newchan->recv_eof = 0; | ||||||
| 	newchan->close_handler_done = 0; |  | ||||||
| 
 | 
 | ||||||
| 	newchan->remotechan = remotechan; | 	newchan->remotechan = remotechan; | ||||||
| 	newchan->transwindow = transwindow; | 	newchan->transwindow = transwindow; | ||||||
| @ -286,7 +285,7 @@ static void check_close(struct Channel *channel) { | |||||||
| 				channel->extrabuf ? cbuf_getused(channel->extrabuf) : 0)) | 				channel->extrabuf ? cbuf_getused(channel->extrabuf) : 0)) | ||||||
| 
 | 
 | ||||||
| 	if (!channel->flushing  | 	if (!channel->flushing  | ||||||
| 		&& !channel->close_handler_done | 		&& !channel->sent_close | ||||||
| 		&& channel->type->check_close | 		&& channel->type->check_close | ||||||
| 		&& channel->type->check_close(channel)) | 		&& channel->type->check_close(channel)) | ||||||
| 	{ | 	{ | ||||||
| @ -298,7 +297,7 @@ static void check_close(struct Channel *channel) { | |||||||
| 	   channel, to ensure that the shell has exited (and the exit status  | 	   channel, to ensure that the shell has exited (and the exit status  | ||||||
| 	   retrieved) before we close things up. */ | 	   retrieved) before we close things up. */ | ||||||
| 	if (!channel->type->check_close	 | 	if (!channel->type->check_close	 | ||||||
| 		|| channel->close_handler_done | 		|| channel->sent_close | ||||||
| 		|| channel->type->check_close(channel)) { | 		|| channel->type->check_close(channel)) { | ||||||
| 		close_allowed = 1; | 		close_allowed = 1; | ||||||
| 	} | 	} | ||||||
| @ -385,10 +384,8 @@ void channel_connect_done(int result, int sock, void* user_data, const char* UNU | |||||||
| static void send_msg_channel_close(struct Channel *channel) { | static void send_msg_channel_close(struct Channel *channel) { | ||||||
| 
 | 
 | ||||||
| 	TRACE(("enter send_msg_channel_close %p", (void*)channel)) | 	TRACE(("enter send_msg_channel_close %p", (void*)channel)) | ||||||
| 	if (channel->type->closehandler  | 	if (channel->type->closehandler) { | ||||||
| 			&& !channel->close_handler_done) { |  | ||||||
| 		channel->type->closehandler(channel); | 		channel->type->closehandler(channel); | ||||||
| 		channel->close_handler_done = 1; |  | ||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
| 	CHECKCLEARTOWRITE(); | 	CHECKCLEARTOWRITE(); | ||||||
| @ -661,10 +658,8 @@ static void remove_channel(struct Channel * channel) { | |||||||
| 		m_close(channel->errfd); | 		m_close(channel->errfd); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (!channel->close_handler_done | 	if (channel->type->cleanup) { | ||||||
| 		&& channel->type->closehandler) { | 		channel->type->cleanup(channel); | ||||||
| 		channel->type->closehandler(channel); |  | ||||||
| 		channel->close_handler_done = 1; |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (channel->conn_pending) { | 	if (channel->conn_pending) { | ||||||
| @ -690,13 +685,7 @@ void recv_msg_channel_request() { | |||||||
| 
 | 
 | ||||||
| 	TRACE(("enter recv_msg_channel_request %p", (void*)channel)) | 	TRACE(("enter recv_msg_channel_request %p", (void*)channel)) | ||||||
| 
 | 
 | ||||||
| 	if (channel->sent_close) { | 	if (channel->type->reqhandler) { | ||||||
| 		TRACE(("leave recv_msg_channel_request: already closed channel")) |  | ||||||
| 		return; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (channel->type->reqhandler  |  | ||||||
| 			&& !channel->close_handler_done) { |  | ||||||
| 		channel->type->reqhandler(channel); | 		channel->type->reqhandler(channel); | ||||||
| 	} else { | 	} else { | ||||||
| 		int wantreply; | 		int wantreply; | ||||||
| @ -1011,6 +1000,11 @@ cleanup: | |||||||
| void send_msg_channel_failure(const struct Channel *channel) { | void send_msg_channel_failure(const struct Channel *channel) { | ||||||
| 
 | 
 | ||||||
| 	TRACE(("enter send_msg_channel_failure")) | 	TRACE(("enter send_msg_channel_failure")) | ||||||
|  | 
 | ||||||
|  | 	if (channel->sent_close) { | ||||||
|  | 		TRACE(("Skipping sending msg_channel_failure for closed channel")) | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
| 	CHECKCLEARTOWRITE(); | 	CHECKCLEARTOWRITE(); | ||||||
| 
 | 
 | ||||||
| 	buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_FAILURE); | 	buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_FAILURE); | ||||||
| @ -1024,6 +1018,10 @@ void send_msg_channel_failure(const struct Channel *channel) { | |||||||
| void send_msg_channel_success(const struct Channel *channel) { | void send_msg_channel_success(const struct Channel *channel) { | ||||||
| 
 | 
 | ||||||
| 	TRACE(("enter send_msg_channel_success")) | 	TRACE(("enter send_msg_channel_success")) | ||||||
|  | 	if (channel->sent_close) { | ||||||
|  | 		TRACE(("Skipping sending msg_channel_success for closed channel")) | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
| 	CHECKCLEARTOWRITE(); | 	CHECKCLEARTOWRITE(); | ||||||
| 
 | 
 | ||||||
| 	buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_SUCCESS); | 	buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_SUCCESS); | ||||||
|  | |||||||
| @ -187,6 +187,7 @@ static const struct ChanType chan_svr_agent = { | |||||||
| 	NULL, | 	NULL, | ||||||
| 	NULL, | 	NULL, | ||||||
| 	NULL, | 	NULL, | ||||||
|  | 	NULL, | ||||||
| 	NULL | 	NULL | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -51,6 +51,7 @@ static void execchild(const void *user_data_chansess); | |||||||
| static void addchildpid(struct ChanSess *chansess, pid_t pid); | static void addchildpid(struct ChanSess *chansess, pid_t pid); | ||||||
| static void sesssigchild_handler(int val); | static void sesssigchild_handler(int val); | ||||||
| static void closechansess(const struct Channel *channel); | static void closechansess(const struct Channel *channel); | ||||||
|  | static void cleanupchansess(const struct Channel *channel); | ||||||
| static int newchansess(struct Channel *channel); | static int newchansess(struct Channel *channel); | ||||||
| static void chansessionrequest(struct Channel *channel); | static void chansessionrequest(struct Channel *channel); | ||||||
| static int sesscheckclose(const struct Channel *channel); | static int sesscheckclose(const struct Channel *channel); | ||||||
| @ -69,6 +70,7 @@ const struct ChanType svrchansess = { | |||||||
| 	sesscheckclose, /* checkclosehandler */ | 	sesscheckclose, /* checkclosehandler */ | ||||||
| 	chansessionrequest, /* reqhandler */ | 	chansessionrequest, /* reqhandler */ | ||||||
| 	closechansess, /* closehandler */ | 	closechansess, /* closehandler */ | ||||||
|  | 	cleanupchansess /* cleanup */ | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /* required to clear environment */ | /* required to clear environment */ | ||||||
| @ -91,7 +93,7 @@ void svr_chansess_checksignal(void) { | |||||||
| 	while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { | 	while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { | ||||||
| 		unsigned int i; | 		unsigned int i; | ||||||
| 		struct exitinfo *ex = NULL; | 		struct exitinfo *ex = NULL; | ||||||
| 		TRACE(("sigchld handler: pid %d", pid)) | 		TRACE(("svr_chansess_checksignal : pid %d", pid)) | ||||||
| 
 | 
 | ||||||
| 		ex = NULL; | 		ex = NULL; | ||||||
| 		/* find the corresponding chansess */ | 		/* find the corresponding chansess */ | ||||||
| @ -285,8 +287,25 @@ chansess_login_alloc(const struct ChanSess *chansess) { | |||||||
| 	return li; | 	return li; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* clean a session channel */ | /* send exit status message before the channel is closed */ | ||||||
| static void closechansess(const struct Channel *channel) { | static void closechansess(const struct Channel *channel) { | ||||||
|  | 	struct ChanSess *chansess; | ||||||
|  | 
 | ||||||
|  | 	TRACE(("enter closechansess")) | ||||||
|  | 
 | ||||||
|  | 	chansess = (struct ChanSess*)channel->typedata; | ||||||
|  | 
 | ||||||
|  | 	if (chansess == NULL) { | ||||||
|  | 		TRACE(("leave closechansess: chansess == NULL")) | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	send_exitsignalstatus(channel); | ||||||
|  | 	TRACE(("leave closechansess")) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* clean a session channel */ | ||||||
|  | static void cleanupchansess(const struct Channel *channel) { | ||||||
| 
 | 
 | ||||||
| 	struct ChanSess *chansess; | 	struct ChanSess *chansess; | ||||||
| 	unsigned int i; | 	unsigned int i; | ||||||
| @ -301,8 +320,6 @@ static void closechansess(const struct Channel *channel) { | |||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	send_exitsignalstatus(channel); |  | ||||||
| 
 |  | ||||||
| 	m_free(chansess->cmd); | 	m_free(chansess->cmd); | ||||||
| 	m_free(chansess->term); | 	m_free(chansess->term); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -238,7 +238,8 @@ const struct ChanType svr_chan_tcpdirect = { | |||||||
| 	newtcpdirect, /* init */ | 	newtcpdirect, /* init */ | ||||||
| 	NULL, /* checkclose */ | 	NULL, /* checkclose */ | ||||||
| 	NULL, /* reqhandler */ | 	NULL, /* reqhandler */ | ||||||
| 	NULL /* closehandler */ | 	NULL, /* closehandler */ | ||||||
|  | 	NULL /* cleanup */ | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /* Called upon creating a new direct tcp channel (ie we connect out to an
 | /* Called upon creating a new direct tcp channel (ie we connect out to an
 | ||||||
|  | |||||||
| @ -216,7 +216,8 @@ static const struct ChanType chan_x11 = { | |||||||
| 	x11_inithandler, /* inithandler */ | 	x11_inithandler, /* inithandler */ | ||||||
| 	NULL, /* checkclose */ | 	NULL, /* checkclose */ | ||||||
| 	NULL, /* reqhandler */ | 	NULL, /* reqhandler */ | ||||||
| 	NULL /* closehandler */ | 	NULL, /* closehandler */ | ||||||
|  | 	NULL /* cleanup */ | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user