]> granicus.if.org Git - libnl/commitdiff
link: fix unaligned access to 64bit link stats
authorBryan Phillippe <bp@darkforest.org>
Thu, 11 Aug 2011 18:43:46 +0000 (11:43 -0700)
committerThomas Graf <tgraf@suug.ch>
Fri, 12 Aug 2011 08:03:04 +0000 (10:03 +0200)
lib/route/link.c

index 4932722111ff739a81f1e397b2afb9355d66f8b2..3e070e56b7ba879c1b678a76babddbfe88572878 100644 (file)
@@ -341,34 +341,44 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
        }
 
        if (tb[IFLA_STATS64]) {
-               struct rtnl_link_stats64 *st = nla_data(tb[IFLA_STATS64]);
+               /*
+                * This structure contains 64bit parameters, and per the
+                * documentation in lib/attr.c, must not be accessed
+                * directly (because of alignment to 4 instead of 8).
+                * Therefore, copy the data to the stack and access it from
+                * there, where it will be aligned to 8.
+                */
+               struct rtnl_link_stats64 st;
+
+               nla_memcpy(&st, tb[IFLA_STATS64], 
+                          sizeof(struct rtnl_link_stats64));
                
-               link->l_stats[RTNL_LINK_RX_PACKETS]     = st->rx_packets;
-               link->l_stats[RTNL_LINK_TX_PACKETS]     = st->tx_packets;
-               link->l_stats[RTNL_LINK_RX_BYTES]       = st->rx_bytes;
-               link->l_stats[RTNL_LINK_TX_BYTES]       = st->tx_bytes;
-               link->l_stats[RTNL_LINK_RX_ERRORS]      = st->rx_errors;
-               link->l_stats[RTNL_LINK_TX_ERRORS]      = st->tx_errors;
-               link->l_stats[RTNL_LINK_RX_DROPPED]     = st->rx_dropped;
-               link->l_stats[RTNL_LINK_TX_DROPPED]     = st->tx_dropped;
-               link->l_stats[RTNL_LINK_MULTICAST]      = st->multicast;
-               link->l_stats[RTNL_LINK_COLLISIONS]     = st->collisions;
-
-               link->l_stats[RTNL_LINK_RX_LEN_ERR]     = st->rx_length_errors;
-               link->l_stats[RTNL_LINK_RX_OVER_ERR]    = st->rx_over_errors;
-               link->l_stats[RTNL_LINK_RX_CRC_ERR]     = st->rx_crc_errors;
-               link->l_stats[RTNL_LINK_RX_FRAME_ERR]   = st->rx_frame_errors;
-               link->l_stats[RTNL_LINK_RX_FIFO_ERR]    = st->rx_fifo_errors;
-               link->l_stats[RTNL_LINK_RX_MISSED_ERR]  = st->rx_missed_errors;
-
-               link->l_stats[RTNL_LINK_TX_ABORT_ERR]   = st->tx_aborted_errors;
-               link->l_stats[RTNL_LINK_TX_CARRIER_ERR] = st->tx_carrier_errors;
-               link->l_stats[RTNL_LINK_TX_FIFO_ERR]    = st->tx_fifo_errors;
-               link->l_stats[RTNL_LINK_TX_HBEAT_ERR]   = st->tx_heartbeat_errors;
-               link->l_stats[RTNL_LINK_TX_WIN_ERR]     = st->tx_window_errors;
-
-               link->l_stats[RTNL_LINK_RX_COMPRESSED]  = st->rx_compressed;
-               link->l_stats[RTNL_LINK_TX_COMPRESSED]  = st->tx_compressed;
+               link->l_stats[RTNL_LINK_RX_PACKETS]     = st.rx_packets;
+               link->l_stats[RTNL_LINK_TX_PACKETS]     = st.tx_packets;
+               link->l_stats[RTNL_LINK_RX_BYTES]       = st.rx_bytes;
+               link->l_stats[RTNL_LINK_TX_BYTES]       = st.tx_bytes;
+               link->l_stats[RTNL_LINK_RX_ERRORS]      = st.rx_errors;
+               link->l_stats[RTNL_LINK_TX_ERRORS]      = st.tx_errors;
+               link->l_stats[RTNL_LINK_RX_DROPPED]     = st.rx_dropped;
+               link->l_stats[RTNL_LINK_TX_DROPPED]     = st.tx_dropped;
+               link->l_stats[RTNL_LINK_MULTICAST]      = st.multicast;
+               link->l_stats[RTNL_LINK_COLLISIONS]     = st.collisions;
+
+               link->l_stats[RTNL_LINK_RX_LEN_ERR]     = st.rx_length_errors;
+               link->l_stats[RTNL_LINK_RX_OVER_ERR]    = st.rx_over_errors;
+               link->l_stats[RTNL_LINK_RX_CRC_ERR]     = st.rx_crc_errors;
+               link->l_stats[RTNL_LINK_RX_FRAME_ERR]   = st.rx_frame_errors;
+               link->l_stats[RTNL_LINK_RX_FIFO_ERR]    = st.rx_fifo_errors;
+               link->l_stats[RTNL_LINK_RX_MISSED_ERR]  = st.rx_missed_errors;
+
+               link->l_stats[RTNL_LINK_TX_ABORT_ERR]   = st.tx_aborted_errors;
+               link->l_stats[RTNL_LINK_TX_CARRIER_ERR] = st.tx_carrier_errors;
+               link->l_stats[RTNL_LINK_TX_FIFO_ERR]    = st.tx_fifo_errors;
+               link->l_stats[RTNL_LINK_TX_HBEAT_ERR]   = st.tx_heartbeat_errors;
+               link->l_stats[RTNL_LINK_TX_WIN_ERR]     = st.tx_window_errors;
+
+               link->l_stats[RTNL_LINK_RX_COMPRESSED]  = st.rx_compressed;
+               link->l_stats[RTNL_LINK_TX_COMPRESSED]  = st.tx_compressed;
 
                link->ce_mask |= LINK_ATTR_STATS;
        }