Здесь вы go, пример, написанный на C (скомпилированный на linux 5.4 и работающий должным образом):
#define _GNU_SOURCE
#define _POSIX_C_SOURCE 200809L
#include <sys/types.h>
#include <sys/mman.h>
#include <unistd.h>
#include <err.h>
#include <errno.h>
size_t min(size_t x, size_t y)
{
return x > y ? y : x;
}
/**
* @param len != 0
*/
void fdput(int fd, const char *str, size_t len)
{
size_t cnt = 0;
do {
ssize_t result = write(fd, str + cnt, min(len - cnt, 0x7ffff000));
if (result == -1) {
if (errno == EINTR)
continue;
err(1, "%s failed", "write");
}
cnt += result;
} while (cnt != len);
}
#define fdputc(fd, constant_str) fdput((fd), (constant_str), sizeof(constant_str) - 1)
int main(int argc, char* argv[])
{
int fd = memfd_create("script", 0);
if (fd == -1)
err(1, "%s failed", "memfd_create");
fdputc(fd, "#!/bin/bash\necho Hello, world!");
{
const char * const argv[] = {"script", NULL};
const char * const envp[] = {NULL};
fexecve(fd, (char * const *) argv, (char * const *) envp);
}
err(1, "%s failed", "fexecve");
}
Я также тестировал с вызовом fork()
непосредственно перед fexecve
, и он также работает должным образом.
Вот код (в основном идентичный приведенному выше):
#define _GNU_SOURCE
#define _POSIX_C_SOURCE 200809L
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <unistd.h>
#include <err.h>
#include <errno.h>
size_t min(size_t x, size_t y)
{
return x > y ? y : x;
}
/**
* @param len != 0
*/
void fdput(int fd, const char *str, size_t len)
{
size_t cnt = 0;
do {
ssize_t result = write(fd, str + cnt, min(len - cnt, 0x7ffff000));
if (result == -1) {
if (errno == EINTR)
continue;
err(1, "%s failed", "write");
}
cnt += result;
} while (cnt != len);
}
#define fdputc(fd, constant_str) fdput((fd), (constant_str), sizeof(constant_str) - 1)
int main(int argc, char* argv[])
{
int fd = memfd_create("script", 0);
if (fd == -1)
err(1, "%s failed", "memfd_create");
fdputc(fd, "#!/bin/bash\necho Hello, world!");
pid_t pid = fork();
if (pid == 0) {
const char * const argv[] = {"script", NULL};
const char * const envp[] = {NULL};
fexecve(fd, (char * const *) argv, (char * const *) envp);
err(1, "%s failed", "fexecve");
} else if (pid == -1)
err(1, "%s failed", "fork");
wait(NULL);
return 0;
}