mirror of
https://github.com/martijnvanbrummelen/nwipe.git
synced 2026-02-20 13:42:14 +00:00
device: sanitize serial numbers and fix uninitialized/fallback handling
This patch fixes several issues that could cause garbage or control characters to appear in the ncurses UI when displaying device serial numbers. Key changes: - Added nwipe_normalize_serial() to strip control characters, non-ASCII bytes and trim whitespace from all serial numbers before they are shown in the UI. - Initialize the serialnumber buffer in nwipe_get_device_bus_type_and_serialno() to avoid passing undefined data back to check_device() when no valid "Serial Number:" field is found. - Prevent ioctl(HDIO_GET_IDENTITY) from being called on an invalid file descriptor when open() fails. - Ensure consistent null termination and sanitize the final device_serial_no regardless of whether it came from HDIO, smartctl output, or quiet-mode anonymization. These fixes resolve cases where devices (especially virtual/QEMU or USB-attached drives) could report malformed or unexpected serial strings, resulting in UI corruption such as extra characters, ^A, or line wrapping.
This commit is contained in:
73
src/device.c
73
src/device.c
@@ -49,6 +49,7 @@
|
||||
|
||||
int check_device( nwipe_context_t*** c, PedDevice* dev, int dcount );
|
||||
char* trim( char* str );
|
||||
static void nwipe_normalize_serial( char* serial );
|
||||
|
||||
/*
|
||||
* Resolve a device path (including /dev/disk/by-* symlinks) to its
|
||||
@@ -360,22 +361,26 @@ int check_device( nwipe_context_t*** c, PedDevice* dev, int dcount )
|
||||
next_device->device_size_text = next_device->device_size_txt;
|
||||
next_device->result = -2;
|
||||
|
||||
/* Attempt to get serial number of device.
|
||||
*/
|
||||
next_device->device_serial_no[0] = 0; /* initialise the serial number */
|
||||
/* Attempt to get serial number of device. */
|
||||
next_device->device_serial_no[0] = '\0'; /* initialise the serial number */
|
||||
|
||||
if( ( fd = open( next_device->device_name = dev->path, O_RDONLY ) ) == ERR )
|
||||
fd = open( next_device->device_name = dev->path, O_RDONLY );
|
||||
if( fd == ERR )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_WARNING, "Unable to open device %s to obtain serial number", next_device->device_name );
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't check the ioctl return status because there are plenty of situations where a serial number may not be
|
||||
* returned by ioctl such as USB drives, logical volumes, encryted volumes, so the log file would have multiple
|
||||
* benign ioctl errors reported which isn't necessarily a problem.
|
||||
*/
|
||||
ioctl( fd, HDIO_GET_IDENTITY, &next_device->identity );
|
||||
close( fd );
|
||||
else
|
||||
{
|
||||
/*
|
||||
* We don't check the ioctl return status because there are plenty of
|
||||
* situations where a serial number may not be returned by ioctl such as
|
||||
* USB drives, logical volumes, encrypted volumes, so the log file
|
||||
* would have multiple benign ioctl errors reported which isn't
|
||||
* necessarily a problem.
|
||||
*/
|
||||
ioctl( fd, HDIO_GET_IDENTITY, &next_device->identity );
|
||||
close( fd );
|
||||
}
|
||||
|
||||
for( idx = 0; idx < NWIPE_SERIALNUMBER_LENGTH; idx++ )
|
||||
{
|
||||
@@ -425,6 +430,9 @@ int check_device( nwipe_context_t*** c, PedDevice* dev, int dcount )
|
||||
* of those strings we should explicitly terminate the string */
|
||||
next_device->device_serial_no[NWIPE_SERIALNUMBER_LENGTH] = 0;
|
||||
|
||||
/* Ensure the serial number cannot break the ncurses UI. */
|
||||
nwipe_normalize_serial( next_device->device_serial_no );
|
||||
|
||||
/* Initialise the variables that toggle the [size][temp c] with [HPA status]
|
||||
* Not currently used, but may be used in the future or for other purposes
|
||||
*/
|
||||
@@ -624,6 +632,39 @@ char* trim( char* str )
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove non-ASCII and control characters from a serial number string,
|
||||
* then trim leading/trailing whitespace and left-justify it in-place.
|
||||
* This keeps the value safe for ncurses output.
|
||||
*/
|
||||
static void nwipe_normalize_serial( char* serial )
|
||||
{
|
||||
unsigned char ch;
|
||||
char* src;
|
||||
char* dst;
|
||||
|
||||
if( serial == NULL )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
src = dst = serial;
|
||||
|
||||
while( ( ch = (unsigned char) *src++ ) != '\0' )
|
||||
{
|
||||
if( isascii( ch ) && !iscntrl( ch ) )
|
||||
{
|
||||
*dst++ = (char) ch;
|
||||
}
|
||||
/* Alle anderen Zeichen (Steuerzeichen, >0x7F) werden verworfen */
|
||||
}
|
||||
|
||||
*dst = '\0';
|
||||
|
||||
/* Vorhandene trim()-Logik wiederverwenden */
|
||||
trim( serial );
|
||||
}
|
||||
|
||||
int nwipe_get_device_bus_type_and_serialno( char* device, nwipe_device_t* bus, int* is_ssd, char* serialnumber )
|
||||
{
|
||||
/* The caller provides a string that contains the device, i.e. /dev/sdc, also a pointer
|
||||
@@ -671,6 +712,14 @@ int nwipe_get_device_bus_type_and_serialno( char* device, nwipe_device_t* bus, i
|
||||
"serial number:", "lu wwn device id:", "logical unit id:", "" /* Don't remove this empty string !, important */
|
||||
};
|
||||
|
||||
/* Ensure the serialnumber buffer is in a defined state even if we
|
||||
* never find a "serial number:" line in smartctl output.
|
||||
*/
|
||||
if( serialnumber != NULL )
|
||||
{
|
||||
memset( serialnumber, 0, NWIPE_SERIALNUMBER_LENGTH + 1 );
|
||||
}
|
||||
|
||||
/* Initialise return value */
|
||||
set_return_value = 0;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user