mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-25 18:40:19 -04:00
Validate logical disk names in configuration parsing to ensure compatibility with snapraid-daemon
This commit is contained in:
parent
bdc2da9a94
commit
3f3e7d4483
3 changed files with 129 additions and 0 deletions
|
|
@ -1883,6 +1883,62 @@ static void test_smart_ignore(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void test_disk_name(void)
|
||||
{
|
||||
char name_127[128];
|
||||
char name_128[129];
|
||||
|
||||
/* valid normal names */
|
||||
assert(disk_name_invalid_reason("d1") == 0);
|
||||
assert(disk_name_invalid_reason("data_01") == 0);
|
||||
assert(disk_name_invalid_reason("disk-A") == 0);
|
||||
|
||||
/* 127-byte name is valid */
|
||||
memset(name_127, 'a', 127);
|
||||
name_127[127] = 0;
|
||||
assert(disk_name_invalid_reason(name_127) == 0);
|
||||
|
||||
/* 128-byte name is rejected */
|
||||
memset(name_128, 'a', 128);
|
||||
name_128[128] = 0;
|
||||
assert(disk_name_invalid_reason(name_128) != 0);
|
||||
|
||||
/* slash delimiter rejected */
|
||||
assert(disk_name_invalid_reason("data/1") != 0);
|
||||
assert(disk_name_invalid_reason("/disk") != 0);
|
||||
assert(disk_name_invalid_reason("disk/") != 0);
|
||||
|
||||
/* backslash delimiter rejected */
|
||||
assert(disk_name_invalid_reason("data\\1") != 0);
|
||||
assert(disk_name_invalid_reason("\\disk") != 0);
|
||||
assert(disk_name_invalid_reason("disk\\") != 0);
|
||||
|
||||
/* colon delimiter rejected */
|
||||
assert(disk_name_invalid_reason("data:1") != 0);
|
||||
assert(disk_name_invalid_reason(":disk") != 0);
|
||||
assert(disk_name_invalid_reason("disk:") != 0);
|
||||
|
||||
/* reserved parity names and aliases rejected */
|
||||
assert(disk_name_invalid_reason("parity") != 0);
|
||||
assert(disk_name_invalid_reason("1-parity") != 0);
|
||||
assert(disk_name_invalid_reason("2-parity") != 0);
|
||||
assert(disk_name_invalid_reason("3-parity") != 0);
|
||||
assert(disk_name_invalid_reason("4-parity") != 0);
|
||||
assert(disk_name_invalid_reason("5-parity") != 0);
|
||||
assert(disk_name_invalid_reason("6-parity") != 0);
|
||||
assert(disk_name_invalid_reason("q-parity") != 0);
|
||||
assert(disk_name_invalid_reason("r-parity") != 0);
|
||||
assert(disk_name_invalid_reason("z-parity") != 0);
|
||||
|
||||
/* valid names containing parity as substring */
|
||||
assert(disk_name_invalid_reason("parity1") == 0);
|
||||
assert(disk_name_invalid_reason("parity_data") == 0);
|
||||
assert(disk_name_invalid_reason("my_parity") == 0);
|
||||
assert(disk_name_invalid_reason("disparity") == 0);
|
||||
assert(disk_name_invalid_reason("2-parity-extra") == 0);
|
||||
assert(disk_name_invalid_reason("q-parity-disk") == 0);
|
||||
}
|
||||
|
||||
static void test_stream(void)
|
||||
{
|
||||
STREAM f;
|
||||
|
|
@ -2733,6 +2789,9 @@ void test(int argc, char* argv[])
|
|||
/* smart attribute ignore rules */
|
||||
test_smart_ignore();
|
||||
|
||||
/* logical disk name validation */
|
||||
test_disk_name();
|
||||
|
||||
t_selftest_start = os_tick_ms();
|
||||
selftest();
|
||||
t_selftest_end = os_tick_ms();
|
||||
|
|
|
|||
|
|
@ -114,6 +114,24 @@ static int lev_config_scan(const char* s, unsigned* level, unsigned* mode)
|
|||
return -1;
|
||||
}
|
||||
|
||||
const char* disk_name_invalid_reason(const char* name)
|
||||
{
|
||||
unsigned dummy_level;
|
||||
|
||||
if (strlen(name) > DISK_NAME_MAX)
|
||||
return "Name is too long (maximum 127 bytes)";
|
||||
if (strchr(name, '/') != 0)
|
||||
return "Name contains '/'";
|
||||
if (strchr(name, '\\') != 0)
|
||||
return "Name contains '\\'";
|
||||
if (strchr(name, ':') != 0)
|
||||
return "Name contains ':'";
|
||||
if (lev_config_scan(name, &dummy_level, 0) == 0)
|
||||
return "Name is a reserved parity name";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* lev_raid_name(unsigned mode, unsigned n)
|
||||
{
|
||||
switch (n) {
|
||||
|
|
@ -1032,6 +1050,14 @@ void state_config(struct snapraid_state* state, const char* path, const char* co
|
|||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
const char* reason = disk_name_invalid_reason(buffer);
|
||||
if (reason) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal(EUSER, "Invalid 'data' name '%s' in '%s' at line %u. %s.\n", buffer, path, line, reason);
|
||||
exit(EXIT_FAILURE);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
sgetspace(f);
|
||||
|
||||
ret = sgetlasttok(f, dir, sizeof(dir));
|
||||
|
|
@ -1065,6 +1091,18 @@ void state_config(struct snapraid_state* state, const char* path, const char* co
|
|||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
for (i = state->extralist; i != 0; i = i->next) {
|
||||
struct snapraid_extra* found_extra = i->data;
|
||||
if (strcmp(found_extra->name, buffer) == 0)
|
||||
break;
|
||||
}
|
||||
if (i) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal(EUSER, "Duplicate 'data' name '%s' already used in 'extra' at line %u\n", buffer, line);
|
||||
exit(EXIT_FAILURE);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
/* if the disk has to be present */
|
||||
skip_access = 0;
|
||||
if (!state->opt.skip_disk_access) {
|
||||
|
|
@ -1134,6 +1172,14 @@ void state_config(struct snapraid_state* state, const char* path, const char* co
|
|||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
const char* reason = disk_name_invalid_reason(buffer);
|
||||
if (reason) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal(EUSER, "Invalid 'extra' name '%s' in '%s' at line %u. %s.\n", buffer, path, line, reason);
|
||||
exit(EXIT_FAILURE);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
sgetspace(f);
|
||||
|
||||
ret = sgetlasttok(f, dir, sizeof(dir));
|
||||
|
|
@ -1167,6 +1213,18 @@ void state_config(struct snapraid_state* state, const char* path, const char* co
|
|||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
for (i = state->disklist; i != 0; i = i->next) {
|
||||
struct snapraid_disk* found_disk = i->data;
|
||||
if (strcmp(found_disk->name, buffer) == 0)
|
||||
break;
|
||||
}
|
||||
if (i) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal(EUSER, "Duplicate 'extra' name '%s' already used in 'data' at line %u\n", buffer, line);
|
||||
exit(EXIT_FAILURE);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
/* if the disk has to be present */
|
||||
if (!state->opt.skip_disk_access) {
|
||||
struct stat st;
|
||||
|
|
|
|||
|
|
@ -27,6 +27,18 @@ const char* lev_name(unsigned level);
|
|||
*/
|
||||
const char* lev_config_name(unsigned level);
|
||||
|
||||
/**
|
||||
* Maximum byte length of a logical disk name.
|
||||
*/
|
||||
#define DISK_NAME_MAX 127
|
||||
|
||||
/**
|
||||
* Validate a logical disk name.
|
||||
*
|
||||
* Returns 0 if valid, or a static string error reason if invalid.
|
||||
*/
|
||||
const char* disk_name_invalid_reason(const char* name);
|
||||
|
||||
/****************************************************************************/
|
||||
/* state */
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue