Commit 6c71bec66ae65305ba5c33c93aa722f21f092737

Authored by David S. Miller

Merge git://1984.lsi.us.es/nf

Pable Neira Ayuso says:

====================
The following five patches contain fixes for 3.6-rc, they are:

* Two fixes for message parsing in the SIP conntrack helper, from
  Patrick McHardy.

* One fix for the SIP helper introduced in the user-space cthelper
  infrastructure, from Patrick McHardy.

* fix missing appropriate locking while modifying one conntrack entry
  from the nfqueue integration code, from myself.

* fix possible access to uninitiliazed timer in the nf_conntrack
  expectation infrastructure, from myself.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 5 changed files Side-by-side Diff

include/linux/netfilter/nf_conntrack_sip.h
... ... @@ -164,7 +164,7 @@
164 164 unsigned int dataoff, unsigned int datalen,
165 165 const char *name,
166 166 unsigned int *matchoff, unsigned int *matchlen,
167   - union nf_inet_addr *addr);
  167 + union nf_inet_addr *addr, bool delim);
168 168 extern int ct_sip_parse_numerical_param(const struct nf_conn *ct, const char *dptr,
169 169 unsigned int off, unsigned int datalen,
170 170 const char *name,
net/ipv4/netfilter/nf_nat_sip.c
... ... @@ -148,7 +148,7 @@
148 148 if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen,
149 149 hdr, NULL, &matchoff, &matchlen,
150 150 &addr, &port) > 0) {
151   - unsigned int matchend, poff, plen, buflen, n;
  151 + unsigned int olen, matchend, poff, plen, buflen, n;
152 152 char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
153 153  
154 154 /* We're only interested in headers related to this
155 155  
156 156  
... ... @@ -163,17 +163,18 @@
163 163 goto next;
164 164 }
165 165  
  166 + olen = *datalen;
166 167 if (!map_addr(skb, dataoff, dptr, datalen, matchoff, matchlen,
167 168 &addr, port))
168 169 return NF_DROP;
169 170  
170   - matchend = matchoff + matchlen;
  171 + matchend = matchoff + matchlen + *datalen - olen;
171 172  
172 173 /* The maddr= parameter (RFC 2361) specifies where to send
173 174 * the reply. */
174 175 if (ct_sip_parse_address_param(ct, *dptr, matchend, *datalen,
175 176 "maddr=", &poff, &plen,
176   - &addr) > 0 &&
  177 + &addr, true) > 0 &&
177 178 addr.ip == ct->tuplehash[dir].tuple.src.u3.ip &&
178 179 addr.ip != ct->tuplehash[!dir].tuple.dst.u3.ip) {
179 180 buflen = sprintf(buffer, "%pI4",
... ... @@ -187,7 +188,7 @@
187 188 * from which the server received the request. */
188 189 if (ct_sip_parse_address_param(ct, *dptr, matchend, *datalen,
189 190 "received=", &poff, &plen,
190   - &addr) > 0 &&
  191 + &addr, false) > 0 &&
191 192 addr.ip == ct->tuplehash[dir].tuple.dst.u3.ip &&
192 193 addr.ip != ct->tuplehash[!dir].tuple.src.u3.ip) {
193 194 buflen = sprintf(buffer, "%pI4",
net/netfilter/nf_conntrack_expect.c
... ... @@ -361,23 +361,6 @@
361 361 }
362 362 }
363 363  
364   -static inline int refresh_timer(struct nf_conntrack_expect *i)
365   -{
366   - struct nf_conn_help *master_help = nfct_help(i->master);
367   - const struct nf_conntrack_expect_policy *p;
368   -
369   - if (!del_timer(&i->timeout))
370   - return 0;
371   -
372   - p = &rcu_dereference_protected(
373   - master_help->helper,
374   - lockdep_is_held(&nf_conntrack_lock)
375   - )->expect_policy[i->class];
376   - i->timeout.expires = jiffies + p->timeout * HZ;
377   - add_timer(&i->timeout);
378   - return 1;
379   -}
380   -
381 364 static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect)
382 365 {
383 366 const struct nf_conntrack_expect_policy *p;
... ... @@ -386,7 +369,7 @@
386 369 struct nf_conn_help *master_help = nfct_help(master);
387 370 struct nf_conntrack_helper *helper;
388 371 struct net *net = nf_ct_exp_net(expect);
389   - struct hlist_node *n;
  372 + struct hlist_node *n, *next;
390 373 unsigned int h;
391 374 int ret = 1;
392 375  
393 376  
... ... @@ -395,12 +378,12 @@
395 378 goto out;
396 379 }
397 380 h = nf_ct_expect_dst_hash(&expect->tuple);
398   - hlist_for_each_entry(i, n, &net->ct.expect_hash[h], hnode) {
  381 + hlist_for_each_entry_safe(i, n, next, &net->ct.expect_hash[h], hnode) {
399 382 if (expect_matches(i, expect)) {
400   - /* Refresh timer: if it's dying, ignore.. */
401   - if (refresh_timer(i)) {
402   - ret = 0;
403   - goto out;
  383 + if (del_timer(&i->timeout)) {
  384 + nf_ct_unlink_expect(i);
  385 + nf_ct_expect_put(i);
  386 + break;
404 387 }
405 388 } else if (expect_clash(i, expect)) {
406 389 ret = -EBUSY;
net/netfilter/nf_conntrack_netlink.c
... ... @@ -1896,10 +1896,15 @@
1896 1896 ctnetlink_nfqueue_parse(const struct nlattr *attr, struct nf_conn *ct)
1897 1897 {
1898 1898 struct nlattr *cda[CTA_MAX+1];
  1899 + int ret;
1899 1900  
1900 1901 nla_parse_nested(cda, CTA_MAX, attr, ct_nla_policy);
1901 1902  
1902   - return ctnetlink_nfqueue_parse_ct((const struct nlattr **)cda, ct);
  1903 + spin_lock_bh(&nf_conntrack_lock);
  1904 + ret = ctnetlink_nfqueue_parse_ct((const struct nlattr **)cda, ct);
  1905 + spin_unlock_bh(&nf_conntrack_lock);
  1906 +
  1907 + return ret;
1903 1908 }
1904 1909  
1905 1910 static struct nfq_ct_hook ctnetlink_nfqueue_hook = {
net/netfilter/nf_conntrack_sip.c
... ... @@ -183,12 +183,12 @@
183 183 return len + digits_len(ct, dptr, limit, shift);
184 184 }
185 185  
186   -static int parse_addr(const struct nf_conn *ct, const char *cp,
187   - const char **endp, union nf_inet_addr *addr,
188   - const char *limit)
  186 +static int sip_parse_addr(const struct nf_conn *ct, const char *cp,
  187 + const char **endp, union nf_inet_addr *addr,
  188 + const char *limit, bool delim)
189 189 {
190 190 const char *end;
191   - int ret = 0;
  191 + int ret;
192 192  
193 193 if (!ct)
194 194 return 0;
195 195  
196 196  
197 197  
... ... @@ -197,16 +197,28 @@
197 197 switch (nf_ct_l3num(ct)) {
198 198 case AF_INET:
199 199 ret = in4_pton(cp, limit - cp, (u8 *)&addr->ip, -1, &end);
  200 + if (ret == 0)
  201 + return 0;
200 202 break;
201 203 case AF_INET6:
  204 + if (cp < limit && *cp == '[')
  205 + cp++;
  206 + else if (delim)
  207 + return 0;
  208 +
202 209 ret = in6_pton(cp, limit - cp, (u8 *)&addr->ip6, -1, &end);
  210 + if (ret == 0)
  211 + return 0;
  212 +
  213 + if (end < limit && *end == ']')
  214 + end++;
  215 + else if (delim)
  216 + return 0;
203 217 break;
204 218 default:
205 219 BUG();
206 220 }
207 221  
208   - if (ret == 0 || end == cp)
209   - return 0;
210 222 if (endp)
211 223 *endp = end;
212 224 return 1;
... ... @@ -219,7 +231,7 @@
219 231 union nf_inet_addr addr;
220 232 const char *aux = dptr;
221 233  
222   - if (!parse_addr(ct, dptr, &dptr, &addr, limit)) {
  234 + if (!sip_parse_addr(ct, dptr, &dptr, &addr, limit, true)) {
223 235 pr_debug("ip: %s parse failed.!\n", dptr);
224 236 return 0;
225 237 }
... ... @@ -296,7 +308,7 @@
296 308 return 0;
297 309 dptr += shift;
298 310  
299   - if (!parse_addr(ct, dptr, &end, addr, limit))
  311 + if (!sip_parse_addr(ct, dptr, &end, addr, limit, true))
300 312 return -1;
301 313 if (end < limit && *end == ':') {
302 314 end++;
... ... @@ -550,7 +562,7 @@
550 562 if (ret == 0)
551 563 return ret;
552 564  
553   - if (!parse_addr(ct, dptr + *matchoff, &c, addr, limit))
  565 + if (!sip_parse_addr(ct, dptr + *matchoff, &c, addr, limit, true))
554 566 return -1;
555 567 if (*c == ':') {
556 568 c++;
... ... @@ -599,7 +611,7 @@
599 611 unsigned int dataoff, unsigned int datalen,
600 612 const char *name,
601 613 unsigned int *matchoff, unsigned int *matchlen,
602   - union nf_inet_addr *addr)
  614 + union nf_inet_addr *addr, bool delim)
603 615 {
604 616 const char *limit = dptr + datalen;
605 617 const char *start, *end;
... ... @@ -613,7 +625,7 @@
613 625 return 0;
614 626  
615 627 start += strlen(name);
616   - if (!parse_addr(ct, start, &end, addr, limit))
  628 + if (!sip_parse_addr(ct, start, &end, addr, limit, delim))
617 629 return 0;
618 630 *matchoff = start - dptr;
619 631 *matchlen = end - start;
... ... @@ -675,6 +687,47 @@
675 687 return 1;
676 688 }
677 689  
  690 +static int sdp_parse_addr(const struct nf_conn *ct, const char *cp,
  691 + const char **endp, union nf_inet_addr *addr,
  692 + const char *limit)
  693 +{
  694 + const char *end;
  695 + int ret;
  696 +
  697 + memset(addr, 0, sizeof(*addr));
  698 + switch (nf_ct_l3num(ct)) {
  699 + case AF_INET:
  700 + ret = in4_pton(cp, limit - cp, (u8 *)&addr->ip, -1, &end);
  701 + break;
  702 + case AF_INET6:
  703 + ret = in6_pton(cp, limit - cp, (u8 *)&addr->ip6, -1, &end);
  704 + break;
  705 + default:
  706 + BUG();
  707 + }
  708 +
  709 + if (ret == 0)
  710 + return 0;
  711 + if (endp)
  712 + *endp = end;
  713 + return 1;
  714 +}
  715 +
  716 +/* skip ip address. returns its length. */
  717 +static int sdp_addr_len(const struct nf_conn *ct, const char *dptr,
  718 + const char *limit, int *shift)
  719 +{
  720 + union nf_inet_addr addr;
  721 + const char *aux = dptr;
  722 +
  723 + if (!sdp_parse_addr(ct, dptr, &dptr, &addr, limit)) {
  724 + pr_debug("ip: %s parse failed.!\n", dptr);
  725 + return 0;
  726 + }
  727 +
  728 + return dptr - aux;
  729 +}
  730 +
678 731 /* SDP header parsing: a SDP session description contains an ordered set of
679 732 * headers, starting with a section containing general session parameters,
680 733 * optionally followed by multiple media descriptions.
... ... @@ -686,10 +739,10 @@
686 739 */
687 740 static const struct sip_header ct_sdp_hdrs[] = {
688 741 [SDP_HDR_VERSION] = SDP_HDR("v=", NULL, digits_len),
689   - [SDP_HDR_OWNER_IP4] = SDP_HDR("o=", "IN IP4 ", epaddr_len),
690   - [SDP_HDR_CONNECTION_IP4] = SDP_HDR("c=", "IN IP4 ", epaddr_len),
691   - [SDP_HDR_OWNER_IP6] = SDP_HDR("o=", "IN IP6 ", epaddr_len),
692   - [SDP_HDR_CONNECTION_IP6] = SDP_HDR("c=", "IN IP6 ", epaddr_len),
  742 + [SDP_HDR_OWNER_IP4] = SDP_HDR("o=", "IN IP4 ", sdp_addr_len),
  743 + [SDP_HDR_CONNECTION_IP4] = SDP_HDR("c=", "IN IP4 ", sdp_addr_len),
  744 + [SDP_HDR_OWNER_IP6] = SDP_HDR("o=", "IN IP6 ", sdp_addr_len),
  745 + [SDP_HDR_CONNECTION_IP6] = SDP_HDR("c=", "IN IP6 ", sdp_addr_len),
693 746 [SDP_HDR_MEDIA] = SDP_HDR("m=", NULL, media_len),
694 747 };
695 748  
... ... @@ -775,8 +828,8 @@
775 828 if (ret <= 0)
776 829 return ret;
777 830  
778   - if (!parse_addr(ct, dptr + *matchoff, NULL, addr,
779   - dptr + *matchoff + *matchlen))
  831 + if (!sdp_parse_addr(ct, dptr + *matchoff, NULL, addr,
  832 + dptr + *matchoff + *matchlen))
780 833 return -1;
781 834 return 1;
782 835 }
... ... @@ -1515,7 +1568,6 @@
1515 1568 }
1516 1569  
1517 1570 static struct nf_conntrack_helper sip[MAX_PORTS][4] __read_mostly;
1518   -static char sip_names[MAX_PORTS][4][sizeof("sip-65535")] __read_mostly;
1519 1571  
1520 1572 static const struct nf_conntrack_expect_policy sip_exp_policy[SIP_EXPECT_MAX + 1] = {
1521 1573 [SIP_EXPECT_SIGNALLING] = {
1522 1574  
... ... @@ -1585,9 +1637,9 @@
1585 1637 sip[i][j].me = THIS_MODULE;
1586 1638  
1587 1639 if (ports[i] == SIP_PORT)
1588   - sprintf(sip_names[i][j], "sip");
  1640 + sprintf(sip[i][j].name, "sip");
1589 1641 else
1590   - sprintf(sip_names[i][j], "sip-%u", i);
  1642 + sprintf(sip[i][j].name, "sip-%u", i);
1591 1643  
1592 1644 pr_debug("port #%u: %u\n", i, ports[i]);
1593 1645