Skip to content
This repository has been archived by the owner on Jan 20, 2022. It is now read-only.

Refactor sysfs to improve sanitization #2661

Closed
Closed
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
17 changes: 17 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,21 @@ 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 integer to a string. When integer representation (enum value) of size multiplier like
*'K', 'M' or 'G' is passed, it is converted back to string and appended. When the size multiplier
* is `MULTIPLIER_NONE`, nothing is appended, and the integer is simply converted to a string. */
int sys_convert_int_to_sizestr(uint64_t val, uint64_t size_mult, char* str, size_t max_size);

/* Converts array of integer range(s) to a string. For example if res_range_info->ranges[0].start
* and res_range_info->ranges[0].end were 0 and 63 respectively, then `0-63` string is generated.
`sep` is used to seperate each generated range string. */
int sys_convert_ranges_to_str(const PAL_RES_RANGE_INFO* res_range_info, char* str, size_t max_size,
const char* sep);

/* Converts array of integer range(s) to a cpu bitmap string. For example, if
* res_range_info->ranges[0].start and res_range_info->ranges[0].end were 0 and 31 respectively,
* then `00000000,ffffffff` string is generated. */
int sys_convert_ranges_to_cpu_bitmap_str(const PAL_RES_RANGE_INFO* res_range_info, char* str,
size_t max_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 graphene 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 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) {
char buf[12];
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
107 changes: 105 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,108 @@
#include "shim_fs_pseudo.h"
#include "stat.h"

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

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

int sys_convert_ranges_to_str(const PAL_RES_RANGE_INFO* res_range_info, char* str, size_t max_size,
const char* sep) {
if (res_range_info->range_count > INT64_MAX)
return -EINVAL;

uint64_t range_cnt = res_range_info->range_count;
size_t offset = 0;
for (uint64_t i = 0; i < range_cnt; i++) {
if (offset > max_size)
return -ENOMEM;

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

if (ret < 0)
return ret;

offset += ret;
}
return 0;
}

int sys_convert_ranges_to_cpu_bitmap_str(const PAL_RES_RANGE_INFO* res_range_info, char* str,
size_t max_size) {
int ret;

if (g_pal_control->topo_info.possible_logical_cores.resource_count > INT64_MAX)
return -EINVAL;

if (res_range_info->range_count > INT64_MAX)
return -EINVAL;

/* 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 < res_range_info->range_count; i++) {
uint64_t start = res_range_info->ranges[i].start;
uint64_t end = res_range_info->ranges[i].end;
if (start > INT64_MAX || end > INT64_MAX) {
ret = -EINVAL;
goto out;
}
for (uint64_t j = start; j <= end; j++) {
uint64_t index = j / BITS_IN_TYPE(int);
if (index >= num_cpumask) {
ret = -EINVAL;
goto out;
}
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 > max_size) {
ret = -ENOMEM;
goto out;
}
ret = snprintf(str + offset, max_size - offset, "%08x%s", bitmap[j-1], (j-1 == 0) ? "\0" : ",");
if (ret < 0)
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 +124,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 +232,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 @@ -816,6 +816,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