179 lines
4.0 KiB
C++
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;
|
|
}
|