The append_stats_reply() function can modify its pointer argument, but
append_port_stat() was failing to propagate this change back to its own
caller. So when append_stats_reply() did in fact modify it (which happens
when the 64 kB maximum OpenFlow message length was exceeded), the
handle_port_stats_request() function would then access freed memory on the
next call to append_port_stat().
Bug #2714.
Reported-by: Ram Jothikumar <rjothikumar@nicira.com>
Debugging help by Justin Pettit <jpettit@nicira.com>
static void
append_port_stat(struct ofport *port, uint16_t port_no, struct ofconn *ofconn,
static void
append_port_stat(struct ofport *port, uint16_t port_no, struct ofconn *ofconn,
{
struct netdev_stats stats;
struct ofp_port_stats *ops;
{
struct netdev_stats stats;
struct ofp_port_stats *ops;
* netdev_get_stats() will log errors. */
netdev_get_stats(port->netdev, &stats);
* netdev_get_stats() will log errors. */
netdev_get_stats(port->netdev, &stats);
- ops = append_stats_reply(sizeof *ops, ofconn, &msg);
+ ops = append_stats_reply(sizeof *ops, ofconn, msgp);
ops->port_no = htons(odp_port_to_ofp_port(port_no));
memset(ops->pad, 0, sizeof ops->pad);
ops->rx_packets = htonll(stats.rx_packets);
ops->port_no = htons(odp_port_to_ofp_port(port_no));
memset(ops->pad, 0, sizeof ops->pad);
ops->rx_packets = htonll(stats.rx_packets);
port = port_array_get(&p->ports,
ofp_port_to_odp_port(ntohs(psr->port_no)));
if (port) {
port = port_array_get(&p->ports,
ofp_port_to_odp_port(ntohs(psr->port_no)));
if (port) {
- append_port_stat(port, ntohs(psr->port_no), ofconn, msg);
+ append_port_stat(port, ntohs(psr->port_no), ofconn, &msg);
}
} else {
PORT_ARRAY_FOR_EACH (port, &p->ports, port_no) {
}
} else {
PORT_ARRAY_FOR_EACH (port, &p->ports, port_no) {
- append_port_stat(port, port_no, ofconn, msg);
+ append_port_stat(port, port_no, ofconn, &msg);