Merge branch 'iov_iter' into for-next

This commit is contained in:
Al Viro
2014-12-08 20:39:29 -05:00
1101 changed files with 10898 additions and 7935 deletions
+7 -1
View File
@@ -659,7 +659,7 @@ ip_set_nfnl_get_byindex(struct net *net, ip_set_id_t index)
struct ip_set *set;
struct ip_set_net *inst = ip_set_pernet(net);
if (index > inst->ip_set_max)
if (index >= inst->ip_set_max)
return IPSET_INVALID_ID;
nfnl_lock(NFNL_SUBSYS_IPSET);
@@ -1863,6 +1863,12 @@ ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len)
if (*op < IP_SET_OP_VERSION) {
/* Check the version at the beginning of operations */
struct ip_set_req_version *req_version = data;
if (*len < sizeof(struct ip_set_req_version)) {
ret = -EINVAL;
goto done;
}
if (req_version->version != IPSET_PROTOCOL) {
ret = -EPROTO;
goto done;
+4 -2
View File
@@ -316,7 +316,7 @@ __ip_vs_get_out_rt(int skb_af, struct sk_buff *skb, struct ip_vs_dest *dest,
if (unlikely(crosses_local_route_boundary(skb_af, skb, rt_mode,
local))) {
IP_VS_DBG_RL("We are crossing local and non-local addresses"
" daddr=%pI4\n", &dest->addr.ip);
" daddr=%pI4\n", &daddr);
goto err_put;
}
@@ -458,7 +458,7 @@ __ip_vs_get_out_rt_v6(int skb_af, struct sk_buff *skb, struct ip_vs_dest *dest,
if (unlikely(crosses_local_route_boundary(skb_af, skb, rt_mode,
local))) {
IP_VS_DBG_RL("We are crossing local and non-local addresses"
" daddr=%pI6\n", &dest->addr.in6);
" daddr=%pI6\n", daddr);
goto err_put;
}
@@ -846,6 +846,8 @@ ip_vs_prepare_tunneled_skb(struct sk_buff *skb, int skb_af,
new_skb = skb_realloc_headroom(skb, max_headroom);
if (!new_skb)
goto error;
if (skb->sk)
skb_set_owner_w(new_skb, skb->sk);
consume_skb(skb);
skb = new_skb;
}
+8 -6
View File
@@ -611,12 +611,16 @@ __nf_conntrack_confirm(struct sk_buff *skb)
*/
NF_CT_ASSERT(!nf_ct_is_confirmed(ct));
pr_debug("Confirming conntrack %p\n", ct);
/* We have to check the DYING flag inside the lock to prevent
a race against nf_ct_get_next_corpse() possibly called from
user context, else we insert an already 'dead' hash, blocking
further use of that particular connection -JM */
/* We have to check the DYING flag after unlink to prevent
* a race against nf_ct_get_next_corpse() possibly called from
* user context, else we insert an already 'dead' hash, blocking
* further use of that particular connection -JM.
*/
nf_ct_del_from_dying_or_unconfirmed_list(ct);
if (unlikely(nf_ct_is_dying(ct))) {
nf_ct_add_to_dying_list(ct);
nf_conntrack_double_unlock(hash, reply_hash);
local_bh_enable();
return NF_ACCEPT;
@@ -636,8 +640,6 @@ __nf_conntrack_confirm(struct sk_buff *skb)
zone == nf_ct_zone(nf_ct_tuplehash_to_ctrack(h)))
goto out;
nf_ct_del_from_dying_or_unconfirmed_list(ct);
/* Timer relative to confirmation time, not original
setting time, otherwise we'd get timer wrap in
weird delay cases. */
+2 -2
View File
@@ -213,7 +213,7 @@ static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = {
{
/* REPLY */
/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 */
/*syn*/ { sIV, sS2, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sS2 },
/*syn*/ { sIV, sS2, sIV, sIV, sIV, sIV, sIV, sSS, sIV, sS2 },
/*
* sNO -> sIV Never reached.
* sSS -> sS2 Simultaneous open
@@ -223,7 +223,7 @@ static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = {
* sFW -> sIV
* sCW -> sIV
* sLA -> sIV
* sTW -> sIV Reopened connection, but server may not do it.
* sTW -> sSS Reopened connection, but server may have switched role
* sCL -> sIV
*/
/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 */
+24 -18
View File
@@ -1328,10 +1328,10 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
basechain->stats = stats;
} else {
stats = netdev_alloc_pcpu_stats(struct nft_stats);
if (IS_ERR(stats)) {
if (stats == NULL) {
module_put(type->owner);
kfree(basechain);
return PTR_ERR(stats);
return -ENOMEM;
}
rcu_assign_pointer(basechain->stats, stats);
}
@@ -3484,13 +3484,8 @@ static void nft_chain_commit_update(struct nft_trans *trans)
}
}
/* Schedule objects for release via rcu to make sure no packets are accesing
* removed rules.
*/
static void nf_tables_commit_release_rcu(struct rcu_head *rt)
static void nf_tables_commit_release(struct nft_trans *trans)
{
struct nft_trans *trans = container_of(rt, struct nft_trans, rcu_head);
switch (trans->msg_type) {
case NFT_MSG_DELTABLE:
nf_tables_table_destroy(&trans->ctx);
@@ -3612,10 +3607,11 @@ static int nf_tables_commit(struct sk_buff *skb)
}
}
synchronize_rcu();
list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) {
list_del(&trans->list);
trans->ctx.nla = NULL;
call_rcu(&trans->rcu_head, nf_tables_commit_release_rcu);
nf_tables_commit_release(trans);
}
nf_tables_gen_notify(net, skb, NFT_MSG_NEWGEN);
@@ -3623,13 +3619,8 @@ static int nf_tables_commit(struct sk_buff *skb)
return 0;
}
/* Schedule objects for release via rcu to make sure no packets are accesing
* aborted rules.
*/
static void nf_tables_abort_release_rcu(struct rcu_head *rt)
static void nf_tables_abort_release(struct nft_trans *trans)
{
struct nft_trans *trans = container_of(rt, struct nft_trans, rcu_head);
switch (trans->msg_type) {
case NFT_MSG_NEWTABLE:
nf_tables_table_destroy(&trans->ctx);
@@ -3725,11 +3716,12 @@ static int nf_tables_abort(struct sk_buff *skb)
}
}
synchronize_rcu();
list_for_each_entry_safe_reverse(trans, next,
&net->nft.commit_list, list) {
list_del(&trans->list);
trans->ctx.nla = NULL;
call_rcu(&trans->rcu_head, nf_tables_abort_release_rcu);
nf_tables_abort_release(trans);
}
return 0;
@@ -3744,6 +3736,20 @@ static const struct nfnetlink_subsystem nf_tables_subsys = {
.abort = nf_tables_abort,
};
int nft_chain_validate_dependency(const struct nft_chain *chain,
enum nft_chain_type type)
{
const struct nft_base_chain *basechain;
if (chain->flags & NFT_BASE_CHAIN) {
basechain = nft_base_chain(chain);
if (basechain->type->type != type)
return -EOPNOTSUPP;
}
return 0;
}
EXPORT_SYMBOL_GPL(nft_chain_validate_dependency);
/*
* Loop detection - walk through the ruleset beginning at the destination chain
* of a new jump until either the source chain is reached (loop) or all
+11 -1
View File
@@ -47,6 +47,8 @@ static const int nfnl_group2type[NFNLGRP_MAX+1] = {
[NFNLGRP_CONNTRACK_EXP_NEW] = NFNL_SUBSYS_CTNETLINK_EXP,
[NFNLGRP_CONNTRACK_EXP_UPDATE] = NFNL_SUBSYS_CTNETLINK_EXP,
[NFNLGRP_CONNTRACK_EXP_DESTROY] = NFNL_SUBSYS_CTNETLINK_EXP,
[NFNLGRP_NFTABLES] = NFNL_SUBSYS_NFTABLES,
[NFNLGRP_ACCT_QUOTA] = NFNL_SUBSYS_ACCT,
};
void nfnl_lock(__u8 subsys_id)
@@ -464,7 +466,12 @@ static void nfnetlink_rcv(struct sk_buff *skb)
static int nfnetlink_bind(int group)
{
const struct nfnetlink_subsystem *ss;
int type = nfnl_group2type[group];
int type;
if (group <= NFNLGRP_NONE || group > NFNLGRP_MAX)
return -EINVAL;
type = nfnl_group2type[group];
rcu_read_lock();
ss = nfnetlink_get_subsys(type);
@@ -514,6 +521,9 @@ static int __init nfnetlink_init(void)
{
int i;
for (i = NFNLGRP_NONE + 1; i <= NFNLGRP_MAX; i++)
BUG_ON(nfnl_group2type[i] == NFNL_SUBSYS_NONE);
for (i=0; i<NFNL_SUBSYS_COUNT; i++)
mutex_init(&table[i].mutex);
+16 -15
View File
@@ -43,7 +43,8 @@
#define NFULNL_NLBUFSIZ_DEFAULT NLMSG_GOODSIZE
#define NFULNL_TIMEOUT_DEFAULT 100 /* every second */
#define NFULNL_QTHRESH_DEFAULT 100 /* 100 packets */
#define NFULNL_COPY_RANGE_MAX 0xFFFF /* max packet size is limited by 16-bit struct nfattr nfa_len field */
/* max packet size is limited by 16-bit struct nfattr nfa_len field */
#define NFULNL_COPY_RANGE_MAX (0xFFFF - NLA_HDRLEN)
#define PRINTR(x, args...) do { if (net_ratelimit()) \
printk(x, ## args); } while (0);
@@ -252,6 +253,8 @@ nfulnl_set_mode(struct nfulnl_instance *inst, u_int8_t mode,
case NFULNL_COPY_PACKET:
inst->copy_mode = mode;
if (range == 0)
range = NFULNL_COPY_RANGE_MAX;
inst->copy_range = min_t(unsigned int,
range, NFULNL_COPY_RANGE_MAX);
break;
@@ -343,26 +346,25 @@ nfulnl_alloc_skb(struct net *net, u32 peer_portid, unsigned int inst_size,
return skb;
}
static int
static void
__nfulnl_send(struct nfulnl_instance *inst)
{
int status = -1;
if (inst->qlen > 1) {
struct nlmsghdr *nlh = nlmsg_put(inst->skb, 0, 0,
NLMSG_DONE,
sizeof(struct nfgenmsg),
0);
if (!nlh)
if (WARN_ONCE(!nlh, "bad nlskb size: %u, tailroom %d\n",
inst->skb->len, skb_tailroom(inst->skb))) {
kfree_skb(inst->skb);
goto out;
}
}
status = nfnetlink_unicast(inst->skb, inst->net, inst->peer_portid,
MSG_DONTWAIT);
nfnetlink_unicast(inst->skb, inst->net, inst->peer_portid,
MSG_DONTWAIT);
out:
inst->qlen = 0;
inst->skb = NULL;
out:
return status;
}
static void
@@ -649,7 +651,8 @@ nfulnl_log_packet(struct net *net,
+ nla_total_size(sizeof(u_int32_t)) /* gid */
+ nla_total_size(plen) /* prefix */
+ nla_total_size(sizeof(struct nfulnl_msg_packet_hw))
+ nla_total_size(sizeof(struct nfulnl_msg_packet_timestamp));
+ nla_total_size(sizeof(struct nfulnl_msg_packet_timestamp))
+ nla_total_size(sizeof(struct nfgenmsg)); /* NLMSG_DONE */
if (in && skb_mac_header_was_set(skb)) {
size += nla_total_size(skb->dev->hard_header_len)
@@ -678,8 +681,7 @@ nfulnl_log_packet(struct net *net,
break;
case NFULNL_COPY_PACKET:
if (inst->copy_range == 0
|| inst->copy_range > skb->len)
if (inst->copy_range > skb->len)
data_len = skb->len;
else
data_len = inst->copy_range;
@@ -692,8 +694,7 @@ nfulnl_log_packet(struct net *net,
goto unlock_and_release;
}
if (inst->skb &&
size > skb_tailroom(inst->skb) - sizeof(struct nfgenmsg)) {
if (inst->skb && size > skb_tailroom(inst->skb)) {
/* either the queue len is too high or we don't have
* enough room in the skb left. flush to userspace. */
__nfulnl_flush(inst);
+1 -1
View File
@@ -665,7 +665,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
* returned by nf_queue. For instance, callers rely on -ECANCELED to
* mean 'ignore this hook'.
*/
if (IS_ERR(segs))
if (IS_ERR_OR_NULL(segs))
goto out_err;
queued = 0;
err = 0;
+45 -12
View File
@@ -19,9 +19,24 @@
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv6/ip6_tables.h>
#include <asm/uaccess.h> /* for set_fs */
#include <net/netfilter/nf_tables.h>
static int nft_compat_chain_validate_dependency(const char *tablename,
const struct nft_chain *chain)
{
const struct nft_base_chain *basechain;
if (!tablename || !(chain->flags & NFT_BASE_CHAIN))
return 0;
basechain = nft_base_chain(chain);
if (strcmp(tablename, "nat") == 0 &&
basechain->type->type != NFT_CHAIN_T_NAT)
return -EINVAL;
return 0;
}
union nft_entry {
struct ipt_entry e4;
struct ip6t_entry e6;
@@ -74,7 +89,7 @@ nft_target_set_tgchk_param(struct xt_tgchk_param *par,
struct xt_target *target, void *info,
union nft_entry *entry, u8 proto, bool inv)
{
par->net = &init_net;
par->net = ctx->net;
par->table = ctx->table->name;
switch (ctx->afi->family) {
case AF_INET:
@@ -95,6 +110,8 @@ nft_target_set_tgchk_param(struct xt_tgchk_param *par,
const struct nf_hook_ops *ops = &basechain->ops[0];
par->hook_mask = 1 << ops->hooknum;
} else {
par->hook_mask = 0;
}
par->family = ctx->afi->family;
}
@@ -151,6 +168,10 @@ nft_target_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
union nft_entry e = {};
int ret;
ret = nft_compat_chain_validate_dependency(target->table, ctx->chain);
if (ret < 0)
goto err;
target_compat_from_user(target, nla_data(tb[NFTA_TARGET_INFO]), info);
if (ctx->nla[NFTA_RULE_COMPAT]) {
@@ -216,6 +237,7 @@ static int nft_target_validate(const struct nft_ctx *ctx,
{
struct xt_target *target = expr->ops->data;
unsigned int hook_mask = 0;
int ret;
if (ctx->chain->flags & NFT_BASE_CHAIN) {
const struct nft_base_chain *basechain =
@@ -223,11 +245,13 @@ static int nft_target_validate(const struct nft_ctx *ctx,
const struct nf_hook_ops *ops = &basechain->ops[0];
hook_mask = 1 << ops->hooknum;
if (hook_mask & target->hooks)
return 0;
if (!(hook_mask & target->hooks))
return -EINVAL;
/* This target is being called from an invalid chain */
return -EINVAL;
ret = nft_compat_chain_validate_dependency(target->table,
ctx->chain);
if (ret < 0)
return ret;
}
return 0;
}
@@ -272,7 +296,7 @@ nft_match_set_mtchk_param(struct xt_mtchk_param *par, const struct nft_ctx *ctx,
struct xt_match *match, void *info,
union nft_entry *entry, u8 proto, bool inv)
{
par->net = &init_net;
par->net = ctx->net;
par->table = ctx->table->name;
switch (ctx->afi->family) {
case AF_INET:
@@ -293,6 +317,8 @@ nft_match_set_mtchk_param(struct xt_mtchk_param *par, const struct nft_ctx *ctx,
const struct nf_hook_ops *ops = &basechain->ops[0];
par->hook_mask = 1 << ops->hooknum;
} else {
par->hook_mask = 0;
}
par->family = ctx->afi->family;
}
@@ -320,6 +346,10 @@ nft_match_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
union nft_entry e = {};
int ret;
ret = nft_compat_chain_validate_dependency(match->table, ctx->chain);
if (ret < 0)
goto err;
match_compat_from_user(match, nla_data(tb[NFTA_MATCH_INFO]), info);
if (ctx->nla[NFTA_RULE_COMPAT]) {
@@ -379,6 +409,7 @@ static int nft_match_validate(const struct nft_ctx *ctx,
{
struct xt_match *match = expr->ops->data;
unsigned int hook_mask = 0;
int ret;
if (ctx->chain->flags & NFT_BASE_CHAIN) {
const struct nft_base_chain *basechain =
@@ -386,11 +417,13 @@ static int nft_match_validate(const struct nft_ctx *ctx,
const struct nf_hook_ops *ops = &basechain->ops[0];
hook_mask = 1 << ops->hooknum;
if (hook_mask & match->hooks)
return 0;
if (!(hook_mask & match->hooks))
return -EINVAL;
/* This match is being called from an invalid chain */
return -EINVAL;
ret = nft_compat_chain_validate_dependency(match->table,
ctx->chain);
if (ret < 0)
return ret;
}
return 0;
}
@@ -611,7 +644,7 @@ nft_target_select_ops(const struct nft_ctx *ctx,
family = ctx->afi->family;
/* Re-use the existing target if it's already loaded. */
list_for_each_entry(nft_target, &nft_match_list, head) {
list_for_each_entry(nft_target, &nft_target_list, head) {
struct xt_target *target = nft_target->ops.data;
if (strcmp(target->name, tg_name) == 0 &&
+12
View File
@@ -26,6 +26,11 @@ int nft_masq_init(const struct nft_ctx *ctx,
const struct nlattr * const tb[])
{
struct nft_masq *priv = nft_expr_priv(expr);
int err;
err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT);
if (err < 0)
return err;
if (tb[NFTA_MASQ_FLAGS] == NULL)
return 0;
@@ -55,5 +60,12 @@ nla_put_failure:
}
EXPORT_SYMBOL_GPL(nft_masq_dump);
int nft_masq_validate(const struct nft_ctx *ctx, const struct nft_expr *expr,
const struct nft_data **data)
{
return nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT);
}
EXPORT_SYMBOL_GPL(nft_masq_validate);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>");
+54 -32
View File
@@ -95,7 +95,13 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
u32 family;
int err;
if (tb[NFTA_NAT_TYPE] == NULL)
err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT);
if (err < 0)
return err;
if (tb[NFTA_NAT_TYPE] == NULL ||
(tb[NFTA_NAT_REG_ADDR_MIN] == NULL &&
tb[NFTA_NAT_REG_PROTO_MIN] == NULL))
return -EINVAL;
switch (ntohl(nla_get_be32(tb[NFTA_NAT_TYPE]))) {
@@ -120,38 +126,44 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
priv->family = family;
if (tb[NFTA_NAT_REG_ADDR_MIN]) {
priv->sreg_addr_min = ntohl(nla_get_be32(
tb[NFTA_NAT_REG_ADDR_MIN]));
priv->sreg_addr_min =
ntohl(nla_get_be32(tb[NFTA_NAT_REG_ADDR_MIN]));
err = nft_validate_input_register(priv->sreg_addr_min);
if (err < 0)
return err;
if (tb[NFTA_NAT_REG_ADDR_MAX]) {
priv->sreg_addr_max =
ntohl(nla_get_be32(tb[NFTA_NAT_REG_ADDR_MAX]));
err = nft_validate_input_register(priv->sreg_addr_max);
if (err < 0)
return err;
} else {
priv->sreg_addr_max = priv->sreg_addr_min;
}
}
if (tb[NFTA_NAT_REG_ADDR_MAX]) {
priv->sreg_addr_max = ntohl(nla_get_be32(
tb[NFTA_NAT_REG_ADDR_MAX]));
err = nft_validate_input_register(priv->sreg_addr_max);
if (err < 0)
return err;
} else
priv->sreg_addr_max = priv->sreg_addr_min;
if (tb[NFTA_NAT_REG_PROTO_MIN]) {
priv->sreg_proto_min = ntohl(nla_get_be32(
tb[NFTA_NAT_REG_PROTO_MIN]));
priv->sreg_proto_min =
ntohl(nla_get_be32(tb[NFTA_NAT_REG_PROTO_MIN]));
err = nft_validate_input_register(priv->sreg_proto_min);
if (err < 0)
return err;
}
if (tb[NFTA_NAT_REG_PROTO_MAX]) {
priv->sreg_proto_max = ntohl(nla_get_be32(
tb[NFTA_NAT_REG_PROTO_MAX]));
err = nft_validate_input_register(priv->sreg_proto_max);
if (err < 0)
return err;
} else
priv->sreg_proto_max = priv->sreg_proto_min;
if (tb[NFTA_NAT_REG_PROTO_MAX]) {
priv->sreg_proto_max =
ntohl(nla_get_be32(tb[NFTA_NAT_REG_PROTO_MAX]));
err = nft_validate_input_register(priv->sreg_proto_max);
if (err < 0)
return err;
} else {
priv->sreg_proto_max = priv->sreg_proto_min;
}
}
if (tb[NFTA_NAT_FLAGS]) {
priv->flags = ntohl(nla_get_be32(tb[NFTA_NAT_FLAGS]));
@@ -179,17 +191,19 @@ static int nft_nat_dump(struct sk_buff *skb, const struct nft_expr *expr)
if (nla_put_be32(skb, NFTA_NAT_FAMILY, htonl(priv->family)))
goto nla_put_failure;
if (nla_put_be32(skb,
NFTA_NAT_REG_ADDR_MIN, htonl(priv->sreg_addr_min)))
goto nla_put_failure;
if (nla_put_be32(skb,
NFTA_NAT_REG_ADDR_MAX, htonl(priv->sreg_addr_max)))
goto nla_put_failure;
if (priv->sreg_addr_min) {
if (nla_put_be32(skb, NFTA_NAT_REG_ADDR_MIN,
htonl(priv->sreg_addr_min)) ||
nla_put_be32(skb, NFTA_NAT_REG_ADDR_MAX,
htonl(priv->sreg_addr_max)))
goto nla_put_failure;
}
if (priv->sreg_proto_min) {
if (nla_put_be32(skb, NFTA_NAT_REG_PROTO_MIN,
htonl(priv->sreg_proto_min)))
goto nla_put_failure;
if (nla_put_be32(skb, NFTA_NAT_REG_PROTO_MAX,
htonl(priv->sreg_proto_min)) ||
nla_put_be32(skb, NFTA_NAT_REG_PROTO_MAX,
htonl(priv->sreg_proto_max)))
goto nla_put_failure;
}
@@ -205,6 +219,13 @@ nla_put_failure:
return -1;
}
static int nft_nat_validate(const struct nft_ctx *ctx,
const struct nft_expr *expr,
const struct nft_data **data)
{
return nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT);
}
static struct nft_expr_type nft_nat_type;
static const struct nft_expr_ops nft_nat_ops = {
.type = &nft_nat_type,
@@ -212,6 +233,7 @@ static const struct nft_expr_ops nft_nat_ops = {
.eval = nft_nat_eval,
.init = nft_nat_init,
.dump = nft_nat_dump,
.validate = nft_nat_validate,
};
static struct nft_expr_type nft_nat_type __read_mostly = {