Browse Source

peer_control: Fix a use-after-free bug. (#1237)

This bug is a classic case of being lazy:
1. peer_accept_channel() allocated its return off the input message,
   rather than taking an explicit allocation context.  This concealed the
   lifetime nature of the return.
2. The context for sanitize_error was the error itself, rather than the
   more obvious tmpctx (connect_failed does not take).

The global tmpctx removes the "efficiency" excuse for grabbing a random
object to use as context, and is also nice and explicit.

All-the-hard-work-by: @ZmnSCPxj
ppa-0.6.1
ZmnSCPxj, ZmnSCPxj jxPCSmnZ 7 years ago
committed by Rusty Russell
parent
commit
044705a547
  1. 5
      lightningd/opening_control.c
  2. 5
      lightningd/opening_control.h
  3. 8
      lightningd/peer_control.c
  4. 6
      wallet/test/run-wallet.c

5
lightningd/opening_control.c

@ -617,7 +617,8 @@ static void channel_config(struct lightningd *ld,
* NULL if we took over, otherwise hand back to gossipd with this
* error.
*/
u8 *peer_accept_channel(struct lightningd *ld,
u8 *peer_accept_channel(const tal_t *ctx,
struct lightningd *ld,
const struct pubkey *peer_id,
const struct wireaddr *addr,
const struct crypto_state *cs,
@ -637,7 +638,7 @@ u8 *peer_accept_channel(struct lightningd *ld,
/* Fails if there's already one */
uc = new_uncommitted_channel(ld, NULL, peer_id, addr);
if (!uc)
return towire_errorfmt(open_msg, channel_id,
return towire_errorfmt(ctx, channel_id,
"Multiple channels unsupported");
uc->openingd = new_channel_subd(ld, "lightning_openingd", uc, uc->log,

5
lightningd/opening_control.h

@ -16,9 +16,10 @@ void json_add_uncommitted_channel(struct json_result *response,
/* Peer has spontaneously exited from gossip due to open msg. Return
* NULL if we took over, otherwise hand back to gossipd with this
* error.
* error (allocated off @ctx).
*/
u8 *peer_accept_channel(struct lightningd *ld,
u8 *peer_accept_channel(const tal_t *ctx,
struct lightningd *ld,
const struct pubkey *peer_id,
const struct wireaddr *addr,
const struct crypto_state *cs,

8
lightningd/peer_control.c

@ -438,7 +438,8 @@ void peer_sent_nongossip(struct lightningd *ld,
/* Open request? */
if (fromwire_peektype(in_msg) == WIRE_OPEN_CHANNEL) {
error = peer_accept_channel(ld, id, addr, cs, gossip_index,
error = peer_accept_channel(tmpctx,
ld, id, addr, cs, gossip_index,
gfeatures, lfeatures,
peer_fd, gossip_fd, channel_id,
in_msg);
@ -459,18 +460,17 @@ void peer_sent_nongossip(struct lightningd *ld,
}
/* Weird request. */
error = towire_errorfmt(ld, channel_id,
error = towire_errorfmt(tmpctx, channel_id,
"Unexpected message %i for peer",
fromwire_peektype(in_msg));
send_error:
/* Hand back to gossipd, with an error packet. */
connect_failed(ld, id, sanitize_error(error, error, NULL));
connect_failed(ld, id, sanitize_error(tmpctx, error, NULL));
msg = towire_gossipctl_hand_back_peer(ld, id, cs, gossip_index, error);
subd_send_msg(ld->gossip, take(msg));
subd_send_fd(ld->gossip, peer_fd);
subd_send_fd(ld->gossip, gossip_fd);
tal_free(error);
}
static enum watch_result funding_announce_cb(struct channel *channel,

6
wallet/test/run-wallet.c

@ -275,7 +275,8 @@ bool outpointfilter_matches(struct outpointfilter *of UNNEEDED,
struct outpointfilter *outpointfilter_new(tal_t *ctx UNNEEDED)
{ fprintf(stderr, "outpointfilter_new called!\n"); abort(); }
/* Generated stub for peer_accept_channel */
u8 *peer_accept_channel(struct lightningd *ld UNNEEDED,
u8 *peer_accept_channel(const tal_t *ctx UNNEEDED,
struct lightningd *ld UNNEEDED,
const struct pubkey *peer_id UNNEEDED,
const struct wireaddr *addr UNNEEDED,
const struct crypto_state *cs UNNEEDED,
@ -333,9 +334,6 @@ u8 *towire_channel_funding_locked(const tal_t *ctx UNNEEDED, const struct short_
/* Generated stub for towire_channel_send_shutdown */
u8 *towire_channel_send_shutdown(const tal_t *ctx UNNEEDED)
{ fprintf(stderr, "towire_channel_send_shutdown called!\n"); abort(); }
/* Generated stub for towire_error */
u8 *towire_error(const tal_t *ctx UNNEEDED, const struct channel_id *channel_id UNNEEDED, const u8 *data UNNEEDED)
{ fprintf(stderr, "towire_error called!\n"); abort(); }
/* Generated stub for towire_errorfmt */
u8 *towire_errorfmt(const tal_t *ctx UNNEEDED,
const struct channel_id *channel UNNEEDED,

Loading…
Cancel
Save