peer_pid checking in ip_queue
Subsystems (2)
PATCH 1/1 peer_pid checking in ip_queue
Hi,
I patched ip_queue.c to modify the default behaviour if peer_pid is 0. In this case, there's no program in user space to receive the skbuff via netlink, but ip_queue will allocate space for the skbuff and after checking if peer_pid is 0, it will destroy this skbuff allocated. Am I missing anything?
best regards,
Pablo
P.S: BTW, Harald, I noticed that I had some problems with my smtp server and some email got lost, I sent you an email with a "digest" of all my recent patches, did you receive it? If not, please let me know.
net/ipv4/netfilter/ip_queue.c +3 -6
@@ -277,6 +277,9 @@struct sk_buff *nskb;struct ipq_queue_entry *entry; +if (!peer_pid) +return -EINVAL ; +if (copy_mode ==IPQ_COPY_NONE )return -EAGAIN ;
@@ -303,9 +306,6 @@write_lock_bh (&queue_lock); -if (!peer_pid) - goto err_out_free_nskb; -/* netlink_unicast will either free the nskb or attach it to a socket */ status =netlink_unicast (ipqnl, nskb, peer_pid,MSG_DONTWAIT );if (status <0 )
@@ -318,9 +318,6 @@write_unlock_bh (&queue_lock);return status; -err_out_free_nskb: -kfree_skb (nskb); - err_out_unlock:write_unlock_bh (&queue_lock);
Hi Pablo,
Quoted 3 lines · Pablo Neira
Hi,
I patched
ip_queue.cto modify the default behaviour ifpeer_pidis 0. In this case, there's no program in user space to receive the skbuff via netlink, butip_queuewill allocate space for the skbuff and after checking ifpeer_pidis 0, it will destroy this skbuff allocated. Am I missing anything?
peer_pid is protected by queue_lock, you move it out of the locked section. This leads to a small race which can cause message loss. Not sure if it's bad though as netlink is unreliable itself.
Regards
Patrick
Quoted 41 lines
best regards,
Pablo
P.S: BTW, Harald, I noticed that I had some problems with my smtp server and some email got lost, I sent you an email with a "digest" of all my recent patches, did you receive it? If not, please let me know.------------------------------------------------------------------------
net/ipv4/netfilter/ip_queue.c +3
-6@@ -277,6 +277,9 @@struct sk_buff *nskb;struct ipq_queue_entry *entry; +if (!peer_pid) +return -EINVAL ; +if (copy_mode ==IPQ_COPY_NONE )return -EAGAIN ;@@ -303,9 +306,6 @@write_lock_bh (&queue_lock); -if (!peer_pid) - goto err_out_free_nskb; -/* netlink_unicast will either free the nskb or attach it to a socket */ status =netlink_unicast (ipqnl, nskb, peer_pid,MSG_DONTWAIT );if (status <0 )@@ -318,9 +318,6 @@write_unlock_bh (&queue_lock);return status; -err_out_free_nskb: -kfree_skb (nskb); - err_out_unlock:write_unlock_bh (&queue_lock);
Hi Patrick,
Quoted 2 lines · Patrick McHardy
peer_pidis protected byqueue_lock, you move it out of the locked
section. This leads to a small race which can cause message loss. Not sure if it's bad though as netlink is unreliable itself.
yes it's true, well if i'm not wrong, this small race could happen for first packets which are going to be enqueued, is it?.
For example, two packets arrive almost at the same time, ip_queue allocates space for both new entries to be enqueued, first packet is not enqueued because peer_pid is 0 but, in that moment, the user space program binds to ip_queue's netlink sockets, but entry for second packet is already created and peer_pid is not 0 anymore, so this packet is enqueue. With my patch, both packets will be lost, with current implementation one is lost and the other one is enqueued.
By other hand, I think that if user programs hungs or dies, we stress the kernel allocating and releasing memory all the time. So, my question is, is really a problem losing these packets?
thanks for the feedback,
Pablo
Quoted 10 lines · Pablo Neira
Hi Patrick,
Quoted 2 lines · Patrick McHardy
peer_pidis protected byqueue_lock, you move it out of the locked
section. This leads to a small race which can cause message loss. Not sure if it's bad though as netlink is unreliable itself.yes it's true, well if i'm not wrong, this small race could happen for first packets which are going to be enqueued, is it?.
It can happen if peer_pid is checked outside the locked section on one CPU and changed on another at the same time. I don't consider it important, as the exact point in time at which the first packet will be received is non-deterministic for userspace anyway. But we can probably also do it without a race-conditions, ipq_build_packet_message read_locks queue_lock, directly after that it is write_locked by ipq_enqueue_packet. As multiple threads will queue at the write_lock anyway it seems we can just replace it by a spin_lock and lock the entire section. But let me think some more about it ..
Regards
Patrick
Quoted 9 lines
For example, two packets arrive almost at the same time,
ip_queueallocates space for both new entries to be enqueued, first packet is not enqueued becausepeer_pidis 0 but, in that moment, the user space program binds to ip_queue's netlink sockets, but entry for second packet is already created andpeer_pidis not 0 anymore, so this packet is enqueue. With my patch, both packets will be lost, with current implementation one is lost and the other one is enqueued.By other hand, I think that if user programs hungs or dies, we stress the kernel allocating and releasing memory all the time. So, my question is, is really a problem losing these packets?
thanks for the feedback,
Pablo
Quoted 4 lines · Patrick McHardy
It can happen if
peer_pidis checked outside the locked section on one CPU and changed on another at the same time. I don't consider it important, as the exact point in time at which the first packet will be received is non-deterministic for userspace anyway.
What about when the user program closes? How bad it is to have read the pid and then there is no userspace there?
Regards
Henrik
Hi,
Quoted 3 lines · Henrik Nordstrom
What about when the user program closes? How bad it is to have read the pid and then there is no userspace there?
As Patrick pointed out before, netlink is not reliable, so it will drop the packets sent to an user space which doesn't exist without notification. But if the user space program closes properly, peer_pid will be reset. Have a look at ipq_rcv_nl_event and netlink_release. AFAIK, if the user space program hangs or dies, kernel will release the socket later, so for quite some time netlink will drop packets. Am I right?
regards,
Pablo
Quoted 8 lines · Pablo Neira
Hi,
Quoted 3 lines · Henrik Nordstrom
What about when the user program closes? How bad it is to have read the pid and then there is no userspace there?
As Patrick pointed out before, netlink is not reliable, so it will drop the packets sent to an user space which doesn't exist without notification. But if the user space program closes properly,
peer_pidwill be reset. Have a look atipq_rcv_nl_eventandnetlink_release. AFAIK, if the user space program hangs or dies, kernel will release the socket later, so for quite some time netlink will drop packets. Am I right?
Well, if it hangs the socket buffer will fill over time until it reaches its limits, but there is nothing we can do. But we can do something for the almost-known-no-listener case :)
Regards
Patrick
Quoted 4 lines
regards,
Pablo
Quoted 10 lines · Henrik Nordstrom
Quoted 4 lines · Patrick McHardy
It can happen if
peer_pidis checked outside the locked section on one CPU and changed on another at the same time. I don't consider it important, as the exact point in time at which the first packet will be received is non-deterministic for userspace anyway.What about when the user program closes? How bad it is to have read the pid and then there is no userspace there?
It's no problem, netlink_unicast checks for existance of the socket, which will be gone with the reader. If no socket is found it returns -ECONNREFUSED.
Regards
Patrick
Quoted 4 lines
Regards
Henrik
Quoted 9 lines · Patrick McHardy
It can happen if
peer_pidis checked outside the locked section on one CPU and changed on another at the same time. I don't consider it important, as the exact point in time at which the first packet will be received is non-deterministic for userspace anyway. But we can probably also do it without a race-conditions,ipq_build_packet_messageread_locksqueue_lock, directly after that it iswrite_lockedbyipq_enqueue_packet. As multiple threads will queue at thewrite_lockanyway it seems we can just replace it by aspin_lockand lock the entire section. But let me think some more about it ..
any results so far? If not, I will just postpone this minor issue.
Quoted 2 lines
Regards
Patrick
Signature · 5 lines
- Harald Welte <[email protected]> http://www.netfilter.org/ ============================================================================ "Fragmentation is like classful addressing -- an interesting early architectural error that shows how much experimentation was going on while IP was being designed." -- Paul Vixie
Quoted 13 lines · Harald Welte
Quoted 9 lines · Patrick McHardy
It can happen if
peer_pidis checked outside the locked section on one CPU and changed on another at the same time. I don't consider it important, as the exact point in time at which the first packet will be received is non-deterministic for userspace anyway. But we can probably also do it without a race-conditions,ipq_build_packet_messageread_locksqueue_lock, directly after that it iswrite_lockedbyipq_enqueue_packet. As multiple threads will queue at thewrite_lockanyway it seems we can just replace it by aspin_lockand lock the entire section. But let me think some more about it ..
Quoted 1 line
any results so far? If not, I will just postpone this minor issue.
Not yet, but I will get to it next week.
Quoted 7 lines
Quoted 4 lines
Regards
Patrick
Quoted 7 lines · Pablo Neira
Hi,
I patched
ip_queue.cto modify the default behaviour ifpeer_pidis 0. In this case, there's no program in user space to receive the skbuff via netlink, butip_queuewill allocate space for the skbuff and after checking ifpeer_pidis 0, it will destroy this skbuff allocated. Am I missing anything?
seems fine to me, I'll put this in my list of pending patches
Quoted 1 line
Pablo
Signature · 5 lines
- Harald Welte <[email protected]> http://www.netfilter.org/ ============================================================================ "Fragmentation is like classful addressing -- an interesting early architectural error that shows how much experimentation was going on while IP was being designed." -- Paul Vixie