-
Notifications
You must be signed in to change notification settings - Fork 738
fix(driver/bpf): bpf_addr_to_kernel takes an unsigned length (less than BPF_MAX_VAR_SIZE) #1730
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,6 +19,10 @@ or GPL2.txt for full copies of the license. | |
|
||
#include "../ppm_flag_helpers.h" | ||
|
||
// Maximum var size allowed by the verifier | ||
// From BPF_MAX_VAR_SIZ in linux/bpf_verifier.h | ||
#define BPF_MAX_VAR_SIZE 1ULL << 29 | ||
|
||
static __always_inline bool in_port_range(uint16_t port, uint16_t min, uint16_t max) | ||
{ | ||
return port >= min && port <= max; | ||
|
@@ -212,10 +216,10 @@ static __always_inline bool bpf_getsockname(struct socket *sock, | |
return true; | ||
} | ||
|
||
static __always_inline int bpf_addr_to_kernel(void *uaddr, int ulen, | ||
static __always_inline int bpf_addr_to_kernel(void *uaddr, unsigned long ulen, | ||
struct sockaddr *kaddr) | ||
{ | ||
if (ulen < 0 || ulen > sizeof(struct sockaddr_storage)) | ||
if (ulen > BPF_MAX_VAR_SIZE) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems to increase the valid range of ulen. Previously the function would return There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like we're doing The original check against Also, not sure what exactly BPF_FORBIDS_ZERO_ACCESS implies but if my guess (length must be > 0) is correct, both the Though I expect both are there to keep the verifier happy? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That check seems like a leftover from move_addr_to_kernel kernel function. Anyways, we read at maximum After some intensive and day-long testing, we (@fntlnz and I) have not been able to break it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @gnosek The verifier rejects a check against There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Anyway the bug here was about the Both were required by the verifier (giving two different errors on each of them). Thus, this is the scope of this PR. In case we'd like to optimize the behaviour of the mask and the presence (or not) of ifdefs, we should approach those in another PR, imho. As per our testing, they do not interfere with the correct functioning of the probe. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So if you replace That is bizarre. That seems like a bug in the verifier. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, we tried in many many ways to retain that check too, but the verifier rejects it. |
||
return -EINVAL; | ||
|
||
if (ulen == 0) | ||
|
@@ -289,7 +293,7 @@ static __always_inline u32 bpf_compute_snaplen(struct filler_data *data, | |
if (!bpf_getsockname(sock, peer_address, 1)) | ||
return res; | ||
} else { | ||
int addrlen = bpf_syscall_get_argument(data, 5); | ||
unsigned long addrlen = bpf_syscall_get_argument(data, 5); | ||
|
||
if (addrlen != 0) { | ||
if (bpf_addr_to_kernel(usrsockaddr, addrlen, (struct sockaddr *)peer_address)) | ||
|
@@ -302,7 +306,7 @@ static __always_inline u32 bpf_compute_snaplen(struct filler_data *data, | |
struct sockaddr *usrsockaddr; | ||
struct user_msghdr mh; | ||
unsigned long val; | ||
int addrlen; | ||
unsigned long addrlen; | ||
|
||
val = bpf_syscall_get_argument(data, 1); | ||
if (bpf_probe_read(&mh, sizeof(mh), (void *)val)) { | ||
|
Uh oh!
There was an error while loading. Please reload this page.