Bounds Checker Report — 20260820_150608_mm

Date: 2026-08-20 15:07:16 Model: claude-sonnet-4-6 Source: mm Files: 190 Stage 1: 18 findings (Cat G2: 18) Stage 2: 0 real  |  18 FP  |  0 unanalyzed Kernel: v7.2-rc7-32-gaf5a019bf97e Branch: work/fscache-fixes
32 local commit(s) since origin/master
  1. af5a019bf97e cifs: fix i_size inconsistency in smb2_duplicate_extents() on FSCTL failure
  2. e6a9c11309cd cifs: call pagecache_isize_extended() in cifs_setsize() when extending
  3. 5fce3864d8e5 smb: client: restore the data_offset bound in is_valid_oplock_break()
  4. 7f11fbcc7141 cifs: clear tcon after cifsFileInfo_put() in cifs_file_set_size()
  5. 1e13b07759b9 smb: client: Avoid leaking sensitive data to the heap in connect.c
  6. d91fefcf00b0 smb: client: Clear sensitive stack data in smb1encrypt.c
  7. 24ec30094b95 smb: client: Clear sensitive stack data in cifsencrypt.c
  8. 3e200e7995cc smb: client: Clear sensitive stack and heap data in smb2ops.c
  9. 13881ad0a8d9 smb: client: Clear sensitive stack data in smb2transport.c
  10. 3356da3ae12b Revert "cifs: remove all cifs files before kill super"
  11. 98dfc0f0348c smb: client: fix use-before-check of ReparseDataLength in reparse_buf_ptr()
  12. 442beae405ea smb: client: fix ALIGN() overflow in symlink_data() error context loop
  13. 67b83682e9c5 smb: client: simplify __build_path_from_dentry_optional_prefix()
  14. cb4c026ddc77 smb: client: fix UAF and buffer leak in cifs_check_trans2() for malformed secondary T2
  15. f1e640a65f45 smb: client: fix OOB read/write from unvalidated DataOffset in coalesce_t2()
  16. e56686589295 smb/client: decode reparse metadata using its payload type
  17. 0a09b6270c91 smb/client: preserve open info type across compound queries
  18. c2f17b3a404d smb/client: mark missing nlink values as unknown
  19. 746f8bb16e15 cifs: fix clearing stats for fastest execution of each smb2 command
  20. 7886f8ae3173 smb/client: remove unused file flags ioctl handlers
  21. 1f852aaa3c8c smb/client: implement fileattr_set for compression flags
  22. 77d852c76342 smb/client: fix nlink of an overwritten open file
  23. 60be95527bc8 cifs: remove dead size-update blocks in cifs_setattr_unix/nounix
  24. 297d8026a570 cifs: remove redundant size-update block in cifs_remap_file_range()
  25. 32a7af68df73 cifs: add cifs_resize_file_locked() to guard fscache_resize_cookie() under i_rwsem
  26. 364b18323058 cifs: use cifs_invalidate_cache() in cifs_do_truncate() for O_TRUNC
  27. b1b741cf8e7c smb: client: clear ce->tgthint in free_tgts()
  28. bf86c08123c6 smb: client: harden DFS cache against invalid target hints
  29. b8e5dc4f95e5 smb: client: clear setuid/setgid bit on write with cifsacl/modefromsid/posix extensions
  30. 45f84cf25a08 smb: client: set replay flag on the read send-error retry path
  31. deb6468f4164 smb: client: fix request buffer leak in smb2_new_read_req()
  32. a2f9fb451c68 smb/client: return EOPNOTSUPP for unsupported O_TMPFILE

Contents

mm/ (12 functions) — 0 real, 13 FP
mm/kasan/ (1 function) — 0 real, 5 FP
mm/ (12 functions) — 0 real, 13 FP

Summary

FunctionFileAssessmentConfidenceRealFPUnanalyzed
mm/ — 12 functions, 0 real, 13 FP
pin_longterm_test_read()mm/gup_test.cFPhigh010
split_huge_pages_write()mm/huge_memory.cFPhigh010
mm/kasan/ — 1 function, 0 real, 5 FP
copy_user_test_oob()mm/kasan/kasan_test_c.cFPhigh050
mm/ — 12 functions, 0 real, 13 FP
copy_folio_from_user()mm/memory.cFPhigh010
get_bitmap()mm/mempolicy.cFPhigh010
do_pages_stat()mm/migrate.cFPhigh020
shrinker_debugfs_scan_write()mm/shrinker_debug.cFPhigh010
mfill_copy_folio_locked()mm/userfaultfd.cFPhigh010
mfill_copy_folio_retry()mm/userfaultfd.cFPhigh010
memdup_user()mm/util.cFPhigh010
memdup_user_nul()mm/util.cFPhigh010
vmemdup_user()mm/util.cFPhigh010
lru_gen_seq_write()mm/vmscan.cFPhigh010

Function Details

pin_longterm_test_read() — mm/gup_test.c FP confidence=high

The static analyzer incorrectly flagged PAGE_SIZE as a user-controlled size argument to copy_to_user(). PAGE_SIZE is a kernel-internal constant (defined at compile time or boot time based on architecture), not derived from any user-supplied or server-supplied data. The taint source listed ('copy_to_user() line 308') is the sink itself, not a genuine external taint source. The loop iterates over kernel-pinned pages using the kernel-controlled counter pin_longterm_test_nr_pages, and copies exactly PAGE_SIZE bytes per page — all kernel-internal values. The user_addr is read from userspace via copy_from_user, but it is used only as the destination pointer in copy_to_user, not as a size argument.

Finding #1 — Category G2 — false positive

CategoryCat G2 — unvalidated size argument to copy_from/to_user
Taint sourcecopy_to_user() line 308
Taint snippetret = copy_to_user((void __user *)(unsigned long)user_addr, addr,
Tainted varPAGE_SIZE
Unvalidated sizecopy_to_user() arg 2 line 308 — size PAGE_SIZE
Sink snippetret = copy_to_user((void __user *)(unsigned long)user_addr, addr,
Possibly guardedno
Dismissed: PAGE_SIZE is a kernel compile-time or boot-time constant — it is not user-supplied or server-supplied in any way. The scanner appears to have confused the taint source: it lists 'copy_to_user()' itself as both source and sink, which is a clear false positive. The size argument to copy_to_user() is PAGE_SIZE, which is entirely kernel-controlled. No counterexample can be constructed where a user-controlled value reaches the size argument, because the size argument is PAGE_SIZE, a kernel constant. This is a straightforward false positive from the static analyzer misidentifying the taint source.

split_huge_pages_write() — mm/huge_memory.c FP confidence=high

The flagged copy_from_user call uses min_t(size_t, count, MAX_INPUT_BUF_SZ) as the size argument, which clamps the user-supplied count to at most MAX_INPUT_BUF_SZ bytes. The destination buffer input_buf is declared as char input_buf[MAX_INPUT_BUF_SZ] on the stack, so the copy can never exceed the buffer's capacity. The scanner incorrectly treats the result of min_t() as unvalidated because 'count' is user-controlled, but the min_t() call is itself the validation/clamping operation. No counterexample exists: any value of count, however large, results in a copy of at most MAX_INPUT_BUF_SZ bytes into a buffer of exactly MAX_INPUT_BUF_SZ bytes.

Finding #1 — Category G2 — false positive

CategoryCat G2 — unvalidated size argument to copy_from/to_user
Taint sourcecopy_from_user() line 4858
Taint snippetif (copy_from_user(input_buf, buf, min_t(size_t, count, MAX_INPUT_BUF_SZ)))
Tainted varmin_t(size_t, count, MAX_INPUT_BUF_SZ)
Unvalidated sizecopy_from_user() arg 2 line 4858 — size min_t(size_t, count, MAX_INPUT_BUF_SZ)
Sink snippetif (copy_from_user(input_buf, buf, min_t(size_t, count, MAX_INPUT_BUF_SZ)))
Possibly guardedno
Dismissed: The size argument is min_t(size_t, count, MAX_INPUT_BUF_SZ), which mathematically caps the copy length at MAX_INPUT_BUF_SZ regardless of what the user provides. The destination buffer input_buf is exactly MAX_INPUT_BUF_SZ bytes, so the copy is always in bounds. No counterexample can be constructed where the guard fails to prevent overflow. This is a classic false positive from taint analysis that does not model the semantics of min_t() as a bounds clamp.

copy_user_test_oob() — mm/kasan/kasan_test_c.c FP confidence=high

This is a KASAN test function (kasan_test_c.c). Its entire purpose is to intentionally trigger out-of-bounds accesses to verify that KASAN detects them. The 'size' variable is computed locally as '128 - KASAN_GRANULE_SIZE' (a compile-time constant expression), not read from any user-supplied or server-supplied source. The scanner incorrectly identifies the return value of copy_from_user/copy_to_user as a taint source and propagates it to subsequent uses of 'size', but 'size' is never modified by those return values — it is a locally-defined constant. All flagged uses of 'size + 1' are deliberate OOB accesses wrapped in KUNIT_EXPECT_KASAN_FAIL macros, which expect and require the KASAN failure. This is intentional test code, not a production security bug.

Finding #1 — Category G2 — false positive

CategoryCat G2 — unvalidated size argument to copy_from/to_user
Taint sourcecopy_from_user() line 2181
Taint snippetunused = copy_from_user(kmem, usermem, size + 1));
Tainted varsize + 1
Unvalidated sizecopy_from_user() arg 2 line 2181 — size size + 1
Sink snippetunused = copy_from_user(kmem, usermem, size + 1));
Possibly guardedno
Dismissed: size = 128 - KASAN_GRANULE_SIZE is a kernel-internal compile-time constant, not server/user supplied. The OOB access is intentional and wrapped in KUNIT_EXPECT_KASAN_FAIL to verify KASAN detection. False positive.

Finding #2 — Category G2 — false positive

CategoryCat G2 — unvalidated size argument to copy_from/to_user
Taint sourcecopy_to_user() line 2183
Taint snippetunused = copy_to_user(usermem, kmem, size + 1));
Tainted varsize + 1
Unvalidated sizecopy_to_user() arg 2 line 2183 — size size + 1
Sink snippetunused = copy_to_user(usermem, kmem, size + 1));
Possibly guardedno
Dismissed: Same as finding #1. size is a locally-computed constant. The intentional OOB write to kmem via copy_to_user is wrapped in KUNIT_EXPECT_KASAN_FAIL_READ to verify KASAN detection. False positive.

Finding #3 — Category G2 — false positive

CategoryCat G2 — unvalidated size argument to copy_from/to_user
Taint source__copy_from_user() line 2185
Taint snippetunused = __copy_from_user(kmem, usermem, size + 1));
Tainted varsize + 1
Unvalidated size__copy_from_user() arg 2 line 2185 — size size + 1
Sink snippetunused = __copy_from_user(kmem, usermem, size + 1));
Possibly guardedno
Dismissed: Same as finding #1. Intentional OOB in KASAN test code. False positive.

Finding #4 — Category G2 — false positive

CategoryCat G2 — unvalidated size argument to copy_from/to_user
Taint source__copy_to_user() line 2187
Taint snippetunused = __copy_to_user(usermem, kmem, size + 1));
Tainted varsize + 1
Unvalidated size__copy_to_user() arg 2 line 2187 — size size + 1
Sink snippetunused = __copy_to_user(usermem, kmem, size + 1));
Possibly guardedno
Dismissed: Same as finding #1. Intentional OOB in KASAN test code. False positive.

Finding #5 — Category G2 — false positive

CategoryCat G2 — unvalidated size argument to copy_from/to_user
Taint sourcecopy_to_user() line 2198
Taint snippetKUNIT_EXPECT_EQ(test, copy_to_user(usermem, kmem, size), 0);
Tainted varsize
Unvalidated sizecopy_to_user() arg 2 line 2198 — size size
Sink snippetKUNIT_EXPECT_EQ(test, copy_to_user(usermem, kmem, size), 0);
Possibly guardedno
Dismissed: This use of 'size' (without +1) copies exactly size bytes into a size-byte kmem buffer — this is a valid, correctly-sized copy used to prepare userspace memory for the subsequent strncpy_from_user OOB test. The scanner incorrectly tracks a taint through copy_to_user's return value back to 'size', but 'size' is never assigned from copy_to_user. False positive.

copy_folio_from_user() — mm/memory.c FP confidence=high

PAGE_SIZE is a kernel-internal compile-time constant (or arch-defined macro), not a value read from a user/server-supplied buffer. The taint source listed is copy_from_user() itself on line 7500, but the scanner has misidentified PAGE_SIZE as the tainted value flowing into the size argument of copy_from_user(). PAGE_SIZE is a fixed kernel constant representing the system page size (e.g., 4096 on x86). It is never user-controlled or server-supplied. The destination buffer 'kaddr' is a kernel mapping of exactly one page (via kmap_local_page), so copying PAGE_SIZE bytes into it is precisely correct. The loop iterates nr_pages times, derived from folio_nr_pages() which is a kernel-internal property of the folio, not externally supplied. There is no missing validation here.

Finding #1 — Category G2 — false positive

CategoryCat G2 — unvalidated size argument to copy_from/to_user
Taint sourcecopy_from_user() line 7500
Taint snippetrc = copy_from_user(kaddr, usr_src + i * PAGE_SIZE, PAGE_SIZE);
Tainted varPAGE_SIZE
Unvalidated sizecopy_from_user() arg 2 line 7500 — size PAGE_SIZE
Sink snippetrc = copy_from_user(kaddr, usr_src + i * PAGE_SIZE, PAGE_SIZE);
Possibly guardedno
Dismissed: PAGE_SIZE is a kernel-internal constant (architecture-defined, set at boot or compile time), not a user-supplied or server-supplied value. The scanner incorrectly identified it as tainted because copy_from_user() was listed as a taint source and PAGE_SIZE appears as the size argument to another copy_from_user() call. However, PAGE_SIZE does not derive from any user-provided data — it is a fixed system constant. The destination buffer kaddr is a kmap of one page, exactly PAGE_SIZE bytes, so the copy is always within bounds. No counterexample can be constructed because PAGE_SIZE is not variable at runtime in a user-controlled way. This is a textbook false positive from the static analyzer confusing a kernel constant with tainted data.

get_bitmap() — mm/mempolicy.c FP confidence=high

The tainted size (nlongs * sizeof(unsigned long)) is user-controlled via maxnode, but get_nodes() enforces 'maxnode > PAGE_SIZE*BITS_PER_BYTE => -EINVAL' before calling get_bitmap(). At call site line 1677, bits is further bounded by min_t(..., BITS_PER_LONG) so nlongs=1 and mask=&t (one ulong). At call site line 1690, the while-loop reduces maxnode to <= MAX_NUMNODES before the call, so copy_from_user's size is bounded to BITS_TO_LONGS(MAX_NUMNODES)*sizeof(ulong), which exactly fits nodes_addr(*nodes). No counterexample can pass all guards and still cause OOB.

Finding #1 — Category G2 — false positive

CategoryCat G2 — unvalidated size argument to copy_from/to_user
Taint sourcecopy_from_user() line 1645
Taint snippetret = copy_from_user(mask, nmask,
Tainted varnlongs * sizeof(unsigned long)
Unvalidated sizecopy_from_user() arg 2 line 1645 — size nlongs * sizeof(unsigned long)
Sink snippetret = copy_from_user(mask, nmask,
Possibly guardedno
Dismissed: At call site line 1677: bits=min_t(maxnode,BITS_PER_LONG)<=BITS_PER_LONG, so nlongs=1, mask=&t (one ulong on stack) — safe. At call site line 1690: the while loop runs while maxnode>MAX_NUMNODES and subtracts bits each iteration, so upon exit maxnode<=MAX_NUMNODES; thus nlongs<=BITS_TO_LONGS(MAX_NUMNODES) which is exactly the size of nodemask_t — safe. No counterexample exists that passes both the PAGE_SIZE*BITS_PER_BYTE guard and the while-loop reduction and still overflows the destination buffer. False positive.

do_pages_stat() — mm/migrate.c FP confidence=high

chunk_nr is computed as min(nr_pages, DO_PAGES_STAT_CHUNK_NR) where DO_PAGES_STAT_CHUNK_NR=16. Regardless of the user-supplied nr_pages value, chunk_nr is always ≤ 16, making the copy sizes exactly fit within the stack-allocated chunk_pages[16] and chunk_status[16] arrays. The scanner's taint analysis propagated the user-controlled nature of nr_pages through the min() expression but did not account for the clamping effect of min().

Finding #1 — Category G2 — false positive

CategoryCat G2 — unvalidated size argument to copy_from/to_user
Taint sourcecopy_from_user() line 2526
Taint snippetif (copy_from_user(chunk_pages, pages + chunk_offset,
Tainted varchunk_nr * sizeof(*chunk_pages)
Unvalidated sizecopy_from_user() arg 2 line 2526 — size chunk_nr * sizeof(*chunk_pages)
Sink snippetif (copy_from_user(chunk_pages, pages + chunk_offset,
Possibly guardedno
Dismissed: chunk_nr = min(nr_pages, 16UL) is always ≤ 16. The destination buffer chunk_pages has exactly 16 elements. chunk_nr * sizeof(*chunk_pages) ≤ sizeof(chunk_pages). No counterexample can be constructed: any nr_pages value yields chunk_nr ≤ 16, which never exceeds the buffer. False positive.

Finding #2 — Category G2 — false positive

CategoryCat G2 — unvalidated size argument to copy_from/to_user
Taint sourcecopy_to_user() line 2533
Taint snippetif (copy_to_user(status + chunk_offset, chunk_status,
Tainted varchunk_nr * sizeof(*status)
Unvalidated sizecopy_to_user() arg 2 line 2533 — size chunk_nr * sizeof(*status)
Sink snippetif (copy_to_user(status + chunk_offset, chunk_status,
Possibly guardedno
Dismissed: Same reasoning as finding #1. chunk_nr ≤ 16 and chunk_status has 16 elements, so chunk_nr * sizeof(*status) ≤ sizeof(chunk_status). The copy to userspace (status + chunk_offset) is a write to user memory, not a kernel buffer overflow. No counterexample exists. False positive.

shrinker_debugfs_scan_write() — mm/shrinker_debug.c FP confidence=high

The taint source flagged by the scanner is copy_from_user() itself, which populates 'read_len' — but read_len is NOT derived from user data. It is computed on line 114 as min(size, sizeof(kbuf) - 1), where sizeof(kbuf) is the compile-time size of the 72-byte stack buffer. The min() call strictly clamps read_len to at most sizeof(kbuf)-1 = 71, which is always less than the destination buffer size of 72. No counterexample exists where read_len could exceed the buffer capacity. The scanner is confused because copy_from_user() is both the 'taint source' (the data read) and the 'sink' (the call itself), and it is misidentifying read_len as user-controlled when read_len is actually a kernel-internal clamped value.

Finding #1 — Category G2 — false positive

CategoryCat G2 — unvalidated size argument to copy_from/to_user
Taint sourcecopy_from_user() line 115
Taint snippetif (copy_from_user(kbuf, buf, read_len))
Tainted varread_len
Unvalidated sizecopy_from_user() arg 2 line 115 — size read_len
Sink snippetif (copy_from_user(kbuf, buf, read_len))
Possibly guardedno
Dismissed: read_len = min(size, sizeof(kbuf) - 1) clamps the copy length to at most 71 bytes, which is strictly less than the 72-byte kbuf. No counterexample is possible: any value of user-supplied 'size' results in read_len <= 71 < 72, so copy_from_user() cannot overflow kbuf. The scanner incorrectly treats read_len as tainted because it appears in the copy_from_user call, but the value itself is a kernel-computed minimum, not user-supplied.

mfill_copy_folio_locked() — mm/userfaultfd.c FP confidence=high

The static analyzer has incorrectly flagged PAGE_SIZE as a user-controlled/tainted value. PAGE_SIZE is a kernel compile-time constant (or boot-time constant), not derived from any user-supplied or server-supplied data. The copy_from_user() call copies exactly one page worth of data from a user-space source address into a kernel-allocated folio page, which is always PAGE_SIZE bytes. The destination buffer (kmap_local_folio result) is also PAGE_SIZE bytes. There is no missing bounds check here — copying PAGE_SIZE bytes into a PAGE_SIZE kernel buffer is inherently safe in terms of destination buffer overflow. The taint propagation from copy_from_user() return value to PAGE_SIZE is a spurious analyzer inference; copy_from_user() returns the number of bytes NOT copied, not a size value that feeds back into the size argument.

Finding #1 — Category G2 — false positive

CategoryCat G2 — unvalidated size argument to copy_from/to_user
Taint sourcecopy_from_user() line 452
Taint snippetret = copy_from_user(kaddr, (const void __user *) src_addr,
Tainted varPAGE_SIZE
Unvalidated sizecopy_from_user() arg 2 line 452 — size PAGE_SIZE
Sink snippetret = copy_from_user(kaddr, (const void __user *) src_addr,
Possibly guardedno
Dismissed: PAGE_SIZE is a kernel-internal constant, not user-supplied or server-supplied data. The analyzer appears to have confused the taint source: copy_from_user() returns the number of bytes NOT copied (stored in 'ret'), which is then checked (if ret → return -EFAULT). The size argument to copy_from_user() is PAGE_SIZE, a compile-time/boot-time constant that cannot be influenced by userspace. The destination buffer from kmap_local_folio is always exactly PAGE_SIZE bytes for a single folio page. No counterexample can be constructed where PAGE_SIZE exceeds the destination buffer size, because they are identical by construction. This is a false positive.

mfill_copy_folio_retry() — mm/userfaultfd.c FP confidence=high

The flagged 'tainted variable' is PAGE_SIZE, which is a kernel-internal compile-time constant (typically 4096 bytes on x86). It is not derived from user input, server responses, or any runtime variable. The static analysis tool incorrectly identified copy_from_user() itself as a taint source and then flagged the size argument in the very same call, confusing the function's return value (bytes not copied) with its arguments. PAGE_SIZE is always a fixed, architecture-defined constant and cannot be influenced by user-space or a network peer. The destination buffer kaddr is obtained from kmap_local_folio(folio, 0), which maps exactly one page (PAGE_SIZE bytes). The copy is therefore correctly sized.

Finding #1 — Category G2 — false positive

CategoryCat G2 — unvalidated size argument to copy_from/to_user
Taint sourcecopy_from_user() line 540
Taint snippeterr = copy_from_user(kaddr, (const void __user *) src_addr, PAGE_SIZE);
Tainted varPAGE_SIZE
Unvalidated sizecopy_from_user() arg 2 line 540 — size PAGE_SIZE
Sink snippeterr = copy_from_user(kaddr, (const void __user *) src_addr, PAGE_SIZE);
Possibly guardedno
Dismissed: PAGE_SIZE is a kernel compile-time constant, not a user-supplied or server-supplied value. The scanner appears to have treated the return value of copy_from_user() (bytes not copied) as tainting the size argument, which is a false-positive artifact of the analysis. kmap_local_folio maps exactly PAGE_SIZE bytes, and copy_from_user is called with PAGE_SIZE as the size, making the operation correctly bounded. No counterexample exists where PAGE_SIZE could be manipulated to cause OOB access.

memdup_user() — mm/util.c FP confidence=high

memdup_user() is a standard kernel utility that allocates exactly 'len' bytes and then copies exactly 'len' bytes from userspace. Because the allocation size and copy size are identical, there is no buffer overflow risk within this function. The scanner incorrectly attributes the taint source to copy_from_user()'s return value rather than recognizing 'len' is a caller-supplied parameter. Validation of 'len' range (e.g., against a maximum) is the caller's responsibility, not this utility's. The function correctly handles allocation failure and copy failure.

Finding #1 — Category G2 — false positive

CategoryCat G2 — unvalidated size argument to copy_from/to_user
Taint sourcecopy_from_user() line 225
Taint snippetif (copy_from_user(p, src, len)) {
Tainted varlen
Unvalidated sizecopy_from_user() arg 2 line 225 — size len
Sink snippetif (copy_from_user(p, src, len)) {
Possibly guardedno
Dismissed: The scanner misidentifies the taint source: 'len' is a function parameter, not something read by copy_from_user(). More importantly, the destination buffer 'p' is allocated with exactly 'len' bytes (via kmem_buckets_alloc_track_caller), so copy_from_user() with size 'len' cannot overflow 'p'. Allocation failure (returning NULL) is handled before the copy. No counterexample can be constructed where len causes OOB within this function because allocation and copy sizes are always equal. Any range validation of len is a caller-level concern. This is a false positive.

memdup_user_nul() — mm/util.c FP confidence=high

This is the generic memdup_user_nul() utility in lib/util.c (or similar). The function allocates len+1 bytes and copies len bytes from userspace. The allocation is sized to exactly len+1, so the copy of len bytes fits perfectly — there is no OOB write. The scanner confused itself by flagging 'len' as a tainted size argument, but the destination buffer p is allocated as kmem_buckets_alloc_track_caller(user_buckets, len+1, ...), which is always >= len+1 bytes. The copy_from_user call copies exactly len bytes into a buffer of len+1 bytes, which is safe by construction. The callers of memdup_user_nul() are responsible for validating len before calling this function; within this function, the allocation and copy are consistently sized.

Finding #1 — Category G2 — false positive

CategoryCat G2 — unvalidated size argument to copy_from/to_user
Taint sourcecopy_from_user() line 307
Taint snippetif (copy_from_user(p, src, len)) {
Tainted varlen
Unvalidated sizecopy_from_user() arg 2 line 307 — size len
Sink snippetif (copy_from_user(p, src, len)) {
Possibly guardedno
Dismissed: The taint source is copy_from_user() itself, which the scanner is treating as introducing a tainted 'len'. However, 'len' is a parameter passed to memdup_user_nul() and the function's only use of 'len' is: (1) allocate len+1 bytes, and (2) copy len bytes into that allocation. The destination buffer is always exactly large enough for the copy — p has len+1 bytes and copy_from_user copies len bytes. No counterexample is possible: any value of len results in an allocation of at least len+1 bytes, making the copy always in-bounds. This is a classic false positive where the static analyzer confuses the size parameter with being unvalidated against the destination, but the destination is sized from the same parameter. Caller responsibility for upper-bounding len is outside the scope of this function.

vmemdup_user() — mm/util.c FP confidence=high

vmemdup_user() is a generic utility that allocates exactly 'len' bytes and copies exactly 'len' bytes from userspace. Since the allocation size and copy size are identical, there is no buffer overflow risk within this function. The scanner flagged 'len' as user-controlled, but the destination buffer is always sized to accommodate the copy. Validation of 'len' against application-specific upper bounds is the responsibility of callers, not this utility.

Finding #1 — Category G2 — false positive

CategoryCat G2 — unvalidated size argument to copy_from/to_user
Taint sourcecopy_from_user() line 251
Taint snippetif (copy_from_user(p, src, len)) {
Tainted varlen
Unvalidated sizecopy_from_user() arg 2 line 251 — size len
Sink snippetif (copy_from_user(p, src, len)) {
Possibly guardedno
Dismissed: The allocation `kmem_buckets_valloc(user_buckets, len, GFP_USER)` uses the same `len` as the `copy_from_user(p, src, len)` call. The destination buffer is exactly `len` bytes, so the copy cannot overflow it. The NULL check after allocation handles the case where `len` is too large for the allocator. No counterexample exists where the copy overflows the allocated buffer, because they share the same size expression. This is a false positive: the scanner sees `len` is user-tainted but misses that the allocation is also sized by `len`.

lru_gen_seq_write() — mm/vmscan.c FP confidence=high

This is a standard sysfs/procfs-style write handler. The 'len' parameter is the kernel's own 'size_t len' argument to the file_operations->write callback, which comes from the VFS layer after the user's write(2) syscall. It represents how many bytes the user wants to write — it is NOT a value read from user memory. The allocation is 'kvmalloc(len + 1, GFP_KERNEL)' which allocates exactly len+1 bytes, and then 'copy_from_user(buf, src, len)' copies exactly len bytes into that buffer. The destination buffer is always large enough for the copy. The scanner is confused because 'len' is a parameter that relates to user-provided data, but it is a kernel ABI value (the write syscall's count argument) passed by the VFS, not something read from user memory with get_user or copy_from_user. There is no OOB risk here.

Finding #1 — Category G2 — false positive

CategoryCat G2 — unvalidated size argument to copy_from/to_user
Taint sourcecopy_from_user() line 5679
Taint snippetif (copy_from_user(buf, src, len)) {
Tainted varlen
Unvalidated sizecopy_from_user() arg 2 line 5679 — size len
Sink snippetif (copy_from_user(buf, src, len)) {
Possibly guardedno
Dismissed: The 'len' parameter is the VFS-supplied write count from the write(2) syscall, not a value read from user memory. The buffer is allocated as kvmalloc(len + 1) and copy_from_user copies exactly len bytes, so the destination is always sufficient. No counterexample exists: any value of len results in a buffer of len+1 bytes, so copy_from_user(buf, src, len) always stays within bounds. This is a textbook false positive for this category of static analysis finding.