ematch.c (f43dc23d5ea91fca257be02138a255f02d98e806) | ematch.c (cc7ec456f82da7f89a5b376e613b3ac4311b3e9a) |
---|---|
1/* 2 * net/sched/ematch.c Extended Match API 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 7 * 2 of the License, or (at your option) any later version. 8 * --- 79 unchanged lines hidden (view full) --- 88#include <linux/errno.h> 89#include <linux/rtnetlink.h> 90#include <linux/skbuff.h> 91#include <net/pkt_cls.h> 92 93static LIST_HEAD(ematch_ops); 94static DEFINE_RWLOCK(ematch_mod_lock); 95 | 1/* 2 * net/sched/ematch.c Extended Match API 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 7 * 2 of the License, or (at your option) any later version. 8 * --- 79 unchanged lines hidden (view full) --- 88#include <linux/errno.h> 89#include <linux/rtnetlink.h> 90#include <linux/skbuff.h> 91#include <net/pkt_cls.h> 92 93static LIST_HEAD(ematch_ops); 94static DEFINE_RWLOCK(ematch_mod_lock); 95 |
96static inline struct tcf_ematch_ops * tcf_em_lookup(u16 kind) | 96static struct tcf_ematch_ops *tcf_em_lookup(u16 kind) |
97{ 98 struct tcf_ematch_ops *e = NULL; 99 100 read_lock(&ematch_mod_lock); 101 list_for_each_entry(e, &ematch_ops, link) { 102 if (kind == e->kind) { 103 if (!try_module_get(e->owner)) 104 e = NULL; --- 53 unchanged lines hidden (view full) --- 158void tcf_em_unregister(struct tcf_ematch_ops *ops) 159{ 160 write_lock(&ematch_mod_lock); 161 list_del(&ops->link); 162 write_unlock(&ematch_mod_lock); 163} 164EXPORT_SYMBOL(tcf_em_unregister); 165 | 97{ 98 struct tcf_ematch_ops *e = NULL; 99 100 read_lock(&ematch_mod_lock); 101 list_for_each_entry(e, &ematch_ops, link) { 102 if (kind == e->kind) { 103 if (!try_module_get(e->owner)) 104 e = NULL; --- 53 unchanged lines hidden (view full) --- 158void tcf_em_unregister(struct tcf_ematch_ops *ops) 159{ 160 write_lock(&ematch_mod_lock); 161 list_del(&ops->link); 162 write_unlock(&ematch_mod_lock); 163} 164EXPORT_SYMBOL(tcf_em_unregister); 165 |
166static inline struct tcf_ematch * tcf_em_get_match(struct tcf_ematch_tree *tree, 167 int index) | 166static inline struct tcf_ematch *tcf_em_get_match(struct tcf_ematch_tree *tree, 167 int index) |
168{ 169 return &tree->matches[index]; 170} 171 172 173static int tcf_em_validate(struct tcf_proto *tp, 174 struct tcf_ematch_tree_hdr *tree_hdr, 175 struct tcf_ematch *em, struct nlattr *nla, int idx) 176{ 177 int err = -EINVAL; 178 struct tcf_ematch_hdr *em_hdr = nla_data(nla); 179 int data_len = nla_len(nla) - sizeof(*em_hdr); 180 void *data = (void *) em_hdr + sizeof(*em_hdr); 181 182 if (!TCF_EM_REL_VALID(em_hdr->flags)) 183 goto errout; 184 185 if (em_hdr->kind == TCF_EM_CONTAINER) { 186 /* Special ematch called "container", carries an index | 168{ 169 return &tree->matches[index]; 170} 171 172 173static int tcf_em_validate(struct tcf_proto *tp, 174 struct tcf_ematch_tree_hdr *tree_hdr, 175 struct tcf_ematch *em, struct nlattr *nla, int idx) 176{ 177 int err = -EINVAL; 178 struct tcf_ematch_hdr *em_hdr = nla_data(nla); 179 int data_len = nla_len(nla) - sizeof(*em_hdr); 180 void *data = (void *) em_hdr + sizeof(*em_hdr); 181 182 if (!TCF_EM_REL_VALID(em_hdr->flags)) 183 goto errout; 184 185 if (em_hdr->kind == TCF_EM_CONTAINER) { 186 /* Special ematch called "container", carries an index |
187 * referencing an external ematch sequence. */ | 187 * referencing an external ematch sequence. 188 */ |
188 u32 ref; 189 190 if (data_len < sizeof(ref)) 191 goto errout; 192 ref = *(u32 *) data; 193 194 if (ref >= tree_hdr->nmatches) 195 goto errout; 196 197 /* We do not allow backward jumps to avoid loops and jumps | 189 u32 ref; 190 191 if (data_len < sizeof(ref)) 192 goto errout; 193 ref = *(u32 *) data; 194 195 if (ref >= tree_hdr->nmatches) 196 goto errout; 197 198 /* We do not allow backward jumps to avoid loops and jumps |
198 * to our own position are of course illegal. */ | 199 * to our own position are of course illegal. 200 */ |
199 if (ref <= idx) 200 goto errout; 201 202 203 em->data = ref; 204 } else { 205 /* Note: This lookup will increase the module refcnt 206 * of the ematch module referenced. In case of a failure, 207 * a destroy function is called by the underlying layer 208 * which automatically releases the reference again, therefore 209 * the module MUST not be given back under any circumstances 210 * here. Be aware, the destroy function assumes that the | 201 if (ref <= idx) 202 goto errout; 203 204 205 em->data = ref; 206 } else { 207 /* Note: This lookup will increase the module refcnt 208 * of the ematch module referenced. In case of a failure, 209 * a destroy function is called by the underlying layer 210 * which automatically releases the reference again, therefore 211 * the module MUST not be given back under any circumstances 212 * here. Be aware, the destroy function assumes that the |
211 * module is held if the ops field is non zero. */ | 213 * module is held if the ops field is non zero. 214 */ |
212 em->ops = tcf_em_lookup(em_hdr->kind); 213 214 if (em->ops == NULL) { 215 err = -ENOENT; 216#ifdef CONFIG_MODULES 217 __rtnl_unlock(); 218 request_module("ematch-kind-%u", em_hdr->kind); 219 rtnl_lock(); 220 em->ops = tcf_em_lookup(em_hdr->kind); 221 if (em->ops) { 222 /* We dropped the RTNL mutex in order to 223 * perform the module load. Tell the caller | 215 em->ops = tcf_em_lookup(em_hdr->kind); 216 217 if (em->ops == NULL) { 218 err = -ENOENT; 219#ifdef CONFIG_MODULES 220 __rtnl_unlock(); 221 request_module("ematch-kind-%u", em_hdr->kind); 222 rtnl_lock(); 223 em->ops = tcf_em_lookup(em_hdr->kind); 224 if (em->ops) { 225 /* We dropped the RTNL mutex in order to 226 * perform the module load. Tell the caller |
224 * to replay the request. */ | 227 * to replay the request. 228 */ |
225 module_put(em->ops->owner); 226 err = -EAGAIN; 227 } 228#endif 229 goto errout; 230 } 231 232 /* ematch module provides expected length of data, so we | 229 module_put(em->ops->owner); 230 err = -EAGAIN; 231 } 232#endif 233 goto errout; 234 } 235 236 /* ematch module provides expected length of data, so we |
233 * can do a basic sanity check. */ | 237 * can do a basic sanity check. 238 */ |
234 if (em->ops->datalen && data_len < em->ops->datalen) 235 goto errout; 236 237 if (em->ops->change) { 238 err = em->ops->change(tp, data, data_len, em); 239 if (err < 0) 240 goto errout; 241 } else if (data_len > 0) { 242 /* ematch module doesn't provide an own change 243 * procedure and expects us to allocate and copy 244 * the ematch data. 245 * 246 * TCF_EM_SIMPLE may be specified stating that the 247 * data only consists of a u32 integer and the module 248 * does not expected a memory reference but rather | 239 if (em->ops->datalen && data_len < em->ops->datalen) 240 goto errout; 241 242 if (em->ops->change) { 243 err = em->ops->change(tp, data, data_len, em); 244 if (err < 0) 245 goto errout; 246 } else if (data_len > 0) { 247 /* ematch module doesn't provide an own change 248 * procedure and expects us to allocate and copy 249 * the ematch data. 250 * 251 * TCF_EM_SIMPLE may be specified stating that the 252 * data only consists of a u32 integer and the module 253 * does not expected a memory reference but rather |
249 * the value carried. */ | 254 * the value carried. 255 */ |
250 if (em_hdr->flags & TCF_EM_SIMPLE) { 251 if (data_len < sizeof(u32)) 252 goto errout; 253 em->data = *(u32 *) data; 254 } else { 255 void *v = kmemdup(data, data_len, GFP_KERNEL); 256 if (v == NULL) { 257 err = -ENOBUFS; --- 71 unchanged lines hidden (view full) --- 329 330 /* We do not use nla_parse_nested here because the maximum 331 * number of attributes is unknown. This saves us the allocation 332 * for a tb buffer which would serve no purpose at all. 333 * 334 * The array of rt attributes is parsed in the order as they are 335 * provided, their type must be incremental from 1 to n. Even 336 * if it does not serve any real purpose, a failure of sticking | 256 if (em_hdr->flags & TCF_EM_SIMPLE) { 257 if (data_len < sizeof(u32)) 258 goto errout; 259 em->data = *(u32 *) data; 260 } else { 261 void *v = kmemdup(data, data_len, GFP_KERNEL); 262 if (v == NULL) { 263 err = -ENOBUFS; --- 71 unchanged lines hidden (view full) --- 335 336 /* We do not use nla_parse_nested here because the maximum 337 * number of attributes is unknown. This saves us the allocation 338 * for a tb buffer which would serve no purpose at all. 339 * 340 * The array of rt attributes is parsed in the order as they are 341 * provided, their type must be incremental from 1 to n. Even 342 * if it does not serve any real purpose, a failure of sticking |
337 * to this policy will result in parsing failure. */ | 343 * to this policy will result in parsing failure. 344 */ |
338 for (idx = 0; nla_ok(rt_match, list_len); idx++) { 339 err = -EINVAL; 340 341 if (rt_match->nla_type != (idx + 1)) 342 goto errout_abort; 343 344 if (idx >= tree_hdr->nmatches) 345 goto errout_abort; --- 8 unchanged lines hidden (view full) --- 354 goto errout_abort; 355 356 rt_match = nla_next(rt_match, &list_len); 357 } 358 359 /* Check if the number of matches provided by userspace actually 360 * complies with the array of matches. The number was used for 361 * the validation of references and a mismatch could lead to | 345 for (idx = 0; nla_ok(rt_match, list_len); idx++) { 346 err = -EINVAL; 347 348 if (rt_match->nla_type != (idx + 1)) 349 goto errout_abort; 350 351 if (idx >= tree_hdr->nmatches) 352 goto errout_abort; --- 8 unchanged lines hidden (view full) --- 361 goto errout_abort; 362 363 rt_match = nla_next(rt_match, &list_len); 364 } 365 366 /* Check if the number of matches provided by userspace actually 367 * complies with the array of matches. The number was used for 368 * the validation of references and a mismatch could lead to |
362 * undefined references during the matching process. */ | 369 * undefined references during the matching process. 370 */ |
363 if (idx != tree_hdr->nmatches) { 364 err = -EINVAL; 365 goto errout_abort; 366 } 367 368 err = 0; 369errout: 370 return err; --- 73 unchanged lines hidden (view full) --- 444 struct nlattr *match_start = (struct nlattr *)tail; 445 struct tcf_ematch *em = tcf_em_get_match(tree, i); 446 struct tcf_ematch_hdr em_hdr = { 447 .kind = em->ops ? em->ops->kind : TCF_EM_CONTAINER, 448 .matchid = em->matchid, 449 .flags = em->flags 450 }; 451 | 371 if (idx != tree_hdr->nmatches) { 372 err = -EINVAL; 373 goto errout_abort; 374 } 375 376 err = 0; 377errout: 378 return err; --- 73 unchanged lines hidden (view full) --- 452 struct nlattr *match_start = (struct nlattr *)tail; 453 struct tcf_ematch *em = tcf_em_get_match(tree, i); 454 struct tcf_ematch_hdr em_hdr = { 455 .kind = em->ops ? em->ops->kind : TCF_EM_CONTAINER, 456 .matchid = em->matchid, 457 .flags = em->flags 458 }; 459 |
452 NLA_PUT(skb, i+1, sizeof(em_hdr), &em_hdr); | 460 NLA_PUT(skb, i + 1, sizeof(em_hdr), &em_hdr); |
453 454 if (em->ops && em->ops->dump) { 455 if (em->ops->dump(skb, em) < 0) 456 goto nla_put_failure; 457 } else if (tcf_em_is_container(em) || tcf_em_is_simple(em)) { 458 u32 u = em->data; 459 nla_put_nohdr(skb, sizeof(u), &u); 460 } else if (em->datalen > 0) --- 12 unchanged lines hidden (view full) --- 473 return -1; 474} 475EXPORT_SYMBOL(tcf_em_tree_dump); 476 477static inline int tcf_em_match(struct sk_buff *skb, struct tcf_ematch *em, 478 struct tcf_pkt_info *info) 479{ 480 int r = em->ops->match(skb, em, info); | 461 462 if (em->ops && em->ops->dump) { 463 if (em->ops->dump(skb, em) < 0) 464 goto nla_put_failure; 465 } else if (tcf_em_is_container(em) || tcf_em_is_simple(em)) { 466 u32 u = em->data; 467 nla_put_nohdr(skb, sizeof(u), &u); 468 } else if (em->datalen > 0) --- 12 unchanged lines hidden (view full) --- 481 return -1; 482} 483EXPORT_SYMBOL(tcf_em_tree_dump); 484 485static inline int tcf_em_match(struct sk_buff *skb, struct tcf_ematch *em, 486 struct tcf_pkt_info *info) 487{ 488 int r = em->ops->match(skb, em, info); |
489 |
|
481 return tcf_em_is_inverted(em) ? !r : r; 482} 483 484/* Do not use this function directly, use tcf_em_tree_match instead */ 485int __tcf_em_tree_match(struct sk_buff *skb, struct tcf_ematch_tree *tree, 486 struct tcf_pkt_info *info) 487{ 488 int stackp = 0, match_idx = 0, res = 0; --- 33 unchanged lines hidden (view full) --- 522 goto proceed; 523 } 524 } 525 526 return res; 527 528stack_overflow: 529 if (net_ratelimit()) | 490 return tcf_em_is_inverted(em) ? !r : r; 491} 492 493/* Do not use this function directly, use tcf_em_tree_match instead */ 494int __tcf_em_tree_match(struct sk_buff *skb, struct tcf_ematch_tree *tree, 495 struct tcf_pkt_info *info) 496{ 497 int stackp = 0, match_idx = 0, res = 0; --- 33 unchanged lines hidden (view full) --- 531 goto proceed; 532 } 533 } 534 535 return res; 536 537stack_overflow: 538 if (net_ratelimit()) |
530 printk(KERN_WARNING "tc ematch: local stack overflow," 531 " increase NET_EMATCH_STACK\n"); | 539 pr_warning("tc ematch: local stack overflow," 540 " increase NET_EMATCH_STACK\n"); |
532 return -1; 533} 534EXPORT_SYMBOL(__tcf_em_tree_match); | 541 return -1; 542} 543EXPORT_SYMBOL(__tcf_em_tree_match); |