diff options
author | 2007-03-24 12:46:02 -0700 | |
---|---|---|
committer | 2007-03-25 18:48:00 -0700 | |
commit | e1701c68c1d1aeb3213d7016593ea9a1d4309417 (patch) | |
tree | 96dc2e47b36589636b15602dcdcfd2ea426260b7 /net/decnet | |
parent | [SCTP]: Update SCTP Maintainers entry (diff) | |
download | linux-e1701c68c1d1aeb3213d7016593ea9a1d4309417.tar.gz linux-e1701c68c1d1aeb3213d7016593ea9a1d4309417.tar.bz2 linux-e1701c68c1d1aeb3213d7016593ea9a1d4309417.zip |
[NET]: Fix fib_rules compatibility breakage
Based upon a patch from Patrick McHardy.
The fib_rules netlink attribute policy introduced in 2.6.19 broke
userspace compatibilty. When specifying a rule with "from all"
or "to all", iproute adds a zero byte long netlink attribute,
but the policy requires all addresses to have a size equal to
sizeof(struct in_addr)/sizeof(struct in6_addr), resulting in a
validation error.
Check attribute length of FRA_SRC/FRA_DST in the generic framework
by letting the family specific rules implementation provide the
length of an address. Report an error if address length is non
zero but no address attribute is provided. Fix actual bug by
checking address length for non-zero instead of relying on
availability of attribute.
Signed-off-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/decnet')
-rw-r--r-- | net/decnet/dn_rules.c | 13 |
1 files changed, 6 insertions, 7 deletions
diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c index b6c98ac93dc8..5e86dd542302 100644 --- a/net/decnet/dn_rules.c +++ b/net/decnet/dn_rules.c @@ -109,8 +109,6 @@ errout: static struct nla_policy dn_fib_rule_policy[FRA_MAX+1] __read_mostly = { FRA_GENERIC_POLICY, - [FRA_SRC] = { .type = NLA_U16 }, - [FRA_DST] = { .type = NLA_U16 }, }; static int dn_fib_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) @@ -133,7 +131,7 @@ static int dn_fib_rule_configure(struct fib_rule *rule, struct sk_buff *skb, int err = -EINVAL; struct dn_fib_rule *r = (struct dn_fib_rule *)rule; - if (frh->src_len > 16 || frh->dst_len > 16 || frh->tos) + if (frh->tos) goto errout; if (rule->table == RT_TABLE_UNSPEC) { @@ -150,10 +148,10 @@ static int dn_fib_rule_configure(struct fib_rule *rule, struct sk_buff *skb, } } - if (tb[FRA_SRC]) + if (frh->src_len) r->src = nla_get_le16(tb[FRA_SRC]); - if (tb[FRA_DST]) + if (frh->dst_len) r->dst = nla_get_le16(tb[FRA_DST]); r->src_len = frh->src_len; @@ -176,10 +174,10 @@ static int dn_fib_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh, if (frh->dst_len && (r->dst_len != frh->dst_len)) return 0; - if (tb[FRA_SRC] && (r->src != nla_get_le16(tb[FRA_SRC]))) + if (frh->src_len && (r->src != nla_get_le16(tb[FRA_SRC]))) return 0; - if (tb[FRA_DST] && (r->dst != nla_get_le16(tb[FRA_DST]))) + if (frh->dst_len && (r->dst != nla_get_le16(tb[FRA_DST]))) return 0; return 1; @@ -249,6 +247,7 @@ int dn_fib_dump_rules(struct sk_buff *skb, struct netlink_callback *cb) static struct fib_rules_ops dn_fib_rules_ops = { .family = AF_DECnet, .rule_size = sizeof(struct dn_fib_rule), + .addr_size = sizeof(u16), .action = dn_fib_rule_action, .match = dn_fib_rule_match, .configure = dn_fib_rule_configure, |