On 12/13/2012 08:56 PM, Eric Sandeen wrote:
> On 4/9/12 11:34 PM, Eric Sandeen wrote:
>> xfs_metadump currently obfuscates entire symlinks without regard
>> to path components; this can lead to a corrupt image when restoring
>> a metadump containing extremely long symlinks:
>>
>> Phase 3 - for each AG...
>> - scan and clear agi unlinked lists...
>> - process known inodes and perform inode discovery...
>> - agno = 0
>> component of symlink in inode 145 too long
>> problem with symbolic link in inode 145
>> cleared inode 145
>> ... <more trail of woe>
>>
>> Fix this by consolidating symlink obfuscation into a new
>> function which obfuscates one path component at a time.
>>
>> Signed-off-by: Eric Sandeen <sandeen@xxxxxxxxxx>
>
> ping? :)
You know, these things take time.
What you have looks good to me, but I rewrote it, below. :)
Even if you don't change anything...
Reviewed-by: Alex Elder <elder@xxxxxxxxxxx>
>> ---
>>
>> Yes, I need to do an xfstest for this. metadumping a filesystem
>> after fsstressing it works well.
>>
>> diff --git a/db/metadump.c b/db/metadump.c
>> index c5ffddb..9f15d9e 100644
>> --- a/db/metadump.c
>> +++ b/db/metadump.c
>> @@ -956,6 +956,40 @@ obfuscate_sf_dir(
>> }
>>
>> static void
>> +obfuscate_path_components(
>> + char *buf,
>> + __uint64_t len)
>> +{
>> + uchar_t *comp;
>> + xfs_dahash_t hash;
>> +
>> + comp = (uchar_t *)buf;
>> + while (comp < (uchar_t *)buf + len) {
>> + char *slash;
>> + int namelen;
>> +
Maybe instead of handling it later, you could check for
leading and duplicate slashes here:
while (*comp == '/')
comp++;
In fact, maybe it could be more like:
while (*comp == '/')
comp++;
slash = strchrnul((char *) comp, '/');
namlen = slash - comp;
if (!namelen)
return;
hash = libxfs_da_hashname(comp, namelen);
obfuscate_name(hash, namelen, comp);
comp += namelen + 1;
Note that these all assume the original buffer is NUL-terminated
(yours did too).
>> + /* find slash at end of this component */
>> + slash = strchr((char *)comp, '/');
>> + if (!slash) {
>> + /* last (or single) component */
>> + namelen = strlen((char *)comp);
>> + hash = libxfs_da_hashname(comp, namelen);
>> + obfuscate_name(hash, namelen, comp);
>> + break;
>> + }
>> + namelen = slash - (char *)comp;
>> + /* handle leading or consecutive slashes */
>> + if (!namelen) {
>> + comp++;
>> + continue;
>> + }
>> + hash = libxfs_da_hashname(comp, namelen);
>> + obfuscate_name(hash, namelen, comp);
>> + comp += namelen + 1;
>> + }
>> +}
>> +
>> +static void
>> obfuscate_sf_symlink(
>> xfs_dinode_t *dip)
>> {
>> @@ -971,8 +1005,7 @@ obfuscate_sf_symlink(
>> }
>>
>> buf = (char *)XFS_DFORK_DPTR(dip);
>> - while (len > 0)
>> - buf[--len] = random() % 127 + 1;
>> + obfuscate_path_components(buf, len);
>> }
>>
>> static void
>> @@ -1176,11 +1209,8 @@ obfuscate_symlink_blocks(
>> char *block,
>> xfs_dfilblks_t count)
>> {
>> - int i;
>> -
>> count <<= mp->m_sb.sb_blocklog;
>> - for (i = 0; i < count; i++)
>> - block[i] = random() % 127 + 1;
>> + obfuscate_path_components(block, count);
This is interesting. Is there any guarantee that the hashed
result here will match the hashed target file? I don't think
there is, necessarily (mostly if the target is subject to a
hash collision). It's a corner case though so it can most
likely be ignored.
>> }
>>
>> #define MAX_REMOTE_VALS 4095
>>
>> _______________________________________________
>> xfs mailing list
>> xfs@xxxxxxxxxxx
>> http://oss.sgi.com/mailman/listinfo/xfs
>>
>
> _______________________________________________
> xfs mailing list
> xfs@xxxxxxxxxxx
> http://oss.sgi.com/mailman/listinfo/xfs
>
|