Contents
crypto/ (5 functions) — 0 real, 60 FP
io_uring/ (4 functions) — 0 real, 4 FP
ipc/ (3 functions) — 0 real, 5 FP
Summary
| Function | File | Assessment | Confidence | Real | FP | Unanalyzed |
|---|---|---|---|---|---|---|
| crypto/ — 5 functions, 0 real, 60 FP | ||||||
| __aria_crypt() | crypto/aria_generic.c | FP | high | 0 | 16 | 0 |
| khazad_crypt() | crypto/khazad.c | FP | high | 0 | 16 | 0 |
| khazad_setkey() | crypto/khazad.c | FP | high | 0 | 16 | 0 |
| seed_set_key() | crypto/seed.c | FP | high | 0 | 4 | 0 |
| streebog_xlps() | crypto/streebog_generic.c | FP | high | 0 | 8 | 0 |
| io_uring/ — 4 functions, 0 real, 4 FP | ||||||
| io_copy_regbuf() | io_uring/mock_file.c | FP | high | 0 | 1 | 0 |
| io_recvmsg_multishot() | io_uring/net.c | FP | high | 0 | 1 | 0 |
| io_probe() | io_uring/register.c | FP | high | 0 | 1 | 0 |
| io_register_iowq_aff() | io_uring/register.c | FP | high | 0 | 1 | 0 |
| ipc/ — 3 functions, 0 real, 5 FP | ||||||
| do_mq_notify() | ipc/mqueue.c | FP | high | 0 | 1 | 0 |
| load_msg() | ipc/msgutil.c | FP | high | 0 | 2 | 0 |
| store_msg() | ipc/msgutil.c | FP | high | 0 | 2 | 0 |
Function Details
__aria_crypt() — crypto/aria_generic.c FP confidence=high
All findings are false positives. The static analyzer tracks taint from get_unaligned_be32() through the register variables (reg0-reg3) to the S-box table subscripts. However, the actual subscript used is get_u8(regN, k), which extracts a single byte from the 32-bit register — always producing a value in [0, 255]. The ARIA S-box tables (x1, x2, s1, s2) are all 256-element lookup tables, so a u8 subscript is always in-bounds by construction. This is the standard safe design of a block cipher S-box lookup and there is no OOB access possible regardless of the input block content.
Finding #1 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be32() line 203 |
| Taint snippet | reg0 = get_unaligned_be32(&in[0]); |
| Tainted var | reg0 |
| Subscript | [] line 225 |
| Sink snippet | reg0 = key[rkidx][0] ^ make_u32((u8)(x1[get_u8(reg0, 0)]), |
| Possibly guarded | no |
Dismissed: get_u8(reg0, 0) extracts byte 0 of reg0, always in [0,255]. x1 has 256 entries. No counterexample possible: any u8 subscript into a 256-element table is always in bounds.
Finding #2 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be32() line 203 |
| Taint snippet | reg0 = get_unaligned_be32(&in[0]); |
| Tainted var | reg0 |
| Subscript | [] line 226 |
| Sink snippet | (u8)(x2[get_u8(reg0, 1)] >> 8), |
| Possibly guarded | no |
Dismissed: get_u8(reg0, 1) extracts byte 1 of reg0, always in [0,255]. x2 has 256 entries. No counterexample possible.
Finding #3 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be32() line 203 |
| Taint snippet | reg0 = get_unaligned_be32(&in[0]); |
| Tainted var | reg0 |
| Subscript | [] line 227 |
| Sink snippet | (u8)(s1[get_u8(reg0, 2)]), |
| Possibly guarded | no |
Dismissed: get_u8(reg0, 2) extracts byte 2 of reg0, always in [0,255]. s1 has 256 entries. No counterexample possible.
Finding #4 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be32() line 203 |
| Taint snippet | reg0 = get_unaligned_be32(&in[0]); |
| Tainted var | reg0 |
| Subscript | [] line 228 |
| Sink snippet | (u8)(s2[get_u8(reg0, 3)])); |
| Possibly guarded | no |
Dismissed: get_u8(reg0, 3) extracts byte 3 of reg0, always in [0,255]. s2 has 256 entries. No counterexample possible.
Finding #5 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be32() line 204 |
| Taint snippet | reg1 = get_unaligned_be32(&in[4]); |
| Tainted var | reg1 |
| Subscript | [] line 229 |
| Sink snippet | reg1 = key[rkidx][1] ^ make_u32((u8)(x1[get_u8(reg1, 0)]), |
| Possibly guarded | no |
Dismissed: get_u8(reg1, 0) extracts byte 0 of reg1, always in [0,255]. x1 has 256 entries. No counterexample possible.
Finding #6 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be32() line 204 |
| Taint snippet | reg1 = get_unaligned_be32(&in[4]); |
| Tainted var | reg1 |
| Subscript | [] line 230 |
| Sink snippet | (u8)(x2[get_u8(reg1, 1)] >> 8), |
| Possibly guarded | no |
Dismissed: get_u8(reg1, 1) extracts byte 1 of reg1, always in [0,255]. x2 has 256 entries. No counterexample possible.
Finding #7 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be32() line 204 |
| Taint snippet | reg1 = get_unaligned_be32(&in[4]); |
| Tainted var | reg1 |
| Subscript | [] line 231 |
| Sink snippet | (u8)(s1[get_u8(reg1, 2)]), |
| Possibly guarded | no |
Dismissed: get_u8(reg1, 2) extracts byte 2 of reg1, always in [0,255]. s1 has 256 entries. No counterexample possible.
Finding #8 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be32() line 204 |
| Taint snippet | reg1 = get_unaligned_be32(&in[4]); |
| Tainted var | reg1 |
| Subscript | [] line 232 |
| Sink snippet | (u8)(s2[get_u8(reg1, 3)])); |
| Possibly guarded | no |
Dismissed: get_u8(reg1, 3) extracts byte 3 of reg1, always in [0,255]. s2 has 256 entries. No counterexample possible.
Finding #9 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be32() line 205 |
| Taint snippet | reg2 = get_unaligned_be32(&in[8]); |
| Tainted var | reg2 |
| Subscript | [] line 233 |
| Sink snippet | reg2 = key[rkidx][2] ^ make_u32((u8)(x1[get_u8(reg2, 0)]), |
| Possibly guarded | no |
Dismissed: get_u8(reg2, 0) extracts byte 0 of reg2, always in [0,255]. x1 has 256 entries. No counterexample possible.
Finding #10 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be32() line 205 |
| Taint snippet | reg2 = get_unaligned_be32(&in[8]); |
| Tainted var | reg2 |
| Subscript | [] line 234 |
| Sink snippet | (u8)(x2[get_u8(reg2, 1)] >> 8), |
| Possibly guarded | no |
Dismissed: get_u8(reg2, 1) extracts byte 1 of reg2, always in [0,255]. x2 has 256 entries. No counterexample possible.
Finding #11 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be32() line 205 |
| Taint snippet | reg2 = get_unaligned_be32(&in[8]); |
| Tainted var | reg2 |
| Subscript | [] line 235 |
| Sink snippet | (u8)(s1[get_u8(reg2, 2)]), |
| Possibly guarded | no |
Dismissed: get_u8(reg2, 2) extracts byte 2 of reg2, always in [0,255]. s1 has 256 entries. No counterexample possible.
Finding #12 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be32() line 205 |
| Taint snippet | reg2 = get_unaligned_be32(&in[8]); |
| Tainted var | reg2 |
| Subscript | [] line 236 |
| Sink snippet | (u8)(s2[get_u8(reg2, 3)])); |
| Possibly guarded | no |
Dismissed: get_u8(reg2, 3) extracts byte 3 of reg2, always in [0,255]. s2 has 256 entries. No counterexample possible.
Finding #13 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be32() line 206 |
| Taint snippet | reg3 = get_unaligned_be32(&in[12]); |
| Tainted var | reg3 |
| Subscript | [] line 237 |
| Sink snippet | reg3 = key[rkidx][3] ^ make_u32((u8)(x1[get_u8(reg3, 0)]), |
| Possibly guarded | no |
Dismissed: get_u8(reg3, 0) extracts byte 0 of reg3, always in [0,255]. x1 has 256 entries. No counterexample possible.
Finding #14 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be32() line 206 |
| Taint snippet | reg3 = get_unaligned_be32(&in[12]); |
| Tainted var | reg3 |
| Subscript | [] line 238 |
| Sink snippet | (u8)(x2[get_u8(reg3, 1)] >> 8), |
| Possibly guarded | no |
Dismissed: get_u8(reg3, 1) extracts byte 1 of reg3, always in [0,255]. x2 has 256 entries. No counterexample possible.
Finding #15 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be32() line 206 |
| Taint snippet | reg3 = get_unaligned_be32(&in[12]); |
| Tainted var | reg3 |
| Subscript | [] line 239 |
| Sink snippet | (u8)(s1[get_u8(reg3, 2)]), |
| Possibly guarded | no |
Dismissed: get_u8(reg3, 2) extracts byte 2 of reg3, always in [0,255]. s1 has 256 entries. No counterexample possible.
Finding #16 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be32() line 206 |
| Taint snippet | reg3 = get_unaligned_be32(&in[12]); |
| Tainted var | reg3 |
| Subscript | [] line 240 |
| Sink snippet | (u8)(s2[get_u8(reg3, 3)])); |
| Possibly guarded | no |
Dismissed: get_u8(reg3, 3) extracts byte 3 of reg3, always in [0,255]. s2 has 256 entries. No counterexample possible.
khazad_crypt() — crypto/khazad.c FP confidence=high
All array subscripts are derived by extracting individual bytes from a 64-bit state value via right-shifts and 0xff masking. The shift amounts (56, 48, 40, 32, 24, 16, 8, 0) combined with the 0xff mask (or the natural 8-bit result of shifting a u64 right by 56) guarantee all indices are in [0, 255]. The Khazad cipher lookup tables T0-T7 each have 256 entries, so no out-of-bounds access is possible regardless of the input data. The taint propagates from user/network data through XOR and table lookups, but every subscript is provably bounded to one byte.
Finding #1 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be64() line 806 |
| Taint snippet | state = get_unaligned_be64(src) ^ roundKey[0]; |
| Tainted var | state |
| Subscript | [] line 809 |
| Sink snippet | state = T0[(int)(state >> 56) ] ^ |
| Possibly guarded | no |
Dismissed: state >> 56 on a u64 yields a value in [0, 255] — exactly 8 bits. T0 has 256 entries. No counterexample exists: the maximum possible index is 0xFF = 255, which is the last valid index.
Finding #2 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be64() line 806 |
| Taint snippet | state = get_unaligned_be64(src) ^ roundKey[0]; |
| Tainted var | state |
| Subscript | [] line 810 |
| Sink snippet | T1[(int)(state >> 48) & 0xff] ^ |
| Possibly guarded | no |
Dismissed: (state >> 48) & 0xff is masked to 8 bits, range [0, 255]. T1 has 256 entries. No counterexample possible.
Finding #3 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be64() line 806 |
| Taint snippet | state = get_unaligned_be64(src) ^ roundKey[0]; |
| Tainted var | state |
| Subscript | [] line 811 |
| Sink snippet | T2[(int)(state >> 40) & 0xff] ^ |
| Possibly guarded | no |
Dismissed: (state >> 40) & 0xff is masked to 8 bits, range [0, 255]. T2 has 256 entries. No counterexample possible.
Finding #4 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be64() line 806 |
| Taint snippet | state = get_unaligned_be64(src) ^ roundKey[0]; |
| Tainted var | state |
| Subscript | [] line 812 |
| Sink snippet | T3[(int)(state >> 32) & 0xff] ^ |
| Possibly guarded | no |
Dismissed: (state >> 32) & 0xff is masked to 8 bits, range [0, 255]. T3 has 256 entries. No counterexample possible.
Finding #5 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be64() line 806 |
| Taint snippet | state = get_unaligned_be64(src) ^ roundKey[0]; |
| Tainted var | state |
| Subscript | [] line 813 |
| Sink snippet | T4[(int)(state >> 24) & 0xff] ^ |
| Possibly guarded | no |
Dismissed: (state >> 24) & 0xff is masked to 8 bits, range [0, 255]. T4 has 256 entries. No counterexample possible.
Finding #6 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be64() line 806 |
| Taint snippet | state = get_unaligned_be64(src) ^ roundKey[0]; |
| Tainted var | state |
| Subscript | [] line 814 |
| Sink snippet | T5[(int)(state >> 16) & 0xff] ^ |
| Possibly guarded | no |
Dismissed: (state >> 16) & 0xff is masked to 8 bits, range [0, 255]. T5 has 256 entries. No counterexample possible.
Finding #7 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be64() line 806 |
| Taint snippet | state = get_unaligned_be64(src) ^ roundKey[0]; |
| Tainted var | state |
| Subscript | [] line 815 |
| Sink snippet | T6[(int)(state >> 8) & 0xff] ^ |
| Possibly guarded | no |
Dismissed: (state >> 8) & 0xff is masked to 8 bits, range [0, 255]. T6 has 256 entries. No counterexample possible.
Finding #8 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be64() line 806 |
| Taint snippet | state = get_unaligned_be64(src) ^ roundKey[0]; |
| Tainted var | state |
| Subscript | [] line 816 |
| Sink snippet | T7[(int)(state ) & 0xff] ^ |
| Possibly guarded | no |
Dismissed: state & 0xff is masked to 8 bits, range [0, 255]. T7 has 256 entries. No counterexample possible.
Finding #9 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be64() line 806 |
| Taint snippet | state = get_unaligned_be64(src) ^ roundKey[0]; |
| Tainted var | state |
| Subscript | [] line 820 |
| Sink snippet | state = (T0[(int)(state >> 56) ] & 0xff00000000000000ULL) ^ |
| Possibly guarded | no |
Dismissed: After the loop, state is the XOR of multiple T-table lookups and round keys — still a u64. state >> 56 yields [0, 255]. T0 has 256 entries. No counterexample possible.
Finding #10 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be64() line 806 |
| Taint snippet | state = get_unaligned_be64(src) ^ roundKey[0]; |
| Tainted var | state |
| Subscript | [] line 821 |
| Sink snippet | (T1[(int)(state >> 48) & 0xff] & 0x00ff000000000000ULL) ^ |
| Possibly guarded | no |
Dismissed: (state >> 48) & 0xff masked to 8 bits. T1 has 256 entries. No counterexample possible.
Finding #11 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be64() line 806 |
| Taint snippet | state = get_unaligned_be64(src) ^ roundKey[0]; |
| Tainted var | state |
| Subscript | [] line 822 |
| Sink snippet | (T2[(int)(state >> 40) & 0xff] & 0x0000ff0000000000ULL) ^ |
| Possibly guarded | no |
Dismissed: (state >> 40) & 0xff masked to 8 bits. T2 has 256 entries. No counterexample possible.
Finding #12 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be64() line 806 |
| Taint snippet | state = get_unaligned_be64(src) ^ roundKey[0]; |
| Tainted var | state |
| Subscript | [] line 823 |
| Sink snippet | (T3[(int)(state >> 32) & 0xff] & 0x000000ff00000000ULL) ^ |
| Possibly guarded | no |
Dismissed: (state >> 32) & 0xff masked to 8 bits. T3 has 256 entries. No counterexample possible.
Finding #13 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be64() line 806 |
| Taint snippet | state = get_unaligned_be64(src) ^ roundKey[0]; |
| Tainted var | state |
| Subscript | [] line 824 |
| Sink snippet | (T4[(int)(state >> 24) & 0xff] & 0x00000000ff000000ULL) ^ |
| Possibly guarded | no |
Dismissed: (state >> 24) & 0xff masked to 8 bits. T4 has 256 entries. No counterexample possible.
Finding #14 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be64() line 806 |
| Taint snippet | state = get_unaligned_be64(src) ^ roundKey[0]; |
| Tainted var | state |
| Subscript | [] line 825 |
| Sink snippet | (T5[(int)(state >> 16) & 0xff] & 0x0000000000ff0000ULL) ^ |
| Possibly guarded | no |
Dismissed: (state >> 16) & 0xff masked to 8 bits. T5 has 256 entries. No counterexample possible.
Finding #15 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be64() line 806 |
| Taint snippet | state = get_unaligned_be64(src) ^ roundKey[0]; |
| Tainted var | state |
| Subscript | [] line 826 |
| Sink snippet | (T6[(int)(state >> 8) & 0xff] & 0x000000000000ff00ULL) ^ |
| Possibly guarded | no |
Dismissed: (state >> 8) & 0xff masked to 8 bits. T6 has 256 entries. No counterexample possible.
Finding #16 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be64() line 806 |
| Taint snippet | state = get_unaligned_be64(src) ^ roundKey[0]; |
| Tainted var | state |
| Subscript | [] line 827 |
| Sink snippet | (T7[(int)(state ) & 0xff] & 0x00000000000000ffULL) ^ |
| Possibly guarded | no |
Dismissed: state & 0xff masked to 8 bits. T7 has 256 entries. No counterexample possible.
khazad_setkey() — crypto/khazad.c FP confidence=high
All array subscripts derived from K1 are mathematically bounded to [0,255] by shift+mask arithmetic. T0[(K1>>56)] uses only bits 63:56 of a u64, yielding 0-255. All other accesses use '& 0xff' masks. T0-T7 and S(=T7) are 256-entry lookup tables, so no OOB access is possible for any key value. The scanner flagged key material as 'server-supplied' and did not model the tight arithmetic bounds established by the shift/mask operations.
Finding #1 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be64() line 765 |
| Taint snippet | K1 = get_unaligned_be64(&in_key[8]); |
| Tainted var | K1 |
| Subscript | [] line 769 |
| Sink snippet | ctx->E[r] = T0[(int)(K1 >> 56) ] ^ |
| Possibly guarded | no |
Dismissed: K1>>56 on a u64 yields bits 63:56 = value 0-255. T0 has 256 entries. No counterexample exists: cannot construct a u64 whose top 8 bits produce an index >= 256.
Finding #2 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be64() line 765 |
| Taint snippet | K1 = get_unaligned_be64(&in_key[8]); |
| Tainted var | K1 |
| Subscript | [] line 770 |
| Sink snippet | T1[(int)(K1 >> 48) & 0xff] ^ |
| Possibly guarded | no |
Dismissed: (K1>>48)&0xff is always 0-255. T1 has 256 entries.
Finding #3 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be64() line 765 |
| Taint snippet | K1 = get_unaligned_be64(&in_key[8]); |
| Tainted var | K1 |
| Subscript | [] line 771 |
| Sink snippet | T2[(int)(K1 >> 40) & 0xff] ^ |
| Possibly guarded | no |
Dismissed: (K1>>40)&0xff is always 0-255. T2 has 256 entries.
Finding #4 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be64() line 765 |
| Taint snippet | K1 = get_unaligned_be64(&in_key[8]); |
| Tainted var | K1 |
| Subscript | [] line 772 |
| Sink snippet | T3[(int)(K1 >> 32) & 0xff] ^ |
| Possibly guarded | no |
Dismissed: (K1>>32)&0xff is always 0-255. T3 has 256 entries.
Finding #5 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be64() line 765 |
| Taint snippet | K1 = get_unaligned_be64(&in_key[8]); |
| Tainted var | K1 |
| Subscript | [] line 773 |
| Sink snippet | T4[(int)(K1 >> 24) & 0xff] ^ |
| Possibly guarded | no |
Dismissed: (K1>>24)&0xff is always 0-255. T4 has 256 entries.
Finding #6 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be64() line 765 |
| Taint snippet | K1 = get_unaligned_be64(&in_key[8]); |
| Tainted var | K1 |
| Subscript | [] line 774 |
| Sink snippet | T5[(int)(K1 >> 16) & 0xff] ^ |
| Possibly guarded | no |
Dismissed: (K1>>16)&0xff is always 0-255. T5 has 256 entries.
Finding #7 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be64() line 765 |
| Taint snippet | K1 = get_unaligned_be64(&in_key[8]); |
| Tainted var | K1 |
| Subscript | [] line 775 |
| Sink snippet | T6[(int)(K1 >> 8) & 0xff] ^ |
| Possibly guarded | no |
Dismissed: (K1>>8)&0xff is always 0-255. T6 has 256 entries.
Finding #8 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be64() line 765 |
| Taint snippet | K1 = get_unaligned_be64(&in_key[8]); |
| Tainted var | K1 |
| Subscript | [] line 776 |
| Sink snippet | T7[(int)(K1 ) & 0xff] ^ |
| Possibly guarded | no |
Dismissed: K1&0xff is always 0-255. T7 has 256 entries.
Finding #9 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be64() line 765 |
| Taint snippet | K1 = get_unaligned_be64(&in_key[8]); |
| Tainted var | K1 |
| Subscript | [] line 785 |
| Sink snippet | ctx->D[r] = T0[(int)S[(int)(K1 >> 56) ] & 0xff] ^ |
| Possibly guarded | no |
Dismissed: K1>>56 is 0-255 (inner index into S=T7[256]); S[...]&0xff is 0-255 (outer index into T0[256]). Both levels bounded.
Finding #10 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be64() line 765 |
| Taint snippet | K1 = get_unaligned_be64(&in_key[8]); |
| Tainted var | K1 |
| Subscript | [] line 786 |
| Sink snippet | T1[(int)S[(int)(K1 >> 48) & 0xff] & 0xff] ^ |
| Possibly guarded | no |
Dismissed: Both inner and outer indices masked to 0-255 by &0xff. S and T1 each have 256 entries.
Finding #11 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be64() line 765 |
| Taint snippet | K1 = get_unaligned_be64(&in_key[8]); |
| Tainted var | K1 |
| Subscript | [] line 787 |
| Sink snippet | T2[(int)S[(int)(K1 >> 40) & 0xff] & 0xff] ^ |
| Possibly guarded | no |
Dismissed: Both inner and outer indices masked to 0-255 by &0xff. S and T2 each have 256 entries.
Finding #12 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be64() line 765 |
| Taint snippet | K1 = get_unaligned_be64(&in_key[8]); |
| Tainted var | K1 |
| Subscript | [] line 788 |
| Sink snippet | T3[(int)S[(int)(K1 >> 32) & 0xff] & 0xff] ^ |
| Possibly guarded | no |
Dismissed: Both inner and outer indices masked to 0-255 by &0xff. S and T3 each have 256 entries.
Finding #13 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be64() line 765 |
| Taint snippet | K1 = get_unaligned_be64(&in_key[8]); |
| Tainted var | K1 |
| Subscript | [] line 789 |
| Sink snippet | T4[(int)S[(int)(K1 >> 24) & 0xff] & 0xff] ^ |
| Possibly guarded | no |
Dismissed: Both inner and outer indices masked to 0-255 by &0xff. S and T4 each have 256 entries.
Finding #14 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be64() line 765 |
| Taint snippet | K1 = get_unaligned_be64(&in_key[8]); |
| Tainted var | K1 |
| Subscript | [] line 790 |
| Sink snippet | T5[(int)S[(int)(K1 >> 16) & 0xff] & 0xff] ^ |
| Possibly guarded | no |
Dismissed: Both inner and outer indices masked to 0-255 by &0xff. S and T5 each have 256 entries.
Finding #15 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be64() line 765 |
| Taint snippet | K1 = get_unaligned_be64(&in_key[8]); |
| Tainted var | K1 |
| Subscript | [] line 791 |
| Sink snippet | T6[(int)S[(int)(K1 >> 8) & 0xff] & 0xff] ^ |
| Possibly guarded | no |
Dismissed: Both inner and outer indices masked to 0-255 by &0xff. S and T6 each have 256 entries.
Finding #16 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be64() line 765 |
| Taint snippet | K1 = get_unaligned_be64(&in_key[8]); |
| Tainted var | K1 |
| Subscript | [] line 792 |
| Sink snippet | T7[(int)S[(int)(K1 ) & 0xff] & 0xff]; |
| Possibly guarded | no |
Dismissed: Both inner and outer indices masked to 0-255 by &0xff. S and T7 each have 256 entries.
seed_set_key() — crypto/seed.c FP confidence=high
The static scanner incorrectly propagates taint from t0/t1 through to the array subscripts. The actual subscript used is the return value of byte(), which returns a u8 — always in range [0,255]. The SS0/SS1/SS2/SS3 tables are 256-entry S-boxes. No out-of-bounds access is possible regardless of the value of t0 or t1. The u8 return type of byte() provides an implicit but complete bounds guarantee.
Finding #1 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be32() line 334 |
| Taint snippet | x1 = get_unaligned_be32(&in_key[0]); |
| Tainted var | t0 |
| Subscript | [] line 342 |
| Sink snippet | *(keyout++) = SS0[byte(t0, 0)] ^ SS1[byte(t0, 1)] ^ |
| Possibly guarded | no |
Dismissed: byte(t0, 0) returns a u8 (0-255). SS0 has 256 entries. No counterexample exists: any 32-bit t0 produces a byte value in [0,255], which is always a valid index into the 256-entry table. The finding is a false positive due to the u8 truncation in byte().
Finding #2 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be32() line 334 |
| Taint snippet | x1 = get_unaligned_be32(&in_key[0]); |
| Tainted var | t0 |
| Subscript | [] line 343 |
| Sink snippet | SS2[byte(t0, 2)] ^ SS3[byte(t0, 3)]; |
| Possibly guarded | no |
Dismissed: byte(t0, 2) and byte(t0, 3) both return u8 (0-255). SS2 and SS3 each have 256 entries. The u8 return type of byte() unconditionally bounds the subscript. False positive.
Finding #3 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be32() line 335 |
| Taint snippet | x2 = get_unaligned_be32(&in_key[4]); |
| Tainted var | t1 |
| Subscript | [] line 344 |
| Sink snippet | *(keyout++) = SS0[byte(t1, 0)] ^ SS1[byte(t1, 1)] ^ |
| Possibly guarded | no |
Dismissed: byte(t1, 0) and byte(t1, 1) return u8 (0-255). SS0 and SS1 have 256 entries. The subscript is the u8 output of byte(), not t1 itself. False positive.
Finding #4 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | get_unaligned_be32() line 335 |
| Taint snippet | x2 = get_unaligned_be32(&in_key[4]); |
| Tainted var | t1 |
| Subscript | [] line 345 |
| Sink snippet | SS2[byte(t1, 2)] ^ SS3[byte(t1, 3)]; |
| Possibly guarded | no |
Dismissed: byte(t1, 2) and byte(t1, 3) return u8 (0-255). SS2 and SS3 have 256 entries. The u8 type constraint in byte() makes OOB impossible. False positive.
streebog_xlps() — crypto/streebog_generic.c FP confidence=high
All eight array subscripts are masked with '& 0xFF' before indexing into the Ax lookup tables. Each Ax[j] table has exactly 256 entries (indices 0–255), so the mask is a tight and sufficient bounds constraint. No out-of-bounds access is possible regardless of the input values. The scanner failed to recognize the masking operation as a bounds check.
Finding #1 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | le64_to_cpu() line 873 |
| Taint snippet | r0 = le64_to_cpu(x->qword[0] ^ y->qword[0]); |
| Tainted var | r0 |
| Subscript | [] line 883 |
| Sink snippet | data->qword[i] = cpu_to_le64(Ax[0][r0 & 0xFF]); |
| Possibly guarded | no |
Dismissed: r0 & 0xFF constrains the index to [0,255], matching the Ax[0] table size of 256. No counterexample exists.
Finding #2 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | le64_to_cpu() line 874 |
| Taint snippet | r1 = le64_to_cpu(x->qword[1] ^ y->qword[1]); |
| Tainted var | r1 |
| Subscript | [] line 884 |
| Sink snippet | data->qword[i] ^= cpu_to_le64(Ax[1][r1 & 0xFF]); |
| Possibly guarded | no |
Dismissed: r1 & 0xFF constrains the index to [0,255], matching the Ax[1] table size of 256. No counterexample exists.
Finding #3 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | le64_to_cpu() line 875 |
| Taint snippet | r2 = le64_to_cpu(x->qword[2] ^ y->qword[2]); |
| Tainted var | r2 |
| Subscript | [] line 885 |
| Sink snippet | data->qword[i] ^= cpu_to_le64(Ax[2][r2 & 0xFF]); |
| Possibly guarded | no |
Dismissed: r2 & 0xFF constrains the index to [0,255], matching the Ax[2] table size of 256. No counterexample exists.
Finding #4 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | le64_to_cpu() line 876 |
| Taint snippet | r3 = le64_to_cpu(x->qword[3] ^ y->qword[3]); |
| Tainted var | r3 |
| Subscript | [] line 886 |
| Sink snippet | data->qword[i] ^= cpu_to_le64(Ax[3][r3 & 0xFF]); |
| Possibly guarded | no |
Dismissed: r3 & 0xFF constrains the index to [0,255], matching the Ax[3] table size of 256. No counterexample exists.
Finding #5 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | le64_to_cpu() line 877 |
| Taint snippet | r4 = le64_to_cpu(x->qword[4] ^ y->qword[4]); |
| Tainted var | r4 |
| Subscript | [] line 887 |
| Sink snippet | data->qword[i] ^= cpu_to_le64(Ax[4][r4 & 0xFF]); |
| Possibly guarded | no |
Dismissed: r4 & 0xFF constrains the index to [0,255], matching the Ax[4] table size of 256. No counterexample exists.
Finding #6 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | le64_to_cpu() line 878 |
| Taint snippet | r5 = le64_to_cpu(x->qword[5] ^ y->qword[5]); |
| Tainted var | r5 |
| Subscript | [] line 888 |
| Sink snippet | data->qword[i] ^= cpu_to_le64(Ax[5][r5 & 0xFF]); |
| Possibly guarded | no |
Dismissed: r5 & 0xFF constrains the index to [0,255], matching the Ax[5] table size of 256. No counterexample exists.
Finding #7 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | le64_to_cpu() line 879 |
| Taint snippet | r6 = le64_to_cpu(x->qword[6] ^ y->qword[6]); |
| Tainted var | r6 |
| Subscript | [] line 889 |
| Sink snippet | data->qword[i] ^= cpu_to_le64(Ax[6][r6 & 0xFF]); |
| Possibly guarded | no |
Dismissed: r6 & 0xFF constrains the index to [0,255], matching the Ax[6] table size of 256. No counterexample exists.
Finding #8 — Category C — false positive
| Category | Cat C — server value → array subscript |
|---|---|
| Taint source | le64_to_cpu() line 880 |
| Taint snippet | r7 = le64_to_cpu(x->qword[7] ^ y->qword[7]); |
| Tainted var | r7 |
| Subscript | [] line 890 |
| Sink snippet | data->qword[i] ^= cpu_to_le64(Ax[7][r7 & 0xFF]); |
| Possibly guarded | no |
Dismissed: r7 & 0xFF constrains the index to [0,255], matching the Ax[7] table size of 256. No counterexample exists.
io_copy_regbuf() — io_uring/mock_file.c FP confidence=high
The function correctly bounds all copy sizes via min(iov_iter_count(reg_iter), buflen) where buflen=PAGE_SIZE, matching the kzalloc(PAGE_SIZE) allocation. No counterexample is constructable because len <= PAGE_SIZE == sizeof(tmp_buf) always holds. The scanner incorrectly propagated taint from the iov_iter through min() without recognizing the PAGE_SIZE upper bound as a sufficient guard.
Finding #1 — Category G2 — false positive
| Category | Cat G2 — unvalidated size argument to copy_from/to_user |
|---|---|
| Taint source | copy_from_user() line 51 |
| Taint snippet | if (copy_from_user(tmp_buf, ubuf, len)) |
| Tainted var | len |
| Unvalidated size | copy_from_user() arg 2 line 51 — size len |
| Sink snippet | if (copy_from_user(tmp_buf, ubuf, len)) |
| Possibly guarded | no |
Dismissed: len = min(iov_iter_count(reg_iter), buflen) where buflen = PAGE_SIZE (a compile-time kernel constant). tmp_buf is allocated with kzalloc(PAGE_SIZE), so len <= PAGE_SIZE == sizeof(tmp_buf) always. No counterexample exists: no value of iov_iter_count() can make len exceed PAGE_SIZE. The min() is a tight and sufficient guard. False positive.
io_recvmsg_multishot() — io_uring/net.c FP confidence=high
copy_len is computed as sizeof(struct io_uring_recvmsg_out) + min(msg_namelen, namelen). Both namelen (from io_recvmsg_prep_multishot, kernel-internal) and msg_namelen (from kernel socket layer, bounded by sockaddr_storage) are kernel-controlled. The source buffer hdr is a stack struct large enough to hold the maximum copy_len. The user buffer io->buf is sized by io_buffer_select/io_recvmsg_prep_multishot to accommodate the full multishot header. No genuine vulnerability exists here.
Finding #1 — Category G2 — false positive
| Category | Cat G2 — unvalidated size argument to copy_from/to_user |
|---|---|
| Taint source | copy_to_user() line 1042 |
| Taint snippet | if (copy_to_user(io->buf, &hdr, copy_len)) { |
| Tainted var | copy_len |
| Unvalidated size | copy_to_user() arg 2 line 1042 — size copy_len |
| Sink snippet | if (copy_to_user(io->buf, &hdr, copy_len)) { |
| Possibly guarded | no |
Dismissed: copy_len is bounded by sizeof(struct io_recvmsg_multishot_hdr) due to the min(msg_namelen, namelen) logic. msg_namelen is kernel-returned from sock_recvmsg and bounded by sockaddr_storage size. namelen is set by io_recvmsg_prep_multishot which validates it fits in the user buffer. The scanner misidentified the copy_to_user destination computation as a taint source. No counterexample can be constructed that would cause OOB — copy_len cannot exceed sizeof(hdr) and the user buffer is pre-validated to be large enough.
io_probe() — io_uring/register.c FP confidence=high
The `size` variable is not user-supplied — it is computed internally by the kernel using `struct_size(p, ops, nr_args)`, where `nr_args` has already been clamped to `IORING_OP_LAST` (line 48-49) and further limited to 256 by the call site guard at line 821. The allocation at line 52 uses the same `size`, and the buffer `p` is validated to be all-zeros before being written. The `copy_to_user` on line 69 copies exactly `size` bytes from the kernel buffer `p` (which was allocated with `memdup_user(arg, size)` — same size) back to `arg`. Since `arg` was originally copied FROM userspace with length `size`, copying back `size` bytes cannot overflow the user buffer (the user provided at least `size` bytes). The scanner is treating `size` as tainted because it derives from `nr_args` which comes from userspace, but the clamp to `IORING_OP_LAST` (a compile-time constant ≤256) makes it fully kernel-controlled.
Finding #1 — Category G2 — false positive
| Category | Cat G2 — unvalidated size argument to copy_from/to_user |
|---|---|
| Taint source | copy_to_user() line 69 |
| Taint snippet | if (copy_to_user(arg, p, size)) |
| Tainted var | size |
| Unvalidated size | copy_to_user() arg 2 line 69 — size size |
| Sink snippet | if (copy_to_user(arg, p, size)) |
| Possibly guarded | no |
Dismissed: nr_args is user-supplied but is clamped to IORING_OP_LAST (a compile-time constant) at line 48-49, and further constrained to ≤256 by the call site guard (line 821). Thus `size = struct_size(p, ops, nr_args)` is bounded by a kernel constant. The memdup_user allocates exactly `size` bytes, and copy_to_user copies those same `size` bytes back. No counterexample exists: any nr_args value that passes the call-site guard (≤256) and the internal clamp (≤IORING_OP_LAST) produces a size that was already used for the allocation, so the copy cannot exceed the buffer. This is a false positive.
io_register_iowq_aff() — io_uring/register.c FP confidence=high
The 'len' parameter comes from user space (nr_args passed by the caller), but it is properly bounded before use. At line 325-326, len is clamped to cpumask_size() if it exceeds that value. The destination buffer new_mask is allocated by alloc_cpumask_var() which allocates exactly cpumask_size() bytes. Since len is clamped to cpumask_size() before the copy_from_user call, the copy cannot overflow the destination buffer. The scanner missed the clamp at lines 325-326 because it only checked for a conditional (not a clamp/assignment) and marked the finding as 'Possibly guarded: no', which is incorrect — the clamp IS a guard.
Finding #1 — Category G2 — false positive
| Category | Cat G2 — unvalidated size argument to copy_from/to_user |
|---|---|
| Taint source | copy_from_user() line 335 |
| Taint snippet | ret = copy_from_user(new_mask, arg, len); |
| Tainted var | len |
| Unvalidated size | copy_from_user() arg 2 line 335 — size len |
| Sink snippet | ret = copy_from_user(new_mask, arg, len); |
| Possibly guarded | no |
Dismissed: len is user-supplied (nr_args from the ioctl caller), but lines 325-326 clamp it: 'if (len > cpumask_size()) len = cpumask_size();'. The destination new_mask is allocated by alloc_cpumask_var() which allocates exactly cpumask_size() bytes. After the clamp, len <= cpumask_size(), so copy_from_user cannot write beyond the allocated buffer. No counterexample exists: any len > cpumask_size() is reduced to cpumask_size() before the copy. The scanner incorrectly reported 'Possibly guarded: no' and missed the clamp assignment as a sufficient bounds check.
do_mq_notify() — ipc/mqueue.c FP confidence=high
NOTIFY_COOKIE_LEN is a kernel-internal compile-time constant, not a user-supplied or server-supplied value. The scanner incorrectly flagged it as tainted because it appears as the size argument to copy_from_user(). The destination buffer nc->data was allocated via alloc_skb(NOTIFY_COOKIE_LEN, GFP_KERNEL), so the buffer capacity exactly equals the copy size. There is no user-controlled size involved — the user supplies only the source pointer (sigev_value.sival_ptr), not the length.
Finding #1 — Category G2 — false positive
| Category | Cat G2 — unvalidated size argument to copy_from/to_user |
|---|---|
| Taint source | copy_from_user() line 1295 |
| Taint snippet | if (copy_from_user(nc->data, |
| Tainted var | NOTIFY_COOKIE_LEN |
| Unvalidated size | copy_from_user() arg 2 line 1295 — size NOTIFY_COOKIE_LEN |
| Sink snippet | if (copy_from_user(nc->data, |
| Possibly guarded | no |
Dismissed: NOTIFY_COOKIE_LEN is a kernel-defined compile-time constant (not user-supplied). The sk_buff nc is allocated with alloc_skb(NOTIFY_COOKIE_LEN, GFP_KERNEL) on line 1291, making the buffer exactly NOTIFY_COOKIE_LEN bytes. The copy_from_user() on line 1295 copies exactly NOTIFY_COOKIE_LEN bytes into nc->data, which is correctly sized. No counterexample can be constructed because there is no variable size — NOTIFY_COOKIE_LEN is fixed at compile time. The scanner erroneously treated this constant as tainted. This is a false positive.
load_msg() — ipc/msgutil.c FP confidence=high
The scanner incorrectly treats `alen` as user-controlled taint. `alen` is computed as `min(len, DATALEN_MSG)` or `min(len, DATALEN_SEG)` — kernel constants cap it. `alloc_msg(len)` allocates exactly the right number of segments and bytes to accommodate the full `len`, so each `copy_from_user` writes within allocated bounds. No genuine vulnerability exists.
Finding #1 — Category G2 — false positive
| Category | Cat G2 — unvalidated size argument to copy_from/to_user |
|---|---|
| Taint source | copy_from_user() line 104 |
| Taint snippet | if (copy_from_user(msg + 1, src, alen)) |
| Tainted var | alen |
| Unvalidated size | copy_from_user() arg 2 line 104 — size alen |
| Sink snippet | if (copy_from_user(msg + 1, src, alen)) |
| Possibly guarded | no |
Dismissed: alen = min(len, DATALEN_MSG) is bounded by the kernel constant DATALEN_MSG. The destination buffer (msg+1) is allocated by alloc_msg() to hold exactly min(len, DATALEN_MSG) bytes. No counterexample can be constructed — the copy size cannot exceed the buffer capacity.
Finding #2 — Category G2 — false positive
| Category | Cat G2 — unvalidated size argument to copy_from/to_user |
|---|---|
| Taint source | copy_from_user() line 111 |
| Taint snippet | if (copy_from_user(seg + 1, src, alen)) |
| Tainted var | alen |
| Unvalidated size | copy_from_user() arg 2 line 111 — size alen |
| Sink snippet | if (copy_from_user(seg + 1, src, alen)) |
| Possibly guarded | no |
Dismissed: alen = min(len, DATALEN_SEG) is bounded by the kernel constant DATALEN_SEG. Each segment is allocated by alloc_msg() with a data area of DATALEN_SEG bytes (or less for the final segment). The min() ensures the copy never exceeds segment capacity. No counterexample is possible.
store_msg() — ipc/msgutil.c FP confidence=high
The `alen` value in both findings is NOT server-supplied or user-controlled. It is computed via `min(len, DATALEN_MSG)` and `min(len, DATALEN_SEG)`, where `len` is a kernel-internal parameter passed by the caller (the amount the caller wants to copy to userspace), and DATALEN_MSG/DATALEN_SEG are kernel-defined constants. The `min()` ensures `alen` never exceeds either the caller-supplied `len` or the segment data capacity constant. The taint source the scanner flagged (the return value of `copy_to_user()`) is just an error code — the scanner appears confused about what is tainted. Neither `alen` nor `dest` originates from a server-supplied or user-supplied field in this function. The caller is responsible for passing a valid `len` (the declared message size), which is itself bounded by kernel message queue limits. No missing validation is present.
Finding #1 — Category G2 — false positive
| Category | Cat G2 — unvalidated size argument to copy_from/to_user |
|---|---|
| Taint source | copy_to_user() line 164 |
| Taint snippet | if (copy_to_user(dest, msg + 1, alen)) |
| Tainted var | alen |
| Unvalidated size | copy_to_user() arg 2 line 164 — size alen |
| Sink snippet | if (copy_to_user(dest, msg + 1, alen)) |
| Possibly guarded | no |
Dismissed: alen is computed as min(len, DATALEN_MSG) where DATALEN_MSG is a kernel constant (PAGE_SIZE - sizeof(struct msg_msg)). len is a kernel-internal parameter. The scanner incorrectly treats copy_to_user()'s return value as a taint source propagating into alen; in reality alen is a bounded minimum. No counterexample can be constructed where alen exceeds the data region immediately following the msg_msg struct (which is exactly DATALEN_MSG bytes), so no OOB is possible.
Finding #2 — Category G2 — false positive
| Category | Cat G2 — unvalidated size argument to copy_from/to_user |
|---|---|
| Taint source | copy_to_user() line 171 |
| Taint snippet | if (copy_to_user(dest, seg + 1, alen)) |
| Tainted var | alen |
| Unvalidated size | copy_to_user() arg 2 line 171 — size alen |
| Sink snippet | if (copy_to_user(dest, seg + 1, alen)) |
| Possibly guarded | no |
Dismissed: alen is computed as min(len, DATALEN_SEG) where DATALEN_SEG is a kernel constant (PAGE_SIZE - sizeof(struct msg_msgseg)). len is decremented by prior alen each iteration, so it only shrinks. The min() ensures alen never exceeds the data region following the msg_msgseg struct. No counterexample can be constructed. False positive from scanner confusing copy_to_user return-value taint with size argument taint.