Class: FrrCliFuzzer::LinuxNamespace

Inherits:
Object
  • Object
show all
Defined in:
lib/frr-cli-fuzzer/linux_namespace.rb

Instance Method Summary collapse

Constructor Details

#initializeLinuxNamespace

Returns a new instance of LinuxNamespace.



3
4
5
6
7
8
9
10
11
# File 'lib/frr-cli-fuzzer/linux_namespace.rb', line 3

def initialize
  fork_and_unshare do
    # This is the init process of the new PID namespace. We need to reap
    # the zombies.
    trap(:CHLD) { Process.wait }
    trap(:INT, :IGNORE)
    sleep
  end
end

Instance Method Details

#fork_and_unshareObject

Create a child process running on a separate network and mount namespace.



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/frr-cli-fuzzer/linux_namespace.rb', line 14

def fork_and_unshare
  io_in, io_out = IO.pipe

  LibC.prctl(FrrCliFuzzer::LibC::PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0)

  pid = Kernel.fork do
    LibC.unshare(LibC::CLONE_NEWNS | LibC::CLONE_NEWPID | LibC::CLONE_NEWNET)

    # Fork again to use the new PID namespace.
    # Need to supress a warning that is irrelevant for us.
    warn_level = $VERBOSE
    $VERBOSE = nil
    pid = Kernel.fork do
      # HACK: kill when parent dies.
      trap(:SIGUSR1) do
        LibC.prctl(LibC::PR_SET_PDEATHSIG, 15, 0, 0, 0)
        trap(:SIGUSR1, :IGNORE)
      end
      LibC.prctl(LibC::PR_SET_PDEATHSIG, 10, 0, 0, 0)

      mount_propagation(LibC::MS_REC | LibC::MS_PRIVATE)
      mount_proc
      yield
    end
    $VERBOSE = warn_level
    io_out.puts(pid)
    exit(0)
  end

  @pid = io_in.gets.to_i
  Process.waitpid(pid)
rescue SystemCallError => e
  warn "System call error:: #{e.message}"
  warn e.backtrace
  exit(1)
end

#mount_procObject

Mount the proc filesystem (useful after creating a new PID namespace).



57
58
59
60
61
# File 'lib/frr-cli-fuzzer/linux_namespace.rb', line 57

def mount_proc
  LibC.mount("none", "/proc", nil, LibC::MS_REC | LibC::MS_PRIVATE, nil)
  LibC.mount("proc", "/proc", "proc",
             LibC::MS_NOSUID | LibC::MS_NOEXEC | LibC::MS_NODEV, nil)
end

#mount_propagation(flags) ⇒ Object

Set the mount propagation of the process.



52
53
54
# File 'lib/frr-cli-fuzzer/linux_namespace.rb', line 52

def mount_propagation(flags)
  LibC.mount("none", "/", nil, flags, nil)
end

#nsenterObject

nsenter(1) is a standard tool from the util-linux package. It can be used to run a program with namespaces of other processes.



65
66
67
# File 'lib/frr-cli-fuzzer/linux_namespace.rb', line 65

def nsenter
  "nsenter -t #{@pid} --mount --pid --net"
end