lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20210107234116.6190-1-magnani@ieee.org>
Date:   Thu,  7 Jan 2021 17:41:15 -0600
From:   Steve Magnani <magnani@...e.org>
To:     Jan Kara <jack@...e.com>
Cc:     linux-kernel@...r.kernel.org,
        "Steven J . Magnani" <magnani@...e.org>
Subject: [PATCH 0/1] udf: fix silent AED tagLocation corruption

From: Steven J. Magnani <magnani@...e.org>

Certain scenarios involving enlargement of a large and/or fragmented file
result in corruption of the file's Allocation Extent Descriptor tag.
Once this has happened, attempts to read the file in Windows 10 fail with
"Data error (cyclic redundancy check)". A "chkdsk /f" in Windows causes
extents of the file described by the corrupted AED (and any subsequent
chained AEDs) to be truncated.

No problems are noted when the file is accessed in Linux.

The script below creates a toy UDF filesystem to illustrate the problem.
The filesystem can be dd'd to a flash disk partition of the same size
to observe how Windows handles the corruption.
---
#!/bin/bash

# Tool to illustrate / test fix for bug in UDF driver
# that can result in corruption of Allocation Extent Descriptor tag location
# Developed using mkudffs from udftools 2.2.

# Terminology:
#  LSN == Logical Sector Number (media / volume relative)
#  LBN == Logical Block Number  (UDF partition relative)


TEST_UDFFS=/tmp/test.udf

# Changing these may alter filesystem layout and/or invalidate the test
UDFFS_SIZE=1M        # --size argument to 'truncate' command
UDF_BLOCKSIZE=512
PD_LSN=98            # Expected UDF Partition Descriptor location
AED_LSN=1343         # Location of Allocation Extent Descriptor under test

require()
{
    local APP_REALPATH=`which $1`
    local PACKAGE_NAME=${2:-$1}
    if [ -z "$APP_REALPATH" ] ; then
        echo This test requires $1. Please install the $PACKAGE_NAME package.
        exit 1
    fi 
}

# "Quiet" dd command
ddq()
{
    dd $* 2> /dev/null
}

# Extract a 16-bit little-endian unsigned value at a specified byte offset ($2)
# of a specified LSN ($1)
# 
extract16()
{
    local value=`ddq if=$TEST_UDFFS bs=$UDF_BLOCKSIZE skip=$1 count=1 | ddq bs=1 skip=$2 count=2 | od -A none -t u2 --endian=little`
    [ -z "$value" ] && value=0   # Fail in a sane manner

    echo -n $value
}

# Extract a 32-bit little-endian unsigned value at a specified byte offset ($2)
# of a specified LSN ($1)
# 
extract32()
{
    local value=`ddq if=$TEST_UDFFS bs=$UDF_BLOCKSIZE skip=$1 count=1 | ddq bs=1 skip=$2 count=4 | od -A none -t u4 --endian=little`
    [ -z "$value" ] && value=0   # Fail in a sane manner

    echo -n $value
}


# $1 = LSN
# $2 = Expected tag ID value (decimal) - i.e., 266 for EFE
require_tag_id()
{
    local found_tag=`extract16 $1 0`

    if [ $found_tag -ne $2 ] ; then
        echo Expected tag $2 in LSN $1, found $found_tag.
        echo Unexpected test conditions - results must be verified manually
        exit 1
    fi
}

gen_provoker_data()
{
    ddq if=/dev/zero bs=$UDF_BLOCKSIZE count=1 of=/tmp/hole.$$

    openssl rand 172032
    cat /tmp/hole.$$
    openssl rand 149504
    cat /tmp/hole.$$
    openssl rand 22528
    cat /tmp/hole.$$
    openssl rand 2048
    cat /tmp/hole.$$
    openssl rand 4096
    cat /tmp/hole.$$
    openssl rand 4096
    cat /tmp/hole.$$
    openssl rand 8192
    cat /tmp/hole.$$
    openssl rand 184320
    cat /tmp/hole.$$
    openssl rand 131072

    rm -f /tmp/hole.$$
}

# $1 == loopback UDF filesystem to create
make_test_udf()
{
    rm -f $1
    truncate --size=$UDFFS_SIZE $1
    mkudffs --label=SPARSE --uid=$UID --blocksize=$UDF_BLOCKSIZE $1 > /dev/null

    mkdir -p /tmp/testudf.mnt
    echo Mounting test UDF filesystem. Please provide the root password if prompted.
    sudo mount $1 /tmp/testudf.mnt
    cp --sparse=always /tmp/provoker.$$ /tmp/testudf.mnt/provoker
    sync
    sudo umount /tmp/testudf.mnt
    rmdir /tmp/testudf.mnt
    echo Test UDF filesystem generated in $1.
}

### MAIN

require openssl
require mkudffs  udftools

if [ -e $TEST_UDFFS ] ; then
    echo $TEST_UDFFS already exists - please dismount and remove it
    exit 1
fi

gen_provoker_data > /tmp/provoker.$$
make_test_udf $TEST_UDFFS

# Verify hardcoded LSNs involved in testing
require_tag_id  $PD_LSN   5  # PD
require_tag_id $AED_LSN 258  # AED

LBN_BASE=`extract32 $PD_LSN 188`   # Partition Starting Location
AED_LBN=`expr $AED_LSN - $LBN_BASE`
AED_TAG_LOCATION=`extract32 $AED_LSN 12`

if [ $AED_TAG_LOCATION -ne $AED_LBN ] ; then
    echo Test FAILED: expected AED tag location $AED_LBN, actual is $AED_TAG_LOCATION
    exit 1
else
    echo Test PASSED. AED tag location field is correct.
fi
------------------------------------------------------------------------
 Steven J. Magnani               "I claim this network for MARS!
                                  Earthling, return my space modulator!"
 #include <standard.disclaimer>

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ