diff options
author | Bryan Phillippe <bp@darkforest.org> | 2011-08-31 11:11:59 -0700 |
---|---|---|
committer | Thomas Graf <tgraf@lsx.localdomain> | 2011-09-01 08:39:48 +0200 |
commit | f1d9e9d52d7751a09a744f3ad83613c6b025c230 (patch) | |
tree | 866de722f2ab18f876acb6b2a3ed357464529288 | |
parent | 7adaad784f02dc3cab0ad97a284edb0eaf2f0663 (diff) | |
download | libnl-f1d9e9d52d7751a09a744f3ad83613c6b025c230.tar.gz |
64bit unaligned access
This patch fixes an unaligned access for IPv6. On systems with strict alignment requirements, the unaligned access will either result in garbage data or a crash.
-rw-r--r-- | lib/route/link/inet6.c | 24 |
1 files changed, 17 insertions, 7 deletions
diff --git a/lib/route/link/inet6.c b/lib/route/link/inet6.c index 399dd4b..5f75342 100644 --- a/lib/route/link/inet6.c +++ b/lib/route/link/inet6.c @@ -71,23 +71,33 @@ static int inet6_parse_protinfo(struct rtnl_link *link, struct nlattr *attr, if (tb[IFLA_INET6_CONF]) nla_memcpy(&i6->i6_conf, tb[IFLA_INET6_CONF], sizeof(i6->i6_conf)); - + + /* + * Due to 32bit data alignment, these addresses must be copied to an + * aligned location prior to access. + */ if (tb[IFLA_INET6_STATS]) { - uint64_t *cnt = nla_data(tb[IFLA_INET6_STATS]); + unsigned char *cnt = nla_data(tb[IFLA_INET6_STATS]); + uint64_t stat; int i; - for (i = 1; i < __IPSTATS_MIB_MAX; i++) + for (i = 1; i < __IPSTATS_MIB_MAX; i++) { + memcpy(&stat, &cnt[i * sizeof(stat)], sizeof(stat)); rtnl_link_set_stat(link, RTNL_LINK_IP6_INPKTS + i - 1, - cnt[i]); + stat); + } } if (tb[IFLA_INET6_ICMP6STATS]) { - uint64_t *cnt = nla_data(tb[IFLA_INET6_ICMP6STATS]); + unsigned char *cnt = nla_data(tb[IFLA_INET6_ICMP6STATS]); + uint64_t stat; int i; - for (i = 1; i < __ICMP6_MIB_MAX; i++) + for (i = 1; i < __ICMP6_MIB_MAX; i++) { + memcpy(&stat, &cnt[i * sizeof(stat)], sizeof(stat)); rtnl_link_set_stat(link, RTNL_LINK_ICMP6_INMSGS + i - 1, - cnt[i]); + stat); + } } return 0; |