Jia
Jia

Reputation: 2581

fork/exec /proc/self/exe: operation not permitted

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

Answers (2)

ElSaeed
ElSaeed

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

terminal

Upvotes: -1

Toisen
Toisen

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

Related Questions