aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/alpha/include/uapi/asm/socket.h3
-rw-r--r--arch/avr32/include/uapi/asm/socket.h3
-rw-r--r--arch/cris/include/uapi/asm/socket.h3
-rw-r--r--arch/frv/include/uapi/asm/socket.h3
-rw-r--r--arch/ia64/include/uapi/asm/socket.h3
-rw-r--r--arch/m32r/include/uapi/asm/socket.h3
-rw-r--r--arch/mips/include/uapi/asm/socket.h3
-rw-r--r--arch/mn10300/include/uapi/asm/socket.h3
-rw-r--r--arch/parisc/include/uapi/asm/socket.h3
-rw-r--r--arch/powerpc/include/uapi/asm/socket.h3
-rw-r--r--arch/s390/include/uapi/asm/socket.h3
-rw-r--r--arch/sparc/include/uapi/asm/socket.h3
-rw-r--r--arch/xtensa/include/uapi/asm/socket.h3
-rw-r--r--include/linux/bpf.h4
-rw-r--r--include/linux/filter.h1
-rw-r--r--include/uapi/asm-generic/socket.h3
-rw-r--r--net/core/filter.c97
-rw-r--r--net/core/sock.c13
18 files changed, 155 insertions, 2 deletions
diff --git a/arch/alpha/include/uapi/asm/socket.h b/arch/alpha/include/uapi/asm/socket.h
index e2fe0700b3b4..9a20821b111c 100644
--- a/arch/alpha/include/uapi/asm/socket.h
+++ b/arch/alpha/include/uapi/asm/socket.h
@@ -89,4 +89,7 @@
89 89
90#define SO_INCOMING_CPU 49 90#define SO_INCOMING_CPU 49
91 91
92#define SO_ATTACH_BPF 50
93#define SO_DETACH_BPF SO_DETACH_FILTER
94
92#endif /* _UAPI_ASM_SOCKET_H */ 95#endif /* _UAPI_ASM_SOCKET_H */
diff --git a/arch/avr32/include/uapi/asm/socket.h b/arch/avr32/include/uapi/asm/socket.h
index 92121b0f5b98..2b65ed6b277c 100644
--- a/arch/avr32/include/uapi/asm/socket.h
+++ b/arch/avr32/include/uapi/asm/socket.h
@@ -82,4 +82,7 @@
82 82
83#define SO_INCOMING_CPU 49 83#define SO_INCOMING_CPU 49
84 84
85#define SO_ATTACH_BPF 50
86#define SO_DETACH_BPF SO_DETACH_FILTER
87
85#endif /* _UAPI__ASM_AVR32_SOCKET_H */ 88#endif /* _UAPI__ASM_AVR32_SOCKET_H */
diff --git a/arch/cris/include/uapi/asm/socket.h b/arch/cris/include/uapi/asm/socket.h
index 60f60f5b9b35..e2503d9f1869 100644
--- a/arch/cris/include/uapi/asm/socket.h
+++ b/arch/cris/include/uapi/asm/socket.h
@@ -84,6 +84,9 @@
84 84
85#define SO_INCOMING_CPU 49 85#define SO_INCOMING_CPU 49
86 86
87#define SO_ATTACH_BPF 50
88#define SO_DETACH_BPF SO_DETACH_FILTER
89
87#endif /* _ASM_SOCKET_H */ 90#endif /* _ASM_SOCKET_H */
88 91
89 92
diff --git a/arch/frv/include/uapi/asm/socket.h b/arch/frv/include/uapi/asm/socket.h
index 2c6890209ea6..4823ad125578 100644
--- a/arch/frv/include/uapi/asm/socket.h
+++ b/arch/frv/include/uapi/asm/socket.h
@@ -82,5 +82,8 @@
82 82
83#define SO_INCOMING_CPU 49 83#define SO_INCOMING_CPU 49
84 84
85#define SO_ATTACH_BPF 50
86#define SO_DETACH_BPF SO_DETACH_FILTER
87
85#endif /* _ASM_SOCKET_H */ 88#endif /* _ASM_SOCKET_H */
86 89
diff --git a/arch/ia64/include/uapi/asm/socket.h b/arch/ia64/include/uapi/asm/socket.h
index 09a93fb566f6..59be3d87f86d 100644
--- a/arch/ia64/include/uapi/asm/socket.h
+++ b/arch/ia64/include/uapi/asm/socket.h
@@ -91,4 +91,7 @@
91 91
92#define SO_INCOMING_CPU 49 92#define SO_INCOMING_CPU 49
93 93
94#define SO_ATTACH_BPF 50
95#define SO_DETACH_BPF SO_DETACH_FILTER
96
94#endif /* _ASM_IA64_SOCKET_H */ 97#endif /* _ASM_IA64_SOCKET_H */
diff --git a/arch/m32r/include/uapi/asm/socket.h b/arch/m32r/include/uapi/asm/socket.h
index e8589819c274..7bc4cb273856 100644
--- a/arch/m32r/include/uapi/asm/socket.h
+++ b/arch/m32r/include/uapi/asm/socket.h
@@ -82,4 +82,7 @@
82 82
83#define SO_INCOMING_CPU 49 83#define SO_INCOMING_CPU 49
84 84
85#define SO_ATTACH_BPF 50
86#define SO_DETACH_BPF SO_DETACH_FILTER
87
85#endif /* _ASM_M32R_SOCKET_H */ 88#endif /* _ASM_M32R_SOCKET_H */
diff --git a/arch/mips/include/uapi/asm/socket.h b/arch/mips/include/uapi/asm/socket.h
index 2e9ee8c55a10..dec3c850f36b 100644
--- a/arch/mips/include/uapi/asm/socket.h
+++ b/arch/mips/include/uapi/asm/socket.h
@@ -100,4 +100,7 @@
100 100
101#define SO_INCOMING_CPU 49 101#define SO_INCOMING_CPU 49
102 102
103#define SO_ATTACH_BPF 50
104#define SO_DETACH_BPF SO_DETACH_FILTER
105
103#endif /* _UAPI_ASM_SOCKET_H */ 106#endif /* _UAPI_ASM_SOCKET_H */
diff --git a/arch/mn10300/include/uapi/asm/socket.h b/arch/mn10300/include/uapi/asm/socket.h
index f3492e8c9f70..cab7d6d50051 100644
--- a/arch/mn10300/include/uapi/asm/socket.h
+++ b/arch/mn10300/include/uapi/asm/socket.h
@@ -82,4 +82,7 @@
82 82
83#define SO_INCOMING_CPU 49 83#define SO_INCOMING_CPU 49
84 84
85#define SO_ATTACH_BPF 50
86#define SO_DETACH_BPF SO_DETACH_FILTER
87
85#endif /* _ASM_SOCKET_H */ 88#endif /* _ASM_SOCKET_H */
diff --git a/arch/parisc/include/uapi/asm/socket.h b/arch/parisc/include/uapi/asm/socket.h
index 7984a1cab3da..a5cd40cd8ee1 100644
--- a/arch/parisc/include/uapi/asm/socket.h
+++ b/arch/parisc/include/uapi/asm/socket.h
@@ -81,4 +81,7 @@
81 81
82#define SO_INCOMING_CPU 0x402A 82#define SO_INCOMING_CPU 0x402A
83 83
84#define SO_ATTACH_BPF 0x402B
85#define SO_DETACH_BPF SO_DETACH_FILTER
86
84#endif /* _UAPI_ASM_SOCKET_H */ 87#endif /* _UAPI_ASM_SOCKET_H */
diff --git a/arch/powerpc/include/uapi/asm/socket.h b/arch/powerpc/include/uapi/asm/socket.h
index 3474e4ef166d..c046666038f8 100644
--- a/arch/powerpc/include/uapi/asm/socket.h
+++ b/arch/powerpc/include/uapi/asm/socket.h
@@ -89,4 +89,7 @@
89 89
90#define SO_INCOMING_CPU 49 90#define SO_INCOMING_CPU 49
91 91
92#define SO_ATTACH_BPF 50
93#define SO_DETACH_BPF SO_DETACH_FILTER
94
92#endif /* _ASM_POWERPC_SOCKET_H */ 95#endif /* _ASM_POWERPC_SOCKET_H */
diff --git a/arch/s390/include/uapi/asm/socket.h b/arch/s390/include/uapi/asm/socket.h
index 8457636c33e1..296942d56e6a 100644
--- a/arch/s390/include/uapi/asm/socket.h
+++ b/arch/s390/include/uapi/asm/socket.h
@@ -88,4 +88,7 @@
88 88
89#define SO_INCOMING_CPU 49 89#define SO_INCOMING_CPU 49
90 90
91#define SO_ATTACH_BPF 50
92#define SO_DETACH_BPF SO_DETACH_FILTER
93
91#endif /* _ASM_SOCKET_H */ 94#endif /* _ASM_SOCKET_H */
diff --git a/arch/sparc/include/uapi/asm/socket.h b/arch/sparc/include/uapi/asm/socket.h
index 4a8003a94163..e6a16c40be5f 100644
--- a/arch/sparc/include/uapi/asm/socket.h
+++ b/arch/sparc/include/uapi/asm/socket.h
@@ -78,6 +78,9 @@
78 78
79#define SO_INCOMING_CPU 0x0033 79#define SO_INCOMING_CPU 0x0033
80 80
81#define SO_ATTACH_BPF 0x0034
82#define SO_DETACH_BPF SO_DETACH_FILTER
83
81/* Security levels - as per NRL IPv6 - don't actually do anything */ 84/* Security levels - as per NRL IPv6 - don't actually do anything */
82#define SO_SECURITY_AUTHENTICATION 0x5001 85#define SO_SECURITY_AUTHENTICATION 0x5001
83#define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002 86#define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002
diff --git a/arch/xtensa/include/uapi/asm/socket.h b/arch/xtensa/include/uapi/asm/socket.h
index c46f6a696849..4120af086160 100644
--- a/arch/xtensa/include/uapi/asm/socket.h
+++ b/arch/xtensa/include/uapi/asm/socket.h
@@ -93,4 +93,7 @@
93 93
94#define SO_INCOMING_CPU 49 94#define SO_INCOMING_CPU 49
95 95
96#define SO_ATTACH_BPF 50
97#define SO_DETACH_BPF SO_DETACH_FILTER
98
96#endif /* _XTENSA_SOCKET_H */ 99#endif /* _XTENSA_SOCKET_H */
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 75e94eaa228b..bbfceb756452 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -128,7 +128,11 @@ struct bpf_prog_aux {
128 struct work_struct work; 128 struct work_struct work;
129}; 129};
130 130
131#ifdef CONFIG_BPF_SYSCALL
131void bpf_prog_put(struct bpf_prog *prog); 132void bpf_prog_put(struct bpf_prog *prog);
133#else
134static inline void bpf_prog_put(struct bpf_prog *prog) {}
135#endif
132struct bpf_prog *bpf_prog_get(u32 ufd); 136struct bpf_prog *bpf_prog_get(u32 ufd);
133/* verify correctness of eBPF program */ 137/* verify correctness of eBPF program */
134int bpf_check(struct bpf_prog *fp, union bpf_attr *attr); 138int bpf_check(struct bpf_prog *fp, union bpf_attr *attr);
diff --git a/include/linux/filter.h b/include/linux/filter.h
index ca95abd2bed1..caac2087a4d5 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -381,6 +381,7 @@ int bpf_prog_create(struct bpf_prog **pfp, struct sock_fprog_kern *fprog);
381void bpf_prog_destroy(struct bpf_prog *fp); 381void bpf_prog_destroy(struct bpf_prog *fp);
382 382
383int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk); 383int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk);
384int sk_attach_bpf(u32 ufd, struct sock *sk);
384int sk_detach_filter(struct sock *sk); 385int sk_detach_filter(struct sock *sk);
385 386
386int bpf_check_classic(const struct sock_filter *filter, unsigned int flen); 387int bpf_check_classic(const struct sock_filter *filter, unsigned int flen);
diff --git a/include/uapi/asm-generic/socket.h b/include/uapi/asm-generic/socket.h
index f541ccefd4ac..5c15c2a5c123 100644
--- a/include/uapi/asm-generic/socket.h
+++ b/include/uapi/asm-generic/socket.h
@@ -84,4 +84,7 @@
84 84
85#define SO_INCOMING_CPU 49 85#define SO_INCOMING_CPU 49
86 86
87#define SO_ATTACH_BPF 50
88#define SO_DETACH_BPF SO_DETACH_FILTER
89
87#endif /* __ASM_GENERIC_SOCKET_H */ 90#endif /* __ASM_GENERIC_SOCKET_H */
diff --git a/net/core/filter.c b/net/core/filter.c
index 647b12265e18..8cc3c03078b3 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -44,6 +44,7 @@
44#include <linux/ratelimit.h> 44#include <linux/ratelimit.h>
45#include <linux/seccomp.h> 45#include <linux/seccomp.h>
46#include <linux/if_vlan.h> 46#include <linux/if_vlan.h>
47#include <linux/bpf.h>
47 48
48/** 49/**
49 * sk_filter - run a packet through a socket filter 50 * sk_filter - run a packet through a socket filter
@@ -813,8 +814,12 @@ static void bpf_release_orig_filter(struct bpf_prog *fp)
813 814
814static void __bpf_prog_release(struct bpf_prog *prog) 815static void __bpf_prog_release(struct bpf_prog *prog)
815{ 816{
816 bpf_release_orig_filter(prog); 817 if (prog->aux->prog_type == BPF_PROG_TYPE_SOCKET_FILTER) {
817 bpf_prog_free(prog); 818 bpf_prog_put(prog);
819 } else {
820 bpf_release_orig_filter(prog);
821 bpf_prog_free(prog);
822 }
818} 823}
819 824
820static void __sk_filter_release(struct sk_filter *fp) 825static void __sk_filter_release(struct sk_filter *fp)
@@ -1088,6 +1093,94 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)
1088} 1093}
1089EXPORT_SYMBOL_GPL(sk_attach_filter); 1094EXPORT_SYMBOL_GPL(sk_attach_filter);
1090 1095
1096#ifdef CONFIG_BPF_SYSCALL
1097int sk_attach_bpf(u32 ufd, struct sock *sk)
1098{
1099 struct sk_filter *fp, *old_fp;
1100 struct bpf_prog *prog;
1101
1102 if (sock_flag(sk, SOCK_FILTER_LOCKED))
1103 return -EPERM;
1104
1105 prog = bpf_prog_get(ufd);
1106 if (!prog)
1107 return -EINVAL;
1108
1109 if (prog->aux->prog_type != BPF_PROG_TYPE_SOCKET_FILTER) {
1110 /* valid fd, but invalid program type */
1111 bpf_prog_put(prog);
1112 return -EINVAL;
1113 }
1114
1115 fp = kmalloc(sizeof(*fp), GFP_KERNEL);
1116 if (!fp) {
1117 bpf_prog_put(prog);
1118 return -ENOMEM;
1119 }
1120 fp->prog = prog;
1121
1122 atomic_set(&fp->refcnt, 0);
1123
1124 if (!sk_filter_charge(sk, fp)) {
1125 __sk_filter_release(fp);
1126 return -ENOMEM;
1127 }
1128
1129 old_fp = rcu_dereference_protected(sk->sk_filter,
1130 sock_owned_by_user(sk));
1131 rcu_assign_pointer(sk->sk_filter, fp);
1132
1133 if (old_fp)
1134 sk_filter_uncharge(sk, old_fp);
1135
1136 return 0;
1137}
1138
1139/* allow socket filters to call
1140 * bpf_map_lookup_elem(), bpf_map_update_elem(), bpf_map_delete_elem()
1141 */
1142static const struct bpf_func_proto *sock_filter_func_proto(enum bpf_func_id func_id)
1143{
1144 switch (func_id) {
1145 case BPF_FUNC_map_lookup_elem:
1146 return &bpf_map_lookup_elem_proto;
1147 case BPF_FUNC_map_update_elem:
1148 return &bpf_map_update_elem_proto;
1149 case BPF_FUNC_map_delete_elem:
1150 return &bpf_map_delete_elem_proto;
1151 default:
1152 return NULL;
1153 }
1154}
1155
1156static bool sock_filter_is_valid_access(int off, int size, enum bpf_access_type type)
1157{
1158 /* skb fields cannot be accessed yet */
1159 return false;
1160}
1161
1162static struct bpf_verifier_ops sock_filter_ops = {
1163 .get_func_proto = sock_filter_func_proto,
1164 .is_valid_access = sock_filter_is_valid_access,
1165};
1166
1167static struct bpf_prog_type_list tl = {
1168 .ops = &sock_filter_ops,
1169 .type = BPF_PROG_TYPE_SOCKET_FILTER,
1170};
1171
1172static int __init register_sock_filter_ops(void)
1173{
1174 bpf_register_prog_type(&tl);
1175 return 0;
1176}
1177late_initcall(register_sock_filter_ops);
1178#else
1179int sk_attach_bpf(u32 ufd, struct sock *sk)
1180{
1181 return -EOPNOTSUPP;
1182}
1183#endif
1091int sk_detach_filter(struct sock *sk) 1184int sk_detach_filter(struct sock *sk)
1092{ 1185{
1093 int ret = -ENOENT; 1186 int ret = -ENOENT;
diff --git a/net/core/sock.c b/net/core/sock.c
index 0725cf0cb685..9a56b2000c3f 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -888,6 +888,19 @@ set_rcvbuf:
888 } 888 }
889 break; 889 break;
890 890
891 case SO_ATTACH_BPF:
892 ret = -EINVAL;
893 if (optlen == sizeof(u32)) {
894 u32 ufd;
895
896 ret = -EFAULT;
897 if (copy_from_user(&ufd, optval, sizeof(ufd)))
898 break;
899
900 ret = sk_attach_bpf(ufd, sk);
901 }
902 break;
903
891 case SO_DETACH_FILTER: 904 case SO_DETACH_FILTER:
892 ret = sk_detach_filter(sk); 905 ret = sk_detach_filter(sk);
893 break; 906 break;