[Add] Enforce file permissions.

This commit is contained in:
Ritchie Cunningham 2025-11-06 19:47:35 +00:00
parent d852d8449f
commit 4057e0f876
5 changed files with 64 additions and 0 deletions

View File

@ -27,6 +27,11 @@ std::string rm(Session& context, const std::string& filename) {
return "rm: cannot remove '" + filename + "': Is a directory."; return "rm: cannot remove '" + filename + "': Is a directory.";
} }
vfs_node* parent_dir = it->second->parent;
if(parent_dir && !has_permission(parent_dir, context, WRITE_PERM)) {
return "rm: cannot remove '" + filename + "': Permission denied";
}
delete it->second; /* Free the memory for the node. */ delete it->second; /* Free the memory for the node. */
current_dir->children.erase(it); /* Remove from map. */ current_dir->children.erase(it); /* Remove from map. */
return ""; return "";
@ -65,6 +70,10 @@ std::string write_file(Session& context, const std::string& path,
return "write: cannot create file in '" + get_full_path(parent_dir) + "': Not a directory"; return "write: cannot create file in '" + get_full_path(parent_dir) + "': Not a directory";
} }
if(!has_permission(parent_dir, context, WRITE_PERM)) {
return "write: cannot create file '" + path + "': Permission denied";
}
auto it = parent_dir->children.find(filename); auto it = parent_dir->children.find(filename);
if(it != parent_dir->children.end()) { if(it != parent_dir->children.end()) {
if(it->second->type == DIR_NODE) { if(it->second->type == DIR_NODE) {
@ -114,6 +123,10 @@ std::string create_executable(Session& context, const std::string& path,
+ "': Not a directory"; + "': Not a directory";
} }
if(!has_permission(parent_dir, context, WRITE_PERM)) {
return "create_executable: cannot create file '" + path + "': Permission denied";
}
/* Overwrite if exists. */ /* Overwrite if exists. */
auto it = parent_dir->children.find(filename); auto it = parent_dir->children.find(filename);
if(it != parent_dir->children.end()) { if(it != parent_dir->children.end()) {
@ -129,6 +142,10 @@ std::string create_executable(Session& context, const std::string& path,
} }
std::string read_file(Session& context, const std::string& path) { std::string read_file(Session& context, const std::string& path) {
vfs_node* node = find_node_by_path(context.get_session_machine()->vfs_root, path);
if(node && !has_permission(node, context, READ_PERM)) {
return "cat: " + path + ": Permission denied";
}
return context.read_file(path); return context.read_file(path);
} }
@ -142,6 +159,9 @@ std::string cd(Session& context, const std::string& path) {
} else { } else {
auto it = current_dir->children.find(path); auto it = current_dir->children.find(path);
if(it != current_dir->children.end() && it->second->type == DIR_NODE) { if(it != current_dir->children.end() && it->second->type == DIR_NODE) {
if(!has_permission(it->second, context, EXEC_PERM)) {
return "cd: " + path + ": Permission denied";
}
context.set_current_dir(it->second); context.set_current_dir(it->second);
} else { } else {
return "cd: no such file or directory: " + path; return "cd: no such file or directory: " + path;

View File

@ -70,6 +70,14 @@ void Session::set_session_machine(Machine* machine) {
} }
} }
uint32_t Session::get_current_uid(void) {
return _home_machine->owner_id;
}
uint32_t Session::get_current_gid(void) {
return _home_machine->owner_id;
}
std::string Session::process_command(const std::string& command) { std::string Session::process_command(const std::string& command) {
/* /*
* Creating the Lua processor on-demand to ensure it exists on the same * Creating the Lua processor on-demand to ensure it exists on the same
@ -113,6 +121,9 @@ std::string Session::process_command(const std::string& command) {
if(command_node) { if(command_node) {
if(command_node->type == EXEC_NODE) { if(command_node->type == EXEC_NODE) {
if(!has_permission(command_node, *this, EXEC_PERM)) {
return "Cannot execute '" + command_name + "': Permission denied.";
}
bool is_remote = (_session_machine != _home_machine); bool is_remote = (_session_machine != _home_machine);
std::string deobfuscated_content = util::xor_string(command_node->content); std::string deobfuscated_content = util::xor_string(command_node->content);
sol::object result = lua.execute(deobfuscated_content, *this, args, is_remote); sol::object result = lua.execute(deobfuscated_content, *this, args, is_remote);

View File

@ -29,6 +29,9 @@ public:
MachineManager* get_machine_manager(void); MachineManager* get_machine_manager(void);
INetworkBridge* get_network_bridge(void); INetworkBridge* get_network_bridge(void);
uint32_t get_current_uid(void);
uint32_t get_current_gid(void);
void set_current_dir(vfs_node* node); void set_current_dir(vfs_node* node);
void set_session_machine(Machine* machine); void set_session_machine(Machine* machine);

View File

@ -1,6 +1,30 @@
#include <sstream> #include <sstream>
#include "vfs.h" #include "vfs.h"
#include "session.h"
bool has_permission(vfs_node* node, Session& context, uint8_t required_perm) {
uint32_t uid = context.get_current_uid();
if(uid == 0) { /* Root user. */
return true;
}
uint32_t gid = context.get_current_gid();
uint16_t perms = node->permissions;
if(node->owner_id == uid) {
/* Check owner permissions. */
return ((perms >> 6) & required_perm) == required_perm;
} else if(node->group_id == gid) {
/* Check group permissions. */
return ((perms >> 3) & required_perm) == required_perm;
} else {
/* Check other permissions. */
return (perms & required_perm) == required_perm;
}
return false;
}
/* Create a new node. */ /* Create a new node. */
vfs_node* new_node(std::string name, vfs_node_type type, vfs_node* parent, vfs_node* new_node(std::string name, vfs_node_type type, vfs_node* parent,

View File

@ -4,6 +4,7 @@
#include <string> #include <string>
#include <map> #include <map>
class Session;
struct vfs_node; struct vfs_node;
/* Store children for quick lookup by name. */ /* Store children for quick lookup by name. */
@ -33,6 +34,11 @@ struct vfs_node {
vfs_node* parent; vfs_node* parent;
}; };
const uint8_t READ_PERM = 4;
const uint8_t WRITE_PERM = 2;
const uint8_t EXEC_PERM = 1;
bool has_permission(vfs_node* node, Session& context, uint8_t required_perm);
vfs_node* new_node(std::string name, vfs_node_type type, vfs_node* parent, vfs_node* new_node(std::string name, vfs_node_type type, vfs_node* parent,
uint32_t owner_id = 0, uint32_t group_id = 0, uint16_t permissions=0755); uint32_t owner_id = 0, uint32_t group_id = 0, uint16_t permissions=0755);
vfs_node* find_node_by_id(vfs_node* root, long long id); vfs_node* find_node_by_id(vfs_node* root, long long id);