Skip to content

Instantly share code, notes, and snippets.

@Garciat
Created February 22, 2025 19:25
Show Gist options
  • Save Garciat/db79dbed7af7c439abf23b80f049a373 to your computer and use it in GitHub Desktop.
Save Garciat/db79dbed7af7c439abf23b80f049a373 to your computer and use it in GitHub Desktop.
const libc = Deno.dlopen(
"libc.so.6",
{
dup2: {
parameters: ["i32", "i32"],
result: "i32",
},
errno: {
type: "i32",
},
},
);
function findUnixSocketPathInode(path: string) {
const out = Deno.readTextFileSync("/proc/net/unix");
const rg = new RegExp("([0-9]+) " + path);
const match = out.match(rg);
if (match === null) {
return null;
}
return parseInt(match[1]);
}
function findProcessFileDescriptorByInode(pid: number, inode: number) {
for (const entry of Deno.readDirSync(`/proc/${pid}/fd`)) {
const stat = Deno.statSync(`/proc/${pid}/fd/${entry.name}`);
if (stat.ino === inode) {
return parseInt(entry.name);
}
}
return null;
}
function hijackFileDescriptorAsUnixSocketListener(
fd: number,
): Deno.UnixListener {
const tmpDir = Deno.makeTempDirSync();
const tmpFile = `${tmpDir}/tmp.sock`;
try {
const listener = Deno.listen({
path: tmpFile,
transport: "unix",
});
const socketInode = findUnixSocketPathInode(tmpFile);
if (socketInode === null) {
listener.close();
throw new Error("could not find socket inode");
}
const socketFd = findProcessFileDescriptorByInode(Deno.pid, socketInode);
if (socketFd === null) {
listener.close();
throw new Error("could not find socket file descriptor");
}
const ret = libc.symbols.dup2(fd, socketFd);
if (ret === -1) {
listener.close();
throw new Error("dup2() errno: " + libc.symbols.errno);
}
if (ret !== socketFd) {
listener.close();
throw new Error("unexpected");
}
return listener;
} finally {
Deno.removeSync(tmpFile);
Deno.removeSync(tmpDir);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment