From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-lf1-f50.google.com (mail-lf1-f50.google.com [209.85.167.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 052BC2FDC5E for ; Sat, 25 Jul 2026 13:22:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.50 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784985749; cv=none; b=BhBRQ/diPas6zGxoQzS91P2XawtGScbcsCA4xwvtH00VsuaeHGEJbrdRz8omzAQTfIw9RiZgJUZbQOJ9wyKN2RtIkrs3MlG5ZYTuXqgXtqUtOz+753Q2kCwGxBqQeBq0X+5O7AZqy8aIpt1Uku//kW5RWGLop5MpNfZdndEwEFA= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784985749; c=relaxed/simple; bh=1se/1NLTTRzWShF//Sg0X+23fU6Q7G8sfYlrbWjO5Y4=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=setWK6ibv+vIY0T1b5NmzfXZcMrb/29lLgE1QiwOdNngltN2qc4OjtceFAMmzZTyZiYItSBC4KTogJORMxkioJjepyPMDWaupUFu+m7KtpVKnJjXZRyfnn8OhQ727yDfWn6EIWS38Z75qnoEPhe9ABi/nBC7g1blGNmKO7hbpzo= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=F6EahryL; arc=none smtp.client-ip=209.85.167.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="F6EahryL" Received: by mail-lf1-f50.google.com with SMTP id 2adb3069b0e04-5b0148201fbso1039970e87.3 for ; Sat, 25 Jul 2026 06:22:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1784985746; x=1785590546; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to:content-type; bh=Kx85czVOhBPoFkPfr8PjazcziqRbOedPhUw+46jDybM=; b=F6EahryLXB9ucbRjNG3YmMshN+URKMN1C9jADB+cYwqam40x6QSi3ljqSLIcHbMYWm H3iuycK6U/AXmfyH906RIAvNZXv3/YtUlTVvEnFv9fVf0XqUEO9zNgynhvw5c9YQ4ABw M7iaOONiqTgjBAMBkjGD0B5FfVEskj5xmjhfEj7Kcn037AESx4Yf+LiEGpQ6N1+INc3/ V2y9o9FeLKFFTHJ66mjzMXbnqdXVn6rVI00B4kwaY3vpiOHS2FqBY7Qk3Yw7pWQAEQam WIokwWS3xRXRRePiuOmT4fFOOtpy6NXbgtj9RNNTvb3Mi0oX14EiJWIF5l2KgWM4t+3X FnPw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1784985746; x=1785590546; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=Kx85czVOhBPoFkPfr8PjazcziqRbOedPhUw+46jDybM=; b=FbEKYFVEsDY7622CfNP7OrpY1/ye7o7ZPQspFa3NQpuOPurmdy8JN97aiyWQMeiDBx llcRurg8j/lbrQdvKopZg4VCEx36qe2tXgxdfDNqz37bHIyWpSOTezEt3UFtgvfOjFwZ lUYoLBFylTCAAhacxC4G+LziS18gsQtfEHUjVn8aq7qx+VTINiknW87UpR+QyCfRTtpN 0zsyMokSjBVt3StOgy32VJnwGTsO3J6aCShKS4SxeFsD0IZgrhIbklp7/mZ4K3iO/Eac Lu8OBFibFl8XqmMKnl64mNZnpq1OFcooFNAno6cKfoL8LLIvPVggAZGtxSoOyoeVt8WS mwRA== X-Forwarded-Encrypted: i=1; AHgh+RqN3xwLFPFcAuGrkwyVaigDbYGFXhwtRp4orsyS29y7PvVUT7q17tcHbH7nNl6IFiUCdBiyI7KOOL6RX64=@vger.kernel.org X-Gm-Message-State: AOJu0YwKhbX7RD0Tv0fn2QovfGrnoWmNiIgMdX87SW5RDR51cxIJ8bVi zTSYhQM60W/NOOBNkCmjb+350ZFcEXUpembesHLIvco0p90LbaNKlQwN X-Gm-Gg: AR+sD1173Vso3a4xed81AvlXJxWmX7KxCpFW2qsZVV/uyb0amuZRp6lJFU703l87vOj jAvGoRIq8xv8j1vZ7FhONCBjLPiWqDBvQ5kqmIwDafB+gib5Js3Wqt5Lli1YGsplEjba0iWsvtf iNpFR03tJ47hogW4oy2ntmMCsSxM8Hrz3HIKs/Ox8jh+LH+n2HLfpqveaeKPWZGfYi2FbeuBE81 la3yeoSDeVc4plrOPHYKKwYN60kiciOJ9YnevtQXs7qXDGNKjPZG3YiT1K5+7NZn3ck5z4CfWw7 0146vgy3HRpfnQMhnjpHWNTuTQVZfouow4LBdE/uRKHu4nvBvwbb7gORqbzMD6V8F9tETz/1aZ8 VsIQ4cR4iF1iUAiLgCqSpSmlPaDXmkI+mMMgR81kfA2F/tYffwUknYdIQuudBtEIlJfcu4yMABo 9zbhdRafW+ILaaEuV+hgtxXZuPjqfthAdBxQGjGfSQxQu0pQppp1QCaq0JRzqKZeUo7o4Oe3E= X-Received: by 2002:a05:6512:12c7:b0:5ae:bd65:9e04 with SMTP id 2adb3069b0e04-5b2c1af528fmr342408e87.8.1784985745841; Sat, 25 Jul 2026 06:22:25 -0700 (PDT) Received: from localhost.localdomain (46-138-176-102.dynamic.spd-mgts.ru. [46.138.176.102]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-5b2be1d8509sm417670e87.38.2026.07.25.06.22.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 25 Jul 2026 06:22:25 -0700 (PDT) From: Artem Lytkin To: linux-mm@kvack.org Cc: akpm@linux-foundation.org, urezki@gmail.com, shivamkalra98@zohomail.in, linux-kernel@vger.kernel.org Subject: [PATCH 1/2] mm/vmalloc: fix 32-bit truncation of the area size in vread_iter() Date: Sat, 25 Jul 2026 16:22:00 +0300 Message-ID: <20260725132201.88279-1-iprintercanon@gmail.com> X-Mailer: git-send-email 2.43.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Commit 0bca23804632 ("mm/vmalloc: use physical page count in vread_iter() for VM_ALLOC areas") replaced get_vm_area_size(vm), which returns a size_t, with vm->nr_pages << PAGE_SHIFT. struct vm_struct::nr_pages is an unsigned int. The shift operator does not perform the usual arithmetic conversions: the integer promotions are applied to each operand and the type of the result is that of the promoted left operand. The expression is therefore evaluated in 32-bit arithmetic no matter how PAGE_SHIFT is typed, and no matter that the result is assigned to a size_t. Once an area reaches 4 GiB the byte count wraps, at 1 << 20 pages with 4 KiB pages, 1 << 18 with 16 KiB and 1 << 16 with 64 KiB. nr_pages counts base pages even for huge vmalloc mappings, since __vmalloc_area_node() requires area->nr_pages == nr_small_pages, so a huge page_order does not raise the threshold. The only limit on the size of a single area is the totalram_pages() check in __vmalloc_node_range_noprof(), so any machine with more than 4 GiB of memory can create an affected area. One example is the zram metadata table, which is a single vzalloc() of disksize / 256 with CONFIG_LOCKDEP=n: "echo 1T > /sys/block/zram0/disksize" allocates exactly 4 GiB and needs no 1 TiB of anything. Sufficiently large BPF array or prealloc-hash maps do it too, as does "modprobe test_vmalloc run_test_mask=1 nr_pages=1048576". Two paths that might be expected to reach it cannot: alloc_large_system_hash() caps a table at a sixteenth of memory, and the KVM dirty bitmap is bounded by KVM_MEM_MAX_NR_PAGES to 512 MiB. The effect is confined to /proc/kcore, the only caller. For an area whose size is an exact multiple of 4 GiB the computed size becomes 0, the if (addr >= vaddr + size) goto next_va; test succeeds and the whole area is skipped; for other sizes only the first nr_pages mod 2^20 pages are read and the rest is skipped. Either way the bytes are zero-filled at the finished_zero label, which returns the full requested length, so read_kcore_iter() sees a successful read and userspace gets neither an error nor a short read. Live inspection with drgn, crash or gdb silently observes zeros where the area is populated, and cannot distinguish that from genuinely zeroed memory. Before the offending commit the size came from vm->size in 64-bit arithmetic, so this is a v7.2 regression. The truncated value is always less than or equal to the true size, so vread_iter() can only under-read; there is no out-of-bounds access. Both the affected reader and every producer above are privileged: opening /proc/kcore requires CAP_SYS_RAWIO and is refused under lockdown. This is a correctness and debuggability problem, not a security one. Fix it by widening the shift, which also makes the expression consistent with the four (unsigned long)nr_pages << PAGE_SHIFT expressions in vrealloc_node_align_noprof(). On 32-bit a widening cast cannot help, size_t being 32 bits there as well, but a 4 GiB vmalloc area is not reachable on 32-bit either. On 64-bit the cast removes the truncation entirely, which is why replacing get_vm_area_size() introduced a regression rather than inheriting a pre-existing wart. Fixes: 0bca23804632 ("mm/vmalloc: use physical page count in vread_iter() for VM_ALLOC areas") Assisted-by: Claude:claude-fable-5 Signed-off-by: Artem Lytkin --- mm/vmalloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 1afca3568b9b6..44647e189f7d6 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -4722,7 +4722,7 @@ long vread_iter(struct iov_iter *iter, const char *addr, size_t count) * mapping types (vmap, ioremap) don't set nr_pages. */ size = (vm->flags & VM_ALLOC && vm->nr_pages) ? - (vm->nr_pages << PAGE_SHIFT) : + ((unsigned long)vm->nr_pages << PAGE_SHIFT) : get_vm_area_size(vm); else size = va_size(va); base-commit: 248951ddc14de84de3910f9b13f51491a8cd91df -- 2.43.0