aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/bpf/syscall.c
diff options
context:
space:
mode:
authorAlexei Starovoitov <ast@fb.com>2017-10-03 01:50:21 -0400
committerDavid S. Miller <davem@davemloft.net>2017-10-04 19:05:05 -0400
commit324bda9e6c5add86ba2e1066476481c48132aca0 (patch)
tree31d4267d10e934e6b3c180556c91aff8ea6dd990 /kernel/bpf/syscall.c
parentc818fa9e288be5be7e360c33cf4f5e30f9fa206e (diff)
bpf: multi program support for cgroup+bpf
introduce BPF_F_ALLOW_MULTI flag that can be used to attach multiple bpf programs to a cgroup. The difference between three possible flags for BPF_PROG_ATTACH command: - NONE(default): No further bpf programs allowed in the subtree. - BPF_F_ALLOW_OVERRIDE: If a sub-cgroup installs some bpf program, the program in this cgroup yields to sub-cgroup program. - BPF_F_ALLOW_MULTI: If a sub-cgroup installs some bpf program, that cgroup program gets run in addition to the program in this cgroup. NONE and BPF_F_ALLOW_OVERRIDE existed before. This patch doesn't change their behavior. It only clarifies the semantics in relation to new flag. Only one program is allowed to be attached to a cgroup with NONE or BPF_F_ALLOW_OVERRIDE flag. Multiple programs are allowed to be attached to a cgroup with BPF_F_ALLOW_MULTI flag. They are executed in FIFO order (those that were attached first, run first) The programs of sub-cgroup are executed first, then programs of this cgroup and then programs of parent cgroup. All eligible programs are executed regardless of return code from earlier programs. To allow efficient execution of multiple programs attached to a cgroup and to avoid penalizing cgroups without any programs attached introduce 'struct bpf_prog_array' which is RCU protected array of pointers to bpf programs. Signed-off-by: Alexei Starovoitov <ast@kernel.org> Acked-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: Martin KaFai Lau <kafai@fb.com> for cgroup bits Acked-by: Tejun Heo <tj@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'kernel/bpf/syscall.c')
-rw-r--r--kernel/bpf/syscall.c37
1 files changed, 26 insertions, 11 deletions
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index b927da66f653..51bee695d32c 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -1168,6 +1168,9 @@ static int sockmap_get_from_fd(const union bpf_attr *attr, bool attach)
1168 return 0; 1168 return 0;
1169} 1169}
1170 1170
1171#define BPF_F_ATTACH_MASK \
1172 (BPF_F_ALLOW_OVERRIDE | BPF_F_ALLOW_MULTI)
1173
1171static int bpf_prog_attach(const union bpf_attr *attr) 1174static int bpf_prog_attach(const union bpf_attr *attr)
1172{ 1175{
1173 enum bpf_prog_type ptype; 1176 enum bpf_prog_type ptype;
@@ -1181,7 +1184,7 @@ static int bpf_prog_attach(const union bpf_attr *attr)
1181 if (CHECK_ATTR(BPF_PROG_ATTACH)) 1184 if (CHECK_ATTR(BPF_PROG_ATTACH))
1182 return -EINVAL; 1185 return -EINVAL;
1183 1186
1184 if (attr->attach_flags & ~BPF_F_ALLOW_OVERRIDE) 1187 if (attr->attach_flags & ~BPF_F_ATTACH_MASK)
1185 return -EINVAL; 1188 return -EINVAL;
1186 1189
1187 switch (attr->attach_type) { 1190 switch (attr->attach_type) {
@@ -1212,8 +1215,8 @@ static int bpf_prog_attach(const union bpf_attr *attr)
1212 return PTR_ERR(cgrp); 1215 return PTR_ERR(cgrp);
1213 } 1216 }
1214 1217
1215 ret = cgroup_bpf_update(cgrp, prog, attr->attach_type, 1218 ret = cgroup_bpf_attach(cgrp, prog, attr->attach_type,
1216 attr->attach_flags & BPF_F_ALLOW_OVERRIDE); 1219 attr->attach_flags);
1217 if (ret) 1220 if (ret)
1218 bpf_prog_put(prog); 1221 bpf_prog_put(prog);
1219 cgroup_put(cgrp); 1222 cgroup_put(cgrp);
@@ -1225,6 +1228,8 @@ static int bpf_prog_attach(const union bpf_attr *attr)
1225 1228
1226static int bpf_prog_detach(const union bpf_attr *attr) 1229static int bpf_prog_detach(const union bpf_attr *attr)
1227{ 1230{
1231 enum bpf_prog_type ptype;
1232 struct bpf_prog *prog;
1228 struct cgroup *cgrp; 1233 struct cgroup *cgrp;
1229 int ret; 1234 int ret;
1230 1235
@@ -1237,23 +1242,33 @@ static int bpf_prog_detach(const union bpf_attr *attr)
1237 switch (attr->attach_type) { 1242 switch (attr->attach_type) {
1238 case BPF_CGROUP_INET_INGRESS: 1243 case BPF_CGROUP_INET_INGRESS:
1239 case BPF_CGROUP_INET_EGRESS: 1244 case BPF_CGROUP_INET_EGRESS:
1245 ptype = BPF_PROG_TYPE_CGROUP_SKB;
1246 break;
1240 case BPF_CGROUP_INET_SOCK_CREATE: 1247 case BPF_CGROUP_INET_SOCK_CREATE:
1248 ptype = BPF_PROG_TYPE_CGROUP_SOCK;
1249 break;
1241 case BPF_CGROUP_SOCK_OPS: 1250 case BPF_CGROUP_SOCK_OPS:
1242 cgrp = cgroup_get_from_fd(attr->target_fd); 1251 ptype = BPF_PROG_TYPE_SOCK_OPS;
1243 if (IS_ERR(cgrp))
1244 return PTR_ERR(cgrp);
1245
1246 ret = cgroup_bpf_update(cgrp, NULL, attr->attach_type, false);
1247 cgroup_put(cgrp);
1248 break; 1252 break;
1249 case BPF_SK_SKB_STREAM_PARSER: 1253 case BPF_SK_SKB_STREAM_PARSER:
1250 case BPF_SK_SKB_STREAM_VERDICT: 1254 case BPF_SK_SKB_STREAM_VERDICT:
1251 ret = sockmap_get_from_fd(attr, false); 1255 return sockmap_get_from_fd(attr, false);
1252 break;
1253 default: 1256 default:
1254 return -EINVAL; 1257 return -EINVAL;
1255 } 1258 }
1256 1259
1260 cgrp = cgroup_get_from_fd(attr->target_fd);
1261 if (IS_ERR(cgrp))
1262 return PTR_ERR(cgrp);
1263
1264 prog = bpf_prog_get_type(attr->attach_bpf_fd, ptype);
1265 if (IS_ERR(prog))
1266 prog = NULL;
1267
1268 ret = cgroup_bpf_detach(cgrp, prog, attr->attach_type, 0);
1269 if (prog)
1270 bpf_prog_put(prog);
1271 cgroup_put(cgrp);
1257 return ret; 1272 return ret;
1258} 1273}
1259 1274