2019-05-27 06:55:01 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2006-12-03 06:09:06 +00:00
|
|
|
/* IRC extension for TCP NAT alteration.
|
|
|
|
*
|
|
|
|
* (C) 2000-2001 by Harald Welte <laforge@gnumonks.org>
|
|
|
|
* (C) 2004 Rusty Russell <rusty@rustcorp.com.au> IBM Corporation
|
|
|
|
* based on a copy of RR's ip_nat_ftp.c
|
|
|
|
*/
|
|
|
|
|
2018-03-12 13:06:29 +00:00
|
|
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
|
|
|
|
2006-12-03 06:09:06 +00:00
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/moduleparam.h>
|
|
|
|
#include <linux/tcp.h>
|
|
|
|
#include <linux/kernel.h>
|
|
|
|
|
|
|
|
#include <net/netfilter/nf_nat.h>
|
|
|
|
#include <net/netfilter/nf_nat_helper.h>
|
|
|
|
#include <net/netfilter/nf_conntrack_helper.h>
|
|
|
|
#include <net/netfilter/nf_conntrack_expect.h>
|
|
|
|
#include <linux/netfilter/nf_conntrack_irc.h>
|
|
|
|
|
2019-04-17 14:46:16 +00:00
|
|
|
#define NAT_HELPER_NAME "irc"
|
|
|
|
|
2006-12-03 06:09:06 +00:00
|
|
|
MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
|
|
|
|
MODULE_DESCRIPTION("IRC (DCC) NAT helper");
|
|
|
|
MODULE_LICENSE("GPL");
|
2019-04-17 14:46:16 +00:00
|
|
|
MODULE_ALIAS_NF_NAT_HELPER(NAT_HELPER_NAME);
|
|
|
|
|
|
|
|
static struct nf_conntrack_nat_helper nat_helper_irc =
|
|
|
|
NF_CT_NAT_HELPER_INIT(NAT_HELPER_NAME);
|
2006-12-03 06:09:06 +00:00
|
|
|
|
2007-10-15 07:53:15 +00:00
|
|
|
static unsigned int help(struct sk_buff *skb,
|
2006-12-03 06:09:06 +00:00
|
|
|
enum ip_conntrack_info ctinfo,
|
2012-08-26 17:14:04 +00:00
|
|
|
unsigned int protoff,
|
2006-12-03 06:09:06 +00:00
|
|
|
unsigned int matchoff,
|
|
|
|
unsigned int matchlen,
|
|
|
|
struct nf_conntrack_expect *exp)
|
|
|
|
{
|
|
|
|
char buffer[sizeof("4294967296 65635")];
|
netfilter: nf_nat: fix access to uninitialized buffer in IRC NAT helper
Commit 5901b6be885e attempted to introduce IPv6 support into
IRC NAT helper. By doing so, the following code seemed to be removed
by accident:
ip = ntohl(exp->master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip);
sprintf(buffer, "%u %u", ip, port);
pr_debug("nf_nat_irc: inserting '%s' == %pI4, port %u\n", buffer, &ip, port);
This leads to the fact that buffer[] was left uninitialized and
contained some stack value. When we call nf_nat_mangle_tcp_packet(),
we call strlen(buffer) on excatly this uninitialized buffer. If we
are unlucky and the skb has enough tailroom, we overwrite resp. leak
contents with values that sit on our stack into the packet and send
that out to the receiver.
Since the rather informal DCC spec [1] does not seem to specify
IPv6 support right now, we log such occurences so that admins can
act accordingly, and drop the packet. I've looked into XChat source,
and IPv6 is not supported there: addresses are in u32 and print
via %u format string.
Therefore, restore old behaviour as in IPv4, use snprintf(). The
IRC helper does not support IPv6 by now. By this, we can safely use
strlen(buffer) in nf_nat_mangle_tcp_packet() and prevent a buffer
overflow. Also simplify some code as we now have ct variable anyway.
[1] http://www.irchelp.org/irchelp/rfc/ctcpspec.html
Fixes: 5901b6be885e ("netfilter: nf_nat: support IPv6 in IRC NAT helper")
Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
Cc: Harald Welte <laforge@gnumonks.org>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2013-12-31 15:28:39 +00:00
|
|
|
struct nf_conn *ct = exp->master;
|
|
|
|
union nf_inet_addr newaddr;
|
2006-12-03 06:09:06 +00:00
|
|
|
u_int16_t port;
|
|
|
|
|
|
|
|
/* Reply comes from server. */
|
netfilter: nf_nat: fix access to uninitialized buffer in IRC NAT helper
Commit 5901b6be885e attempted to introduce IPv6 support into
IRC NAT helper. By doing so, the following code seemed to be removed
by accident:
ip = ntohl(exp->master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip);
sprintf(buffer, "%u %u", ip, port);
pr_debug("nf_nat_irc: inserting '%s' == %pI4, port %u\n", buffer, &ip, port);
This leads to the fact that buffer[] was left uninitialized and
contained some stack value. When we call nf_nat_mangle_tcp_packet(),
we call strlen(buffer) on excatly this uninitialized buffer. If we
are unlucky and the skb has enough tailroom, we overwrite resp. leak
contents with values that sit on our stack into the packet and send
that out to the receiver.
Since the rather informal DCC spec [1] does not seem to specify
IPv6 support right now, we log such occurences so that admins can
act accordingly, and drop the packet. I've looked into XChat source,
and IPv6 is not supported there: addresses are in u32 and print
via %u format string.
Therefore, restore old behaviour as in IPv4, use snprintf(). The
IRC helper does not support IPv6 by now. By this, we can safely use
strlen(buffer) in nf_nat_mangle_tcp_packet() and prevent a buffer
overflow. Also simplify some code as we now have ct variable anyway.
[1] http://www.irchelp.org/irchelp/rfc/ctcpspec.html
Fixes: 5901b6be885e ("netfilter: nf_nat: support IPv6 in IRC NAT helper")
Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
Cc: Harald Welte <laforge@gnumonks.org>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2013-12-31 15:28:39 +00:00
|
|
|
newaddr = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3;
|
|
|
|
|
2006-12-03 06:09:06 +00:00
|
|
|
exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
|
|
|
|
exp->dir = IP_CT_DIR_REPLY;
|
|
|
|
exp->expectfn = nf_nat_follow_master;
|
|
|
|
|
2022-09-06 15:20:35 +00:00
|
|
|
port = nf_nat_exp_find_port(exp,
|
|
|
|
ntohs(exp->saved_proto.tcp.port));
|
2013-02-10 17:56:56 +00:00
|
|
|
if (port == 0) {
|
netfilter: nf_nat: fix access to uninitialized buffer in IRC NAT helper
Commit 5901b6be885e attempted to introduce IPv6 support into
IRC NAT helper. By doing so, the following code seemed to be removed
by accident:
ip = ntohl(exp->master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip);
sprintf(buffer, "%u %u", ip, port);
pr_debug("nf_nat_irc: inserting '%s' == %pI4, port %u\n", buffer, &ip, port);
This leads to the fact that buffer[] was left uninitialized and
contained some stack value. When we call nf_nat_mangle_tcp_packet(),
we call strlen(buffer) on excatly this uninitialized buffer. If we
are unlucky and the skb has enough tailroom, we overwrite resp. leak
contents with values that sit on our stack into the packet and send
that out to the receiver.
Since the rather informal DCC spec [1] does not seem to specify
IPv6 support right now, we log such occurences so that admins can
act accordingly, and drop the packet. I've looked into XChat source,
and IPv6 is not supported there: addresses are in u32 and print
via %u format string.
Therefore, restore old behaviour as in IPv4, use snprintf(). The
IRC helper does not support IPv6 by now. By this, we can safely use
strlen(buffer) in nf_nat_mangle_tcp_packet() and prevent a buffer
overflow. Also simplify some code as we now have ct variable anyway.
[1] http://www.irchelp.org/irchelp/rfc/ctcpspec.html
Fixes: 5901b6be885e ("netfilter: nf_nat: support IPv6 in IRC NAT helper")
Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
Cc: Harald Welte <laforge@gnumonks.org>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2013-12-31 15:28:39 +00:00
|
|
|
nf_ct_helper_log(skb, ct, "all ports in use");
|
2006-12-03 06:09:06 +00:00
|
|
|
return NF_DROP;
|
2013-02-10 17:56:56 +00:00
|
|
|
}
|
2006-12-03 06:09:06 +00:00
|
|
|
|
netfilter: nf_nat: fix access to uninitialized buffer in IRC NAT helper
Commit 5901b6be885e attempted to introduce IPv6 support into
IRC NAT helper. By doing so, the following code seemed to be removed
by accident:
ip = ntohl(exp->master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip);
sprintf(buffer, "%u %u", ip, port);
pr_debug("nf_nat_irc: inserting '%s' == %pI4, port %u\n", buffer, &ip, port);
This leads to the fact that buffer[] was left uninitialized and
contained some stack value. When we call nf_nat_mangle_tcp_packet(),
we call strlen(buffer) on excatly this uninitialized buffer. If we
are unlucky and the skb has enough tailroom, we overwrite resp. leak
contents with values that sit on our stack into the packet and send
that out to the receiver.
Since the rather informal DCC spec [1] does not seem to specify
IPv6 support right now, we log such occurences so that admins can
act accordingly, and drop the packet. I've looked into XChat source,
and IPv6 is not supported there: addresses are in u32 and print
via %u format string.
Therefore, restore old behaviour as in IPv4, use snprintf(). The
IRC helper does not support IPv6 by now. By this, we can safely use
strlen(buffer) in nf_nat_mangle_tcp_packet() and prevent a buffer
overflow. Also simplify some code as we now have ct variable anyway.
[1] http://www.irchelp.org/irchelp/rfc/ctcpspec.html
Fixes: 5901b6be885e ("netfilter: nf_nat: support IPv6 in IRC NAT helper")
Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
Cc: Harald Welte <laforge@gnumonks.org>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2013-12-31 15:28:39 +00:00
|
|
|
/* strlen("\1DCC CHAT chat AAAAAAAA P\1\n")=27
|
|
|
|
* strlen("\1DCC SCHAT chat AAAAAAAA P\1\n")=28
|
|
|
|
* strlen("\1DCC SEND F AAAAAAAA P S\1\n")=26
|
|
|
|
* strlen("\1DCC MOVE F AAAAAAAA P S\1\n")=26
|
|
|
|
* strlen("\1DCC TSEND F AAAAAAAA P S\1\n")=27
|
|
|
|
*
|
|
|
|
* AAAAAAAAA: bound addr (1.0.0.0==16777216, min 8 digits,
|
|
|
|
* 255.255.255.255==4294967296, 10 digits)
|
|
|
|
* P: bound port (min 1 d, max 5d (65635))
|
|
|
|
* F: filename (min 1 d )
|
|
|
|
* S: size (min 1 d )
|
|
|
|
* 0x01, \n: terminators
|
|
|
|
*/
|
|
|
|
/* AAA = "us", ie. where server normally talks to. */
|
|
|
|
snprintf(buffer, sizeof(buffer), "%u %u", ntohl(newaddr.ip), port);
|
2018-03-12 13:06:29 +00:00
|
|
|
pr_debug("inserting '%s' == %pI4, port %u\n",
|
netfilter: nf_nat: fix access to uninitialized buffer in IRC NAT helper
Commit 5901b6be885e attempted to introduce IPv6 support into
IRC NAT helper. By doing so, the following code seemed to be removed
by accident:
ip = ntohl(exp->master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip);
sprintf(buffer, "%u %u", ip, port);
pr_debug("nf_nat_irc: inserting '%s' == %pI4, port %u\n", buffer, &ip, port);
This leads to the fact that buffer[] was left uninitialized and
contained some stack value. When we call nf_nat_mangle_tcp_packet(),
we call strlen(buffer) on excatly this uninitialized buffer. If we
are unlucky and the skb has enough tailroom, we overwrite resp. leak
contents with values that sit on our stack into the packet and send
that out to the receiver.
Since the rather informal DCC spec [1] does not seem to specify
IPv6 support right now, we log such occurences so that admins can
act accordingly, and drop the packet. I've looked into XChat source,
and IPv6 is not supported there: addresses are in u32 and print
via %u format string.
Therefore, restore old behaviour as in IPv4, use snprintf(). The
IRC helper does not support IPv6 by now. By this, we can safely use
strlen(buffer) in nf_nat_mangle_tcp_packet() and prevent a buffer
overflow. Also simplify some code as we now have ct variable anyway.
[1] http://www.irchelp.org/irchelp/rfc/ctcpspec.html
Fixes: 5901b6be885e ("netfilter: nf_nat: support IPv6 in IRC NAT helper")
Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
Cc: Harald Welte <laforge@gnumonks.org>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2013-12-31 15:28:39 +00:00
|
|
|
buffer, &newaddr.ip, port);
|
|
|
|
|
2017-03-27 15:12:08 +00:00
|
|
|
if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, protoff, matchoff,
|
|
|
|
matchlen, buffer, strlen(buffer))) {
|
netfilter: nf_nat: fix access to uninitialized buffer in IRC NAT helper
Commit 5901b6be885e attempted to introduce IPv6 support into
IRC NAT helper. By doing so, the following code seemed to be removed
by accident:
ip = ntohl(exp->master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip);
sprintf(buffer, "%u %u", ip, port);
pr_debug("nf_nat_irc: inserting '%s' == %pI4, port %u\n", buffer, &ip, port);
This leads to the fact that buffer[] was left uninitialized and
contained some stack value. When we call nf_nat_mangle_tcp_packet(),
we call strlen(buffer) on excatly this uninitialized buffer. If we
are unlucky and the skb has enough tailroom, we overwrite resp. leak
contents with values that sit on our stack into the packet and send
that out to the receiver.
Since the rather informal DCC spec [1] does not seem to specify
IPv6 support right now, we log such occurences so that admins can
act accordingly, and drop the packet. I've looked into XChat source,
and IPv6 is not supported there: addresses are in u32 and print
via %u format string.
Therefore, restore old behaviour as in IPv4, use snprintf(). The
IRC helper does not support IPv6 by now. By this, we can safely use
strlen(buffer) in nf_nat_mangle_tcp_packet() and prevent a buffer
overflow. Also simplify some code as we now have ct variable anyway.
[1] http://www.irchelp.org/irchelp/rfc/ctcpspec.html
Fixes: 5901b6be885e ("netfilter: nf_nat: support IPv6 in IRC NAT helper")
Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
Cc: Harald Welte <laforge@gnumonks.org>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2013-12-31 15:28:39 +00:00
|
|
|
nf_ct_helper_log(skb, ct, "cannot mangle packet");
|
2007-07-08 05:30:49 +00:00
|
|
|
nf_ct_unexpect_related(exp);
|
2017-03-27 15:12:08 +00:00
|
|
|
return NF_DROP;
|
2013-02-10 17:56:56 +00:00
|
|
|
}
|
netfilter: nf_nat: fix access to uninitialized buffer in IRC NAT helper
Commit 5901b6be885e attempted to introduce IPv6 support into
IRC NAT helper. By doing so, the following code seemed to be removed
by accident:
ip = ntohl(exp->master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip);
sprintf(buffer, "%u %u", ip, port);
pr_debug("nf_nat_irc: inserting '%s' == %pI4, port %u\n", buffer, &ip, port);
This leads to the fact that buffer[] was left uninitialized and
contained some stack value. When we call nf_nat_mangle_tcp_packet(),
we call strlen(buffer) on excatly this uninitialized buffer. If we
are unlucky and the skb has enough tailroom, we overwrite resp. leak
contents with values that sit on our stack into the packet and send
that out to the receiver.
Since the rather informal DCC spec [1] does not seem to specify
IPv6 support right now, we log such occurences so that admins can
act accordingly, and drop the packet. I've looked into XChat source,
and IPv6 is not supported there: addresses are in u32 and print
via %u format string.
Therefore, restore old behaviour as in IPv4, use snprintf(). The
IRC helper does not support IPv6 by now. By this, we can safely use
strlen(buffer) in nf_nat_mangle_tcp_packet() and prevent a buffer
overflow. Also simplify some code as we now have ct variable anyway.
[1] http://www.irchelp.org/irchelp/rfc/ctcpspec.html
Fixes: 5901b6be885e ("netfilter: nf_nat: support IPv6 in IRC NAT helper")
Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
Cc: Harald Welte <laforge@gnumonks.org>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2013-12-31 15:28:39 +00:00
|
|
|
|
2017-03-27 15:12:08 +00:00
|
|
|
return NF_ACCEPT;
|
2006-12-03 06:09:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void __exit nf_nat_irc_fini(void)
|
|
|
|
{
|
2019-04-17 14:46:16 +00:00
|
|
|
nf_nat_helper_unregister(&nat_helper_irc);
|
2011-08-01 16:19:00 +00:00
|
|
|
RCU_INIT_POINTER(nf_nat_irc_hook, NULL);
|
2006-12-03 06:09:06 +00:00
|
|
|
synchronize_rcu();
|
|
|
|
}
|
|
|
|
|
|
|
|
static int __init nf_nat_irc_init(void)
|
|
|
|
{
|
2007-11-06 04:43:30 +00:00
|
|
|
BUG_ON(nf_nat_irc_hook != NULL);
|
2019-04-17 14:46:16 +00:00
|
|
|
nf_nat_helper_register(&nat_helper_irc);
|
2011-08-01 16:19:00 +00:00
|
|
|
RCU_INIT_POINTER(nf_nat_irc_hook, help);
|
2006-12-03 06:09:06 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Prior to 2.6.11, we had a ports param. No longer, but don't break users. */
|
treewide: Fix function prototypes for module_param_call()
Several function prototypes for the set/get functions defined by
module_param_call() have a slightly wrong argument types. This fixes
those in an effort to clean up the calls when running under type-enforced
compiler instrumentation for CFI. This is the result of running the
following semantic patch:
@match_module_param_call_function@
declarer name module_param_call;
identifier _name, _set_func, _get_func;
expression _arg, _mode;
@@
module_param_call(_name, _set_func, _get_func, _arg, _mode);
@fix_set_prototype
depends on match_module_param_call_function@
identifier match_module_param_call_function._set_func;
identifier _val, _param;
type _val_type, _param_type;
@@
int _set_func(
-_val_type _val
+const char * _val
,
-_param_type _param
+const struct kernel_param * _param
) { ... }
@fix_get_prototype
depends on match_module_param_call_function@
identifier match_module_param_call_function._get_func;
identifier _val, _param;
type _val_type, _param_type;
@@
int _get_func(
-_val_type _val
+char * _val
,
-_param_type _param
+const struct kernel_param * _param
) { ... }
Two additional by-hand changes are included for places where the above
Coccinelle script didn't notice them:
drivers/platform/x86/thinkpad_acpi.c
fs/lockd/svc.c
Signed-off-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Jessica Yu <jeyu@kernel.org>
2017-10-18 02:04:42 +00:00
|
|
|
static int warn_set(const char *val, const struct kernel_param *kp)
|
2006-12-03 06:09:06 +00:00
|
|
|
{
|
2018-03-12 13:06:29 +00:00
|
|
|
pr_info("kernel >= 2.6.10 only uses 'ports' for conntrack modules\n");
|
2006-12-03 06:09:06 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
module_param_call(ports, warn_set, NULL, NULL, 0);
|
|
|
|
|
|
|
|
module_init(nf_nat_irc_init);
|
|
|
|
module_exit(nf_nat_irc_fini);
|