]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
mkfs: fix symlink target length check in create_nondir_inode
authorDarrick J. Wong <djwong@kernel.org>
Mon, 8 Jun 2026 17:08:35 +0000 (10:08 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Thu, 2 Jul 2026 19:38:24 +0000 (12:38 -0700)
Codex complains about the way this function tries to detect symlink
targets that are so long that the new filesystem cannot handle them.
Specifically, it complains about the confusion between
XFS_SYMLINK_MAXLEN and PATH_MAX.

To be clear, XFS cannot handle targets longer than XFS_SYMLINK_MAXLEN
bytes.  PATH_MAX is irrelevant here.  The manpage for readlink(3) says
that it returns the number of bytes copied into the buffer and does not
say that it null-terminates the buffer.  Therefore, the only way to
detect the overflow condition is to declare a buffer larger than
XFS_SYMLINK_MAXLEN and see if readink returns a value greater than
XFS_SYMLINK_MAXLEN.

Cc: <linux-xfs@vger.kernel.org> # v6.17.0
Fixes: 8a4ea72724930c ("proto: add ability to populate a filesystem from a directory")
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
mkfs/proto.c

index e167cba1d8d3ecb205c49f82dfbd4c12baf7586d..e258424ae4140a4180c58ca471f752d406826283 100644 (file)
@@ -1542,7 +1542,7 @@ create_nondir_inode(
        char                    *src_fname)
 {
 
-       char                    link_target[XFS_SYMLINK_MAXLEN];
+       char                    link_target[XFS_SYMLINK_MAXLEN + 1];
        int                     error;
        ssize_t                 link_len = 0;
        struct xfs_inode        *ip;
@@ -1563,10 +1563,10 @@ create_nondir_inode(
         * We need to read out our link target and act accordingly.
         */
        if (xname.type == XFS_DIR3_FT_SYMLINK) {
-               link_len = readlink(src_fname, link_target, XFS_SYMLINK_MAXLEN);
+               link_len = readlink(src_fname, link_target, sizeof(link_target));
                if (link_len < 0)
                        fail(_("could not resolve symlink"), errno);
-               if (link_len >= PATH_MAX)
+               if (link_len > XFS_SYMLINK_MAXLEN)
                        fail(_("symlink target too long"), ENAMETOOLONG);
                tp = getres(mp, XFS_B_TO_FSB(mp, link_len));
        } else {