Similar to kernel's nla_policy, enable expressions to inform about restrictions on attribute use. This allows the generic expression code to perform sanity checks before dispatching to expression ops. For now, this holds only the maximum data len which may be passed to nftnl_expr_set(). Signed-off-by: Phil Sutter <phil@xxxxxx> --- include/expr_ops.h | 5 +++++ src/expr.c | 6 ++++++ src/expr/bitwise.c | 11 +++++++++++ src/expr/byteorder.c | 9 +++++++++ src/expr/immediate.c | 9 +++++++++ 5 files changed, 40 insertions(+) diff --git a/include/expr_ops.h b/include/expr_ops.h index 51b221483552c..6c95297bfcd58 100644 --- a/include/expr_ops.h +++ b/include/expr_ops.h @@ -8,10 +8,15 @@ struct nlattr; struct nlmsghdr; struct nftnl_expr; +struct attr_policy { + size_t maxlen; +}; + struct expr_ops { const char *name; uint32_t alloc_len; int nftnl_max_attr; + struct attr_policy *attr_policy; void (*init)(const struct nftnl_expr *e); void (*free)(const struct nftnl_expr *e); int (*set)(struct nftnl_expr *e, uint16_t type, const void *data, uint32_t data_len); diff --git a/src/expr.c b/src/expr.c index b4581f1a79ff6..3e06c48aeb5f3 100644 --- a/src/expr.c +++ b/src/expr.c @@ -71,6 +71,12 @@ int nftnl_expr_set(struct nftnl_expr *expr, uint16_t type, case NFTNL_EXPR_NAME: /* cannot be modified */ return 0; default: + if (expr->ops->attr_policy && + type <= expr->ops->nftnl_max_attr && + expr->ops->attr_policy[type].maxlen && + expr->ops->attr_policy[type].maxlen < data_len) + return -1; + if (expr->ops->set(expr, type, data, data_len) < 0) return -1; } diff --git a/src/expr/bitwise.c b/src/expr/bitwise.c index d11272fbd37b0..0a881eb3545dd 100644 --- a/src/expr/bitwise.c +++ b/src/expr/bitwise.c @@ -274,10 +274,21 @@ nftnl_expr_bitwise_snprintf(char *buf, size_t size, return err; } +static struct attr_policy bitwise_attr_policy[__NFTNL_EXPR_BITWISE_MAX] = { + [NFTNL_EXPR_BITWISE_SREG] = { .maxlen = sizeof(enum nft_registers) }, + [NFTNL_EXPR_BITWISE_DREG] = { .maxlen = sizeof(enum nft_registers) }, + [NFTNL_EXPR_BITWISE_LEN] = { .maxlen = sizeof(uint8_t) }, + [NFTNL_EXPR_BITWISE_MASK] = { .maxlen = NFT_DATA_VALUE_MAXLEN }, + [NFTNL_EXPR_BITWISE_XOR] = { .maxlen = NFT_DATA_VALUE_MAXLEN }, + [NFTNL_EXPR_BITWISE_OP] = { .maxlen = sizeof(enum nft_bitwise_ops) }, + [NFTNL_EXPR_BITWISE_DATA] = { .maxlen = NFT_DATA_VALUE_MAXLEN }, +}; + struct expr_ops expr_ops_bitwise = { .name = "bitwise", .alloc_len = sizeof(struct nftnl_expr_bitwise), .nftnl_max_attr = __NFTNL_EXPR_BITWISE_MAX - 1, + .attr_policy = bitwise_attr_policy, .set = nftnl_expr_bitwise_set, .get = nftnl_expr_bitwise_get, .parse = nftnl_expr_bitwise_parse, diff --git a/src/expr/byteorder.c b/src/expr/byteorder.c index f05ae59b688eb..6d085197b40c7 100644 --- a/src/expr/byteorder.c +++ b/src/expr/byteorder.c @@ -212,10 +212,19 @@ nftnl_expr_byteorder_snprintf(char *buf, size_t remain, return offset; } +static struct attr_policy byteorder_attr_policy[__NFTNL_EXPR_BYTEORDER_MAX] = { + [NFTNL_EXPR_BYTEORDER_DREG] = { .maxlen = sizeof(enum nft_registers) }, + [NFTNL_EXPR_BYTEORDER_SREG] = { .maxlen = sizeof(enum nft_registers) }, + [NFTNL_EXPR_BYTEORDER_OP] = { .maxlen = sizeof(enum nft_byteorder_ops) }, + [NFTNL_EXPR_BYTEORDER_LEN] = { .maxlen = sizeof(uint8_t) }, + [NFTNL_EXPR_BYTEORDER_SIZE] = { .maxlen = sizeof(uint8_t) }, +}; + struct expr_ops expr_ops_byteorder = { .name = "byteorder", .alloc_len = sizeof(struct nftnl_expr_byteorder), .nftnl_max_attr = __NFTNL_EXPR_BYTEORDER_MAX - 1, + .attr_policy = byteorder_attr_policy, .set = nftnl_expr_byteorder_set, .get = nftnl_expr_byteorder_get, .parse = nftnl_expr_byteorder_parse, diff --git a/src/expr/immediate.c b/src/expr/immediate.c index 2ffa0c5e9ebc3..774ed3dcfea7e 100644 --- a/src/expr/immediate.c +++ b/src/expr/immediate.c @@ -220,10 +220,19 @@ static void nftnl_expr_immediate_free(const struct nftnl_expr *e) nftnl_free_verdict(&imm->data); } +static struct attr_policy immediate_attr_policy[__NFTNL_EXPR_IMM_MAX] = { + [NFTNL_EXPR_IMM_DREG] = { .maxlen = sizeof(enum nft_registers) }, + [NFTNL_EXPR_IMM_DATA] = { .maxlen = NFT_DATA_VALUE_MAXLEN }, + [NFTNL_EXPR_IMM_VERDICT] = { .maxlen = sizeof(uint32_t) }, + /*[NFTNL_EXPR_IMM_CHAIN] = { .maxlen = NFT_CHAIN_MAXNAMELEN },*/ + [NFTNL_EXPR_IMM_CHAIN_ID] = { .maxlen = sizeof(uint32_t) }, +}; + struct expr_ops expr_ops_immediate = { .name = "immediate", .alloc_len = sizeof(struct nftnl_expr_immediate), .nftnl_max_attr = __NFTNL_EXPR_IMM_MAX - 1, + .attr_policy = immediate_attr_policy, .free = nftnl_expr_immediate_free, .set = nftnl_expr_immediate_set, .get = nftnl_expr_immediate_get, -- 2.43.0