]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
netfilter: xt_u32: reject invalid shift counts
authorWyatt Feng <bronzed_45_vested@icloud.com>
Sun, 28 Jun 2026 08:05:54 +0000 (16:05 +0800)
committerFlorian Westphal <fw@strlen.de>
Fri, 3 Jul 2026 12:45:21 +0000 (14:45 +0200)
u32_match_it() executes rule-supplied shift operands on a 32-bit
value. A malformed u32 rule can provide a shift count of 32 or more,
triggering an undefined shift out-of-bounds during packet evaluation.

Validate XT_U32_LEFTSH and XT_U32_RIGHTSH operands in
u32_mt_checkentry() and reject malformed rules before they reach the
packet path.

Fixes: 1b50b8a371e9 ("[NETFILTER]: Add u32 match")
Reported-by: Yuan Tan <yuantan098@gmail.com>
Reported-by: Yifan Wu <yifanwucs@gmail.com>
Reported-by: Juefei Pu <tomapufckgml@gmail.com>
Reported-by: Zhengchuan Liang <zcliangcn@gmail.com>
Reported-by: Xin Liu <bird@lzu.edu.cn>
Assisted-by: Codex:GPT-5.4
Signed-off-by: Wyatt Feng <bronzed_45_vested@icloud.com>
Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
Signed-off-by: Florian Westphal <fw@strlen.de>
net/netfilter/xt_u32.c

index 117d4615d6684c53b3a13225d2222a0993df0002..ec1a21e3b6e2c3f9d6c4f7f325d23648d8a47404 100644 (file)
@@ -100,7 +100,7 @@ static int u32_mt_checkentry(const struct xt_mtchk_param *par)
 {
        const struct xt_u32 *data = par->matchinfo;
        const struct xt_u32_test *ct;
-       unsigned int i;
+       unsigned int i, j;
 
        if (data->ntests > ARRAY_SIZE(data->tests))
                return -EINVAL;
@@ -111,6 +111,16 @@ static int u32_mt_checkentry(const struct xt_mtchk_param *par)
                if (ct->nnums > ARRAY_SIZE(ct->location) ||
                    ct->nvalues > ARRAY_SIZE(ct->value))
                        return -EINVAL;
+
+               for (j = 1; j < ct->nnums; ++j) {
+                       switch (ct->location[j].nextop) {
+                       case XT_U32_LEFTSH:
+                       case XT_U32_RIGHTSH:
+                               if (ct->location[j].number >= 32)
+                                       return -EINVAL;
+                               break;
+                       }
+               }
        }
 
        return 0;