zebra: check for buffer boundary

* Move code encoding Netlink messages to separate functions
 * Add buffer bounds checking while creating Nelink messages

Signed-off-by: Jakub Urbańczyk <xthaid@gmail.com>
This commit is contained in:
Jakub Urbańczyk 2020-06-10 11:44:31 +02:00
parent 312a6beed6
commit 0be6e7d75d
5 changed files with 463 additions and 270 deletions

View File

@ -709,12 +709,13 @@ static int fpm_nl_enqueue(struct fpm_nl_ctx *fnc, struct zebra_dplane_ctx *ctx)
switch (op) { switch (op) {
case DPLANE_OP_ROUTE_UPDATE: case DPLANE_OP_ROUTE_UPDATE:
case DPLANE_OP_ROUTE_DELETE: case DPLANE_OP_ROUTE_DELETE:
rv = netlink_route_multipath(RTM_DELROUTE, ctx, nl_buf, rv = netlink_route_multipath_msg_encode(RTM_DELROUTE, ctx,
sizeof(nl_buf), true, nl_buf, sizeof(nl_buf),
fnc->use_nhg); true, fnc->use_nhg);
if (rv <= 0) { if (rv <= 0) {
zlog_err("%s: netlink_route_multipath failed", zlog_err(
__func__); "%s: netlink_route_multipath_msg_encode failed",
__func__);
return 0; return 0;
} }
@ -726,12 +727,13 @@ static int fpm_nl_enqueue(struct fpm_nl_ctx *fnc, struct zebra_dplane_ctx *ctx)
/* FALL THROUGH */ /* FALL THROUGH */
case DPLANE_OP_ROUTE_INSTALL: case DPLANE_OP_ROUTE_INSTALL:
rv = netlink_route_multipath( rv = netlink_route_multipath_msg_encode(
RTM_NEWROUTE, ctx, &nl_buf[nl_buf_len], RTM_NEWROUTE, ctx, &nl_buf[nl_buf_len],
sizeof(nl_buf) - nl_buf_len, true, fnc->use_nhg); sizeof(nl_buf) - nl_buf_len, true, fnc->use_nhg);
if (rv <= 0) { if (rv <= 0) {
zlog_err("%s: netlink_route_multipath failed", zlog_err(
__func__); "%s: netlink_route_multipath_msg_encode failed",
__func__);
return 0; return 0;
} }
@ -751,10 +753,11 @@ static int fpm_nl_enqueue(struct fpm_nl_ctx *fnc, struct zebra_dplane_ctx *ctx)
break; break;
case DPLANE_OP_NH_DELETE: case DPLANE_OP_NH_DELETE:
rv = netlink_nexthop_encode(RTM_DELNEXTHOP, ctx, nl_buf, rv = netlink_nexthop_msg_encode(RTM_DELNEXTHOP, ctx, nl_buf,
sizeof(nl_buf)); sizeof(nl_buf));
if (rv <= 0) { if (rv <= 0) {
zlog_err("%s: netlink_nexthop_encode failed", __func__); zlog_err("%s: netlink_nexthop_msg_encode failed",
__func__);
return 0; return 0;
} }
@ -762,10 +765,11 @@ static int fpm_nl_enqueue(struct fpm_nl_ctx *fnc, struct zebra_dplane_ctx *ctx)
break; break;
case DPLANE_OP_NH_INSTALL: case DPLANE_OP_NH_INSTALL:
case DPLANE_OP_NH_UPDATE: case DPLANE_OP_NH_UPDATE:
rv = netlink_nexthop_encode(RTM_NEWNEXTHOP, ctx, nl_buf, rv = netlink_nexthop_msg_encode(RTM_NEWNEXTHOP, ctx, nl_buf,
sizeof(nl_buf)); sizeof(nl_buf));
if (rv <= 0) { if (rv <= 0) {
zlog_err("%s: netlink_nexthop_encode failed", __func__); zlog_err("%s: netlink_nexthop_msg_encode failed",
__func__);
return 0; return 0;
} }

File diff suppressed because it is too large Load Diff

View File

@ -64,11 +64,14 @@ extern "C" {
void rt_netlink_init(void); void rt_netlink_init(void);
/* MPLS label forwarding table change, using dataplane context information. */ /* MPLS label forwarding table change, using dataplane context information. */
extern int netlink_mpls_multipath(int cmd, struct zebra_dplane_ctx *ctx); extern ssize_t netlink_mpls_multipath_msg_encode(int cmd,
struct zebra_dplane_ctx *ctx,
void *buf, size_t buflen);
extern ssize_t netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx, extern ssize_t netlink_route_multipath_msg_encode(int cmd,
uint8_t *data, size_t datalen, bool fpm, struct zebra_dplane_ctx *ctx,
bool force_nhg); uint8_t *data, size_t datalen,
bool fpm, bool force_nhg);
extern ssize_t netlink_macfdb_update_ctx(struct zebra_dplane_ctx *ctx, extern ssize_t netlink_macfdb_update_ctx(struct zebra_dplane_ctx *ctx,
uint8_t *data, size_t datalen); uint8_t *data, size_t datalen);
@ -78,9 +81,9 @@ extern int netlink_route_read(struct zebra_ns *zns);
extern int netlink_nexthop_change(struct nlmsghdr *h, ns_id_t ns_id, extern int netlink_nexthop_change(struct nlmsghdr *h, ns_id_t ns_id,
int startup); int startup);
extern int netlink_nexthop_read(struct zebra_ns *zns); extern int netlink_nexthop_read(struct zebra_ns *zns);
extern ssize_t netlink_nexthop_encode(uint16_t cmd, extern ssize_t netlink_nexthop_msg_encode(uint16_t cmd,
const struct zebra_dplane_ctx *ctx, const struct zebra_dplane_ctx *ctx,
void *buf, size_t buflen); void *buf, size_t buflen);
extern int netlink_neigh_change(struct nlmsghdr *h, ns_id_t ns_id); extern int netlink_neigh_change(struct nlmsghdr *h, ns_id_t ns_id);
extern int netlink_macfdb_read(struct zebra_ns *zns); extern int netlink_macfdb_read(struct zebra_ns *zns);

View File

@ -87,38 +87,48 @@ static ssize_t netlink_rule_msg_encode(
req->frh.family = family; req->frh.family = family;
req->frh.action = FR_ACT_TO_TBL; req->frh.action = FR_ACT_TO_TBL;
nl_attr_put(&req->n, buflen, FRA_PROTOCOL, &protocol, sizeof(protocol)); if (!nl_attr_put(&req->n, buflen, FRA_PROTOCOL, &protocol,
sizeof(protocol)))
return 0;
/* rule's pref # */ /* rule's pref # */
nl_attr_put32(&req->n, buflen, FRA_PRIORITY, priority); if (!nl_attr_put32(&req->n, buflen, FRA_PRIORITY, priority))
return 0;
/* interface on which applied */ /* interface on which applied */
nl_attr_put(&req->n, buflen, FRA_IFNAME, ifname, strlen(ifname) + 1); if (!nl_attr_put(&req->n, buflen, FRA_IFNAME, ifname,
strlen(ifname) + 1))
return 0;
/* source IP, if specified */ /* source IP, if specified */
if (filter_bm & PBR_FILTER_SRC_IP) { if (filter_bm & PBR_FILTER_SRC_IP) {
req->frh.src_len = src_ip->prefixlen; req->frh.src_len = src_ip->prefixlen;
nl_attr_put(&req->n, buflen, FRA_SRC, &src_ip->u.prefix, if (!nl_attr_put(&req->n, buflen, FRA_SRC, &src_ip->u.prefix,
bytelen); bytelen))
return 0;
} }
/* destination IP, if specified */ /* destination IP, if specified */
if (filter_bm & PBR_FILTER_DST_IP) { if (filter_bm & PBR_FILTER_DST_IP) {
req->frh.dst_len = dst_ip->prefixlen; req->frh.dst_len = dst_ip->prefixlen;
nl_attr_put(&req->n, buflen, FRA_DST, &dst_ip->u.prefix, if (!nl_attr_put(&req->n, buflen, FRA_DST, &dst_ip->u.prefix,
bytelen); bytelen))
return 0;
} }
/* fwmark, if specified */ /* fwmark, if specified */
if (filter_bm & PBR_FILTER_FWMARK) if (filter_bm & PBR_FILTER_FWMARK) {
nl_attr_put32(&req->n, buflen, FRA_FWMARK, fwmark); if (!nl_attr_put32(&req->n, buflen, FRA_FWMARK, fwmark))
return 0;
}
/* Route table to use to forward, if filter criteria matches. */ /* Route table to use to forward, if filter criteria matches. */
if (table < 256) if (table < 256)
req->frh.table = table; req->frh.table = table;
else { else {
req->frh.table = RT_TABLE_UNSPEC; req->frh.table = RT_TABLE_UNSPEC;
nl_attr_put32(&req->n, buflen, FRA_TABLE, table); if (!nl_attr_put32(&req->n, buflen, FRA_TABLE, table))
return 0;
} }
if (IS_ZEBRA_DEBUG_KERNEL) if (IS_ZEBRA_DEBUG_KERNEL)

View File

@ -26,13 +26,16 @@
#include "zebra/rt.h" #include "zebra/rt.h"
#include "zebra/rt_netlink.h" #include "zebra/rt_netlink.h"
#include "zebra/zebra_mpls.h" #include "zebra/zebra_mpls.h"
#include "zebra/kernel_netlink.h"
/* /*
* LSP forwarding update using dataplane context information. * LSP forwarding update using dataplane context information.
*/ */
enum zebra_dplane_result kernel_lsp_update(struct zebra_dplane_ctx *ctx) enum zebra_dplane_result kernel_lsp_update(struct zebra_dplane_ctx *ctx)
{ {
int cmd, ret = -1; uint8_t nl_pkt[NL_PKT_BUF_SIZE];
ssize_t ret = -1;
int cmd;
/* Call to netlink layer based on type of update */ /* Call to netlink layer based on type of update */
if (dplane_ctx_get_op(ctx) == DPLANE_OP_LSP_DELETE) { if (dplane_ctx_get_op(ctx) == DPLANE_OP_LSP_DELETE) {
@ -53,7 +56,13 @@ enum zebra_dplane_result kernel_lsp_update(struct zebra_dplane_ctx *ctx)
/* Invalid op? */ /* Invalid op? */
goto done; goto done;
ret = netlink_mpls_multipath(cmd, ctx); ret = netlink_mpls_multipath_msg_encode(cmd, ctx, nl_pkt,
sizeof(nl_pkt));
if (ret <= 0)
return ZEBRA_DPLANE_REQUEST_FAILURE;
ret = netlink_talk_info(netlink_talk_filter, (struct nlmsghdr *)nl_pkt,
dplane_ctx_get_ns(ctx), 0);
done: done: