31
31
#include <net/netfilter/nf_conntrack_core.h>
32
32
#include <net/netfilter/nf_conntrack_labels.h>
33
33
#endif
34
+ #include <linux/bpf-netns.h>
34
35
35
- static DEFINE_MUTEX (flow_dissector_mutex );
36
+ /* Protects updates to netns_bpf */
37
+ DEFINE_MUTEX (netns_bpf_mutex );
36
38
37
39
static void dissector_set_key (struct flow_dissector * flow_dissector ,
38
40
enum flow_dissector_key_id key_id )
@@ -70,23 +72,28 @@ void skb_flow_dissector_init(struct flow_dissector *flow_dissector,
70
72
}
71
73
EXPORT_SYMBOL (skb_flow_dissector_init );
72
74
73
- int skb_flow_dissector_prog_query (const union bpf_attr * attr ,
74
- union bpf_attr __user * uattr )
75
+ int netns_bpf_prog_query (const union bpf_attr * attr ,
76
+ union bpf_attr __user * uattr )
75
77
{
76
78
__u32 __user * prog_ids = u64_to_user_ptr (attr -> query .prog_ids );
77
79
u32 prog_id , prog_cnt = 0 , flags = 0 ;
80
+ enum netns_bpf_attach_type type ;
78
81
struct bpf_prog * attached ;
79
82
struct net * net ;
80
83
81
84
if (attr -> query .query_flags )
82
85
return - EINVAL ;
83
86
87
+ type = to_netns_bpf_attach_type (attr -> query .attach_type );
88
+ if (type < 0 )
89
+ return - EINVAL ;
90
+
84
91
net = get_net_ns_by_fd (attr -> query .target_fd );
85
92
if (IS_ERR (net ))
86
93
return PTR_ERR (net );
87
94
88
95
rcu_read_lock ();
89
- attached = rcu_dereference (net -> flow_dissector_prog );
96
+ attached = rcu_dereference (net -> bpf . progs [ type ] );
90
97
if (attached ) {
91
98
prog_cnt = 1 ;
92
99
prog_id = attached -> aux -> id ;
@@ -112,6 +119,7 @@ int skb_flow_dissector_prog_query(const union bpf_attr *attr,
112
119
static int flow_dissector_bpf_prog_attach (struct net * net ,
113
120
struct bpf_prog * prog )
114
121
{
122
+ enum netns_bpf_attach_type type = NETNS_BPF_FLOW_DISSECTOR ;
115
123
struct bpf_prog * attached ;
116
124
117
125
if (net == & init_net ) {
@@ -125,74 +133,97 @@ static int flow_dissector_bpf_prog_attach(struct net *net,
125
133
for_each_net (ns ) {
126
134
if (ns == & init_net )
127
135
continue ;
128
- if (rcu_access_pointer (ns -> flow_dissector_prog ))
136
+ if (rcu_access_pointer (ns -> bpf . progs [ type ] ))
129
137
return - EEXIST ;
130
138
}
131
139
} else {
132
140
/* Make sure root flow dissector is not attached
133
141
* when attaching to the non-root namespace.
134
142
*/
135
- if (rcu_access_pointer (init_net .flow_dissector_prog ))
143
+ if (rcu_access_pointer (init_net .bpf . progs [ type ] ))
136
144
return - EEXIST ;
137
145
}
138
146
139
- attached = rcu_dereference_protected (net -> flow_dissector_prog ,
140
- lockdep_is_held (& flow_dissector_mutex ));
147
+ attached = rcu_dereference_protected (net -> bpf . progs [ type ] ,
148
+ lockdep_is_held (& netns_bpf_mutex ));
141
149
if (attached == prog )
142
150
/* The same program cannot be attached twice */
143
151
return - EINVAL ;
144
152
145
- rcu_assign_pointer (net -> flow_dissector_prog , prog );
153
+ rcu_assign_pointer (net -> bpf . progs [ type ] , prog );
146
154
if (attached )
147
155
bpf_prog_put (attached );
148
156
return 0 ;
149
157
}
150
158
151
- int skb_flow_dissector_bpf_prog_attach (const union bpf_attr * attr ,
152
- struct bpf_prog * prog )
159
+ int netns_bpf_prog_attach (const union bpf_attr * attr , struct bpf_prog * prog )
153
160
{
161
+ enum netns_bpf_attach_type type ;
162
+ struct net * net ;
154
163
int ret ;
155
164
156
- mutex_lock (& flow_dissector_mutex );
157
- ret = flow_dissector_bpf_prog_attach (current -> nsproxy -> net_ns , prog );
158
- mutex_unlock (& flow_dissector_mutex );
165
+ type = to_netns_bpf_attach_type (attr -> attach_type );
166
+ if (type < 0 )
167
+ return - EINVAL ;
168
+
169
+ net = current -> nsproxy -> net_ns ;
170
+ mutex_lock (& netns_bpf_mutex );
171
+ switch (type ) {
172
+ case NETNS_BPF_FLOW_DISSECTOR :
173
+ ret = flow_dissector_bpf_prog_attach (net , prog );
174
+ break ;
175
+ default :
176
+ ret = - EINVAL ;
177
+ break ;
178
+ }
179
+ mutex_unlock (& netns_bpf_mutex );
159
180
160
181
return ret ;
161
182
}
162
183
163
- static int flow_dissector_bpf_prog_detach (struct net * net )
184
+ /* Must be called with netns_bpf_mutex held. */
185
+ static int __netns_bpf_prog_detach (struct net * net ,
186
+ enum netns_bpf_attach_type type )
164
187
{
165
188
struct bpf_prog * attached ;
166
189
167
- mutex_lock (& flow_dissector_mutex );
168
- attached = rcu_dereference_protected (net -> flow_dissector_prog ,
169
- lockdep_is_held (& flow_dissector_mutex ));
170
- if (!attached ) {
171
- mutex_unlock (& flow_dissector_mutex );
190
+ attached = rcu_dereference_protected (net -> bpf .progs [type ],
191
+ lockdep_is_held (& netns_bpf_mutex ));
192
+ if (!attached )
172
193
return - ENOENT ;
173
- }
174
- RCU_INIT_POINTER (net -> flow_dissector_prog , NULL );
194
+ RCU_INIT_POINTER (net -> bpf .progs [type ], NULL );
175
195
bpf_prog_put (attached );
176
- mutex_unlock (& flow_dissector_mutex );
177
196
return 0 ;
178
197
}
179
198
180
- int skb_flow_dissector_bpf_prog_detach (const union bpf_attr * attr )
199
+ int netns_bpf_prog_detach (const union bpf_attr * attr )
181
200
{
182
- return flow_dissector_bpf_prog_detach (current -> nsproxy -> net_ns );
201
+ enum netns_bpf_attach_type type ;
202
+ int ret ;
203
+
204
+ type = to_netns_bpf_attach_type (attr -> attach_type );
205
+ if (type < 0 )
206
+ return - EINVAL ;
207
+
208
+ mutex_lock (& netns_bpf_mutex );
209
+ ret = __netns_bpf_prog_detach (current -> nsproxy -> net_ns , type );
210
+ mutex_unlock (& netns_bpf_mutex );
211
+
212
+ return ret ;
183
213
}
184
214
185
- static void __net_exit flow_dissector_pernet_pre_exit (struct net * net )
215
+ static void __net_exit netns_bpf_pernet_pre_exit (struct net * net )
186
216
{
187
- /* We're not racing with attach/detach because there are no
188
- * references to netns left when pre_exit gets called.
189
- */
190
- if (rcu_access_pointer (net -> flow_dissector_prog ))
191
- flow_dissector_bpf_prog_detach (net );
217
+ enum netns_bpf_attach_type type ;
218
+
219
+ mutex_lock (& netns_bpf_mutex );
220
+ for (type = 0 ; type < MAX_NETNS_BPF_ATTACH_TYPE ; type ++ )
221
+ __netns_bpf_prog_detach (net , type );
222
+ mutex_unlock (& netns_bpf_mutex );
192
223
}
193
224
194
- static struct pernet_operations flow_dissector_pernet_ops __net_initdata = {
195
- .pre_exit = flow_dissector_pernet_pre_exit ,
225
+ static struct pernet_operations netns_bpf_pernet_ops __net_initdata = {
226
+ .pre_exit = netns_bpf_pernet_pre_exit ,
196
227
};
197
228
198
229
/**
@@ -1044,11 +1075,13 @@ bool __skb_flow_dissect(const struct net *net,
1044
1075
1045
1076
WARN_ON_ONCE (!net );
1046
1077
if (net ) {
1078
+ enum netns_bpf_attach_type type = NETNS_BPF_FLOW_DISSECTOR ;
1079
+
1047
1080
rcu_read_lock ();
1048
- attached = rcu_dereference (init_net .flow_dissector_prog );
1081
+ attached = rcu_dereference (init_net .bpf . progs [ type ] );
1049
1082
1050
1083
if (!attached )
1051
- attached = rcu_dereference (net -> flow_dissector_prog );
1084
+ attached = rcu_dereference (net -> bpf . progs [ type ] );
1052
1085
1053
1086
if (attached ) {
1054
1087
struct bpf_flow_keys flow_keys ;
@@ -1870,6 +1903,6 @@ static int __init init_default_flow_dissectors(void)
1870
1903
flow_keys_basic_dissector_keys ,
1871
1904
ARRAY_SIZE (flow_keys_basic_dissector_keys ));
1872
1905
1873
- return register_pernet_subsys (& flow_dissector_pernet_ops );
1906
+ return register_pernet_subsys (& netns_bpf_pernet_ops );
1874
1907
}
1875
1908
core_initcall (init_default_flow_dissectors );
0 commit comments