aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>2007-04-21 07:12:43 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-04-26 01:29:35 -0400
commit2334e973559e119fa4161047035f03ad97a8676a (patch)
tree0c01f78dac17f031ed39e262eea042c4381f9dd7
parent9e412ba7632f71259a53085665d4983b78257b7c (diff)
[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 <davem@davemloft.net>. Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
-rw-r--r--include/net/ipv6.h2
-rw-r--r--net/ipv6/proc.c22
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);
172int snmp6_free_dev(struct inet6_dev *idev); 172int snmp6_free_dev(struct inet6_dev *idev);
173int snmp6_mib_init(void *ptr[2], size_t mibsize, size_t mibalign); 173int snmp6_mib_init(void *ptr[2], size_t mibsize, size_t mibalign);
174void snmp6_mib_free(void *ptr[2]); 174void snmp6_mib_free(void *ptr[2]);
175void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, int bytes); 175void snmp6_fill_stats(void *stats, struct inet6_dev *idev, int attrtype, int bytes);
176 176
177struct ip6_ra_chain 177struct ip6_ra_chain
178{ 178{
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 = {
210}; 210};
211#endif /* CONFIG_PROC_FS */ 211#endif /* CONFIG_PROC_FS */
212 212
213/*
214 * Stats may not be aligned for u64, so use memcpy to avoid
215 * unaligned accesses.
216 */
217static inline void __set_u64(void *p, u64 v)
218{
219 memcpy(p, &v, sizeof(u64));
220}
221
213static inline void 222static inline void
214__snmp6_fill_stats(u64 *stats, void **mib, int items, int bytes) 223__snmp6_fill_stats(void *stats, void **mib, int items, int bytes)
215{ 224{
216 int i; 225 int i;
226 u8 *p = stats;
217 int pad = bytes - sizeof(u64) * items; 227 int pad = bytes - sizeof(u64) * items;
218 BUG_ON(pad < 0); 228 BUG_ON(pad < 0);
219 stats[0] = items; 229 __set_u64(p, items);
220 for (i = 1; i < items; i++) 230 for (i = 1, p += sizeof(u64); i < items; i++, p += sizeof(u64))
221 stats[i] = (u64)fold_field(mib, i); 231 __set_u64(p, fold_field(mib, i));
222 memset(&stats[items], 0, pad); 232 memset(p, 0, pad);
223} 233}
224 234
225void 235void
226snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, int bytes) 236snmp6_fill_stats(void *stats, struct inet6_dev *idev, int attrtype, int bytes)
227{ 237{
228 switch(attrtype) { 238 switch(attrtype) {
229 case IFLA_INET6_STATS: 239 case IFLA_INET6_STATS: