lindows/lsmss/main.cxx
2024-03-05 17:46:15 -05:00

179 lines
4.0 KiB
C++

#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>
#include <filesystem>
#include <vector>
#include <unistd.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/mount.h>
#include <dlfcn.h>
#include <lindows/lrss.h>
void PiiLog(const std::string& message);
[[noreturn]] void PiiAbortBoot();
/**
i* State for a subsystem managed by LSMSS
*/
class PiiSubsystemState {
// -- General info --
std::string SubsystemName; // Subsystem display name in debug logs
bool Running = false; // Subsystem is running
// -- Linux information --
pid_t LnxPid = 0; // PID
std::filesystem::path LnxPath; // Binary path
public:
// -- Constructors --
PiiSubsystemState(const std::string& name, const std::filesystem::path& path) {
this->SubsystemName = name;
this->LnxPath = path;
return;
}
// -- General --
/**
* Start the subsystem process
*/
void Start() {
PiiLog("Starting subsystem " + this->SubsystemName);
if (pid_t child = fork()) {
// save the process id
this->LnxPid = child;
this->Running = true;
while (true) {
int status;
if (waitpid(this->LnxPid, &status, WUNTRACED) < 0) {
perror("waitpid");
PiiLog("Failed to start " + this->SubsystemName);
this->Running = false;
return;
}
if (WIFEXITED(status)) {
PiiLog("Failed to start " + this->SubsystemName + " (Exit code " + std::to_string(WEXITSTATUS(status)) + ")");
this->Running = false;
return;
}
if (WIFSTOPPED(status)) {
if (kill(this->LnxPid, SIGCONT) < 0) {
perror("kill");
PiiLog("Failed to start " + this->SubsystemName + ". Unknown state, boot process cannot continue.");
PiiAbortBoot();
}
PiiLog("Started subsystem " + this->SubsystemName);
return;
}
}
return;
} else {
char* args[] = { strdup(this->LnxPath.c_str()), nullptr };
execv(args[0], args);
// this should never happen
std::exit(1);
}
}
};
/**
* Log something.
*
* \param message to log
*/
void PiiLog(const std::string& message) {
std::cout << message << "\n";
return;
}
/**
* execute a program from an absolute path
*
* \param path absolute path to program (duh)
* \return program return value, 1 if it does not exist or -1 on error
*/
int PiiExecuteProgram(const std::string& path) {
if (pid_t child = fork()) {
int exitcode = -1;
waitpid(child, &exitcode, 0);
return exitcode;
} else {
char* args[] = { strdup(path.c_str()), nullptr };
execv(args[0], args);
// this should only be reached if we cant load the program
std::exit(1);
}
}
/**
* Abort the boot process and drop the user into a recovery shell
*/
[[noreturn]]
void PiiAbortBoot() {
PiiLog("Unable to complete preinitialization. You have been dropped into a minimal recovery environment. Good luck.");
PiiExecuteProgram("/Windows/System32/bash.exe");
std::exit(1);
}
int main() {
std::vector<PiiSubsystemState> subsystems {};
// -- just print shit --
PiiLog("Starting Lindows Session Manager Subsystem");
// -- dynamic linking fun --
PiiLog("Regenerating dynamic linker cache");
PiiExecuteProgram("/Windows/System32/ldconfig.exe");
// -- registry --
PiiLog("Starting Lindows Registry Subsystem");
subsystems.emplace(subsystems.end(), "Lindows Registry Subsystem", "/Windows/System32/lrss.exe")
->Start(); // We don't actually know if this started, we aren't in the mainloop. We just have to pray :>
PiiLog("Loading Lindows registry");
auto liblrssclient = dlopen("/Windows/System32/liblrssclient.so", RTLD_NOW);
auto pLrcOpenRegistry = reinterpret_cast<decltype(LrcOpenRegistry)*>(dlsym(liblrssclient, "LrcOpenRegistry"));
if (auto error = dlerror()) {
PiiLog(error);
PiiAbortBoot();
}
if (pLrcOpenRegistry()) {
PiiLog("Failed to connect to registry subsystem.");
PiiAbortBoot();
}
// TODO
// -- swap --
PiiLog("Creating pagefiles");
// TODO
// -- env --
PiiLog("Setting environment variables");
// TODO
// we are never ok
PiiAbortBoot();
return 0;
}