Date: Tue, 21 Apr 2026 11:32:52 +0000 From: Kristof Provost <kp@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Subject: git: 9933bdcb1264 - main - pf: only allow a subset of netlink calls when securelevel is set Message-ID: <69e76064.42067.611e2563@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch main has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=9933bdcb12641839b7396ccd0c6b8a2d55d12744 commit 9933bdcb12641839b7396ccd0c6b8a2d55d12744 Author: Kristof Provost <kp@FreeBSD.org> AuthorDate: 2026-04-20 06:36:17 +0000 Commit: Kristof Provost <kp@FreeBSD.org> CommitDate: 2026-04-21 09:51:28 +0000 pf: only allow a subset of netlink calls when securelevel is set Extend the genl_cmd struct to allow calls to also carry a securelevel. If that's set compare the current securelevel to only allow the call if the level is lower than that. If no value is specified continue to allow calls in any securelevel, as before. This allows us to easily implement the same securelevel restrictions for pf as we have for the corresponding ioctls. Reviewed by: glebius MFC after: 1 week Sponsored by: Rubicon Communications, LLC ("Netgate") Differential Revision: https://reviews.freebsd.org/D56390 --- sys/netlink/netlink_ctl.h | 3 +++ sys/netlink/netlink_generic.c | 7 +++++++ sys/netpfil/pf/pf_nl.c | 47 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+) diff --git a/sys/netlink/netlink_ctl.h b/sys/netlink/netlink_ctl.h index 7f43e0f2c25e..4740d306dd54 100644 --- a/sys/netlink/netlink_ctl.h +++ b/sys/netlink/netlink_ctl.h @@ -89,6 +89,9 @@ struct genl_cmd { uint32_t cmd_flags; uint32_t cmd_priv; uint32_t cmd_num; + + /* Disallow this call from this level up (inclusive). */ + uint32_t cmd_securelevel; }; uint16_t genl_register_family(const char *family_name, size_t hdrsize, diff --git a/sys/netlink/netlink_generic.c b/sys/netlink/netlink_generic.c index d20ec4c7545f..3a73ecc0b339 100644 --- a/sys/netlink/netlink_generic.c +++ b/sys/netlink/netlink_generic.c @@ -150,6 +150,13 @@ genl_handle_message(struct nlmsghdr *hdr, struct nl_pstate *npt) return (EPERM); } + if (cmd->cmd_securelevel > 0 && + securelevel_ge(nlp_get_cred(nlp), cmd->cmd_securelevel)) { + NLP_LOG(LOG_DEBUG, nlp, "family %s: cmd %d securelevel_gt() failed", + gf->family_name, ghdr->cmd); + return (EPERM); + } + NLP_LOG(LOG_DEBUG2, nlp, "received family %s cmd %s(%d) len %d", gf->family_name, cmd->cmd_name, ghdr->cmd, hdr->nlmsg_len); diff --git a/sys/netpfil/pf/pf_nl.c b/sys/netpfil/pf/pf_nl.c index c2ea65f4b043..e4ce9e64f637 100644 --- a/sys/netpfil/pf/pf_nl.c +++ b/sys/netpfil/pf/pf_nl.c @@ -2872,6 +2872,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_getstates, .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 3, }, { .cmd_num = PFNL_CMD_GETCREATORS, @@ -2879,6 +2880,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_getcreators, .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 3, }, { .cmd_num = PFNL_CMD_START, @@ -2886,6 +2888,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_start, .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 2, }, { .cmd_num = PFNL_CMD_STOP, @@ -2893,6 +2896,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_stop, .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 2, }, { .cmd_num = PFNL_CMD_ADDRULE, @@ -2900,6 +2904,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_addrule, .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 2, }, { .cmd_num = PFNL_CMD_GETRULES, @@ -2907,6 +2912,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_getrules, .cmd_flags = GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 3, }, { .cmd_num = PFNL_CMD_GETRULE, @@ -2914,6 +2920,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_getrule, .cmd_flags = GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 3, }, { .cmd_num = PFNL_CMD_CLRSTATES, @@ -2921,6 +2928,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_clear_states, .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 2, }, { .cmd_num = PFNL_CMD_KILLSTATES, @@ -2928,6 +2936,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_kill_states, .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 2, }, { .cmd_num = PFNL_CMD_SET_STATUSIF, @@ -2935,6 +2944,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_set_statusif, .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 2, }, { .cmd_num = PFNL_CMD_GET_STATUS, @@ -2942,6 +2952,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_get_status, .cmd_flags = GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 3, }, { .cmd_num = PFNL_CMD_CLEAR_STATUS, @@ -2949,6 +2960,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_clear_status, .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 2, }, { .cmd_num = PFNL_CMD_NATLOOK, @@ -2956,6 +2968,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_natlook, .cmd_flags = GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 3, }, { .cmd_num = PFNL_CMD_SET_DEBUG, @@ -2963,6 +2976,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_set_debug, .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 2, }, { .cmd_num = PFNL_CMD_SET_TIMEOUT, @@ -2970,6 +2984,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_set_timeout, .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 2, }, { .cmd_num = PFNL_CMD_GET_TIMEOUT, @@ -2977,6 +2992,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_get_timeout, .cmd_flags = GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 3, }, { .cmd_num = PFNL_CMD_SET_LIMIT, @@ -2984,6 +3000,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_set_limit, .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 2, }, { .cmd_num = PFNL_CMD_GET_LIMIT, @@ -2991,6 +3008,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_get_limit, .cmd_flags = GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 3, }, { .cmd_num = PFNL_CMD_BEGIN_ADDRS, @@ -2998,6 +3016,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_begin_addrs, .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 3, }, { .cmd_num = PFNL_CMD_ADD_ADDR, @@ -3005,6 +3024,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_add_addr, .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 3, }, { .cmd_num = PFNL_CMD_GET_ADDRS, @@ -3012,6 +3032,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_get_addrs, .cmd_flags = GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 3, }, { .cmd_num = PFNL_CMD_GET_ADDR, @@ -3019,6 +3040,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_get_addr, .cmd_flags = GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 3, }, { .cmd_num = PFNL_CMD_GET_RULESETS, @@ -3026,6 +3048,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_get_rulesets, .cmd_flags = GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 3, }, { .cmd_num = PFNL_CMD_GET_RULESET, @@ -3033,6 +3056,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_get_ruleset, .cmd_flags = GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 3, }, { .cmd_num = PFNL_CMD_GET_SRCNODES, @@ -3040,6 +3064,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_get_srcnodes, .cmd_flags = GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 3, }, { .cmd_num = PFNL_CMD_CLEAR_TABLES, @@ -3047,6 +3072,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_clear_tables, .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 2, }, { .cmd_num = PFNL_CMD_ADD_TABLE, @@ -3054,6 +3080,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_add_table, .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 2, }, { .cmd_num = PFNL_CMD_DEL_TABLE, @@ -3061,6 +3088,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_del_table, .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 2, }, { .cmd_num = PFNL_CMD_GET_TSTATS, @@ -3068,6 +3096,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_get_tstats, .cmd_flags = GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 3, }, { .cmd_num = PFNL_CMD_CLR_TSTATS, @@ -3075,6 +3104,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_clear_tstats, .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 3, }, { .cmd_num = PFNL_CMD_CLR_ADDRS, @@ -3082,6 +3112,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_clear_addrs, .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 3, }, { .cmd_num = PFNL_CMD_TABLE_ADD_ADDR, @@ -3089,6 +3120,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_table_add_addrs, .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 3, }, { .cmd_num = PFNL_CMD_TABLE_DEL_ADDR, @@ -3096,6 +3128,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_table_del_addrs, .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 3, }, { .cmd_num = PFNL_CMD_TABLE_SET_ADDR, @@ -3103,6 +3136,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_table_set_addrs, .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 3, }, { .cmd_num = PFNL_CMD_TABLE_GET_ADDR, @@ -3110,6 +3144,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_table_get_addrs, .cmd_flags = GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 3, }, { .cmd_num = PFNL_CMD_TABLE_GET_ASTATS, @@ -3117,6 +3152,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_table_get_astats, .cmd_flags = GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 3, }, { .cmd_num = PFNL_CMD_TABLE_CLEAR_ASTATS, @@ -3124,6 +3160,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_table_clear_astats, .cmd_flags = GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 3, }, { .cmd_num = PFNL_CMD_STATE_LIMITER_ADD, @@ -3131,6 +3168,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_state_limiter_add, .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 2, }, { .cmd_num = PFNL_CMD_STATE_LIMITER_GET, @@ -3138,6 +3176,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_state_limiter_get, .cmd_flags = GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 3, }, { .cmd_num = PFNL_CMD_STATE_LIMITER_NGET, @@ -3145,6 +3184,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_state_limiter_get, .cmd_flags = GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 3, }, { .cmd_num = PFNL_CMD_SOURCE_LIMITER_ADD, @@ -3152,6 +3192,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_source_limiter_add, .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 2, }, { .cmd_num = PFNL_CMD_SOURCE_LIMITER_GET, @@ -3159,6 +3200,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_source_limiter_get, .cmd_flags = GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 3, }, { .cmd_num = PFNL_CMD_SOURCE_LIMITER_NGET, @@ -3166,6 +3208,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_source_limiter_get, .cmd_flags = GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 3, }, { .cmd_num = PFNL_CMD_SOURCE_GET, @@ -3173,6 +3216,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_source_get, .cmd_flags = GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 3, }, { .cmd_num = PFNL_CMD_SOURCE_NGET, @@ -3180,6 +3224,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_source_get, .cmd_flags = GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 3, }, { .cmd_num = PFNL_CMD_SOURCE_CLEAR, @@ -3187,6 +3232,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_source_clear, .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 3, }, { .cmd_num = PFNL_CMD_TABLE_TEST_ADDRS, @@ -3194,6 +3240,7 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_table_test_addrs, .cmd_flags = GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, + .cmd_securelevel = 3, }, };home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69e76064.42067.611e2563>
