static const char* unique_string(const char *name) { int unique = 2; string_set::iterator i = all_strings.find(name); if (i == all_strings.end()) return register_string(name); while (true) { vector<char> n(strlen(name)+10); snprintf(&n[0], n.size(), "%s %d", name, unique++); string_set::iterator i = all_strings.find(&n[0]); if (i == all_strings.end()) return register_string(&n[0]); } }
static void free_strings(string_set &s) { for (string_set::iterator i=s.begin(); i!=s.end(); i++) { free((void*)*i); } s.clear(); }
string_set operator+(const string_set& a_, const string_set& b_) { string_set r(a_); for (string_set::iterator i = b_.begin(), e = b_.end(); i != e; ++i) { r._data.insert(*i); } return r; }
/** Build the chroot at the path **/ bool WorkerBee::build_chroot(const std::string &path, uid_t user, gid_t group, string_set &executables, string_set &extra_dirs) { // Make the root path make_path(strdup(path.c_str())); string_set already_copied; std::string full_path; // The base directories string_set base_dirs; base_dirs.insert("bin"); base_dirs.insert("usr"); base_dirs.insert("var"); base_dirs.insert("lib"); base_dirs.insert("home"); base_dirs.insert("etc"); // Add the extra directories requested for (string_set::iterator dir = extra_dirs.begin(); dir != extra_dirs.end(); ++dir) base_dirs.insert(dir->c_str()); for (string_set::iterator dir = base_dirs.begin(); dir != base_dirs.end(); ++dir) { if ((*dir->c_str()) == '/') full_path = path + *dir; else full_path = path + '/' + *dir; // Make the paths make_path(full_path.c_str()); } // Build the root libraries for (string_set::iterator executable = executables.begin(); executable != executables.end(); ++executable) { // If we are pointed at an absolute path to a binary // then find the linked libraries of the executable // If it's not found, then find it, then look up the libraries std::string res_bin; if (abs_path(*executable)) res_bin = *executable; else { res_bin = find_binary(*executable); } // The libraries for the resolved binary bee_files_set *s_libs = libs_for(res_bin); // collect the libraries and copy them to the full path of the chroot for (bee_files_set::iterator bf = s_libs->begin(); bf != s_libs->end(); ++bf) { BeeFile bee = *bf; std::string s (bee.file_path()); // Don't copy if the file is already copied if (already_copied.count(s)) { } else { // If it is a symlink, then make a symlink, otherwise copy the file // If the library starts with a '/' then don't add one, otherwise, do // i.e. if libs/hi.so.1 turns into full_path/libs/hi.so.1 otherwise libs.so.1 turns into full_path/libs.so.1 if (s.c_str()[0] == '/') full_path = path + s.c_str(); else full_path = path + '/' + s.c_str(); if (bee.is_link()) { // make symlink make_path(dirname(strdup(full_path.c_str()))); if (symlink(bee.sym_origin().c_str(), full_path.c_str())) { fprintf(stderr, "Could not make a symlink: %s to %s because %s\n", bee.sym_origin().c_str(), full_path.c_str(), strerror(errno)); } } else { // Copy the file (recursively) cp_r(s, full_path); } // Change the permissions to match the original file struct stat file_stats = bee.file_stats(); mode_t mode = file_stats.st_mode; if (chown(full_path.c_str(), user, group) != 0) { fprintf(stderr, "Could not change owner of '%s' to %i\n", full_path.c_str(), user); } if (chmod(full_path.c_str(), mode) != 0) { fprintf(stderr, "Could not change permissions to '%s' %o\n", full_path.c_str(), mode); } // Add it to the already_copied set and move on already_copied.insert(s); } } // Copy the executables and make them executable std::string bin_path = path + '/' + res_bin; cp_r(res_bin.c_str(), bin_path.c_str()); if (chown(bin_path.c_str(), user, group) != 0) { fprintf(stderr, "Could not change owner of '%s' to %i\n", bin_path.c_str(), user); } if (chmod(bin_path.c_str(), S_IREAD|S_IEXEC|S_IXGRP|S_IRGRP|S_IWRITE)) { fprintf(stderr, "Could not change permissions to '%s' make it executable\n", bin_path.c_str()); } } return true; }