Skip to content

Instantly share code, notes, and snippets.

@hinzundcode
Created January 16, 2018 01:24
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save hinzundcode/6ce03dcd62bd5571fc3c1ceea141f3d1 to your computer and use it in GitHub Desktop.
Save hinzundcode/6ce03dcd62bd5571fc3c1ceea141f3d1 to your computer and use it in GitHub Desktop.
call execve from nodejs!
const { syscall, getAddress } = require("libsys");
const os = require("os");
if (os.endianess() != "LE")
throw "only little endian supported";
let dontGC = [];
function ref(buffer) {
dontGC.push(buffer);
return getAddress(buffer);
}
const pointerSize = 8;
const SYS_execve = 59;
const SYS_dup2 = 33;
// Buffer.from(string) doesn't append a null byte
function stringToBuffer(string) {
let buffer = Buffer.alloc(Buffer.byteLength(string)+1, 0);
buffer.write(string);
return buffer;
}
function stringArrayToBuffer(strings) {
let buffer = Buffer.alloc((strings.length+1)*pointerSize, 0);
let offset = 0;
for (let string of strings) {
let stringBuffer = stringToBuffer(string);
let pos = ref(stringBuffer);
buffer.writeInt32LE(pos[0], offset);
buffer.writeInt32LE(pos[1], offset+4);
offset += 8;
}
return buffer;
}
function dup2(oldfd, newfd) {
return syscall(SYS_dup2, oldfd, newfd);
}
function execve(cmd, argv, envp) {
let cmdBuf = stringToBuffer(cmd);
let argvBuf = stringArrayToBuffer(argv);
let envpBuf = stringArrayToBuffer(envp);
return syscall(SYS_execve, cmdBuf, argvBuf, envpBuf);
}
let cmd = "/bin/ls";
let argv = ["/bin/ls", "-la"];
let envp = [
"HOME=/",
"PATH=/bin",
];
dup2(process.stdin._handle.fd, 0);
dup2(process.stdout._handle.fd, 1);
dup2(process.stderr._handle.fd, 2);
execve(cmd, argv, envp);
@karlbohlmark
Copy link

Hi, this looks useful! I'm replacing a docker container bootstrap script written in bash with the equivalent in nodejs and the missing piece is the final exec call. Using this code it works nicely when I run docker in interactive mode, but when I remove -it I don't get the standard output after the execve call. I would greatly appreciate if you could give me a pointer. (I skip the dup2 call if stdout._handle.fd === 1 and so on)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment