aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCong Wang <amwang@redhat.com>2013-01-17 03:34:11 -0500
committerSteffen Klassert <steffen.klassert@secunet.com>2013-01-17 04:03:57 -0500
commit7a9885b93bb623524468b37d04146d3422e099eb (patch)
tree11445bbd6fd8a3a1191dbf59d50c81f830f0cb7b
parent85168c0036fadf3657470b93cd9babeee8d123d7 (diff)
xfrm: use separated locks to protect pointers of struct xfrm_state_afinfo
afinfo->type_map and afinfo->mode_map deserve separated locks, they are different things. We should just take RCU read lock to protect afinfo itself, but not for the inner pointers. Cc: Steffen Klassert <steffen.klassert@secunet.com> Cc: Herbert Xu <herbert@gondor.apana.org.au> Cc: "David S. Miller" <davem@davemloft.net> Signed-off-by: Cong Wang <amwang@redhat.com> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
-rw-r--r--net/xfrm/xfrm_state.c43
1 files changed, 18 insertions, 25 deletions
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 1522f19f273a..0adae918a7a2 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -168,57 +168,45 @@ int __xfrm_state_delete(struct xfrm_state *x);
168int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol); 168int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol);
169void km_state_expired(struct xfrm_state *x, int hard, u32 portid); 169void km_state_expired(struct xfrm_state *x, int hard, u32 portid);
170 170
171static struct xfrm_state_afinfo *xfrm_state_lock_afinfo(unsigned int family) 171static DEFINE_SPINLOCK(xfrm_type_lock);
172{
173 struct xfrm_state_afinfo *afinfo;
174 if (unlikely(family >= NPROTO))
175 return NULL;
176 spin_lock_bh(&xfrm_state_afinfo_lock);
177 afinfo = xfrm_state_afinfo[family];
178 if (unlikely(!afinfo))
179 spin_unlock_bh(&xfrm_state_afinfo_lock);
180 return afinfo;
181}
182
183static void xfrm_state_unlock_afinfo(struct xfrm_state_afinfo *afinfo)
184{
185 spin_unlock_bh(&xfrm_state_afinfo_lock);
186}
187
188int xfrm_register_type(const struct xfrm_type *type, unsigned short family) 172int xfrm_register_type(const struct xfrm_type *type, unsigned short family)
189{ 173{
190 struct xfrm_state_afinfo *afinfo = xfrm_state_lock_afinfo(family); 174 struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
191 const struct xfrm_type **typemap; 175 const struct xfrm_type **typemap;
192 int err = 0; 176 int err = 0;
193 177
194 if (unlikely(afinfo == NULL)) 178 if (unlikely(afinfo == NULL))
195 return -EAFNOSUPPORT; 179 return -EAFNOSUPPORT;
196 typemap = afinfo->type_map; 180 typemap = afinfo->type_map;
181 spin_lock_bh(&xfrm_type_lock);
197 182
198 if (likely(typemap[type->proto] == NULL)) 183 if (likely(typemap[type->proto] == NULL))
199 typemap[type->proto] = type; 184 typemap[type->proto] = type;
200 else 185 else
201 err = -EEXIST; 186 err = -EEXIST;
202 xfrm_state_unlock_afinfo(afinfo); 187 spin_unlock_bh(&xfrm_type_lock);
188 xfrm_state_put_afinfo(afinfo);
203 return err; 189 return err;
204} 190}
205EXPORT_SYMBOL(xfrm_register_type); 191EXPORT_SYMBOL(xfrm_register_type);
206 192
207int xfrm_unregister_type(const struct xfrm_type *type, unsigned short family) 193int xfrm_unregister_type(const struct xfrm_type *type, unsigned short family)
208{ 194{
209 struct xfrm_state_afinfo *afinfo = xfrm_state_lock_afinfo(family); 195 struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
210 const struct xfrm_type **typemap; 196 const struct xfrm_type **typemap;
211 int err = 0; 197 int err = 0;
212 198
213 if (unlikely(afinfo == NULL)) 199 if (unlikely(afinfo == NULL))
214 return -EAFNOSUPPORT; 200 return -EAFNOSUPPORT;
215 typemap = afinfo->type_map; 201 typemap = afinfo->type_map;
202 spin_lock_bh(&xfrm_type_lock);
216 203
217 if (unlikely(typemap[type->proto] != type)) 204 if (unlikely(typemap[type->proto] != type))
218 err = -ENOENT; 205 err = -ENOENT;
219 else 206 else
220 typemap[type->proto] = NULL; 207 typemap[type->proto] = NULL;
221 xfrm_state_unlock_afinfo(afinfo); 208 spin_unlock_bh(&xfrm_type_lock);
209 xfrm_state_put_afinfo(afinfo);
222 return err; 210 return err;
223} 211}
224EXPORT_SYMBOL(xfrm_unregister_type); 212EXPORT_SYMBOL(xfrm_unregister_type);
@@ -255,6 +243,7 @@ static void xfrm_put_type(const struct xfrm_type *type)
255 module_put(type->owner); 243 module_put(type->owner);
256} 244}
257 245
246static DEFINE_SPINLOCK(xfrm_mode_lock);
258int xfrm_register_mode(struct xfrm_mode *mode, int family) 247int xfrm_register_mode(struct xfrm_mode *mode, int family)
259{ 248{
260 struct xfrm_state_afinfo *afinfo; 249 struct xfrm_state_afinfo *afinfo;
@@ -264,12 +253,13 @@ int xfrm_register_mode(struct xfrm_mode *mode, int family)
264 if (unlikely(mode->encap >= XFRM_MODE_MAX)) 253 if (unlikely(mode->encap >= XFRM_MODE_MAX))
265 return -EINVAL; 254 return -EINVAL;
266 255
267 afinfo = xfrm_state_lock_afinfo(family); 256 afinfo = xfrm_state_get_afinfo(family);
268 if (unlikely(afinfo == NULL)) 257 if (unlikely(afinfo == NULL))
269 return -EAFNOSUPPORT; 258 return -EAFNOSUPPORT;
270 259
271 err = -EEXIST; 260 err = -EEXIST;
272 modemap = afinfo->mode_map; 261 modemap = afinfo->mode_map;
262 spin_lock_bh(&xfrm_mode_lock);
273 if (modemap[mode->encap]) 263 if (modemap[mode->encap])
274 goto out; 264 goto out;
275 265
@@ -282,7 +272,8 @@ int xfrm_register_mode(struct xfrm_mode *mode, int family)
282 err = 0; 272 err = 0;
283 273
284out: 274out:
285 xfrm_state_unlock_afinfo(afinfo); 275 spin_unlock_bh(&xfrm_mode_lock);
276 xfrm_state_put_afinfo(afinfo);
286 return err; 277 return err;
287} 278}
288EXPORT_SYMBOL(xfrm_register_mode); 279EXPORT_SYMBOL(xfrm_register_mode);
@@ -296,19 +287,21 @@ int xfrm_unregister_mode(struct xfrm_mode *mode, int family)
296 if (unlikely(mode->encap >= XFRM_MODE_MAX)) 287 if (unlikely(mode->encap >= XFRM_MODE_MAX))
297 return -EINVAL; 288 return -EINVAL;
298 289
299 afinfo = xfrm_state_lock_afinfo(family); 290 afinfo = xfrm_state_get_afinfo(family);
300 if (unlikely(afinfo == NULL)) 291 if (unlikely(afinfo == NULL))
301 return -EAFNOSUPPORT; 292 return -EAFNOSUPPORT;
302 293
303 err = -ENOENT; 294 err = -ENOENT;
304 modemap = afinfo->mode_map; 295 modemap = afinfo->mode_map;
296 spin_lock_bh(&xfrm_mode_lock);
305 if (likely(modemap[mode->encap] == mode)) { 297 if (likely(modemap[mode->encap] == mode)) {
306 modemap[mode->encap] = NULL; 298 modemap[mode->encap] = NULL;
307 module_put(mode->afinfo->owner); 299 module_put(mode->afinfo->owner);
308 err = 0; 300 err = 0;
309 } 301 }
310 302
311 xfrm_state_unlock_afinfo(afinfo); 303 spin_unlock_bh(&xfrm_mode_lock);
304 xfrm_state_put_afinfo(afinfo);
312 return err; 305 return err;
313} 306}
314EXPORT_SYMBOL(xfrm_unregister_mode); 307EXPORT_SYMBOL(xfrm_unregister_mode);