From: Darrick J. Wong <djwong@xxxxxxxxxx> Don't obfuscate the directory and attribute names of metadata inodes. Signed-off-by: "Darrick J. Wong" <djwong@xxxxxxxxxx> Reviewed-by: Christoph Hellwig <hch@xxxxxx> --- db/metadump.c | 385 +++++++++++++++++++++++++++------------------------------ 1 file changed, 183 insertions(+), 202 deletions(-) diff --git a/db/metadump.c b/db/metadump.c index 5c57c1293a53cb..144ebfbfe2a90e 100644 --- a/db/metadump.c +++ b/db/metadump.c @@ -1056,10 +1056,26 @@ generate_obfuscated_name( free(orig_name); } +static inline bool +is_metadata_ino( + struct xfs_dinode *dip) +{ + if (!xfs_has_metadir(mp) || dip->di_version < 3) + return false; + return dip->di_flags2 & cpu_to_be64(XFS_DIFLAG2_METADATA); +} + +static inline bool +want_obfuscate_dirents(bool is_meta) +{ + return metadump.obfuscate && !is_meta; +} + static void process_sf_dir( struct xfs_dinode *dip) { + bool is_meta = is_metadata_ino(dip); struct xfs_dir2_sf_hdr *sfp; xfs_dir2_sf_entry_t *sfep; uint64_t ino_dir_size; @@ -1105,7 +1121,7 @@ process_sf_dir( (char *)sfp); } - if (metadump.obfuscate) + if (want_obfuscate_dirents(is_meta)) generate_obfuscated_name( libxfs_dir2_sf_get_ino(mp, sfp, sfep), namelen, &sfep->name[0]); @@ -1201,7 +1217,8 @@ maybe_obfuscate_pptr( uint8_t *name, int namelen, const void *value, - int valuelen) + int valuelen, + bool is_meta) { unsigned char old_name[MAXNAMELEN]; struct remap_ent *remap; @@ -1210,7 +1227,7 @@ maybe_obfuscate_pptr( xfs_ino_t parent_ino; int error; - if (!metadump.obfuscate) + if (!metadump.obfuscate || is_meta) return; if (!(attr_flags & XFS_ATTR_PARENT)) @@ -1274,9 +1291,10 @@ want_obfuscate_attr( const void *name, unsigned int namelen, const void *value, - unsigned int valuelen) + unsigned int valuelen, + bool is_meta) { - if (!metadump.obfuscate) + if (!metadump.obfuscate || is_meta) return false; /* @@ -1289,15 +1307,15 @@ want_obfuscate_attr( return true; } +/* + * Obfuscate the attr names and fill the actual values with 'v' (to see a valid + * string length, as opposed to NULLs). + */ static void process_sf_attr( struct xfs_dinode *dip) { - /* - * with extended attributes, obfuscate the names and fill the actual - * values with 'v' (to see a valid string length, as opposed to NULLs) - */ - + bool is_meta = is_metadata_ino(dip); struct xfs_attr_sf_hdr *hdr = XFS_DFORK_APTR(dip); struct xfs_attr_sf_entry *asfep = libxfs_attr_sf_firstentry(hdr); int ino_attr_size; @@ -1338,9 +1356,9 @@ process_sf_attr( if (asfep->flags & XFS_ATTR_PARENT) { maybe_obfuscate_pptr(asfep->flags, name, namelen, - value, asfep->valuelen); + value, asfep->valuelen, is_meta); } else if (want_obfuscate_attr(asfep->flags, name, namelen, - value, asfep->valuelen)) { + value, asfep->valuelen, is_meta)) { generate_obfuscated_name(0, asfep->namelen, name); memset(value, 'v', asfep->valuelen); } @@ -1442,7 +1460,8 @@ static void process_dir_data_block( char *block, xfs_fileoff_t offset, - int is_block_format) + int is_block_format, + bool is_meta) { /* * we have to rely on the fileoffset and signature of the block to @@ -1549,7 +1568,7 @@ process_dir_data_block( dir_offset) return; - if (metadump.obfuscate) + if (want_obfuscate_dirents(is_meta)) generate_obfuscated_name(be64_to_cpu(dep->inumber), dep->namelen, &dep->name[0]); dir_offset += length; @@ -1574,7 +1593,8 @@ process_symlink_block( xfs_fsblock_t s, xfs_filblks_t c, typnm_t btype, - xfs_fileoff_t last) + xfs_fileoff_t last, + bool is_meta) { struct bbmap map; char *link; @@ -1599,7 +1619,7 @@ process_symlink_block( if (xfs_has_crc((mp))) link += sizeof(struct xfs_dsymlink_hdr); - if (metadump.obfuscate) + if (want_obfuscate_dirents(is_meta)) obfuscate_path_components(link, XFS_SYMLINK_BUF_SPACE(mp, mp->m_sb.sb_blocksize)); if (metadump.zero_stale_data) { @@ -1650,7 +1670,8 @@ add_remote_vals( static void process_attr_block( char *block, - xfs_fileoff_t offset) + xfs_fileoff_t offset, + bool is_meta) { struct xfs_attr_leafblock *leaf; struct xfs_attr3_icleaf_hdr hdr; @@ -1730,10 +1751,10 @@ process_attr_block( if (entry->flags & XFS_ATTR_PARENT) { maybe_obfuscate_pptr(entry->flags, name, local->namelen, value, - valuelen); + valuelen, is_meta); } else if (want_obfuscate_attr(entry->flags, name, local->namelen, value, - valuelen)) { + valuelen, is_meta)) { generate_obfuscated_name(0, local->namelen, name); memset(value, 'v', valuelen); @@ -1759,7 +1780,7 @@ process_attr_block( /* do not obfuscate obviously busted pptr */ add_remote_vals(be32_to_cpu(remote->valueblk), be32_to_cpu(remote->valuelen)); - } else if (metadump.obfuscate) { + } else if (want_obfuscate_dirents(is_meta)) { generate_obfuscated_name(0, remote->namelen, &remote->name[0]); add_remote_vals(be32_to_cpu(remote->valueblk), @@ -1792,7 +1813,8 @@ process_single_fsb_objects( xfs_fsblock_t s, xfs_filblks_t c, typnm_t btype, - xfs_fileoff_t last) + xfs_fileoff_t last, + bool is_meta) { int rval = 1; char *dp; @@ -1862,12 +1884,13 @@ process_single_fsb_objects( process_dir_leaf_block(dp); } else { process_dir_data_block(dp, o, - last == mp->m_dir_geo->fsbcount); + last == mp->m_dir_geo->fsbcount, + is_meta); } iocur_top->need_crc = 1; break; case TYP_ATTR: - process_attr_block(dp, o); + process_attr_block(dp, o, is_meta); iocur_top->need_crc = 1; break; default: @@ -1900,7 +1923,8 @@ process_multi_fsb_dir( xfs_fsblock_t s, xfs_filblks_t c, typnm_t btype, - xfs_fileoff_t last) + xfs_fileoff_t last, + bool is_meta) { char *dp; int rval = 1; @@ -1944,7 +1968,8 @@ process_multi_fsb_dir( process_dir_leaf_block(dp); } else { process_dir_data_block(dp, o, - last == mp->m_dir_geo->fsbcount); + last == mp->m_dir_geo->fsbcount, + is_meta); } iocur_top->need_crc = 1; write: @@ -1963,6 +1988,38 @@ process_multi_fsb_dir( return rval; } +static typnm_t +ifork_data_type( + struct xfs_dinode *dip, + int whichfork) +{ + xfs_ino_t ino = be64_to_cpu(dip->di_ino); + + if (whichfork == XFS_ATTR_FORK) + return TYP_ATTR; + + switch (be16_to_cpu(dip->di_mode) & S_IFMT) { + case S_IFDIR: + return TYP_DIR2; + case S_IFLNK: + return TYP_SYMLINK; + case S_IFREG: + if (ino == mp->m_sb.sb_rbmino) + return TYP_RTBITMAP; + if (ino == mp->m_sb.sb_rsumino) + return TYP_RTSUMMARY; + if (ino == mp->m_sb.sb_uquotino) + return TYP_DQBLK; + if (ino == mp->m_sb.sb_gquotino) + return TYP_DQBLK; + if (ino == mp->m_sb.sb_pquotino) + return TYP_DQBLK; + return TYP_DATA; + default: + return TYP_NONE; + } +} + static bool is_multi_fsb_object( struct xfs_mount *mp, @@ -1981,13 +2038,14 @@ process_multi_fsb_objects( xfs_fsblock_t s, xfs_filblks_t c, typnm_t btype, - xfs_fileoff_t last) + xfs_fileoff_t last, + bool is_meta) { switch (btype) { case TYP_DIR2: - return process_multi_fsb_dir(o, s, c, btype, last); + return process_multi_fsb_dir(o, s, c, btype, last, is_meta); case TYP_SYMLINK: - return process_symlink_block(o, s, c, btype, last); + return process_symlink_block(o, s, c, btype, last, is_meta); default: print_warning("bad type for multi-fsb object %d", btype); return 1; @@ -1997,10 +2055,13 @@ process_multi_fsb_objects( /* inode copy routines */ static int process_bmbt_reclist( - xfs_bmbt_rec_t *rp, - int numrecs, - typnm_t btype) + struct xfs_dinode *dip, + int whichfork, + struct xfs_bmbt_rec *rp, + int numrecs) { + bool is_meta = is_metadata_ino(dip); + typnm_t btype = ifork_data_type(dip, whichfork); int i; xfs_fileoff_t o, op = NULLFILEOFF; xfs_fsblock_t s; @@ -2009,7 +2070,6 @@ process_bmbt_reclist( xfs_fileoff_t last; xfs_agnumber_t agno; xfs_agblock_t agbno; - bool is_multi_fsb = is_multi_fsb_object(mp, btype); int rval = 1; if (btype == TYP_DATA) @@ -2077,12 +2137,12 @@ process_bmbt_reclist( } /* multi-extent blocks require special handling */ - if (is_multi_fsb) + if (is_multi_fsb_object(mp, btype)) rval = process_multi_fsb_objects(o, s, c, btype, - last); + last, is_meta); else rval = process_single_fsb_objects(o, s, c, btype, - last); + last, is_meta); if (!rval) break; } @@ -2090,6 +2150,11 @@ process_bmbt_reclist( return rval; } +struct scan_bmap { + struct xfs_dinode *dip; + int whichfork; +}; + static int scanfunc_bmap( struct xfs_btree_block *block, @@ -2097,8 +2162,9 @@ scanfunc_bmap( xfs_agblock_t agbno, int level, typnm_t btype, - void *arg) /* ptr to itype */ + void *arg) { + struct scan_bmap *sbm = arg; int i; xfs_bmbt_ptr_t *pp; int nrecs; @@ -2113,8 +2179,8 @@ scanfunc_bmap( typtab[btype].name, agno, agbno); return 1; } - return process_bmbt_reclist(xfs_bmbt_rec_addr(mp, block, 1), - nrecs, *(typnm_t*)arg); + return process_bmbt_reclist(sbm->dip, sbm->whichfork, + xfs_bmbt_rec_addr(mp, block, 1), nrecs); } if (nrecs > mp->m_bmap_dmxr[1]) { @@ -2149,23 +2215,17 @@ scanfunc_bmap( static int process_btinode( struct xfs_dinode *dip, - typnm_t itype) + int whichfork) { - xfs_bmdr_block_t *dib; - int i; - xfs_bmbt_ptr_t *pp; - int level; - int nrecs; + struct xfs_bmdr_block *dib = + (struct xfs_bmdr_block *)XFS_DFORK_PTR(dip, whichfork); + int level = be16_to_cpu(dib->bb_level); + int nrecs = be16_to_cpu(dib->bb_numrecs); int maxrecs; - int whichfork; - typnm_t btype; - - whichfork = (itype == TYP_ATTR) ? XFS_ATTR_FORK : XFS_DATA_FORK; - btype = (itype == TYP_ATTR) ? TYP_BMAPBTA : TYP_BMAPBTD; - - dib = (xfs_bmdr_block_t *)XFS_DFORK_PTR(dip, whichfork); - level = be16_to_cpu(dib->bb_level); - nrecs = be16_to_cpu(dib->bb_numrecs); + typnm_t btype = (whichfork == XFS_ATTR_FORK) ? + TYP_BMAPBTA : TYP_BMAPBTD; + xfs_bmbt_ptr_t *pp; + int i; if (level > XFS_BM_MAXLEVELS(mp, whichfork)) { if (metadump.show_warnings) @@ -2176,8 +2236,8 @@ process_btinode( } if (level == 0) { - return process_bmbt_reclist(xfs_bmdr_rec_addr(dib, 1), - nrecs, itype); + return process_bmbt_reclist(dip, whichfork, + xfs_bmdr_rec_addr(dib, 1), nrecs); } maxrecs = libxfs_bmdr_maxrecs(XFS_DFORK_SIZE(dip, mp, whichfork), 0); @@ -2204,6 +2264,10 @@ process_btinode( } for (i = 0; i < nrecs; i++) { + struct scan_bmap sbm = { + .dip = dip, + .whichfork = whichfork, + }; xfs_agnumber_t ag; xfs_agblock_t bno; @@ -2220,7 +2284,7 @@ process_btinode( continue; } - if (!scan_btree(ag, bno, level, btype, &itype, scanfunc_bmap)) + if (!scan_btree(ag, bno, level, btype, &sbm, scanfunc_bmap)) return 0; } return 1; @@ -2229,19 +2293,13 @@ process_btinode( static int process_exinode( struct xfs_dinode *dip, - typnm_t itype) + int whichfork) { - int whichfork; - int used; - xfs_extnum_t nex, max_nex; + xfs_extnum_t max_nex = xfs_iext_max_nextents( + xfs_dinode_has_large_extent_counts(dip), whichfork); + xfs_extnum_t nex = xfs_dfork_nextents(dip, whichfork); + int used = nex * sizeof(struct xfs_bmbt_rec); - whichfork = (itype == TYP_ATTR) ? XFS_ATTR_FORK : XFS_DATA_FORK; - - nex = xfs_dfork_nextents(dip, whichfork); - max_nex = xfs_iext_max_nextents( - xfs_dinode_has_large_extent_counts(dip), - whichfork); - used = nex * sizeof(xfs_bmbt_rec_t); if (nex > max_nex || used > XFS_DFORK_SIZE(dip, mp, whichfork)) { if (metadump.show_warnings) print_warning("bad number of extents %llu in inode %lld", @@ -2257,52 +2315,52 @@ process_exinode( XFS_DFORK_SIZE(dip, mp, whichfork) - used); - return process_bmbt_reclist((xfs_bmbt_rec_t *)XFS_DFORK_PTR(dip, - whichfork), nex, itype); + return process_bmbt_reclist(dip, whichfork, + (struct xfs_bmbt_rec *)XFS_DFORK_PTR(dip, whichfork), + nex); } static int process_inode_data( - struct xfs_dinode *dip, - typnm_t itype) + struct xfs_dinode *dip) { switch (dip->di_format) { - case XFS_DINODE_FMT_LOCAL: - if (!(metadump.obfuscate || metadump.zero_stale_data)) - break; + case XFS_DINODE_FMT_LOCAL: + if (!(metadump.obfuscate || metadump.zero_stale_data)) + break; - /* - * If the fork size is invalid, we can't safely do - * anything with this fork. Leave it alone to preserve - * the information for diagnostic purposes. - */ - if (XFS_DFORK_DSIZE(dip, mp) > XFS_LITINO(mp)) { - print_warning( + /* + * If the fork size is invalid, we can't safely do anything + * with this fork. Leave it alone to preserve the information + * for diagnostic purposes. + */ + if (XFS_DFORK_DSIZE(dip, mp) > XFS_LITINO(mp)) { + print_warning( "Invalid data fork size (%d) in inode %llu, preserving contents!", - XFS_DFORK_DSIZE(dip, mp), - (long long)metadump.cur_ino); - break; - } + XFS_DFORK_DSIZE(dip, mp), + (long long)metadump.cur_ino); + break; + } - switch (itype) { - case TYP_DIR2: - process_sf_dir(dip); - break; + switch (be16_to_cpu(dip->di_mode) & S_IFMT) { + case S_IFDIR: + process_sf_dir(dip); + break; - case TYP_SYMLINK: - process_sf_symlink(dip); - break; + case S_IFLNK: + process_sf_symlink(dip); + break; - default: - break; - } + default: break; + } + break; - case XFS_DINODE_FMT_EXTENTS: - return process_exinode(dip, itype); + case XFS_DINODE_FMT_EXTENTS: + return process_exinode(dip, XFS_DATA_FORK); - case XFS_DINODE_FMT_BTREE: - return process_btinode(dip, itype); + case XFS_DINODE_FMT_BTREE: + return process_btinode(dip, XFS_DATA_FORK); } return 1; } @@ -2375,28 +2433,22 @@ process_inode( /* copy appropriate data fork metadata */ switch (be16_to_cpu(dip->di_mode) & S_IFMT) { - case S_IFDIR: - rval = process_inode_data(dip, TYP_DIR2); - if (dip->di_format == XFS_DINODE_FMT_LOCAL) - need_new_crc = true; - break; - case S_IFLNK: - rval = process_inode_data(dip, TYP_SYMLINK); - if (dip->di_format == XFS_DINODE_FMT_LOCAL) - need_new_crc = true; - break; - case S_IFREG: - rval = process_inode_data(dip, TYP_DATA); - break; - case S_IFIFO: - case S_IFCHR: - case S_IFBLK: - case S_IFSOCK: - process_dev_inode(dip); + case S_IFDIR: + case S_IFLNK: + case S_IFREG: + rval = process_inode_data(dip); + if (dip->di_format == XFS_DINODE_FMT_LOCAL) need_new_crc = true; - break; - default: - break; + break; + case S_IFIFO: + case S_IFCHR: + case S_IFBLK: + case S_IFSOCK: + process_dev_inode(dip); + need_new_crc = true; + break; + default: + break; } nametable_clear(); if (!rval) @@ -2406,20 +2458,17 @@ process_inode( if (XFS_DFORK_DSIZE(dip, mp) < XFS_LITINO(mp)) { attr_data.remote_val_count = 0; switch (dip->di_aformat) { - case XFS_DINODE_FMT_LOCAL: - need_new_crc = true; - if (metadump.obfuscate || - metadump.zero_stale_data) - process_sf_attr(dip); - break; - - case XFS_DINODE_FMT_EXTENTS: - rval = process_exinode(dip, TYP_ATTR); - break; - - case XFS_DINODE_FMT_BTREE: - rval = process_btinode(dip, TYP_ATTR); - break; + case XFS_DINODE_FMT_LOCAL: + need_new_crc = true; + if (metadump.obfuscate || metadump.zero_stale_data) + process_sf_attr(dip); + break; + case XFS_DINODE_FMT_EXTENTS: + rval = process_exinode(dip, XFS_ATTR_FORK); + break; + case XFS_DINODE_FMT_BTREE: + rval = process_btinode(dip, XFS_ATTR_FORK); + break; } nametable_clear(); } @@ -2796,70 +2845,6 @@ scan_ag( return rval; } -static int -copy_ino( - xfs_ino_t ino, - typnm_t itype) -{ - xfs_agnumber_t agno; - xfs_agblock_t agbno; - xfs_agino_t agino; - int offset; - int rval = 1; - - if (ino == 0 || ino == NULLFSINO) - return 1; - - agno = XFS_INO_TO_AGNO(mp, ino); - agino = XFS_INO_TO_AGINO(mp, ino); - agbno = XFS_AGINO_TO_AGBNO(mp, agino); - offset = XFS_AGINO_TO_OFFSET(mp, agino); - - if (agno >= mp->m_sb.sb_agcount || agbno >= mp->m_sb.sb_agblocks || - offset >= mp->m_sb.sb_inopblock) { - if (metadump.show_warnings) - print_warning("invalid %s inode number (%lld)", - typtab[itype].name, (long long)ino); - return 1; - } - - push_cur(); - set_cur(&typtab[TYP_INODE], XFS_AGB_TO_DADDR(mp, agno, agbno), - blkbb, DB_RING_IGN, NULL); - if (iocur_top->data == NULL) { - print_warning("cannot read %s inode %lld", - typtab[itype].name, (long long)ino); - rval = !metadump.stop_on_read_error; - goto pop_out; - } - off_cur(offset << mp->m_sb.sb_inodelog, mp->m_sb.sb_inodesize); - - metadump.cur_ino = ino; - rval = process_inode_data(iocur_top->data, itype); -pop_out: - pop_cur(); - return rval; -} - - -static int -copy_sb_inodes(void) -{ - if (!copy_ino(mp->m_sb.sb_rbmino, TYP_RTBITMAP)) - return 0; - - if (!copy_ino(mp->m_sb.sb_rsumino, TYP_RTSUMMARY)) - return 0; - - if (!copy_ino(mp->m_sb.sb_uquotino, TYP_DQBLK)) - return 0; - - if (!copy_ino(mp->m_sb.sb_gquotino, TYP_DQBLK)) - return 0; - - return copy_ino(mp->m_sb.sb_pquotino, TYP_DQBLK); -} - static int copy_log(void) { @@ -3296,10 +3281,6 @@ metadump_f( } } - /* copy realtime and quota inode contents */ - if (!exitcode) - exitcode = !copy_sb_inodes(); - /* copy log */ if (!exitcode && !(metadump.version == 1 && metadump.external_log)) exitcode = !copy_log();