Skip to content

Commit

Permalink
find_file(): Check for symlinks to /dev/tcp/
Browse files Browse the repository at this point in the history
This path should not exist, so subsequent accesses will fail.  However,
later changes will interpret these paths specially.
  • Loading branch information
DemiMarie committed Apr 23, 2024
1 parent 4342589 commit 695c3f3
Showing 1 changed file with 51 additions and 6 deletions.
57 changes: 51 additions & 6 deletions libqrexec/exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,13 @@ static int qubes_connect(int s, const char *connect_path, const size_t total_pat
Returns 0 on success, -1 if the file is definitely absent in all of the
paths, and -2 on error (broken symlink, I/O error, path too long, out
of memory, etc).
On success, fills buffer and statbuf (unless statbuf is NULL).
On success, fills buffer and statbuf (unless statbuf is NULL). buffer
will contain the path to the file, while statbuf will contain metadata
about the file as reported by stat(2).
If statbuf is not NULL, buffer may be filled with string starting
with "/dev/tcp/", which corresponds to the target of the symbolic link.
In this case, statbuf will contain the metadata for the symlink itself,
not its (hopefully nonexistent) target.
*/
static int find_file(
const char *path_list,
Expand All @@ -220,13 +226,22 @@ static int find_file(
struct stat dummy_buf;
const char *path_start = path_list;
size_t name_length = strlen(name);
char *buf = NULL;
int res;
int rc;

if (name_length > NAME_MAX)
return -1; /* cannot possibly exist */

if (!statbuf)
if (!statbuf) {
statbuf = &dummy_buf;
} else {
buf = malloc(buffer_size);
if (buf == NULL) {
LOG(ERROR, "Cannot allocate %zu bytes", buffer_size);
return -2;
}
}

while (*path_start) {
/* Find next path (up to ':') */
Expand All @@ -235,7 +250,8 @@ static int find_file(

if (path_length + name_length + 1 >= buffer_size) {
LOG(ERROR, "find_qrexec_service_file: buffer too small for file path");
return -2;
rc = -2;
goto done;
}

memcpy(buffer, path_start, path_length);
Expand All @@ -244,24 +260,53 @@ static int find_file(
//LOG(INFO, "stat(%s)", buffer);
res = lstat(buffer, statbuf);
if (res == 0 && S_ISLNK(statbuf->st_mode)) {
if (buf != NULL) {
ssize_t res = readlink(buffer, buf, buffer_size);
if (res < 0) {
/* readlink(2) failed */
LOG(ERROR, "readlink(2) failed: %m");
rc = -2;
goto done;
}
size_t target_len = (size_t)res;
if ((target_len >= sizeof("/dev/tcp") && memcmp(buf, "/dev/tcp/", sizeof("/dev/tcp")) == 0) ||
(target_len == sizeof("/dev/tcp") - 1 && memcmp(buf, "/dev/tcp/", sizeof("/dev/tcp") - 1) == 0))
{
if (target_len >= buffer_size) {
/* buffer too small */
rc = -2;
} else {
memcpy(buffer, buf, target_len);
buffer[target_len] = '\0';
rc = 0;
}
goto done;
}
}
/* check if the symlink is valid */
res = stat(buffer, statbuf);
assert(res == -1 || !S_ISLNK(statbuf->st_mode));
}
if (res == 0) {
return 0;
rc = 0;
goto done;
} else {
assert(res == -1);
if (errno != ENOENT) {
return -2;
LOG(ERROR, "stat/lstat(%s): %m", buffer);
rc = -2;
goto done;
}
}

path_start = path_end;
while (*path_start == ':')
path_start++;
}
return -1;
rc = -1;
done:
free(buf);
return rc;
}

static int load_service_config_raw(struct qrexec_parsed_command *cmd,
Expand Down

0 comments on commit 695c3f3

Please sign in to comment.