Documentation
¶
Overview ¶
Package execve is a wrapper around the system execve(2) and fexecve(3) system calls.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Execveat ¶
Execveat executes at program at a path using a file descriptor. The go runtime process image is replaced by the executable described by the directory file descriptor and pathname.
Example ¶
package main
import (
"fmt"
"os"
"codeberg.org/msantos/execve"
"golang.org/x/sys/unix"
)
func main() {
if err := os.Chdir("/bin"); err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
n := int32(unix.AT_FDCWD)
AT_FDCWD := uintptr(uint32(n))
if err := execve.Execveat(
AT_FDCWD,
"sh", []string{"sh", "-c", "echo test"},
[]string{},
0,
); err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
}
func Fexecve ¶
Fexecve executes the program referred to by a file descriptor. The go runtime process image is replaced with the executable referred to by the file descriptor. The file descriptor should be opened with the O_CLOEXEC flag set (the default when using os.Open) to prevent the fd from leaking to the new process image.
The exception to this rule is running scripts: the file descriptor must be opened without O_CLOEXEC.
BUG(fexecve): If fd refers to a script (i.e., it is an executable text file that names a script interpreter with a first line that begins with the characters #!) and the close-on-exec flag has been set for fd, then fexecve() fails with the error ENOENT. This error occurs because, by the time the script interpreter is executed, fd has already been closed because of the close-on-exec flag. Thus, the close-on-exec flag can't be set on fd if it refers to a script, leading to the problems described in NOTES (fexecve(3)).
Example ¶
package main
import (
"fmt"
"os"
"codeberg.org/msantos/execve"
)
func main() {
fd, err := os.Open("/bin/sh")
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
if err := execve.Fexecve(
fd.Fd(),
[]string{"sh", "-c", "echo test"},
[]string{},
); err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
}
Example (Memfd) ¶
ExampleFexecve_memfd is an example of running an executable from memory.
package main
import (
"fmt"
"io"
"os"
"os/exec"
"codeberg.org/msantos/execve"
"golang.org/x/sys/unix"
)
func main() {
path, err := exec.LookPath("echo")
if err != nil {
fmt.Fprintf(os.Stderr, "LookPath: %v", err)
return
}
exe, err := os.Open(path)
if err != nil {
fmt.Fprintf(os.Stderr, "Open: %v", err)
return
}
fd, err := unix.MemfdCreate("ExampleFexecve_memfd", unix.MFD_CLOEXEC)
if err != nil {
fmt.Fprintf(os.Stderr, "MemfdCreate: %v", err)
return
}
f := os.NewFile(uintptr(fd), "ExampleFexecve_memfd")
if _, err := io.Copy(f, exe); err != nil {
fmt.Fprintf(os.Stderr, "Copy: %v", err)
return
}
if err := execve.Fexecve(f.Fd(), []string{"-n", "test"}, os.Environ()); err != nil {
fmt.Fprintf(os.Stderr, "Fexecve: %v", err)
return
}
}
Example (Script) ¶
package main
import (
"fmt"
"os"
"syscall"
"codeberg.org/msantos/execve"
)
func main() {
// Make a shell script
file, err := os.CreateTemp("", "script")
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
if _, err := file.Write([]byte("#!/bin/sh\necho $@")); err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
if err := file.Chmod(0o755); err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
if err := file.Close(); err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
// Get a file descriptor with O_CLOEXEC unset
fd, err := syscall.Open(file.Name(), syscall.O_RDONLY, 0)
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
sh := fmt.Sprintf("/dev/fd/%d", fd)
if err := execve.Fexecve(
uintptr(fd),
[]string{sh, "test"},
[]string{},
); err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
}
Types ¶
This section is empty.
Notes ¶
Bugs ¶
If fd refers to a script (i.e., it is an executable text file that names a script interpreter with a first line that begins with the characters #!) and the close-on-exec flag has been set for fd, then fexecve() fails with the error ENOENT. This error occurs because, by the time the script interpreter is executed, fd has already been closed because of the close-on-exec flag. Thus, the close-on-exec flag can't be set on fd if it refers to a script, leading to the problems described in NOTES (fexecve(3)).
Directories
¶
| Path | Synopsis |
|---|---|
|
examples
|
|
|
dfdexe
command
Dfdexe embeds and runs a directory of executables from memory.
|
Dfdexe embeds and runs a directory of executables from memory. |
|
fdexe
command
Fdexe embeds and runs an executable from memory.
|
Fdexe embeds and runs an executable from memory. |
|
ioexe
command
Ioexe reads and runs an executable from stdin.
|
Ioexe reads and runs an executable from stdin. |