lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <alpine.LSU.2.01.1007251838040.14790@obet.zrqbmnf.qr>
Date:	Sun, 25 Jul 2010 18:46:02 +0200 (CEST)
From:	Jan Engelhardt <jengelh@...ozas.de>
To:	"Neco.F" <necofang@...il.com>
cc:	linux-kernel@...r.kernel.org, netfilter@...r.kernel.org,
	netfilter-devel@...r.kernel.org
Subject: Re: about conntrack for oracle tns


On Thursday 2010-07-08 09:56, Neco.F wrote:

>hi,
>  I have a conntrack module for oracle tns. the kernel version is 2.6.26.5.
> sometimes when I use this module to access the oracle server, the kernel panic.
> panic info: EIP:[xxx] get_next_timer_interrupt...........

The panic info usually includes more info, which you should post.


>static int mangle_packet (struct sk_buff *skb,
>			  __be32 newip,
>			  u_int16_t port,
>			  unsigned int matchoff,
>			  unsigned int matchlen,
>			  struct nf_conn *ct,
>			  enum ip_conntrack_info ctinfo)
>{
>  char buffer[128];
>  struct tnshdr_redirect * ptnshdr = (struct tnshdr_redirect * )buffer;
>
>  sprintf (ptnshdr->datas,
>"(ADDRESS=(PROTOCOL=tcp)(HOST=%u.%u.%u.%u)(PORT=%u))", NIPQUAD(newip),
>port);

Questionable whether this is safe without a length limit. But you tell me.

>  ptnshdr->pkt_len = htons (sizeof (struct tnshdr_redirect) +
>strlen(ptnshdr->datas) - 1);
>  ptnshdr->pkt_checksum = 0x00;
>  ptnshdr->tns_type = NF_CT_TNS_REDIRECT;
>  ptnshdr->pkt_flags = 0;
>  ptnshdr->head_checksum = 0x00;
>  ptnshdr->data_len = htons (strlen(ptnshdr->datas));
>
>  TNS_PRINT ("calling nf_nat_mangle_tcp_packet (%s) matchoff: %u
>matchlen: %u", ptnshdr->datas, matchoff, matchlen);

Use pr_debug instead.

>  return (nf_nat_mangle_tcp_packet (skb, ct, ctinfo, matchoff,
>matchlen, buffer, sizeof (struct
>tnshdr_redirect)+strlen(ptnshdr->datas)-1));
>}
>
>static u_int nf_nat_tns (struct sk_buff *skb,
>			 enum ip_conntrack_info ctinfo,
>			 unsigned int matchoff,
>			 unsigned int matchlen,
>			 struct nf_conntrack_expect *exp)
>{
>  __be32 newip;
>  u_int16_t port;
>  struct nf_conn *ct = exp->master;
>  enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
>
>  newip = ct->tuplehash[!dir].tuple.dst.u3.ip;
>  exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
>
>  exp->dir = !dir;
>
>  exp->expectfn = nf_nat_follow_master;
>
>  TNS_PRINT ("exp->saved_proto.tcp.port: %u exp->tuple.src.u.tcp.port:
>%u exp->tuple.dst.u.tcp.port: %u exp->dir: %u",
>                 ntohs (exp->saved_proto.tcp.port),
>                 ntohs (exp->tuple.src.u.tcp.port),
>                 ntohs (exp->tuple.dst.u.tcp.port),
>                 exp->dir);
>
>  for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
>    exp->tuple.dst.u.tcp.port = htons(port);
>    TNS_PRINT ("tuple %p: %u " NIPQUAD_FMT ":%hu -> " NIPQUAD_FMT ":%hu",
>		   &exp->tuple, exp->tuple.dst.protonum,
>		   NIPQUAD(exp->tuple.src.u3.ip), ntohs(exp->tuple.src.u.all),
>		   NIPQUAD(exp->tuple.dst.u3.ip), ntohs(exp->tuple.dst.u.all));
>
>    if (0 == nf_ct_expect_related(exp)) {TNS_PRINT
>("nf_ct_expect_related succ"); break;}
>  }
>
>  if (0 == port) return NF_DROP;
>
>  if (!mangle_packet (skb, newip, port, matchoff, matchlen, ct, ctinfo)) {
>    TNS_PRINT ("mangle packet failed, nf_ct_unexpect_related");
>    nf_ct_unexpect_related(exp);
>    return NF_DROP;
>  }
>  return NF_ACCEPT;
>}
>
>/* Return 1 for match, 0 for accept*/
>static int find_pattern (const char *data, size_t dlen, struct
>nf_conntrack_man *cmd, u_int * matchoff, u_int * matchlen)
>{
>  struct tnshdr_redirect * ptnshdr = (struct tnshdr_redirect*) data;

You also want const here.

>  int len = 0;
>  int level = 1;
>  __be16 port = 0;
>  char * data_ptr = NULL;
>
>  //check TNS TYPE
>  if (NF_CT_TNS_REDIRECT != ptnshdr->tns_type) {
>    TNS_PRINT ("current data is not tns packet");
>    return (0);
>  }
>
>  *matchoff = 0;
>  *matchlen = ntohs (ptnshdr->pkt_len);
>
>  data_ptr =  (char*)data + dlen - 1;

Drop the cast, it seems to serve no purpose.

>  port = 0;
>  for (len = 0; len < dlen; len++, data_ptr--) {
>    if ('=' == *data_ptr) break;
>    if (*data_ptr >= '0' && *data_ptr <= '9') {
>      port = port + (*data_ptr -'0') * level;
>      level *= 10;
>    }
>  }

You could be using simple_strtoul here.

>
>  cmd->u.tcp.port = htons (port);
>
>  TNS_PRINT ("ip = "NIPQUAD_FMT" port = %u", NIPQUAD(cmd->u3.ip), port);
>  return ((0==port) ? 0 : 1);

"return port != 0;" is sufficient.

>}
>
>static int help (struct sk_buff *skb,
>		 unsigned int protoff,
>		 struct nf_conn *ct,
>		 enum ip_conntrack_info ctinfo)
>{
>  u_int dataoff = 0, datalen = 0;
>  const struct tcphdr *th = NULL;
>  struct tcphdr _tcph;
>  const char *buf_ptr = NULL;
>  int ret = NF_ACCEPT;
>  int found = 0;
>  struct nf_conntrack_expect * exp = NULL;
>  u_int matchlen = 0, matchoff = 0;
>  enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
>  struct nf_conntrack_man cmd = {};
>  union nf_inet_addr *daddr = NULL;
>
>  if (ctinfo != IP_CT_ESTABLISHED && ctinfo !=
>IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
>    TNS_PRINT ("tns: Conntrackinfo = %u", ctinfo);
>    return NF_ACCEPT;
>  }
>
>  th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
>  if (th == NULL) return (NF_ACCEPT);
>
>  dataoff = protoff + th->doff * 4;
>  /* No data? */
>  if (dataoff >= skb->len) {
>    TNS_PRINT ("tns: dataoff(%u) >= skblen(%u)", dataoff, skb->len);
>    return NF_ACCEPT;
>  }
>  datalen = skb->len - dataoff;
>
>  spin_lock_bh (&nf_tns_lock);
>
>  TNS_PRINT ("skb_headlen(skb)= %u offset: %u datalen: %u",
>skb_headlen(skb), dataoff, datalen);
>  buf_ptr = skb_header_pointer (skb, dataoff, datalen, tns_buffer);
>  BUG_ON(buf_ptr == NULL);

Don't use BUG_ON, handle the problem correctly and return from the
function.

>  //tns_dump_block ("buf_ptr", (caddr_t)buf_ptr, datalen);
>  //tns_dump_block ("tns_buffer", (caddr_t)tns_buffer, datalen);
>
>  cmd.l3num = nf_ct_l3num(ct);
>  memcpy (cmd.u3.all, &ct->tuplehash[dir].tuple.src.u3.all, sizeof(cmd.u3.all));
>
>  found = find_pattern (buf_ptr, datalen, &cmd, &matchoff, &matchlen);
>
>  /*no match */
>  if (0 == found) {ret = NF_ACCEPT; TNS_PRINT ("unfound pattern"); goto out;}
>
>  //proto: 2 192.168.100.100-> 192.168.100.103 port: 3747
>  TNS_PRINT ("proto: %u " NIPQUAD_FMT "-> " NIPQUAD_FMT " port: %u",
>		 nf_ct_l3num (ct),
>		 NIPQUAD(ct->tuplehash[!dir].tuple.src.u3.ip),
>		 NIPQUAD (ct->tuplehash[!dir].tuple.dst.u3.ip),
>		 ntohs(cmd.u.tcp.port ));
>
>  daddr = &ct->tuplehash[!dir].tuple.dst.u3;
>
>  /* Update the tns info */
>  if ((cmd.l3num == nf_ct_l3num(ct)) && memcmp(&cmd.u3.all,
>&ct->tuplehash[dir].tuple.src.u3.all, sizeof(cmd.u3.all))) {
>    if (cmd.l3num == PF_INET) {

==NFPROTO_IPV4.

>      TNS_PRINT ("NOT RECORDING: " NIPQUAD_FMT " != " NIPQUAD_FMT,
>		     NIPQUAD(cmd.u3.ip),
>		     NIPQUAD(ct->tuplehash[dir].tuple.src.u3.ip));
>    }
>    TNS_PRINT ("update the tns info");
>    daddr = &cmd.u3;
>  }
>
>#if 1
>  exp = nf_ct_expect_alloc (ct);
>  if (NULL == exp) {
>    ret = NF_DROP;
>    TNS_PRINT ("nf_ct_expect_alloc failed");
>    goto out;
>  }
>
>  nf_ct_expect_init (exp, NF_CT_EXPECT_CLASS_DEFAULT, cmd.l3num,
>		     &ct->tuplehash[!dir].tuple.src.u3, daddr,
>		     IPPROTO_TCP, NULL, &cmd.u.tcp.port);
>
>  if (ct->status & IPS_NAT_MASK) {
>    TNS_PRINT ("match nat mask");
>    ret = nf_nat_tns (skb, ctinfo, matchoff, matchlen, exp);
>  } else {
>    TNS_PRINT ("no nat");
>    if (0 != nf_ct_expect_related (exp)) {
>     ret = NF_DROP;
>     TNS_PRINT ("nf_ct_expect_related failed");
>    } else {
>      ret = NF_ACCEPT;
>     TNS_PRINT ("nf_ct_expect_related succ");
>    }
>  }
>
>  nf_ct_expect_put (exp);
>#endif
> out:
>  spin_unlock_bh (&nf_tns_lock);
>  return (ret);
>}
>
>static struct nf_conntrack_helper tns[MAX_PORTS] __read_mostly;
>static char tns_names[MAX_PORTS][sizeof("tns-65535")] __read_mostly;
>
>static const struct nf_conntrack_expect_policy tns_exp_policy = {
>  .max_expected	= 1,
>  .timeout	= 5 * 60,
>};
>
>/* don't make this __exit, since it's called from __init ! */
>static void nf_conntrack_tns_fini(void)
>{
>  int i = 0;
>
>  for (i = 0; i < ports_c; i++) {
>    if (tns[i].me == NULL) continue;
>    TNS_PRINT ("nf_ct_tns: unregistering helper for pf: %d port: %d",
>tns[i].tuple.src.l3num, ports[i]);
>    nf_conntrack_helper_unregister(&tns[i]);
>  }
>
>  if (NULL != tns_buffer) kfree(tns_buffer);
>}
>
>static int __init nf_conntrack_tns_init(void)
>{
>  int i = 0, ret = 0;
>  char *tmpname;
>
>  tns_buffer = kmalloc(65536, GFP_KERNEL);
>
>  if (!tns_buffer) return -ENOMEM;
>
>  if (ports_c == 0) ports[ports_c++] = TNS_PORT;
>
>  for (i = 0; i < ports_c; i++) {
>    tns[i].tuple.src.l3num = PF_INET;

NFPROTO_IPV4.

>...
>}
>
>module_init(nf_conntrack_tns_init);
>module_exit(nf_conntrack_tns_fini);

You need to do something about the coding style, this is hard to read.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ