aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/fib6_rules.c
diff options
context:
space:
mode:
authorThomas Graf <tgraf@suug.ch>2007-03-24 15:46:02 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-03-25 21:48:00 -0400
commite1701c68c1d1aeb3213d7016593ea9a1d4309417 (patch)
tree96dc2e47b36589636b15602dcdcfd2ea426260b7 /net/ipv6/fib6_rules.c
parent5f85813c33ddbf6d11ccfdbcc01f176e24a76bd2 (diff)
[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/ipv6/fib6_rules.c')
-rw-r--r--net/ipv6/fib6_rules.c14
1 files changed, 5 insertions, 9 deletions
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index 0862809ffcf7..ea3035b4e3e8 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -131,8 +131,6 @@ static int fib6_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
131 131
132static struct nla_policy fib6_rule_policy[FRA_MAX+1] __read_mostly = { 132static struct nla_policy fib6_rule_policy[FRA_MAX+1] __read_mostly = {
133 FRA_GENERIC_POLICY, 133 FRA_GENERIC_POLICY,
134 [FRA_SRC] = { .len = sizeof(struct in6_addr) },
135 [FRA_DST] = { .len = sizeof(struct in6_addr) },
136}; 134};
137 135
138static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb, 136static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
@@ -142,9 +140,6 @@ static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
142 int err = -EINVAL; 140 int err = -EINVAL;
143 struct fib6_rule *rule6 = (struct fib6_rule *) rule; 141 struct fib6_rule *rule6 = (struct fib6_rule *) rule;
144 142
145 if (frh->src_len > 128 || frh->dst_len > 128)
146 goto errout;
147
148 if (rule->action == FR_ACT_TO_TBL) { 143 if (rule->action == FR_ACT_TO_TBL) {
149 if (rule->table == RT6_TABLE_UNSPEC) 144 if (rule->table == RT6_TABLE_UNSPEC)
150 goto errout; 145 goto errout;
@@ -155,11 +150,11 @@ static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
155 } 150 }
156 } 151 }
157 152
158 if (tb[FRA_SRC]) 153 if (frh->src_len)
159 nla_memcpy(&rule6->src.addr, tb[FRA_SRC], 154 nla_memcpy(&rule6->src.addr, tb[FRA_SRC],
160 sizeof(struct in6_addr)); 155 sizeof(struct in6_addr));
161 156
162 if (tb[FRA_DST]) 157 if (frh->dst_len)
163 nla_memcpy(&rule6->dst.addr, tb[FRA_DST], 158 nla_memcpy(&rule6->dst.addr, tb[FRA_DST],
164 sizeof(struct in6_addr)); 159 sizeof(struct in6_addr));
165 160
@@ -186,11 +181,11 @@ static int fib6_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
186 if (frh->tos && (rule6->tclass != frh->tos)) 181 if (frh->tos && (rule6->tclass != frh->tos))
187 return 0; 182 return 0;
188 183
189 if (tb[FRA_SRC] && 184 if (frh->src_len &&
190 nla_memcmp(tb[FRA_SRC], &rule6->src.addr, sizeof(struct in6_addr))) 185 nla_memcmp(tb[FRA_SRC], &rule6->src.addr, sizeof(struct in6_addr)))
191 return 0; 186 return 0;
192 187
193 if (tb[FRA_DST] && 188 if (frh->dst_len &&
194 nla_memcmp(tb[FRA_DST], &rule6->dst.addr, sizeof(struct in6_addr))) 189 nla_memcmp(tb[FRA_DST], &rule6->dst.addr, sizeof(struct in6_addr)))
195 return 0; 190 return 0;
196 191
@@ -240,6 +235,7 @@ static size_t fib6_rule_nlmsg_payload(struct fib_rule *rule)
240static struct fib_rules_ops fib6_rules_ops = { 235static struct fib_rules_ops fib6_rules_ops = {
241 .family = AF_INET6, 236 .family = AF_INET6,
242 .rule_size = sizeof(struct fib6_rule), 237 .rule_size = sizeof(struct fib6_rule),
238 .addr_size = sizeof(struct in6_addr),
243 .action = fib6_rule_action, 239 .action = fib6_rule_action,
244 .match = fib6_rule_match, 240 .match = fib6_rule_match,
245 .configure = fib6_rule_configure, 241 .configure = fib6_rule_configure,