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 a3654d929814..b9d1baaa8bdc 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -3344,19 +3344,25 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv | |||
3344 | 3344 | ||
3345 | if (optlen != sizeof(val)) | 3345 | if (optlen != sizeof(val)) |
3346 | return -EINVAL; | 3346 | return -EINVAL; |
3347 | if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) | ||
3348 | return -EBUSY; | ||
3349 | if (copy_from_user(&val, optval, sizeof(val))) | 3347 | if (copy_from_user(&val, optval, sizeof(val))) |
3350 | return -EFAULT; | 3348 | return -EFAULT; |
3351 | switch (val) { | 3349 | switch (val) { |
3352 | case TPACKET_V1: | 3350 | case TPACKET_V1: |
3353 | case TPACKET_V2: | 3351 | case TPACKET_V2: |
3354 | case TPACKET_V3: | 3352 | case TPACKET_V3: |
3355 | po->tp_version = val; | 3353 | break; |
3356 | return 0; | ||
3357 | default: | 3354 | default: |
3358 | return -EINVAL; | 3355 | return -EINVAL; |
3359 | } | 3356 | } |
3357 | lock_sock(sk); | ||
3358 | if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) { | ||
3359 | ret = -EBUSY; | ||
3360 | } else { | ||
3361 | po->tp_version = val; | ||
3362 | ret = 0; | ||
3363 | } | ||
3364 | release_sock(sk); | ||
3365 | return ret; | ||
3360 | } | 3366 | } |
3361 | case PACKET_RESERVE: | 3367 | case PACKET_RESERVE: |
3362 | { | 3368 | { |
@@ -3819,6 +3825,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, | |||
3819 | /* Added to avoid minimal code churn */ | 3825 | /* Added to avoid minimal code churn */ |
3820 | struct tpacket_req *req = &req_u->req; | 3826 | struct tpacket_req *req = &req_u->req; |
3821 | 3827 | ||
3828 | lock_sock(sk); | ||
3822 | /* Opening a Tx-ring is NOT supported in TPACKET_V3 */ | 3829 | /* Opening a Tx-ring is NOT supported in TPACKET_V3 */ |
3823 | if (!closing && tx_ring && (po->tp_version > TPACKET_V2)) { | 3830 | if (!closing && tx_ring && (po->tp_version > TPACKET_V2)) { |
3824 | WARN(1, "Tx-ring is not supported.\n"); | 3831 | WARN(1, "Tx-ring is not supported.\n"); |
@@ -3900,7 +3907,6 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, | |||
3900 | goto out; | 3907 | goto out; |
3901 | } | 3908 | } |
3902 | 3909 | ||
3903 | lock_sock(sk); | ||
3904 | 3910 | ||
3905 | /* Detach socket from network */ | 3911 | /* Detach socket from network */ |
3906 | spin_lock(&po->bind_lock); | 3912 | spin_lock(&po->bind_lock); |
@@ -3949,11 +3955,11 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, | |||
3949 | if (!tx_ring) | 3955 | if (!tx_ring) |
3950 | prb_shutdown_retire_blk_timer(po, tx_ring, rb_queue); | 3956 | prb_shutdown_retire_blk_timer(po, tx_ring, rb_queue); |
3951 | } | 3957 | } |
3952 | release_sock(sk); | ||
3953 | 3958 | ||
3954 | if (pg_vec) | 3959 | if (pg_vec) |
3955 | free_pg_vec(pg_vec, order, req->tp_block_nr); | 3960 | free_pg_vec(pg_vec, order, req->tp_block_nr); |
3956 | out: | 3961 | out: |
3962 | release_sock(sk); | ||
3957 | return err; | 3963 | return err; |
3958 | } | 3964 | } |
3959 | 3965 | ||