In-Memory-Only ELF Execution Without Tmpfs
magisterquis.github.io
magisterquis.github.io
The payload executable is extracted to a temporary file. When running as root, this is done by mounting a tmpfs file system and lazily unmounting it before the extraction.
What I mean is:
- to go from a memfd to anonymous memory, you can call mmap(2) on the fd
- to go from anonymous memory to a memfd, you...?
Security issues aside, I can imagine maintaining compiled code for stored procedures in database BLOBs.
Similarly, in an appropriate trust environment, I might want to ship work units to remote machines in the form of raw ELF. Copying the bits to disk just to execute them is unneeded overhead.
I wonder if there's a way to execute from mlock'd or madvised memory. I can imagine this be particularly useful, if you wanted to prevent your injected program (malware? valuable IP?) from being written to disk or appearing in a core dump.
> otherwise the API would not have been introduced
I don't think memfd_create was added specifically for the purpose of running binaries from memory; it's more generally useful in cases where you want a memory-backed file but don't want to rely on the presence of a memory-backed filesystem (tmpfs). Many programs create a file in a well-known tmpfs like /dev/shm then delete it, but memfd_create is a more sensible solution if you don't want to share memory via the filesystem. memfd_create eliminates concerns over naming and collisions.
The memfd api has lots of other uses, the fact you can exec is just a byproduct.
It is in fact silly since write and execute are orthogonal. You can mount a filesystem as noexec. Although memfd does put a bullet into W^X aspirations.
It doesn't work worth shbang-based scripts, though; that just returns ENOENT. Makes sense, I suppose.
snprintf(pathbuf, sizeof(pathbuf), "/proc/self/fd/%u", fd);
execve(pathbuf, argv, envp);
you do execveat(fd, "", argv, envp, AT_EMPTY_PATH);
and that's it.And you can use '$FH->autoflush(1)' instead of the eye-watering 'select((select($FH), $|=1)[0])'
From https://metacpan.org/pod/perl5120delta#Other-potentially-inc... :
> Filehandles are now always blessed into IO::File.
> The previous behaviour was to bless Filehandles into FileHandle (an empty proxy class) if it was loaded into memory and otherwise to bless them into IO::Handle.
https://metacpan.org/pod/perl5140delta#Filehandle-method-cal...
When a method call on a filehandle would die because the method cannot be resolved and IO::File has not been loaded, Perl now loads IO::File via require and attempts method resolution again