Mercurial > dropbear
comparison common-channel.c @ 652:17962b2a6b8f
- Make sure we don't use channel-specific data after it has been freed
with a ChanType->closehandler()
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Sun, 04 Dec 2011 05:27:29 +0800 |
parents | a98a2138364a |
children | c519b78b6d1a |
comparison
equal
deleted
inserted
replaced
651:a48a1f6ab43e | 652:17962b2a6b8f |
---|---|
136 newchan = (struct Channel*)m_malloc(sizeof(struct Channel)); | 136 newchan = (struct Channel*)m_malloc(sizeof(struct Channel)); |
137 newchan->type = type; | 137 newchan->type = type; |
138 newchan->index = i; | 138 newchan->index = i; |
139 newchan->sent_close = newchan->recv_close = 0; | 139 newchan->sent_close = newchan->recv_close = 0; |
140 newchan->sent_eof = newchan->recv_eof = 0; | 140 newchan->sent_eof = newchan->recv_eof = 0; |
141 newchan->close_handler_done = 0; | |
141 | 142 |
142 newchan->remotechan = remotechan; | 143 newchan->remotechan = remotechan; |
143 newchan->transwindow = transwindow; | 144 newchan->transwindow = transwindow; |
144 newchan->transmaxpacket = transmaxpacket; | 145 newchan->transmaxpacket = transmaxpacket; |
145 | 146 |
268 channel->errfd, channel->sent_close, channel->recv_close)) | 269 channel->errfd, channel->sent_close, channel->recv_close)) |
269 TRACE(("writebuf size %d extrabuf size %d", | 270 TRACE(("writebuf size %d extrabuf size %d", |
270 cbuf_getused(channel->writebuf), | 271 cbuf_getused(channel->writebuf), |
271 channel->extrabuf ? cbuf_getused(channel->extrabuf) : 0)) | 272 channel->extrabuf ? cbuf_getused(channel->extrabuf) : 0)) |
272 | 273 |
273 if (!channel->flushing && channel->type->check_close | 274 if (!channel->flushing |
275 && !channel->close_handler_done | |
276 && channel->type->check_close | |
274 && channel->type->check_close(channel)) | 277 && channel->type->check_close(channel)) |
275 { | 278 { |
276 channel->flushing = 1; | 279 channel->flushing = 1; |
277 } | 280 } |
278 | 281 |
279 /* if a type-specific check_close is defined we will only exit | 282 /* if a type-specific check_close is defined we will only exit |
280 once that has been triggered. this is only used for a server "session" | 283 once that has been triggered. this is only used for a server "session" |
281 channel, to ensure that the shell has exited (and the exit status | 284 channel, to ensure that the shell has exited (and the exit status |
282 retrieved) before we close things up. */ | 285 retrieved) before we close things up. */ |
283 if (!channel->type->check_close | 286 if (!channel->type->check_close |
284 || channel->type->check_close(channel)) { | 287 || channel->close_handler_done |
288 || channel->type->check_close(channel)) { | |
285 close_allowed = 1; | 289 close_allowed = 1; |
286 } | 290 } |
287 | 291 |
288 if (channel->recv_close && !write_pending(channel) && close_allowed) { | 292 if (channel->recv_close && !write_pending(channel) && close_allowed) { |
289 if (!channel->sent_close) { | 293 if (!channel->sent_close) { |
361 | 365 |
362 | 366 |
363 /* Send the close message and set the channel as closed */ | 367 /* Send the close message and set the channel as closed */ |
364 static void send_msg_channel_close(struct Channel *channel) { | 368 static void send_msg_channel_close(struct Channel *channel) { |
365 | 369 |
366 TRACE(("enter send_msg_channel_close")) | 370 TRACE(("enter send_msg_channel_close %p", channel)) |
367 if (channel->type->closehandler) { | 371 if (channel->type->closehandler |
372 && !channel->close_handler_done) { | |
368 channel->type->closehandler(channel); | 373 channel->type->closehandler(channel); |
374 channel->close_handler_done = 1; | |
369 } | 375 } |
370 | 376 |
371 CHECKCLEARTOWRITE(); | 377 CHECKCLEARTOWRITE(); |
372 | 378 |
373 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_CLOSE); | 379 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_CLOSE); |
566 * such as chansession or x11fwd */ | 572 * such as chansession or x11fwd */ |
567 void recv_msg_channel_request() { | 573 void recv_msg_channel_request() { |
568 | 574 |
569 struct Channel *channel; | 575 struct Channel *channel; |
570 | 576 |
571 TRACE(("enter recv_msg_channel_request")) | |
572 | |
573 channel = getchannel(); | 577 channel = getchannel(); |
578 | |
579 TRACE(("enter recv_msg_channel_request %p", channel)) | |
574 | 580 |
575 if (channel->sent_close) { | 581 if (channel->sent_close) { |
576 TRACE(("leave recv_msg_channel_request: already closed channel")) | 582 TRACE(("leave recv_msg_channel_request: already closed channel")) |
577 return; | 583 return; |
578 } | 584 } |
579 | 585 |
580 if (channel->type->reqhandler) { | 586 if (channel->type->reqhandler |
587 && !channel->close_handler_done) { | |
581 channel->type->reqhandler(channel); | 588 channel->type->reqhandler(channel); |
582 } else { | 589 } else { |
583 send_msg_channel_failure(channel); | 590 send_msg_channel_failure(channel); |
584 } | 591 } |
585 | 592 |