From 487e8c964078f823646d3b0584745ab7d0ef99ca Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 26 Nov 2019 09:01:21 +0000 Subject: [PATCH 11/12] ext2: Build symbolic links correctly (RHBZ#1770304). We created symlinks in two steps, by creating the empty inode and then calling ext2fs_symlink to populate it. This created broken symlinks where the directory name contained a / character, eg: lrwxrwxrwx 1 root root 7 Nov 26 08:43 /bin -> usr/bin lrwxrwxrwx 1 root root 7 Nov 26 08:43 /lib -> usr/lib lrwxrwxrwx 1 root root 9 Nov 26 08:43 /lib64 -> usr/lib64 lrwxrwxrwx 1 root root 8 Nov 26 08:43 /sbin -> usr/sbin lrwxrwxrwx 1 root root 7 Nov 26 08:38 bin -> usr/bin This breaks with Linux >= 5.3.8, most likely because of extra validation now being done at the VFS layer: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/fs/readdir.c?id=8a23eb804ca4f2be909e372cf5a9e7b30ae476cd It's unnecessary to create the empty inode since ext2fs_symlink can create the inode for us perfectly fine if we simply pass ino == 0, and it creates them correctly too. Thanks: Toolybird for identifying the problem and kernel patch. --- src/ext2fs-c.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/ext2fs-c.c b/src/ext2fs-c.c index e8ab972..8903f74 100644 --- a/src/ext2fs-c.c +++ b/src/ext2fs-c.c @@ -782,12 +782,6 @@ ext2_copy_file (struct ext2_data *data, const char *src, const char *dest) } /* Create a symlink. */ else if (S_ISLNK (statbuf.st_mode)) { - ext2_ino_t ino; - ext2_empty_inode (data->fs, dir_ino, dirname, basename, - statbuf.st_mode, statbuf.st_uid, statbuf.st_gid, - statbuf.st_ctime, statbuf.st_atime, statbuf.st_mtime, - 0, 0, EXT2_FT_SYMLINK, &ino); - char *buf = malloc (statbuf.st_size+1); if (buf == NULL) caml_raise_out_of_memory (); @@ -797,7 +791,7 @@ ext2_copy_file (struct ext2_data *data, const char *src, const char *dest) if (r > statbuf.st_size) r = statbuf.st_size; buf[r] = '\0'; - ext2fs_symlink (data->fs, dir_ino, ino, dest, buf); + ext2fs_symlink (data->fs, dir_ino, 0, basename, buf); free (buf); } /* Create directory. */ -- 2.23.0