Message ID | 20211206232227.3286237-9-haoluo@google.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | BPF |
Headers | show |
Series | Introduce composable bpf types | expand |
On Mon, Dec 6, 2021 at 3:22 PM Hao Luo <haoluo@google.com> wrote: > > Some helper functions may modify its arguments, for example, > bpf_d_path, bpf_get_stack etc. Previously, their argument types > were marked as ARG_PTR_TO_MEM, which is compatible with read-only > mem types, such as PTR_TO_RDONLY_BUF. Therefore it's legitimate > to modify a read-only memory by passing it into one of such helper > functions. > > This patch tags the bpf_args compatible with immutable memory with > MEM_RDONLY flag. The arguments that don't have this flag will be > only compatible with mutable memory types, preventing the helper > from modifying a read-only memory. The bpf_args that have > MEM_RDONLY are compatible with both mutable memory and immutable > memory. > > Signed-off-by: Hao Luo <haoluo@google.com> > --- > include/linux/bpf.h | 4 ++- > kernel/bpf/btf.c | 2 +- > kernel/bpf/cgroup.c | 2 +- > kernel/bpf/helpers.c | 8 ++--- > kernel/bpf/ringbuf.c | 2 +- > kernel/bpf/syscall.c | 2 +- > kernel/bpf/verifier.c | 14 +++++++-- > kernel/trace/bpf_trace.c | 26 ++++++++-------- > net/core/filter.c | 64 ++++++++++++++++++++-------------------- > 9 files changed, 67 insertions(+), 57 deletions(-) > > diff --git a/include/linux/bpf.h b/include/linux/bpf.h > index 03418ab3f416..5151d6b1f392 100644 > --- a/include/linux/bpf.h > +++ b/include/linux/bpf.h > @@ -311,7 +311,9 @@ enum bpf_type_flag { > /* PTR may be NULL. */ > PTR_MAYBE_NULL = BIT(0 + BPF_BASE_TYPE_BITS), > > - /* MEM is read-only. */ > + /* MEM is read-only. When applied on bpf_arg, it indicates the arg is > + * compatible with both mutable and immutable memory. > + */ > MEM_RDONLY = BIT(1 + BPF_BASE_TYPE_BITS), > > __BPF_TYPE_LAST_FLAG = MEM_RDONLY, > diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c > index 7adc099bb24b..e09b5a7bfdc3 100644 > --- a/kernel/bpf/btf.c > +++ b/kernel/bpf/btf.c > @@ -6350,7 +6350,7 @@ const struct bpf_func_proto bpf_btf_find_by_name_kind_proto = { > .func = bpf_btf_find_by_name_kind, > .gpl_only = false, > .ret_type = RET_INTEGER, > - .arg1_type = ARG_PTR_TO_MEM, > + .arg1_type = ARG_PTR_TO_MEM | MEM_RDONLY, > .arg2_type = ARG_CONST_SIZE, > .arg3_type = ARG_ANYTHING, > .arg4_type = ARG_ANYTHING, > diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c > index 2ca643af9a54..b8fe671af13c 100644 > --- a/kernel/bpf/cgroup.c > +++ b/kernel/bpf/cgroup.c > @@ -1789,7 +1789,7 @@ static const struct bpf_func_proto bpf_sysctl_set_new_value_proto = { > .gpl_only = false, > .ret_type = RET_INTEGER, > .arg1_type = ARG_PTR_TO_CTX, > - .arg2_type = ARG_PTR_TO_MEM, > + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, > .arg3_type = ARG_CONST_SIZE, > }; > > diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c > index a5e349c9d3e3..66b466903a4e 100644 > --- a/kernel/bpf/helpers.c > +++ b/kernel/bpf/helpers.c > @@ -530,7 +530,7 @@ const struct bpf_func_proto bpf_strtol_proto = { > .func = bpf_strtol, > .gpl_only = false, > .ret_type = RET_INTEGER, > - .arg1_type = ARG_PTR_TO_MEM, > + .arg1_type = ARG_PTR_TO_MEM | MEM_RDONLY, > .arg2_type = ARG_CONST_SIZE, > .arg3_type = ARG_ANYTHING, > .arg4_type = ARG_PTR_TO_LONG, > @@ -558,7 +558,7 @@ const struct bpf_func_proto bpf_strtoul_proto = { > .func = bpf_strtoul, > .gpl_only = false, > .ret_type = RET_INTEGER, > - .arg1_type = ARG_PTR_TO_MEM, > + .arg1_type = ARG_PTR_TO_MEM | MEM_RDONLY, > .arg2_type = ARG_CONST_SIZE, > .arg3_type = ARG_ANYTHING, > .arg4_type = ARG_PTR_TO_LONG, > @@ -630,7 +630,7 @@ const struct bpf_func_proto bpf_event_output_data_proto = { > .arg1_type = ARG_PTR_TO_CTX, > .arg2_type = ARG_CONST_MAP_PTR, > .arg3_type = ARG_ANYTHING, > - .arg4_type = ARG_PTR_TO_MEM, > + .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY, > .arg5_type = ARG_CONST_SIZE_OR_ZERO, > }; > > @@ -1011,7 +1011,7 @@ const struct bpf_func_proto bpf_snprintf_proto = { > .arg1_type = ARG_PTR_TO_MEM_OR_NULL, > .arg2_type = ARG_CONST_SIZE_OR_ZERO, > .arg3_type = ARG_PTR_TO_CONST_STR, > - .arg4_type = ARG_PTR_TO_MEM_OR_NULL, > + .arg4_type = ARG_PTR_TO_MEM | PTR_MAYBE_NULL | MEM_RDONLY, > .arg5_type = ARG_CONST_SIZE_OR_ZERO, > }; > > diff --git a/kernel/bpf/ringbuf.c b/kernel/bpf/ringbuf.c > index 9e0c10c6892a..638d7fd7b375 100644 > --- a/kernel/bpf/ringbuf.c > +++ b/kernel/bpf/ringbuf.c > @@ -444,7 +444,7 @@ const struct bpf_func_proto bpf_ringbuf_output_proto = { > .func = bpf_ringbuf_output, > .ret_type = RET_INTEGER, > .arg1_type = ARG_CONST_MAP_PTR, > - .arg2_type = ARG_PTR_TO_MEM, > + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, > .arg3_type = ARG_CONST_SIZE_OR_ZERO, > .arg4_type = ARG_ANYTHING, > }; > diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c > index 50f96ea4452a..301afb44e47f 100644 > --- a/kernel/bpf/syscall.c > +++ b/kernel/bpf/syscall.c > @@ -4757,7 +4757,7 @@ static const struct bpf_func_proto bpf_sys_bpf_proto = { > .gpl_only = false, > .ret_type = RET_INTEGER, > .arg1_type = ARG_ANYTHING, > - .arg2_type = ARG_PTR_TO_MEM, > + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, > .arg3_type = ARG_CONST_SIZE, > }; > > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c > index 44af65f07a82..a7c015a7b52d 100644 > --- a/kernel/bpf/verifier.c > +++ b/kernel/bpf/verifier.c > @@ -4966,6 +4966,7 @@ static int resolve_map_arg_type(struct bpf_verifier_env *env, > return 0; > } > > + nit: unnecessary extra empty line? > struct bpf_reg_types { > const enum bpf_reg_type types[10]; > u32 *btf_id; > @@ -5012,7 +5013,6 @@ static const struct bpf_reg_types mem_types = { > PTR_TO_MAP_VALUE, > PTR_TO_MEM, > PTR_TO_BUF, > - PTR_TO_BUF | MEM_RDONLY, > }, > }; > > @@ -5074,6 +5074,7 @@ static int check_reg_type(struct bpf_verifier_env *env, u32 regno, > struct bpf_reg_state *regs = cur_regs(env), *reg = ®s[regno]; > enum bpf_reg_type expected, type = reg->type; > const struct bpf_reg_types *compatible; > + u32 compatible_flags; > int i, j; > > compatible = compatible_reg_types[base_type(arg_type)]; > @@ -5082,6 +5083,13 @@ static int check_reg_type(struct bpf_verifier_env *env, u32 regno, > return -EFAULT; > } > > + /* If arg_type is tagged with MEM_RDONLY, it's compatible with both > + * RDONLY and non-RDONLY reg values. Therefore fold this flag before > + * comparison. PTR_MAYBE_NULL is similar. > + */ > + compatible_flags = arg_type & (MEM_RDONLY | PTR_MAYBE_NULL); > + type &= ~compatible_flags; > + wouldn't type &= ~MEM_RDONLY; /* clear read-only flag, if any */ type &= ~PTR_MAYBE_NULL; /* clear nullable flag, if any */ be cleaner and more straightforward? > for (i = 0; i < ARRAY_SIZE(compatible->types); i++) { > expected = compatible->types[i]; > if (expected == NOT_INIT) [...]
On Mon, Dec 6, 2021 at 10:24 PM Andrii Nakryiko <andrii.nakryiko@gmail.com> wrote: > > On Mon, Dec 6, 2021 at 3:22 PM Hao Luo <haoluo@google.com> wrote: > > > > Some helper functions may modify its arguments, for example, > > bpf_d_path, bpf_get_stack etc. Previously, their argument types > > were marked as ARG_PTR_TO_MEM, which is compatible with read-only > > mem types, such as PTR_TO_RDONLY_BUF. Therefore it's legitimate > > to modify a read-only memory by passing it into one of such helper > > functions. > > > > This patch tags the bpf_args compatible with immutable memory with > > MEM_RDONLY flag. The arguments that don't have this flag will be > > only compatible with mutable memory types, preventing the helper > > from modifying a read-only memory. The bpf_args that have > > MEM_RDONLY are compatible with both mutable memory and immutable > > memory. > > > > Signed-off-by: Hao Luo <haoluo@google.com> > > --- > > include/linux/bpf.h | 4 ++- > > kernel/bpf/btf.c | 2 +- > > kernel/bpf/cgroup.c | 2 +- > > kernel/bpf/helpers.c | 8 ++--- > > kernel/bpf/ringbuf.c | 2 +- > > kernel/bpf/syscall.c | 2 +- > > kernel/bpf/verifier.c | 14 +++++++-- > > kernel/trace/bpf_trace.c | 26 ++++++++-------- > > net/core/filter.c | 64 ++++++++++++++++++++-------------------- > > 9 files changed, 67 insertions(+), 57 deletions(-) > > [...] > > > > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c > > index 44af65f07a82..a7c015a7b52d 100644 > > --- a/kernel/bpf/verifier.c > > +++ b/kernel/bpf/verifier.c > > @@ -4966,6 +4966,7 @@ static int resolve_map_arg_type(struct bpf_verifier_env *env, > > return 0; > > } > > > > + > > nit: unnecessary extra empty line? > Ack. > > struct bpf_reg_types { > > const enum bpf_reg_type types[10]; > > u32 *btf_id; > > @@ -5012,7 +5013,6 @@ static const struct bpf_reg_types mem_types = { > > PTR_TO_MAP_VALUE, > > PTR_TO_MEM, > > PTR_TO_BUF, > > - PTR_TO_BUF | MEM_RDONLY, > > }, > > }; > > > > @@ -5074,6 +5074,7 @@ static int check_reg_type(struct bpf_verifier_env *env, u32 regno, > > struct bpf_reg_state *regs = cur_regs(env), *reg = ®s[regno]; > > enum bpf_reg_type expected, type = reg->type; > > const struct bpf_reg_types *compatible; > > + u32 compatible_flags; > > int i, j; > > > > compatible = compatible_reg_types[base_type(arg_type)]; > > @@ -5082,6 +5083,13 @@ static int check_reg_type(struct bpf_verifier_env *env, u32 regno, > > return -EFAULT; > > } > > > > + /* If arg_type is tagged with MEM_RDONLY, it's compatible with both > > + * RDONLY and non-RDONLY reg values. Therefore fold this flag before > > + * comparison. PTR_MAYBE_NULL is similar. > > + */ > > + compatible_flags = arg_type & (MEM_RDONLY | PTR_MAYBE_NULL); > > + type &= ~compatible_flags; > > + > > wouldn't > > type &= ~MEM_RDONLY; /* clear read-only flag, if any */ > type &= ~PTR_MAYBE_NULL; /* clear nullable flag, if any */ > > be cleaner and more straightforward? > > No problem. Sounds good to me. > > for (i = 0; i < ARRAY_SIZE(compatible->types); i++) { > > expected = compatible->types[i]; > > if (expected == NOT_INIT) > > [...]
On Tue, Dec 7, 2021 at 7:49 PM Hao Luo <haoluo@google.com> wrote: > > On Mon, Dec 6, 2021 at 10:24 PM Andrii Nakryiko > <andrii.nakryiko@gmail.com> wrote: > > > > On Mon, Dec 6, 2021 at 3:22 PM Hao Luo <haoluo@google.com> wrote: > > > > > > Some helper functions may modify its arguments, for example, > > > bpf_d_path, bpf_get_stack etc. Previously, their argument types > > > were marked as ARG_PTR_TO_MEM, which is compatible with read-only > > > mem types, such as PTR_TO_RDONLY_BUF. Therefore it's legitimate > > > to modify a read-only memory by passing it into one of such helper > > > functions. > > > > > > This patch tags the bpf_args compatible with immutable memory with > > > MEM_RDONLY flag. The arguments that don't have this flag will be > > > only compatible with mutable memory types, preventing the helper > > > from modifying a read-only memory. The bpf_args that have > > > MEM_RDONLY are compatible with both mutable memory and immutable > > > memory. > > > > > > Signed-off-by: Hao Luo <haoluo@google.com> > > > --- > > > include/linux/bpf.h | 4 ++- > > > kernel/bpf/btf.c | 2 +- > > > kernel/bpf/cgroup.c | 2 +- > > > kernel/bpf/helpers.c | 8 ++--- > > > kernel/bpf/ringbuf.c | 2 +- > > > kernel/bpf/syscall.c | 2 +- > > > kernel/bpf/verifier.c | 14 +++++++-- > > > kernel/trace/bpf_trace.c | 26 ++++++++-------- > > > net/core/filter.c | 64 ++++++++++++++++++++-------------------- > > > 9 files changed, 67 insertions(+), 57 deletions(-) > > > [...] > > > @@ -5074,6 +5074,7 @@ static int check_reg_type(struct bpf_verifier_env *env, u32 regno, > > > struct bpf_reg_state *regs = cur_regs(env), *reg = ®s[regno]; > > > enum bpf_reg_type expected, type = reg->type; > > > const struct bpf_reg_types *compatible; > > > + u32 compatible_flags; > > > int i, j; > > > > > > compatible = compatible_reg_types[base_type(arg_type)]; > > > @@ -5082,6 +5083,13 @@ static int check_reg_type(struct bpf_verifier_env *env, u32 regno, > > > return -EFAULT; > > > } > > > > > > + /* If arg_type is tagged with MEM_RDONLY, it's compatible with both > > > + * RDONLY and non-RDONLY reg values. Therefore fold this flag before > > > + * comparison. PTR_MAYBE_NULL is similar. > > > + */ > > > + compatible_flags = arg_type & (MEM_RDONLY | PTR_MAYBE_NULL); > > > + type &= ~compatible_flags; > > > + > > > > wouldn't > > > > type &= ~MEM_RDONLY; /* clear read-only flag, if any */ > > type &= ~PTR_MAYBE_NULL; /* clear nullable flag, if any */ > > > > be cleaner and more straightforward? > > > > > > No problem. Sounds good to me. > I just realized the suggested transformation is wrong. Whether to fold the flag depends on whether arg_type has the flag. So it should instead be if (arg_type & MEM_RDONLY) type &= ~MEM_RDONLY; or type &= ~(arg_type & MEM_RDONLY); > > > for (i = 0; i < ARRAY_SIZE(compatible->types); i++) { > > > expected = compatible->types[i]; > > > if (expected == NOT_INIT) > > > > [...]
On Thu, Dec 9, 2021 at 12:04 PM Hao Luo <haoluo@google.com> wrote: > > On Tue, Dec 7, 2021 at 7:49 PM Hao Luo <haoluo@google.com> wrote: > > > > On Mon, Dec 6, 2021 at 10:24 PM Andrii Nakryiko > > <andrii.nakryiko@gmail.com> wrote: > > > > > > On Mon, Dec 6, 2021 at 3:22 PM Hao Luo <haoluo@google.com> wrote: > > > > > > > > Some helper functions may modify its arguments, for example, > > > > bpf_d_path, bpf_get_stack etc. Previously, their argument types > > > > were marked as ARG_PTR_TO_MEM, which is compatible with read-only > > > > mem types, such as PTR_TO_RDONLY_BUF. Therefore it's legitimate > > > > to modify a read-only memory by passing it into one of such helper > > > > functions. > > > > > > > > This patch tags the bpf_args compatible with immutable memory with > > > > MEM_RDONLY flag. The arguments that don't have this flag will be > > > > only compatible with mutable memory types, preventing the helper > > > > from modifying a read-only memory. The bpf_args that have > > > > MEM_RDONLY are compatible with both mutable memory and immutable > > > > memory. > > > > > > > > Signed-off-by: Hao Luo <haoluo@google.com> > > > > --- > > > > include/linux/bpf.h | 4 ++- > > > > kernel/bpf/btf.c | 2 +- > > > > kernel/bpf/cgroup.c | 2 +- > > > > kernel/bpf/helpers.c | 8 ++--- > > > > kernel/bpf/ringbuf.c | 2 +- > > > > kernel/bpf/syscall.c | 2 +- > > > > kernel/bpf/verifier.c | 14 +++++++-- > > > > kernel/trace/bpf_trace.c | 26 ++++++++-------- > > > > net/core/filter.c | 64 ++++++++++++++++++++-------------------- > > > > 9 files changed, 67 insertions(+), 57 deletions(-) > > > > > [...] > > > > @@ -5074,6 +5074,7 @@ static int check_reg_type(struct bpf_verifier_env *env, u32 regno, > > > > struct bpf_reg_state *regs = cur_regs(env), *reg = ®s[regno]; > > > > enum bpf_reg_type expected, type = reg->type; > > > > const struct bpf_reg_types *compatible; > > > > + u32 compatible_flags; > > > > int i, j; > > > > > > > > compatible = compatible_reg_types[base_type(arg_type)]; > > > > @@ -5082,6 +5083,13 @@ static int check_reg_type(struct bpf_verifier_env *env, u32 regno, > > > > return -EFAULT; > > > > } > > > > > > > > + /* If arg_type is tagged with MEM_RDONLY, it's compatible with both > > > > + * RDONLY and non-RDONLY reg values. Therefore fold this flag before > > > > + * comparison. PTR_MAYBE_NULL is similar. > > > > + */ > > > > + compatible_flags = arg_type & (MEM_RDONLY | PTR_MAYBE_NULL); > > > > + type &= ~compatible_flags; > > > > + > > > > > > wouldn't > > > > > > type &= ~MEM_RDONLY; /* clear read-only flag, if any */ > > > type &= ~PTR_MAYBE_NULL; /* clear nullable flag, if any */ > > > > > > be cleaner and more straightforward? > > > > > > > > > > No problem. Sounds good to me. > > > > I just realized the suggested transformation is wrong. Whether to fold > the flag depends on whether arg_type has the flag. So it should > instead be > > if (arg_type & MEM_RDONLY) > type &= ~MEM_RDONLY; > > or > > type &= ~(arg_type & MEM_RDONLY); You are totally right. I think this deserves a big verbose comment explaining that: ARG_PTR_TO_MEM+RDONLY is compatible with PTR_TO_MEM and PTR_TO_MEM+RDONLY, but ARG_PTR_TO_MEM is compatible only with PTR_TO_MEM and NOT with PTR_TO_MEM+RDONLY Same for MAYBE_NULL: ARG_PTR_TO_MEM + MAYBE_NULL is compatible with PTR_TO_MEM and PTR_TO_MEM+MAYBE_NULL, but ARG_PTR_TO_MEM is compatible only with PTR_TO_MEM but NOT with PTR_TO_MEM+MAYBE_NULL It might not be true for other future modifiers, so I'd do each of RDONLY and MAYBE_NULL with a separate if and comment. Good catch, btw! (but hopefully selftests would have caught this? if not, we need better tests) > > > > > for (i = 0; i < ARRAY_SIZE(compatible->types); i++) { > > > > expected = compatible->types[i]; > > > > if (expected == NOT_INIT) > > > > > > [...]
diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 03418ab3f416..5151d6b1f392 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -311,7 +311,9 @@ enum bpf_type_flag { /* PTR may be NULL. */ PTR_MAYBE_NULL = BIT(0 + BPF_BASE_TYPE_BITS), - /* MEM is read-only. */ + /* MEM is read-only. When applied on bpf_arg, it indicates the arg is + * compatible with both mutable and immutable memory. + */ MEM_RDONLY = BIT(1 + BPF_BASE_TYPE_BITS), __BPF_TYPE_LAST_FLAG = MEM_RDONLY, diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c index 7adc099bb24b..e09b5a7bfdc3 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c @@ -6350,7 +6350,7 @@ const struct bpf_func_proto bpf_btf_find_by_name_kind_proto = { .func = bpf_btf_find_by_name_kind, .gpl_only = false, .ret_type = RET_INTEGER, - .arg1_type = ARG_PTR_TO_MEM, + .arg1_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg2_type = ARG_CONST_SIZE, .arg3_type = ARG_ANYTHING, .arg4_type = ARG_ANYTHING, diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c index 2ca643af9a54..b8fe671af13c 100644 --- a/kernel/bpf/cgroup.c +++ b/kernel/bpf/cgroup.c @@ -1789,7 +1789,7 @@ static const struct bpf_func_proto bpf_sysctl_set_new_value_proto = { .gpl_only = false, .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE, }; diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c index a5e349c9d3e3..66b466903a4e 100644 --- a/kernel/bpf/helpers.c +++ b/kernel/bpf/helpers.c @@ -530,7 +530,7 @@ const struct bpf_func_proto bpf_strtol_proto = { .func = bpf_strtol, .gpl_only = false, .ret_type = RET_INTEGER, - .arg1_type = ARG_PTR_TO_MEM, + .arg1_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg2_type = ARG_CONST_SIZE, .arg3_type = ARG_ANYTHING, .arg4_type = ARG_PTR_TO_LONG, @@ -558,7 +558,7 @@ const struct bpf_func_proto bpf_strtoul_proto = { .func = bpf_strtoul, .gpl_only = false, .ret_type = RET_INTEGER, - .arg1_type = ARG_PTR_TO_MEM, + .arg1_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg2_type = ARG_CONST_SIZE, .arg3_type = ARG_ANYTHING, .arg4_type = ARG_PTR_TO_LONG, @@ -630,7 +630,7 @@ const struct bpf_func_proto bpf_event_output_data_proto = { .arg1_type = ARG_PTR_TO_CTX, .arg2_type = ARG_CONST_MAP_PTR, .arg3_type = ARG_ANYTHING, - .arg4_type = ARG_PTR_TO_MEM, + .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg5_type = ARG_CONST_SIZE_OR_ZERO, }; @@ -1011,7 +1011,7 @@ const struct bpf_func_proto bpf_snprintf_proto = { .arg1_type = ARG_PTR_TO_MEM_OR_NULL, .arg2_type = ARG_CONST_SIZE_OR_ZERO, .arg3_type = ARG_PTR_TO_CONST_STR, - .arg4_type = ARG_PTR_TO_MEM_OR_NULL, + .arg4_type = ARG_PTR_TO_MEM | PTR_MAYBE_NULL | MEM_RDONLY, .arg5_type = ARG_CONST_SIZE_OR_ZERO, }; diff --git a/kernel/bpf/ringbuf.c b/kernel/bpf/ringbuf.c index 9e0c10c6892a..638d7fd7b375 100644 --- a/kernel/bpf/ringbuf.c +++ b/kernel/bpf/ringbuf.c @@ -444,7 +444,7 @@ const struct bpf_func_proto bpf_ringbuf_output_proto = { .func = bpf_ringbuf_output, .ret_type = RET_INTEGER, .arg1_type = ARG_CONST_MAP_PTR, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE_OR_ZERO, .arg4_type = ARG_ANYTHING, }; diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 50f96ea4452a..301afb44e47f 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -4757,7 +4757,7 @@ static const struct bpf_func_proto bpf_sys_bpf_proto = { .gpl_only = false, .ret_type = RET_INTEGER, .arg1_type = ARG_ANYTHING, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE, }; diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 44af65f07a82..a7c015a7b52d 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -4966,6 +4966,7 @@ static int resolve_map_arg_type(struct bpf_verifier_env *env, return 0; } + struct bpf_reg_types { const enum bpf_reg_type types[10]; u32 *btf_id; @@ -5012,7 +5013,6 @@ static const struct bpf_reg_types mem_types = { PTR_TO_MAP_VALUE, PTR_TO_MEM, PTR_TO_BUF, - PTR_TO_BUF | MEM_RDONLY, }, }; @@ -5074,6 +5074,7 @@ static int check_reg_type(struct bpf_verifier_env *env, u32 regno, struct bpf_reg_state *regs = cur_regs(env), *reg = ®s[regno]; enum bpf_reg_type expected, type = reg->type; const struct bpf_reg_types *compatible; + u32 compatible_flags; int i, j; compatible = compatible_reg_types[base_type(arg_type)]; @@ -5082,6 +5083,13 @@ static int check_reg_type(struct bpf_verifier_env *env, u32 regno, return -EFAULT; } + /* If arg_type is tagged with MEM_RDONLY, it's compatible with both + * RDONLY and non-RDONLY reg values. Therefore fold this flag before + * comparison. PTR_MAYBE_NULL is similar. + */ + compatible_flags = arg_type & (MEM_RDONLY | PTR_MAYBE_NULL); + type &= ~compatible_flags; + for (i = 0; i < ARRAY_SIZE(compatible->types); i++) { expected = compatible->types[i]; if (expected == NOT_INIT) @@ -5091,14 +5099,14 @@ static int check_reg_type(struct bpf_verifier_env *env, u32 regno, goto found; } - verbose(env, "R%d type=%s expected=", regno, reg_type_str(type)); + verbose(env, "R%d type=%s expected=", regno, reg_type_str(reg->type)); for (j = 0; j + 1 < i; j++) verbose(env, "%s, ", reg_type_str(compatible->types[j])); verbose(env, "%s\n", reg_type_str(compatible->types[j])); return -EACCES; found: - if (type == PTR_TO_BTF_ID) { + if (reg->type == PTR_TO_BTF_ID) { if (!arg_btf_id) { if (!compatible->btf_id) { verbose(env, "verifier internal error: missing arg compatible BTF ID\n"); diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index 25ea521fb8f1..79404049b70f 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -345,7 +345,7 @@ static const struct bpf_func_proto bpf_probe_write_user_proto = { .gpl_only = true, .ret_type = RET_INTEGER, .arg1_type = ARG_ANYTHING, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE, }; @@ -394,7 +394,7 @@ static const struct bpf_func_proto bpf_trace_printk_proto = { .func = bpf_trace_printk, .gpl_only = true, .ret_type = RET_INTEGER, - .arg1_type = ARG_PTR_TO_MEM, + .arg1_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg2_type = ARG_CONST_SIZE, }; @@ -450,9 +450,9 @@ static const struct bpf_func_proto bpf_trace_vprintk_proto = { .func = bpf_trace_vprintk, .gpl_only = true, .ret_type = RET_INTEGER, - .arg1_type = ARG_PTR_TO_MEM, + .arg1_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg2_type = ARG_CONST_SIZE, - .arg3_type = ARG_PTR_TO_MEM_OR_NULL, + .arg3_type = ARG_PTR_TO_MEM | PTR_MAYBE_NULL | MEM_RDONLY, .arg4_type = ARG_CONST_SIZE_OR_ZERO, }; @@ -492,9 +492,9 @@ static const struct bpf_func_proto bpf_seq_printf_proto = { .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_BTF_ID, .arg1_btf_id = &btf_seq_file_ids[0], - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE, - .arg4_type = ARG_PTR_TO_MEM_OR_NULL, + .arg4_type = ARG_PTR_TO_MEM | PTR_MAYBE_NULL | MEM_RDONLY, .arg5_type = ARG_CONST_SIZE_OR_ZERO, }; @@ -509,7 +509,7 @@ static const struct bpf_func_proto bpf_seq_write_proto = { .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_BTF_ID, .arg1_btf_id = &btf_seq_file_ids[0], - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE_OR_ZERO, }; @@ -533,7 +533,7 @@ static const struct bpf_func_proto bpf_seq_printf_btf_proto = { .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_BTF_ID, .arg1_btf_id = &btf_seq_file_ids[0], - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE_OR_ZERO, .arg4_type = ARG_ANYTHING, }; @@ -694,7 +694,7 @@ static const struct bpf_func_proto bpf_perf_event_output_proto = { .arg1_type = ARG_PTR_TO_CTX, .arg2_type = ARG_CONST_MAP_PTR, .arg3_type = ARG_ANYTHING, - .arg4_type = ARG_PTR_TO_MEM, + .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg5_type = ARG_CONST_SIZE_OR_ZERO, }; @@ -1004,7 +1004,7 @@ const struct bpf_func_proto bpf_snprintf_btf_proto = { .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_MEM, .arg2_type = ARG_CONST_SIZE, - .arg3_type = ARG_PTR_TO_MEM, + .arg3_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg4_type = ARG_CONST_SIZE, .arg5_type = ARG_ANYTHING, }; @@ -1289,7 +1289,7 @@ static const struct bpf_func_proto bpf_perf_event_output_proto_tp = { .arg1_type = ARG_PTR_TO_CTX, .arg2_type = ARG_CONST_MAP_PTR, .arg3_type = ARG_ANYTHING, - .arg4_type = ARG_PTR_TO_MEM, + .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg5_type = ARG_CONST_SIZE_OR_ZERO, }; @@ -1515,7 +1515,7 @@ static const struct bpf_func_proto bpf_perf_event_output_proto_raw_tp = { .arg1_type = ARG_PTR_TO_CTX, .arg2_type = ARG_CONST_MAP_PTR, .arg3_type = ARG_ANYTHING, - .arg4_type = ARG_PTR_TO_MEM, + .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg5_type = ARG_CONST_SIZE_OR_ZERO, }; @@ -1569,7 +1569,7 @@ static const struct bpf_func_proto bpf_get_stack_proto_raw_tp = { .gpl_only = true, .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE_OR_ZERO, .arg4_type = ARG_ANYTHING, }; diff --git a/net/core/filter.c b/net/core/filter.c index 26e0276aa00d..eadca10b436d 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -1713,7 +1713,7 @@ static const struct bpf_func_proto bpf_skb_store_bytes_proto = { .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_CTX, .arg2_type = ARG_ANYTHING, - .arg3_type = ARG_PTR_TO_MEM, + .arg3_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg4_type = ARG_CONST_SIZE, .arg5_type = ARG_ANYTHING, }; @@ -2018,9 +2018,9 @@ static const struct bpf_func_proto bpf_csum_diff_proto = { .gpl_only = false, .pkt_access = true, .ret_type = RET_INTEGER, - .arg1_type = ARG_PTR_TO_MEM_OR_NULL, + .arg1_type = ARG_PTR_TO_MEM | PTR_MAYBE_NULL | MEM_RDONLY, .arg2_type = ARG_CONST_SIZE_OR_ZERO, - .arg3_type = ARG_PTR_TO_MEM_OR_NULL, + .arg3_type = ARG_PTR_TO_MEM | PTR_MAYBE_NULL | MEM_RDONLY, .arg4_type = ARG_CONST_SIZE_OR_ZERO, .arg5_type = ARG_ANYTHING, }; @@ -2541,7 +2541,7 @@ static const struct bpf_func_proto bpf_redirect_neigh_proto = { .gpl_only = false, .ret_type = RET_INTEGER, .arg1_type = ARG_ANYTHING, - .arg2_type = ARG_PTR_TO_MEM_OR_NULL, + .arg2_type = ARG_PTR_TO_MEM | PTR_MAYBE_NULL | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE_OR_ZERO, .arg4_type = ARG_ANYTHING, }; @@ -4174,7 +4174,7 @@ static const struct bpf_func_proto bpf_skb_event_output_proto = { .arg1_type = ARG_PTR_TO_CTX, .arg2_type = ARG_CONST_MAP_PTR, .arg3_type = ARG_ANYTHING, - .arg4_type = ARG_PTR_TO_MEM, + .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg5_type = ARG_CONST_SIZE_OR_ZERO, }; @@ -4188,7 +4188,7 @@ const struct bpf_func_proto bpf_skb_output_proto = { .arg1_btf_id = &bpf_skb_output_btf_ids[0], .arg2_type = ARG_CONST_MAP_PTR, .arg3_type = ARG_ANYTHING, - .arg4_type = ARG_PTR_TO_MEM, + .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg5_type = ARG_CONST_SIZE_OR_ZERO, }; @@ -4371,7 +4371,7 @@ static const struct bpf_func_proto bpf_skb_set_tunnel_key_proto = { .gpl_only = false, .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE, .arg4_type = ARG_ANYTHING, }; @@ -4397,7 +4397,7 @@ static const struct bpf_func_proto bpf_skb_set_tunnel_opt_proto = { .gpl_only = false, .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE, }; @@ -4567,7 +4567,7 @@ static const struct bpf_func_proto bpf_xdp_event_output_proto = { .arg1_type = ARG_PTR_TO_CTX, .arg2_type = ARG_CONST_MAP_PTR, .arg3_type = ARG_ANYTHING, - .arg4_type = ARG_PTR_TO_MEM, + .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg5_type = ARG_CONST_SIZE_OR_ZERO, }; @@ -4581,7 +4581,7 @@ const struct bpf_func_proto bpf_xdp_output_proto = { .arg1_btf_id = &bpf_xdp_output_btf_ids[0], .arg2_type = ARG_CONST_MAP_PTR, .arg3_type = ARG_ANYTHING, - .arg4_type = ARG_PTR_TO_MEM, + .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg5_type = ARG_CONST_SIZE_OR_ZERO, }; @@ -5067,7 +5067,7 @@ const struct bpf_func_proto bpf_sk_setsockopt_proto = { .arg1_type = ARG_PTR_TO_BTF_ID_SOCK_COMMON, .arg2_type = ARG_ANYTHING, .arg3_type = ARG_ANYTHING, - .arg4_type = ARG_PTR_TO_MEM, + .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg5_type = ARG_CONST_SIZE, }; @@ -5101,7 +5101,7 @@ static const struct bpf_func_proto bpf_sock_addr_setsockopt_proto = { .arg1_type = ARG_PTR_TO_CTX, .arg2_type = ARG_ANYTHING, .arg3_type = ARG_ANYTHING, - .arg4_type = ARG_PTR_TO_MEM, + .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg5_type = ARG_CONST_SIZE, }; @@ -5135,7 +5135,7 @@ static const struct bpf_func_proto bpf_sock_ops_setsockopt_proto = { .arg1_type = ARG_PTR_TO_CTX, .arg2_type = ARG_ANYTHING, .arg3_type = ARG_ANYTHING, - .arg4_type = ARG_PTR_TO_MEM, + .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg5_type = ARG_CONST_SIZE, }; @@ -5310,7 +5310,7 @@ static const struct bpf_func_proto bpf_bind_proto = { .gpl_only = false, .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE, }; @@ -5898,7 +5898,7 @@ static const struct bpf_func_proto bpf_lwt_in_push_encap_proto = { .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_CTX, .arg2_type = ARG_ANYTHING, - .arg3_type = ARG_PTR_TO_MEM, + .arg3_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg4_type = ARG_CONST_SIZE }; @@ -5908,7 +5908,7 @@ static const struct bpf_func_proto bpf_lwt_xmit_push_encap_proto = { .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_CTX, .arg2_type = ARG_ANYTHING, - .arg3_type = ARG_PTR_TO_MEM, + .arg3_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg4_type = ARG_CONST_SIZE }; @@ -5951,7 +5951,7 @@ static const struct bpf_func_proto bpf_lwt_seg6_store_bytes_proto = { .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_CTX, .arg2_type = ARG_ANYTHING, - .arg3_type = ARG_PTR_TO_MEM, + .arg3_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg4_type = ARG_CONST_SIZE }; @@ -6039,7 +6039,7 @@ static const struct bpf_func_proto bpf_lwt_seg6_action_proto = { .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_CTX, .arg2_type = ARG_ANYTHING, - .arg3_type = ARG_PTR_TO_MEM, + .arg3_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg4_type = ARG_CONST_SIZE }; @@ -6264,7 +6264,7 @@ static const struct bpf_func_proto bpf_skc_lookup_tcp_proto = { .pkt_access = true, .ret_type = RET_PTR_TO_SOCK_COMMON_OR_NULL, .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE, .arg4_type = ARG_ANYTHING, .arg5_type = ARG_ANYTHING, @@ -6283,7 +6283,7 @@ static const struct bpf_func_proto bpf_sk_lookup_tcp_proto = { .pkt_access = true, .ret_type = RET_PTR_TO_SOCKET_OR_NULL, .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE, .arg4_type = ARG_ANYTHING, .arg5_type = ARG_ANYTHING, @@ -6302,7 +6302,7 @@ static const struct bpf_func_proto bpf_sk_lookup_udp_proto = { .pkt_access = true, .ret_type = RET_PTR_TO_SOCKET_OR_NULL, .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE, .arg4_type = ARG_ANYTHING, .arg5_type = ARG_ANYTHING, @@ -6339,7 +6339,7 @@ static const struct bpf_func_proto bpf_xdp_sk_lookup_udp_proto = { .pkt_access = true, .ret_type = RET_PTR_TO_SOCKET_OR_NULL, .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE, .arg4_type = ARG_ANYTHING, .arg5_type = ARG_ANYTHING, @@ -6362,7 +6362,7 @@ static const struct bpf_func_proto bpf_xdp_skc_lookup_tcp_proto = { .pkt_access = true, .ret_type = RET_PTR_TO_SOCK_COMMON_OR_NULL, .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE, .arg4_type = ARG_ANYTHING, .arg5_type = ARG_ANYTHING, @@ -6385,7 +6385,7 @@ static const struct bpf_func_proto bpf_xdp_sk_lookup_tcp_proto = { .pkt_access = true, .ret_type = RET_PTR_TO_SOCKET_OR_NULL, .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE, .arg4_type = ARG_ANYTHING, .arg5_type = ARG_ANYTHING, @@ -6404,7 +6404,7 @@ static const struct bpf_func_proto bpf_sock_addr_skc_lookup_tcp_proto = { .gpl_only = false, .ret_type = RET_PTR_TO_SOCK_COMMON_OR_NULL, .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE, .arg4_type = ARG_ANYTHING, .arg5_type = ARG_ANYTHING, @@ -6423,7 +6423,7 @@ static const struct bpf_func_proto bpf_sock_addr_sk_lookup_tcp_proto = { .gpl_only = false, .ret_type = RET_PTR_TO_SOCKET_OR_NULL, .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE, .arg4_type = ARG_ANYTHING, .arg5_type = ARG_ANYTHING, @@ -6442,7 +6442,7 @@ static const struct bpf_func_proto bpf_sock_addr_sk_lookup_udp_proto = { .gpl_only = false, .ret_type = RET_PTR_TO_SOCKET_OR_NULL, .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE, .arg4_type = ARG_ANYTHING, .arg5_type = ARG_ANYTHING, @@ -6755,9 +6755,9 @@ static const struct bpf_func_proto bpf_tcp_check_syncookie_proto = { .pkt_access = true, .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_BTF_ID_SOCK_COMMON, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE, - .arg4_type = ARG_PTR_TO_MEM, + .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg5_type = ARG_CONST_SIZE, }; @@ -6824,9 +6824,9 @@ static const struct bpf_func_proto bpf_tcp_gen_syncookie_proto = { .pkt_access = true, .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_BTF_ID_SOCK_COMMON, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE, - .arg4_type = ARG_PTR_TO_MEM, + .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg5_type = ARG_CONST_SIZE, }; @@ -7055,7 +7055,7 @@ static const struct bpf_func_proto bpf_sock_ops_store_hdr_opt_proto = { .gpl_only = false, .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE, .arg4_type = ARG_ANYTHING, };
Some helper functions may modify its arguments, for example, bpf_d_path, bpf_get_stack etc. Previously, their argument types were marked as ARG_PTR_TO_MEM, which is compatible with read-only mem types, such as PTR_TO_RDONLY_BUF. Therefore it's legitimate to modify a read-only memory by passing it into one of such helper functions. This patch tags the bpf_args compatible with immutable memory with MEM_RDONLY flag. The arguments that don't have this flag will be only compatible with mutable memory types, preventing the helper from modifying a read-only memory. The bpf_args that have MEM_RDONLY are compatible with both mutable memory and immutable memory. Signed-off-by: Hao Luo <haoluo@google.com> --- include/linux/bpf.h | 4 ++- kernel/bpf/btf.c | 2 +- kernel/bpf/cgroup.c | 2 +- kernel/bpf/helpers.c | 8 ++--- kernel/bpf/ringbuf.c | 2 +- kernel/bpf/syscall.c | 2 +- kernel/bpf/verifier.c | 14 +++++++-- kernel/trace/bpf_trace.c | 26 ++++++++-------- net/core/filter.c | 64 ++++++++++++++++++++-------------------- 9 files changed, 67 insertions(+), 57 deletions(-)