Revert NFTSet feature

This reverts PR #22587 and its follow-up commit. More specifically,
2299b1cae3 (partially),
e176f855278d5098d3fecc5aa24ba702147d42e0,
ceb46a31a01b3d3d1d6095d857e29ea214a2776b, and
51bb9076ab8c050bebb64db5035852385accda35.

The PR was merged without final approval, and has several issues:
- OSS fuzz reported issues in the conf parser,
- It calls synchrnous netlink call, it should not be especially in PID1,
- The importance of NFTSet for CGroup and DynamicUser may be
  questionable, at least, there was no justification PID1 should support
  it.
- For networkd, it should be implemented with Request object,
- There is no test for the feature.

Fixes #23711.
Fixes #23717.
Fixes #23719.
Fixes #23720.
Fixes #23721.
Fixes #23759.
This commit is contained in:
Yu Watanabe
2022-06-22 22:23:58 +09:00
parent 127b26f3d8
commit b48ed70c79
33 changed files with 7 additions and 1395 deletions
-92
View File
@@ -16,7 +16,6 @@
#include "exec-util.h"
#include "exit-status.h"
#include "fileio.h"
#include "firewall-util.h"
#include "hexdecoct.h"
#include "hostname-util.h"
#include "in-addr-util.h"
@@ -435,91 +434,6 @@ static int bus_append_ip_address_access(sd_bus_message *m, int family, const uni
return sd_bus_message_close_container(m);
}
static int bus_append_nft_set(sd_bus_message *m, const char *field, const char *eq) {
int r;
assert(m);
if (isempty(eq)) {
r = sd_bus_message_append(m, "(sv)", field, "a(iss)", 0);
if (r < 0)
return bus_log_create_error(r);
return 1;
}
r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_open_container(m, 'v', "a(iss)");
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_open_container(m, 'a', "(iss)");
if (r < 0)
return bus_log_create_error(r);
for (;;) {
_cleanup_free_ char *word = NULL;
int family;
r = extract_first_word(&eq, &word, ":", 0);
if (r == -ENOMEM)
return log_oom();
if (r < 0)
return log_error_errno(r, "Failed to parse %s: %m", field);
if (isempty(word)) {
log_error("Failed to parse %s", field);
return 0;
}
family = nfproto_from_string(word);
if (family < 0)
return log_error_errno(family, "Failed to parse %s: %m", field);
r = extract_first_word(&eq, &word, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS);
if (r == -ENOMEM)
return log_oom();
if (r < 0)
return log_error_errno(r, "Failed to parse %s: %m", field);
if (isempty(word) || isempty(eq)) {
log_error("Failed to parse %s", field);
return 0;
}
_cleanup_free_ char *unescaped = NULL;
ssize_t l;
l = cunescape(eq, 0, &unescaped);
if (l < 0)
return log_error_errno(l, "Failed to unescape %s= value: %s", field, eq);
r = sd_bus_message_append(m, "(iss)", family, word, eq);
r = sd_bus_message_close_container(m);
if (r < 0)
return bus_log_create_error(r);
}
r = sd_bus_message_close_container(m);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_close_container(m);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_close_container(m);
if (r < 0)
return bus_log_create_error(r);
return 1;
}
static int bus_append_cgroup_property(sd_bus_message *m, const char *field, const char *eq) {
int r;
@@ -977,9 +891,6 @@ static int bus_append_cgroup_property(sd_bus_message *m, const char *field, cons
return 1;
}
if (streq(field, "ControlGroupNFTSet"))
return bus_append_nft_set(m, field, eq);
return 0;
}
@@ -2137,9 +2048,6 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
return 1;
}
if (STR_IN_SET(field, "DynamicUserNFTSet"))
return bus_append_nft_set(m, field, eq);
return 0;
}
+7 -290
View File
@@ -14,13 +14,11 @@
#include "sd-netlink.h"
#include "alloc-util.h"
#include "extract-word.h"
#include "firewall-util.h"
#include "firewall-util-private.h"
#include "in-addr-util.h"
#include "macro.h"
#include "socket-util.h"
#include "string-table.h"
#include "time-util.h"
#define NFT_SYSTEMD_DNAT_MAP_NAME "map_port_ipport"
@@ -850,12 +848,9 @@ static int nft_message_add_setelem_ip6range(
#define NFT_MASQ_MSGS 3
static int nft_set_element_op_in_addr(
sd_netlink *nfnl,
const char *table,
const char *set,
static int fw_nftables_add_masquerade_internal(
FirewallContext *ctx,
bool add,
int nfproto,
int af,
const union in_addr_union *source,
unsigned int source_prefixlen) {
@@ -870,14 +865,14 @@ static int nft_set_element_op_in_addr(
if (af == AF_INET6 && source_prefixlen < 8)
return -EINVAL;
r = sd_nfnl_message_batch_begin(nfnl, &transaction[0]);
r = sd_nfnl_message_batch_begin(ctx->nfnl, &transaction[0]);
if (r < 0)
return r;
tsize = 1;
if (add)
r = sd_nfnl_nft_message_new_setelems_begin(nfnl, &transaction[tsize], nfproto, table, set);
r = sd_nfnl_nft_message_new_setelems_begin(ctx->nfnl, &transaction[tsize], af, NFT_SYSTEMD_TABLE_NAME, NFT_SYSTEMD_MASQ_SET_NAME);
else
r = sd_nfnl_nft_message_del_setelems_begin(nfnl, &transaction[tsize], nfproto, table, set);
r = sd_nfnl_nft_message_del_setelems_begin(ctx->nfnl, &transaction[tsize], af, NFT_SYSTEMD_TABLE_NAME, NFT_SYSTEMD_MASQ_SET_NAME);
if (r < 0)
goto out_unref;
@@ -890,12 +885,12 @@ static int nft_set_element_op_in_addr(
++tsize;
assert(tsize < NFT_MASQ_MSGS);
r = sd_nfnl_message_batch_end(nfnl, &transaction[tsize]);
r = sd_nfnl_message_batch_end(ctx->nfnl, &transaction[tsize]);
if (r < 0)
return r;
++tsize;
r = nfnl_netlink_sendv(nfnl, transaction, tsize);
r = nfnl_netlink_sendv(ctx->nfnl, transaction, tsize);
out_unref:
while (tsize > 0)
@@ -903,65 +898,6 @@ out_unref:
return r < 0 ? r : 0;
}
static int nft_set_element_op_in_addr_open(
bool add,
const NFTSetContext *nft_set_context,
int af,
const union in_addr_union *address,
unsigned int prefixlen) {
_cleanup_(sd_netlink_unrefp) sd_netlink *nfnl = NULL;
const char *table, *set;
int r, nfproto;
assert(nft_set_context);
nfproto = nft_set_context->nfproto;
table = nft_set_context->table;
assert(table);
set = nft_set_context->set;
assert(set);
r = sd_nfnl_socket_open(&nfnl);
if (r < 0)
return r;
r = nft_set_element_op_in_addr(nfnl, table, set,
add, nfproto, af, address, prefixlen);
log_debug("%s NFT family %s table %s set %s IP address %s",
add ? "Added" : "Deleted",
nfproto_to_string(nfproto), table, set,
IN_ADDR_PREFIX_TO_STRING(af, address, prefixlen));
return r;
}
int nft_set_element_add_in_addr(
const NFTSetContext *nft_set_context,
int af,
const union in_addr_union *address,
unsigned int prefixlen) {
return nft_set_element_op_in_addr_open(true, nft_set_context, af, address, prefixlen);
}
int nft_set_element_del_in_addr(
const NFTSetContext *nft_set_context,
int af,
const union in_addr_union *address,
unsigned int prefixlen) {
return nft_set_element_op_in_addr_open(false, nft_set_context, af, address, prefixlen);
}
static int fw_nftables_add_masquerade_internal(
FirewallContext *ctx,
bool add,
int af,
const union in_addr_union *source,
unsigned int source_prefixlen) {
return nft_set_element_op_in_addr(ctx->nfnl, NFT_SYSTEMD_TABLE_NAME, NFT_SYSTEMD_MASQ_SET_NAME,
add, af, af, source, source_prefixlen);
}
int fw_nftables_add_masquerade(
FirewallContext *ctx,
bool add,
@@ -1135,222 +1071,3 @@ int fw_nftables_add_local_dnat(
/* table created anew; previous address already gone */
return fw_nftables_add_local_dnat_internal(ctx, add, af, protocol, local_port, remote, remote_port, NULL);
}
static const char *const nfproto_table[] = {
[NFPROTO_ARP] = "arp",
[NFPROTO_BRIDGE] = "bridge",
[NFPROTO_INET] = "inet",
[NFPROTO_IPV4] = "ip",
[NFPROTO_IPV6] = "ip6",
[NFPROTO_NETDEV] = "netdev",
};
DEFINE_STRING_TABLE_LOOKUP(nfproto, int);
#define NFT_SET_MSGS 3
static int nft_set_element_op(bool add, const NFTSetContext *nft_set_context, void *element, size_t element_size) {
_cleanup_(sd_netlink_unrefp) sd_netlink *nfnl = NULL;
sd_netlink_message *transaction[NFT_SET_MSGS] = {};
_cleanup_free_ uint32_t *serial = NULL;
size_t tsize;
int r, nfproto;
const char *table, *set;
assert(nft_set_context);
nfproto = nft_set_context->nfproto;
table = nft_set_context->table;
assert(table);
set = nft_set_context->set;
assert(set);
assert(element);
r = sd_nfnl_socket_open(&nfnl);
if (r < 0)
return r;
r = sd_nfnl_message_batch_begin(nfnl, &transaction[0]);
if (r < 0)
return r;
tsize = 1;
if (add)
r = sd_nfnl_nft_message_new_setelems_begin(nfnl, &transaction[tsize], nfproto, table, set);
else
r = sd_nfnl_nft_message_del_setelems_begin(nfnl, &transaction[tsize], nfproto, table, set);
if (r < 0)
goto out_unref;
r = sd_nfnl_nft_message_add_setelem(transaction[tsize], 0, element, element_size, NULL, 0);
if (r < 0)
return r;
r = sd_nfnl_nft_message_add_setelem_end(transaction[tsize]);
if (r < 0)
return r;
++tsize;
assert(tsize < ELEMENTSOF(transaction));
r = sd_nfnl_message_batch_end(nfnl, &transaction[tsize]);
if (r < 0)
return r;
++tsize;
r = sd_netlink_sendv(nfnl, transaction, tsize, &serial);
out_unref:
while (tsize > 0)
sd_netlink_message_unref(transaction[--tsize]);
return r < 0 ? r : 0;
}
int nft_set_element_add_uint32(const NFTSetContext *nft_set_context, uint32_t element) {
int r;
assert(nft_set_context);
r = nft_set_element_op(true, nft_set_context, &element, sizeof(element));
if (r == 0)
log_debug("Added NFT family %s table %s set %s element %d",
nfproto_to_string(nft_set_context->nfproto), nft_set_context->table, nft_set_context->set, element);
return r;
}
int nft_set_element_del_uint32(const NFTSetContext *nft_set_context, uint32_t element) {
int r;
assert(nft_set_context);
r = nft_set_element_op(false, nft_set_context, &element, sizeof(element));
if (r == 0)
log_debug("Deleted NFT family %s table %s set %s element %d",
nfproto_to_string(nft_set_context->nfproto), nft_set_context->table, nft_set_context->set, element);
return r;
}
int nft_set_element_add_uint64(const NFTSetContext *nft_set_context, uint64_t element) {
int r;
assert(nft_set_context);
r = nft_set_element_op(true, nft_set_context, &element, sizeof(element));
if (r == 0)
log_debug("Added NFT family %s table %s set %s element %"PRIu64,
nfproto_to_string(nft_set_context->nfproto), nft_set_context->table, nft_set_context->set, element);
return r;
}
int nft_set_element_del_uint64(const NFTSetContext *nft_set_context, uint64_t element) {
int r;
assert(nft_set_context);
r = nft_set_element_op(false, nft_set_context, &element, sizeof(element));
if (r == 0)
log_debug("Deleted NFT family %s table %s set %s element %"PRIu64,
nfproto_to_string(nft_set_context->nfproto), nft_set_context->table, nft_set_context->set, element);
return r;
}
NFTSetContext* nft_set_context_free_many(NFTSetContext *s, size_t *n) {
assert(n);
assert(s || *n == 0);
for (size_t i = 0; i < *n; i++) {
free(s[i].table);
free(s[i].set);
}
free(s);
*n = 0;
return NULL;
}
int nft_set_context_add(NFTSetContext **s, size_t *n, int nfproto, const char *table, const char *set) {
_cleanup_free_ char *table_dup = NULL, *set_dup = NULL;
assert(s);
assert(n);
table_dup = strdup(table);
if (!table_dup)
return -ENOMEM;
set_dup = strdup(set);
if (!set_dup)
return -ENOMEM;
NFTSetContext *c;
c = reallocarray(*s, *n + 1, sizeof(NFTSetContext));
if (!c)
return -ENOMEM;
*s = c;
c[(*n) ++] = (NFTSetContext) {
.nfproto = nfproto,
.table = TAKE_PTR(table_dup),
.set = TAKE_PTR(set_dup),
};
return 0;
}
int config_parse_nft_set_context(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
NFTSetContext **nft_set_context,
size_t *n) {
_cleanup_free_ char *family_str = NULL, *table = NULL, *set = NULL;
int nfproto, r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(nft_set_context);
if (isempty(rvalue)) {
nft_set_context_free_many(*nft_set_context, n);
return 0;
}
for (const char *p = rvalue;;) {
r = extract_many_words(&p, ":" WHITESPACE, EXTRACT_CUNESCAPE, &family_str, &table, &set, NULL);
if (r == -ENOMEM)
return log_oom();
if (r == 0)
return 0;
if (r != 3) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse IPvxNFT set, ignoring: %s", rvalue);
return 0;
}
nfproto = nfproto_from_string(family_str);
if (nfproto < 0) {
log_syntax(unit, LOG_WARNING, filename, line, 0, "Unknown NFT protocol family, ignoring: %s", family_str);
return 0;
}
if (nft_identifier_bad(table))
return log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid table name %s, ignoring", table);
if (nft_identifier_bad(set))
return log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid set name %s, ignoring", set);
NFTSetContext *c;
c = reallocarray(*nft_set_context, *n + 1, sizeof(NFTSetContext));
if (!c)
return -ENOMEM;
*nft_set_context = c;
c[(*n) ++] = (NFTSetContext) {
.nfproto = nfproto,
.table = TAKE_PTR(table),
.set = TAKE_PTR(set),
};
}
return 0;
}
-40
View File
@@ -29,43 +29,3 @@ int fw_add_local_dnat(
const union in_addr_union *remote,
uint16_t remote_port,
const union in_addr_union *previous_remote);
struct NFTSetContext {
int nfproto;
char *table;
char *set;
};
typedef struct NFTSetContext NFTSetContext;
int nft_set_context_add(NFTSetContext **s, size_t *n, int nfproto, const char *table, const char *set);
NFTSetContext* nft_set_context_free_many(NFTSetContext *s, size_t *n);
int config_parse_nft_set_context(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
NFTSetContext **nft_set_context,
size_t *n);
const char *nfproto_to_string(int i) _const_;
int nfproto_from_string(const char *s) _pure_;
int nft_set_element_add_in_addr(
const NFTSetContext *nft_set_context,
int af,
const union in_addr_union *address,
unsigned int prefixlen);
int nft_set_element_del_in_addr(
const NFTSetContext *nft_set_context,
int af,
const union in_addr_union *address,
unsigned int prefixlen);
int nft_set_element_add_uint32(const NFTSetContext *nft_set_context, uint32_t element);
int nft_set_element_del_uint32(const NFTSetContext *nft_set_context, uint32_t element);
int nft_set_element_add_uint64(const NFTSetContext *nft_set_context, uint64_t element);
int nft_set_element_del_uint64(const NFTSetContext *nft_set_context, uint64_t element);