Re: 64-bit inodes (ino64) Status Update and Call for Testing

2017-05-21 Thread Jilles Tjoelker
On Sun, May 21, 2017 at 05:25:35PM +0300, Konstantin Belousov wrote:
> On Sun, May 21, 2017 at 04:03:55PM +0200, Jilles Tjoelker wrote:
> > On Sun, May 21, 2017 at 03:31:18PM +0300, Konstantin Belousov wrote:
> > > On Sun, May 21, 2017 at 02:14:56PM +0200, Jilles Tjoelker wrote:
> > > > We have another type in this area which is too small in some situations:
> > > > uint8_t for struct dirent.d_namlen. For filesystems that store filenames
> > > > as upto 255 UTF-16 code units, the name to be stored in d_name may be
> > > > upto 765 bytes long in UTF-8. This was reported in PR 204643. The code
> > > > currently handles this by returning the short (8.3) name, but this name
> > > > may not be present or usable, leaving the file inaccessible.

> > > > Actually allowing longer names seems too complicated to add to the ino64
> > > > change, but changing d_namlen to uint16_t (using d_pad0 space) and
> > > > skipping entries with d_namlen > 255 in libc may be helpful.

> > > > Note that applications using the deprecated readdir_r() will not be able
> > > > to read such long names, since the API does not allow specifying that a
> > > > larger buffer has been provided. (This could be avoided by making struct
> > > > dirent.d_name 766 bytes long instead of 256.)

> > > > Unfortunately, the existence of readdir_r() also prevents changing
> > > > struct dirent.d_name to the more correct flexible array.

> > > Yes, changing the size of d_name at this stage of the project is out of
> > > question. My reading of your proposal is that we should extend the size
> > > of d_namlen to uint16_t, am I right ? Should we go to 32bit directly
> > > then, perhaps ?

> > Yes, my proposal is to change d_namlen to uint16_t.

> > Making it 32 bits is not useful with the 16-bit d_reclen, and increasing
> > d_reclen does not seem useful to me with the current model of
> > getdirentries() where the whole dirent must fit into the caller's
> > buffer.

> Bumping it now might cause less churn later, even if unused, but ok.

> > > I did not committed the change below, nor did I tested or even build it.

> > I'd like to skip overlong names in the native readdir_r() as well, so
> > that long name support can be added to the kernel later without causing
> > buffer overflows with applications using FreeBSD 12.0 libc.

> > The native readdir() does not seem to have such a problem.

> Again, not even compiled.

Looks good to me.

> [patch snipped]

-- 
Jilles Tjoelker
___
freebsd-ports@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/freebsd-ports
To unsubscribe, send any mail to "freebsd-ports-unsubscr...@freebsd.org"


Re: 64-bit inodes (ino64) Status Update and Call for Testing

2017-05-21 Thread Konstantin Belousov
On Sun, May 21, 2017 at 04:03:55PM +0200, Jilles Tjoelker wrote:
> On Sun, May 21, 2017 at 03:31:18PM +0300, Konstantin Belousov wrote:
> > On Sun, May 21, 2017 at 02:14:56PM +0200, Jilles Tjoelker wrote:
> > > We have another type in this area which is too small in some situations:
> > > uint8_t for struct dirent.d_namlen. For filesystems that store filenames
> > > as upto 255 UTF-16 code units, the name to be stored in d_name may be
> > > upto 765 bytes long in UTF-8. This was reported in PR 204643. The code
> > > currently handles this by returning the short (8.3) name, but this name
> > > may not be present or usable, leaving the file inaccessible.
> 
> > > Actually allowing longer names seems too complicated to add to the ino64
> > > change, but changing d_namlen to uint16_t (using d_pad0 space) and
> > > skipping entries with d_namlen > 255 in libc may be helpful.
> 
> > > Note that applications using the deprecated readdir_r() will not be able
> > > to read such long names, since the API does not allow specifying that a
> > > larger buffer has been provided. (This could be avoided by making struct
> > > dirent.d_name 766 bytes long instead of 256.)
> 
> > > Unfortunately, the existence of readdir_r() also prevents changing
> > > struct dirent.d_name to the more correct flexible array.
> 
> > Yes, changing the size of d_name at this stage of the project is out of
> > question. My reading of your proposal is that we should extend the size
> > of d_namlen to uint16_t, am I right ? Should we go to 32bit directly
> > then, perhaps ?
> 
> Yes, my proposal is to change d_namlen to uint16_t.
> 
> Making it 32 bits is not useful with the 16-bit d_reclen, and increasing
> d_reclen does not seem useful to me with the current model of
> getdirentries() where the whole dirent must fit into the caller's
> buffer.
Bumping it now might cause less churn later, even if unused, but ok.

> 
> > I did not committed the change below, nor did I tested or even build it.
> 
> I'd like to skip overlong names in the native readdir_r() as well, so
> that long name support can be added to the kernel later without causing
> buffer overflows with applications using FreeBSD 12.0 libc.
> 
> The native readdir() does not seem to have such a problem.

Again, not even compiled.

diff --git a/lib/libc/gen/readdir-compat11.c b/lib/libc/gen/readdir-compat11.c
index 1c52f563c75..a865ab9157e 100644
--- a/lib/libc/gen/readdir-compat11.c
+++ b/lib/libc/gen/readdir-compat11.c
@@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$");
 #define_WANT_FREEBSD11_DIRENT
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -53,10 +54,12 @@ __FBSDID("$FreeBSD$");
 
 #include "gen-compat.h"
 
-static void
+static bool
 freebsd11_cvtdirent(struct freebsd11_dirent *dstdp, struct dirent *srcdp)
 {
 
+   if (srcdp->d_namelen >= sizeof(dstdp->d_name))
+   return (false);
dstdp->d_type = srcdp->d_type;
dstdp->d_namlen = srcdp->d_namlen;
dstdp->d_fileno = srcdp->d_fileno;  /* truncate */
@@ -65,6 +68,7 @@ freebsd11_cvtdirent(struct freebsd11_dirent *dstdp, struct 
dirent *srcdp)
bzero(dstdp->d_name + dstdp->d_namlen,
dstdp->d_reclen - offsetof(struct freebsd11_dirent, d_name) -
dstdp->d_namlen);
+   return (true);
 }
 
 struct freebsd11_dirent *
@@ -75,13 +79,15 @@ freebsd11_readdir(DIR *dirp)
 
if (__isthreaded)
_pthread_mutex_lock(>dd_lock);
-   dp = _readdir_unlocked(dirp, 1);
+   dp = _readdir_unlocked(dirp, RDU_SKIP);
if (dp != NULL) {
if (dirp->dd_compat_de == NULL)
dirp->dd_compat_de = malloc(sizeof(struct
freebsd11_dirent));
-   freebsd11_cvtdirent(dirp->dd_compat_de, dp);
-   dstdp = dirp->dd_compat_de;
+   if (freebsd11_cvtdirent(dirp->dd_compat_de, dp))
+   dstdp = dirp->dd_compat_de;
+   else
+   dstdp = NULL;
} else
dstdp = NULL;
if (__isthreaded)
@@ -101,8 +107,10 @@ freebsd11_readdir_r(DIR *dirp, struct freebsd11_dirent 
*entry,
if (error != 0)
return (error);
if (xresult != NULL) {
-   freebsd11_cvtdirent(entry, );
-   *result = entry;
+   if (freebsd11_cvtdirent(entry, ))
+   *result = entry;
+   else /* should not happen due to RDU_SHORT */
+   *result = NULL;
} else
*result = NULL;
return (0);
diff --git a/lib/libc/gen/readdir.c b/lib/libc/gen/readdir.c
index dc7b0df18b2..c30d48273b8 100644
--- a/lib/libc/gen/readdir.c
+++ b/lib/libc/gen/readdir.c
@@ -49,7 +49,7 @@ __FBSDID("$FreeBSD$");
  * get next entry in a directory.
  */
 struct dirent *
-_readdir_unlocked(DIR *dirp, int skip)
+_readdir_unlocked(DIR *dirp, int flags)
 {
struct dirent *dp;
long 

Re: 64-bit inodes (ino64) Status Update and Call for Testing

2017-05-21 Thread Jilles Tjoelker
On Sun, May 21, 2017 at 03:31:18PM +0300, Konstantin Belousov wrote:
> On Sun, May 21, 2017 at 02:14:56PM +0200, Jilles Tjoelker wrote:
> > We have another type in this area which is too small in some situations:
> > uint8_t for struct dirent.d_namlen. For filesystems that store filenames
> > as upto 255 UTF-16 code units, the name to be stored in d_name may be
> > upto 765 bytes long in UTF-8. This was reported in PR 204643. The code
> > currently handles this by returning the short (8.3) name, but this name
> > may not be present or usable, leaving the file inaccessible.

> > Actually allowing longer names seems too complicated to add to the ino64
> > change, but changing d_namlen to uint16_t (using d_pad0 space) and
> > skipping entries with d_namlen > 255 in libc may be helpful.

> > Note that applications using the deprecated readdir_r() will not be able
> > to read such long names, since the API does not allow specifying that a
> > larger buffer has been provided. (This could be avoided by making struct
> > dirent.d_name 766 bytes long instead of 256.)

> > Unfortunately, the existence of readdir_r() also prevents changing
> > struct dirent.d_name to the more correct flexible array.

> Yes, changing the size of d_name at this stage of the project is out of
> question. My reading of your proposal is that we should extend the size
> of d_namlen to uint16_t, am I right ? Should we go to 32bit directly
> then, perhaps ?

Yes, my proposal is to change d_namlen to uint16_t.

Making it 32 bits is not useful with the 16-bit d_reclen, and increasing
d_reclen does not seem useful to me with the current model of
getdirentries() where the whole dirent must fit into the caller's
buffer.

> I did not committed the change below, nor did I tested or even build it.

I'd like to skip overlong names in the native readdir_r() as well, so
that long name support can be added to the kernel later without causing
buffer overflows with applications using FreeBSD 12.0 libc.

The native readdir() does not seem to have such a problem.

> [patch snipped]

-- 
Jilles Tjoelker
___
freebsd-ports@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/freebsd-ports
To unsubscribe, send any mail to "freebsd-ports-unsubscr...@freebsd.org"


Re: 64-bit inodes (ino64) Status Update and Call for Testing

2017-05-21 Thread Konstantin Belousov
On Sun, May 21, 2017 at 02:14:56PM +0200, Jilles Tjoelker wrote:
> We have another type in this area which is too small in some situations:
> uint8_t for struct dirent.d_namlen. For filesystems that store filenames
> as upto 255 UTF-16 code units, the name to be stored in d_name may be
> upto 765 bytes long in UTF-8. This was reported in PR 204643. The code
> currently handles this by returning the short (8.3) name, but this name
> may not be present or usable, leaving the file inaccessible.
> 
> Actually allowing longer names seems too complicated to add to the ino64
> change, but changing d_namlen to uint16_t (using d_pad0 space) and
> skipping entries with d_namlen > 255 in libc may be helpful.
> 
> Note that applications using the deprecated readdir_r() will not be able
> to read such long names, since the API does not allow specifying that a
> larger buffer has been provided. (This could be avoided by making struct
> dirent.d_name 766 bytes long instead of 256.)
> 
> Unfortunately, the existence of readdir_r() also prevents changing
> struct dirent.d_name to the more correct flexible array.

Yes, changing the size of d_name at this stage of the project is out of
question. My reading of your proposal is that we should extend the size
of d_namlen to uint16_t, am I right ? Should we go to 32bit directly
then, perhaps ?

I did not committed the change below, nor did I tested or even build it.

diff --git a/lib/libc/gen/readdir-compat11.c b/lib/libc/gen/readdir-compat11.c
index 1c52f563c75..18d85adaa63 100644
--- a/lib/libc/gen/readdir-compat11.c
+++ b/lib/libc/gen/readdir-compat11.c
@@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$");
 #define_WANT_FREEBSD11_DIRENT
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -53,10 +54,12 @@ __FBSDID("$FreeBSD$");
 
 #include "gen-compat.h"
 
-static void
+static bool
 freebsd11_cvtdirent(struct freebsd11_dirent *dstdp, struct dirent *srcdp)
 {
 
+   if (srcdp->d_namelen >= sizeof(dstdp->d_name))
+   return (false);
dstdp->d_type = srcdp->d_type;
dstdp->d_namlen = srcdp->d_namlen;
dstdp->d_fileno = srcdp->d_fileno;  /* truncate */
@@ -65,6 +68,7 @@ freebsd11_cvtdirent(struct freebsd11_dirent *dstdp, struct 
dirent *srcdp)
bzero(dstdp->d_name + dstdp->d_namlen,
dstdp->d_reclen - offsetof(struct freebsd11_dirent, d_name) -
dstdp->d_namlen);
+   return (true);
 }
 
 struct freebsd11_dirent *
@@ -80,8 +84,10 @@ freebsd11_readdir(DIR *dirp)
if (dirp->dd_compat_de == NULL)
dirp->dd_compat_de = malloc(sizeof(struct
freebsd11_dirent));
-   freebsd11_cvtdirent(dirp->dd_compat_de, dp);
-   dstdp = dirp->dd_compat_de;
+   if (freebsd11_cvtdirent(dirp->dd_compat_de, dp))
+   dstdp = dirp->dd_compat_de;
+   else
+   dstdp = NULL;
} else
dstdp = NULL;
if (__isthreaded)
@@ -101,8 +107,10 @@ freebsd11_readdir_r(DIR *dirp, struct freebsd11_dirent 
*entry,
if (error != 0)
return (error);
if (xresult != NULL) {
-   freebsd11_cvtdirent(entry, );
-   *result = entry;
+   if (freebsd11_cvtdirent(entry, ))
+   *result = entry;
+   else
+   *result = NULL;
} else
*result = NULL;
return (0);
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index 784af836aee..27b2635030d 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -3733,7 +3733,8 @@ freebsd11_kern_getdirentries(struct thread *td, int fd, 
char *ubuf, u_int count,
if (dp->d_reclen == 0)
break;
MPASS(dp->d_reclen >= _GENERIC_DIRLEN(0));
-   /* dp->d_namlen <= sizeof(dstdp.d_name) - 1 always */
+   if (dp->d_namlen >= sizeof(dstdp.d_name))
+   continue;
dstdp.d_type = dp->d_type;
dstdp.d_namlen = dp->d_namlen;
dstdp.d_fileno = dp->d_fileno;  /* truncate */
diff --git a/sys/sys/dirent.h b/sys/sys/dirent.h
index 341855d0530..691c4e8f90f 100644
--- a/sys/sys/dirent.h
+++ b/sys/sys/dirent.h
@@ -67,8 +67,9 @@ struct dirent {
off_t  d_off;   /* directory offset of entry */
__uint16_t d_reclen;/* length of this record */
__uint8_t  d_type;  /* file type, see below */
-   __uint8_t  d_namlen;/* length of string in d_name */
-   __uint32_t d_pad0;
+   __uint8_t  d_pad0
+   __uint16_t d_namlen;/* length of string in d_name */
+   __uint16_t d_pad1;
 #if __BSD_VISIBLE
 #defineMAXNAMLEN   255
chard_name[MAXNAMLEN + 1];  /* name must be no longer than this */

Re: 64-bit inodes (ino64) Status Update and Call for Testing

2017-05-21 Thread Jilles Tjoelker
On Thu, Apr 20, 2017 at 10:43:14PM +0300, Konstantin Belousov wrote:
> Inodes are data structures corresponding to objects in a file system,
> such as files and directories. FreeBSD has historically used 32-bit
> values to identify inodes, which limits file systems to somewhat under
> 2^32 objects. Many modern file systems internally use 64-bit identifiers
> and FreeBSD needs to follow suit to properly and fully support these
> file systems.

> The 64-bit inode project, also known as ino64, started life many years
> ago as a project by Gleb Kurtsou (gleb@).  After that time several
> people have had a hand in updating it and addressing regressions, after
> mckusick@ picked up and updated the patch, and acted as a flag-waver.

> Sponsored by the FreeBSD Foundation I have spent a significant effort
> on outstanding issues and integration -- fixing compat32 ABI, NFS and
> ZFS, addressing ABI compat issues and investigating and fixing ports
> failures.  rmacklem@ provided feedback on NFS changes, emaste@ and
> jhb@ provided feedback and review on the ABI transition support. pho@
> performed extensive testing and identified a number of issues that
> have now been fixed.  kris@ performed an initial ports investigation
> followed by an exp-run by antoine@. emaste@ helped with organization
> of the process.

> This note explains how to perform useful testing of the ino64 branch,
> beyond typical smoke tests.

> 1. Overview.

> The ino64 branch extends the basic system types ino_t and dev_t from
> 32-bit to 64-bit, and nlink_t from 16-bit to 64-bit.  The struct dirent
> layout is modified due to the larger size of ino_t, and also gains a
> d_off (directory offset) member. As ino64 implies an ABI change anyway
> the struct statfs f_mntfromname[] and f_mntonname[] array length
> MNAMELEN is increased from 88 to 1024, to allow for longer mount path
> names.

> ABI breakage is mitigated by providing compatibility using versioned
> symbols, ingenious use of the existing padding in structures, and by
> employing other tricks.  Unfortunately, not everything can be fixed,
> especially outside the base system.  For instance, third-party APIs
> which pass struct stat around are broken in backward and forward-
> incompatible way.

We have another type in this area which is too small in some situations:
uint8_t for struct dirent.d_namlen. For filesystems that store filenames
as upto 255 UTF-16 code units, the name to be stored in d_name may be
upto 765 bytes long in UTF-8. This was reported in PR 204643. The code
currently handles this by returning the short (8.3) name, but this name
may not be present or usable, leaving the file inaccessible.

Actually allowing longer names seems too complicated to add to the ino64
change, but changing d_namlen to uint16_t (using d_pad0 space) and
skipping entries with d_namlen > 255 in libc may be helpful.

Note that applications using the deprecated readdir_r() will not be able
to read such long names, since the API does not allow specifying that a
larger buffer has been provided. (This could be avoided by making struct
dirent.d_name 766 bytes long instead of 256.)

Unfortunately, the existence of readdir_r() also prevents changing
struct dirent.d_name to the more correct flexible array.

-- 
Jilles Tjoelker
___
freebsd-ports@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/freebsd-ports
To unsubscribe, send any mail to "freebsd-ports-unsubscr...@freebsd.org"


Re: 64-bit inodes (ino64) Status Update and Call for Testing

2017-05-15 Thread Shawn Webb
On Mon, May 15, 2017 at 03:41:45PM -0400, Shawn Webb wrote:
> On Thu, Apr 20, 2017 at 10:43:14PM +0300, Konstantin Belousov wrote:
> > Inodes are data structures corresponding to objects in a file system,
> > such as files and directories. FreeBSD has historically used 32-bit
> > values to identify inodes, which limits file systems to somewhat under
> > 2^32 objects. Many modern file systems internally use 64-bit identifiers
> > and FreeBSD needs to follow suit to properly and fully support these
> > file systems.
> > 
> > The 64-bit inode project, also known as ino64, started life many years
> > ago as a project by Gleb Kurtsou (gleb@).  After that time several
> > people have had a hand in updating it and addressing regressions, after
> > mckusick@ picked up and updated the patch, and acted as a flag-waver.
> > 
> > Sponsored by the FreeBSD Foundation I have spent a significant effort
> > on outstanding issues and integration -- fixing compat32 ABI, NFS and
> > ZFS, addressing ABI compat issues and investigating and fixing ports
> > failures.  rmacklem@ provided feedback on NFS changes, emaste@ and
> > jhb@ provided feedback and review on the ABI transition support. pho@
> > performed extensive testing and identified a number of issues that
> > have now been fixed.  kris@ performed an initial ports investigation
> > followed by an exp-run by antoine@. emaste@ helped with organization
> > of the process.
> > 
> > This note explains how to perform useful testing of the ino64 branch,
> > beyond typical smoke tests.
> > 
> > 1. Overview.
> > 
> > The ino64 branch extends the basic system types ino_t and dev_t from
> > 32-bit to 64-bit, and nlink_t from 16-bit to 64-bit.  The struct dirent
> > layout is modified due to the larger size of ino_t, and also gains a
> > d_off (directory offset) member. As ino64 implies an ABI change anyway
> > the struct statfs f_mntfromname[] and f_mntonname[] array length
> > MNAMELEN is increased from 88 to 1024, to allow for longer mount path
> > names.
> > 
> > ABI breakage is mitigated by providing compatibility using versioned
> > symbols, ingenious use of the existing padding in structures, and by
> > employing other tricks.  Unfortunately, not everything can be fixed,
> > especially outside the base system.  For instance, third-party APIs
> > which pass struct stat around are broken in backward and forward-
> > incompatible way.
> > 
> > 2. Motivation.
> > 
> > The main risk of the ino64 change is the uncontrolled ABI breakage.
> > Due to expansion of the basic types dev_t, ino_t and struct dirent,
> > the impact is not limited to one part of the system, but affects:
> > - kernel/userspace interface (syscalls ABI, mostly stat(2), kinfo
> >   and more)
> > - libc interface (mostly related to the readdir(3), FTS(3))
> > - collateral damage in other libraries that happens to use changed types
> >   in the interfaces.  See, for instance, libprocstat, for which compat
> >   was provided using symbol versioning, and libutil, which shlib version
> >   was bumped.
> > 
> > 3. Quirks.
> > 
> > We handled kinfo sysctl MIBs, but other MIBs which report structures
> > depended on the changed type, are not handled in general.  It was
> > considered that the breakage is either in the management interfaces,
> > where we usually allow ABI slip, or is not important.
> > 
> > Struct xvnode changed layout, no compat shims are provided.
> > 
> > For struct xtty, dev_t tty device member was reduced to uint32_t.  It
> > was decided that keeping ABI compat in this case is more useful than
> > reporting 64bit dev_t, for the sake of pstat.
> > 
> > 4. Testing procedure.
> > 
> > The ino64 project can be tested by cloning the project branch from
> > GitHub or by applying the patch  > at URL | attached> to a working tree.  The authorative source is the
> > GitHub, I do not promise to update the review for each update.
> > 
> > To clone from GitHub:
> > % git clone -b ino64 https://github.com/FreeBSDFoundation/freebsd.git ino64
> > 
> > To fetch the patch from Phabricator:
> > - Visit https://reviews.freebsd.org/D10439
> > - Click "Download Raw Diff" at the upper right of the page
> > 
> > Or
> > % arc patch D10439
> > 
> > After that, in the checkout directory do
> > % (cd sys/kern && touch syscalls.master && make sysent)
> > % (cd sys/compat/freebsd32 && touch syscalls.master && make sysent)
> > If you use custom kernel configuration, ensure that
> > options COMPAT_FREEBSD11
> > is included into the config.  Then build world and kernel in the
> > usual way, install kernel, reboot, install new world.  Do not make
> > shortcuts in the update procedure.
> 
> Hey Kostik,
> 
> On my HardenedBSD system, world compiled fine with the patch, but the
> kernel didn't compile. I've uploaded the log to:
> 
> https://hardenedbsd.org/~shawn/2017-05-15_ino64-r01.log
> 
> This was from importing the patch from Phabricator into
> hardened/current/master in HardenedBSD.

Update: I missed a step. Kernel and 

Re: 64-bit inodes (ino64) Status Update and Call for Testing

2017-05-15 Thread Shawn Webb
On Thu, Apr 20, 2017 at 10:43:14PM +0300, Konstantin Belousov wrote:
> Inodes are data structures corresponding to objects in a file system,
> such as files and directories. FreeBSD has historically used 32-bit
> values to identify inodes, which limits file systems to somewhat under
> 2^32 objects. Many modern file systems internally use 64-bit identifiers
> and FreeBSD needs to follow suit to properly and fully support these
> file systems.
> 
> The 64-bit inode project, also known as ino64, started life many years
> ago as a project by Gleb Kurtsou (gleb@).  After that time several
> people have had a hand in updating it and addressing regressions, after
> mckusick@ picked up and updated the patch, and acted as a flag-waver.
> 
> Sponsored by the FreeBSD Foundation I have spent a significant effort
> on outstanding issues and integration -- fixing compat32 ABI, NFS and
> ZFS, addressing ABI compat issues and investigating and fixing ports
> failures.  rmacklem@ provided feedback on NFS changes, emaste@ and
> jhb@ provided feedback and review on the ABI transition support. pho@
> performed extensive testing and identified a number of issues that
> have now been fixed.  kris@ performed an initial ports investigation
> followed by an exp-run by antoine@. emaste@ helped with organization
> of the process.
> 
> This note explains how to perform useful testing of the ino64 branch,
> beyond typical smoke tests.
> 
> 1. Overview.
> 
> The ino64 branch extends the basic system types ino_t and dev_t from
> 32-bit to 64-bit, and nlink_t from 16-bit to 64-bit.  The struct dirent
> layout is modified due to the larger size of ino_t, and also gains a
> d_off (directory offset) member. As ino64 implies an ABI change anyway
> the struct statfs f_mntfromname[] and f_mntonname[] array length
> MNAMELEN is increased from 88 to 1024, to allow for longer mount path
> names.
> 
> ABI breakage is mitigated by providing compatibility using versioned
> symbols, ingenious use of the existing padding in structures, and by
> employing other tricks.  Unfortunately, not everything can be fixed,
> especially outside the base system.  For instance, third-party APIs
> which pass struct stat around are broken in backward and forward-
> incompatible way.
> 
> 2. Motivation.
> 
> The main risk of the ino64 change is the uncontrolled ABI breakage.
> Due to expansion of the basic types dev_t, ino_t and struct dirent,
> the impact is not limited to one part of the system, but affects:
> - kernel/userspace interface (syscalls ABI, mostly stat(2), kinfo
>   and more)
> - libc interface (mostly related to the readdir(3), FTS(3))
> - collateral damage in other libraries that happens to use changed types
>   in the interfaces.  See, for instance, libprocstat, for which compat
>   was provided using symbol versioning, and libutil, which shlib version
>   was bumped.
> 
> 3. Quirks.
> 
> We handled kinfo sysctl MIBs, but other MIBs which report structures
> depended on the changed type, are not handled in general.  It was
> considered that the breakage is either in the management interfaces,
> where we usually allow ABI slip, or is not important.
> 
> Struct xvnode changed layout, no compat shims are provided.
> 
> For struct xtty, dev_t tty device member was reduced to uint32_t.  It
> was decided that keeping ABI compat in this case is more useful than
> reporting 64bit dev_t, for the sake of pstat.
> 
> 4. Testing procedure.
> 
> The ino64 project can be tested by cloning the project branch from
> GitHub or by applying the patch  at URL | attached> to a working tree.  The authorative source is the
> GitHub, I do not promise to update the review for each update.
> 
> To clone from GitHub:
> % git clone -b ino64 https://github.com/FreeBSDFoundation/freebsd.git ino64
> 
> To fetch the patch from Phabricator:
> - Visit https://reviews.freebsd.org/D10439
> - Click "Download Raw Diff" at the upper right of the page
> 
> Or
> % arc patch D10439
> 
> After that, in the checkout directory do
> % (cd sys/kern && touch syscalls.master && make sysent)
> % (cd sys/compat/freebsd32 && touch syscalls.master && make sysent)
> If you use custom kernel configuration, ensure that
>   options COMPAT_FREEBSD11
> is included into the config.  Then build world and kernel in the
> usual way, install kernel, reboot, install new world.  Do not make
> shortcuts in the update procedure.

Hey Kostik,

On my HardenedBSD system, world compiled fine with the patch, but the
kernel didn't compile. I've uploaded the log to:

https://hardenedbsd.org/~shawn/2017-05-15_ino64-r01.log

This was from importing the patch from Phabricator into
hardened/current/master in HardenedBSD.

Thanks,

-- 
Shawn Webb
Cofounder and Security Engineer
HardenedBSD

GPG Key ID:  0x6A84658F52456EEE
GPG Key Fingerprint: 2ABA B6BD EF6A F486 BE89  3D9E 6A84 658F 5245 6EEE


signature.asc
Description: PGP signature


64-bit inodes (ino64) Status Update and Call for Testing

2017-04-20 Thread Konstantin Belousov
Inodes are data structures corresponding to objects in a file system,
such as files and directories. FreeBSD has historically used 32-bit
values to identify inodes, which limits file systems to somewhat under
2^32 objects. Many modern file systems internally use 64-bit identifiers
and FreeBSD needs to follow suit to properly and fully support these
file systems.

The 64-bit inode project, also known as ino64, started life many years
ago as a project by Gleb Kurtsou (gleb@).  After that time several
people have had a hand in updating it and addressing regressions, after
mckusick@ picked up and updated the patch, and acted as a flag-waver.

Sponsored by the FreeBSD Foundation I have spent a significant effort
on outstanding issues and integration -- fixing compat32 ABI, NFS and
ZFS, addressing ABI compat issues and investigating and fixing ports
failures.  rmacklem@ provided feedback on NFS changes, emaste@ and
jhb@ provided feedback and review on the ABI transition support. pho@
performed extensive testing and identified a number of issues that
have now been fixed.  kris@ performed an initial ports investigation
followed by an exp-run by antoine@. emaste@ helped with organization
of the process.

This note explains how to perform useful testing of the ino64 branch,
beyond typical smoke tests.

1. Overview.

The ino64 branch extends the basic system types ino_t and dev_t from
32-bit to 64-bit, and nlink_t from 16-bit to 64-bit.  The struct dirent
layout is modified due to the larger size of ino_t, and also gains a
d_off (directory offset) member. As ino64 implies an ABI change anyway
the struct statfs f_mntfromname[] and f_mntonname[] array length
MNAMELEN is increased from 88 to 1024, to allow for longer mount path
names.

ABI breakage is mitigated by providing compatibility using versioned
symbols, ingenious use of the existing padding in structures, and by
employing other tricks.  Unfortunately, not everything can be fixed,
especially outside the base system.  For instance, third-party APIs
which pass struct stat around are broken in backward and forward-
incompatible way.

2. Motivation.

The main risk of the ino64 change is the uncontrolled ABI breakage.
Due to expansion of the basic types dev_t, ino_t and struct dirent,
the impact is not limited to one part of the system, but affects:
- kernel/userspace interface (syscalls ABI, mostly stat(2), kinfo
  and more)
- libc interface (mostly related to the readdir(3), FTS(3))
- collateral damage in other libraries that happens to use changed types
  in the interfaces.  See, for instance, libprocstat, for which compat
  was provided using symbol versioning, and libutil, which shlib version
  was bumped.

3. Quirks.

We handled kinfo sysctl MIBs, but other MIBs which report structures
depended on the changed type, are not handled in general.  It was
considered that the breakage is either in the management interfaces,
where we usually allow ABI slip, or is not important.

Struct xvnode changed layout, no compat shims are provided.

For struct xtty, dev_t tty device member was reduced to uint32_t.  It
was decided that keeping ABI compat in this case is more useful than
reporting 64bit dev_t, for the sake of pstat.

4. Testing procedure.

The ino64 project can be tested by cloning the project branch from
GitHub or by applying the patch  to a working tree.  The authorative source is the
GitHub, I do not promise to update the review for each update.

To clone from GitHub:
% git clone -b ino64 https://github.com/FreeBSDFoundation/freebsd.git ino64

To fetch the patch from Phabricator:
- Visit https://reviews.freebsd.org/D10439
- Click "Download Raw Diff" at the upper right of the page

Or
% arc patch D10439

After that, in the checkout directory do
% (cd sys/kern && touch syscalls.master && make sysent)
% (cd sys/compat/freebsd32 && touch syscalls.master && make sysent)
If you use custom kernel configuration, ensure that
options COMPAT_FREEBSD11
is included into the config.  Then build world and kernel in the
usual way, install kernel, reboot, install new world.  Do not make
shortcuts in the update procedure.

4.1 New kernel, old world.

Build and install pristine HEAD world, apply patch and only build and
install updated kernel. The system must work same as with the pristine
kernel.

4.2 New kernel, new world, old third-party applications.

Build and install patched kernel and world.  Applications compiled on the
pristine HEAD (e.g. installed by pkg from the regular portmgr builds) must
work without a regression.

4.3 32bit compat.

Same as 4.1 and 4.2, but for 32bit (i386) binaries on the amd64 host.
Note that big-endian host, like powerpc, might expose additional
bugs in the 32bit compat with the patch, but the testing is too cumbersome
to arrange.

4.4 Targeted tests.

Useful programs to check items 4.1, 4.2 and 4.3 are versions of the
following programs, taken from the pristine system:

  stat(8). Use it on regular file, file in /dev, socket, pipe and