mirror of
https://gitee.com/spark-store-project/spark-store
synced 2026-06-22 06:03:49 +08:00
fix pkexec lookup for privilege escalation
This commit is contained in:
@@ -6,6 +6,7 @@ import pino from "pino";
|
|||||||
|
|
||||||
import { ChannelPayload } from "../../typedefinition";
|
import { ChannelPayload } from "../../typedefinition";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
import { findExecutable, SUPER_USER_COMMAND_CANDIDATES } from "./superuser";
|
||||||
|
|
||||||
const logger = pino({ name: "install-manager" });
|
const logger = pino({ name: "install-manager" });
|
||||||
|
|
||||||
@@ -43,42 +44,11 @@ type InstallTask = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const SHELL_CALLER_PATH = "/opt/spark-store/extras/shell-caller.sh";
|
const SHELL_CALLER_PATH = "/opt/spark-store/extras/shell-caller.sh";
|
||||||
const SUPER_USER_COMMAND_CANDIDATES = [
|
|
||||||
"/usr/bin/pkexec",
|
|
||||||
"/run/wrappers/bin/pkexec",
|
|
||||||
"pkexec",
|
|
||||||
];
|
|
||||||
|
|
||||||
export const tasks = new Map<number, InstallTask>();
|
export const tasks = new Map<number, InstallTask>();
|
||||||
|
|
||||||
let idle = true; // Indicates if the installation manager is idle
|
let idle = true; // Indicates if the installation manager is idle
|
||||||
|
|
||||||
const findExecutable = async (command: string): Promise<string> => {
|
|
||||||
if (path.isAbsolute(command)) {
|
|
||||||
try {
|
|
||||||
await fs.promises.access(command, fs.constants.X_OK);
|
|
||||||
return command;
|
|
||||||
} catch {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return await new Promise((resolve) => {
|
|
||||||
const child = spawn("which", [command]);
|
|
||||||
let stdout = "";
|
|
||||||
|
|
||||||
child.stdout?.on("data", (data) => {
|
|
||||||
stdout += data.toString();
|
|
||||||
});
|
|
||||||
child.on("close", (code) => {
|
|
||||||
resolve(code === 0 ? stdout.trim() : "");
|
|
||||||
});
|
|
||||||
child.on("error", () => {
|
|
||||||
resolve("");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const checkSuperUserCommand = async (): Promise<string> => {
|
export const checkSuperUserCommand = async (): Promise<string> => {
|
||||||
if (process.getuid?.() === 0) return "";
|
if (process.getuid?.() === 0) return "";
|
||||||
|
|
||||||
|
|||||||
@@ -8,15 +8,11 @@ import * as fs from "node:fs";
|
|||||||
import * as path from "node:path";
|
import * as path from "node:path";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import pino from "pino";
|
import pino from "pino";
|
||||||
|
import { findExecutable, SUPER_USER_COMMAND_CANDIDATES } from "./superuser";
|
||||||
|
|
||||||
const logger = pino({ name: "shared-installer" });
|
const logger = pino({ name: "shared-installer" });
|
||||||
|
|
||||||
export const SHELL_CALLER_PATH = "/opt/spark-store/extras/shell-caller.sh";
|
export const SHELL_CALLER_PATH = "/opt/spark-store/extras/shell-caller.sh";
|
||||||
const SUPER_USER_COMMAND_CANDIDATES = [
|
|
||||||
"/usr/bin/pkexec",
|
|
||||||
"/run/wrappers/bin/pkexec",
|
|
||||||
"pkexec",
|
|
||||||
];
|
|
||||||
|
|
||||||
export interface DownloadOptions {
|
export interface DownloadOptions {
|
||||||
pkgname: string;
|
pkgname: string;
|
||||||
@@ -363,29 +359,3 @@ export const checkSuperUserCommand = async (): Promise<string> => {
|
|||||||
logger.error("没有找到提升权限的命令 pkexec!");
|
logger.error("没有找到提升权限的命令 pkexec!");
|
||||||
return "";
|
return "";
|
||||||
};
|
};
|
||||||
|
|
||||||
const findExecutable = async (command: string): Promise<string> => {
|
|
||||||
if (path.isAbsolute(command)) {
|
|
||||||
try {
|
|
||||||
await fs.promises.access(command, fs.constants.X_OK);
|
|
||||||
return command;
|
|
||||||
} catch {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return await new Promise((resolve) => {
|
|
||||||
const child = spawn("which", [command]);
|
|
||||||
let stdout = "";
|
|
||||||
|
|
||||||
child.stdout?.on("data", (data) => {
|
|
||||||
stdout += data.toString();
|
|
||||||
});
|
|
||||||
child.on("close", (code) => {
|
|
||||||
resolve(code === 0 ? stdout.trim() : "");
|
|
||||||
});
|
|
||||||
child.on("error", () => {
|
|
||||||
resolve("");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
import { spawn } from "node:child_process";
|
||||||
|
import fs from "node:fs";
|
||||||
|
import path from "node:path";
|
||||||
|
|
||||||
|
export const SUPER_USER_COMMAND_CANDIDATES = [
|
||||||
|
"/usr/bin/pkexec",
|
||||||
|
"/run/wrappers/bin/pkexec",
|
||||||
|
];
|
||||||
|
|
||||||
|
const WHICH_TIMEOUT_MS = 5000;
|
||||||
|
|
||||||
|
export const findExecutable = async (command: string): Promise<string> => {
|
||||||
|
if (path.isAbsolute(command)) {
|
||||||
|
try {
|
||||||
|
await fs.promises.access(command, fs.constants.X_OK);
|
||||||
|
return command;
|
||||||
|
} catch {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return await new Promise<string>((resolve) => {
|
||||||
|
const child = spawn("which", [command]);
|
||||||
|
let stdout = "";
|
||||||
|
let settled = false;
|
||||||
|
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
child.kill();
|
||||||
|
finish("");
|
||||||
|
}, WHICH_TIMEOUT_MS);
|
||||||
|
|
||||||
|
function finish(result: string) {
|
||||||
|
if (settled) return;
|
||||||
|
settled = true;
|
||||||
|
clearTimeout(timer);
|
||||||
|
resolve(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
child.stdout?.on("data", (data) => {
|
||||||
|
stdout += data.toString();
|
||||||
|
});
|
||||||
|
child.on("close", (code) => {
|
||||||
|
finish(code === 0 ? stdout.trim() : "");
|
||||||
|
});
|
||||||
|
child.on("error", () => {
|
||||||
|
finish("");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user