[Devel] [PATCH 01/14] ve/netfilter: Basic ve transformations
Alexander Mikhalitsyn
alexander.mikhalitsyn at virtuozzo.com
Fri Apr 30 15:45:29 MSK 2021
From: Stanislav Kinsburskiy <skinsbursky at virtuozzo.com>
Rebasing and splitting netfilters sybsystem
(port 66-diff-ve-net-netfilter-combined).
Part 1.
https://jira.sw.ru/browse/PSBM-18322
Signed-off-by: Kirill Tkhai <ktkhai at parallels.com>
khorenko@: rebase to kernel-3.10.0-229.7.2.el7:
* hunk for include/net/netfilter/xt_log.h has been dropped
cause the file absents now
* couple of CAP_NET_ADMIN -> CAP_NET_ADMIN + CAP_VE_NET_ADMIN
replacements have been dropped because Initial patch
already have proper version
+++
ve/net/printk: net_veboth_ratelimited introduced
net_veboth_ratelimited is required to save net-ratelimited messages
both into host and into containers dmesg buffers
Signed-off-by: Vasily Averin <vvs at openvz.org>
Acked-by: Kirill Tkhai <ktkhai at odin.com>
==============================================
net: remove CAP_VE_NET_ADMIN from "ve/netfilter: Basic ve transformations"
https://jira.sw.ru/browse/PSBM-39077
Signed-off-by: Andrew Vagin <avagin at virtuozzo.com>
Reviewed-by: Vladimir Davydov <vdavydov at virtuozzo.com>
==============================================
VZ 8 rebase part https://jira.sw.ru/browse/PSBM-127783
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn at virtuozzo.com>
---
include/linux/netfilter/x_tables.h | 17 ++++++++
net/ipv4/netfilter/ip_tables.c | 27 +++++++++---
net/ipv4/netfilter/ipt_REJECT.c | 4 +-
net/ipv6/netfilter/ip6_tables.c | 15 +++++--
net/netfilter/x_tables.c | 70 +++++++++++++++---------------
net/netfilter/xt_TCPMSS.c | 12 ++---
net/netfilter/xt_limit.c | 4 +-
7 files changed, 95 insertions(+), 54 deletions(-)
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index 9077b3ebea08..781ac5c3649e 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -531,4 +531,21 @@ int xt_compat_check_entry_offsets(const void *base, const char *elems,
unsigned int next_offset);
#endif /* CONFIG_COMPAT */
+
+#ifdef CONFIG_VE
+static inline bool ve_xt_table_forbidden(struct xt_table *xt)
+{
+ /*
+ * The only purpose to have this check as a separate
+ * helper is "grep"-a-bility
+ *
+ * If this helper hit it means that a VE has been
+ * configured without the particular xt_table support
+ */
+ return xt == NULL;
+}
+#else
+static inline bool ve_xt_table_forbidden(struct xt_table *xt) { return true; }
+#endif
+
#endif /* _X_TABLES_H */
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index e3bc52578af3..ae2112cd58be 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -242,6 +242,9 @@ ipt_do_table(struct sk_buff *skb,
struct xt_action_param acpar;
unsigned int addend;
+ if (ve_xt_table_forbidden(table))
+ return NF_ACCEPT;
+
/* Initialization */
stackidx = 0;
ip = ip_hdr(skb);
@@ -391,9 +394,12 @@ mark_source_chains(const struct xt_table_info *newinfo,
= (void *)ipt_get_target_c(e);
int visited = e->comefrom & (1 << hook);
- if (e->comefrom & (1 << NF_INET_NUMHOOKS))
+ if (e->comefrom & (1 << NF_INET_NUMHOOKS)) {
+ ve_printk(VE_LOG, "iptables: loop hook %u pos "
+ "%u %08X.\n",
+ hook, pos, e->comefrom);
return 0;
-
+ }
e->comefrom |= ((1 << hook) | (1 << NF_INET_NUMHOOKS));
/* Unconditional return/END. */
@@ -1537,13 +1543,17 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len)
return ret;
}
+static int
+do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len);
+
static int
compat_do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user,
unsigned int len)
{
+ struct user_namespace *user_ns = sock_net(sk)->user_ns;
int ret;
- if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
+ if (!ns_capable(user_ns, CAP_NET_ADMIN))
return -EPERM;
switch (cmd) {
@@ -1556,7 +1566,7 @@ compat_do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user,
break;
default:
- ret = -EINVAL;
+ ret = do_ipt_set_ctl(sk, cmd, user, len);
}
return ret;
@@ -1643,9 +1653,10 @@ static int do_ipt_get_ctl(struct sock *, int, void __user *, int *);
static int
compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
{
+ struct user_namespace *user_ns = sock_net(sk)->user_ns;
int ret;
- if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
+ if (!ns_capable(user_ns, CAP_NET_ADMIN))
return -EPERM;
switch (cmd) {
@@ -1665,9 +1676,10 @@ compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
static int
do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
{
+ struct user_namespace *user_ns = sock_net(sk)->user_ns;
int ret;
- if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
+ if (!ns_capable(user_ns, CAP_NET_ADMIN))
return -EPERM;
switch (cmd) {
@@ -1689,9 +1701,10 @@ do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
static int
do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
{
+ struct user_namespace *user_ns = sock_net(sk)->user_ns;
int ret;
- if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
+ if (!ns_capable(user_ns, CAP_NET_ADMIN))
return -EPERM;
switch (cmd) {
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index e8bed3390e58..271b1c9623d3 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -74,13 +74,13 @@ static int reject_tg_check(const struct xt_tgchk_param *par)
const struct ipt_entry *e = par->entryinfo;
if (rejinfo->with == IPT_ICMP_ECHOREPLY) {
- pr_info_ratelimited("ECHOREPLY no longer supported.\n");
+ ve_printk(VE_LOG, "ECHOREPLY no longer supported.\n");
return -EINVAL;
} else if (rejinfo->with == IPT_TCP_RESET) {
/* Must specify that it's a TCP packet */
if (e->ip.proto != IPPROTO_TCP ||
(e->ip.invflags & XT_INV_PROTO)) {
- pr_info_ratelimited("TCP_RESET invalid for non-tcp\n");
+ ve_printk(VE_LOG, "TCP_RESET invalid for non-tcp\n");
return -EINVAL;
}
}
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 238a1f135499..5075c8aae734 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -266,6 +266,9 @@ ip6t_do_table(struct sk_buff *skb,
struct xt_action_param acpar;
unsigned int addend;
+ if (ve_xt_table_forbidden(table))
+ return NF_ACCEPT;
+
/* Initialization */
stackidx = 0;
indev = state->in ? state->in->name : nulldevname;
@@ -1550,9 +1553,10 @@ static int
compat_do_ip6t_set_ctl(struct sock *sk, int cmd, void __user *user,
unsigned int len)
{
+ struct user_namespace *user_ns = sock_net(sk)->user_ns;
int ret;
- if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
+ if (!ns_capable(user_ns, CAP_NET_ADMIN))
return -EPERM;
switch (cmd) {
@@ -1652,9 +1656,10 @@ static int do_ip6t_get_ctl(struct sock *, int, void __user *, int *);
static int
compat_do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
{
+ struct user_namespace *user_ns = sock_net(sk)->user_ns;
int ret;
- if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
+ if (!ns_capable(user_ns, CAP_NET_ADMIN))
return -EPERM;
switch (cmd) {
@@ -1674,9 +1679,10 @@ compat_do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
static int
do_ip6t_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
{
+ struct user_namespace *user_ns = sock_net(sk)->user_ns;
int ret;
- if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
+ if (!ns_capable(user_ns, CAP_NET_ADMIN))
return -EPERM;
switch (cmd) {
@@ -1698,9 +1704,10 @@ do_ip6t_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
static int
do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
{
+ struct user_namespace *user_ns = sock_net(sk)->user_ns;
int ret;
- if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
+ if (!ns_capable(user_ns, CAP_NET_ADMIN))
return -EPERM;
switch (cmd) {
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index c5014610d3b9..cfd218769c62 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -473,35 +473,36 @@ int xt_check_match(struct xt_mtchk_param *par,
* ebt_among is exempt from centralized matchsize checking
* because it uses a dynamic-size data set.
*/
- pr_err_ratelimited("%s_tables: %s.%u match: invalid size %u (kernel) != (user) %u\n",
- xt_prefix[par->family], par->match->name,
- par->match->revision,
- XT_ALIGN(par->match->matchsize), size);
+ ve_printk(VE_LOG, "%s_tables: %s.%u match: invalid size "
+ "%u (kernel) != (user) %u\n",
+ xt_prefix[par->family], par->match->name,
+ par->match->revision,
+ XT_ALIGN(par->match->matchsize), size);
return -EINVAL;
}
if (par->match->table != NULL &&
strcmp(par->match->table, par->table) != 0) {
- pr_info_ratelimited("%s_tables: %s match: only valid in %s table, not %s\n",
- xt_prefix[par->family], par->match->name,
- par->match->table, par->table);
+ ve_printk(VE_LOG, "%s_tables: %s match: only valid in %s table, not %s\n",
+ xt_prefix[par->family], par->match->name,
+ par->match->table, par->table);
return -EINVAL;
}
if (par->match->hooks && (par->hook_mask & ~par->match->hooks) != 0) {
char used[64], allow[64];
- pr_info_ratelimited("%s_tables: %s match: used from hooks %s, but only valid from %s\n",
- xt_prefix[par->family], par->match->name,
- textify_hooks(used, sizeof(used),
- par->hook_mask, par->family),
- textify_hooks(allow, sizeof(allow),
- par->match->hooks,
- par->family));
+ ve_printk(VE_LOG, "%s_tables: %s match: used from hooks %s, but only "
+ "valid from %s\n",
+ xt_prefix[par->family], par->match->name,
+ textify_hooks(used, sizeof(used), par->hook_mask,
+ par->family),
+ textify_hooks(allow, sizeof(allow), par->match->hooks,
+ par->family));
return -EINVAL;
}
if (par->match->proto && (par->match->proto != proto || inv_proto)) {
- pr_info_ratelimited("%s_tables: %s match: only valid for protocol %u\n",
- xt_prefix[par->family], par->match->name,
- par->match->proto);
+ ve_printk(VE_LOG, "%s_tables: %s match: only valid for protocol %u\n",
+ xt_prefix[par->family], par->match->name,
+ par->match->proto);
return -EINVAL;
}
if (par->match->checkentry != NULL) {
@@ -991,35 +992,36 @@ int xt_check_target(struct xt_tgchk_param *par,
int ret;
if (XT_ALIGN(par->target->targetsize) != size) {
- pr_err_ratelimited("%s_tables: %s.%u target: invalid size %u (kernel) != (user) %u\n",
- xt_prefix[par->family], par->target->name,
- par->target->revision,
- XT_ALIGN(par->target->targetsize), size);
+ ve_printk(VE_LOG, "%s_tables: %s.%u target: invalid size "
+ "%u (kernel) != (user) %u\n",
+ xt_prefix[par->family], par->target->name,
+ par->target->revision,
+ XT_ALIGN(par->target->targetsize), size);
return -EINVAL;
}
if (par->target->table != NULL &&
strcmp(par->target->table, par->table) != 0) {
- pr_info_ratelimited("%s_tables: %s target: only valid in %s table, not %s\n",
- xt_prefix[par->family], par->target->name,
- par->target->table, par->table);
+ ve_printk(VE_LOG, "%s_tables: %s target: only valid in %s table, not %s\n",
+ xt_prefix[par->family], par->target->name,
+ par->target->table, par->table);
return -EINVAL;
}
if (par->target->hooks && (par->hook_mask & ~par->target->hooks) != 0) {
char used[64], allow[64];
- pr_info_ratelimited("%s_tables: %s target: used from hooks %s, but only usable from %s\n",
- xt_prefix[par->family], par->target->name,
- textify_hooks(used, sizeof(used),
- par->hook_mask, par->family),
- textify_hooks(allow, sizeof(allow),
- par->target->hooks,
- par->family));
+ ve_printk(VE_LOG, "%s_tables: %s target: used from hooks %s, but only "
+ "usable from %s\n",
+ xt_prefix[par->family], par->target->name,
+ textify_hooks(used, sizeof(used), par->hook_mask,
+ par->family),
+ textify_hooks(allow, sizeof(allow), par->target->hooks,
+ par->family));
return -EINVAL;
}
if (par->target->proto && (par->target->proto != proto || inv_proto)) {
- pr_info_ratelimited("%s_tables: %s target: only valid for protocol %u\n",
- xt_prefix[par->family], par->target->name,
- par->target->proto);
+ ve_printk(VE_LOG, "%s_tables: %s target: only valid for protocol %u\n",
+ xt_prefix[par->family], par->target->name,
+ par->target->proto);
return -EINVAL;
}
if (par->target->checkentry != NULL) {
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c
index 98efb202f8b4..2a50584c7247 100644
--- a/net/netfilter/xt_TCPMSS.c
+++ b/net/netfilter/xt_TCPMSS.c
@@ -108,7 +108,7 @@ tcpmss_mangle_packet(struct sk_buff *skb,
unsigned int min_mtu = min(dst_mtu(skb_dst(skb)), in_mtu);
if (min_mtu <= minlen) {
- net_err_ratelimited("unknown or invalid path-MTU (%u)\n",
+ net_velog_ratelimited("unknown or invalid path-MTU (%u)\n",
min_mtu);
return -1;
}
@@ -273,7 +273,8 @@ static int tcpmss_tg4_check(const struct xt_tgchk_param *par)
(par->hook_mask & ~((1 << NF_INET_FORWARD) |
(1 << NF_INET_LOCAL_OUT) |
(1 << NF_INET_POST_ROUTING))) != 0) {
- pr_info_ratelimited("path-MTU clamping only supported in FORWARD, OUTPUT and POSTROUTING hooks\n");
+ ve_printk(VE_LOG, "path-MTU clamping only supported in "
+ "FORWARD, OUTPUT and POSTROUTING hooks\n");
return -EINVAL;
}
if (par->nft_compat)
@@ -282,7 +283,7 @@ static int tcpmss_tg4_check(const struct xt_tgchk_param *par)
xt_ematch_foreach(ematch, e)
if (find_syn_match(ematch))
return 0;
- pr_info_ratelimited("Only works on TCP SYN packets\n");
+ ve_printk(VE_LOG, "Only works on TCP SYN packets\n");
return -EINVAL;
}
@@ -297,7 +298,8 @@ static int tcpmss_tg6_check(const struct xt_tgchk_param *par)
(par->hook_mask & ~((1 << NF_INET_FORWARD) |
(1 << NF_INET_LOCAL_OUT) |
(1 << NF_INET_POST_ROUTING))) != 0) {
- pr_info_ratelimited("path-MTU clamping only supported in FORWARD, OUTPUT and POSTROUTING hooks\n");
+ ve_printk(VE_LOG, "path-MTU clamping only supported in "
+ "FORWARD, OUTPUT and POSTROUTING hooks\n");
return -EINVAL;
}
if (par->nft_compat)
@@ -306,7 +308,7 @@ static int tcpmss_tg6_check(const struct xt_tgchk_param *par)
xt_ematch_foreach(ematch, e)
if (find_syn_match(ematch))
return 0;
- pr_info_ratelimited("Only works on TCP SYN packets\n");
+ ve_printk(VE_LOG, "Only works on TCP SYN packets\n");
return -EINVAL;
}
#endif
diff --git a/net/netfilter/xt_limit.c b/net/netfilter/xt_limit.c
index 9f098ecb2449..ea7ffb9c39d6 100644
--- a/net/netfilter/xt_limit.c
+++ b/net/netfilter/xt_limit.c
@@ -106,8 +106,8 @@ static int limit_mt_check(const struct xt_mtchk_param *par)
/* Check for overflow. */
if (r->burst == 0
|| user2credits(r->avg * r->burst) < user2credits(r->avg)) {
- pr_info_ratelimited("Overflow, try lower: %u/%u\n",
- r->avg, r->burst);
+ ve_printk(VE_LOG, "Overflow, try lower: %u/%u\n",
+ r->avg, r->burst);
return -ERANGE;
}
--
2.28.0
More information about the Devel
mailing list