From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751527AbdJEShP (ORCPT ); Thu, 5 Oct 2017 14:37:15 -0400 Received: from mail-lf0-f68.google.com ([209.85.215.68]:38293 "EHLO mail-lf0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751319AbdJEShN (ORCPT ); Thu, 5 Oct 2017 14:37:13 -0400 X-Google-Smtp-Source: AOwi7QAVWNSHnZj2REfaOFSz7yNOZ5qn3hEEda8JFtcRiK94Ap+rxuO0R990UZV1dZ6KpAh/ydFplw== From: Sergey Klyaus To: sergey.m.klyaus@gmail.com Cc: Alexander Viro , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH] vfs: fix statfs64() returning impossible EOVERFLOW for 64-bit f_files Date: Thu, 5 Oct 2017 21:36:36 +0300 Message-Id: <20171005183636.20732-1-sergey.m.klyaus@gmail.com> X-Mailer: git-send-email 2.14.1 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org compat_statfs64 structure has some 32-bit and some 64-bit fields, so 64d2ab32e "vfs: fix put_compat_statfs64() does not handle errors" fixed 32-bit overflow checks not being performed, but accidentally enabled checks for f_files and f_ffree that are 64-bit and cannot have overflow. Now checks for both groups of fields are enabled by different conditions. This broke my Steam runtime and can be reproduced with this test case: # mount -t tmpfs -o nr_inodes=4294967297 tmpfs /mnt $ cat statfs.c int main() { struct statvfs sv; statvfs("/mnt", &sv); printf("%d %llu %llu\n", errno, (unsigned long long) sv.f_files, (unsigned long long) sv.f_ffree); return 0; } $ gcc -g -m32 -D_FILE_OFFSET_BITS=64 statfs.c $ ./a.out 75 134513445 0 | \- some junk on stack EOVERFLOW Signed-off-by: Sergey Klyaus --- fs/statfs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/statfs.c b/fs/statfs.c index fab9b6a3c116..073bb2d1871e 100644 --- a/fs/statfs.c +++ b/fs/statfs.c @@ -307,6 +307,8 @@ static int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstat if ((kbuf->f_type | kbuf->f_bsize | kbuf->f_namelen | kbuf->f_frsize | kbuf->f_flags) & 0xffffffff00000000ULL) return -EOVERFLOW; + } + if (sizeof(ubuf->f_blocks) == 4) { /* f_files and f_ffree may be -1; it's okay * to stuff that into 32 bits */ if (kbuf->f_files != 0xffffffffffffffffULL -- 2.14.1