Commit 143554ac authored by David S. Miller's avatar David S. Miller

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next

Conflicts:
	net/netfilter/nf_log.c

The conflict in nf_log.c is that in 'net' we added CONFIG_PROC_FS
protection around foo_proc_entry() calls to fix a build failure,
whereas in Pablo's tree a guard if() test around a call is
remove_proc_entry() was removed.  Trivially resolved.

Pablo Neira Ayuso says:

====================
The following patchset contains the first batch of
Netfilter/IPVS updates for your net-next tree, they are:

* Three patches with improvements and code refactorization
  for nfnetlink_queue, from Florian Westphal.

* FTP helper now parses replies without brackets, as RFC1123
  recommends, from Jeff Mahoney.

* Rise a warning to tell everyone about ULOG deprecation,
  NFLOG has been already in the kernel tree for long time
  and supersedes the old logging over netlink stub, from
  myself.

* Don't panic if we fail to load netfilter core framework,
  just bail out instead, from myself.

* Add cond_resched_rcu, used by IPVS to allow rescheduling
  while walking over big hashtables, from Simon Horman.

* Change type of IPVS sysctl_sync_qlen_max sysctl to avoid
  possible overflow, from Zhang Yanfei.

* Use strlcpy instead of strncpy to skip zeroing of already
  initialized area to write the extension names in ebtables,
  from Chen Gang.

* Use already existing per-cpu notrack object from xt_CT,
  from Eric Dumazet.

* Save explicit socket lookup in xt_socket now that we have
  early demux, also from Eric Dumazet.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 6bc19fb8 7f87712c
......@@ -35,7 +35,7 @@ static inline void nf_inet_addr_mask(const union nf_inet_addr *a1,
result->all[3] = a1->all[3] & mask->all[3];
}
extern void netfilter_init(void);
extern int netfilter_init(void);
/* Largest hook number + 1 */
#define NF_MAX_HOOKS 8
......
......@@ -2444,6 +2444,15 @@ extern int __cond_resched_softirq(void);
__cond_resched_softirq(); \
})
static inline void cond_resched_rcu(void)
{
#if defined(CONFIG_DEBUG_ATOMIC_SLEEP) || !defined(CONFIG_PREEMPT_RCU)
rcu_read_unlock();
cond_resched();
rcu_read_lock();
#endif
}
/*
* Does a critical section need to be broken due to another
* task waiting?: (technically does not depend on CONFIG_PREEMPT,
......
......@@ -905,7 +905,7 @@ struct ip_vs_app {
struct ipvs_master_sync_state {
struct list_head sync_queue;
struct ip_vs_sync_buff *sync_buff;
int sync_queue_len;
unsigned long sync_queue_len;
unsigned int sync_queue_delay;
struct task_struct *master_thread;
struct delayed_work master_wakeup_work;
......@@ -998,7 +998,7 @@ struct netns_ipvs {
int sysctl_snat_reroute;
int sysctl_sync_ver;
int sysctl_sync_ports;
int sysctl_sync_qlen_max;
unsigned long sysctl_sync_qlen_max;
int sysctl_sync_sock_size;
int sysctl_cache_bypass;
int sysctl_expire_nodest_conn;
......@@ -1085,7 +1085,7 @@ static inline int sysctl_sync_ports(struct netns_ipvs *ipvs)
return ACCESS_ONCE(ipvs->sysctl_sync_ports);
}
static inline int sysctl_sync_qlen_max(struct netns_ipvs *ipvs)
static inline unsigned long sysctl_sync_qlen_max(struct netns_ipvs *ipvs)
{
return ipvs->sysctl_sync_qlen_max;
}
......@@ -1138,7 +1138,7 @@ static inline int sysctl_sync_ports(struct netns_ipvs *ipvs)
return 1;
}
static inline int sysctl_sync_qlen_max(struct netns_ipvs *ipvs)
static inline unsigned long sysctl_sync_qlen_max(struct netns_ipvs *ipvs)
{
return IPVS_SYNC_QLEN_MAX;
}
......
......@@ -15,5 +15,11 @@ struct netns_xt {
struct ebt_table *frame_filter;
struct ebt_table *frame_nat;
#endif
#if IS_ENABLED(CONFIG_IP_NF_TARGET_ULOG)
bool ulog_warn_deprecated;
#endif
#if IS_ENABLED(CONFIG_BRIDGE_EBT_ULOG)
bool ebt_ulog_warn_deprecated;
#endif
};
#endif
......@@ -271,6 +271,12 @@ static int ebt_ulog_tg_check(const struct xt_tgchk_param *par)
{
struct ebt_ulog_info *uloginfo = par->targinfo;
if (!par->net->xt.ebt_ulog_warn_deprecated) {
pr_info("ebt_ulog is deprecated and it will be removed soon, "
"use ebt_nflog instead\n");
par->net->xt.ebt_ulog_warn_deprecated = true;
}
if (uloginfo->nlgroup > 31)
return -EINVAL;
......
......@@ -1339,7 +1339,7 @@ static inline int ebt_make_matchname(const struct ebt_entry_match *m,
/* ebtables expects 32 bytes long names but xt_match names are 29 bytes
long. Copy 29 bytes and fill remaining bytes with zeroes. */
strncpy(name, m->u.match->name, sizeof(name));
strlcpy(name, m->u.match->name, sizeof(name));
if (copy_to_user(hlp, name, EBT_FUNCTION_MAXNAMELEN))
return -EFAULT;
return 0;
......@@ -1351,7 +1351,7 @@ static inline int ebt_make_watchername(const struct ebt_entry_watcher *w,
char __user *hlp = ubase + ((char *)w - base);
char name[EBT_FUNCTION_MAXNAMELEN] = {};
strncpy(name, w->u.watcher->name, sizeof(name));
strlcpy(name, w->u.watcher->name, sizeof(name));
if (copy_to_user(hlp , name, EBT_FUNCTION_MAXNAMELEN))
return -EFAULT;
return 0;
......@@ -1377,7 +1377,7 @@ ebt_make_names(struct ebt_entry *e, const char *base, char __user *ubase)
ret = EBT_WATCHER_ITERATE(e, ebt_make_watchername, base, ubase);
if (ret != 0)
return ret;
strncpy(name, t->u.target->name, sizeof(name));
strlcpy(name, t->u.target->name, sizeof(name));
if (copy_to_user(hlp, name, EBT_FUNCTION_MAXNAMELEN))
return -EFAULT;
return 0;
......
......@@ -111,7 +111,7 @@ config IP_NF_TARGET_REJECT
To compile it as a module, choose M here. If unsure, say N.
config IP_NF_TARGET_ULOG
tristate "ULOG target support"
tristate "ULOG target support (obsolete)"
default m if NETFILTER_ADVANCED=n
---help---
......
......@@ -330,6 +330,12 @@ static int ulog_tg_check(const struct xt_tgchk_param *par)
{
const struct ipt_ulog_info *loginfo = par->targinfo;
if (!par->net->xt.ulog_warn_deprecated) {
pr_info("ULOG is deprecated and it will be removed soon, "
"use NFLOG instead\n");
par->net->xt.ulog_warn_deprecated = true;
}
if (loginfo->prefix[sizeof(loginfo->prefix) - 1] != '\0') {
pr_debug("prefix not null-terminated\n");
return -EINVAL;
......
......@@ -304,17 +304,26 @@ static struct pernet_operations netfilter_net_ops = {
.exit = netfilter_net_exit,
};
void __init netfilter_init(void)
int __init netfilter_init(void)
{
int i, h;
int i, h, ret;
for (i = 0; i < ARRAY_SIZE(nf_hooks); i++) {
for (h = 0; h < NF_MAX_HOOKS; h++)
INIT_LIST_HEAD(&nf_hooks[i][h]);
}
if (register_pernet_subsys(&netfilter_net_ops) < 0)
panic("cannot create netfilter proc entry");
ret = register_pernet_subsys(&netfilter_net_ops);
if (ret < 0)
goto err;
ret = netfilter_log_init();
if (ret < 0)
goto err_pernet;
if (netfilter_log_init() < 0)
panic("cannot initialize nf_log");
return 0;
err_pernet:
unregister_pernet_subsys(&netfilter_net_ops);
err:
return ret;
}
......@@ -975,8 +975,7 @@ static void *ip_vs_conn_array(struct seq_file *seq, loff_t pos)
return cp;
}
}
rcu_read_unlock();
rcu_read_lock();
cond_resched_rcu();
}
return NULL;
......@@ -1015,8 +1014,7 @@ static void *ip_vs_conn_seq_next(struct seq_file *seq, void *v, loff_t *pos)
iter->l = &ip_vs_conn_tab[idx];
return cp;
}
rcu_read_unlock();
rcu_read_lock();
cond_resched_rcu();
}
iter->l = NULL;
return NULL;
......@@ -1206,17 +1204,13 @@ void ip_vs_random_dropentry(struct net *net)
int idx;
struct ip_vs_conn *cp, *cp_c;
rcu_read_lock();
/*
* Randomly scan 1/32 of the whole table every second
*/
for (idx = 0; idx < (ip_vs_conn_tab_size>>5); idx++) {
unsigned int hash = net_random() & ip_vs_conn_tab_mask;
/*
* Lock is actually needed in this loop.
*/
rcu_read_lock();
hlist_for_each_entry_rcu(cp, &ip_vs_conn_tab[hash], c_list) {
if (cp->flags & IP_VS_CONN_F_TEMPLATE)
/* connection template */
......@@ -1252,8 +1246,9 @@ void ip_vs_random_dropentry(struct net *net)
__ip_vs_conn_put(cp);
}
}
rcu_read_unlock();
cond_resched_rcu();
}
rcu_read_unlock();
}
......@@ -1267,11 +1262,8 @@ static void ip_vs_conn_flush(struct net *net)
struct netns_ipvs *ipvs = net_ipvs(net);
flush_again:
rcu_read_lock();
for (idx = 0; idx < ip_vs_conn_tab_size; idx++) {
/*
* Lock is actually needed in this loop.
*/
rcu_read_lock();
hlist_for_each_entry_rcu(cp, &ip_vs_conn_tab[idx], c_list) {
if (!ip_vs_conn_net_eq(cp, net))
......@@ -1286,8 +1278,9 @@ static void ip_vs_conn_flush(struct net *net)
__ip_vs_conn_put(cp);
}
}
rcu_read_unlock();
cond_resched_rcu();
}
rcu_read_unlock();
/* the counter may be not NULL, because maybe some conn entries
are run by slow timer handler or unhashed but still referred */
......
......@@ -1716,9 +1716,9 @@ static struct ctl_table vs_vars[] = {
},
{
.procname = "sync_qlen_max",
.maxlen = sizeof(int),
.maxlen = sizeof(unsigned long),
.mode = 0644,
.proc_handler = proc_dointvec,
.proc_handler = proc_doulongvec_minmax,
},
{
.procname = "sync_sock_size",
......
......@@ -55,10 +55,14 @@ unsigned int (*nf_nat_ftp_hook)(struct sk_buff *skb,
struct nf_conntrack_expect *exp);
EXPORT_SYMBOL_GPL(nf_nat_ftp_hook);
static int try_rfc959(const char *, size_t, struct nf_conntrack_man *, char);
static int try_eprt(const char *, size_t, struct nf_conntrack_man *, char);
static int try_rfc959(const char *, size_t, struct nf_conntrack_man *,
char, unsigned int *);
static int try_rfc1123(const char *, size_t, struct nf_conntrack_man *,
char, unsigned int *);
static int try_eprt(const char *, size_t, struct nf_conntrack_man *,
char, unsigned int *);
static int try_epsv_response(const char *, size_t, struct nf_conntrack_man *,
char);
char, unsigned int *);
static struct ftp_search {
const char *pattern;
......@@ -66,7 +70,7 @@ static struct ftp_search {
char skip;
char term;
enum nf_ct_ftp_type ftptype;
int (*getnum)(const char *, size_t, struct nf_conntrack_man *, char);
int (*getnum)(const char *, size_t, struct nf_conntrack_man *, char, unsigned int *);
} search[IP_CT_DIR_MAX][2] = {
[IP_CT_DIR_ORIGINAL] = {
{
......@@ -90,10 +94,8 @@ static struct ftp_search {
{
.pattern = "227 ",
.plen = sizeof("227 ") - 1,
.skip = '(',
.term = ')',
.ftptype = NF_CT_FTP_PASV,
.getnum = try_rfc959,
.getnum = try_rfc1123,
},
{
.pattern = "229 ",
......@@ -132,8 +134,9 @@ static int try_number(const char *data, size_t dlen, u_int32_t array[],
i++;
else {
/* Unexpected character; true if it's the
terminator and we're finished. */
if (*data == term && i == array_size - 1)
terminator (or we don't care about one)
and we're finished. */
if ((*data == term || !term) && i == array_size - 1)
return len;
pr_debug("Char %u (got %u nums) `%u' unexpected\n",
......@@ -148,7 +151,8 @@ static int try_number(const char *data, size_t dlen, u_int32_t array[],
/* Returns 0, or length of numbers: 192,168,1,1,5,6 */
static int try_rfc959(const char *data, size_t dlen,
struct nf_conntrack_man *cmd, char term)
struct nf_conntrack_man *cmd, char term,
unsigned int *offset)
{
int length;
u_int32_t array[6];
......@@ -163,6 +167,33 @@ static int try_rfc959(const char *data, size_t dlen,
return length;
}
/*
* From RFC 1123:
* The format of the 227 reply to a PASV command is not
* well standardized. In particular, an FTP client cannot
* assume that the parentheses shown on page 40 of RFC-959
* will be present (and in fact, Figure 3 on page 43 omits
* them). Therefore, a User-FTP program that interprets
* the PASV reply must scan the reply for the first digit
* of the host and port numbers.
*/
static int try_rfc1123(const char *data, size_t dlen,
struct nf_conntrack_man *cmd, char term,
unsigned int *offset)
{
int i;
for (i = 0; i < dlen; i++)
if (isdigit(data[i]))
break;
if (i == dlen)
return 0;
*offset += i;
return try_rfc959(data + i, dlen - i, cmd, 0, offset);
}
/* Grab port: number up to delimiter */
static int get_port(const char *data, int start, size_t dlen, char delim,
__be16 *port)
......@@ -191,7 +222,7 @@ static int get_port(const char *data, int start, size_t dlen, char delim,
/* Returns 0, or length of numbers: |1|132.235.1.2|6275| or |2|3ffe::1|6275| */
static int try_eprt(const char *data, size_t dlen, struct nf_conntrack_man *cmd,
char term)
char term, unsigned int *offset)
{
char delim;
int length;
......@@ -239,7 +270,8 @@ static int try_eprt(const char *data, size_t dlen, struct nf_conntrack_man *cmd,
/* Returns 0, or length of numbers: |||6446| */
static int try_epsv_response(const char *data, size_t dlen,
struct nf_conntrack_man *cmd, char term)
struct nf_conntrack_man *cmd, char term,
unsigned int *offset)
{
char delim;
......@@ -261,9 +293,10 @@ static int find_pattern(const char *data, size_t dlen,
unsigned int *numlen,
struct nf_conntrack_man *cmd,
int (*getnum)(const char *, size_t,
struct nf_conntrack_man *, char))
struct nf_conntrack_man *, char,
unsigned int *))
{
size_t i;
size_t i = plen;
pr_debug("find_pattern `%s': dlen = %Zu\n", pattern, dlen);
if (dlen == 0)
......@@ -293,16 +326,18 @@ static int find_pattern(const char *data, size_t dlen,
pr_debug("Pattern matches!\n");
/* Now we've found the constant string, try to skip
to the 'skip' character */
for (i = plen; data[i] != skip; i++)
if (i == dlen - 1) return -1;
if (skip) {
for (i = plen; data[i] != skip; i++)
if (i == dlen - 1) return -1;
/* Skip over the last character */
i++;
/* Skip over the last character */
i++;
}
pr_debug("Skipped up to `%c'!\n", skip);
*numoff = i;
*numlen = getnum(data + i, dlen - i, cmd, term);
*numlen = getnum(data + i, dlen - i, cmd, term, numoff);
if (!*numlen)
return -1;
......
......@@ -369,9 +369,7 @@ static int __net_init nf_log_net_init(struct net *net)
out_sysctl:
#ifdef CONFIG_PROC_FS
/* For init_net: errors will trigger panic, don't unroll on error. */
if (!net_eq(net, &init_net))
remove_proc_entry("nf_log", net->nf.proc_netfilter);
remove_proc_entry("nf_log", net->nf.proc_netfilter);
#endif
return ret;
}
......
......@@ -41,6 +41,14 @@
#define NFQNL_QMAX_DEFAULT 1024
/* We're using struct nlattr which has 16bit nla_len. Note that nla_len
* includes the header length. Thus, the maximum packet length that we
* support is 65531 bytes. We send truncated packets if the specified length
* is larger than that. Userspace can check for presence of NFQA_CAP_LEN
* attribute to detect truncation.
*/
#define NFQNL_MAX_COPY_RANGE (0xffff - NLA_HDRLEN)
struct nfqnl_instance {
struct hlist_node hlist; /* global list of queues */
struct rcu_head rcu;
......@@ -122,7 +130,7 @@ instance_create(struct nfnl_queue_net *q, u_int16_t queue_num,
inst->queue_num = queue_num;
inst->peer_portid = portid;
inst->queue_maxlen = NFQNL_QMAX_DEFAULT;
inst->copy_range = 0xffff;
inst->copy_range = NFQNL_MAX_COPY_RANGE;
inst->copy_mode = NFQNL_COPY_NONE;
spin_lock_init(&inst->lock);
INIT_LIST_HEAD(&inst->queue_list);
......@@ -333,10 +341,9 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
return NULL;
data_len = ACCESS_ONCE(queue->copy_range);
if (data_len == 0 || data_len > entskb->len)
if (data_len > entskb->len)
data_len = entskb->len;
if (!entskb->head_frag ||
skb_headlen(entskb) < L1_CACHE_BYTES ||
skb_shinfo(entskb)->nr_frags >= MAX_SKB_FRAGS)
......@@ -465,7 +472,8 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
if (ct && nfqnl_ct_put(skb, ct, ctinfo) < 0)
goto nla_put_failure;
if (cap_len > 0 && nla_put_be32(skb, NFQA_CAP_LEN, htonl(cap_len)))
if (cap_len > data_len &&
nla_put_be32(skb, NFQA_CAP_LEN, htonl(cap_len)))
goto nla_put_failure;
if (nfqnl_put_packet_info(skb, entskb))
......@@ -509,10 +517,6 @@ __nfqnl_enqueue_packet(struct net *net, struct nfqnl_instance *queue,
}
spin_lock_bh(&queue->lock);
if (!queue->peer_portid) {
err = -EINVAL;
goto err_out_free_nskb;
}
if (queue->queue_total >= queue->queue_maxlen) {
if (queue->flags & NFQA_CFG_F_FAIL_OPEN) {
failopen = 1;
......@@ -731,13 +735,8 @@ nfqnl_set_mode(struct nfqnl_instance *queue,
case NFQNL_COPY_PACKET:
queue->copy_mode = mode;
/* We're using struct nlattr which has 16bit nla_len. Note that
* nla_len includes the header length. Thus, the maximum packet
* length that we support is 65531 bytes. We send truncated
* packets if the specified length is larger than that.
*/
if (range > 0xffff - NLA_HDRLEN)
queue->copy_range = 0xffff - NLA_HDRLEN;
if (range == 0 || range > NFQNL_MAX_COPY_RANGE)
queue->copy_range = NFQNL_MAX_COPY_RANGE;
else
queue->copy_range = range;
break;
......
......@@ -26,6 +26,9 @@ static inline int xt_ct_target(struct sk_buff *skb, struct nf_conn *ct)
if (skb->nfct != NULL)
return XT_CONTINUE;
/* special case the untracked ct : we want the percpu object */
if (!ct)
ct = nf_ct_untracked_get();
atomic_inc(&ct->ct_general.use);
skb->nfct = &ct->ct_general;
skb->nfctinfo = IP_CT_NEW;
......@@ -186,8 +189,7 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par,
int ret = -EOPNOTSUPP;
if (info->flags & XT_CT_NOTRACK) {
ct = nf_ct_untracked_get();
atomic_inc(&ct->ct_general.use);
ct = NULL;
goto out;
}
......@@ -311,7 +313,7 @@ static void xt_ct_tg_destroy(const struct xt_tgdtor_param *par,
struct nf_conn *ct = info->ct;
struct nf_conn_help *help;
if (!nf_ct_is_untracked(ct)) {
if (ct && !nf_ct_is_untracked(ct)) {
help = nfct_help(ct);
if (help)
module_put(help->helper->me);
......@@ -319,8 +321,8 @@ static void xt_ct_tg_destroy(const struct xt_tgdtor_param *par,
nf_ct_l3proto_module_put(par->family);
xt_ct_destroy_timeout(ct);
nf_ct_put(info->ct);
}
nf_ct_put(info->ct);
}
static void xt_ct_tg_destroy_v0(const struct xt_tgdtor_param *par)
......
......@@ -107,7 +107,7 @@ socket_match(const struct sk_buff *skb, struct xt_action_param *par,
{
const struct iphdr *iph = ip_hdr(skb);
struct udphdr _hdr, *hp = NULL;
struct sock *sk;
struct sock *sk = skb->sk;
__be32 uninitialized_var(daddr), uninitialized_var(saddr);
__be16 uninitialized_var(dport), uninitialized_var(sport);
u8 uninitialized_var(protocol);
......@@ -155,9 +155,11 @@ socket_match(const struct sk_buff *skb, struct xt_action_param *par,
}
#endif
sk = nf_tproxy_get_sock_v4(dev_net(skb->dev), protocol,
saddr, daddr, sport, dport, par->in, NFT_LOOKUP_ANY);
if (sk != NULL) {
if (!sk)
sk = nf_tproxy_get_sock_v4(dev_net(skb->dev), protocol,
saddr, daddr, sport, dport,
par->in, NFT_LOOKUP_ANY);
if (sk) {
bool wildcard;
bool transparent = true;
......@@ -173,7 +175,8 @@ socket_match(const struct sk_buff *skb, struct xt_action_param *par,
(sk->sk_state == TCP_TIME_WAIT &&
inet_twsk(sk)->tw_transparent));
xt_socket_put_sk(sk);
if (sk != skb->sk)
xt_socket_put_sk(sk);
if (wildcard || !transparent)
sk = NULL;
......@@ -260,7 +263,7 @@ socket_mt6_v1(const struct sk_buff *skb, struct xt_action_param *par)
{
struct ipv6hdr *iph = ipv6_hdr(skb);
struct udphdr _hdr, *hp = NULL;
struct sock *sk;
struct sock *sk = skb->sk;
struct in6_addr *daddr = NULL, *saddr = NULL;
__be16 uninitialized_var(dport), uninitialized_var(sport);
int thoff = 0, uninitialized_var(tproto);
......@@ -291,9 +294,11 @@ socket_mt6_v1(const struct sk_buff *skb, struct xt_action_param *par)
return false;
}
sk = nf_tproxy_get_sock_v6(dev_net(skb->dev), tproto,
saddr, daddr, sport, dport, par->in, NFT_LOOKUP_ANY);
if (sk != NULL) {
if (!sk)
sk = nf_tproxy_get_sock_v6(dev_net(skb->dev), tproto,
saddr, daddr, sport, dport,
par->in, NFT_LOOKUP_ANY);
if (sk) {
bool wildcard;
bool transparent = true;
......@@ -309,7 +314,8 @@ socket_mt6_v1(const struct sk_buff *skb, struct xt_action_param *par)
(sk->sk_state == TCP_TIME_WAIT &&
inet_twsk(sk)->tw_transparent));
xt_socket_put_sk(sk);
if (sk != skb->sk)
xt_socket_put_sk(sk);
if (wildcard || !transparent)
sk = NULL;
......
......@@ -2641,7 +2641,9 @@ static int __init sock_init(void)
*/
#ifdef CONFIG_NETFILTER
netfilter_init();
err = netfilter_init();
if (err)
goto out;
#endif
#ifdef CONFIG_NETWORK_PHY_TIMESTAMPING
......
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