All of lore.kernel.org
 help / color / mirror / Atom feed
From: Li Wang <liwang@redhat.com>
To: Andreas Dilger <adilger@dilger.ca>
Cc: viro@zeniv.linux.org.uk, linux-fsdevel@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH] vfs: fix statfs64() does not handle errors
Date: Mon, 14 Nov 2016 18:59:42 +0800	[thread overview]
Message-ID: <20161114105942.GA772@gmail.com> (raw)
In-Reply-To: <6D8E6AD1-CE9D-4578-A508-8FCD4C97C6BE@dilger.ca>

On Mon, Nov 07, 2016 at 11:03:11AM -0700, Andreas Dilger wrote:
> On Nov 7, 2016, at 3:21 AM, Li Wang <liwang@redhat.com> wrote:
> > 
> > statfs64() does NOT return -1 and setting errno to EOVERFLOW when some
> > variables(like: f_bsize) overflowed in the returned struct.
> > 
> > reproducer:
> > step1. mount hugetlbfs with two different pagesize on ppc64 arch.
> > 
> > $ hugeadm --pool-pages-max 16M:0
> > $ hugeadm --create-mount
> > $ mount | grep -i hugetlbfs
> > none on /var/lib/hugetlbfs/pagesize-16MB type hugetlbfs (rw,relatime,seclabel,pagesize=16777216)
> > none on /var/lib/hugetlbfs/pagesize-16GB type hugetlbfs (rw,relatime,seclabel,pagesize=17179869184)
> > 
> > step2. compile & run this C program.
> > 
> > $ cat statfs64_test.c
> > 
> > #define _LARGEFILE64_SOURCE
> > #include <stdio.h>
> > #include <sys/statfs.h>
> > 
> > int main()
> > {
> > 	struct statfs64 sb;
> > 	int err;
> > 
> > 	err = statfs64("/var/lib/hugetlbfs/pagesize-16GB", &sb);
> > 	if (err)
> > 		return -1;
> > 
> > 	printf("sizeof f_bsize = %d, f_bsize=%ld\n", sizeof(sb.f_bsize), sb.f_bsize);
> > 
> > 	return 0;
> > }
> > 
> > $ gcc -m32 statfs64_test.c
> > $ ./a.out
> > sizeof f_bsize = 4, f_bsize=0
> > 
> > Signed-off-by: Li Wang <liwang@redhat.com>
> > ---
> > 
> > Notes:
> >    This is my first patch to kernel fs part, I'm not sure if
> >    this one useful, but just want someone have a look.
> > 
> >    thanks~
> > 
> > fs/statfs.c | 17 +++++++++++++++++
> > 1 file changed, 17 insertions(+)
> > 
> > diff --git a/fs/statfs.c b/fs/statfs.c
> > index 083dc0a..849dde95 100644
> > --- a/fs/statfs.c
> > +++ b/fs/statfs.c
> > @@ -151,6 +151,23 @@ static int do_statfs64(struct kstatfs *st, struct statfs64 __user *p)
> > 	if (sizeof(buf) == sizeof(*st))
> > 		memcpy(&buf, st, sizeof(*st));
> > 	else {
> > +		if (sizeof buf.f_bsize == 4) {
> 
> Linux CodingStyle says this should be used like sizeof(buf.f_bsize).

agree.

> 
> > +			if ((st->f_blocks | st->f_bfree | st->f_bavail |
> > +			     st->f_bsize | st->f_frsize) &
> > +			    0xffffffff00000000ULL)
> > +				return -EOVERFLOW;
> 
> I'm not sure I agree with this check.  Sure, if sizeof(buf.f_bsize) == 4
> then the large st->f_bsize will overflow this field, and that is valid.

After thinking over, I feel that my fix in this patch is not right.

The reproducer.c running on ppc64 arch was build in 32bit, but it does
not call SYS_statfs64 in kernel. It calls compat_sys_statfs64 indeed.

# cat reproducer.c

#define _LARGEFILE64_SOURCE
#include <stdio.h>
#include <sys/statfs.h>
#include <sys/syscall.h>

int main()
{
	struct statfs64 sb;
	int err;

	err = syscall(SYS_statfs64, "/var/lib/hugetlbfs/pagesize-16GB", sizeof(sb), &sb);
	if (err)
		return -1;

	printf("sizeof f_bsize = %d, f_bsize=%ld\n", sizeof(sb.f_bsize), sb.f_bsize);
	return 0;
}

# gcc reproducer.c -m32

# stap -e 'probe kernel.function("compat_sys_statfs64") {printf ("%s",
$$parms);}' -vvv &

# ./a.out 
sizeof f_bsize = 4, f_bsize=0
# pathname=0x100006c4 sz=0x58 buf=0xff8a20b0


Guess the fix should be like:

diff --git a/fs/compat.c b/fs/compat.c
index bd064a2..3d923fd 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -253,7 +253,7 @@ static int put_compat_statfs(struct compat_statfs __user *ubuf, struct kstatfs *
 
 static int put_compat_statfs64(struct compat_statfs64 __user *ubuf,
 struct kstatfs *kbuf)
 {
-       if (sizeof ubuf->f_blocks == 4) {
+       if (sizeof ubuf->f_bsize == 4) {
                if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail |
                     kbuf->f_bsize | kbuf->f_frsize) & 0xffffffff00000000ULL)
                        return -EOVERFLOW;


I will test it and send a new patch. 

Regards,
Li Wang

> 
> However, that doesn't mean that large values for f_blocks, f_bfree, f_bavail
> should return an error.  I assume you are concerned that the product of the
> large f_bsize and one of those values would overflow a 64-bit bytes value,
> but that is for userspace to worry about, since the values in the individual
> fields themselves are OK.
> 
> We're already over 100PiB Lustre filesystems (2^57 bytes) today, and I
> don't want statfs() failing prematurely because userspace feels the need
> to multiply out the blocks and blocksize into bytes, instead of shifting
> the values to KB (which would allow filesystems up to 2^74-1024 bytes to
> be handled correctly in userspace).
> 
> > +			/*
> > +			 * f_files and f_ffree may be -1; it's okay to stuff
> > +			 * that into 32 bits
> > +			 */
> > +			if (st->f_files != -1 &&
> > +			    (st->f_files & 0xffffffff00000000ULL))
> > +				return -EOVERFLOW;
> 
> > +			if (st->f_ffree != -1 &&
> > +			    (st->f_ffree & 0xffffffff00000000ULL))
> > +				return -EOVERFLOW;
> 
> Why does sizeof(f_bsize) have anything to do with the number of free files?
> These two checks are just plain wrong, since f_files and f_ffree are 64-bit
> fields in struct statfs64.

right.

> 
> Cheers, Andreas
> 
> > +		}
> > +
> > 		buf.f_type = st->f_type;
> > 		buf.f_bsize = st->f_bsize;
> > 		buf.f_blocks = st->f_blocks;
> > --
> > 1.8.3.1
> > 
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> 
> Cheers, Andreas
> 
> 
> 
> 
> 



      reply	other threads:[~2016-11-14 11:06 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-11-07 10:21 [PATCH] vfs: fix statfs64() does not handle errors Li Wang
2016-11-07 18:03 ` Andreas Dilger
2016-11-14 10:59   ` Li Wang [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20161114105942.GA772@gmail.com \
    --to=liwang@redhat.com \
    --cc=adilger@dilger.ca \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=viro@zeniv.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.