aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Borkmann <daniel@iogearbox.net>2016-06-30 11:24:44 -0400
committerDavid S. Miller <davem@davemloft.net>2016-07-01 16:00:47 -0400
commit113214be7f6c98dd6d0435e4765aea8dea91662c (patch)
tree31d2c41c7af6991401c3aff11e7ade3317b4a614
parent1aacde3d22c42281236155c1ef6d7a5aa32a826b (diff)
bpf: refactor bpf_prog_get and type check into helper
Since bpf_prog_get() and program type check is used in a couple of places, refactor this into a small helper function that we can make use of. Since the non RO prog->aux part is not used in performance critical paths and a program destruction via RCU is rather very unlikley when doing the put, we shouldn't have an issue just doing the bpf_prog_get() + prog->type != type check, but actually not taking the ref at all (due to being in fdget() / fdput() section of the bpf fd) is even cleaner and makes the diff smaller as well, so just go for that. Callsites are changed to make use of the new helper where possible. Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/bpf.h7
-rw-r--r--kernel/bpf/syscall.c27
-rw-r--r--net/core/filter.c13
-rw-r--r--net/kcm/kcmsock.c8
-rw-r--r--net/packet/af_packet.c6
-rw-r--r--net/sched/act_bpf.c7
-rw-r--r--net/sched/cls_bpf.c7
7 files changed, 31 insertions, 44 deletions
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 749549888b86..b3336b4f5d04 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -218,6 +218,7 @@ void bpf_register_prog_type(struct bpf_prog_type_list *tl);
218void bpf_register_map_type(struct bpf_map_type_list *tl); 218void bpf_register_map_type(struct bpf_map_type_list *tl);
219 219
220struct bpf_prog *bpf_prog_get(u32 ufd); 220struct bpf_prog *bpf_prog_get(u32 ufd);
221struct bpf_prog *bpf_prog_get_type(u32 ufd, enum bpf_prog_type type);
221struct bpf_prog *bpf_prog_inc(struct bpf_prog *prog); 222struct bpf_prog *bpf_prog_inc(struct bpf_prog *prog);
222void bpf_prog_put(struct bpf_prog *prog); 223void bpf_prog_put(struct bpf_prog *prog);
223 224
@@ -277,6 +278,12 @@ static inline struct bpf_prog *bpf_prog_get(u32 ufd)
277 return ERR_PTR(-EOPNOTSUPP); 278 return ERR_PTR(-EOPNOTSUPP);
278} 279}
279 280
281static inline struct bpf_prog *bpf_prog_get_type(u32 ufd,
282 enum bpf_prog_type type)
283{
284 return ERR_PTR(-EOPNOTSUPP);
285}
286
280static inline void bpf_prog_put(struct bpf_prog *prog) 287static inline void bpf_prog_put(struct bpf_prog *prog)
281{ 288{
282} 289}
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index f6806a1d7ed9..22863d9872b1 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -657,7 +657,7 @@ int bpf_prog_new_fd(struct bpf_prog *prog)
657 O_RDWR | O_CLOEXEC); 657 O_RDWR | O_CLOEXEC);
658} 658}
659 659
660static struct bpf_prog *__bpf_prog_get(struct fd f) 660static struct bpf_prog *____bpf_prog_get(struct fd f)
661{ 661{
662 if (!f.file) 662 if (!f.file)
663 return ERR_PTR(-EBADF); 663 return ERR_PTR(-EBADF);
@@ -678,24 +678,35 @@ struct bpf_prog *bpf_prog_inc(struct bpf_prog *prog)
678 return prog; 678 return prog;
679} 679}
680 680
681/* called by sockets/tracing/seccomp before attaching program to an event 681static struct bpf_prog *__bpf_prog_get(u32 ufd, enum bpf_prog_type *type)
682 * pairs with bpf_prog_put()
683 */
684struct bpf_prog *bpf_prog_get(u32 ufd)
685{ 682{
686 struct fd f = fdget(ufd); 683 struct fd f = fdget(ufd);
687 struct bpf_prog *prog; 684 struct bpf_prog *prog;
688 685
689 prog = __bpf_prog_get(f); 686 prog = ____bpf_prog_get(f);
690 if (IS_ERR(prog)) 687 if (IS_ERR(prog))
691 return prog; 688 return prog;
689 if (type && prog->type != *type) {
690 prog = ERR_PTR(-EINVAL);
691 goto out;
692 }
692 693
693 prog = bpf_prog_inc(prog); 694 prog = bpf_prog_inc(prog);
695out:
694 fdput(f); 696 fdput(f);
695
696 return prog; 697 return prog;
697} 698}
698EXPORT_SYMBOL_GPL(bpf_prog_get); 699
700struct bpf_prog *bpf_prog_get(u32 ufd)
701{
702 return __bpf_prog_get(ufd, NULL);
703}
704
705struct bpf_prog *bpf_prog_get_type(u32 ufd, enum bpf_prog_type type)
706{
707 return __bpf_prog_get(ufd, &type);
708}
709EXPORT_SYMBOL_GPL(bpf_prog_get_type);
699 710
700/* last field in 'union bpf_attr' used by this command */ 711/* last field in 'union bpf_attr' used by this command */
701#define BPF_PROG_LOAD_LAST_FIELD kern_version 712#define BPF_PROG_LOAD_LAST_FIELD kern_version
diff --git a/net/core/filter.c b/net/core/filter.c
index 76f9a4938be4..76fee35da244 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -1301,21 +1301,10 @@ int sk_reuseport_attach_filter(struct sock_fprog *fprog, struct sock *sk)
1301 1301
1302static struct bpf_prog *__get_bpf(u32 ufd, struct sock *sk) 1302static struct bpf_prog *__get_bpf(u32 ufd, struct sock *sk)
1303{ 1303{
1304 struct bpf_prog *prog;
1305
1306 if (sock_flag(sk, SOCK_FILTER_LOCKED)) 1304 if (sock_flag(sk, SOCK_FILTER_LOCKED))
1307 return ERR_PTR(-EPERM); 1305 return ERR_PTR(-EPERM);
1308 1306
1309 prog = bpf_prog_get(ufd); 1307 return bpf_prog_get_type(ufd, BPF_PROG_TYPE_SOCKET_FILTER);
1310 if (IS_ERR(prog))
1311 return prog;
1312
1313 if (prog->type != BPF_PROG_TYPE_SOCKET_FILTER) {
1314 bpf_prog_put(prog);
1315 return ERR_PTR(-EINVAL);
1316 }
1317
1318 return prog;
1319} 1308}
1320 1309
1321int sk_attach_bpf(u32 ufd, struct sock *sk) 1310int sk_attach_bpf(u32 ufd, struct sock *sk)
diff --git a/net/kcm/kcmsock.c b/net/kcm/kcmsock.c
index 0b68ba730a06..cb39e05b166c 100644
--- a/net/kcm/kcmsock.c
+++ b/net/kcm/kcmsock.c
@@ -1765,18 +1765,12 @@ static int kcm_attach_ioctl(struct socket *sock, struct kcm_attach *info)
1765 if (!csock) 1765 if (!csock)
1766 return -ENOENT; 1766 return -ENOENT;
1767 1767
1768 prog = bpf_prog_get(info->bpf_fd); 1768 prog = bpf_prog_get_type(info->bpf_fd, BPF_PROG_TYPE_SOCKET_FILTER);
1769 if (IS_ERR(prog)) { 1769 if (IS_ERR(prog)) {
1770 err = PTR_ERR(prog); 1770 err = PTR_ERR(prog);
1771 goto out; 1771 goto out;
1772 } 1772 }
1773 1773
1774 if (prog->type != BPF_PROG_TYPE_SOCKET_FILTER) {
1775 bpf_prog_put(prog);
1776 err = -EINVAL;
1777 goto out;
1778 }
1779
1780 err = kcm_attach(sock, csock, prog); 1774 err = kcm_attach(sock, csock, prog);
1781 if (err) { 1775 if (err) {
1782 bpf_prog_put(prog); 1776 bpf_prog_put(prog);
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index d1f3b9e977e5..48b58957adf4 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -1588,13 +1588,9 @@ static int fanout_set_data_ebpf(struct packet_sock *po, char __user *data,
1588 if (copy_from_user(&fd, data, len)) 1588 if (copy_from_user(&fd, data, len))
1589 return -EFAULT; 1589 return -EFAULT;
1590 1590
1591 new = bpf_prog_get(fd); 1591 new = bpf_prog_get_type(fd, BPF_PROG_TYPE_SOCKET_FILTER);
1592 if (IS_ERR(new)) 1592 if (IS_ERR(new))
1593 return PTR_ERR(new); 1593 return PTR_ERR(new);
1594 if (new->type != BPF_PROG_TYPE_SOCKET_FILTER) {
1595 bpf_prog_put(new);
1596 return -EINVAL;
1597 }
1598 1594
1599 __fanout_set_data_bpf(po->fanout, new); 1595 __fanout_set_data_bpf(po->fanout, new);
1600 return 0; 1596 return 0;
diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c
index f7b6cf49ea6f..ef74bffa6101 100644
--- a/net/sched/act_bpf.c
+++ b/net/sched/act_bpf.c
@@ -223,15 +223,10 @@ static int tcf_bpf_init_from_efd(struct nlattr **tb, struct tcf_bpf_cfg *cfg)
223 223
224 bpf_fd = nla_get_u32(tb[TCA_ACT_BPF_FD]); 224 bpf_fd = nla_get_u32(tb[TCA_ACT_BPF_FD]);
225 225
226 fp = bpf_prog_get(bpf_fd); 226 fp = bpf_prog_get_type(bpf_fd, BPF_PROG_TYPE_SCHED_ACT);
227 if (IS_ERR(fp)) 227 if (IS_ERR(fp))
228 return PTR_ERR(fp); 228 return PTR_ERR(fp);
229 229
230 if (fp->type != BPF_PROG_TYPE_SCHED_ACT) {
231 bpf_prog_put(fp);
232 return -EINVAL;
233 }
234
235 if (tb[TCA_ACT_BPF_NAME]) { 230 if (tb[TCA_ACT_BPF_NAME]) {
236 name = kmemdup(nla_data(tb[TCA_ACT_BPF_NAME]), 231 name = kmemdup(nla_data(tb[TCA_ACT_BPF_NAME]),
237 nla_len(tb[TCA_ACT_BPF_NAME]), 232 nla_len(tb[TCA_ACT_BPF_NAME]),
diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c
index 7b342c779da7..c3002c2c68bb 100644
--- a/net/sched/cls_bpf.c
+++ b/net/sched/cls_bpf.c
@@ -272,15 +272,10 @@ static int cls_bpf_prog_from_efd(struct nlattr **tb, struct cls_bpf_prog *prog,
272 272
273 bpf_fd = nla_get_u32(tb[TCA_BPF_FD]); 273 bpf_fd = nla_get_u32(tb[TCA_BPF_FD]);
274 274
275 fp = bpf_prog_get(bpf_fd); 275 fp = bpf_prog_get_type(bpf_fd, BPF_PROG_TYPE_SCHED_CLS);
276 if (IS_ERR(fp)) 276 if (IS_ERR(fp))
277 return PTR_ERR(fp); 277 return PTR_ERR(fp);
278 278
279 if (fp->type != BPF_PROG_TYPE_SCHED_CLS) {
280 bpf_prog_put(fp);
281 return -EINVAL;
282 }
283
284 if (tb[TCA_BPF_NAME]) { 279 if (tb[TCA_BPF_NAME]) {
285 name = kmemdup(nla_data(tb[TCA_BPF_NAME]), 280 name = kmemdup(nla_data(tb[TCA_BPF_NAME]),
286 nla_len(tb[TCA_BPF_NAME]), 281 nla_len(tb[TCA_BPF_NAME]),