From 65f1d9c1cdc43443fd0b4644a9747fabaad49461 Mon Sep 17 00:00:00 2001 From: renato Date: Mon, 27 Jun 2016 19:06:33 +0000 Subject: [PATCH] Handle ibuf_add() errors. tweaks from claudio@ --- usr.sbin/ldpd/address.c | 30 ++++++++++------ usr.sbin/ldpd/hello.c | 22 +++++++----- usr.sbin/ldpd/init.c | 13 ++++--- usr.sbin/ldpd/labelmapping.c | 70 ++++++++++++++++++++---------------- usr.sbin/ldpd/ldpe.h | 6 ++-- usr.sbin/ldpd/notification.c | 17 +++++---- 6 files changed, 95 insertions(+), 63 deletions(-) diff --git a/usr.sbin/ldpd/address.c b/usr.sbin/ldpd/address.c index ee7181d6111..fe2e174046d 100644 --- a/usr.sbin/ldpd/address.c +++ b/usr.sbin/ldpd/address.c @@ -1,4 +1,4 @@ -/* $OpenBSD: address.c,v 1.25 2016/05/23 19:11:42 renato Exp $ */ +/* $OpenBSD: address.c,v 1.26 2016/06/27 19:06:33 renato Exp $ */ /* * Copyright (c) 2009 Michele Marchetto @@ -25,7 +25,7 @@ #include "lde.h" #include "log.h" -static void gen_address_list_tlv(struct ibuf *, uint16_t, int, +static int gen_address_list_tlv(struct ibuf *, uint16_t, int, struct if_addr *); void @@ -35,6 +35,7 @@ send_address(struct nbr *nbr, int af, struct if_addr *if_addr, int withdraw) uint32_t msg_type; uint16_t size; int iface_count = 0; + int err = 0; if (!withdraw) msg_type = MSG_TYPE_ADDR; @@ -63,11 +64,15 @@ send_address(struct nbr *nbr, int af, struct if_addr *if_addr, int withdraw) if ((buf = ibuf_open(size)) == NULL) fatal(__func__); - gen_ldp_hdr(buf, size); + err |= gen_ldp_hdr(buf, size); size -= LDP_HDR_SIZE; - gen_msg_hdr(buf, msg_type, size); + err |= gen_msg_hdr(buf, msg_type, size); size -= LDP_MSG_SIZE; - gen_address_list_tlv(buf, size, af, if_addr); + err |= gen_address_list_tlv(buf, size, af, if_addr); + if (err) { + ibuf_free(buf); + return; + } evbuf_enqueue(&nbr->tcp->wbuf, buf); @@ -169,12 +174,13 @@ recv_address(struct nbr *nbr, char *buf, uint16_t len) return (0); } -static void +static int gen_address_list_tlv(struct ibuf *buf, uint16_t size, int af, struct if_addr *if_addr) { struct address_list_tlv alt; uint16_t addr_size; + int err = 0; memset(&alt, 0, sizeof(alt)); alt.type = TLV_TYPE_ADDRLIST; @@ -192,13 +198,15 @@ gen_address_list_tlv(struct ibuf *buf, uint16_t size, int af, fatalx("gen_address_list_tlv: unknown af"); } - ibuf_add(buf, &alt, sizeof(alt)); - + err |= ibuf_add(buf, &alt, sizeof(alt)); if (if_addr == NULL) { LIST_FOREACH(if_addr, &global.addr_list, entry) { - if (if_addr->af == af) - ibuf_add(buf, &if_addr->addr, addr_size); + if (if_addr->af != af) + continue; + err |= ibuf_add(buf, &if_addr->addr, addr_size); } } else - ibuf_add(buf, &if_addr->addr, addr_size); + err |= ibuf_add(buf, &if_addr->addr, addr_size); + + return (err); } diff --git a/usr.sbin/ldpd/hello.c b/usr.sbin/ldpd/hello.c index 192bdf908b8..e9c6da1cb60 100644 --- a/usr.sbin/ldpd/hello.c +++ b/usr.sbin/ldpd/hello.c @@ -1,4 +1,4 @@ -/* $OpenBSD: hello.c,v 1.50 2016/06/18 17:31:32 renato Exp $ */ +/* $OpenBSD: hello.c,v 1.51 2016/06/27 19:06:33 renato Exp $ */ /* * Copyright (c) 2013, 2016 Renato Westphal @@ -41,6 +41,7 @@ send_hello(enum hello_type type, struct iface_af *ia, struct tnbr *tnbr) uint16_t size, holdtime = 0, flags = 0; int fd = 0; struct ibuf *buf; + int err = 0; switch (type) { case HELLO_LINK: @@ -96,10 +97,10 @@ send_hello(enum hello_type type, struct iface_af *ia, struct tnbr *tnbr) if ((buf = ibuf_open(size)) == NULL) fatal(__func__); - gen_ldp_hdr(buf, size); + err |= gen_ldp_hdr(buf, size); size -= LDP_HDR_SIZE; - gen_msg_hdr(buf, MSG_TYPE_HELLO, size); - gen_hello_prms_tlv(buf, holdtime, flags); + err |= gen_msg_hdr(buf, MSG_TYPE_HELLO, size); + err |= gen_hello_prms_tlv(buf, holdtime, flags); /* * RFC 7552 - Section 6.1: @@ -109,18 +110,18 @@ send_hello(enum hello_type type, struct iface_af *ia, struct tnbr *tnbr) */ switch (af) { case AF_INET: - gen_opt4_hello_prms_tlv(buf, TLV_TYPE_IPV4TRANSADDR, + err |= gen_opt4_hello_prms_tlv(buf, TLV_TYPE_IPV4TRANSADDR, leconf->ipv4.trans_addr.v4.s_addr); break; case AF_INET6: - gen_opt16_hello_prms_tlv(buf, TLV_TYPE_IPV6TRANSADDR, + err |= gen_opt16_hello_prms_tlv(buf, TLV_TYPE_IPV6TRANSADDR, leconf->ipv6.trans_addr.v6.s6_addr); break; default: fatalx("send_hello: unknown af"); } - gen_opt4_hello_prms_tlv(buf, TLV_TYPE_CONFIG, + err |= gen_opt4_hello_prms_tlv(buf, TLV_TYPE_CONFIG, htonl(global.conf_seqnum)); /* @@ -129,7 +130,12 @@ send_hello(enum hello_type type, struct iface_af *ia, struct tnbr *tnbr) * MUST include the Dual-Stack capability TLV in all of its LDP Hellos". */ if (ldp_is_dual_stack(leconf)) - gen_ds_hello_prms_tlv(buf, leconf->trans_pref); + err |= gen_ds_hello_prms_tlv(buf, leconf->trans_pref); + + if (err) { + ibuf_free(buf); + return (-1); + } send_packet(fd, af, &dst, ia, buf->buf, buf->wpos); ibuf_free(buf); diff --git a/usr.sbin/ldpd/init.c b/usr.sbin/ldpd/init.c index 7832cd1671e..c6039cc2e19 100644 --- a/usr.sbin/ldpd/init.c +++ b/usr.sbin/ldpd/init.c @@ -1,4 +1,4 @@ -/* $OpenBSD: init.c,v 1.29 2016/06/11 01:55:35 renato Exp $ */ +/* $OpenBSD: init.c,v 1.30 2016/06/27 19:06:33 renato Exp $ */ /* * Copyright (c) 2009 Michele Marchetto @@ -32,6 +32,7 @@ send_init(struct nbr *nbr) { struct ibuf *buf; uint16_t size; + int err = 0; log_debug("%s: lsr-id %s", __func__, inet_ntoa(nbr->id)); @@ -39,11 +40,15 @@ send_init(struct nbr *nbr) if ((buf = ibuf_open(size)) == NULL) fatal(__func__); - gen_ldp_hdr(buf, size); + err |= gen_ldp_hdr(buf, size); size -= LDP_HDR_SIZE; - gen_msg_hdr(buf, MSG_TYPE_INIT, size); + err |= gen_msg_hdr(buf, MSG_TYPE_INIT, size); size -= LDP_MSG_SIZE; - gen_init_prms_tlv(buf, nbr, size); + err |= gen_init_prms_tlv(buf, nbr, size); + if (err) { + ibuf_free(buf); + return; + } evbuf_enqueue(&nbr->tcp->wbuf, buf); } diff --git a/usr.sbin/ldpd/labelmapping.c b/usr.sbin/ldpd/labelmapping.c index c064a541604..c901ea37ee1 100644 --- a/usr.sbin/ldpd/labelmapping.c +++ b/usr.sbin/ldpd/labelmapping.c @@ -1,4 +1,4 @@ -/* $OpenBSD: labelmapping.c,v 1.51 2016/06/18 01:29:05 renato Exp $ */ +/* $OpenBSD: labelmapping.c,v 1.52 2016/06/27 19:06:33 renato Exp $ */ /* * Copyright (c) 2014, 2015 Renato Westphal @@ -30,10 +30,10 @@ #include "log.h" static void enqueue_pdu(struct nbr *, struct ibuf *, uint16_t); -static void gen_label_tlv(struct ibuf *, uint32_t); +static int gen_label_tlv(struct ibuf *, uint32_t); static int tlv_decode_label(struct nbr *, struct ldp_msg *, char *, uint16_t, uint32_t *); -static void gen_reqid_tlv(struct ibuf *, uint32_t); +static int gen_reqid_tlv(struct ibuf *, uint32_t); static void enqueue_pdu(struct nbr *nbr, struct ibuf *buf, uint16_t size) @@ -53,6 +53,7 @@ send_labelmessage(struct nbr *nbr, uint16_t type, struct mapping_head *mh) struct mapping_entry *me; uint16_t msg_size, size = 0; int first = 1; + int err = 0; /* nothing to send */ if (TAILQ_EMPTY(mh)) @@ -66,7 +67,7 @@ send_labelmessage(struct nbr *nbr, uint16_t type, struct mapping_head *mh) fatal(__func__); /* real size will be set up later */ - gen_ldp_hdr(buf, 0); + err |= gen_ldp_hdr(buf, 0); size = LDP_HDR_PDU_LEN; first = 0; @@ -110,14 +111,18 @@ send_labelmessage(struct nbr *nbr, uint16_t type, struct mapping_head *mh) size += msg_size; /* append message and tlvs */ - gen_msg_hdr(buf, type, msg_size); - gen_fec_tlv(buf, &me->map); + err |= gen_msg_hdr(buf, type, msg_size); + err |= gen_fec_tlv(buf, &me->map); if (me->map.label != NO_LABEL) - gen_label_tlv(buf, me->map.label); + err |= gen_label_tlv(buf, me->map.label); if (me->map.flags & F_MAP_REQ_ID) - gen_reqid_tlv(buf, me->map.requestid); + err |= gen_reqid_tlv(buf, me->map.requestid); if (me->map.flags & F_MAP_PW_STATUS) - gen_pw_status_tlv(buf, me->map.pw_status); + err |= gen_pw_status_tlv(buf, me->map.pw_status); + if (err) { + ibuf_free(buf); + return; + } TAILQ_REMOVE(mh, me, entry); free(me); @@ -423,7 +428,7 @@ err: } /* Other TLV related functions */ -static void +static int gen_label_tlv(struct ibuf *buf, uint32_t label) { struct label_tlv lt; @@ -432,7 +437,7 @@ gen_label_tlv(struct ibuf *buf, uint32_t label) lt.length = htons(sizeof(label)); lt.label = htonl(label); - ibuf_add(buf, <, sizeof(lt)); + return (ibuf_add(buf, <, sizeof(lt))); } static int @@ -482,7 +487,7 @@ tlv_decode_label(struct nbr *nbr, struct ldp_msg *lm, char *buf, return (sizeof(lt)); } -static void +static int gen_reqid_tlv(struct ibuf *buf, uint32_t reqid) { struct reqid_tlv rt; @@ -491,10 +496,10 @@ gen_reqid_tlv(struct ibuf *buf, uint32_t reqid) rt.length = htons(sizeof(reqid)); rt.reqid = htonl(reqid); - ibuf_add(buf, &rt, sizeof(rt)); + return (ibuf_add(buf, &rt, sizeof(rt))); } -void +int gen_pw_status_tlv(struct ibuf *buf, uint32_t status) { struct pw_status_tlv st; @@ -503,38 +508,39 @@ gen_pw_status_tlv(struct ibuf *buf, uint32_t status) st.length = htons(sizeof(status)); st.value = htonl(status); - ibuf_add(buf, &st, sizeof(st)); + return (ibuf_add(buf, &st, sizeof(st))); } -void +int gen_fec_tlv(struct ibuf *buf, struct map *map) { struct tlv ft; uint16_t family, len, pw_type, ifmtu; uint8_t pw_len = 0; uint32_t group_id, pwid; + int err = 0; ft.type = htons(TLV_TYPE_FEC); switch (map->type) { case MAP_TYPE_WILDCARD: ft.length = htons(sizeof(uint8_t)); - ibuf_add(buf, &ft, sizeof(ft)); - ibuf_add(buf, &map->type, sizeof(map->type)); + err |= ibuf_add(buf, &ft, sizeof(ft)); + err |= ibuf_add(buf, &map->type, sizeof(map->type)); break; case MAP_TYPE_PREFIX: len = PREFIX_SIZE(map->fec.prefix.prefixlen); ft.length = htons(sizeof(map->type) + sizeof(family) + sizeof(map->fec.prefix.prefixlen) + len); - ibuf_add(buf, &ft, sizeof(ft)); + err |= ibuf_add(buf, &ft, sizeof(ft)); - ibuf_add(buf, &map->type, sizeof(map->type)); + err |= ibuf_add(buf, &map->type, sizeof(map->type)); family = htons(map->fec.prefix.af); - ibuf_add(buf, &family, sizeof(family)); - ibuf_add(buf, &map->fec.prefix.prefixlen, + err |= ibuf_add(buf, &family, sizeof(family)); + err |= ibuf_add(buf, &map->fec.prefix.prefixlen, sizeof(map->fec.prefix.prefixlen)); if (len) - ibuf_add(buf, &map->fec.prefix.prefix, len); + err |= ibuf_add(buf, &map->fec.prefix.prefix, len); break; case MAP_TYPE_PWID: if (map->flags & F_MAP_PW_ID) @@ -545,35 +551,37 @@ gen_fec_tlv(struct ibuf *buf, struct map *map) len = FEC_PWID_ELM_MIN_LEN + pw_len; ft.length = htons(len); - ibuf_add(buf, &ft, sizeof(ft)); + err |= ibuf_add(buf, &ft, sizeof(ft)); - ibuf_add(buf, &map->type, sizeof(uint8_t)); + err |= ibuf_add(buf, &map->type, sizeof(uint8_t)); pw_type = map->fec.pwid.type; if (map->flags & F_MAP_PW_CWORD) pw_type |= CONTROL_WORD_FLAG; pw_type = htons(pw_type); - ibuf_add(buf, &pw_type, sizeof(uint16_t)); - ibuf_add(buf, &pw_len, sizeof(uint8_t)); + err |= ibuf_add(buf, &pw_type, sizeof(uint16_t)); + err |= ibuf_add(buf, &pw_len, sizeof(uint8_t)); group_id = htonl(map->fec.pwid.group_id); - ibuf_add(buf, &group_id, sizeof(uint32_t)); + err |= ibuf_add(buf, &group_id, sizeof(uint32_t)); if (map->flags & F_MAP_PW_ID) { pwid = htonl(map->fec.pwid.pwid); - ibuf_add(buf, &pwid, sizeof(uint32_t)); + err |= ibuf_add(buf, &pwid, sizeof(uint32_t)); } if (map->flags & F_MAP_PW_IFMTU) { struct subtlv stlv; stlv.type = SUBTLV_IFMTU; stlv.length = FEC_SUBTLV_IFMTU_LEN; - ibuf_add(buf, &stlv, sizeof(uint16_t)); + err |= ibuf_add(buf, &stlv, sizeof(uint16_t)); ifmtu = htons(map->fec.pwid.ifmtu); - ibuf_add(buf, &ifmtu, sizeof(uint16_t)); + err |= ibuf_add(buf, &ifmtu, sizeof(uint16_t)); } break; default: break; } + + return (err); } int diff --git a/usr.sbin/ldpd/ldpe.h b/usr.sbin/ldpd/ldpe.h index 9c52a3e860a..dade57be7d3 100644 --- a/usr.sbin/ldpd/ldpe.h +++ b/usr.sbin/ldpd/ldpe.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ldpe.h,v 1.62 2016/06/18 17:31:32 renato Exp $ */ +/* $OpenBSD: ldpe.h,v 1.63 2016/06/27 19:06:33 renato Exp $ */ /* * Copyright (c) 2013, 2016 Renato Westphal @@ -169,8 +169,8 @@ int recv_address(struct nbr *, char *, uint16_t); #define PREFIX_SIZE(x) (((x) + 7) / 8) void send_labelmessage(struct nbr *, uint16_t, struct mapping_head *); int recv_labelmessage(struct nbr *, char *, uint16_t, uint16_t); -void gen_pw_status_tlv(struct ibuf *, uint32_t); -void gen_fec_tlv(struct ibuf *, struct map *); +int gen_pw_status_tlv(struct ibuf *, uint32_t); +int gen_fec_tlv(struct ibuf *, struct map *); int tlv_decode_fec_elm(struct nbr *, struct ldp_msg *, char *, uint16_t, struct map *); diff --git a/usr.sbin/ldpd/notification.c b/usr.sbin/ldpd/notification.c index 06233cf9e86..e6c9cc92825 100644 --- a/usr.sbin/ldpd/notification.c +++ b/usr.sbin/ldpd/notification.c @@ -1,4 +1,4 @@ -/* $OpenBSD: notification.c,v 1.35 2016/06/11 01:55:35 renato Exp $ */ +/* $OpenBSD: notification.c,v 1.36 2016/06/27 19:06:33 renato Exp $ */ /* * Copyright (c) 2009 Michele Marchetto @@ -32,6 +32,7 @@ send_notification_full(struct tcp_conn *tcp, struct notify_msg *nm) { struct ibuf *buf; uint16_t size; + int err = 0; /* calculate size */ size = LDP_HDR_SIZE + LDP_MSG_SIZE + STATUS_SIZE; @@ -51,15 +52,19 @@ send_notification_full(struct tcp_conn *tcp, struct notify_msg *nm) if ((buf = ibuf_open(size)) == NULL) fatal(__func__); - gen_ldp_hdr(buf, size); + err |= gen_ldp_hdr(buf, size); size -= LDP_HDR_SIZE; - gen_msg_hdr(buf, MSG_TYPE_NOTIFICATION, size); - gen_status_tlv(buf, nm->status, nm->messageid, nm->type); + err |= gen_msg_hdr(buf, MSG_TYPE_NOTIFICATION, size); + err |= gen_status_tlv(buf, nm->status, nm->messageid, nm->type); /* optional tlvs */ if (nm->flags & F_NOTIF_PW_STATUS) - gen_pw_status_tlv(buf, nm->pw_status); + err |= gen_pw_status_tlv(buf, nm->pw_status); if (nm->flags & F_NOTIF_FEC) - gen_fec_tlv(buf, &nm->fec); + err |= gen_fec_tlv(buf, &nm->fec); + if (err) { + ibuf_free(buf); + return; + } evbuf_enqueue(&tcp->wbuf, buf); } -- 2.20.1