Skip to content

[ciqlts8_6] Patches for CVE-2022-23222 #335

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

Draft
wants to merge 8 commits into
base: ciqlts8_6
Choose a base branch
from

Conversation

thefossguy-ciq
Copy link

  • Commit Message Requirements
  • Built against Vault/LTS Environment
  • kABI Check Passed, where Valid (Pre 9.4 RT does not have kABI stability)
  • Boot Test
  • Kernel SelfTest results
  • Additional Tests as determined relevant

Kernel build logs

Kselftests

$ grep '^ok ' logs/kselftest/before.log | wc -l && grep '^ok ' logs/kselftest/after.log | wc -l

$ grep '^not ok ' logs/kselftest/before.log | wc -l && grep '^not ok ' logs/kselftest/after.log | wc -l

jira VULN-140
pre-cve CVE-2022-23222
commit-author Hao Luo <haoluo@google.com>
commit d639b9d
upstream-diff A merge confict arised because the function
    `bpf_free_kfunc_btf_tab` introduced in 2357672 ("bpf: Introduce
    BPF support for kernel module function calls") does not exist in
    our tree.

There are some common properties shared between bpf reg, ret and arg
values. For instance, a value may be a NULL pointer, or a pointer to
a read-only memory. Previously, to express these properties, enumeration
was used. For example, in order to test whether a reg value can be NULL,
reg_type_may_be_null() simply enumerates all types that are possibly
NULL. The problem of this approach is that it's not scalable and causes
a lot of duplication. These properties can be combined, for example, a
type could be either MAYBE_NULL or RDONLY, or both.

This patch series rewrites the layout of reg_type, arg_type and
ret_type, so that common properties can be extracted and represented as
composable flag. For example, one can write

 ARG_PTR_TO_MEM | PTR_MAYBE_NULL

which is equivalent to the previous

 ARG_PTR_TO_MEM_OR_NULL

The type ARG_PTR_TO_MEM are called "base type" in this patch. Base
types can be extended with flags. A flag occupies the higher bits while
base types sits in the lower bits.

This patch in particular sets up a set of macro for this purpose. The
following patches will rewrite arg_types, ret_types and reg_types
respectively.

	Signed-off-by: Hao Luo <haoluo@google.com>
	Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20211217003152.48334-2-haoluo@google.com
(cherry picked from commit d639b9d)
	Signed-off-by: Pratham Patel <ppatel@ciq.com>
jira VULN-140
pre-cve CVE-2022-23222
commit-author Hao Luo <haoluo@google.com>
commit 48946bd

We have introduced a new type to make bpf_arg composable, by
reserving high bits of bpf_arg to represent flags of a type.

One of the flags is PTR_MAYBE_NULL which indicates a pointer
may be NULL. When applying this flag to an arg_type, it means
the arg can take NULL pointer. This patch switches the
qualified arg_types to use this flag. The arg_types changed
in this patch include:

1. ARG_PTR_TO_MAP_VALUE_OR_NULL
2. ARG_PTR_TO_MEM_OR_NULL
3. ARG_PTR_TO_CTX_OR_NULL
4. ARG_PTR_TO_SOCKET_OR_NULL
5. ARG_PTR_TO_ALLOC_MEM_OR_NULL
6. ARG_PTR_TO_STACK_OR_NULL

This patch does not eliminate the use of these arg_types, instead
it makes them an alias to the 'ARG_XXX | PTR_MAYBE_NULL'.

	Signed-off-by: Hao Luo <haoluo@google.com>
	Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20211217003152.48334-3-haoluo@google.com
(cherry picked from commit 48946bd)
	Signed-off-by: Pratham Patel <ppatel@ciq.com>
jira VULN-140
pre-cve CVE-2022-23222
commit-author Hao Luo <haoluo@google.com>
commit 3c48073
upstream-diff The patch does not apply cleanly because 3e8ce29 ("bpf:
    Prevent pointer mismatch in bpf_timer_init.") is not present
    in our tree and will not be backported because it does not fix
    another commit nor fixes a CVE.

We have introduced a new type to make bpf_ret composable, by
reserving high bits to represent flags.

One of the flag is PTR_MAYBE_NULL, which indicates a pointer
may be NULL. When applying this flag to ret_types, it means
the returned value could be a NULL pointer. This patch
switches the qualified arg_types to use this flag.
The ret_types changed in this patch include:

1. RET_PTR_TO_MAP_VALUE_OR_NULL
2. RET_PTR_TO_SOCKET_OR_NULL
3. RET_PTR_TO_TCP_SOCK_OR_NULL
4. RET_PTR_TO_SOCK_COMMON_OR_NULL
5. RET_PTR_TO_ALLOC_MEM_OR_NULL
6. RET_PTR_TO_MEM_OR_BTF_ID_OR_NULL
7. RET_PTR_TO_BTF_ID_OR_NULL

This patch doesn't eliminate the use of these names, instead
it makes them aliases to 'RET_PTR_TO_XXX | PTR_MAYBE_NULL'.

	Signed-off-by: Hao Luo <haoluo@google.com>
	Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20211217003152.48334-4-haoluo@google.com
(cherry picked from commit 3c48073)
	Signed-off-by: Pratham Patel <ppatel@ciq.com>
jira VULN-140
pre-cve CVE-2022-23222
commit-author Hao Luo <haoluo@google.com>
commit c25b2ae
upstream-diff Two commits bfc6bb7 ("bpf: Implement verifier support for
    validation of async callbacks.") and 3e8ce29 ("bpf: revent pointer
    mismatch in bpf_timer_init.") are missing in our tree. There is no
    plan to backport them since they do not fix a CVE nor are fixes for
    a commit present in our tree.

We have introduced a new type to make bpf_reg composable, by
allocating bits in the type to represent flags.

One of the flags is PTR_MAYBE_NULL which indicates a pointer
may be NULL. This patch switches the qualified reg_types to
use this flag. The reg_types changed in this patch include:

1. PTR_TO_MAP_VALUE_OR_NULL
2. PTR_TO_SOCKET_OR_NULL
3. PTR_TO_SOCK_COMMON_OR_NULL
4. PTR_TO_TCP_SOCK_OR_NULL
5. PTR_TO_BTF_ID_OR_NULL
6. PTR_TO_MEM_OR_NULL
7. PTR_TO_RDONLY_BUF_OR_NULL
8. PTR_TO_RDWR_BUF_OR_NULL

	Signed-off-by: Hao Luo <haoluo@google.com>
	Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/r/20211217003152.48334-5-haoluo@google.com
(cherry picked from commit c25b2ae)
	Signed-off-by: Pratham Patel <ppatel@ciq.com>
jira VULN-140
pre-cve CVE-2022-23222
commit-author Hao Luo <haoluo@google.com>
commit 20b2aff

This patch introduce a flag MEM_RDONLY to tag a reg value
pointing to read-only memory. It makes the following changes:

1. PTR_TO_RDWR_BUF -> PTR_TO_BUF
2. PTR_TO_RDONLY_BUF -> PTR_TO_BUF | MEM_RDONLY

	Signed-off-by: Hao Luo <haoluo@google.com>
	Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20211217003152.48334-6-haoluo@google.com
(cherry picked from commit 20b2aff)
	Signed-off-by: Pratham Patel <ppatel@ciq.com>
jira VULN-140
pre-cve CVE-2022-23222
commit-author Daniel Borkmann <daniel@iogearbox.net>
commit be80a1d
upstream-diff We do not have the commit 3363bd0 ("bpf: Extend kfunc
    with PTR_TO_CTX, PTR_TO_MEM argument support"). Since it is not
    a commit fixing a previous commit, I do not intend to backport
    it either.

Generalize the check_ctx_reg() helper function into a more generic named one
so that it can be reused for other register types as well to check whether
their offset is non-zero. No functional change.

	Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
	Acked-by: John Fastabend <john.fastabend@gmail.com>
	Acked-by: Alexei Starovoitov <ast@kernel.org>
(cherry picked from commit be80a1d)
	Signed-off-by: Pratham Patel <ppatel@ciq.com>
jira VULN-140
pre-cve CVE-2022-23222
commit-author Daniel Borkmann <daniel@iogearbox.net>
commit 6788ab2

Right now the assertion on check_ptr_off_reg() is only enforced for register
types PTR_TO_CTX (and open coded also for PTR_TO_BTF_ID), however, this is
insufficient since many other PTR_TO_* register types such as PTR_TO_FUNC do
not handle/expect register offsets when passed to helper functions.

Given this can slip-through easily when adding new types, make this an explicit
allow-list and reject all other current and future types by default if this is
encountered.

Also, extend check_ptr_off_reg() to handle PTR_TO_BTF_ID as well instead of
duplicating it. For PTR_TO_BTF_ID, reg->off is used for BTF to match expected
BTF ids if struct offset is used. This part still needs to be allowed, but the
dynamic off from the tnum must be rejected.

Fixes: 69c087b ("bpf: Add bpf_for_each_map_elem() helper")
Fixes: eaa6bcb ("bpf: Introduce bpf_per_cpu_ptr()")
	Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
	Acked-by: John Fastabend <john.fastabend@gmail.com>
	Acked-by: Alexei Starovoitov <ast@kernel.org>
(cherry picked from commit 6788ab2)
	Signed-off-by: Pratham Patel <ppatel@ciq.com>
jira VULN-140
cve CVE-2022-23222
commit-author Daniel Borkmann <daniel@iogearbox.net>
commit 64620e0

Both bpf_ringbuf_submit() and bpf_ringbuf_discard() have ARG_PTR_TO_ALLOC_MEM
in their bpf_func_proto definition as their first argument. They both expect
the result from a prior bpf_ringbuf_reserve() call which has a return type of
RET_PTR_TO_ALLOC_MEM_OR_NULL.

Meaning, after a NULL check in the code, the verifier will promote the register
type in the non-NULL branch to a PTR_TO_MEM and in the NULL branch to a known
zero scalar. Generally, pointer arithmetic on PTR_TO_MEM is allowed, so the
latter could have an offset.

The ARG_PTR_TO_ALLOC_MEM expects a PTR_TO_MEM register type. However, the non-
zero result from bpf_ringbuf_reserve() must be fed into either bpf_ringbuf_submit()
or bpf_ringbuf_discard() but with the original offset given it will then read
out the struct bpf_ringbuf_hdr mapping.

The verifier missed to enforce a zero offset, so that out of bounds access
can be triggered which could be used to escalate privileges if unprivileged
BPF was enabled (disabled by default in kernel).

Fixes: 457f443 ("bpf: Implement BPF ring buffer and verifier support for it")
	Reported-by: <tr3e.wang@gmail.com> (SecCoder Security Lab)
	Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
	Acked-by: John Fastabend <john.fastabend@gmail.com>
	Acked-by: Alexei Starovoitov <ast@kernel.org>
(cherry picked from commit 64620e0)
	Signed-off-by: Pratham Patel <ppatel@ciq.com>
@thefossguy-ciq
Copy link
Author

First push with a build, pushed so I have a history before a rebase (if any). Will fill in the fields once I have the logs.

@bmastbergen
Copy link
Collaborator

Your first five commits are part of what was originally a nine commit series:

bpf: Introduce composable reg, ret and arg types.
bpf: Replace ARG_XXX_OR_NULL with ARG_XXX | PTR_MAYBE_NULL
bpf: Replace RET_XXX_OR_NULL with RET_XXX | PTR_MAYBE_NULL
bpf: Replace PTR_TO_XXX_OR_NULL with PTR_TO_XXX | PTR_MAYBE_NULL
bpf: Introduce MEM_RDONLY flag
bpf: Convert PTR_TO_MEM_OR_NULL to composable types.
bpf: Make per_cpu_ptr return rdonly PTR_TO_MEM.
bpf: Add MEM_RDONLY for helper args that are pointers to rdonly mem.
bpf/selftests: Test PTR_TO_RDONLY_MEM

Your other three commits were part of a backport to 5.15

Daniel Borkmann (4):
  bpf: Generalize check_ctx_reg for reuse with other types
  bpf: Generally fix helper register offset check
  bpf: Fix out of bounds access for ringbuf helpers
  bpf: Fix ringbuf memory type confusion when passing to helpers

Kumar Kartikeya Dwivedi (1):
  bpf: Extend kfunc with PTR_TO_CTX, PTR_TO_MEM argument support

If you look at the commit history for fips-8-compliant/4.18.0-553.16.1 you'll see RH came up with something pretty close to the commit list above. They didn't backport the selftest from the first series or bpf: Extend kfunc with PTR_TO_CTX, ... from the second, and they included an additional fix bpf: Fix crash due to out of.... which i believe they did because of how it was backported out of sequence as mentioned in the 5.15 backport message I linked above.

brett@iconium ~/ciq/kernel-src-tree
 % git log --oneline origin/fips-8-compliant/4.18.0-553.16.1 | less
...
...
...
b5da9a8d1493e bpf: Mark PTR_TO_FUNC register initially with zero offset
106133a2db52f bpf: Fix out of bounds access for ringbuf helpers
24526f20cc888 bpf: Generally fix helper register offset check
92a2f9e9a1ae5 bpf: Generalize check_ctx_reg for reuse with other types
eb88e636998a4 bpf: Check PTR_TO_MEM | MEM_RDONLY in check_helper_mem_access
6d45992c4b715 bpf: Fix crash due to out of bounds access into reg2btf_ids.
e3a3fdc2cfeec bpf: Add MEM_RDONLY for helper args that are pointers to rdonly mem.
4c9baa7ca4d23 bpf: Make per_cpu_ptr return rdonly PTR_TO_MEM.
44a7c509e6b17 bpf: Convert PTR_TO_MEM_OR_NULL to composable types.
8dedef7f02ace bpf: Introduce MEM_RDONLY flag
98e752a512d76 bpf: Replace PTR_TO_XXX_OR_NULL with PTR_TO_XXX | PTR_MAYBE_NULL
faec44fe0f775 bpf: Replace RET_XXX_OR_NULL with RET_XXX | PTR_MAYBE_NULL
e8981445f9a53 bpf: Replace ARG_XXX_OR_NULL with ARG_XXX | PTR_MAYBE_NULL
fe73f4bc875c4 bpf: Introduce composable reg, ret and arg types.
...
...
...

I think I'd be tempted to do it just like above. Interestingly the commit history there marks 98e752a512d76 bpf: Replace PTR_TO_XXX_OR_NULL with... as the fix for CVE-2022-23222, but that doesn't seem right. You'd also be picking up the fixes for CVE-2021-4204 and CVE-2022-0500 with all the commits above FWIW. If you look at the commit history for fips-8-compliant/4.18.0-553.16.1 you'll see that they pretty much all had conflicts while we tried to auto apply them, so unfortunately you won't get to cherry-pick their conflict resolution. My guess is its pretty close to what you've already done with the 8 you have though.

Just my .02

@thefossguy-ciq
Copy link
Author

Yeah, I spent yesterday trying to find my way out of at least one patch and came to the same conclusion as you. Only thing remaining now is to properly backport patches. They were done out of order and I don't trust git-rebase on such an old tree with merge conflicts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants