Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor sysfs to improve sanitization #106

Closed
19 changes: 19 additions & 0 deletions LibOS/shim/include/shim_fs_pseudo.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,4 +209,23 @@ 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 an integer to a string, optionally appending a given single-letter unit suffix
* (see enum size_multiplier for possible values).
* Note: This function adds a newline at end of the string. */
int sys_convert_int_to_sizestr(uint64_t val, enum size_multiplier size_mult, char* str,
size_t buf_size);

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

/* Converts 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 end of the string. */
int sys_convert_ranges_to_cpu_bitmap_str(const PAL_RES_RANGE_INFO* resource_range_info, char* str,
size_t buf_size);

#endif /* SHIM_FS_PSEUDO_H_ */
7 changes: 4 additions & 3 deletions LibOS/shim/src/fs/proc/info.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,8 @@ int proc_cpuinfo_load(struct shim_dentry* dent, char** out_data, size_t* out_siz
size += ret; \
} while (0)

for (size_t n = 0; n < g_pal_control->cpu_info.online_logical_cores; n++) {
uint64_t online_logical_cores = g_pal_control->topo_info.online_logical_cores.resource_count;
for (uint64_t n = 0; n < online_logical_cores; n++) {
/* 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", n);
Expand All @@ -122,9 +123,9 @@ int proc_cpuinfo_load(struct shim_dentry* dent, char** out_data, size_t* out_siz
ADD_INFO("model\t\t: %lu\n", g_pal_control->cpu_info.cpu_model);
ADD_INFO("model name\t: %s\n", g_pal_control->cpu_info.cpu_brand);
ADD_INFO("stepping\t: %lu\n", g_pal_control->cpu_info.cpu_stepping);
ADD_INFO("physical id\t: %d\n", g_pal_control->cpu_info.cpu_socket[n]);
ADD_INFO("physical id\t: %d\n", g_pal_control->topo_info.core_topology[n].cpu_socket);
ADD_INFO("core id\t\t: %lu\n", n);
ADD_INFO("cpu cores\t: %lu\n", g_pal_control->cpu_info.physical_cores_per_socket);
ADD_INFO("cpu cores\t: %lu\n", g_pal_control->topo_info.physical_cores_per_socket);
double bogomips = g_pal_control->cpu_info.cpu_bogomips;
// Apparently Gramine snprintf cannot into floats.
ADD_INFO("bogomips\t: %lu.%02lu\n", (unsigned long)bogomips,
Expand Down
33 changes: 24 additions & 9 deletions LibOS/shim/src/fs/sys/cache_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,25 +27,40 @@ int sys_cache_load(struct shim_dentry* dent, char** out_data, size_t* out_size)

const char* name = dent->name;
PAL_CORE_CACHE_INFO* cache = &g_pal_control->topo_info.core_topology[cpu_num].cache[cache_num];
const char* str;
char str[PAL_SYSFS_MAP_FILESZ] = {'\0'};
if (strcmp(name, "shared_cpu_map") == 0) {
str = cache->shared_cpu_map;
ret = sys_convert_ranges_to_cpu_bitmap_str(&cache->shared_cpu_map, str, sizeof(str));
} else if (strcmp(name, "level") == 0) {
str = cache->level;
ret = sys_convert_int_to_sizestr(cache->level, MULTIPLIER_NONE, str, sizeof(str));
} else if (strcmp(name, "type") == 0) {
str = cache->type;
switch (cache->type) {
case CACHE_TYPE_DATA:
ret = snprintf(str, sizeof(str), "%s", "Data\n");
break;
case CACHE_TYPE_INSTRUCTION:
ret = snprintf(str, sizeof(str), "%s", "Instruction\n");
break;
case CACHE_TYPE_UNIFIED:
ret = snprintf(str, sizeof(str), "%s", "Unified\n");
break;
default:
ret = -ENOENT;
}
} else if (strcmp(name, "size") == 0) {
str = cache->size;
ret = sys_convert_int_to_sizestr(cache->size, cache->size_multiplier, str, sizeof(str));
} else if (strcmp(name, "coherency_line_size") == 0) {
str = cache->coherency_line_size;
ret = sys_convert_int_to_sizestr(cache->coherency_line_size, MULTIPLIER_NONE, str, sizeof(str));
} else if (strcmp(name, "number_of_sets") == 0) {
str = cache->number_of_sets;
ret = sys_convert_int_to_sizestr(cache->number_of_sets, MULTIPLIER_NONE, str, sizeof(str));
} else if (strcmp(name, "physical_line_partition") == 0) {
str = cache->physical_line_partition;
ret = sys_convert_int_to_sizestr(cache->physical_line_partition, MULTIPLIER_NONE, 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);
}
34 changes: 21 additions & 13 deletions LibOS/shim/src/fs/sys/cpu_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,23 @@
#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_control->topo_info.online_logical_cores;
ret = sys_convert_ranges_to_str(&g_pal_control->topo_info.online_logical_cores, str,
sizeof(str), ",");
} else if (strcmp(name, "possible") == 0) {
str = g_pal_control->topo_info.possible_logical_cores;
ret = sys_convert_ranges_to_str(&g_pal_control->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,27 +42,30 @@ int sys_cpu_load(struct shim_dentry* dent, char** out_data, size_t* out_size) {

const char* name = dent->name;
PAL_CORE_TOPO_INFO* core_topology = &g_pal_control->topo_info.core_topology[cpu_num];
const char* str;
char buf[12];
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 = sys_convert_int_to_sizestr(core_topology->is_logical_core_online, MULTIPLIER_NONE,
str, sizeof(str));
} else if (strcmp(name, "core_id") == 0) {
str = core_topology->core_id;
ret = sys_convert_int_to_sizestr(core_topology->core_id, MULTIPLIER_NONE, str, sizeof(str));
} else if (strcmp(name, "physical_package_id") == 0) {
snprintf(buf, sizeof(buf), "%d\n", g_pal_control->cpu_info.cpu_socket[cpu_num]);
str = buf;
ret = sys_convert_int_to_sizestr(core_topology->cpu_socket, MULTIPLIER_NONE, str,
sizeof(str));
} 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
118 changes: 116 additions & 2 deletions LibOS/shim/src/fs/sys/fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,119 @@
#include "shim_fs_pseudo.h"
#include "stat.h"

int sys_convert_int_to_sizestr(uint64_t val, enum size_multiplier size_mult, char* str,
size_t buf_size) {
int ret = 0;

switch (size_mult) {
case MULTIPLIER_KB:
ret = snprintf(str, buf_size, "%luK\n", val);
break;
case MULTIPLIER_MB:
ret = snprintf(str, buf_size, "%luM\n", val);
break;
case MULTIPLIER_GB:
ret = snprintf(str, buf_size, "%luG\n", val);
break;
default:
ret = snprintf(str, buf_size, "%lu\n", val);
break;
}

if (ret >= (int)buf_size)
ret = -EOVERFLOW;
return ret;
}

int sys_convert_ranges_to_str(const PAL_RES_RANGE_INFO* resource_range_info, char* str,
size_t buf_size, const char* sep) {
uint64_t range_cnt = resource_range_info->range_count;
size_t offset = 0;
for (uint64_t i = 0; i < range_cnt; i++) {
if (offset > buf_size)
return -ENOMEM;

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

if (ret < 0)
return ret;

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

offset += ret;
}
return 0;
}

int sys_convert_ranges_to_cpu_bitmap_str(const PAL_RES_RANGE_INFO* resource_range_info, char* str,
size_t buf_size) {
int ret;

/* Extract cpumask from the ranges */
uint64_t possible_cores = g_pal_control->topo_info.possible_logical_cores.resource_count;
uint64_t num_cpumask = BITS_TO_INTS(possible_cores);
uint32_t* bitmap = (uint32_t*)calloc(num_cpumask, sizeof(uint32_t));
if (!bitmap)
return -ENOMEM;

for (uint64_t i = 0; i < resource_range_info->range_count; i++) {
uint64_t start = resource_range_info->ranges[i].start;
uint64_t end = resource_range_info->ranges[i].end;

for (uint64_t j = start; j <= end; j++) {
uint64_t index = j / BITS_IN_TYPE(int);
assert(index < num_cpumask);

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

/* Convert cpumask to strings */
size_t offset = 0;
for (uint64_t j = num_cpumask; j > 0; j--) {
if (offset > buf_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_cores >= 32) {
ret = snprintf(str + offset, buf_size - offset, "%08x%s", bitmap[j-1],
(j-1 == 0) ? "\n" : ",");
} else {
ret = snprintf(str + offset, buf_size - offset, "%x%s", bitmap[j-1],
(j-1 == 0) ? "\n" : ",");
}

if (ret < 0)
goto out;

/* Truncation has occurred */
if ((size_t)ret >= buf_size) {
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;
Expand All @@ -22,10 +135,10 @@ static int sys_resource(struct shim_dentry* parent, const char* name, unsigned i
const char* prefix;

if (strcmp(parent_name, "node") == 0) {
pal_total = g_pal_control->topo_info.num_online_nodes;
pal_total = g_pal_control->topo_info.nodes.resource_count;
prefix = "node";
} else if (strcmp(parent_name, "cpu") == 0) {
pal_total = g_pal_control->cpu_info.online_logical_cores;
pal_total = g_pal_control->topo_info.online_logical_cores.resource_count;
prefix = "cpu";
} else if (strcmp(parent_name, "cache") == 0) {
pal_total = g_pal_control->topo_info.num_cache_index;
Expand Down Expand Up @@ -130,6 +243,7 @@ static void init_cpu_dir(struct pseudo_node* cpu) {
pseudo_add_str(indexX, "type", &sys_cache_load);
pseudo_add_str(indexX, "size", &sys_cache_load);
pseudo_add_str(indexX, "coherency_line_size", &sys_cache_load);
pseudo_add_str(indexX, "number_of_sets", &sys_cache_load);
pseudo_add_str(indexX, "physical_line_partition", &sys_cache_load);
}

Expand Down
35 changes: 23 additions & 12 deletions LibOS/shim/src/fs/sys/node_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,20 @@
#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_control->topo_info.online_nodes;
} else {
char str[PAL_SYSFS_BUF_FILESZ] = {'\0'};

if (strcmp(name, "online") != 0) {
log_debug("unrecognized file: %s", name);
return -ENOENT;
}

ret = sys_convert_ranges_to_str(&g_pal_control->topo_info.nodes, str, sizeof(str), ",");
if (ret < 0)
return ret;

return sys_load(str, out_data, out_size);
}

Expand All @@ -33,23 +38,29 @@ int sys_node_load(struct shim_dentry* dent, char** out_data, size_t* out_size) {

const char* name = dent->name;
PAL_NUMA_TOPO_INFO* numa_topology = &g_pal_control->topo_info.numa_topology[node_num];
const char* str = NULL;
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_topology->cpumap, str, sizeof(str));
} else if (strcmp(name, "distance") == 0) {
str = numa_topology->distance;
ret = sys_convert_ranges_to_str(&numa_topology->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 = sys_convert_int_to_sizestr(numa_topology->nr_hugepages[HUGEPAGES_2M],
MULTIPLIER_NONE, str, sizeof(str));
} else if (strcmp(parent_name, "hugepages-1048576kB") == 0) {
str = numa_topology->hugepages[HUGEPAGES_1G].nr_hugepages;
ret = sys_convert_int_to_sizestr(numa_topology->nr_hugepages[HUGEPAGES_1G],
MULTIPLIER_NONE, str, sizeof(str));
} 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_control->cpu_info.online_logical_cores;
size_t cpu_cnt = g_pal_control->topo_info.online_logical_cores.resource_count;

/* Check if user_mask_ptr is valid */
if (!is_user_memory_writable(user_mask_ptr, cpumask_size))
Expand Down
1 change: 1 addition & 0 deletions LibOS/shim/test/regression/test_libos.py
Original file line number Diff line number Diff line change
Expand Up @@ -886,6 +886,7 @@ def test_040_sysfs(self):
self.assertIn(f'{cache}/type: file', lines)
self.assertIn(f'{cache}/size: file', lines)
self.assertIn(f'{cache}/coherency_line_size: file', lines)
self.assertIn(f'{cache}/number_of_sets: file', lines)
self.assertIn(f'{cache}/physical_line_partition: file', lines)

self.assertIn('/sys/devices/system/node: directory', lines)
Expand Down
Loading