Class: OsCtld::BpfFs
- Inherits:
-
Object
- Object
- OsCtld::BpfFs
- Extended by:
- Forwardable
- Includes:
- OsCtl::Lib::Utils::Log, OsCtl::Lib::Utils::System, Singleton
- Defined in:
- lib/osctld/bpf_fs.rb
Constant Summary collapse
- FS =
'/run/osctl/bpf'.freeze
- CT_FS =
'/run/osctl/ct-bpf'.freeze
- ROOT_DIR =
File.join(FS, 'osctl')
- PROG_DIR =
File.join(ROOT_DIR, 'progs')
- POOL_DIR =
File.join(ROOT_DIR, 'pools')
Instance Method Summary collapse
- #add_pool(pool_name) ⇒ Object
- #ct_mount_options(root_uid, root_gid) ⇒ Object protected
- #ct_mount_path(pool_name, ct_id) ⇒ Object
- #ct_pool_dir(pool_name) ⇒ Object protected
- #link_pin_path(pool_name, link_name) ⇒ Object
- #link_pinned?(pool_name, link_name) ⇒ Boolean
- #list_links(pool_name) ⇒ Object
- #list_progs ⇒ Object
- #log_type ⇒ Object
- #mount_type(path) ⇒ Object protected
- #pool_dir(pool_name) ⇒ Object protected
- #prog_pin_path(prog_name) ⇒ Object
- #prog_pinned?(prog_name) ⇒ Boolean
- #remove_ct(pool_name, ct_id) ⇒ Object
- #remove_pool(pool_name) ⇒ Object
- #setup ⇒ Object
- #setup_ct(pool_name, ct_id, root_uid:, root_gid:) ⇒ Object
-
#setup_host_mount ⇒ Object
protected
A generation switch does not run the boot-time mount setup.
Instance Method Details
#add_pool(pool_name) ⇒ Object
37 38 39 40 |
# File 'lib/osctld/bpf_fs.rb', line 37 def add_pool(pool_name) FileUtils.mkdir_p(File.join(pool_dir(pool_name), 'links')) FileUtils.mkdir_p(ct_pool_dir(pool_name)) end |
#ct_mount_options(root_uid, root_gid) ⇒ Object (protected)
148 149 150 151 152 153 154 155 156 157 |
# File 'lib/osctld/bpf_fs.rb', line 148 def (root_uid, root_gid) [ 'nosuid', 'nodev', 'noexec', "uid=#{Integer(root_uid)}", "gid=#{Integer(root_gid)}", 'mode=700' ].join(',') end |
#ct_mount_path(pool_name, ct_id) ⇒ Object
89 90 91 |
# File 'lib/osctld/bpf_fs.rb', line 89 def ct_mount_path(pool_name, ct_id) File.join(ct_pool_dir(pool_name), ct_id) end |
#ct_pool_dir(pool_name) ⇒ Object (protected)
144 145 146 |
# File 'lib/osctld/bpf_fs.rb', line 144 def ct_pool_dir(pool_name) File.join(CT_FS, pool_name) end |
#link_pin_path(pool_name, link_name) ⇒ Object
71 72 73 |
# File 'lib/osctld/bpf_fs.rb', line 71 def link_pin_path(pool_name, link_name) File.join(pool_dir(pool_name), 'links', link_name) end |
#link_pinned?(pool_name, link_name) ⇒ Boolean
75 76 77 |
# File 'lib/osctld/bpf_fs.rb', line 75 def link_pinned?(pool_name, link_name) File.file?(link_pin_path(pool_name, link_name)) end |
#list_links(pool_name) ⇒ Object
79 80 81 82 83 84 85 86 87 |
# File 'lib/osctld/bpf_fs.rb', line 79 def list_links(pool_name) dir = File.join(pool_dir(pool_name), 'links') Dir.entries(dir).select do |f| !%w[. ..].include?(f) && File.file?(File.join(dir, f)) end rescue Errno::ENOENT [] end |
#list_progs ⇒ Object
61 62 63 64 65 66 67 68 69 |
# File 'lib/osctld/bpf_fs.rb', line 61 def list_progs dir = PROG_DIR Dir.entries(dir).select do |f| !%w[. ..].include?(f) && File.file?(File.join(dir, f)) end rescue Errno::ENOENT [] end |
#log_type ⇒ Object
119 120 121 |
# File 'lib/osctld/bpf_fs.rb', line 119 def log_type 'bpf-fs' end |
#mount_type(path) ⇒ Object (protected)
159 160 161 162 163 164 165 166 167 168 169 |
# File 'lib/osctld/bpf_fs.rb', line 159 def mount_type(path) File.readlines('/proc/self/mountinfo').any? do |line| parts = line.split next unless parts.fetch(4) == path sep = parts.index('-') return parts.fetch(sep + 1) if sep end nil end |
#pool_dir(pool_name) ⇒ Object (protected)
140 141 142 |
# File 'lib/osctld/bpf_fs.rb', line 140 def pool_dir(pool_name) File.join(POOL_DIR, pool_name) end |
#prog_pin_path(prog_name) ⇒ Object
53 54 55 |
# File 'lib/osctld/bpf_fs.rb', line 53 def prog_pin_path(prog_name) File.join(PROG_DIR, prog_name) end |
#prog_pinned?(prog_name) ⇒ Boolean
57 58 59 |
# File 'lib/osctld/bpf_fs.rb', line 57 def prog_pinned?(prog_name) File.exist?(prog_pin_path(prog_name)) end |
#remove_ct(pool_name, ct_id) ⇒ Object
112 113 114 115 116 117 |
# File 'lib/osctld/bpf_fs.rb', line 112 def remove_ct(pool_name, ct_id) path = ct_mount_path(pool_name, ct_id) syscmd("umount -f #{Shellwords.escape(path)}", valid_rcs: [32]) if Dir.exist?(path) FileUtils.rm_rf(path, secure: true) end |
#remove_pool(pool_name) ⇒ Object
42 43 44 45 46 47 48 49 50 51 |
# File 'lib/osctld/bpf_fs.rb', line 42 def remove_pool(pool_name) if Dir.exist?(ct_pool_dir(pool_name)) Dir.each_child(ct_pool_dir(pool_name)) do |ct_id| remove_ct(pool_name, ct_id) end end FileUtils.rm_rf(ct_pool_dir(pool_name), secure: true) FileUtils.rm_rf(pool_dir(pool_name), secure: true) end |
#setup ⇒ Object
31 32 33 34 35 |
# File 'lib/osctld/bpf_fs.rb', line 31 def setup setup_host_mount FileUtils.mkdir_p(PROG_DIR) FileUtils.mkdir_p(CT_FS) end |
#setup_ct(pool_name, ct_id, root_uid:, root_gid:) ⇒ Object
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/osctld/bpf_fs.rb', line 93 def setup_ct(pool_name, ct_id, root_uid:, root_gid:) path = ct_mount_path(pool_name, ct_id) opts = (root_uid, root_gid) FileUtils.mkdir_p(path) mounted_type = mount_type(path) if mounted_type == 'bpf' syscmd("mount -o remount,#{Shellwords.escape(opts)} #{Shellwords.escape(path)}") else syscmd("umount -f #{Shellwords.escape(path)}", valid_rcs: [32]) if mounted_type syscmd("mount -t bpf -o #{Shellwords.escape(opts)} bpf #{Shellwords.escape(path)}") end syscmd("mount --make-rprivate #{Shellwords.escape(path)}") path end |
#setup_host_mount ⇒ Object (protected)
A generation switch does not run the boot-time mount setup. Bind the predecessor's existing bpffs so device programs and links stay pinned; mounting a fresh filesystem here would lose their userspace identities.
128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/osctld/bpf_fs.rb', line 128 def setup_host_mount mounted_type = mount_type(FS) return if mounted_type == 'bpf' raise "#{FS} is not a BPF filesystem" if mounted_type raise 'legacy BPF filesystem is not mounted' unless mount_type('/sys/fs/bpf') == 'bpf' FileUtils.mkdir_p(FS) syscmd("mount --bind /sys/fs/bpf #{FS}") syscmd("mount --make-rprivate #{FS}") end |