diff options
Diffstat (limited to 'net/packet/af_packet.c')
-rw-r--r-- | net/packet/af_packet.c | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index fab9bbfdead5..89f2e8c1f4dc 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -3593,19 +3593,25 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv | |||
3593 | 3593 | ||
3594 | if (optlen != sizeof(val)) | 3594 | if (optlen != sizeof(val)) |
3595 | return -EINVAL; | 3595 | return -EINVAL; |
3596 | if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) | ||
3597 | return -EBUSY; | ||
3598 | if (copy_from_user(&val, optval, sizeof(val))) | 3596 | if (copy_from_user(&val, optval, sizeof(val))) |
3599 | return -EFAULT; | 3597 | return -EFAULT; |
3600 | switch (val) { | 3598 | switch (val) { |
3601 | case TPACKET_V1: | 3599 | case TPACKET_V1: |
3602 | case TPACKET_V2: | 3600 | case TPACKET_V2: |
3603 | case TPACKET_V3: | 3601 | case TPACKET_V3: |
3604 | po->tp_version = val; | 3602 | break; |
3605 | return 0; | ||
3606 | default: | 3603 | default: |
3607 | return -EINVAL; | 3604 | return -EINVAL; |
3608 | } | 3605 | } |
3606 | lock_sock(sk); | ||
3607 | if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) { | ||
3608 | ret = -EBUSY; | ||
3609 | } else { | ||
3610 | po->tp_version = val; | ||
3611 | ret = 0; | ||
3612 | } | ||
3613 | release_sock(sk); | ||
3614 | return ret; | ||
3609 | } | 3615 | } |
3610 | case PACKET_RESERVE: | 3616 | case PACKET_RESERVE: |
3611 | { | 3617 | { |
@@ -4109,6 +4115,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, | |||
4109 | /* Added to avoid minimal code churn */ | 4115 | /* Added to avoid minimal code churn */ |
4110 | struct tpacket_req *req = &req_u->req; | 4116 | struct tpacket_req *req = &req_u->req; |
4111 | 4117 | ||
4118 | lock_sock(sk); | ||
4112 | /* Opening a Tx-ring is NOT supported in TPACKET_V3 */ | 4119 | /* Opening a Tx-ring is NOT supported in TPACKET_V3 */ |
4113 | if (!closing && tx_ring && (po->tp_version > TPACKET_V2)) { | 4120 | if (!closing && tx_ring && (po->tp_version > TPACKET_V2)) { |
4114 | net_warn_ratelimited("Tx-ring is not supported.\n"); | 4121 | net_warn_ratelimited("Tx-ring is not supported.\n"); |
@@ -4190,7 +4197,6 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, | |||
4190 | goto out; | 4197 | goto out; |
4191 | } | 4198 | } |
4192 | 4199 | ||
4193 | lock_sock(sk); | ||
4194 | 4200 | ||
4195 | /* Detach socket from network */ | 4201 | /* Detach socket from network */ |
4196 | spin_lock(&po->bind_lock); | 4202 | spin_lock(&po->bind_lock); |
@@ -4239,11 +4245,11 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, | |||
4239 | if (!tx_ring) | 4245 | if (!tx_ring) |
4240 | prb_shutdown_retire_blk_timer(po, rb_queue); | 4246 | prb_shutdown_retire_blk_timer(po, rb_queue); |
4241 | } | 4247 | } |
4242 | release_sock(sk); | ||
4243 | 4248 | ||
4244 | if (pg_vec) | 4249 | if (pg_vec) |
4245 | free_pg_vec(pg_vec, order, req->tp_block_nr); | 4250 | free_pg_vec(pg_vec, order, req->tp_block_nr); |
4246 | out: | 4251 | out: |
4252 | release_sock(sk); | ||
4247 | return err; | 4253 | return err; |
4248 | } | 4254 | } |
4249 | 4255 | ||