diff options
-rw-r--r-- | include/net/ipv6.h | 2 | ||||
-rw-r--r-- | net/ipv6/proc.c | 26 |
2 files changed, 11 insertions, 17 deletions
diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 1df360eb0791..4408def379bf 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h | |||
@@ -172,7 +172,7 @@ int snmp6_alloc_dev(struct inet6_dev *idev); | |||
172 | int snmp6_free_dev(struct inet6_dev *idev); | 172 | int snmp6_free_dev(struct inet6_dev *idev); |
173 | int snmp6_mib_init(void *ptr[2], size_t mibsize, size_t mibalign); | 173 | int snmp6_mib_init(void *ptr[2], size_t mibsize, size_t mibalign); |
174 | void snmp6_mib_free(void *ptr[2]); | 174 | void snmp6_mib_free(void *ptr[2]); |
175 | void snmp6_fill_stats(void *stats, struct inet6_dev *idev, int attrtype, int bytes); | 175 | void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, int bytes); |
176 | 176 | ||
177 | struct ip6_ra_chain | 177 | struct ip6_ra_chain |
178 | { | 178 | { |
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index aba94316b773..7a00bedb6b93 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/proc_fs.h> | 23 | #include <linux/proc_fs.h> |
24 | #include <linux/seq_file.h> | 24 | #include <linux/seq_file.h> |
25 | #include <linux/stddef.h> | 25 | #include <linux/stddef.h> |
26 | #include <asm/unaligned.h> | ||
26 | #include <net/sock.h> | 27 | #include <net/sock.h> |
27 | #include <net/tcp.h> | 28 | #include <net/tcp.h> |
28 | #include <net/transp_v6.h> | 29 | #include <net/transp_v6.h> |
@@ -210,30 +211,23 @@ static const struct file_operations snmp6_seq_fops = { | |||
210 | }; | 211 | }; |
211 | #endif /* CONFIG_PROC_FS */ | 212 | #endif /* CONFIG_PROC_FS */ |
212 | 213 | ||
213 | /* | ||
214 | * Stats may not be aligned for u64, so use memcpy to avoid | ||
215 | * unaligned accesses. | ||
216 | */ | ||
217 | static inline void __set_u64(void *p, u64 v) | ||
218 | { | ||
219 | memcpy(p, &v, sizeof(u64)); | ||
220 | } | ||
221 | |||
222 | static inline void | 214 | static inline void |
223 | __snmp6_fill_stats(void *stats, void **mib, int items, int bytes) | 215 | __snmp6_fill_stats(u64 *stats, void **mib, int items, int bytes) |
224 | { | 216 | { |
225 | int i; | 217 | int i; |
226 | u8 *p = stats; | ||
227 | int pad = bytes - sizeof(u64) * items; | 218 | int pad = bytes - sizeof(u64) * items; |
228 | BUG_ON(pad < 0); | 219 | BUG_ON(pad < 0); |
229 | __set_u64(p, items); | 220 | |
230 | for (i = 1, p += sizeof(u64); i < items; i++, p += sizeof(u64)) | 221 | /* Use put_unaligned() because stats may not be aligned for u64. */ |
231 | __set_u64(p, fold_field(mib, i)); | 222 | put_unaligned(items, &stats[0]); |
232 | memset(p, 0, pad); | 223 | for (i = 1; i < items; i++) |
224 | put_unaligned(fold_field(mib, i), &stats[i]); | ||
225 | |||
226 | memset(&stats[items], 0, pad); | ||
233 | } | 227 | } |
234 | 228 | ||
235 | void | 229 | void |
236 | snmp6_fill_stats(void *stats, struct inet6_dev *idev, int attrtype, int bytes) | 230 | snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, int bytes) |
237 | { | 231 | { |
238 | switch(attrtype) { | 232 | switch(attrtype) { |
239 | case IFLA_INET6_STATS: | 233 | case IFLA_INET6_STATS: |