Commit 8cdb46da authored by Hans Schillstrom's avatar Hans Schillstrom Committed by Pablo Neira Ayuso

netfilter: log: netns NULL ptr bug when calling from conntrack

Since (69b34fb9 netfilter: xt_LOG: add net namespace support
for xt_LOG), we hit this:

[ 4224.708977] BUG: unable to handle kernel NULL pointer dereference at 0000000000000388
[ 4224.709074] IP: [<ffffffff8147f699>] ipt_log_packet+0x29/0x270

when callling log functions from conntrack both in and out
are NULL i.e. the net pointer is invalid.

Adding struct net *net in call to nf_logfn() will secure that
there always is a vaild net ptr.

Reported as netfilter's bugzilla bug 818:
https://bugzilla.netfilter.org/show_bug.cgi?id=818Reported-by: default avatarRonald <ronald645@gmail.com>
Signed-off-by: default avatarHans Schillstrom <hans@schillstrom.com>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 42010ed0
...@@ -30,7 +30,8 @@ struct nf_loginfo { ...@@ -30,7 +30,8 @@ struct nf_loginfo {
} u; } u;
}; };
typedef void nf_logfn(u_int8_t pf, typedef void nf_logfn(struct net *net,
u_int8_t pf,
unsigned int hooknum, unsigned int hooknum,
const struct sk_buff *skb, const struct sk_buff *skb,
const struct net_device *in, const struct net_device *in,
......
...@@ -2,7 +2,8 @@ ...@@ -2,7 +2,8 @@
#define _KER_NFNETLINK_LOG_H #define _KER_NFNETLINK_LOG_H
void void
nfulnl_log_packet(u_int8_t pf, nfulnl_log_packet(struct net *net,
u_int8_t pf,
unsigned int hooknum, unsigned int hooknum,
const struct sk_buff *skb, const struct sk_buff *skb,
const struct net_device *in, const struct net_device *in,
......
...@@ -72,13 +72,12 @@ print_ports(const struct sk_buff *skb, uint8_t protocol, int offset) ...@@ -72,13 +72,12 @@ print_ports(const struct sk_buff *skb, uint8_t protocol, int offset)
} }
static void static void
ebt_log_packet(u_int8_t pf, unsigned int hooknum, ebt_log_packet(struct net *net, u_int8_t pf, unsigned int hooknum,
const struct sk_buff *skb, const struct net_device *in, const struct sk_buff *skb, const struct net_device *in,
const struct net_device *out, const struct nf_loginfo *loginfo, const struct net_device *out, const struct nf_loginfo *loginfo,
const char *prefix) const char *prefix)
{ {
unsigned int bitmask; unsigned int bitmask;
struct net *net = dev_net(in ? in : out);
/* FIXME: Disabled from containers until syslog ns is supported */ /* FIXME: Disabled from containers until syslog ns is supported */
if (!net_eq(net, &init_net)) if (!net_eq(net, &init_net))
...@@ -191,7 +190,7 @@ ebt_log_tg(struct sk_buff *skb, const struct xt_action_param *par) ...@@ -191,7 +190,7 @@ ebt_log_tg(struct sk_buff *skb, const struct xt_action_param *par)
nf_log_packet(net, NFPROTO_BRIDGE, par->hooknum, skb, nf_log_packet(net, NFPROTO_BRIDGE, par->hooknum, skb,
par->in, par->out, &li, "%s", info->prefix); par->in, par->out, &li, "%s", info->prefix);
else else
ebt_log_packet(NFPROTO_BRIDGE, par->hooknum, skb, par->in, ebt_log_packet(net, NFPROTO_BRIDGE, par->hooknum, skb, par->in,
par->out, &li, info->prefix); par->out, &li, info->prefix);
return EBT_CONTINUE; return EBT_CONTINUE;
} }
......
...@@ -131,14 +131,16 @@ static struct sk_buff *ulog_alloc_skb(unsigned int size) ...@@ -131,14 +131,16 @@ static struct sk_buff *ulog_alloc_skb(unsigned int size)
return skb; return skb;
} }
static void ebt_ulog_packet(unsigned int hooknr, const struct sk_buff *skb, static void ebt_ulog_packet(struct net *net, unsigned int hooknr,
const struct net_device *in, const struct net_device *out, const struct sk_buff *skb,
const struct ebt_ulog_info *uloginfo, const char *prefix) const struct net_device *in,
const struct net_device *out,
const struct ebt_ulog_info *uloginfo,
const char *prefix)
{ {
ebt_ulog_packet_msg_t *pm; ebt_ulog_packet_msg_t *pm;
size_t size, copy_len; size_t size, copy_len;
struct nlmsghdr *nlh; struct nlmsghdr *nlh;
struct net *net = dev_net(in ? in : out);
struct ebt_ulog_net *ebt = ebt_ulog_pernet(net); struct ebt_ulog_net *ebt = ebt_ulog_pernet(net);
unsigned int group = uloginfo->nlgroup; unsigned int group = uloginfo->nlgroup;
ebt_ulog_buff_t *ub = &ebt->ulog_buffers[group]; ebt_ulog_buff_t *ub = &ebt->ulog_buffers[group];
...@@ -233,7 +235,7 @@ static void ebt_ulog_packet(unsigned int hooknr, const struct sk_buff *skb, ...@@ -233,7 +235,7 @@ static void ebt_ulog_packet(unsigned int hooknr, const struct sk_buff *skb,
} }
/* this function is registered with the netfilter core */ /* this function is registered with the netfilter core */
static void ebt_log_packet(u_int8_t pf, unsigned int hooknum, static void ebt_log_packet(struct net *net, u_int8_t pf, unsigned int hooknum,
const struct sk_buff *skb, const struct net_device *in, const struct sk_buff *skb, const struct net_device *in,
const struct net_device *out, const struct nf_loginfo *li, const struct net_device *out, const struct nf_loginfo *li,
const char *prefix) const char *prefix)
...@@ -252,13 +254,15 @@ static void ebt_log_packet(u_int8_t pf, unsigned int hooknum, ...@@ -252,13 +254,15 @@ static void ebt_log_packet(u_int8_t pf, unsigned int hooknum,
strlcpy(loginfo.prefix, prefix, sizeof(loginfo.prefix)); strlcpy(loginfo.prefix, prefix, sizeof(loginfo.prefix));
} }
ebt_ulog_packet(hooknum, skb, in, out, &loginfo, prefix); ebt_ulog_packet(net, hooknum, skb, in, out, &loginfo, prefix);
} }
static unsigned int static unsigned int
ebt_ulog_tg(struct sk_buff *skb, const struct xt_action_param *par) ebt_ulog_tg(struct sk_buff *skb, const struct xt_action_param *par)
{ {
ebt_ulog_packet(par->hooknum, skb, par->in, par->out, struct net *net = dev_net(par->in ? par->in : par->out);
ebt_ulog_packet(net, par->hooknum, skb, par->in, par->out,
par->targinfo, NULL); par->targinfo, NULL);
return EBT_CONTINUE; return EBT_CONTINUE;
} }
......
...@@ -162,7 +162,8 @@ static struct sk_buff *ulog_alloc_skb(unsigned int size) ...@@ -162,7 +162,8 @@ static struct sk_buff *ulog_alloc_skb(unsigned int size)
return skb; return skb;
} }
static void ipt_ulog_packet(unsigned int hooknum, static void ipt_ulog_packet(struct net *net,
unsigned int hooknum,
const struct sk_buff *skb, const struct sk_buff *skb,
const struct net_device *in, const struct net_device *in,
const struct net_device *out, const struct net_device *out,
...@@ -174,7 +175,6 @@ static void ipt_ulog_packet(unsigned int hooknum, ...@@ -174,7 +175,6 @@ static void ipt_ulog_packet(unsigned int hooknum,
size_t size, copy_len; size_t size, copy_len;
struct nlmsghdr *nlh; struct nlmsghdr *nlh;
struct timeval tv; struct timeval tv;
struct net *net = dev_net(in ? in : out);
struct ulog_net *ulog = ulog_pernet(net); struct ulog_net *ulog = ulog_pernet(net);
/* ffs == find first bit set, necessary because userspace /* ffs == find first bit set, necessary because userspace
...@@ -291,12 +291,15 @@ static void ipt_ulog_packet(unsigned int hooknum, ...@@ -291,12 +291,15 @@ static void ipt_ulog_packet(unsigned int hooknum,
static unsigned int static unsigned int
ulog_tg(struct sk_buff *skb, const struct xt_action_param *par) ulog_tg(struct sk_buff *skb, const struct xt_action_param *par)
{ {
ipt_ulog_packet(par->hooknum, skb, par->in, par->out, struct net *net = dev_net(par->in ? par->in : par->out);
ipt_ulog_packet(net, par->hooknum, skb, par->in, par->out,
par->targinfo, NULL); par->targinfo, NULL);
return XT_CONTINUE; return XT_CONTINUE;
} }
static void ipt_logfn(u_int8_t pf, static void ipt_logfn(struct net *net,
u_int8_t pf,
unsigned int hooknum, unsigned int hooknum,
const struct sk_buff *skb, const struct sk_buff *skb,
const struct net_device *in, const struct net_device *in,
...@@ -318,7 +321,7 @@ static void ipt_logfn(u_int8_t pf, ...@@ -318,7 +321,7 @@ static void ipt_logfn(u_int8_t pf,
strlcpy(loginfo.prefix, prefix, sizeof(loginfo.prefix)); strlcpy(loginfo.prefix, prefix, sizeof(loginfo.prefix));
} }
ipt_ulog_packet(hooknum, skb, in, out, &loginfo, prefix); ipt_ulog_packet(net, hooknum, skb, in, out, &loginfo, prefix);
} }
static int ulog_tg_check(const struct xt_tgchk_param *par) static int ulog_tg_check(const struct xt_tgchk_param *par)
......
...@@ -148,7 +148,7 @@ void nf_log_packet(struct net *net, ...@@ -148,7 +148,7 @@ void nf_log_packet(struct net *net,
va_start(args, fmt); va_start(args, fmt);
vsnprintf(prefix, sizeof(prefix), fmt, args); vsnprintf(prefix, sizeof(prefix), fmt, args);
va_end(args); va_end(args);
logger->logfn(pf, hooknum, skb, in, out, loginfo, prefix); logger->logfn(net, pf, hooknum, skb, in, out, loginfo, prefix);
} }
rcu_read_unlock(); rcu_read_unlock();
} }
......
...@@ -602,7 +602,8 @@ static struct nf_loginfo default_loginfo = { ...@@ -602,7 +602,8 @@ static struct nf_loginfo default_loginfo = {
/* log handler for internal netfilter logging api */ /* log handler for internal netfilter logging api */
void void
nfulnl_log_packet(u_int8_t pf, nfulnl_log_packet(struct net *net,
u_int8_t pf,
unsigned int hooknum, unsigned int hooknum,
const struct sk_buff *skb, const struct sk_buff *skb,
const struct net_device *in, const struct net_device *in,
...@@ -615,7 +616,6 @@ nfulnl_log_packet(u_int8_t pf, ...@@ -615,7 +616,6 @@ nfulnl_log_packet(u_int8_t pf,
const struct nf_loginfo *li; const struct nf_loginfo *li;
unsigned int qthreshold; unsigned int qthreshold;
unsigned int plen; unsigned int plen;
struct net *net = dev_net(in ? in : out);
struct nfnl_log_net *log = nfnl_log_pernet(net); struct nfnl_log_net *log = nfnl_log_pernet(net);
if (li_user && li_user->type == NF_LOG_TYPE_ULOG) if (li_user && li_user->type == NF_LOG_TYPE_ULOG)
......
...@@ -466,7 +466,8 @@ log_packet_common(struct sbuff *m, ...@@ -466,7 +466,8 @@ log_packet_common(struct sbuff *m,
static void static void
ipt_log_packet(u_int8_t pf, ipt_log_packet(struct net *net,
u_int8_t pf,
unsigned int hooknum, unsigned int hooknum,
const struct sk_buff *skb, const struct sk_buff *skb,
const struct net_device *in, const struct net_device *in,
...@@ -475,7 +476,6 @@ ipt_log_packet(u_int8_t pf, ...@@ -475,7 +476,6 @@ ipt_log_packet(u_int8_t pf,
const char *prefix) const char *prefix)
{ {
struct sbuff *m; struct sbuff *m;
struct net *net = dev_net(in ? in : out);
/* FIXME: Disabled from containers until syslog ns is supported */ /* FIXME: Disabled from containers until syslog ns is supported */
if (!net_eq(net, &init_net)) if (!net_eq(net, &init_net))
...@@ -797,7 +797,8 @@ static void dump_ipv6_mac_header(struct sbuff *m, ...@@ -797,7 +797,8 @@ static void dump_ipv6_mac_header(struct sbuff *m,
} }
static void static void
ip6t_log_packet(u_int8_t pf, ip6t_log_packet(struct net *net,
u_int8_t pf,
unsigned int hooknum, unsigned int hooknum,
const struct sk_buff *skb, const struct sk_buff *skb,
const struct net_device *in, const struct net_device *in,
...@@ -806,7 +807,6 @@ ip6t_log_packet(u_int8_t pf, ...@@ -806,7 +807,6 @@ ip6t_log_packet(u_int8_t pf,
const char *prefix) const char *prefix)
{ {
struct sbuff *m; struct sbuff *m;
struct net *net = dev_net(in ? in : out);
/* FIXME: Disabled from containers until syslog ns is supported */ /* FIXME: Disabled from containers until syslog ns is supported */
if (!net_eq(net, &init_net)) if (!net_eq(net, &init_net))
...@@ -833,17 +833,18 @@ log_tg(struct sk_buff *skb, const struct xt_action_param *par) ...@@ -833,17 +833,18 @@ log_tg(struct sk_buff *skb, const struct xt_action_param *par)
{ {
const struct xt_log_info *loginfo = par->targinfo; const struct xt_log_info *loginfo = par->targinfo;
struct nf_loginfo li; struct nf_loginfo li;
struct net *net = dev_net(par->in ? par->in : par->out);
li.type = NF_LOG_TYPE_LOG; li.type = NF_LOG_TYPE_LOG;
li.u.log.level = loginfo->level; li.u.log.level = loginfo->level;
li.u.log.logflags = loginfo->logflags; li.u.log.logflags = loginfo->logflags;
if (par->family == NFPROTO_IPV4) if (par->family == NFPROTO_IPV4)
ipt_log_packet(NFPROTO_IPV4, par->hooknum, skb, par->in, ipt_log_packet(net, NFPROTO_IPV4, par->hooknum, skb, par->in,
par->out, &li, loginfo->prefix); par->out, &li, loginfo->prefix);
#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
else if (par->family == NFPROTO_IPV6) else if (par->family == NFPROTO_IPV6)
ip6t_log_packet(NFPROTO_IPV6, par->hooknum, skb, par->in, ip6t_log_packet(net, NFPROTO_IPV6, par->hooknum, skb, par->in,
par->out, &li, loginfo->prefix); par->out, &li, loginfo->prefix);
#endif #endif
else else
......
...@@ -26,13 +26,14 @@ nflog_tg(struct sk_buff *skb, const struct xt_action_param *par) ...@@ -26,13 +26,14 @@ nflog_tg(struct sk_buff *skb, const struct xt_action_param *par)
{ {
const struct xt_nflog_info *info = par->targinfo; const struct xt_nflog_info *info = par->targinfo;
struct nf_loginfo li; struct nf_loginfo li;
struct net *net = dev_net(par->in ? par->in : par->out);
li.type = NF_LOG_TYPE_ULOG; li.type = NF_LOG_TYPE_ULOG;
li.u.ulog.copy_len = info->len; li.u.ulog.copy_len = info->len;
li.u.ulog.group = info->group; li.u.ulog.group = info->group;
li.u.ulog.qthreshold = info->threshold; li.u.ulog.qthreshold = info->threshold;
nfulnl_log_packet(par->family, par->hooknum, skb, par->in, nfulnl_log_packet(net, par->family, par->hooknum, skb, par->in,
par->out, &li, info->prefix); par->out, &li, info->prefix);
return XT_CONTINUE; return XT_CONTINUE;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment