Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+90 -49
+1 -1
include/linux/netfilter/nf_conntrack_sip.h
··· 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,
+5 -4
net/ipv4/netfilter/nf_nat_sip.c
··· 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 ··· 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", ··· 188 187 * from which the server received the request. */ 189 188 if (ct_sip_parse_address_param(ct, *dptr, matchend, *datalen, 190 189 "received=", &poff, &plen, 191 - &addr) > 0 && 190 + &addr, false) > 0 && 192 191 addr.ip == ct->tuplehash[dir].tuple.dst.u3.ip && 193 192 addr.ip != ct->tuplehash[!dir].tuple.src.u3.ip) { 194 193 buflen = sprintf(buffer, "%pI4",
+6 -23
net/netfilter/nf_conntrack_expect.c
··· 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; ··· 369 386 struct nf_conn_help *master_help = nfct_help(master); 370 387 struct nf_conntrack_helper *helper; 371 388 struct net *net = nf_ct_exp_net(expect); 372 - struct hlist_node *n; 389 + struct hlist_node *n, *next; 373 390 unsigned int h; 374 391 int ret = 1; 375 392 ··· 378 395 goto out; 379 396 } 380 397 h = nf_ct_expect_dst_hash(&expect->tuple); 381 - hlist_for_each_entry(i, n, &net->ct.expect_hash[h], hnode) { 398 + hlist_for_each_entry_safe(i, n, next, &net->ct.expect_hash[h], hnode) { 382 399 if (expect_matches(i, expect)) { 383 - /* Refresh timer: if it's dying, ignore.. */ 384 - if (refresh_timer(i)) { 385 - ret = 0; 386 - goto out; 400 + if (del_timer(&i->timeout)) { 401 + nf_ct_unlink_expect(i); 402 + nf_ct_expect_put(i); 403 + break; 387 404 } 388 405 } else if (expect_clash(i, expect)) { 389 406 ret = -EBUSY;
+6 -1
net/netfilter/nf_conntrack_netlink.c
··· 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 = {
+72 -20
net/netfilter/nf_conntrack_sip.c
··· 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; ··· 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; ··· 231 219 union nf_inet_addr addr; 232 220 const char *aux = dptr; 233 221 234 - if (!parse_addr(ct, dptr, &dptr, &addr, limit)) { 222 + if (!sip_parse_addr(ct, dptr, &dptr, &addr, limit, true)) { 235 223 pr_debug("ip: %s parse failed.!\n", dptr); 236 224 return 0; 237 225 } ··· 308 296 return 0; 309 297 dptr += shift; 310 298 311 - if (!parse_addr(ct, dptr, &end, addr, limit)) 299 + if (!sip_parse_addr(ct, dptr, &end, addr, limit, true)) 312 300 return -1; 313 301 if (end < limit && *end == ':') { 314 302 end++; ··· 562 550 if (ret == 0) 563 551 return ret; 564 552 565 - if (!parse_addr(ct, dptr + *matchoff, &c, addr, limit)) 553 + if (!sip_parse_addr(ct, dptr + *matchoff, &c, addr, limit, true)) 566 554 return -1; 567 555 if (*c == ':') { 568 556 c++; ··· 611 599 unsigned int dataoff, unsigned int datalen, 612 600 const char *name, 613 601 unsigned int *matchoff, unsigned int *matchlen, 614 - union nf_inet_addr *addr) 602 + union nf_inet_addr *addr, bool delim) 615 603 { 616 604 const char *limit = dptr + datalen; 617 605 const char *start, *end; ··· 625 613 return 0; 626 614 627 615 start += strlen(name); 628 - if (!parse_addr(ct, start, &end, addr, limit)) 616 + if (!sip_parse_addr(ct, start, &end, addr, limit, delim)) 629 617 return 0; 630 618 *matchoff = start - dptr; 631 619 *matchlen = end - start; ··· 687 675 return 1; 688 676 } 689 677 678 + static int sdp_parse_addr(const struct nf_conn *ct, const char *cp, 679 + const char **endp, union nf_inet_addr *addr, 680 + const char *limit) 681 + { 682 + const char *end; 683 + int ret; 684 + 685 + memset(addr, 0, sizeof(*addr)); 686 + switch (nf_ct_l3num(ct)) { 687 + case AF_INET: 688 + ret = in4_pton(cp, limit - cp, (u8 *)&addr->ip, -1, &end); 689 + break; 690 + case AF_INET6: 691 + ret = in6_pton(cp, limit - cp, (u8 *)&addr->ip6, -1, &end); 692 + break; 693 + default: 694 + BUG(); 695 + } 696 + 697 + if (ret == 0) 698 + return 0; 699 + if (endp) 700 + *endp = end; 701 + return 1; 702 + } 703 + 704 + /* skip ip address. returns its length. */ 705 + static int sdp_addr_len(const struct nf_conn *ct, const char *dptr, 706 + const char *limit, int *shift) 707 + { 708 + union nf_inet_addr addr; 709 + const char *aux = dptr; 710 + 711 + if (!sdp_parse_addr(ct, dptr, &dptr, &addr, limit)) { 712 + pr_debug("ip: %s parse failed.!\n", dptr); 713 + return 0; 714 + } 715 + 716 + return dptr - aux; 717 + } 718 + 690 719 /* SDP header parsing: a SDP session description contains an ordered set of 691 720 * headers, starting with a section containing general session parameters, 692 721 * optionally followed by multiple media descriptions. ··· 739 686 */ 740 687 static const struct sip_header ct_sdp_hdrs[] = { 741 688 [SDP_HDR_VERSION] = SDP_HDR("v=", NULL, digits_len), 742 - [SDP_HDR_OWNER_IP4] = SDP_HDR("o=", "IN IP4 ", epaddr_len), 743 - [SDP_HDR_CONNECTION_IP4] = SDP_HDR("c=", "IN IP4 ", epaddr_len), 744 - [SDP_HDR_OWNER_IP6] = SDP_HDR("o=", "IN IP6 ", epaddr_len), 745 - [SDP_HDR_CONNECTION_IP6] = SDP_HDR("c=", "IN IP6 ", epaddr_len), 689 + [SDP_HDR_OWNER_IP4] = SDP_HDR("o=", "IN IP4 ", sdp_addr_len), 690 + [SDP_HDR_CONNECTION_IP4] = SDP_HDR("c=", "IN IP4 ", sdp_addr_len), 691 + [SDP_HDR_OWNER_IP6] = SDP_HDR("o=", "IN IP6 ", sdp_addr_len), 692 + [SDP_HDR_CONNECTION_IP6] = SDP_HDR("c=", "IN IP6 ", sdp_addr_len), 746 693 [SDP_HDR_MEDIA] = SDP_HDR("m=", NULL, media_len), 747 694 }; 748 695 ··· 828 775 if (ret <= 0) 829 776 return ret; 830 777 831 - if (!parse_addr(ct, dptr + *matchoff, NULL, addr, 832 - dptr + *matchoff + *matchlen)) 778 + if (!sdp_parse_addr(ct, dptr + *matchoff, NULL, addr, 779 + dptr + *matchoff + *matchlen)) 833 780 return -1; 834 781 return 1; 835 782 } ··· 1568 1515 } 1569 1516 1570 1517 static struct nf_conntrack_helper sip[MAX_PORTS][4] __read_mostly; 1571 - static char sip_names[MAX_PORTS][4][sizeof("sip-65535")] __read_mostly; 1572 1518 1573 1519 static const struct nf_conntrack_expect_policy sip_exp_policy[SIP_EXPECT_MAX + 1] = { 1574 1520 [SIP_EXPECT_SIGNALLING] = { ··· 1637 1585 sip[i][j].me = THIS_MODULE; 1638 1586 1639 1587 if (ports[i] == SIP_PORT) 1640 - sprintf(sip_names[i][j], "sip"); 1588 + sprintf(sip[i][j].name, "sip"); 1641 1589 else 1642 - sprintf(sip_names[i][j], "sip-%u", i); 1590 + sprintf(sip[i][j].name, "sip-%u", i); 1643 1591 1644 1592 pr_debug("port #%u: %u\n", i, ports[i]); 1645 1593