diff options
Diffstat (limited to 'net/packet')
-rw-r--r-- | net/packet/af_packet.c | 46 |
1 files changed, 8 insertions, 38 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 40053a08f00..0f661745df0 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -3224,10 +3224,10 @@ static int packet_getsockopt(struct socket *sock, int level, int optname, | |||
3224 | char __user *optval, int __user *optlen) | 3224 | char __user *optval, int __user *optlen) |
3225 | { | 3225 | { |
3226 | int len; | 3226 | int len; |
3227 | int val; | 3227 | int val, lv = sizeof(val); |
3228 | struct sock *sk = sock->sk; | 3228 | struct sock *sk = sock->sk; |
3229 | struct packet_sock *po = pkt_sk(sk); | 3229 | struct packet_sock *po = pkt_sk(sk); |
3230 | void *data; | 3230 | void *data = &val; |
3231 | struct tpacket_stats st; | 3231 | struct tpacket_stats st; |
3232 | union tpacket_stats_u st_u; | 3232 | union tpacket_stats_u st_u; |
3233 | 3233 | ||
@@ -3242,21 +3242,17 @@ static int packet_getsockopt(struct socket *sock, int level, int optname, | |||
3242 | 3242 | ||
3243 | switch (optname) { | 3243 | switch (optname) { |
3244 | case PACKET_STATISTICS: | 3244 | case PACKET_STATISTICS: |
3245 | if (po->tp_version == TPACKET_V3) { | ||
3246 | len = sizeof(struct tpacket_stats_v3); | ||
3247 | } else { | ||
3248 | if (len > sizeof(struct tpacket_stats)) | ||
3249 | len = sizeof(struct tpacket_stats); | ||
3250 | } | ||
3251 | spin_lock_bh(&sk->sk_receive_queue.lock); | 3245 | spin_lock_bh(&sk->sk_receive_queue.lock); |
3252 | if (po->tp_version == TPACKET_V3) { | 3246 | if (po->tp_version == TPACKET_V3) { |
3247 | lv = sizeof(struct tpacket_stats_v3); | ||
3253 | memcpy(&st_u.stats3, &po->stats, | 3248 | memcpy(&st_u.stats3, &po->stats, |
3254 | sizeof(struct tpacket_stats)); | 3249 | sizeof(struct tpacket_stats)); |
3255 | st_u.stats3.tp_freeze_q_cnt = | 3250 | st_u.stats3.tp_freeze_q_cnt = |
3256 | po->stats_u.stats3.tp_freeze_q_cnt; | 3251 | po->stats_u.stats3.tp_freeze_q_cnt; |
3257 | st_u.stats3.tp_packets += po->stats.tp_drops; | 3252 | st_u.stats3.tp_packets += po->stats.tp_drops; |
3258 | data = &st_u.stats3; | 3253 | data = &st_u.stats3; |
3259 | } else { | 3254 | } else { |
3255 | lv = sizeof(struct tpacket_stats); | ||
3260 | st = po->stats; | 3256 | st = po->stats; |
3261 | st.tp_packets += st.tp_drops; | 3257 | st.tp_packets += st.tp_drops; |
3262 | data = &st; | 3258 | data = &st; |
@@ -3265,31 +3261,16 @@ static int packet_getsockopt(struct socket *sock, int level, int optname, | |||
3265 | spin_unlock_bh(&sk->sk_receive_queue.lock); | 3261 | spin_unlock_bh(&sk->sk_receive_queue.lock); |
3266 | break; | 3262 | break; |
3267 | case PACKET_AUXDATA: | 3263 | case PACKET_AUXDATA: |
3268 | if (len > sizeof(int)) | ||
3269 | len = sizeof(int); | ||
3270 | val = po->auxdata; | 3264 | val = po->auxdata; |
3271 | |||
3272 | data = &val; | ||
3273 | break; | 3265 | break; |
3274 | case PACKET_ORIGDEV: | 3266 | case PACKET_ORIGDEV: |
3275 | if (len > sizeof(int)) | ||
3276 | len = sizeof(int); | ||
3277 | val = po->origdev; | 3267 | val = po->origdev; |
3278 | |||
3279 | data = &val; | ||
3280 | break; | 3268 | break; |
3281 | case PACKET_VNET_HDR: | 3269 | case PACKET_VNET_HDR: |
3282 | if (len > sizeof(int)) | ||
3283 | len = sizeof(int); | ||
3284 | val = po->has_vnet_hdr; | 3270 | val = po->has_vnet_hdr; |
3285 | |||
3286 | data = &val; | ||
3287 | break; | 3271 | break; |
3288 | case PACKET_VERSION: | 3272 | case PACKET_VERSION: |
3289 | if (len > sizeof(int)) | ||
3290 | len = sizeof(int); | ||
3291 | val = po->tp_version; | 3273 | val = po->tp_version; |
3292 | data = &val; | ||
3293 | break; | 3274 | break; |
3294 | case PACKET_HDRLEN: | 3275 | case PACKET_HDRLEN: |
3295 | if (len > sizeof(int)) | 3276 | if (len > sizeof(int)) |
@@ -3309,39 +3290,28 @@ static int packet_getsockopt(struct socket *sock, int level, int optname, | |||
3309 | default: | 3290 | default: |
3310 | return -EINVAL; | 3291 | return -EINVAL; |
3311 | } | 3292 | } |
3312 | data = &val; | ||
3313 | break; | 3293 | break; |
3314 | case PACKET_RESERVE: | 3294 | case PACKET_RESERVE: |
3315 | if (len > sizeof(unsigned int)) | ||
3316 | len = sizeof(unsigned int); | ||
3317 | val = po->tp_reserve; | 3295 | val = po->tp_reserve; |
3318 | data = &val; | ||
3319 | break; | 3296 | break; |
3320 | case PACKET_LOSS: | 3297 | case PACKET_LOSS: |
3321 | if (len > sizeof(unsigned int)) | ||
3322 | len = sizeof(unsigned int); | ||
3323 | val = po->tp_loss; | 3298 | val = po->tp_loss; |
3324 | data = &val; | ||
3325 | break; | 3299 | break; |
3326 | case PACKET_TIMESTAMP: | 3300 | case PACKET_TIMESTAMP: |
3327 | if (len > sizeof(int)) | ||
3328 | len = sizeof(int); | ||
3329 | val = po->tp_tstamp; | 3301 | val = po->tp_tstamp; |
3330 | data = &val; | ||
3331 | break; | 3302 | break; |
3332 | case PACKET_FANOUT: | 3303 | case PACKET_FANOUT: |
3333 | if (len > sizeof(int)) | ||
3334 | len = sizeof(int); | ||
3335 | val = (po->fanout ? | 3304 | val = (po->fanout ? |
3336 | ((u32)po->fanout->id | | 3305 | ((u32)po->fanout->id | |
3337 | ((u32)po->fanout->type << 16)) : | 3306 | ((u32)po->fanout->type << 16)) : |
3338 | 0); | 3307 | 0); |
3339 | data = &val; | ||
3340 | break; | 3308 | break; |
3341 | default: | 3309 | default: |
3342 | return -ENOPROTOOPT; | 3310 | return -ENOPROTOOPT; |
3343 | } | 3311 | } |
3344 | 3312 | ||
3313 | if (len > lv) | ||
3314 | len = lv; | ||
3345 | if (put_user(len, optlen)) | 3315 | if (put_user(len, optlen)) |
3346 | return -EFAULT; | 3316 | return -EFAULT; |
3347 | if (copy_to_user(optval, data, len)) | 3317 | if (copy_to_user(optval, data, len)) |