-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
bpf: don't sign-extend IPv6 address components #28417
Conversation
/test |
e5290b1
to
b389e2b
Compare
/test |
Unqualified integers are treated as `int` in C, but the behaviour when doing binary operations on them against unsigned integers is surprising, to say the least. Consider the following scenario, before this patch: ``` #define DEFINE_IPV6(NAME, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16) \ DEFINE_U64_I(NAME, 1) = bpf_cpu_to_be64( \ (__u64)(a1) << 56 | (__u64)(a2) << 48 | (__u64)(a3) << 40 | \ (__u64)(a4) << 32 | (a5) << 24 | (a6) << 16 | (a7) << 8 | (a8)) .. <elip> DEFINE_IPV6(ROUTER_IP, 0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0); ``` Both a5 and a13 are set to a byte with a most-significant bit of 1. This results in the following output in the .data section during compilation: ``` 0000000000000038 <ROUTER_IP_1>: 7: ff ff ff ff 80 00 00 00 <unknown> 0000000000000040 <ROUTER_IP_2>: 8: ff ff ff ff 80 00 00 00 <unknown> ``` Since the `<< 24` pushed the 1 bit to now be the most-significant bit of an int, equivalent to an int32 on most 64-bit architectures, the subsequent OR operation against a __u64 causes the value to become sign-extended, setting the upper 32 bits of the resulting (unsigned..) integer to 1. Ouch. This commit treats each member as a u64, and additionally truncates each macro argument to u8 to prevent any of the arguments overlapping as a defensive measure. Signed-off-by: Timo Beckers <timo@isovalent.com>
b389e2b
to
0a28eb9
Compare
/test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚀
(__u64)(__u8)(a1) << 56 | (__u64)(__u8)(a2) << 48 | \ | ||
(__u64)(__u8)(a3) << 40 | (__u64)(__u8)(a4) << 32 | \ | ||
(__u64)(__u8)(a5) << 24 | (__u64)(__u8)(a6) << 16 | \ | ||
(__u64)(__u8)(a7) << 8 | (__u64)(__u8)(a8)); \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't want any values to spill over into the higher bits, so it's okay to be defensive here.
Yes, agree, makes sense! Kudos, amazing catch! |
The update-label-backport-pr workflow cannot handle characters like single quote and double quotes in the body of the PR passed as input. An example of a PR body containing single quotes is cilium#28435 Calling the workflow with that PR as input led to this failure: ``` Run echo '- [x] cilium#28417 -- bpf: don't sign-extend IPv6 address components (@ti-mo) echo '- [x] cilium#28417 -- bpf: don't sign-extend IPv6 address components (@ti-mo) Once this PR is merged, you can update the PR labels via: ```upstream-prs $ for pr in 28417; do contrib/backporting/set-labels.py $pr done 1.14; done ```' | sed -En "/upstream-prs/ { n; p }" | cut -d ';' -f 1 | grep -Eo '[0-9]+' | while read -r pr; do echo "Removing label backport-pending/1.14 from pr #${pr}." gh pr edit ${pr} --repo "${GITHUB_REPOSITORY}" --remove-label backport-pending/"1.14" echo "Adding label backport-done/1.14 to pr #${pr}." gh pr edit ${pr} --repo "${GITHUB_REPOSITORY}" --add-label backport-done/"1.14" done shell: /usr/bin/bash -e {0} env: GITHUB_TOKEN: *** /home/runner/work/_temp/f513ca6f-a4be-4c83-b2fa-7c179befdf5f.sh: line 1: syntax error near unexpected token `(' ``` This is due to the single quote in the word "don't" contained in the backported PR title. To fix the issue an initial step to preprocess the body is added. The step will remove single quotes, double quotes, backtick and dollar signs before parsing the input to get the list of backported PRs. Fixes: cilium#27875 Signed-off-by: Fabio Falzoi <fabio.falzoi@isovalent.com>
The update-label-backport-pr workflow cannot handle characters like single quote and double quotes in the body of the PR passed as input. An example of a PR body containing single quotes is cilium#28435 Calling the workflow with that PR as input led to this failure: ``` Run echo '- [x] cilium#28417 -- bpf: don't sign-extend IPv6 address components (@ti-mo) echo '- [x] cilium#28417 -- bpf: don't sign-extend IPv6 address components (@ti-mo) Once this PR is merged, you can update the PR labels via: ```upstream-prs $ for pr in 28417; do contrib/backporting/set-labels.py $pr done 1.14; done ```' | sed -En "/upstream-prs/ { n; p }" | cut -d ';' -f 1 | grep -Eo '[0-9]+' | while read -r pr; do echo "Removing label backport-pending/1.14 from pr #${pr}." gh pr edit ${pr} --repo "${GITHUB_REPOSITORY}" --remove-label backport-pending/"1.14" echo "Adding label backport-done/1.14 to pr #${pr}." gh pr edit ${pr} --repo "${GITHUB_REPOSITORY}" --add-label backport-done/"1.14" done shell: /usr/bin/bash -e {0} env: GITHUB_TOKEN: *** /home/runner/work/_temp/f513ca6f-a4be-4c83-b2fa-7c179befdf5f.sh: line 1: syntax error near unexpected token `(' ``` This is due to the single quote in the word "don't" contained in the backported PR title. To fix the issue an initial step to preprocess the body is added. The step will remove single quotes, double quotes, backtick and dollar signs before parsing the input to get the list of backported PRs. Fixes: cilium#27875 Signed-off-by: Fabio Falzoi <fabio.falzoi@isovalent.com>
The update-label-backport-pr workflow cannot handle characters like single quote and double quotes in the body of the PR passed as input. An example of a PR body containing single quotes is #28435 Calling the workflow with that PR as input led to this failure: ``` Run echo '- [x] #28417 -- bpf: don't sign-extend IPv6 address components (@ti-mo) echo '- [x] #28417 -- bpf: don't sign-extend IPv6 address components (@ti-mo) Once this PR is merged, you can update the PR labels via: ```upstream-prs $ for pr in 28417; do contrib/backporting/set-labels.py $pr done 1.14; done ```' | sed -En "/upstream-prs/ { n; p }" | cut -d ';' -f 1 | grep -Eo '[0-9]+' | while read -r pr; do echo "Removing label backport-pending/1.14 from pr #${pr}." gh pr edit ${pr} --repo "${GITHUB_REPOSITORY}" --remove-label backport-pending/"1.14" echo "Adding label backport-done/1.14 to pr #${pr}." gh pr edit ${pr} --repo "${GITHUB_REPOSITORY}" --add-label backport-done/"1.14" done shell: /usr/bin/bash -e {0} env: GITHUB_TOKEN: *** /home/runner/work/_temp/f513ca6f-a4be-4c83-b2fa-7c179befdf5f.sh: line 1: syntax error near unexpected token `(' ``` This is due to the single quote in the word "don't" contained in the backported PR title. To fix the issue an initial step to preprocess the body is added. The step will remove single quotes, double quotes, backtick and dollar signs before parsing the input to get the list of backported PRs. Fixes: #27875 Signed-off-by: Fabio Falzoi <fabio.falzoi@isovalent.com>
Unqualified integers are treated as
int
in C, but the behaviour when doing binary operations on them against unsigned integers is surprising, to say the least.Consider the following scenario, before this patch:
Both a5 and a13 are set to a byte with a most-significant bit of 1. This results in the following output in the .data section during compilation:
Since the
<< 24
pushed the 1 bit to now be the most-significant bit of an int, equivalent to an int32 on most 64-bit architectures, the subsequent OR operation against a __u64 causes the value to become sign-extended, setting the upper 32 bits of the resulting (unsigned..) integer to 1. Ouch.This commit treats each member as a u64, and additionally truncates each macro argument to u8 to prevent any of the arguments overlapping as a defensive measure.
Fixes: #27898