netfilter: log: netns NULL ptr bug when calling from conntrack
Since (69b34fb
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=818
Reported-by: Ronald <ronald645@gmail.com>
Signed-off-by: Hans Schillstrom <hans@schillstrom.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
committed by
Pablo Neira Ayuso
parent
42010ed0c6
commit
8cdb46da06
@@ -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 @@
|
|||||||
#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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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 @@ unlock:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 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,
|
|||||||
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)
|
|||||||
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,
|
|||||||
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 @@ alloc_failure:
|
|||||||
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,
|
|||||||
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,
|
|||||||
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 = {
|
|||||||
|
|
||||||
/* 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,
|
|||||||
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,
|
|||||||
|
|
||||||
|
|
||||||
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,
|
|||||||
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 @@ fallback:
|
|||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
{
|
{
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user