Allow to match on the cgroupsv2 id from ancestor level.
Unified · Split
| @@ -1014,11 +1014,13 @@ enum nft_rt_attributes { · 1013 unmodified lines | |||
| 1014 | * | 1014 | * |
| 1015 | * @NFTA_SOCKET_KEY: socket key to match | 1015 | * @NFTA_SOCKET_KEY: socket key to match |
| 1016 | * @NFTA_SOCKET_DREG: destination register | 1016 | * @NFTA_SOCKET_DREG: destination register |
| 1017 | * @NFTA_SOCKET_LEVEL: cgroups2 ancestor level (only for cgroupsv2) | ||
| 1017 | */ | 1018 | */ |
| 1018 | enum nft_socket_attributes { | 1019 | enum nft_socket_attributes { |
| 1019 | NFTA_SOCKET_UNSPEC, | 1020 | NFTA_SOCKET_UNSPEC, |
| 1020 | NFTA_SOCKET_KEY, | 1021 | NFTA_SOCKET_KEY, |
| 1021 | NFTA_SOCKET_DREG, | 1022 | NFTA_SOCKET_DREG, |
| 1023 | NFTA_SOCKET_LEVEL, | ||
| 1022 | __NFTA_SOCKET_MAX | 1024 | __NFTA_SOCKET_MAX |
| 1023 | }; | 1025 | }; |
| 1024 | #define NFTA_SOCKET_MAX (__NFTA_SOCKET_MAX - 1) | 1026 | #define NFTA_SOCKET_MAX (__NFTA_SOCKET_MAX - 1) |
| @@ -1029,11 +1031,13 @@ enum nft_socket_attributes { · 4 unmodified lines | |||
| 1029 | * @NFT_SOCKET_TRANSPARENT: Value of the IP(V6)_TRANSPARENT socket option | 1031 | * @NFT_SOCKET_TRANSPARENT: Value of the IP(V6)_TRANSPARENT socket option |
| 1030 | * @NFT_SOCKET_MARK: Value of the socket mark | 1032 | * @NFT_SOCKET_MARK: Value of the socket mark |
| 1031 | * @NFT_SOCKET_WILDCARD: Whether the socket is zero-bound (e.g. 0.0.0.0 or ::0) | 1033 | * @NFT_SOCKET_WILDCARD: Whether the socket is zero-bound (e.g. 0.0.0.0 or ::0) |
| 1034 | * @NFT_SOCKET_CGROUPV2: Match on cgroups version 2 | ||
| 1032 | */ | 1035 | */ |
| 1033 | enum nft_socket_keys { | 1036 | enum nft_socket_keys { |
| 1034 | NFT_SOCKET_TRANSPARENT, | 1037 | NFT_SOCKET_TRANSPARENT, |
| 1035 | NFT_SOCKET_MARK, | 1038 | NFT_SOCKET_MARK, |
| 1036 | NFT_SOCKET_WILDCARD, | 1039 | NFT_SOCKET_WILDCARD, |
| 1040 | NFT_SOCKET_CGROUPV2, | ||
| 1037 | __NFT_SOCKET_MAX | 1041 | __NFT_SOCKET_MAX |
| 1038 | }; | 1042 | }; |
| 1039 | #define NFT_SOCKET_MAX (__NFT_SOCKET_MAX - 1) | 1043 | #define NFT_SOCKET_MAX (__NFT_SOCKET_MAX - 1) |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | |||
| 9 | 9 | ||
| 10 | struct nft_socket { | 10 | struct nft_socket { |
| 11 | enum nft_socket_keys key:8; | 11 | enum nft_socket_keys key:8; |
| 12 | u8 level; | ||
| 12 | union { | 13 | union { |
| 13 | u8 dreg; | 14 | u8 dreg; |
| 14 | }; | 15 | }; |
| @@ -33,6 +34,26 @@ static void nft_socket_wildcard(const struct nft_pktinfo *pkt, · 18 unmodified lines | |||
| 33 | } | 34 | } |
| 34 | } | 35 | } |
| 35 | 36 | ||
| 37 | #ifdef CONFIG_CGROUPS | ||
| 38 | static noinline bool | ||
| 39 | nft_sock_get_eval_cgroupv2(u32 *dest, const struct nft_pktinfo *pkt, u32 level) | ||
| 40 | { | ||
| 41 | struct sock *sk = skb_to_full_sk(pkt->skb); | ||
| 42 | struct cgroup *cgrp; | ||
| 43 | |||
| 44 | if (!sk || !sk_fullsock(sk) || !net_eq(nft_net(pkt), sock_net(sk))) | ||
| 45 | return false; | ||
| 46 | |||
| 47 | cgrp = sock_cgroup_ptr(&sk->sk_cgrp_data); | ||
| 48 | if (level > cgrp->level) | ||
| 49 | return false; | ||
| 50 | |||
| 51 | memcpy(dest, &cgrp->ancestor_ids[level], sizeof(u64)); | ||
| 52 | |||
| 53 | return true; | ||
| 54 | } | ||
| 55 | #endif | ||
| 56 | |||
| 36 | static void nft_socket_eval(const struct nft_expr *expr, | 57 | static void nft_socket_eval(const struct nft_expr *expr, |
| 37 | struct nft_regs *regs, | 58 | struct nft_regs *regs, |
| 38 | const struct nft_pktinfo *pkt) | 59 | const struct nft_pktinfo *pkt) |
| @@ -85,6 +106,14 @@ static void nft_socket_eval(const struct nft_expr *expr, · 46 unmodified lines | |||
| 85 | } | 106 | } |
| 86 | nft_socket_wildcard(pkt, regs, sk, dest); | 107 | nft_socket_wildcard(pkt, regs, sk, dest); |
| 87 | break; | 108 | break; |
| 109 | #ifdef CONFIG_CGROUPS | ||
| 110 | case NFT_SOCKET_CGROUPV2: | ||
| 111 | if (!nft_sock_get_eval_cgroupv2(dest, pkt, priv->level)) { | ||
| 112 | regs->verdict.code = NFT_BREAK; | ||
| 113 | return; | ||
| 114 | } | ||
| 115 | break; | ||
| 116 | #endif | ||
| 88 | default: | 117 | default: |
| 89 | WARN_ON(1); | 118 | WARN_ON(1); |
| 90 | regs->verdict.code = NFT_BREAK; | 119 | regs->verdict.code = NFT_BREAK; |
| @@ -97,6 +126,7 @@ static void nft_socket_eval(const struct nft_expr *expr, · 6 unmodified lines | |||
| 97 | static const struct nla_policy nft_socket_policy[NFTA_SOCKET_MAX + 1] = { | 126 | static const struct nla_policy nft_socket_policy[NFTA_SOCKET_MAX + 1] = { |
| 98 | [NFTA_SOCKET_KEY] = { .type = NLA_U32 }, | 127 | [NFTA_SOCKET_KEY] = { .type = NLA_U32 }, |
| 99 | [NFTA_SOCKET_DREG] = { .type = NLA_U32 }, | 128 | [NFTA_SOCKET_DREG] = { .type = NLA_U32 }, |
| 129 | [NFTA_SOCKET_LEVEL] = { .type = NLA_U32 }, | ||
| 100 | }; | 130 | }; |
| 101 | 131 | ||
| 102 | static int nft_socket_init(const struct nft_ctx *ctx, | 132 | static int nft_socket_init(const struct nft_ctx *ctx, |
| @@ -104,7 +134,7 @@ static int nft_socket_init(const struct nft_ctx *ctx, · 1 unmodified line | |||
| 104 | const struct nlattr * const tb[]) | 134 | const struct nlattr * const tb[]) |
| 105 | { | 135 | { |
| 106 | struct nft_socket *priv = nft_expr_priv(expr); | 136 | struct nft_socket *priv = nft_expr_priv(expr); |
| 107 | unsigned int len; | 137 | unsigned int len, level; |
| 108 | 138 | ||
| 109 | if (!tb[NFTA_SOCKET_DREG] || !tb[NFTA_SOCKET_KEY]) | 139 | if (!tb[NFTA_SOCKET_DREG] || !tb[NFTA_SOCKET_KEY]) |
| 110 | return -EINVAL; | 140 | return -EINVAL; |
| @@ -129,6 +159,19 @@ static int nft_socket_init(const struct nft_ctx *ctx, · 18 unmodified lines | |||
| 129 | case NFT_SOCKET_MARK: | 159 | case NFT_SOCKET_MARK: |
| 130 | len = sizeof(u32); | 160 | len = sizeof(u32); |
| 131 | break; | 161 | break; |
| 162 | #ifdef CONFIG_CGROUPS | ||
| 163 | case NFT_SOCKET_CGROUPV2: | ||
| 164 | if (!tb[NFTA_SOCKET_LEVEL]) | ||
| 165 | return -EINVAL; | ||
| 166 | |||
| 167 | level = ntohl(nla_get_u32(tb[NFTA_SOCKET_LEVEL])); | ||
| 168 | if (level > 255) | ||
| 169 | return -EOPNOTSUPP; | ||
| 170 | |||
| 171 | priv->level = level; | ||
| 172 | len = sizeof(u64); | ||
| 173 | break; | ||
| 174 | #endif | ||
| 132 | default: | 175 | default: |
| 133 | return -EOPNOTSUPP; | 176 | return -EOPNOTSUPP; |
| 134 | } | 177 | } |
| @@ -146,6 +189,9 @@ static int nft_socket_dump(struct sk_buff *skb, · 11 unmodified lines | |||
| 146 | return -1; | 189 | return -1; |
| 147 | if (nft_dump_register(skb, NFTA_SOCKET_DREG, priv->dreg)) | 190 | if (nft_dump_register(skb, NFTA_SOCKET_DREG, priv->dreg)) |
| 148 | return -1; | 191 | return -1; |
| 192 | if (priv->key == NFT_SOCKET_CGROUPV2 && | ||
| 193 | nla_put_u32(skb, NFTA_SOCKET_LEVEL, htonl(priv->level))) | ||
| 194 | return -1; | ||
| 149 | return 0; | 195 | return 0; |
| 150 | } | 196 | } |
| 151 | 197 | ||