Skip to content

Commit

Permalink
netfilter: ipset: fix timeout value overflow bug
Browse files Browse the repository at this point in the history
Large timeout parameters could result wrong timeout values due to
an overflow at msec to jiffies conversion (reported by Andreas Herz)

[ This patch was mangled by Pablo Neira Ayuso since David Laight and
  Eric Dumazet noticed that we were using hardcoded 1000 instead of
  MSEC_PER_SEC to calculate the timeout ]

Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
  • Loading branch information
Jozsef Kadlecsik authored and Pablo Neira Ayuso committed May 16, 2012
1 parent 1a4ac98 commit 127f559
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 2 deletions.
4 changes: 4 additions & 0 deletions include/linux/netfilter/ipset/ip_set_timeout.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ ip_set_timeout_uget(struct nlattr *tb)
{
unsigned int timeout = ip_set_get_h32(tb);

/* Normalize to fit into jiffies */
if (timeout > UINT_MAX/MSEC_PER_SEC)
timeout = UINT_MAX/MSEC_PER_SEC;

/* Userspace supplied TIMEOUT parameter: adjust crazy size */
return timeout == IPSET_NO_TIMEOUT ? IPSET_NO_TIMEOUT - 1 : timeout;
}
Expand Down
15 changes: 13 additions & 2 deletions net/netfilter/xt_set.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ const struct ip_set_adt_opt n = { \
.cmdflags = cfs, \
.timeout = t, \
}
#define ADT_MOPT(n, f, d, fs, cfs, t) \
struct ip_set_adt_opt n = { \
.family = f, \
.dim = d, \
.flags = fs, \
.cmdflags = cfs, \
.timeout = t, \
}

/* Revision 0 interface: backward compatible with netfilter/iptables */

Expand Down Expand Up @@ -296,11 +304,14 @@ static unsigned int
set_target_v2(struct sk_buff *skb, const struct xt_action_param *par)
{
const struct xt_set_info_target_v2 *info = par->targinfo;
ADT_OPT(add_opt, par->family, info->add_set.dim,
info->add_set.flags, info->flags, info->timeout);
ADT_MOPT(add_opt, par->family, info->add_set.dim,
info->add_set.flags, info->flags, info->timeout);
ADT_OPT(del_opt, par->family, info->del_set.dim,
info->del_set.flags, 0, UINT_MAX);

/* Normalize to fit into jiffies */
if (add_opt.timeout > UINT_MAX/MSEC_PER_SEC)
add_opt.timeout = UINT_MAX/MSEC_PER_SEC;
if (info->add_set.index != IPSET_INVALID_ID)
ip_set_add(info->add_set.index, skb, par, &add_opt);
if (info->del_set.index != IPSET_INVALID_ID)
Expand Down

0 comments on commit 127f559

Please sign in to comment.