Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 4 additions & 15 deletions src/core/rosetta.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,6 @@
#include "syscall/internal.h" /* fd_alloc_from, fd_publish_linux_flags, FD_REGULAR */
#include "syscall/proc.h" /* proc_set_cmdline */

/* Round a guest virtual address (or size) up to the next 2 MiB boundary. */
static inline uint64_t align2m_up(uint64_t v)
{
return (v + BLOCK_2MIB - 1) & ~(BLOCK_2MIB - 1);
}

static inline uint64_t align2m_down(uint64_t v)
{
return v & ~(BLOCK_2MIB - 1);
}

/* The VZ_CAPS payload only has room for a 42-byte inline path. Publish
* /proc/self/fd/<bin_guest_fd> there when the real host path is longer so
* rosetta sees a valid reopenable path without truncation, while the host-side
Expand Down Expand Up @@ -227,8 +216,8 @@ int rosetta_prepare(guest_t *g,
* range above that. The mapping must cover the entire span so all segments
* resolve through a single Stage-2 region.
*/
uint64_t va_base = align2m_down(ri->load_min);
uint64_t va_end = align2m_up(ri->load_max);
uint64_t va_base = ALIGN_2MIB_DOWN(ri->load_min);
uint64_t va_end = ALIGN_2MIB_UP(ri->load_max);
if (va_end <= va_base) {
log_error("rosetta: empty load range");
return -1;
Expand Down Expand Up @@ -258,7 +247,7 @@ int rosetta_prepare(guest_t *g,
(unsigned long long) g->interp_base);
return -1;
}
guest_base = (rosetta_limit - size) & ~(BLOCK_2MIB - 1);
guest_base = ALIGN_2MIB_DOWN(rosetta_limit - size);
if (guest_base < g->stack_top + BLOCK_2MIB) {
log_error(
"rosetta: no image gap between stack_top=0x%llx and "
Expand Down Expand Up @@ -296,7 +285,7 @@ int rosetta_prepare(guest_t *g,
(unsigned long long) guest_base);
return -1;
}
uint64_t kbuf_gpa = (guest_base - KBUF_SIZE) & ~(BLOCK_2MIB - 1);
uint64_t kbuf_gpa = ALIGN_2MIB_DOWN(guest_base - KBUF_SIZE);
if (guest_init_kbuf(g, kbuf_gpa) < 0) {
log_error("rosetta: guest_init_kbuf failed at 0x%llx",
(unsigned long long) kbuf_gpa);
Expand Down
19 changes: 5 additions & 14 deletions src/debug/gdbstub-rsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,6 @@

static const char hex_chars[] = "0123456789abcdef";

static int hex_val(char c)
{
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
return -1;
}

int gdb_hex_encode(char *dst, const uint8_t *src, size_t len)
{
return (int) bytes_to_hex(dst, src, len);
Expand All @@ -37,7 +26,8 @@ int gdb_hex_encode(char *dst, const uint8_t *src, size_t len)
int gdb_hex_decode(uint8_t *dst, const char *src, size_t len)
{
for (size_t i = 0; i < len; i++) {
int hi = hex_val(src[i * 2]), lo = hex_val(src[i * 2 + 1]);
int hi = hex_nibble((unsigned char) src[i * 2]),
lo = hex_nibble((unsigned char) src[i * 2 + 1]);
if (hi < 0 || lo < 0)
return -1;
dst[i] = (uint8_t) ((hi << 4) | lo);
Expand All @@ -50,7 +40,7 @@ uint64_t gdb_parse_hex(const char **pp)
const char *p = *pp;
uint64_t val = 0;
while (1) {
int d = hex_val(*p);
int d = hex_nibble((unsigned char) *p);
if (d < 0)
break;
val = (val << 4) | (uint64_t) d;
Expand Down Expand Up @@ -209,7 +199,8 @@ int gdb_rsp_recv(gdb_rsp_ctx_t *ctx, int fd, char *buf, size_t bufsz)
buf[pos] = '\0';

uint8_t expected =
(uint8_t) ((hex_val(ck_hi) << 4) | hex_val(ck_lo));
(uint8_t) ((hex_nibble((unsigned char) ck_hi) << 4) |
hex_nibble((unsigned char) ck_lo));
uint8_t actual = rsp_checksum(buf, pos);
if (expected == actual) {
if (!ctx->no_ack_mode)
Expand Down
11 changes: 3 additions & 8 deletions src/runtime/procemu.c
Original file line number Diff line number Diff line change
Expand Up @@ -2120,8 +2120,7 @@ void proc_pty_dup_keepalive_locked(int src_master_host_fd,
/* dup(2) clears FD_CLOEXEC; the keepalive must not survive exec into a
* guest child that has no map back to it.
*/
int fdflags = fcntl(dst_slave, F_GETFD);
if (fdflags < 0 || fcntl(dst_slave, F_SETFD, fdflags | FD_CLOEXEC) < 0) {
if (fd_set_cloexec(dst_slave) < 0) {
close(dst_slave);
return;
}
Expand Down Expand Up @@ -2246,12 +2245,8 @@ void proc_pty_restore_keepalive(int master_host_fd,
if (master_host_fd < 0)
goto drop;

if (slave_host_fd >= 0) {
int fdflags = fcntl(slave_host_fd, F_GETFD);
if (fdflags < 0 ||
fcntl(slave_host_fd, F_SETFD, fdflags | FD_CLOEXEC) < 0)
goto drop;
}
if (slave_host_fd >= 0 && fd_set_cloexec(slave_host_fd) < 0)
goto drop;

/* Trust the parent's linux_pts_num verbatim instead of re-parsing
* slave_path. The wire-format string is bounded to PTY_SLAVE_PATH_MAX - 1
Expand Down
18 changes: 1 addition & 17 deletions src/syscall/fuse.c
Original file line number Diff line number Diff line change
Expand Up @@ -1660,22 +1660,6 @@ int fuse_access_path(const char *path, int mode, int flags)
return 0;
}

static int fuse_write_all(int fd, const void *buf, size_t len)
{
const uint8_t *p = buf;
while (len > 0) {
ssize_t nw = write(fd, p, len);
if (nw < 0) {
if (errno == EINTR)
continue;
return -1;
}
p += (size_t) nw;
len -= (size_t) nw;
}
return 0;
}

static int fuse_materialize_open_file_locked(fuse_session_t *session,
uint64_t nodeid,
uint64_t fh,
Expand Down Expand Up @@ -1713,7 +1697,7 @@ static int fuse_materialize_open_file_locked(fuse_session_t *session,
free(reply);
break;
}
if (fuse_write_all(tmp_fd, reply, reply_len) < 0) {
if (write_all(tmp_fd, reply, reply_len) < 0) {
rc = linux_errno();
free(reply);
break;
Expand Down
8 changes: 1 addition & 7 deletions src/syscall/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -2303,13 +2303,7 @@ int64_t sys_ioctl(guest_t *g, int fd, uint64_t request, uint64_t arg)
host_fd_ref_close(&host_ref);
return -LINUX_EFAULT;
}
int flags = fcntl(host_fd, F_GETFL);
if (flags < 0) {
host_fd_ref_close(&host_ref);
return linux_errno();
}
flags = on ? (flags | O_NONBLOCK) : (flags & ~O_NONBLOCK);
int r = fcntl(host_fd, F_SETFL, flags);
int r = fd_update_status_flag(host_fd, O_NONBLOCK, on != 0);
host_fd_ref_close(&host_ref);
return r < 0 ? linux_errno() : 0;
}
Expand Down
17 changes: 3 additions & 14 deletions src/syscall/path.c
Original file line number Diff line number Diff line change
Expand Up @@ -418,13 +418,10 @@ int sys_path_has_symlink(guest_fd_t dirfd, const char *path)
continue;

char name[NAME_MAX + 1];
if (len > NAME_MAX) {
errno = ENAMETOOLONG;
if (path_component_copy(name, sizeof(name), comp, len) < 0) {
rc = -1;
goto out;
}
memcpy(name, comp, len);
name[len] = '\0';

struct stat st;
if (fstatat(current_fd, name, &st, AT_SYMLINK_NOFOLLOW) < 0) {
Expand Down Expand Up @@ -1217,12 +1214,8 @@ int path_openat2_crosses_mount(guest_fd_t dirfd,
} else {
char name[NAME_MAX + 1];
char parent[LINUX_PATH_MAX];
if (len > NAME_MAX) {
errno = ENAMETOOLONG;
if (path_component_copy(name, sizeof(name), comp, len) < 0)
goto out;
}
memcpy(name, comp, len);
name[len] = '\0';
if (str_copy_trunc(parent, current, sizeof(parent)) >=
sizeof(parent)) {
errno = ENAMETOOLONG;
Expand Down Expand Up @@ -1316,12 +1309,8 @@ int path_openat2_crosses_mount(guest_fd_t dirfd,
if (host_walk && *rest != '\0' &&
!(len == 2 && comp[0] == '.' && comp[1] == '.')) {
char name[NAME_MAX + 1];
if (len > NAME_MAX) {
errno = ENAMETOOLONG;
if (path_component_copy(name, sizeof(name), comp, len) < 0)
goto out;
}
memcpy(name, comp, len);
name[len] = '\0';
host_fd_t next_fd =
openat(current_fd, name, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
if (replace_walk_fd(&current_fd, next_fd) < 0)
Expand Down
22 changes: 22 additions & 0 deletions src/syscall/path.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@

#pragma once

#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <sys/stat.h>

#include "syscall/internal.h"
Expand Down Expand Up @@ -62,6 +64,26 @@ static inline int path_translation_at_flags(const path_translation_t *tx,
*/
bool path_next_component(const char **pathp, const char **comp, size_t *len);

/* Copy a counted component (not NUL-terminated, as path_next_component reports)
* into dst and NUL-terminate it. Returns 0, or -1 with errno set to
* ENAMETOOLONG when the component does not fit. dst is typically a NAME_MAX+1
* buffer, so this also unifies the "len > NAME_MAX" and "len >= sizeof(dst)"
* bound checks the callers used to spell inconsistently.
*/
static inline int path_component_copy(char *dst,
size_t dstsz,
const char *comp,
size_t len)
{
if (len >= dstsz) {
errno = ENAMETOOLONG;
return -1;
}
memcpy(dst, comp, len);
dst[len] = '\0';
return 0;
}

bool path_might_use_open_intercept(const char *path);
bool path_might_use_stat_intercept(const char *path);
int path_check_intercept_access(const struct stat *st, int mode, int flags);
Expand Down
46 changes: 5 additions & 41 deletions src/syscall/sidecar.c
Original file line number Diff line number Diff line change
Expand Up @@ -295,17 +295,6 @@ bool sidecar_path_targets_reserved_name(const char *path)
return sidecar_name_reserved(basename);
}

static int hex_nibble(unsigned char c)
{
if (c >= '0' && c <= '9')
return (int) (c - '0');
if (c >= 'a' && c <= 'f')
return (int) (c - 'a' + 10);
if (c >= 'A' && c <= 'F')
return (int) (c - 'A' + 10);
return -1;
}

static int sidecar_decode_name(const char *hex, char **out)
{
size_t len = strlen(hex);
Expand Down Expand Up @@ -676,13 +665,11 @@ int sidecar_translate_lookup_at(guest_fd_t dirfd,
size_t comp_len;
while (path_next_component(&scan, &comp, &comp_len)) {
char guest_comp[NAME_MAX + 1];
if (comp_len >= sizeof(guest_comp)) {
if (path_component_copy(guest_comp, sizeof(guest_comp), comp,
comp_len) < 0) {
close(cur_fd);
errno = ENAMETOOLONG;
return -1;
}
memcpy(guest_comp, comp, comp_len);
guest_comp[comp_len] = '\0';

if (sidecar_name_reserved(guest_comp)) {
close(cur_fd);
Expand Down Expand Up @@ -809,12 +796,9 @@ int sidecar_translate_lookup_at(guest_fd_t dirfd,
*/
while (path_next_component(&scan, &comp, &comp_len)) {
char rest_comp[NAME_MAX + 1];
if (comp_len >= sizeof(rest_comp)) {
errno = ENAMETOOLONG;
if (path_component_copy(rest_comp, sizeof(rest_comp), comp,
comp_len) < 0)
return -1;
}
memcpy(rest_comp, comp, comp_len);
rest_comp[comp_len] = '\0';
if (sidecar_append_component(out, outsz, &out_len, rest_comp,
absolute) < 0)
return -1;
Expand Down Expand Up @@ -1113,25 +1097,6 @@ static int sidecar_load_locked_index(int parent_dirfd,
* Returns 0 on success, -1 with errno set on error. Handles short writes by
* retrying until everything is committed.
*/
static int sidecar_write_all(int fd, const char *buf, size_t len)
{
size_t off = 0;
while (off < len) {
ssize_t n = write(fd, buf + off, len - off);
if (n < 0) {
if (errno == EINTR)
continue;
return -1;
}
if (n == 0) {
errno = EIO;
return -1;
}
off += (size_t) n;
}
return 0;
}

/* Serialize the index into a malloc'd buffer. *@out_len receives the byte
* count.
*
Expand Down Expand Up @@ -1222,8 +1187,7 @@ static int sidecar_write_locked_index(int parent_dirfd,
errno = saved_errno;
return -1;
}
if (payload_len > 0 &&
sidecar_write_all(tmp_fd, payload, payload_len) < 0) {
if (payload_len > 0 && write_all(tmp_fd, payload, payload_len) < 0) {
int saved_errno = errno;
close(tmp_fd);
(void) unlinkat(parent_dirfd, SIDECAR_INDEX_TMP_NAME, 0);
Expand Down
14 changes: 14 additions & 0 deletions src/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,20 @@ static inline size_t bytes_to_hex(char *dst, const uint8_t *src, size_t len)
return len * 2;
}

/* Decode a single hex digit to its 0-15 value, or -1 if @c is not a hex digit.
* The inverse building block of bytes_to_hex; accepts either case.
*/
static inline int hex_nibble(unsigned char c)
{
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
return -1;
}

/* Write exactly @len bytes to a blocking @fd, resuming across short writes and
* EINTR. Returns 0 once every byte is written, or -1 with errno set on error.
* An unexpected zero-byte return is treated as EIO rather than spun on, since
Expand Down
Loading