Skip to content

Commit

Permalink
Improve symlink tests
Browse files Browse the repository at this point in the history
Instead of crashing on the first failed test, log an error message for
each failed test that points to the location of the error.

(cherry picked from commit 5dcc596)
  • Loading branch information
DemiMarie authored and marmarek committed Jun 22, 2024
1 parent acfa2b6 commit 030ae67
Showing 1 changed file with 48 additions and 17 deletions.
65 changes: 48 additions & 17 deletions qrexec-lib/validator-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,23 +119,54 @@ int main(int argc, char **argv)
(always_forbidden || bad_unicode ? -EILSEQ : 0));
}

// Symbolic links
// Top level cannot be symlink
assert(!qubes_pure_validate_symbolic_link((const uint8_t *)"a", (const uint8_t *)"b"));
// Symbolic links cannot escape
assert(!qubes_pure_validate_symbolic_link((const uint8_t *)"a/b", (const uint8_t *)"../a"));
assert(!qubes_pure_validate_symbolic_link((const uint8_t *)"a/b", (const uint8_t *)"../a/b/c"));
assert(!qubes_pure_validate_symbolic_link((const uint8_t *)"a/b/c", (const uint8_t *)"../../a"));
assert(qubes_pure_validate_symbolic_link((const uint8_t *)"a/b", (const uint8_t *)"a"));
assert(qubes_pure_validate_symbolic_link((const uint8_t *)"a/b/c", (const uint8_t *)"../a"));
// Absolute symlinks are rejected
assert(!qubes_pure_validate_symbolic_link((const uint8_t *)"a/b/c", (const uint8_t *)"/a"));
// Symlinks may end in "..".
assert(qubes_pure_validate_symbolic_link((const uint8_t *)"a/b/c", (const uint8_t *)".."));
// Symlinks may end in "/".
assert(qubes_pure_validate_symbolic_link((const uint8_t *)"a/b/c", (const uint8_t *)"a/"));
// Symlinks reject invalid paths.
assert(!qubes_pure_validate_symbolic_link((const uint8_t *)"..", (const uint8_t *)"a/"));
struct p {
const char *const path, *const target, *const file;
int const line, flags;
bool const allowed;
} symlink_checks[] = {
#define TEST(path_, target_, flags_, allowed_) \
{ .path = (path_) \
, .target = (target_) \
, .file = __FILE__ \
, .line = __LINE__ \
, .flags = (flags_) \
, .allowed = (allowed_) \
}
// Symbolic links
// Top level cannot be symlink
TEST("a", "b", 0, false),
TEST("a/b", "../a", 0, false),
TEST("a", "b", 0, false),
// Symbolic links cannot escape
TEST("a/b", "../a", 0, false),
TEST("a/b", "../a", 0, false),
TEST("a/b", "../a/b/c", 0, false),
TEST("a/b", "../a/b/c", 0, false),
TEST("a/b/c", "../../a", 0, false),
TEST("a/b/c", "../../a", 0, false),
TEST("a/b", "a", 0, true),
TEST("a/b/c", "../a", 0, true),
// Absolute symlinks are rejected
TEST("a/b/c", "/a", 0, false),
TEST("a/b/c", "/a", 0, false),
// Symlinks may end in "..".
TEST("a/b/c", "..", 0, true),
// Symlinks may end in "/".
TEST("a/b/c", "a/", 0, true),
// Invalid paths are rejected.
TEST("..", "a/", 0, false),
};
bool failed = false;
for (size_t i = 0; i < sizeof(symlink_checks)/sizeof(symlink_checks[0]); ++i) {
const struct p *p = symlink_checks + i;
if ((qubes_pure_validate_symbolic_link_v2((const unsigned char *)p->path,
(const unsigned char *)p->target,
p->flags) == 0) != p->allowed) {
failed = true;
fprintf(stderr, "%s:%d:Test failure\n", p->file, p->line);
}
}
assert(!failed);

// Greek letters are safe
assert(qubes_pure_validate_file_name((uint8_t *)u8"\u03b2.txt"));
Expand Down

0 comments on commit 030ae67

Please sign in to comment.