diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2011-12-13 06:38:00 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-12-14 02:39:29 -0500 |
commit | c63044f0d22a13532047ad04216af45b6ac7fdaf (patch) | |
tree | f2d7dbcfd8139ef77fcd480176fd9c71b5a0d282 /net/core/rtnetlink.c | |
parent | b43faac69062f0fc75bd3230d67da64e184232d1 (diff) |
rtnetlink: rtnl_link_register() sanity test
Before adding a struct rtnl_link_ops into link_ops list, check it doesnt
clash with a prior one.
Based on a previous patch from Alexander Smirnov
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
CC: Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core/rtnetlink.c')
-rw-r--r-- | net/core/rtnetlink.c | 25 |
1 files changed, 14 insertions, 11 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 9083e82bdae5..dbf2ddafd52d 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -273,6 +273,17 @@ EXPORT_SYMBOL_GPL(rtnl_unregister_all); | |||
273 | 273 | ||
274 | static LIST_HEAD(link_ops); | 274 | static LIST_HEAD(link_ops); |
275 | 275 | ||
276 | static const struct rtnl_link_ops *rtnl_link_ops_get(const char *kind) | ||
277 | { | ||
278 | const struct rtnl_link_ops *ops; | ||
279 | |||
280 | list_for_each_entry(ops, &link_ops, list) { | ||
281 | if (!strcmp(ops->kind, kind)) | ||
282 | return ops; | ||
283 | } | ||
284 | return NULL; | ||
285 | } | ||
286 | |||
276 | /** | 287 | /** |
277 | * __rtnl_link_register - Register rtnl_link_ops with rtnetlink. | 288 | * __rtnl_link_register - Register rtnl_link_ops with rtnetlink. |
278 | * @ops: struct rtnl_link_ops * to register | 289 | * @ops: struct rtnl_link_ops * to register |
@@ -285,6 +296,9 @@ static LIST_HEAD(link_ops); | |||
285 | */ | 296 | */ |
286 | int __rtnl_link_register(struct rtnl_link_ops *ops) | 297 | int __rtnl_link_register(struct rtnl_link_ops *ops) |
287 | { | 298 | { |
299 | if (rtnl_link_ops_get(ops->kind)) | ||
300 | return -EEXIST; | ||
301 | |||
288 | if (!ops->dellink) | 302 | if (!ops->dellink) |
289 | ops->dellink = unregister_netdevice_queue; | 303 | ops->dellink = unregister_netdevice_queue; |
290 | 304 | ||
@@ -351,17 +365,6 @@ void rtnl_link_unregister(struct rtnl_link_ops *ops) | |||
351 | } | 365 | } |
352 | EXPORT_SYMBOL_GPL(rtnl_link_unregister); | 366 | EXPORT_SYMBOL_GPL(rtnl_link_unregister); |
353 | 367 | ||
354 | static const struct rtnl_link_ops *rtnl_link_ops_get(const char *kind) | ||
355 | { | ||
356 | const struct rtnl_link_ops *ops; | ||
357 | |||
358 | list_for_each_entry(ops, &link_ops, list) { | ||
359 | if (!strcmp(ops->kind, kind)) | ||
360 | return ops; | ||
361 | } | ||
362 | return NULL; | ||
363 | } | ||
364 | |||
365 | static size_t rtnl_link_get_size(const struct net_device *dev) | 368 | static size_t rtnl_link_get_size(const struct net_device *dev) |
366 | { | 369 | { |
367 | const struct rtnl_link_ops *ops = dev->rtnl_link_ops; | 370 | const struct rtnl_link_ops *ops = dev->rtnl_link_ops; |