aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorAndrey Ignatov <rdna@fb.com>2018-03-30 18:08:00 -0400
committerDaniel Borkmann <daniel@iogearbox.net>2018-03-30 20:14:44 -0400
commit5e43f899b03a3492ce5fc44e8900becb04dae9c0 (patch)
tree2811b77402c54e99a10a74f8a1b092b4bc2e24f6 /net/core
parent807ae7daf5fb9ba9ef688344ae7c0d8cbebd211c (diff)
bpf: Check attach type at prog load time
== The problem == There are use-cases when a program of some type can be attached to multiple attach points and those attach points must have different permissions to access context or to call helpers. E.g. context structure may have fields for both IPv4 and IPv6 but it doesn't make sense to read from / write to IPv6 field when attach point is somewhere in IPv4 stack. Same applies to BPF-helpers: it may make sense to call some helper from some attach point, but not from other for same prog type. == The solution == Introduce `expected_attach_type` field in in `struct bpf_attr` for `BPF_PROG_LOAD` command. If scenario described in "The problem" section is the case for some prog type, the field will be checked twice: 1) At load time prog type is checked to see if attach type for it must be known to validate program permissions correctly. Prog will be rejected with EINVAL if it's the case and `expected_attach_type` is not specified or has invalid value. 2) At attach time `attach_type` is compared with `expected_attach_type`, if prog type requires to have one, and, if they differ, attach will be rejected with EINVAL. The `expected_attach_type` is now available as part of `struct bpf_prog` in both `bpf_verifier_ops->is_valid_access()` and `bpf_verifier_ops->get_func_proto()` () and can be used to check context accesses and calls to helpers correspondingly. Initially the idea was discussed by Alexei Starovoitov <ast@fb.com> and Daniel Borkmann <daniel@iogearbox.net> here: https://marc.info/?l=linux-netdev&m=152107378717201&w=2 Signed-off-by: Andrey Ignatov <rdna@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/filter.c39
1 files changed, 25 insertions, 14 deletions
diff --git a/net/core/filter.c b/net/core/filter.c
index e989bf313195..7790fd128614 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -3685,7 +3685,7 @@ bpf_base_func_proto(enum bpf_func_id func_id)
3685} 3685}
3686 3686
3687static const struct bpf_func_proto * 3687static const struct bpf_func_proto *
3688sock_filter_func_proto(enum bpf_func_id func_id) 3688sock_filter_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
3689{ 3689{
3690 switch (func_id) { 3690 switch (func_id) {
3691 /* inet and inet6 sockets are created in a process 3691 /* inet and inet6 sockets are created in a process
@@ -3699,7 +3699,7 @@ sock_filter_func_proto(enum bpf_func_id func_id)
3699} 3699}
3700 3700
3701static const struct bpf_func_proto * 3701static const struct bpf_func_proto *
3702sk_filter_func_proto(enum bpf_func_id func_id) 3702sk_filter_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
3703{ 3703{
3704 switch (func_id) { 3704 switch (func_id) {
3705 case BPF_FUNC_skb_load_bytes: 3705 case BPF_FUNC_skb_load_bytes:
@@ -3714,7 +3714,7 @@ sk_filter_func_proto(enum bpf_func_id func_id)
3714} 3714}
3715 3715
3716static const struct bpf_func_proto * 3716static const struct bpf_func_proto *
3717tc_cls_act_func_proto(enum bpf_func_id func_id) 3717tc_cls_act_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
3718{ 3718{
3719 switch (func_id) { 3719 switch (func_id) {
3720 case BPF_FUNC_skb_store_bytes: 3720 case BPF_FUNC_skb_store_bytes:
@@ -3781,7 +3781,7 @@ tc_cls_act_func_proto(enum bpf_func_id func_id)
3781} 3781}
3782 3782
3783static const struct bpf_func_proto * 3783static const struct bpf_func_proto *
3784xdp_func_proto(enum bpf_func_id func_id) 3784xdp_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
3785{ 3785{
3786 switch (func_id) { 3786 switch (func_id) {
3787 case BPF_FUNC_perf_event_output: 3787 case BPF_FUNC_perf_event_output:
@@ -3804,7 +3804,7 @@ xdp_func_proto(enum bpf_func_id func_id)
3804} 3804}
3805 3805
3806static const struct bpf_func_proto * 3806static const struct bpf_func_proto *
3807lwt_inout_func_proto(enum bpf_func_id func_id) 3807lwt_inout_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
3808{ 3808{
3809 switch (func_id) { 3809 switch (func_id) {
3810 case BPF_FUNC_skb_load_bytes: 3810 case BPF_FUNC_skb_load_bytes:
@@ -3831,7 +3831,7 @@ lwt_inout_func_proto(enum bpf_func_id func_id)
3831} 3831}
3832 3832
3833static const struct bpf_func_proto * 3833static const struct bpf_func_proto *
3834 sock_ops_func_proto(enum bpf_func_id func_id) 3834sock_ops_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
3835{ 3835{
3836 switch (func_id) { 3836 switch (func_id) {
3837 case BPF_FUNC_setsockopt: 3837 case BPF_FUNC_setsockopt:
@@ -3847,7 +3847,8 @@ static const struct bpf_func_proto *
3847 } 3847 }
3848} 3848}
3849 3849
3850static const struct bpf_func_proto *sk_msg_func_proto(enum bpf_func_id func_id) 3850static const struct bpf_func_proto *
3851sk_msg_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
3851{ 3852{
3852 switch (func_id) { 3853 switch (func_id) {
3853 case BPF_FUNC_msg_redirect_map: 3854 case BPF_FUNC_msg_redirect_map:
@@ -3863,7 +3864,8 @@ static const struct bpf_func_proto *sk_msg_func_proto(enum bpf_func_id func_id)
3863 } 3864 }
3864} 3865}
3865 3866
3866static const struct bpf_func_proto *sk_skb_func_proto(enum bpf_func_id func_id) 3867static const struct bpf_func_proto *
3868sk_skb_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
3867{ 3869{
3868 switch (func_id) { 3870 switch (func_id) {
3869 case BPF_FUNC_skb_store_bytes: 3871 case BPF_FUNC_skb_store_bytes:
@@ -3888,7 +3890,7 @@ static const struct bpf_func_proto *sk_skb_func_proto(enum bpf_func_id func_id)
3888} 3890}
3889 3891
3890static const struct bpf_func_proto * 3892static const struct bpf_func_proto *
3891lwt_xmit_func_proto(enum bpf_func_id func_id) 3893lwt_xmit_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
3892{ 3894{
3893 switch (func_id) { 3895 switch (func_id) {
3894 case BPF_FUNC_skb_get_tunnel_key: 3896 case BPF_FUNC_skb_get_tunnel_key:
@@ -3918,11 +3920,12 @@ lwt_xmit_func_proto(enum bpf_func_id func_id)
3918 case BPF_FUNC_set_hash_invalid: 3920 case BPF_FUNC_set_hash_invalid:
3919 return &bpf_set_hash_invalid_proto; 3921 return &bpf_set_hash_invalid_proto;
3920 default: 3922 default:
3921 return lwt_inout_func_proto(func_id); 3923 return lwt_inout_func_proto(func_id, prog);
3922 } 3924 }
3923} 3925}
3924 3926
3925static bool bpf_skb_is_valid_access(int off, int size, enum bpf_access_type type, 3927static bool bpf_skb_is_valid_access(int off, int size, enum bpf_access_type type,
3928 const struct bpf_prog *prog,
3926 struct bpf_insn_access_aux *info) 3929 struct bpf_insn_access_aux *info)
3927{ 3930{
3928 const int size_default = sizeof(__u32); 3931 const int size_default = sizeof(__u32);
@@ -3966,6 +3969,7 @@ static bool bpf_skb_is_valid_access(int off, int size, enum bpf_access_type type
3966 3969
3967static bool sk_filter_is_valid_access(int off, int size, 3970static bool sk_filter_is_valid_access(int off, int size,
3968 enum bpf_access_type type, 3971 enum bpf_access_type type,
3972 const struct bpf_prog *prog,
3969 struct bpf_insn_access_aux *info) 3973 struct bpf_insn_access_aux *info)
3970{ 3974{
3971 switch (off) { 3975 switch (off) {
@@ -3986,11 +3990,12 @@ static bool sk_filter_is_valid_access(int off, int size,
3986 } 3990 }
3987 } 3991 }
3988 3992
3989 return bpf_skb_is_valid_access(off, size, type, info); 3993 return bpf_skb_is_valid_access(off, size, type, prog, info);
3990} 3994}
3991 3995
3992static bool lwt_is_valid_access(int off, int size, 3996static bool lwt_is_valid_access(int off, int size,
3993 enum bpf_access_type type, 3997 enum bpf_access_type type,
3998 const struct bpf_prog *prog,
3994 struct bpf_insn_access_aux *info) 3999 struct bpf_insn_access_aux *info)
3995{ 4000{
3996 switch (off) { 4001 switch (off) {
@@ -4020,11 +4025,12 @@ static bool lwt_is_valid_access(int off, int size,
4020 break; 4025 break;
4021 } 4026 }
4022 4027
4023 return bpf_skb_is_valid_access(off, size, type, info); 4028 return bpf_skb_is_valid_access(off, size, type, prog, info);
4024} 4029}
4025 4030
4026static bool sock_filter_is_valid_access(int off, int size, 4031static bool sock_filter_is_valid_access(int off, int size,
4027 enum bpf_access_type type, 4032 enum bpf_access_type type,
4033 const struct bpf_prog *prog,
4028 struct bpf_insn_access_aux *info) 4034 struct bpf_insn_access_aux *info)
4029{ 4035{
4030 if (type == BPF_WRITE) { 4036 if (type == BPF_WRITE) {
@@ -4096,6 +4102,7 @@ static int tc_cls_act_prologue(struct bpf_insn *insn_buf, bool direct_write,
4096 4102
4097static bool tc_cls_act_is_valid_access(int off, int size, 4103static bool tc_cls_act_is_valid_access(int off, int size,
4098 enum bpf_access_type type, 4104 enum bpf_access_type type,
4105 const struct bpf_prog *prog,
4099 struct bpf_insn_access_aux *info) 4106 struct bpf_insn_access_aux *info)
4100{ 4107{
4101 if (type == BPF_WRITE) { 4108 if (type == BPF_WRITE) {
@@ -4125,7 +4132,7 @@ static bool tc_cls_act_is_valid_access(int off, int size,
4125 return false; 4132 return false;
4126 } 4133 }
4127 4134
4128 return bpf_skb_is_valid_access(off, size, type, info); 4135 return bpf_skb_is_valid_access(off, size, type, prog, info);
4129} 4136}
4130 4137
4131static bool __is_valid_xdp_access(int off, int size) 4138static bool __is_valid_xdp_access(int off, int size)
@@ -4142,6 +4149,7 @@ static bool __is_valid_xdp_access(int off, int size)
4142 4149
4143static bool xdp_is_valid_access(int off, int size, 4150static bool xdp_is_valid_access(int off, int size,
4144 enum bpf_access_type type, 4151 enum bpf_access_type type,
4152 const struct bpf_prog *prog,
4145 struct bpf_insn_access_aux *info) 4153 struct bpf_insn_access_aux *info)
4146{ 4154{
4147 if (type == BPF_WRITE) 4155 if (type == BPF_WRITE)
@@ -4174,6 +4182,7 @@ EXPORT_SYMBOL_GPL(bpf_warn_invalid_xdp_action);
4174 4182
4175static bool sock_ops_is_valid_access(int off, int size, 4183static bool sock_ops_is_valid_access(int off, int size,
4176 enum bpf_access_type type, 4184 enum bpf_access_type type,
4185 const struct bpf_prog *prog,
4177 struct bpf_insn_access_aux *info) 4186 struct bpf_insn_access_aux *info)
4178{ 4187{
4179 const int size_default = sizeof(__u32); 4188 const int size_default = sizeof(__u32);
@@ -4220,6 +4229,7 @@ static int sk_skb_prologue(struct bpf_insn *insn_buf, bool direct_write,
4220 4229
4221static bool sk_skb_is_valid_access(int off, int size, 4230static bool sk_skb_is_valid_access(int off, int size,
4222 enum bpf_access_type type, 4231 enum bpf_access_type type,
4232 const struct bpf_prog *prog,
4223 struct bpf_insn_access_aux *info) 4233 struct bpf_insn_access_aux *info)
4224{ 4234{
4225 switch (off) { 4235 switch (off) {
@@ -4249,11 +4259,12 @@ static bool sk_skb_is_valid_access(int off, int size,
4249 break; 4259 break;
4250 } 4260 }
4251 4261
4252 return bpf_skb_is_valid_access(off, size, type, info); 4262 return bpf_skb_is_valid_access(off, size, type, prog, info);
4253} 4263}
4254 4264
4255static bool sk_msg_is_valid_access(int off, int size, 4265static bool sk_msg_is_valid_access(int off, int size,
4256 enum bpf_access_type type, 4266 enum bpf_access_type type,
4267 const struct bpf_prog *prog,
4257 struct bpf_insn_access_aux *info) 4268 struct bpf_insn_access_aux *info)
4258{ 4269{
4259 if (type == BPF_WRITE) 4270 if (type == BPF_WRITE)