Re: numerous statfs bugs

2016-04-25 Thread Martin Natano
On Sun, Apr 24, 2016 at 01:48:04PM +0200, Stefan Kempf wrote:
> 
> Diff reads good to me. Any reason why you changed setting f_mntfromname
> from "fusefs" to "fuse"?

No, it's a typo; updated diff below. Thanks!

natano



Index: isofs/cd9660/cd9660_vfsops.c
===
RCS file: /cvs/src/sys/isofs/cd9660/cd9660_vfsops.c,v
retrieving revision 1.77
diff -u -p -r1.77 cd9660_vfsops.c
--- isofs/cd9660/cd9660_vfsops.c27 Mar 2016 11:39:37 -  1.77
+++ isofs/cd9660/cd9660_vfsops.c19 Apr 2016 18:52:52 -
@@ -383,6 +383,7 @@ iso_mountfs(devvp, mp, p, argp)
mp->mnt_data = (qaddr_t)isomp;
mp->mnt_stat.f_fsid.val[0] = (long)dev;
mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
+   mp->mnt_stat.f_namemax = NAME_MAX;
mp->mnt_flag |= MNT_LOCAL;
isomp->im_mountp = mp;
isomp->im_dev = dev;
@@ -650,13 +651,9 @@ cd9660_statfs(mp, sbp, p)
sbp->f_bavail = 0; /* blocks free for non superuser */
sbp->f_files =  0; /* total files */
sbp->f_ffree = 0; /* free file nodes */
-   if (sbp != >mnt_stat) {
-   bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
-   bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname,
-   MNAMELEN);
-   bcopy(>mnt_stat.mount_info.iso_args,
-   >mount_info.iso_args, sizeof(struct iso_args));
-   }
+   sbp->f_favail = 0; /* file nodes free for non superuser */
+   copy_statfs_info(sbp, mp);
+
return (0);
 }
 
Index: isofs/udf/udf_vfsops.c
===
RCS file: /cvs/src/sys/isofs/udf/udf_vfsops.c,v
retrieving revision 1.49
diff -u -p -r1.49 udf_vfsops.c
--- isofs/udf/udf_vfsops.c  27 Mar 2016 11:39:37 -  1.49
+++ isofs/udf/udf_vfsops.c  19 Apr 2016 18:52:52 -
@@ -264,6 +264,7 @@ udf_mountfs(struct vnode *devvp, struct 
mp->mnt_data = (qaddr_t) ump;
mp->mnt_stat.f_fsid.val[0] = devvp->v_rdev;
mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
+   mp->mnt_stat.f_namemax = NAME_MAX;
mp->mnt_flag |= MNT_LOCAL;
 
ump->um_mountp = mp;
@@ -542,6 +543,8 @@ udf_statfs(struct mount *mp, struct stat
sbp->f_bavail = 0;
sbp->f_files = 0;
sbp->f_ffree = 0;
+   sbp->f_favail = 0;
+   copy_statfs_info(sbp, mp);
 
return (0);
 }
Index: kern/vfs_subr.c
===
RCS file: /cvs/src/sys/kern/vfs_subr.c,v
retrieving revision 1.244
diff -u -p -r1.244 vfs_subr.c
--- kern/vfs_subr.c 7 Apr 2016 09:58:11 -   1.244
+++ kern/vfs_subr.c 19 Apr 2016 18:52:52 -
@@ -2276,6 +2276,6 @@ copy_statfs_info(struct statfs *sbp, con
memcpy(sbp->f_mntonname, mp->mnt_stat.f_mntonname, MNAMELEN);
memcpy(sbp->f_mntfromname, mp->mnt_stat.f_mntfromname, MNAMELEN);
memcpy(sbp->f_mntfromspec, mp->mnt_stat.f_mntfromspec, MNAMELEN);
-   memcpy(>mount_info.ufs_args, >mnt_stat.mount_info.ufs_args,
-   sizeof(struct ufs_args));
+   memcpy(>mount_info, >mnt_stat.mount_info,
+   sizeof(union mount_info));
 }
Index: miscfs/fuse/fuse_vfsops.c
===
RCS file: /cvs/src/sys/miscfs/fuse/fuse_vfsops.c,v
retrieving revision 1.20
diff -u -p -r1.20 fuse_vfsops.c
--- miscfs/fuse/fuse_vfsops.c   27 Mar 2016 11:39:37 -  1.20
+++ miscfs/fuse/fuse_vfsops.c   19 Apr 2016 18:52:52 -
@@ -111,7 +111,9 @@ fusefs_mount(struct mount *mp, const cha
bzero(mp->mnt_stat.f_mntonname, MNAMELEN);
strlcpy(mp->mnt_stat.f_mntonname, path, MNAMELEN);
bzero(mp->mnt_stat.f_mntfromname, MNAMELEN);
-   bcopy("fusefs", mp->mnt_stat.f_mntfromname, sizeof("fusefs"));
+   strlcpy(mp->mnt_stat.f_mntfromname, "fusefs", MNAMELEN);
+   bzero(mp->mnt_stat.f_mntfromspec, MNAMELEN);
+   strlcpy(mp->mnt_stat.f_mntfromspec, "fusefs", MNAMELEN);
 
fuse_device_set_fmp(fmp, 1);
fbuf = fb_setup(0, 0, FBT_INIT, p);
@@ -204,6 +206,8 @@ fusefs_statfs(struct mount *mp, struct s
 
fmp = VFSTOFUSEFS(mp);
 
+   copy_statfs_info(sbp, mp);
+
if (fmp->sess_init) {
fbuf = fb_setup(0, FUSE_ROOT_ID, FBT_STATFS, p);
 
@@ -219,7 +223,9 @@ fusefs_statfs(struct mount *mp, struct s
sbp->f_blocks = fbuf->fb_stat.f_blocks;
sbp->f_files = fbuf->fb_stat.f_files;
sbp->f_ffree = fbuf->fb_stat.f_ffree;
+   sbp->f_favail = fbuf->fb_stat.f_favail;
sbp->f_bsize = fbuf->fb_stat.f_frsize;
+   sbp->f_iosize = fbuf->fb_stat.f_bsize;
sbp->f_namemax = fbuf->fb_stat.f_namemax;
fb_delete(fbuf);
} else {
@@ -227,8 +233,10 @@ fusefs_statfs(struct mount *mp, struct s
sbp->f_bfree = 0;

Re: numerous statfs bugs

2016-04-24 Thread Stefan Kempf
Martin Natano wrote:
> There seem to be a number of issues with statfs related code in the
> kernel. The first issue is inside of the copy_statfs_info() function
> which is designed to be used by the filesystem's .vfs_statfs
> implementations to copy data from mp->mnt_stat to the target stat
> buffer. copy_statfs_info() always copies the ufs_args from the
> mount_info union, although the function is also used by non-ufs
> filesystems. Copying the whole union instead of just one member should
> do the trick for the general case.
> 
> statfs(2) returns incomplete information for most filesystems: cd9660,
> udf, msdosfs and nfsv2 don't set f_namemax. ntfs and ext2fs don't set
> f_namemeax and f_favail. fusefs doesn't set f_mntfromspec, f_favail and
> f_iosize.
> 
> In sys_statfs(), the mount point specific >mnt_stat structure is
> passed as the stat buffer to VFS_STATFS. When looking at the case where
> (sb != >mnt-stat), the situation is even worse. cd9660, udf, fusefs,
> msdosfs, ntfs and ext2fs don't use copy_statfs_info(), so there is a lot
> of unset members in the stat buffer (f_fsid, f_owner, f_flags,
> f_syncwrites, f_asyncwrites, f_syncreads, f_asyncreads, f_mntonname,
> f_mntfromname and f_mntfromspec).
> 
> nfs copies MNAMELEN bytes from a smaller buffer into f_mntonname, so
> there is garbage after the null byte.
> 
> Diff below fixes all those issues. Ok?

Diff reads good to me. Any reason why you changed setting f_mntfromname
from "fusefs" to "fuse"?
 
> natano
> 
> 
> Index: isofs/cd9660/cd9660_vfsops.c
> ===
> RCS file: /cvs/src/sys/isofs/cd9660/cd9660_vfsops.c,v
> retrieving revision 1.77
> diff -u -p -r1.77 cd9660_vfsops.c
> --- isofs/cd9660/cd9660_vfsops.c  27 Mar 2016 11:39:37 -  1.77
> +++ isofs/cd9660/cd9660_vfsops.c  19 Apr 2016 18:52:52 -
> @@ -383,6 +383,7 @@ iso_mountfs(devvp, mp, p, argp)
>   mp->mnt_data = (qaddr_t)isomp;
>   mp->mnt_stat.f_fsid.val[0] = (long)dev;
>   mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
> + mp->mnt_stat.f_namemax = NAME_MAX;
>   mp->mnt_flag |= MNT_LOCAL;
>   isomp->im_mountp = mp;
>   isomp->im_dev = dev;
> @@ -650,13 +651,9 @@ cd9660_statfs(mp, sbp, p)
>   sbp->f_bavail = 0; /* blocks free for non superuser */
>   sbp->f_files =  0; /* total files */
>   sbp->f_ffree = 0; /* free file nodes */
> - if (sbp != >mnt_stat) {
> - bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
> - bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname,
> - MNAMELEN);
> - bcopy(>mnt_stat.mount_info.iso_args,
> - >mount_info.iso_args, sizeof(struct iso_args));
> - }
> + sbp->f_favail = 0; /* file nodes free for non superuser */
> + copy_statfs_info(sbp, mp);
> +
>   return (0);
>  }
>  
> Index: isofs/udf/udf_vfsops.c
> ===
> RCS file: /cvs/src/sys/isofs/udf/udf_vfsops.c,v
> retrieving revision 1.49
> diff -u -p -r1.49 udf_vfsops.c
> --- isofs/udf/udf_vfsops.c27 Mar 2016 11:39:37 -  1.49
> +++ isofs/udf/udf_vfsops.c19 Apr 2016 18:52:52 -
> @@ -264,6 +264,7 @@ udf_mountfs(struct vnode *devvp, struct 
>   mp->mnt_data = (qaddr_t) ump;
>   mp->mnt_stat.f_fsid.val[0] = devvp->v_rdev;
>   mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
> + mp->mnt_stat.f_namemax = NAME_MAX;
>   mp->mnt_flag |= MNT_LOCAL;
>  
>   ump->um_mountp = mp;
> @@ -542,6 +543,8 @@ udf_statfs(struct mount *mp, struct stat
>   sbp->f_bavail = 0;
>   sbp->f_files = 0;
>   sbp->f_ffree = 0;
> + sbp->f_favail = 0;
> + copy_statfs_info(sbp, mp);
>  
>   return (0);
>  }
> Index: kern/vfs_subr.c
> ===
> RCS file: /cvs/src/sys/kern/vfs_subr.c,v
> retrieving revision 1.244
> diff -u -p -r1.244 vfs_subr.c
> --- kern/vfs_subr.c   7 Apr 2016 09:58:11 -   1.244
> +++ kern/vfs_subr.c   19 Apr 2016 18:52:52 -
> @@ -2276,6 +2276,6 @@ copy_statfs_info(struct statfs *sbp, con
>   memcpy(sbp->f_mntonname, mp->mnt_stat.f_mntonname, MNAMELEN);
>   memcpy(sbp->f_mntfromname, mp->mnt_stat.f_mntfromname, MNAMELEN);
>   memcpy(sbp->f_mntfromspec, mp->mnt_stat.f_mntfromspec, MNAMELEN);
> - memcpy(>mount_info.ufs_args, >mnt_stat.mount_info.ufs_args,
> - sizeof(struct ufs_args));
> + memcpy(>mount_info, >mnt_stat.mount_info,
> + sizeof(union mount_info));
>  }
> Index: miscfs/fuse/fuse_vfsops.c
> ===
> RCS file: /cvs/src/sys/miscfs/fuse/fuse_vfsops.c,v
> retrieving revision 1.20
> diff -u -p -r1.20 fuse_vfsops.c
> --- miscfs/fuse/fuse_vfsops.c 27 Mar 2016 11:39:37 -  1.20
> +++ miscfs/fuse/fuse_vfsops.c 19 Apr 2016 18:52:52 -
> @@ -111,7 +111,9 @@ fusefs_mount(struct mount *mp, const 

numerous statfs bugs

2016-04-19 Thread Martin Natano
There seem to be a number of issues with statfs related code in the
kernel. The first issue is inside of the copy_statfs_info() function
which is designed to be used by the filesystem's .vfs_statfs
implementations to copy data from mp->mnt_stat to the target stat
buffer. copy_statfs_info() always copies the ufs_args from the
mount_info union, although the function is also used by non-ufs
filesystems. Copying the whole union instead of just one member should
do the trick for the general case.

statfs(2) returns incomplete information for most filesystems: cd9660,
udf, msdosfs and nfsv2 don't set f_namemax. ntfs and ext2fs don't set
f_namemeax and f_favail. fusefs doesn't set f_mntfromspec, f_favail and
f_iosize.

In sys_statfs(), the mount point specific >mnt_stat structure is
passed as the stat buffer to VFS_STATFS. When looking at the case where
(sb != >mnt-stat), the situation is even worse. cd9660, udf, fusefs,
msdosfs, ntfs and ext2fs don't use copy_statfs_info(), so there is a lot
of unset members in the stat buffer (f_fsid, f_owner, f_flags,
f_syncwrites, f_asyncwrites, f_syncreads, f_asyncreads, f_mntonname,
f_mntfromname and f_mntfromspec).

nfs copies MNAMELEN bytes from a smaller buffer into f_mntonname, so
there is garbage after the null byte.

Diff below fixes all those issues. Ok?

natano


Index: isofs/cd9660/cd9660_vfsops.c
===
RCS file: /cvs/src/sys/isofs/cd9660/cd9660_vfsops.c,v
retrieving revision 1.77
diff -u -p -r1.77 cd9660_vfsops.c
--- isofs/cd9660/cd9660_vfsops.c27 Mar 2016 11:39:37 -  1.77
+++ isofs/cd9660/cd9660_vfsops.c19 Apr 2016 18:52:52 -
@@ -383,6 +383,7 @@ iso_mountfs(devvp, mp, p, argp)
mp->mnt_data = (qaddr_t)isomp;
mp->mnt_stat.f_fsid.val[0] = (long)dev;
mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
+   mp->mnt_stat.f_namemax = NAME_MAX;
mp->mnt_flag |= MNT_LOCAL;
isomp->im_mountp = mp;
isomp->im_dev = dev;
@@ -650,13 +651,9 @@ cd9660_statfs(mp, sbp, p)
sbp->f_bavail = 0; /* blocks free for non superuser */
sbp->f_files =  0; /* total files */
sbp->f_ffree = 0; /* free file nodes */
-   if (sbp != >mnt_stat) {
-   bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
-   bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname,
-   MNAMELEN);
-   bcopy(>mnt_stat.mount_info.iso_args,
-   >mount_info.iso_args, sizeof(struct iso_args));
-   }
+   sbp->f_favail = 0; /* file nodes free for non superuser */
+   copy_statfs_info(sbp, mp);
+
return (0);
 }
 
Index: isofs/udf/udf_vfsops.c
===
RCS file: /cvs/src/sys/isofs/udf/udf_vfsops.c,v
retrieving revision 1.49
diff -u -p -r1.49 udf_vfsops.c
--- isofs/udf/udf_vfsops.c  27 Mar 2016 11:39:37 -  1.49
+++ isofs/udf/udf_vfsops.c  19 Apr 2016 18:52:52 -
@@ -264,6 +264,7 @@ udf_mountfs(struct vnode *devvp, struct 
mp->mnt_data = (qaddr_t) ump;
mp->mnt_stat.f_fsid.val[0] = devvp->v_rdev;
mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
+   mp->mnt_stat.f_namemax = NAME_MAX;
mp->mnt_flag |= MNT_LOCAL;
 
ump->um_mountp = mp;
@@ -542,6 +543,8 @@ udf_statfs(struct mount *mp, struct stat
sbp->f_bavail = 0;
sbp->f_files = 0;
sbp->f_ffree = 0;
+   sbp->f_favail = 0;
+   copy_statfs_info(sbp, mp);
 
return (0);
 }
Index: kern/vfs_subr.c
===
RCS file: /cvs/src/sys/kern/vfs_subr.c,v
retrieving revision 1.244
diff -u -p -r1.244 vfs_subr.c
--- kern/vfs_subr.c 7 Apr 2016 09:58:11 -   1.244
+++ kern/vfs_subr.c 19 Apr 2016 18:52:52 -
@@ -2276,6 +2276,6 @@ copy_statfs_info(struct statfs *sbp, con
memcpy(sbp->f_mntonname, mp->mnt_stat.f_mntonname, MNAMELEN);
memcpy(sbp->f_mntfromname, mp->mnt_stat.f_mntfromname, MNAMELEN);
memcpy(sbp->f_mntfromspec, mp->mnt_stat.f_mntfromspec, MNAMELEN);
-   memcpy(>mount_info.ufs_args, >mnt_stat.mount_info.ufs_args,
-   sizeof(struct ufs_args));
+   memcpy(>mount_info, >mnt_stat.mount_info,
+   sizeof(union mount_info));
 }
Index: miscfs/fuse/fuse_vfsops.c
===
RCS file: /cvs/src/sys/miscfs/fuse/fuse_vfsops.c,v
retrieving revision 1.20
diff -u -p -r1.20 fuse_vfsops.c
--- miscfs/fuse/fuse_vfsops.c   27 Mar 2016 11:39:37 -  1.20
+++ miscfs/fuse/fuse_vfsops.c   19 Apr 2016 18:52:52 -
@@ -111,7 +111,9 @@ fusefs_mount(struct mount *mp, const cha
bzero(mp->mnt_stat.f_mntonname, MNAMELEN);
strlcpy(mp->mnt_stat.f_mntonname, path, MNAMELEN);
bzero(mp->mnt_stat.f_mntfromname, MNAMELEN);
-   bcopy("fusefs", mp->mnt_stat.f_mntfromname, sizeof("fusefs"));
+