svn commit: r269523 - head/sys/fs/ext2fs

Bruce Evans brde at optusnet.com.au
Mon Aug 4 19:01:54 UTC 2014


On Mon, 4 Aug 2014, Pedro F. Giffuni wrote:

> Log:
>  set EXT2_LINK_MAX to LINK_MAX
>
>  In linux EXT4_LINK_MAX is now 64000.  We can't really do that
>  since i_nlink and va_nlink are signed so setting higher values
>  is likely to cause trouble.

Hmm, va_nlink doesn't use nlink_t and is inconsistent with nlink_t
since nlink_t is unsigned.  The bug is nlink_t being unsigned.
Signed for i_nlink is more reasonable although it is inconsistent
with unsigned for e2di_nlink.  The implementation might want to
use the better arithmetic of signed types.  However, it blindly
converts from unsigned to signed when converting e2di_nlink to
i_nlink, so it overflows for corrupt file systems with e2di_nlink
larger than 32767.

>  This is a system limitation so set the EXT_LINK_MAX to
>  what the system can handle.
>
>  MFC after:	3 days
>
> Modified:
>  head/sys/fs/ext2fs/ext2_dir.h
>
> Modified: head/sys/fs/ext2fs/ext2_dir.h
> ==============================================================================
> --- head/sys/fs/ext2fs/ext2_dir.h	Mon Aug  4 16:32:08 2014	(r269522)
> +++ head/sys/fs/ext2fs/ext2_dir.h	Mon Aug  4 16:41:06 2014	(r269523)
> @@ -72,7 +72,7 @@ struct	ext2fs_direct_2 {
> /*
>  * Maximal count of links to a file
>  */
> -#define	EXT2_LINK_MAX	32000
> +#define	EXT2_LINK_MAX	LINK_MAX
>
> /*
>  * Ext2 directory file types.  Only the low 3 bits are used.  The

This breaks ext2 where the limit is 32000.  It allows creating corrupt
file systems containing inodes with more than 32000 links.  The
corruption would be noticed by ext2fs implemenations with a non-broken
limit and should be noticed by ext2fsck.  The failure modes in the
previous version of ext2fs in FreeBSD seem to be limited to operations
that increase the link count further (including temporary increases for
rename?).

Old versions of ext2fs in FreeBSD had the same bug in a worse way.  They
defined EXT2_LINK_MAX as 32000 but never used it.  They used the system
LINK_MAX instead.

Old versions of linux (2.6.10) have many bugs related to LINK_MAX, but
not this one.  {LINK_MAX} is variable.  Thus LINK_MAX must not be
defined in <limits.h>.  But it is defined in <limits.h>, with a value
of 127 that is too small for most file systems.  Many nearby variable
limits that must not be defined are defined (the worst one in practice
is {OPEN_MAX}.  Similarly in FreeBSD, except the LINK_MAX that must
not be defined in <limits.h> is defined as large enough for all file
systems.  Back in linux, nlink_t is uint16_t on some arches including
x86, but JFS_LINK_MAX is 0xffffffff.  I can't see where pathconf()
returns an fs-dependent (or file-dependent) limit.

Bruce


More information about the svn-src-all mailing list