Re: [bpf-next PATCH 05/16] bpf: create tcp_bpf_ulp allowing BPF to monitor socket TX/RX data
flat view
From: John Fastabend <john.fastabend@gmail.com>
Date: 2018-03-05 22:53:22
On 03/05/2018 01:40 PM, David Miller wrote:
From: John Fastabend <john.fastabend@gmail.com> Date: Mon, 05 Mar 2018 11:51:22 -0800quoted
BPF_PROG_TYPE_SK_MSG supports only two return codes SK_PASS and SK_DROP. Returning SK_DROP free's the copied data in the sendmsg case and in the sendpage case leaves the data untouched. Both cases return -EACESS to the user. Returning SK_PASS will allow the msg to be sent. In the sendmsg case data is copied into kernel space buffers before running the BPF program. In the sendpage case data is never copied. The implication being users may change data after BPF programs run in the sendpage case. (A flag will be added to always copy shortly if the copy must always be performed).I don't see how the sendpage case can be right. The user can asynchronously change the page contents whenever they want, and if the BPF program runs on the old contents then the verdict is not for what actually ends up being sent on the socket> There is really no way to cheaply freeze the page contents other than to make a copy.
Right, so we have two cases. The first is we are not trying to protect against malicious users but merely monitor the connection. This case is primarily for L7 statistics, number of bytes sent to URL foo for example. If users are changing data (for a real program not something malicious) mid sendfile() this is really buggy anyways. There is no way to know when/if the data is being copied lower in the stack. Even worse would be if it changed a msg header, such as the http or kafka header, then I don't see how such a program would work reliable at all. Some of my L7 monitoring BPF programs fall into this category. The second case is we want to implement a strict policy. For example never allow user 'bar' to send to URL foo. In the current patches this would be vulnerable to async data changes. I was planning to have a follow up patch to this series to add a flag "always copy" which handles the asynchronous case by always copying the data if the BPF policy can not tolerate user changing data mid-send. Another class of BPF programs I have fall into this bucket. However, the performance cost of copy can be significant so allowing the BPF policy to decide which mode they require seems best to me. I decided to make the default no-copy to mirror the existing sendpage() semantics and then to add the flag later. The flag support is not in this series simply because I wanted to get the base support in first. Make sense? The default could be to copy sendpage data and then a flag could be made to allow it to skip the copy. But I prefer the current defaults. Thanks, John