diff options
-rw-r--r-- | arch/alpha/include/uapi/asm/socket.h | 3 | ||||
-rw-r--r-- | arch/avr32/include/uapi/asm/socket.h | 3 | ||||
-rw-r--r-- | arch/cris/include/uapi/asm/socket.h | 3 | ||||
-rw-r--r-- | arch/frv/include/uapi/asm/socket.h | 3 | ||||
-rw-r--r-- | arch/ia64/include/uapi/asm/socket.h | 3 | ||||
-rw-r--r-- | arch/m32r/include/uapi/asm/socket.h | 3 | ||||
-rw-r--r-- | arch/mips/include/uapi/asm/socket.h | 3 | ||||
-rw-r--r-- | arch/mn10300/include/uapi/asm/socket.h | 3 | ||||
-rw-r--r-- | arch/parisc/include/uapi/asm/socket.h | 3 | ||||
-rw-r--r-- | arch/powerpc/include/uapi/asm/socket.h | 3 | ||||
-rw-r--r-- | arch/s390/include/uapi/asm/socket.h | 3 | ||||
-rw-r--r-- | arch/sparc/include/uapi/asm/socket.h | 3 | ||||
-rw-r--r-- | arch/xtensa/include/uapi/asm/socket.h | 3 | ||||
-rw-r--r-- | include/linux/bpf.h | 4 | ||||
-rw-r--r-- | include/linux/filter.h | 1 | ||||
-rw-r--r-- | include/uapi/asm-generic/socket.h | 3 | ||||
-rw-r--r-- | net/core/filter.c | 97 | ||||
-rw-r--r-- | net/core/sock.c | 13 |
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 | ||
131 | void bpf_prog_put(struct bpf_prog *prog); | 132 | void bpf_prog_put(struct bpf_prog *prog); |
133 | #else | ||
134 | static inline void bpf_prog_put(struct bpf_prog *prog) {} | ||
135 | #endif | ||
132 | struct bpf_prog *bpf_prog_get(u32 ufd); | 136 | struct bpf_prog *bpf_prog_get(u32 ufd); |
133 | /* verify correctness of eBPF program */ | 137 | /* verify correctness of eBPF program */ |
134 | int bpf_check(struct bpf_prog *fp, union bpf_attr *attr); | 138 | int 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); | |||
381 | void bpf_prog_destroy(struct bpf_prog *fp); | 381 | void bpf_prog_destroy(struct bpf_prog *fp); |
382 | 382 | ||
383 | int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk); | 383 | int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk); |
384 | int sk_attach_bpf(u32 ufd, struct sock *sk); | ||
384 | int sk_detach_filter(struct sock *sk); | 385 | int sk_detach_filter(struct sock *sk); |
385 | 386 | ||
386 | int bpf_check_classic(const struct sock_filter *filter, unsigned int flen); | 387 | int 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 | ||
814 | static void __bpf_prog_release(struct bpf_prog *prog) | 815 | static 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 | ||
820 | static void __sk_filter_release(struct sk_filter *fp) | 825 | static 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 | } |
1089 | EXPORT_SYMBOL_GPL(sk_attach_filter); | 1094 | EXPORT_SYMBOL_GPL(sk_attach_filter); |
1090 | 1095 | ||
1096 | #ifdef CONFIG_BPF_SYSCALL | ||
1097 | int 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 | */ | ||
1142 | static 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 | |||
1156 | static 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 | |||
1162 | static 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 | |||
1167 | static struct bpf_prog_type_list tl = { | ||
1168 | .ops = &sock_filter_ops, | ||
1169 | .type = BPF_PROG_TYPE_SOCKET_FILTER, | ||
1170 | }; | ||
1171 | |||
1172 | static int __init register_sock_filter_ops(void) | ||
1173 | { | ||
1174 | bpf_register_prog_type(&tl); | ||
1175 | return 0; | ||
1176 | } | ||
1177 | late_initcall(register_sock_filter_ops); | ||
1178 | #else | ||
1179 | int sk_attach_bpf(u32 ufd, struct sock *sk) | ||
1180 | { | ||
1181 | return -EOPNOTSUPP; | ||
1182 | } | ||
1183 | #endif | ||
1091 | int sk_detach_filter(struct sock *sk) | 1184 | int 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; |