From 2334e973559e119fa4161047035f03ad97a8676a Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Sat, 21 Apr 2007 20:12:43 +0900 Subject: [PATCH] [IPV6] SNMP: Avoid unaligned accesses. Because stats pointer may not be aligned for u64, use memcpy to fill u64 values. Issue reported by David Miller . Signed-off-by: YOSHIFUJI Hideaki --- include/net/ipv6.h | 2 +- net/ipv6/proc.c | 22 ++++++++++++++++------ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 4408def379bf..1df360eb0791 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -172,7 +172,7 @@ int snmp6_alloc_dev(struct inet6_dev *idev); int snmp6_free_dev(struct inet6_dev *idev); int snmp6_mib_init(void *ptr[2], size_t mibsize, size_t mibalign); void snmp6_mib_free(void *ptr[2]); -void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, int bytes); +void snmp6_fill_stats(void *stats, struct inet6_dev *idev, int attrtype, int bytes); struct ip6_ra_chain { diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index c847cef626a8..aba94316b773 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c @@ -210,20 +210,30 @@ static const struct file_operations snmp6_seq_fops = { }; #endif /* CONFIG_PROC_FS */ +/* + * Stats may not be aligned for u64, so use memcpy to avoid + * unaligned accesses. + */ +static inline void __set_u64(void *p, u64 v) +{ + memcpy(p, &v, sizeof(u64)); +} + static inline void -__snmp6_fill_stats(u64 *stats, void **mib, int items, int bytes) +__snmp6_fill_stats(void *stats, void **mib, int items, int bytes) { int i; + u8 *p = stats; int pad = bytes - sizeof(u64) * items; BUG_ON(pad < 0); - stats[0] = items; - for (i = 1; i < items; i++) - stats[i] = (u64)fold_field(mib, i); - memset(&stats[items], 0, pad); + __set_u64(p, items); + for (i = 1, p += sizeof(u64); i < items; i++, p += sizeof(u64)) + __set_u64(p, fold_field(mib, i)); + memset(p, 0, pad); } void -snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, int bytes) +snmp6_fill_stats(void *stats, struct inet6_dev *idev, int attrtype, int bytes) { switch(attrtype) { case IFLA_INET6_STATS: -- 2.39.5