Merge pull request #449 from PartialVolume/HPA_DCO_006

HPA_DCO_006 - Add HPA/DCO capability
This commit is contained in:
PartialVolume
2023-03-10 00:52:14 +00:00
committed by GitHub
4 changed files with 108 additions and 27 deletions

View File

@@ -818,13 +818,13 @@ void nwipe_gui_select( int count, nwipe_context_t** c )
case HPA_ENABLED:
wprintw( main_window, " " );
wattron( main_window, COLOR_PAIR( 9 ) );
wprintw( main_window, " HPA/DCO Warning, hidden area detected " );
wprintw( main_window, " HPA/DCO hidden area detected !! " );
wattroff( main_window, COLOR_PAIR( 9 ) );
break;
case HPA_DISABLED:
wprintw( main_window, " " );
wprintw( main_window, " HPA/DCO GOOD, no hidden areas " );
wprintw( main_window, " HPA/DCO Excellent NO hidden areas " );
break;
case HPA_UNKNOWN:

View File

@@ -188,7 +188,7 @@ int hpa_dco_status( nwipe_context_t* ptr )
if( strstr( result, "SG_IO: bad/missing sense data" ) != 0 )
{
c->HPA_status = HPA_UNKNOWN;
nwipe_log( NWIPE_LOG_INFO, "[ERROR] SG_IO bad/missing sense data %s", hdparm_cmd_get_hpa );
nwipe_log( NWIPE_LOG_ERROR, "SG_IO bad/missing sense data %s", hdparm_cmd_get_hpa );
break;
}
else
@@ -197,7 +197,11 @@ int hpa_dco_status( nwipe_context_t* ptr )
{
c->HPA_status = HPA_DISABLED;
nwipe_log( NWIPE_LOG_INFO, "[GOOD] The host protected area is disabled on %s", c->device_name );
nwipe_log( NWIPE_LOG_DEBUG,
"hdparm says the host protected area is disabled on %s but this information may or "
"may not be correct, as occurs when you get a SG_IO error and 0/1 sectors and it "
"says HPA is enabled. Further checks are conducted below..",
c->device_name );
hpa_line_found = 1;
}
else
@@ -205,7 +209,11 @@ int hpa_dco_status( nwipe_context_t* ptr )
if( strstr( result, "hpa is enabled" ) != 0 )
{
c->HPA_status = HPA_ENABLED;
nwipe_log( NWIPE_LOG_WARNING, "The host protected area is enabled on %s", c->device_name );
nwipe_log( NWIPE_LOG_DEBUG,
"hdparm says the host protected area is enabled on %s but this information may "
"or may not be correct, as occurs when you get a SG_IO error and 0/1 sectors "
"and it says HPA is enabled. Further checks are conducted below..",
c->device_name );
hpa_line_found = 1;
}
else
@@ -214,7 +222,8 @@ int hpa_dco_status( nwipe_context_t* ptr )
{
c->HPA_status = HPA_ENABLED;
nwipe_log( NWIPE_LOG_WARNING,
"[UNSURE] hdparm reports invalid output, buggy drive firmware on %s?",
"hdparm reports invalid output, sector information may be invalid, buggy "
"drive firmware on %s?",
c->device_name );
// We'll assume the HPA values are in the string as we may be able to extract something
// meaningful
@@ -342,9 +351,41 @@ int hpa_dco_status( nwipe_context_t* ptr )
{
c->DCO_reported_real_max_sectors = str_ascii_number_to_ll( result );
nwipe_log( NWIPE_LOG_INFO,
"DCO Real max sectors reported as %lli on %s",
"hdparm:DCO Real max sectors reported as %lli on %s",
c->DCO_reported_real_max_sectors,
c->device_name );
/* Validate the real max sectors to detect extreme or impossible
* values, so the size must be greater than zero but less than
* 200TB (429496729600 sectors). As its 2023 and the largest drive
* available is 20TB I wonder if somebody in the future will be looking
* at this and thinking, yep we need to increase that value... and I'm
* wondering what year that will be. This validation is necessary all
* because of a bug in hdparm v9.60 (and maybe other versions) which
* produced wildly inaccurate values, often negative.
*/
if( c->DCO_reported_real_max_sectors > 0 && c->DCO_reported_real_max_sectors < 429496729600 )
{
/* Call nwipe's own low level function to retrieve the drive configuration
* overlay and retrieve the real max sectors. We may remove reliance on hdparm
* if nwipes own low level drive access code works well.
*/
c->DCO_reported_real_max_sectors = nwipe_read_dco_real_max_sectors( c->device_name );
/* Check our real max sectors function is returning sensible data too */
if( c->DCO_reported_real_max_sectors > 0 && c->DCO_reported_real_max_sectors < 429496729600 )
{
nwipe_log( NWIPE_LOG_INFO,
"NWipe:DCO Real max sectors reported as %lli on %s",
c->DCO_reported_real_max_sectors,
c->device_name );
}
else
{
c->DCO_reported_real_max_sectors = 0;
nwipe_log( NWIPE_LOG_INFO, "DCO Real max sectors not found" );
}
}
}
else
{
@@ -388,7 +429,10 @@ int hpa_dco_status( nwipe_context_t* ptr )
* HPA is disabled.
*
* If 'HPA set' and 'HPA real' are different then it
* can be considered that HPA is enabled)
* can be considered that HPA is enabled, assuming 'HPA set'
* and 'HPA real' are not 0/1 which occurs when a SG_IO error
* occurs. That also is checked for as it often indicates a
* poor USB device that does not have ATA pass through support.
*
* However we also need to consider that more recent drives
* no longer support HPA/DCO such as the Seagate ST10000NM0016,
@@ -434,9 +478,17 @@ int hpa_dco_status( nwipe_context_t* ptr )
}
else
{
if( !strcmp( c->device_type_str, "NVME" ) )
/* This occurs when a SG_IO error occurs with USB devices that don't support ATA pass through */
if( c->HPA_reported_set == 0 && c->HPA_reported_real == 1 )
{
c->HPA_status = HPA_NOT_APPLICABLE;
c->HPA_status = HPA_UNKNOWN;
}
else
{
if( !strcmp( c->device_type_str, "NVME" ) )
{
c->HPA_status = HPA_NOT_APPLICABLE;
}
}
}
}
@@ -456,7 +508,9 @@ int hpa_dco_status( nwipe_context_t* ptr )
{
if( c->HPA_status == HPA_UNKNOWN )
{
nwipe_log( NWIPE_LOG_WARNING, "HIDDEN AREA INDETERMINATE! on %s", c->device_name );
nwipe_log( NWIPE_LOG_WARNING,
"HIDDEN AREA INDETERMINATE! on %s, are you using a USB bridge or memory stick?",
c->device_name );
}
}
}
@@ -507,6 +561,7 @@ u64 nwipe_read_dco_real_max_sectors( char* device )
#define CMD_LEN 16
#define BLOCK_MAX 65535
#define LBA_MAX ( 1 << 30 )
#define SENSE_BUFFER_SIZE 32
u64 nwipe_real_max_sectors;
@@ -515,9 +570,14 @@ u64 nwipe_read_dco_real_max_sectors( char* device )
sg_io_hdr_t io_hdr;
unsigned char buffer[LBA_SIZE]; // Received data block
unsigned char sense_buffer[32]; // Sense data
unsigned char sense_buffer[SENSE_BUFFER_SIZE]; // Sense data
int i; // index
/* three characters represent one byte of sense data, i.e
* two characters and a space "01 AE 67"
*/
char sense_buffer_hex[( SENSE_BUFFER_SIZE * 3 ) + 1];
int i, i2; // index
int fd; // file descripter
if( ( fd = open( device, O_RDWR ) ) < 0 )
@@ -528,7 +588,7 @@ u64 nwipe_read_dco_real_max_sectors( char* device )
/******************************************
* Initialise the sg header for reading the
* device configuration overlay identify
* device configuration overlay identify data
*/
memset( &io_hdr, 0, sizeof( sg_io_hdr_t ) );
io_hdr.interface_id = 'S';
@@ -543,12 +603,15 @@ u64 nwipe_read_dco_real_max_sectors( char* device )
if( ioctl( fd, SG_IO, &io_hdr ) < 0 )
{
printf( "ioctl failed\n" );
for( i = 0; i < 32; i++ )
nwipe_log( NWIPE_LOG_ERROR, "IOCTL command failed retrieving DCO" );
i2 = 0;
for( i = 0, i2 = 0; i < SENSE_BUFFER_SIZE; i++, i2 += 3 )
{
/* IOCTL returned an error */
printf( "%02x ", sense_buffer[i] ); // WARNING make this an nwipe_log
snprintf( &sense_buffer_hex[i2], sizeof( sense_buffer_hex ), "%02x ", sense_buffer[i] );
}
sense_buffer_hex[i2] = 0; // terminate string
nwipe_log( NWIPE_LOG_DEBUG, "Sense buffer from failed DCO identify cmd:%s", sense_buffer_hex );
return -2;
}
@@ -565,9 +628,13 @@ u64 nwipe_read_dco_real_max_sectors( char* device )
| buffer[6];
/* Don't really understand this but hdparm adds 1 to
* the real max sectors too, (starting from 0??)
* the real max sectors too, counting zero as sector?
* but only increment if it's already greater than zero
*/
nwipe_real_max_sectors++;
if( nwipe_real_max_sectors > 0 )
{
nwipe_real_max_sectors++;
}
nwipe_log(
NWIPE_LOG_INFO, "func:nwipe_read_dco_real_max_sectors(), DCO real max sectors = %lli", nwipe_real_max_sectors );

View File

@@ -86,6 +86,19 @@ void nwipe_log( nwipe_log_t level, const char* format, ... )
/* initialise characters written */
chars_written = 0;
/* Only log messages with the debug label if the command line --verbose
* options has been specified, otherwise just return
*/
if( level == NWIPE_LOG_DEBUG && nwipe_options.verbose == 0 )
{
r = pthread_mutex_unlock( &mutex1 );
if( r != 0 )
{
fprintf( stderr, "nwipe_log: pthread_mutex_unlock failed. Code %i \n", r );
}
return;
}
/* Print the date. The rc script uses the same format. */
if( level != NWIPE_LOG_NOTIMESTAMP )
{
@@ -602,16 +615,16 @@ int nwipe_log_sysinfo()
if( *( &dmidecode_keywords[keywords_idx][1][0] ) == '0' )
{
nwipe_log(
NWIPE_LOG_NOTICE, "%s = %s", &dmidecode_keywords[keywords_idx][0][0], "XXXXXXXXXXXXXXX" );
NWIPE_LOG_INFO, "%s = %s", &dmidecode_keywords[keywords_idx][0][0], "XXXXXXXXXXXXXXX" );
}
else
{
nwipe_log( NWIPE_LOG_NOTICE, "%s = %s", &dmidecode_keywords[keywords_idx][0][0], path );
nwipe_log( NWIPE_LOG_INFO, "%s = %s", &dmidecode_keywords[keywords_idx][0][0], path );
}
}
else
{
nwipe_log( NWIPE_LOG_NOTICE, "%s = %s", &dmidecode_keywords[keywords_idx][0][0], path );
nwipe_log( NWIPE_LOG_INFO, "%s = %s", &dmidecode_keywords[keywords_idx][0][0], path );
}
}
/* close */

View File

@@ -22,17 +22,18 @@
#define LOGGING_H_
/* Maximum size of a log message */
#define MAX_LOG_LINE_CHARS 512
#define MAX_LOG_LINE_CHARS 1024
#define MAX_SIZE_OS_STRING 1024 /* Maximum size of acceptable OS string */
#define MAX_SIZE_OS_STRING 512 /* Maximum size of acceptable OS string */
#define OS_info_Line_offset 31 /* OS_info line offset in log */
#define OS_info_Line_Length 48 /* OS_info line length */
typedef enum nwipe_log_t_ {
NWIPE_LOG_NONE = 0,
NWIPE_LOG_DEBUG, // TODO: Very verbose logging.
NWIPE_LOG_INFO, // TODO: Verbose logging.
NWIPE_LOG_NOTICE, // Most logging happens at this level.
NWIPE_LOG_DEBUG, // Output only when --verbose option used on cmd line.
NWIPE_LOG_INFO, // General Info not specifically relevant to the wipe.
NWIPE_LOG_NOTICE, // Most logging happens at this level related to wiping.
NWIPE_LOG_WARNING, // Things that the user should know about.
NWIPE_LOG_ERROR, // Non-fatal errors that result in failure.
NWIPE_LOG_FATAL, // Errors that cause the program to exit.