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