]> git.ipfire.org Git - thirdparty/e2fsprogs.git/commitdiff
Add debian patches for commits cherry picked since v1.44.1-1
authorTheodore Ts'o <tytso@mit.edu>
Mon, 9 Apr 2018 20:31:27 +0000 (16:31 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Tue, 10 Apr 2018 15:18:04 +0000 (11:18 -0400)
(Also remove tests/f_orphquot since it has a binary file which makes
 debian's patch infrastructure unhappy.)

Signed-off-by: Theodore Ts'o <tytso@mit.edu>
debian/patches/e2fsck-adjust-quota-counters-when-clearing-orphaned-inodes [new file with mode: 0644]
debian/patches/e2image-fix-metadata-image-handling-on-big-endian-systems [new file with mode: 0644]
debian/patches/filefrag-avoid-temporary-buffer-overflow [new file with mode: 0644]
debian/patches/libext2fs-add-sanity-checks-for-ea_in_inode [new file with mode: 0644]
debian/patches/series [new file with mode: 0644]
tests/f_orphquot/expect [deleted file]
tests/f_orphquot/image.bz2 [deleted file]
tests/f_orphquot/script [deleted file]

diff --git a/debian/patches/e2fsck-adjust-quota-counters-when-clearing-orphaned-inodes b/debian/patches/e2fsck-adjust-quota-counters-when-clearing-orphaned-inodes
new file mode 100644 (file)
index 0000000..a999329
--- /dev/null
@@ -0,0 +1,302 @@
+Description: e2fsck: adjust quota counters when clearing orphaned inodes
+ If e2fsck encounters a filesystem that supports internal quotas, it is
+ responsible for adjusting the quota counters if it decides to clear any
+ orphaned inodes.  Therefore, we must read the quota files, adjust the
+ counters, and write the quota files back out when we are done.
+From: "Darrick J. Wong" <darrick.wong@oracle.com>
+Origin: upstream, commit:7d79b40bb30e
+---
+ e2fsck/super.c             | 121 +++++++++++++++++++++++++++++++++++++--------
+ lib/support/mkquota.c      |  12 +++--
+ 2 files changed, 133 insertions(+), 24 deletions(-)
+
+diff --git a/e2fsck/super.c b/e2fsck/super.c
+index 5e29b64ef..9c0e0e7b3 100644
+--- a/e2fsck/super.c
++++ b/e2fsck/super.c
+@@ -72,6 +72,7 @@ struct process_block_struct {
+       int             abort;
+       errcode_t       errcode;
+       blk64_t last_cluster;
++      struct ext2_inode_large *inode;
+ };
+ static int release_inode_block(ext2_filsys fs,
+@@ -168,6 +169,8 @@ static int release_inode_block(ext2_filsys fs,
+               retval |= BLOCK_CHANGED;
+       }
++      if (ctx->qctx)
++              quota_data_sub(ctx->qctx, pb->inode, 0, ctx->fs->blocksize);
+       ext2fs_block_alloc_stats2(fs, blk, -1);
+       ctx->free_blocks++;
+       return retval;
+@@ -179,15 +182,16 @@ static int release_inode_block(ext2_filsys fs,
+  * not deleted.
+  */
+ static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino,
+-                              struct ext2_inode *inode, char *block_buf,
++                              struct ext2_inode_large *inode, char *block_buf,
+                               struct problem_context *pctx)
+ {
+       struct process_block_struct     pb;
+       ext2_filsys                     fs = ctx->fs;
++      blk64_t                         blk;
+       errcode_t                       retval;
+       __u32                           count;
+-      if (!ext2fs_inode_has_valid_blocks2(fs, inode))
++      if (!ext2fs_inode_has_valid_blocks2(fs, EXT2_INODE(inode)))
+               return 0;
+       pb.buf = block_buf + 3 * ctx->fs->blocksize;
+@@ -196,6 +200,7 @@ static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino,
+       pb.errcode = 0;
+       pb.pctx = pctx;
+       pb.last_cluster = 0;
++      pb.inode = inode;
+       if (inode->i_links_count) {
+               pb.truncating = 1;
+               pb.truncate_block = (e2_blkcnt_t)
+@@ -220,15 +225,17 @@ static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino,
+               return 1;
+       /* Refresh the inode since ext2fs_block_iterate may have changed it */
+-      e2fsck_read_inode(ctx, ino, inode, "release_inode_blocks");
++      e2fsck_read_inode_full(ctx, ino, EXT2_INODE(inode), sizeof(*inode),
++                      "release_inode_blocks");
+       if (pb.truncated_blocks)
+-              ext2fs_iblk_sub_blocks(fs, inode, pb.truncated_blocks);
++              ext2fs_iblk_sub_blocks(fs, EXT2_INODE(inode),
++                              pb.truncated_blocks);
+-      if (ext2fs_file_acl_block(fs, inode)) {
+-              retval = ext2fs_adjust_ea_refcount3(fs,
+-                              ext2fs_file_acl_block(fs, inode),
+-                              block_buf, -1, &count, ino);
++      blk = ext2fs_file_acl_block(fs, EXT2_INODE(inode));
++      if (blk) {
++              retval = ext2fs_adjust_ea_refcount3(fs, blk, block_buf, -1,
++                              &count, ino);
+               if (retval == EXT2_ET_BAD_EA_BLOCK_NUM) {
+                       retval = 0;
+                       count = 1;
+@@ -240,15 +247,68 @@ static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino,
+                       return 1;
+               }
+               if (count == 0) {
+-                      ext2fs_block_alloc_stats2(fs,
+-                                      ext2fs_file_acl_block(fs, inode), -1);
++                      if (ctx->qctx)
++                              quota_data_sub(ctx->qctx, inode, 0,
++                                              ctx->fs->blocksize);
++                      ext2fs_block_alloc_stats2(fs, blk, -1);
+                       ctx->free_blocks++;
+               }
+-              ext2fs_file_acl_block_set(fs, inode, 0);
++              ext2fs_file_acl_block_set(fs, EXT2_INODE(inode), 0);
+       }
+       return 0;
+ }
++/* Load all quota data in preparation for orphan clearing. */
++static errcode_t e2fsck_read_all_quotas(e2fsck_t ctx)
++{
++      ext2_ino_t qf_ino;
++      enum quota_type qtype;
++      errcode_t retval = 0;
++
++      if (!ext2fs_has_feature_quota(ctx->fs->super))
++              return retval;
++
++      retval = quota_init_context(&ctx->qctx, ctx->fs, 0);
++      if (retval)
++              return retval;
++
++      for (qtype = 0 ; qtype < MAXQUOTAS; qtype++) {
++              qf_ino = *quota_sb_inump(ctx->fs->super, qtype);
++              if (qf_ino == 0)
++                      continue;
++
++              retval = quota_update_limits(ctx->qctx, qf_ino, qtype);
++              if (retval)
++                      break;
++      }
++      if (retval)
++              quota_release_context(&ctx->qctx);
++      return retval;
++}
++
++/* Write all the quota info to disk. */
++static errcode_t e2fsck_write_all_quotas(e2fsck_t ctx)
++{
++      struct problem_context pctx;
++      enum quota_type qtype;
++
++      if (!ext2fs_has_feature_quota(ctx->fs->super))
++              return 0;
++
++      clear_problem_context(&pctx);
++      for (qtype = 0 ; qtype < MAXQUOTAS; qtype++) {
++              pctx.num = qtype;
++              pctx.errcode = quota_write_inode(ctx->qctx, 1 << qtype);
++              if (pctx.errcode) {
++                      fix_problem(ctx, PR_6_WRITE_QUOTAS, &pctx);
++                      break;
++              }
++      }
++
++      quota_release_context(&ctx->qctx);
++      return pctx.errcode;
++}
++
+ /*
+  * This function releases all of the orphan inodes.  It returns 1 if
+  * it hit some error, and 0 on success.
+@@ -257,13 +317,20 @@ static int release_orphan_inodes(e2fsck_t ctx)
+ {
+       ext2_filsys fs = ctx->fs;
+       ext2_ino_t      ino, next_ino;
+-      struct ext2_inode inode;
++      struct ext2_inode_large inode;
+       struct problem_context pctx;
+       char *block_buf;
+       if ((ino = fs->super->s_last_orphan) == 0)
+               return 0;
++      clear_problem_context(&pctx);
++      pctx.errcode = e2fsck_read_all_quotas(ctx);
++      if (pctx.errcode) {
++              fix_problem(ctx, PR_0_QUOTA_INIT_CTX, &pctx);
++              return 1;
++      }
++
+       /*
+        * Win or lose, we won't be using the head of the orphan inode
+        * list again.
+@@ -276,15 +343,18 @@ static int release_orphan_inodes(e2fsck_t ctx)
+        * list, since the orphan list can't be trusted; and we're
+        * going to be running a full e2fsck run anyway...
+        */
+-      if (fs->super->s_state & EXT2_ERROR_FS)
++      if (fs->super->s_state & EXT2_ERROR_FS) {
++              if (ctx->qctx)
++                      quota_release_context(&ctx->qctx);
+               return 0;
++      }
+       if ((ino < EXT2_FIRST_INODE(fs->super)) ||
+           (ino > fs->super->s_inodes_count)) {
+               clear_problem_context(&pctx);
+               pctx.ino = ino;
+               fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_HEAD_INODE, &pctx);
+-              return 1;
++              goto err_qctx;
+       }
+       block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
+@@ -292,10 +362,11 @@ static int release_orphan_inodes(e2fsck_t ctx)
+       e2fsck_read_bitmaps(ctx);
+       while (ino) {
+-              e2fsck_read_inode(ctx, ino, &inode, "release_orphan_inodes");
++              e2fsck_read_inode_full(ctx, ino, EXT2_INODE(&inode),
++                              sizeof(inode), "release_orphan_inodes");
+               clear_problem_context(&pctx);
+               pctx.ino = ino;
+-              pctx.inode = &inode;
++              pctx.inode = EXT2_INODE(&inode);
+               pctx.str = inode.i_links_count ? _("Truncating") :
+                       _("Clearing");
+@@ -307,13 +378,15 @@ static int release_orphan_inodes(e2fsck_t ctx)
+                    (next_ino > fs->super->s_inodes_count))) {
+                       pctx.ino = next_ino;
+                       fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_INODE, &pctx);
+-                      goto return_abort;
++                      goto err_buf;
+               }
+               if (release_inode_blocks(ctx, ino, &inode, block_buf, &pctx))
+-                      goto return_abort;
++                      goto err_buf;
+               if (!inode.i_links_count) {
++                      if (ctx->qctx)
++                              quota_data_inodes(ctx->qctx, &inode, ino, -1);
+                       ext2fs_inode_alloc_stats2(fs, ino, -1,
+                                                 LINUX_S_ISDIR(inode.i_mode));
+                       ctx->free_inodes++;
+@@ -321,13 +394,21 @@ static int release_orphan_inodes(e2fsck_t ctx)
+               } else {
+                       inode.i_dtime = 0;
+               }
+-              e2fsck_write_inode(ctx, ino, &inode, "delete_file");
++              e2fsck_write_inode_full(ctx, ino, EXT2_INODE(&inode),
++                              sizeof(inode), "delete_file");
+               ino = next_ino;
+       }
+       ext2fs_free_mem(&block_buf);
++      pctx.errcode = e2fsck_write_all_quotas(ctx);
++      if (pctx.errcode)
++              goto err;
+       return 0;
+-return_abort:
++err_buf:
+       ext2fs_free_mem(&block_buf);
++err_qctx:
++      if (ctx->qctx)
++              quota_release_context(&ctx->qctx);
++err:
+       return 1;
+ }
+diff --git a/lib/support/mkquota.c b/lib/support/mkquota.c
+index e65c95b76..efc37cb49 100644
+--- a/lib/support/mkquota.c
++++ b/lib/support/mkquota.c
+@@ -516,6 +516,7 @@ struct scan_dquots_data {
+       dict_t          *quota_dict;
+       int             update_limits; /* update limits from disk */
+       int             update_usage;
++      int             check_consistency;
+       int             usage_is_inconsistent;
+ };
+@@ -533,8 +534,9 @@ static int scan_dquots_callback(struct dquot *dquot, void *cb_data)
+       print_dquot("dsk", dquot);
+       /* Check if there is inconsistency */
+-      if (dq->dq_dqb.dqb_curspace != dquot->dq_dqb.dqb_curspace ||
+-          dq->dq_dqb.dqb_curinodes != dquot->dq_dqb.dqb_curinodes) {
++      if (scan_data->check_consistency &&
++          (dq->dq_dqb.dqb_curspace != dquot->dq_dqb.dqb_curspace ||
++           dq->dq_dqb.dqb_curinodes != dquot->dq_dqb.dqb_curinodes)) {
+               scan_data->usage_is_inconsistent = 1;
+               fprintf(stderr, "[QUOTA WARNING] Usage inconsistent for ID %u:"
+                       "actual (%lld, %lld) != expected (%lld, %lld)\n",
+@@ -568,8 +570,9 @@ static errcode_t quota_read_all_dquots(struct quota_handle *qh,
+       struct scan_dquots_data scan_data;
+       scan_data.quota_dict = qctx->quota_dict[qh->qh_type];
+-      scan_data.update_limits = update_limits;
+-      scan_data.update_usage = 0;
++      scan_data.check_consistency = 0;
++      scan_data.update_limits = 0;
++      scan_data.update_usage = 1;
+       return qh->qh_ops->scan_dquots(qh, scan_dquots_callback, &scan_data);
+ }
+@@ -659,6 +662,7 @@ errcode_t quota_compare_and_update(quota_ctx_t qctx, enum quota_type qtype,
+       scan_data.quota_dict = qctx->quota_dict[qtype];
+       scan_data.update_limits = 1;
+       scan_data.update_usage = 0;
++      scan_data.check_consistency = 1;
+       scan_data.usage_is_inconsistent = 0;
+       err = qh.qh_ops->scan_dquots(&qh, scan_dquots_callback, &scan_data);
+       if (err) {
+-- 
+2.16.1.72.g5be1f00a9a
+
diff --git a/debian/patches/e2image-fix-metadata-image-handling-on-big-endian-systems b/debian/patches/e2image-fix-metadata-image-handling-on-big-endian-systems
new file mode 100644 (file)
index 0000000..41b3407
--- /dev/null
@@ -0,0 +1,221 @@
+Description: e2image: fix metadata image handling on big endian systems
+ Currently e2image metadata image handling and creating is completely
+ broken on big endian systems. It just does not care about endianness at
+ all. This was uncovered With addition of i_bitmaps test, which is the
+ first test that actually tests e2image metadata image.
+ .
+ Fix it by making sure that all on-disk metadata that we write and read
+ to/from the metadata image is properly converted.
+From: Lukas Czerner <lczerner@redhat.com>
+Origin: upstream, commit:bfc1856029ff
+---
+ lib/ext2fs/imager.c     | 41 +++++++++++++++++++++++++++++++++++++++++
+ lib/ext2fs/inode.c      |  2 +-
+ lib/ext2fs/openfs.c     |  4 ++--
+ lib/ext2fs/rw_bitmaps.c |  4 ++--
+ misc/e2image.c          | 22 +++++++++++-----------
+ 5 files changed, 57 insertions(+), 16 deletions(-)
+
+diff --git a/lib/ext2fs/imager.c b/lib/ext2fs/imager.c
+index efb85b947..7fd06f743 100644
+--- a/lib/ext2fs/imager.c
++++ b/lib/ext2fs/imager.c
+@@ -195,6 +195,11 @@ errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd,
+       char            *buf, *cp;
+       ssize_t         actual;
+       errcode_t       retval;
++#ifdef WORDS_BIGENDIAN
++      unsigned int    groups_per_block;
++      struct          ext2_group_desc *gdp;
++      int             j;
++#endif
+       buf = malloc(fs->blocksize);
+       if (!buf)
+@@ -204,7 +209,17 @@ errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd,
+        * Write out the superblock
+        */
+       memset(buf, 0, fs->blocksize);
++#ifdef WORDS_BIGENDIAN
++      /*
++       * We're writing out superblock so let's convert
++       * it to little endian and then back if needed
++       */
++      ext2fs_swap_super(fs->super);
+       memcpy(buf, fs->super, SUPERBLOCK_SIZE);
++      ext2fs_swap_super(fs->super);
++#else
++      memcpy(buf, fs->super, SUPERBLOCK_SIZE);
++#endif
+       actual = write(fd, buf, fs->blocksize);
+       if (actual == -1) {
+               retval = errno;
+@@ -218,8 +233,34 @@ errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd,
+       /*
+        * Now write out the block group descriptors
+        */
++
+       cp = (char *) fs->group_desc;
++
++#ifdef WORDS_BIGENDIAN
++      /*
++       * Convert group descriptors to little endian and back
++       * if needed
++       */
++      groups_per_block = EXT2_DESC_PER_BLOCK(fs->super);
++      gdp = (struct ext2_group_desc *) cp;
++      for (j=0; j < groups_per_block*fs->desc_blocks; j++) {
++              gdp = ext2fs_group_desc(fs, fs->group_desc, j);
++              ext2fs_swap_group_desc2(fs, gdp);
++      }
++#endif
++
+       actual = write(fd, cp, fs->blocksize * fs->desc_blocks);
++
++
++#ifdef WORDS_BIGENDIAN
++      groups_per_block = EXT2_DESC_PER_BLOCK(fs->super);
++      gdp = (struct ext2_group_desc *) cp;
++      for (j=0; j < groups_per_block*fs->desc_blocks; j++) {
++              gdp = ext2fs_group_desc(fs, fs->group_desc, j);
++              ext2fs_swap_group_desc2(fs, gdp);
++      }
++#endif
++
+       if (actual == -1) {
+               retval = errno;
+               goto errout;
+diff --git a/lib/ext2fs/inode.c b/lib/ext2fs/inode.c
+index ad01a9fc5..015cfe4b5 100644
+--- a/lib/ext2fs/inode.c
++++ b/lib/ext2fs/inode.c
+@@ -770,7 +770,7 @@ errcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino,
+       }
+       if (fs->flags & EXT2_FLAG_IMAGE_FILE) {
+               inodes_per_block = fs->blocksize / EXT2_INODE_SIZE(fs->super);
+-              block_nr = fs->image_header->offset_inode / fs->blocksize;
++              block_nr = ext2fs_le32_to_cpu(fs->image_header->offset_inode) / fs->blocksize;
+               block_nr += (ino - 1) / inodes_per_block;
+               offset = ((ino - 1) % inodes_per_block) *
+                       EXT2_INODE_SIZE(fs->super);
+diff --git a/lib/ext2fs/openfs.c b/lib/ext2fs/openfs.c
+index 385d6e88c..532e70f7f 100644
+--- a/lib/ext2fs/openfs.c
++++ b/lib/ext2fs/openfs.c
+@@ -185,10 +185,10 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
+                                            fs->image_header);
+               if (retval)
+                       goto cleanup;
+-              if (fs->image_header->magic_number != EXT2_ET_MAGIC_E2IMAGE)
++              if (ext2fs_le32_to_cpu(fs->image_header->magic_number) != EXT2_ET_MAGIC_E2IMAGE)
+                       return EXT2_ET_MAGIC_E2IMAGE;
+               superblock = 1;
+-              block_size = fs->image_header->fs_blocksize;
++              block_size = ext2fs_le32_to_cpu(fs->image_header->fs_blocksize);
+       }
+       /*
+diff --git a/lib/ext2fs/rw_bitmaps.c b/lib/ext2fs/rw_bitmaps.c
+index 0b532dbf9..e86bacd53 100644
+--- a/lib/ext2fs/rw_bitmaps.c
++++ b/lib/ext2fs/rw_bitmaps.c
+@@ -253,7 +253,7 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
+       ext2fs_free_mem(&buf);
+       if (fs->flags & EXT2_FLAG_IMAGE_FILE) {
+-              blk = (fs->image_header->offset_inodemap / fs->blocksize);
++              blk = (ext2fs_le32_to_cpu(fs->image_header->offset_inodemap) / fs->blocksize);
+               ino_cnt = fs->super->s_inodes_count;
+               while (inode_bitmap && ino_cnt > 0) {
+                       retval = io_channel_read_blk64(fs->image_io, blk++,
+@@ -270,7 +270,7 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
+                       ino_itr += cnt;
+                       ino_cnt -= cnt;
+               }
+-              blk = (fs->image_header->offset_blockmap /
++              blk = (ext2fs_le32_to_cpu(fs->image_header->offset_blockmap) /
+                      fs->blocksize);
+               blk_cnt = EXT2_GROUPS_TO_CLUSTERS(fs->super,
+                                                 fs->group_desc_count);
+diff --git a/misc/e2image.c b/misc/e2image.c
+index 5a18bb41d..83ae6335b 100644
+--- a/misc/e2image.c
++++ b/misc/e2image.c
+@@ -240,7 +240,7 @@ static void write_image_file(ext2_filsys fs, int fd)
+       write_header(fd, NULL, sizeof(struct ext2_image_hdr), fs->blocksize);
+       memset(&hdr, 0, sizeof(struct ext2_image_hdr));
+-      hdr.offset_super = seek_relative(fd, 0);
++      hdr.offset_super = ext2fs_cpu_to_le32(seek_relative(fd, 0));
+       retval = ext2fs_image_super_write(fs, fd, 0);
+       if (retval) {
+               com_err(program_name, retval, "%s",
+@@ -248,7 +248,7 @@ static void write_image_file(ext2_filsys fs, int fd)
+               exit(1);
+       }
+-      hdr.offset_inode = seek_relative(fd, 0);
++      hdr.offset_inode = ext2fs_cpu_to_le32(seek_relative(fd, 0));
+       retval = ext2fs_image_inode_write(fs, fd,
+                                 (fd != 1) ? IMAGER_FLAG_SPARSEWRITE : 0);
+       if (retval) {
+@@ -257,7 +257,7 @@ static void write_image_file(ext2_filsys fs, int fd)
+               exit(1);
+       }
+-      hdr.offset_blockmap = seek_relative(fd, 0);
++      hdr.offset_blockmap = ext2fs_cpu_to_le32(seek_relative(fd, 0));
+       retval = ext2fs_image_bitmap_write(fs, fd, 0);
+       if (retval) {
+               com_err(program_name, retval, "%s",
+@@ -265,7 +265,7 @@ static void write_image_file(ext2_filsys fs, int fd)
+               exit(1);
+       }
+-      hdr.offset_inodemap = seek_relative(fd, 0);
++      hdr.offset_inodemap = ext2fs_cpu_to_le32(seek_relative(fd, 0));
+       retval = ext2fs_image_bitmap_write(fs, fd, IMAGER_FLAG_INODEMAP);
+       if (retval) {
+               com_err(program_name, retval, "%s",
+@@ -273,23 +273,23 @@ static void write_image_file(ext2_filsys fs, int fd)
+               exit(1);
+       }
+-      hdr.magic_number = EXT2_ET_MAGIC_E2IMAGE;
++      hdr.magic_number = ext2fs_cpu_to_le32(EXT2_ET_MAGIC_E2IMAGE);
+       strcpy(hdr.magic_descriptor, "Ext2 Image 1.0");
+       gethostname(hdr.fs_hostname, sizeof(hdr.fs_hostname));
+       strncpy(hdr.fs_device_name, device_name, sizeof(hdr.fs_device_name)-1);
+       hdr.fs_device_name[sizeof(hdr.fs_device_name) - 1] = 0;
+-      hdr.fs_blocksize = fs->blocksize;
++      hdr.fs_blocksize = ext2fs_cpu_to_le32(fs->blocksize);
+       if (stat(device_name, &st) == 0)
+-              hdr.fs_device = st.st_rdev;
++              hdr.fs_device = ext2fs_cpu_to_le32(st.st_rdev);
+       if (fstat(fd, &st) == 0) {
+-              hdr.image_device = st.st_dev;
+-              hdr.image_inode = st.st_ino;
++              hdr.image_device = ext2fs_cpu_to_le32(st.st_dev);
++              hdr.image_inode = ext2fs_cpu_to_le32(st.st_ino);
+       }
+       memcpy(hdr.fs_uuid, fs->super->s_uuid, sizeof(hdr.fs_uuid));
+-      hdr.image_time = time(0);
++      hdr.image_time = ext2fs_cpu_to_le32(time(0));
+       write_header(fd, &hdr, sizeof(struct ext2_image_hdr), fs->blocksize);
+ }
+@@ -1423,7 +1423,7 @@ static void install_image(char *device, char *image_fn, int type)
+       ext2fs_rewrite_to_io(fs, io);
+-      seek_set(fd, fs->image_header->offset_inode);
++      seek_set(fd, ext2fs_le32_to_cpu(fs->image_header->offset_inode));
+       retval = ext2fs_image_inode_read(fs, fd, 0);
+       if (retval) {
+-- 
+2.16.1.72.g5be1f00a9a
+
diff --git a/debian/patches/filefrag-avoid-temporary-buffer-overflow b/debian/patches/filefrag-avoid-temporary-buffer-overflow
new file mode 100644 (file)
index 0000000..0feecea
--- /dev/null
@@ -0,0 +1,27 @@
+Description: filefrag: avoid temporary buffer overflow
+ If an unknown flag is present in a FIEMAP extent, it is printed as a
+ hex value into a temporary buffer before adding it to the flags.  If
+ that unknown flag is over 0xfff then it will overflow the temporary
+ buffer.
+From: Andreas Dilger <adilger@dilger.ca>
+Origin: upstream, commit:17a1f2c19296
+---
+ misc/filefrag.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/misc/filefrag.c b/misc/filefrag.c
+index 9c57ab930..dc003931b 100644
+--- a/misc/filefrag.c
++++ b/misc/filefrag.c
+@@ -179,7 +179,7 @@ static void print_extent_info(struct fiemap_extent *fm_extent, int cur_ex,
+       print_flag(&fe_flags, FIEMAP_EXTENT_SHARED, flags, "shared,");
+       /* print any unknown flags as hex values */
+       for (mask = 1; fe_flags != 0 && mask != 0; mask <<= 1) {
+-              char hex[6];
++              char hex[sizeof(mask) * 2 + 4]; /* 2 chars/byte + 0x, + NUL */
+               if ((fe_flags & mask) == 0)
+                       continue;
+-- 
+2.16.1.72.g5be1f00a9a
+
diff --git a/debian/patches/libext2fs-add-sanity-checks-for-ea_in_inode b/debian/patches/libext2fs-add-sanity-checks-for-ea_in_inode
new file mode 100644 (file)
index 0000000..4e629c9
--- /dev/null
@@ -0,0 +1,68 @@
+Description: libext2fs: add sanity checks for ea_in_inode
+ An inode containing the value for an extended attribute (aka an
+ ea_in_inode) must not have the INLINE_DATA flag and must have the
+ EA_INODE flag set.  Enforcing this prevents e2fsck and debugfs crashes
+ caused by a maliciously crafted file system containing an inode which
+ has both the EA_INODE and INLINE_DATA flags set, and where that inode
+ has an extended attribute whose e_value_inum points to itself.
+From: Theodore Ts'o <tytso@mit.edu>
+Origin: upstream, commit:9db53e3fec34
+---
+ e2fsck/pass1.c            | 1 +
+ lib/ext2fs/ext2_err.et.in | 3 +++
+ lib/ext2fs/ext_attr.c     | 8 +++++++-
+ 3 files changed, 11 insertions(+), 1 deletion(-)
+
+diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c
+index fccd8816a..69b3f09e7 100644
+--- a/e2fsck/pass1.c
++++ b/e2fsck/pass1.c
+@@ -1542,6 +1542,7 @@ void e2fsck_pass1(e2fsck_t ctx)
+                       case EXT2_ET_NO_INLINE_DATA:
+                       case EXT2_ET_EXT_ATTR_CSUM_INVALID:
+                       case EXT2_ET_EA_BAD_VALUE_OFFSET:
++                      case EXT2_ET_EA_INODE_CORRUPTED:
+                               /* broken EA or no system.data EA; truncate */
+                               if (fix_problem(ctx, PR_1_INLINE_DATA_NO_ATTR,
+                                               &pctx)) {
+diff --git a/lib/ext2fs/ext2_err.et.in b/lib/ext2fs/ext2_err.et.in
+index ac96964d9..16abd23d8 100644
+--- a/lib/ext2fs/ext2_err.et.in
++++ b/lib/ext2fs/ext2_err.et.in
+@@ -542,4 +542,7 @@ ec EXT2_ET_CORRUPT_JOURNAL_SB,
+ ec    EXT2_ET_INODE_CORRUPTED,
+       "Inode is corrupted"
++ec    EXT2_ET_EA_INODE_CORRUPTED,
++      "Inode containing extended attribute value is corrupted"
++
+       end
+diff --git a/lib/ext2fs/ext_attr.c b/lib/ext2fs/ext_attr.c
+index 89c5f2cb6..81b067ad5 100644
+--- a/lib/ext2fs/ext_attr.c
++++ b/lib/ext2fs/ext_attr.c
+@@ -903,6 +903,7 @@ static errcode_t read_xattrs_from_buffer(struct ext2_xattr_handle *handle,
+                       memcpy(x->value, value_start + entry->e_value_offs,
+                              entry->e_value_size);
+               } else {
++                      struct ext2_inode *ea_inode;
+                       ext2_file_t ea_file;
+                       if (entry->e_value_offs != 0)
+@@ -920,7 +921,12 @@ static errcode_t read_xattrs_from_buffer(struct ext2_xattr_handle *handle,
+                       if (err)
+                               return err;
+-                      if (ext2fs_file_get_size(ea_file) !=
++                      ea_inode = ext2fs_file_get_inode(ea_file);
++                      if ((ea_inode->i_flags & EXT4_INLINE_DATA_FL) ||
++                          !(ea_inode->i_flags & EXT4_EA_INODE_FL) ||
++                          ea_inode->i_links_count == 0)
++                              err = EXT2_ET_EA_INODE_CORRUPTED;
++                      else if (ext2fs_file_get_size(ea_file) !=
+                           entry->e_value_size)
+                               err = EXT2_ET_EA_BAD_VALUE_SIZE;
+                       else
+-- 
+2.16.1.72.g5be1f00a9a
+
diff --git a/debian/patches/series b/debian/patches/series
new file mode 100644 (file)
index 0000000..e0639d5
--- /dev/null
@@ -0,0 +1,4 @@
+filefrag-avoid-temporary-buffer-overflow
+e2fsck-adjust-quota-counters-when-clearing-orphaned-inodes
+libext2fs-add-sanity-checks-for-ea_in_inode
+e2image-fix-metadata-image-handling-on-big-endian-systems
diff --git a/tests/f_orphquot/expect b/tests/f_orphquot/expect
deleted file mode 100644 (file)
index 90a7813..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-Clearing orphaned inode 12 (uid=0, gid=0, mode=0100644, size=3842048)
-Pass 1: Checking inodes, blocks, and sizes
-Pass 2: Checking directory structure
-Pass 3: Checking directory connectivity
-Pass 4: Checking reference counts
-Pass 5: Checking group summary information
-
-test_filesystem: ***** FILE SYSTEM WAS MODIFIED *****
-test_filesystem: 11/512 files (9.1% non-contiguous), 1070/2048 blocks
-Exit status is 0
diff --git a/tests/f_orphquot/image.bz2 b/tests/f_orphquot/image.bz2
deleted file mode 100644 (file)
index 44c8318..0000000
Binary files a/tests/f_orphquot/image.bz2 and /dev/null differ
diff --git a/tests/f_orphquot/script b/tests/f_orphquot/script
deleted file mode 100644 (file)
index acdf567..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-test_description="e2fsck with quota and orphan inodes"
-OUT=$test_name.log
-EXP=$test_dir/expect
-
-bzip2 -dc < $test_dir/image.bz2 > $TMPFILE
-
-rm -rf $OUT
-$FSCK -f -y -N test_filesystem $TMPFILE > $OUT.new 2>&1
-status=$?
-echo Exit status is $status >> $OUT.new
-sed -f $cmd_dir/filter.sed $OUT.new >> $OUT
-rm -f $OUT.new
-
-cmp -s $OUT $EXP
-status=$?
-
-if [ "$status" = 0 ] ; then
-       echo "$test_name: $test_description: ok"
-       touch $test_name.ok
-else
-       echo "$test_name: $test_description: failed"
-       diff $DIFF_OPTS $EXP $OUT > $test_name.failed
-       rm -f tmp_expect
-fi
-
-unset IMAGE FSCK_OPT OUT EXP