Reputation: 2581
I am following : Containers From Scratch • Liz Rice • GOTO 2018 and test the source code lizrice/containers-from-scratch locally to learn containers.
But with code below , I am not able to fork a child process on Ubuntu 1804, below are my main.go
package main
import (
"fmt"
"os"
"os/exec"
"syscall"
)
// go run main.go run <cmd> <args>
func main() {
switch os.Args[1] {
case "run":
run()
case "child":
child()
default:
panic("help")
}
}
func run() {
fmt.Printf("In <Run> Running %v \n", os.Args[2:])
cmd := exec.Command("/proc/self/exe", append([]string{"child"}, os.Args[2:]...)...)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.SysProcAttr = &syscall.SysProcAttr{
Cloneflags: syscall.CLONE_NEWUTS,
}
must(cmd.Run())
}
func child() {
fmt.Printf("In <child> Running %v \n", os.Args[2:])
cmd := exec.Command(os.Args[2], os.Args[3:]...)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
syscall.Sethostname([]byte("container"))
must(cmd.Run())
}
func must(err error) {
if err != nil {
panic(err)
}
}
I tried to run it :
go run main1.go run /bin/bash
Error below occurred:
In <Run> Running [/bin/bash]
panic: fork/exec /proc/self/exe: operation not permitted
goroutine 1 [running]:
main.must(...)
/home/jia/cs_study_plan/docker/containers-from-scratch/main1.go:72
main.run()
/home/jia/cs_study_plan/docker/containers-from-scratch/main1.go:44 +0x27f
main.main()
/home/jia/cs_study_plan/docker/containers-from-scratch/main1.go:17 +0x4d
exit status 2
Any suggestion how can I fix this permission issue in my main.go ?
Thank you @Peter for suggestions. I could run my app use 'go build' and 'sudo'
Here is what I do
1. go to directory of main1.go
2. go mod init main1 <it must be the same name as main1.go>
3. go mod tidy <it is optional step>
4. gp build
5. main1 is build in current directory
6. run command :
sudo ./main1 run /bin/bash
7. child forked successfully , as I can tell from my output
In <Run> Running [/bin/bash]
In <child> Running [/bin/bash]
ps
PID TTY TIME CMD
15774 pts/0 00:00:00 sudo
15775 pts/0 00:00:00 main1
15781 pts/0 00:00:00 exe
15786 pts/0 00:00:00 bash
16047 pts/0 00:00:00 ps
Also I tried to disable 'AppArmor' in my Ubunut , see if that is what blocks main1.go from fork child process
$sudo systemctl status apparmor
[sudo] password for jia:
● apparmor.service - AppArmor initialization
Loaded: loaded (/lib/systemd/system/apparmor.service; enabled; vendor preset: enabled)
Active: active (exited) since Thu 2022-06-09 08:31:21 CST; 2h 3min ago
Docs: man:apparmor(7)
http://wiki.apparmor.net/
Main PID: 660 (code=exited, status=0/SUCCESS)
Tasks: 0 (limit: 4915)
CGroup: /system.slice/apparmor.service
Jun 09 08:31:21 ub1804 apparmor[660]: * Starting AppArmor profiles
Jun 09 08:31:21 ub1804 apparmor[660]: Skipping profile in /etc/apparmor.d/disable: usr.bin.firefox
Jun 09 08:31:21 ub1804 apparmor[660]: Skipping profile in /etc/apparmor.d/disable: usr.sbin.rsyslogd
Jun 09 08:31:21 ub1804 systemd[1]: Starting AppArmor initialization...
Jun 09 08:31:21 ub1804 apparmor[660]: ...done.
Jun 09 08:31:21 ub1804 systemd[1]: Started AppArmor initialization.
$sudo systemctl stop apparmor
$go run main1.go run echo hello
In <Run> Running [echo hello]
panic: fork/exec /proc/self/exe: operation not permitted
NO luck , if anyone knows what stops my main1.go to fork child , please let me know , thanks in advance
Upvotes: 1
Views: 3856
Reputation: 1
I have encountered the same problem and solved it as follows
sudo su
export PATH=$PATH:/usr/local/go/bin
# change dir where main.go live in
go run main.go run /bin/bash
and it worked for me
Upvotes: -1
Reputation: 39
Your problem appears because Ubuntu has sudo preinstalled so your user has restricted rights. According to proc documentation, it provides an interface for kernel data structures and represents a pseudo-filesystem. The /proc is mounted by the system itself as read-only, but you are trying to create a new process inside this file system which is read-only for your current user. You can read more about it in the man https://man7.org/linux/man-pages/man5/proc.5.html
TL;DR: you need to run your program as a root.
Upvotes: -1