Skip to content

Commit

Permalink
[Pal,LibOS] Refactor sysfs to improve sanitization
Browse files Browse the repository at this point in the history
This commit creates a clean representation of topology
data on the trusted<->untrusted boundary, so that we can
easily verify its correctness. The following are done:

1. Refactor sysfs code to convert CPU/NUMA information from
   Linux-formatted strings to integers in untrusted PAL.
2. Copy and sanitize CPU/NUMA information based on untrusted
   integers to trusted PAL.
3. Convert the trusted CPU/NUMA information from integers back
   to Linux-formatted strings in LibOS.

Signed-off-by: Vijay Dhanraj <vijay.dhanraj@intel.com>
  • Loading branch information
vijaydhanraj committed Jan 31, 2022
1 parent 9d9f4cd commit bc06c66
Show file tree
Hide file tree
Showing 14 changed files with 1,045 additions and 587 deletions.
13 changes: 13 additions & 0 deletions LibOS/shim/include/shim_fs_pseudo.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,4 +210,17 @@ int sys_cache_load(struct shim_dentry* dent, char** out_data, size_t* out_size);
bool sys_cpu_online_name_exists(struct shim_dentry* parent, const char* name);
int sys_cpu_online_list_names(struct shim_dentry* parent, readdir_callback_t callback, void* arg);

/* Converts struct pal_res_range_info to a string representation.
* Example output when sep == ',': "10-63,68,70-127".
* Note: This function adds a newline at the end of the string. */
int sys_convert_ranges_to_str(const struct pal_res_range_info* resource_range_info, const char* sep,
char* str, size_t str_size);

/* Converts struct pal_res_range_info to a sysfs CPU bitmask representation with bitmask size based
* on the possible cores count in the system.
* Example output for 64 cores in total and ranges 0-15,48-55: "00ff0000,0000ffff".
* Note: This function adds a newline at the end of the string. */
int sys_convert_ranges_to_cpu_bitmap_str(const struct pal_res_range_info* resource_range_info,
char* str, size_t str_size);

#endif /* SHIM_FS_PSEUDO_H_ */
8 changes: 5 additions & 3 deletions LibOS/shim/src/fs/proc/info.c
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ int proc_cpuinfo_load(struct shim_dentry* dent, char** out_data, size_t* out_siz

const struct pal_topo_info* ti = &g_pal_public_state->topo_info;
const struct pal_cpu_info* ci = &g_pal_public_state->cpu_info;
for (size_t i = 0; i < ti->online_logical_cores_cnt; i++) {
for (size_t i = 0; i < ti->online_logical_cores.resource_cnt; i++) {
/* Below strings must match exactly the strings retrieved from /proc/cpuinfo
* (see Linux's arch/x86/kernel/cpu/proc.c) */
ADD_INFO("processor\t: %lu\n", i);
Expand All @@ -151,7 +151,9 @@ int proc_cpuinfo_load(struct shim_dentry* dent, char** out_data, size_t* out_siz
ADD_INFO("model\t\t: %lu\n", ci->cpu_model);
ADD_INFO("model name\t: %s\n", ci->cpu_brand);
ADD_INFO("stepping\t: %lu\n", ci->cpu_stepping);
ADD_INFO("physical id\t: %zu\n", ti->cpu_to_socket_arr[i]);
if (g_pal_public_state->enable_sysfs_topology) {
ADD_INFO("physical id\t: %zu\n", ti->core_topo_arr[i].socket_id);
}
ADD_INFO("core id\t\t: %lu\n", i);
ADD_INFO("cpu cores\t: %zu\n", ti->physical_cores_per_socket);
double bogomips = ci->cpu_bogomips;
Expand Down Expand Up @@ -191,7 +193,7 @@ int proc_stat_load(struct shim_dentry* dent, char** out_data, size_t* out_size)
* (see Linux's fs/proc/stat.c) */
ADD_INFO("cpu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n", user, nice, system, idle, iowait,
irq, softirq, steal, guest, guest_nice);
for (size_t n = 0; n < g_pal_public_state->topo_info.online_logical_cores_cnt; n++) {
for (size_t n = 0; n < g_pal_public_state->topo_info.online_logical_cores.resource_cnt; n++) {
ADD_INFO("cpu%lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n", n, user, nice, system, idle,
iowait, irq, softirq, steal, guest, guest_nice);
}
Expand Down
35 changes: 25 additions & 10 deletions LibOS/shim/src/fs/sys/cache_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,26 +27,41 @@ int sys_cache_load(struct shim_dentry* dent, char** out_data, size_t* out_size)

const char* name = dent->name;
struct pal_core_cache_info* cache_info =
&g_pal_public_state->topo_info.core_topology_arr[cpu_num].cache_info_arr[cache_num];
const char* str;
&g_pal_public_state->topo_info.core_topo_arr[cpu_num].cache_info_arr[cache_num];
char str[PAL_SYSFS_MAP_FILESZ] = {'\0'};
if (strcmp(name, "shared_cpu_map") == 0) {
str = cache_info->shared_cpu_map;
ret = sys_convert_ranges_to_cpu_bitmap_str(&cache_info->shared_cpu_map, str, sizeof(str));
} else if (strcmp(name, "level") == 0) {
str = cache_info->level;
ret = snprintf(str, sizeof(str), "%zu\n", cache_info->level);
} else if (strcmp(name, "type") == 0) {
str = cache_info->type;
switch (cache_info->type) {
case CACHE_TYPE_DATA:
ret = snprintf(str, sizeof(str), "Data\n");
break;
case CACHE_TYPE_INSTRUCTION:
ret = snprintf(str, sizeof(str), "Instruction\n");
break;
case CACHE_TYPE_UNIFIED:
ret = snprintf(str, sizeof(str), "Unified\n");
break;
default:
ret = -ENOENT;
}
} else if (strcmp(name, "size") == 0) {
str = cache_info->size;
ret = snprintf(str, sizeof(str), "%zuK\n", cache_info->size >> 10);
} else if (strcmp(name, "coherency_line_size") == 0) {
str = cache_info->coherency_line_size;
ret = snprintf(str, sizeof(str), "%zu\n", cache_info->coherency_line_size);
} else if (strcmp(name, "number_of_sets") == 0) {
str = cache_info->number_of_sets;
ret = snprintf(str, sizeof(str), "%zu\n", cache_info->number_of_sets);
} else if (strcmp(name, "physical_line_partition") == 0) {
str = cache_info->physical_line_partition;
snprintf(str, sizeof(str), "%zu\n", cache_info->physical_line_partition);
} else {
log_debug("unrecognized file: %s", name);
return -ENOENT;
ret = -ENOENT;
}

if (ret < 0)
return ret;

return sys_load(str, out_data, out_size);
}
38 changes: 23 additions & 15 deletions LibOS/shim/src/fs/sys/cpu_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,24 @@
#include "shim_fs_pseudo.h"

int sys_cpu_general_load(struct shim_dentry* dent, char** out_data, size_t* out_size) {
int ret;
const char* name = dent->name;
const char* str;
char str[PAL_SYSFS_BUF_FILESZ] = {'\0'};

if (strcmp(name, "online") == 0) {
str = g_pal_public_state->topo_info.online_logical_cores;
ret = sys_convert_ranges_to_str(&g_pal_public_state->topo_info.online_logical_cores, ",",
str, sizeof(str));
} else if (strcmp(name, "possible") == 0) {
str = g_pal_public_state->topo_info.possible_logical_cores;
ret = sys_convert_ranges_to_str(&g_pal_public_state->topo_info.possible_logical_cores, ",",
str, sizeof(str));
} else {
log_debug("unrecognized file: %s", name);
return -ENOENT;
ret = -ENOENT;
}

if (ret < 0)
return ret;

return sys_load(str, out_data, out_size);
}

Expand All @@ -37,29 +43,30 @@ int sys_cpu_load(struct shim_dentry* dent, char** out_data, size_t* out_size) {

const char* name = dent->name;
struct pal_core_topo_info* core_topology =
&g_pal_public_state->topo_info.core_topology_arr[cpu_num];
const char* str;
char buf[12];
&g_pal_public_state->topo_info.core_topo_arr[cpu_num];
char str[PAL_SYSFS_MAP_FILESZ] = {'\0'};
if (strcmp(name, "online") == 0) {
/* `cpu/cpuX/online` is not present for cpu0 */
if (cpu_num == 0)
return -ENOENT;
str = core_topology->is_logical_core_online;
ret = snprintf(str, sizeof(str), "%d\n", core_topology->is_logical_core_online);
} else if (strcmp(name, "core_id") == 0) {
str = core_topology->core_id;
ret = snprintf(str, sizeof(str), "%zu\n", core_topology->core_id);
} else if (strcmp(name, "physical_package_id") == 0) {
snprintf(buf, sizeof(buf), "%zu\n",
g_pal_public_state->topo_info.cpu_to_socket_arr[cpu_num]);
str = buf;
ret = snprintf(str, sizeof(str), "%zu\n", core_topology->socket_id);
} else if (strcmp(name, "core_siblings") == 0) {
str = core_topology->core_siblings;
ret = sys_convert_ranges_to_cpu_bitmap_str(&core_topology->core_siblings, str, sizeof(str));
} else if (strcmp(name, "thread_siblings") == 0) {
str = core_topology->thread_siblings;
ret = sys_convert_ranges_to_cpu_bitmap_str(&core_topology->thread_siblings, str,
sizeof(str));
} else {
log_debug("unrecognized file: %s", name);
return -ENOENT;
ret = -ENOENT;
}

if (ret < 0)
return ret;

return sys_load(str, out_data, out_size);
}

Expand Down Expand Up @@ -88,5 +95,6 @@ int sys_cpu_online_list_names(struct shim_dentry* parent, readdir_callback_t cal
if (ret < 0)
return ret;
}

return 0;
}
102 changes: 100 additions & 2 deletions LibOS/shim/src/fs/sys/fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,115 @@
#include "shim_fs_pseudo.h"
#include "stat.h"

int sys_convert_ranges_to_str(const struct pal_res_range_info* resource_range_info, const char* sep,
char* str, size_t str_size) {
size_t ranges_cnt = resource_range_info->ranges_cnt;
if (!ranges_cnt)
return -EINVAL;

str[0] = '\0';
size_t offset = 0;
for (size_t i = 0; i < ranges_cnt; i++) {
if (offset >= str_size)
return -ENOMEM;

int ret;
if (resource_range_info->ranges_arr[i].end == resource_range_info->ranges_arr[i].start) {
ret = snprintf(str + offset, str_size - offset, "%zu%s",
resource_range_info->ranges_arr[i].start,
(i + 1 == ranges_cnt) ? "\n" : sep);
} else {
ret = snprintf(str + offset, str_size - offset, "%zu-%zu%s",
resource_range_info->ranges_arr[i].start,
resource_range_info->ranges_arr[i].end,
(i + 1 == ranges_cnt) ? "\n" : sep);
}

if (ret < 0)
return ret;

/* Truncation has occurred */
if ((size_t)ret >= str_size - offset)
return -EOVERFLOW;

offset += ret;
}
return 0;
}

int sys_convert_ranges_to_cpu_bitmap_str(const struct pal_res_range_info* resource_range_info,
char* str, size_t str_size) {
int ret;

/* Extract cpumask from the ranges */
size_t possible_logical_cores_cnt =
g_pal_public_state->topo_info.possible_logical_cores.resource_cnt;
size_t cpumask_cnt = BITS_TO_UINT32S(possible_logical_cores_cnt);
assert(cpumask_cnt > 0);

uint32_t* bitmap = calloc(cpumask_cnt, sizeof(*bitmap));
if (!bitmap)
return -ENOMEM;

for (size_t i = 0; i < resource_range_info->ranges_cnt; i++) {
size_t start = resource_range_info->ranges_arr[i].start;
size_t end = resource_range_info->ranges_arr[i].end;

for (size_t j = start; j <= end; j++) {
size_t index = j / BITS_IN_TYPE(uint32_t);
assert(index < cpumask_cnt);

bitmap[index] |= 1U << (j % BITS_IN_TYPE(uint32_t));
}
}

/* Convert cpumask to strings */
size_t offset = 0;
for (size_t j = cpumask_cnt; j > 0; j--) {
if (offset >= str_size) {
ret = -ENOMEM;
goto out;
}

/* Linux doesn't print leading zeroes for systems with less than 32 cores, e.g. "fff" for
* 12 cores; we mimic this behavior. */
if (possible_logical_cores_cnt >= 32) {
ret = snprintf(str + offset, str_size - offset, "%08x%s", bitmap[j-1],
(j-1 == 0) ? "\n" : ",");
} else {
ret = snprintf(str + offset, str_size - offset, "%x%s", bitmap[j-1],
(j-1 == 0) ? "\n" : ",");
}

if (ret < 0)
goto out;

/* Truncation has occurred */
if ((size_t)ret >= str_size - offset) {
ret = -EOVERFLOW;
goto out;
}

offset += ret;
}
ret = 0;

out:
free(bitmap);
return ret;
}

static int sys_resource(struct shim_dentry* parent, const char* name, unsigned int* out_num,
readdir_callback_t callback, void* arg) {
const char* parent_name = parent->name;
size_t total;
const char* prefix;

if (strcmp(parent_name, "node") == 0) {
total = g_pal_public_state->topo_info.online_nodes_cnt;
total = g_pal_public_state->topo_info.online_nodes.resource_cnt;
prefix = "node";
} else if (strcmp(parent_name, "cpu") == 0) {
total = g_pal_public_state->topo_info.online_logical_cores_cnt;
total = g_pal_public_state->topo_info.online_logical_cores.resource_cnt;
prefix = "cpu";
} else if (strcmp(parent_name, "cache") == 0) {
total = g_pal_public_state->topo_info.cache_indices_cnt;
Expand Down
36 changes: 22 additions & 14 deletions LibOS/shim/src/fs/sys/node_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,19 @@
#include "shim_fs_pseudo.h"

int sys_node_general_load(struct shim_dentry* dent, char** out_data, size_t* out_size) {
int ret;
const char* name = dent->name;
const char* str;
if (strcmp(name, "online") == 0) {
str = g_pal_public_state->topo_info.online_nodes;
} else {
if (strcmp(name, "online") != 0) {
log_debug("unrecognized file: %s", name);
return -ENOENT;
}

char str[PAL_SYSFS_BUF_FILESZ] = {'\0'};
ret = sys_convert_ranges_to_str(&g_pal_public_state->topo_info.online_nodes, ",", str,
sizeof(str));
if (ret < 0)
return ret;

return sys_load(str, out_data, out_size);
}

Expand All @@ -32,25 +36,29 @@ int sys_node_load(struct shim_dentry* dent, char** out_data, size_t* out_size) {
return ret;

const char* name = dent->name;
struct pal_numa_topo_info* numa_topology =
&g_pal_public_state->topo_info.numa_topology_arr[node_num];
const char* str = NULL;
struct pal_numa_topo_info* numa_topo = &g_pal_public_state->topo_info.numa_topo_arr[node_num];
char str[PAL_SYSFS_MAP_FILESZ] = {'\0'};
if (strcmp(name, "cpumap" ) == 0) {
str = numa_topology->cpumap;
ret = sys_convert_ranges_to_cpu_bitmap_str(&numa_topo->cpumap, str, sizeof(str));
} else if (strcmp(name, "distance") == 0) {
str = numa_topology->distance;
ret = sys_convert_ranges_to_str(&numa_topo->distance, " ", str, sizeof(str));
} else if (strcmp(name, "nr_hugepages") == 0) {
const char* parent_name = dent->parent->name;
if (strcmp(parent_name, "hugepages-2048kB") == 0) {
str = numa_topology->hugepages[HUGEPAGES_2M].nr_hugepages;
ret = snprintf(str, sizeof(str), "%zu\n", numa_topo->nr_hugepages[HUGEPAGES_2M]);
} else if (strcmp(parent_name, "hugepages-1048576kB") == 0) {
str = numa_topology->hugepages[HUGEPAGES_1G].nr_hugepages;
ret = snprintf(str, sizeof(str), "%zu\n", numa_topo->nr_hugepages[HUGEPAGES_1G]);
} else {
log_debug("unrecognized hugepage file: %s", parent_name);
ret = -ENOENT;
}
}
if (!str) {
} else {
log_debug("unrecognized file: %s", name);
return -ENOENT;
ret = -ENOENT;
}

if (ret < 0)
return ret;

return sys_load(str, out_data, out_size);
}
2 changes: 1 addition & 1 deletion LibOS/shim/src/sys/shim_sched.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ long shim_do_sched_setaffinity(pid_t pid, unsigned int cpumask_size, unsigned lo

long shim_do_sched_getaffinity(pid_t pid, unsigned int cpumask_size, unsigned long* user_mask_ptr) {
int ret;
size_t cpu_cnt = g_pal_public_state->topo_info.online_logical_cores_cnt;
size_t cpu_cnt = g_pal_public_state->topo_info.online_logical_cores.resource_cnt;

/* Check if user_mask_ptr is valid */
if (!is_user_memory_writable(user_mask_ptr, cpumask_size))
Expand Down
Loading

0 comments on commit bc06c66

Please sign in to comment.