diff options
-rw-r--r-- | include/uapi/linux/bpf.h | 1 | ||||
-rw-r--r-- | kernel/bpf/verifier.c | 15 | ||||
-rw-r--r-- | net/core/filter.c | 7 |
3 files changed, 21 insertions, 2 deletions
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 0248180bf2e2..3fa1af8a58d7 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h | |||
@@ -118,6 +118,7 @@ enum bpf_map_type { | |||
118 | enum bpf_prog_type { | 118 | enum bpf_prog_type { |
119 | BPF_PROG_TYPE_UNSPEC, | 119 | BPF_PROG_TYPE_UNSPEC, |
120 | BPF_PROG_TYPE_SOCKET_FILTER, | 120 | BPF_PROG_TYPE_SOCKET_FILTER, |
121 | BPF_PROG_TYPE_SCHED_CLS, | ||
121 | }; | 122 | }; |
122 | 123 | ||
123 | #define BPF_PSEUDO_MAP_FD 1 | 124 | #define BPF_PSEUDO_MAP_FD 1 |
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index a28e09c7825d..594d341f04db 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c | |||
@@ -1172,6 +1172,17 @@ static int check_ld_imm(struct verifier_env *env, struct bpf_insn *insn) | |||
1172 | return 0; | 1172 | return 0; |
1173 | } | 1173 | } |
1174 | 1174 | ||
1175 | static bool may_access_skb(enum bpf_prog_type type) | ||
1176 | { | ||
1177 | switch (type) { | ||
1178 | case BPF_PROG_TYPE_SOCKET_FILTER: | ||
1179 | case BPF_PROG_TYPE_SCHED_CLS: | ||
1180 | return true; | ||
1181 | default: | ||
1182 | return false; | ||
1183 | } | ||
1184 | } | ||
1185 | |||
1175 | /* verify safety of LD_ABS|LD_IND instructions: | 1186 | /* verify safety of LD_ABS|LD_IND instructions: |
1176 | * - they can only appear in the programs where ctx == skb | 1187 | * - they can only appear in the programs where ctx == skb |
1177 | * - since they are wrappers of function calls, they scratch R1-R5 registers, | 1188 | * - since they are wrappers of function calls, they scratch R1-R5 registers, |
@@ -1194,8 +1205,8 @@ static int check_ld_abs(struct verifier_env *env, struct bpf_insn *insn) | |||
1194 | struct reg_state *reg; | 1205 | struct reg_state *reg; |
1195 | int i, err; | 1206 | int i, err; |
1196 | 1207 | ||
1197 | if (env->prog->aux->prog_type != BPF_PROG_TYPE_SOCKET_FILTER) { | 1208 | if (!may_access_skb(env->prog->aux->prog_type)) { |
1198 | verbose("BPF_LD_ABS|IND instructions are only allowed in socket filters\n"); | 1209 | verbose("BPF_LD_ABS|IND instructions not allowed for this program type\n"); |
1199 | return -EINVAL; | 1210 | return -EINVAL; |
1200 | } | 1211 | } |
1201 | 1212 | ||
diff --git a/net/core/filter.c b/net/core/filter.c index 741721233166..514d4082f326 100644 --- a/net/core/filter.c +++ b/net/core/filter.c | |||
@@ -1166,9 +1166,16 @@ static struct bpf_prog_type_list sk_filter_type __read_mostly = { | |||
1166 | .type = BPF_PROG_TYPE_SOCKET_FILTER, | 1166 | .type = BPF_PROG_TYPE_SOCKET_FILTER, |
1167 | }; | 1167 | }; |
1168 | 1168 | ||
1169 | static struct bpf_prog_type_list sched_cls_type __read_mostly = { | ||
1170 | .ops = &sk_filter_ops, | ||
1171 | .type = BPF_PROG_TYPE_SCHED_CLS, | ||
1172 | }; | ||
1173 | |||
1169 | static int __init register_sk_filter_ops(void) | 1174 | static int __init register_sk_filter_ops(void) |
1170 | { | 1175 | { |
1171 | bpf_register_prog_type(&sk_filter_type); | 1176 | bpf_register_prog_type(&sk_filter_type); |
1177 | bpf_register_prog_type(&sched_cls_type); | ||
1178 | |||
1172 | return 0; | 1179 | return 0; |
1173 | } | 1180 | } |
1174 | late_initcall(register_sk_filter_ops); | 1181 | late_initcall(register_sk_filter_ops); |