Class: Sandbox::Landlock
- Inherits:
-
LinuxBackend
- Object
- LinuxBackend
- Sandbox::Landlock
- Includes:
- Utils::Output::Mixin
- Defined in:
- extend/os/linux/sandbox/landlock.rb
Class Method Summary collapse
- .abi_version ⇒ Integer? private
- .available? ⇒ Boolean private
- .close_file_descriptor(file_descriptor) ⇒ Integer private
- .configuration_command_messages ⇒ Array<String> private
- .configuration_commands ⇒ Array<String> private
- .configure! ⇒ void private
- .ensure_installed!(install_from_tests: false) ⇒ void private
- .failure_reason ⇒ String? private
-
.full_write_isolation? ⇒ Boolean
private
Landlock cannot restrict chmod, chown, extended attributes or timestamp changes.
- .install_command ⇒ String? private
- .landlock_add_rule(ruleset_fd, type, attributes, flags) ⇒ Integer private
- .landlock_create_ruleset(attributes, size, flags) ⇒ Integer private
- .landlock_restrict_self(ruleset_fd, flags) ⇒ Integer private
- .last_error ⇒ Integer private
- .nested_sandbox? ⇒ Boolean private
- .open_path(path) ⇒ Integer private
- .reset_state! ⇒ void private
- .set_no_new_privileges ⇒ Integer private
- .state ⇒ Symbol private
Instance Method Summary collapse
- #apply! ⇒ void private
- #command(args, tmpdir) ⇒ Array<String, ::Pathname> private
- #initialize(profile) ⇒ void constructor private
Methods included from Utils::Output::Mixin
#issue_reporting_message, #odebug, #odeprecated, #odie, #odisabled, #ofail, #oh1, #oh1_title, #ohai, #ohai_title, #onoe, #opoo, #opoo_outside_github_actions, #opoo_without_github_actions_annotation, #pretty_deprecated, #pretty_disabled, #pretty_duration, #pretty_install_status, #pretty_installed, #pretty_uninstalled, #pretty_unmarked, #pretty_upgradable, #pretty_warning
Methods inherited from LinuxBackend
Constructor Details
#initialize(profile) ⇒ void
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
282 283 284 285 286 287 288 289 |
# File 'extend/os/linux/sandbox/landlock.rb', line 282 def initialize(profile) super @writable_paths = T.let([], T::Array[String]) @readable_paths = T.let([], T::Array[String]) @error_pipe_path = T.let(nil, T.nilable(String)) @deny_all_network = T.let(false, T::Boolean) @deny_read = T.let(false, T::Boolean) end |
Class Method Details
.abi_version ⇒ Integer?
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
105 106 107 108 |
# File 'extend/os/linux/sandbox/landlock.rb', line 105 def abi_version state @abi_version end |
.available? ⇒ Boolean
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
95 96 97 |
# File 'extend/os/linux/sandbox/landlock.rb', line 95 def available? state == :available end |
.close_file_descriptor(file_descriptor) ⇒ Integer
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
227 228 229 230 231 232 233 234 235 236 237 |
# File 'extend/os/linux/sandbox/landlock.rb', line 227 def close_file_descriptor(file_descriptor) @close ||= T.let( Fiddle::Function.new( Fiddle.dlopen(nil)["close"], [Fiddle::TYPE_INT], Fiddle::TYPE_INT, ), T.nilable(Fiddle::Function), ) @close.call(file_descriptor) end |
.configuration_command_messages ⇒ Array<String>
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
153 |
# File 'extend/os/linux/sandbox/landlock.rb', line 153 def = [] |
.configuration_commands ⇒ Array<String>
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
150 |
# File 'extend/os/linux/sandbox/landlock.rb', line 150 def configuration_commands = [] |
.configure! ⇒ void
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
This method returns an undefined value.
145 146 147 |
# File 'extend/os/linux/sandbox/landlock.rb', line 145 def configure! ensure_available! end |
.ensure_installed!(install_from_tests: false) ⇒ void
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
This method returns an undefined value.
142 |
# File 'extend/os/linux/sandbox/landlock.rb', line 142 def ensure_installed!(install_from_tests: false); end |
.failure_reason ⇒ String?
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'extend/os/linux/sandbox/landlock.rb', line 111 def failure_reason case state when :available nil when :config_disabled "Landlock cannot be used because Linux sandboxing is disabled." when :missing_fiddle "Landlock requires Ruby's bundled Fiddle library." when :unsupported "Landlock is not supported by this Linux kernel." when :disabled "Landlock is disabled by this Linux kernel." when :unsupported_abi abi = @abi_version if abi "Landlock ABI #{MINIMUM_ABI} or later is required; found ABI #{abi}." else "Landlock ABI #{MINIMUM_ABI} or later is required." end else "Landlock is not available." end end |
.full_write_isolation? ⇒ Boolean
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
Landlock cannot restrict chmod, chown, extended attributes or timestamp changes. Callers requiring Bubblewrap-equivalent write isolation must compensate for these limitations: https://www.kernel.org/doc/html/latest/userspace-api/landlock.html#filesystem-flags
92 |
# File 'extend/os/linux/sandbox/landlock.rb', line 92 def full_write_isolation? = false |
.install_command ⇒ String?
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
156 |
# File 'extend/os/linux/sandbox/landlock.rb', line 156 def install_command = nil |
.landlock_add_rule(ruleset_fd, type, attributes, flags) ⇒ Integer
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
175 176 177 178 179 180 181 182 183 184 185 |
# File 'extend/os/linux/sandbox/landlock.rb', line 175 def landlock_add_rule(ruleset_fd, type, attributes, flags) @landlock_add_rule ||= T.let( Fiddle::Function.new( Fiddle.dlopen(nil)["syscall"], [Fiddle::TYPE_LONG, Fiddle::TYPE_INT, Fiddle::TYPE_INT, Fiddle::TYPE_VOIDP, Fiddle::TYPE_UINT], Fiddle::TYPE_LONG, ), T.nilable(Fiddle::Function), ) @landlock_add_rule.call(ADD_RULE_SYSCALL, ruleset_fd, type, attributes, flags) end |
.landlock_create_ruleset(attributes, size, flags) ⇒ Integer
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
162 163 164 165 166 167 168 169 170 171 172 |
# File 'extend/os/linux/sandbox/landlock.rb', line 162 def landlock_create_ruleset(attributes, size, flags) @landlock_create_ruleset ||= T.let( Fiddle::Function.new( Fiddle.dlopen(nil)["syscall"], [Fiddle::TYPE_LONG, Fiddle::TYPE_VOIDP, Fiddle::TYPE_SIZE_T, Fiddle::TYPE_UINT], Fiddle::TYPE_LONG, ), T.nilable(Fiddle::Function), ) @landlock_create_ruleset.call(CREATE_RULESET_SYSCALL, attributes, size, flags) end |
.landlock_restrict_self(ruleset_fd, flags) ⇒ Integer
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
188 189 190 191 192 193 194 195 196 197 198 |
# File 'extend/os/linux/sandbox/landlock.rb', line 188 def landlock_restrict_self(ruleset_fd, flags) @landlock_restrict_self ||= T.let( Fiddle::Function.new( Fiddle.dlopen(nil)["syscall"], [Fiddle::TYPE_LONG, Fiddle::TYPE_INT, Fiddle::TYPE_UINT], Fiddle::TYPE_LONG, ), T.nilable(Fiddle::Function), ) @landlock_restrict_self.call(RESTRICT_SELF_SYSCALL, ruleset_fd, flags) end |
.last_error ⇒ Integer
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
240 241 242 |
# File 'extend/os/linux/sandbox/landlock.rb', line 240 def last_error Fiddle.last_error end |
.nested_sandbox? ⇒ Boolean
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
159 |
# File 'extend/os/linux/sandbox/landlock.rb', line 159 def nested_sandbox? = false |
.open_path(path) ⇒ Integer
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
214 215 216 217 218 219 220 221 222 223 224 |
# File 'extend/os/linux/sandbox/landlock.rb', line 214 def open_path(path) @open ||= T.let( Fiddle::Function.new( Fiddle.dlopen(nil)["open"], [Fiddle::TYPE_CONST_STRING, Fiddle::TYPE_INT], Fiddle::TYPE_INT, ), T.nilable(Fiddle::Function), ) @open.call(path, O_PATH | O_CLOEXEC) end |
.reset_state! ⇒ void
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
This method returns an undefined value.
136 137 138 139 |
# File 'extend/os/linux/sandbox/landlock.rb', line 136 def reset_state! @state = T.let(nil, T.nilable(Symbol)) @abi_version = T.let(nil, T.nilable(Integer)) end |
.set_no_new_privileges ⇒ Integer
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
201 202 203 204 205 206 207 208 209 210 211 |
# File 'extend/os/linux/sandbox/landlock.rb', line 201 def set_no_new_privileges @prctl ||= T.let( Fiddle::Function.new( Fiddle.dlopen(nil)["prctl"], [Fiddle::TYPE_INT, Fiddle::TYPE_ULONG, Fiddle::TYPE_ULONG, Fiddle::TYPE_ULONG, Fiddle::TYPE_ULONG], Fiddle::TYPE_INT, ), T.nilable(Fiddle::Function), ) @prctl.call(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) end |
.state ⇒ Symbol
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
100 101 102 |
# File 'extend/os/linux/sandbox/landlock.rb', line 100 def state @state ||= T.let(compute_state, T.nilable(Symbol)) end |
Instance Method Details
#apply! ⇒ void
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
This method returns an undefined value.
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 |
# File 'extend/os/linux/sandbox/landlock.rb', line 305 def apply! abi = self.class.abi_version if !abi || abi < MINIMUM_ABI raise self.class.failure_reason || "Landlock ABI #{MINIMUM_ABI} or later is required." end if @deny_all_network && abi < MINIMUM_FULL_NETWORK_ABI opoo "Landlock ABI #{MINIMUM_FULL_NETWORK_ABI} or later is required to deny all network access; " \ "found ABI #{abi}. Applying the network restrictions supported by this kernel." end attributes, handled_access_fs, allowed_write_access_fs = ruleset_attributes(abi) ruleset_fd = self.class.landlock_create_ruleset(attributes, attributes.bytesize, 0) raise_system_call_error("landlock_create_ruleset") if ruleset_fd.negative? begin # PTY allocation opens `/dev/ptmx` read-write, then configures its # dynamically allocated `/dev/pts/*` slave with device ioctls: # https://github.com/torvalds/linux/blob/master/drivers/tty/pty.c # https://www.kernel.org/doc/html/latest/userspace-api/landlock.html#ioctl-support pty_access = ACCESS_FS_WRITE_FILE pty_access |= ACCESS_FS_IOCTL_DEV if abi >= 5 pty_access |= ACCESS_FS_READ_FILE if @deny_read ["/dev/ptmx", "/dev/pts"].each do |path| next unless File.exist?(path) add_path_rule(ruleset_fd, path, pty_access) end error_pipe_path = @error_pipe_path if @deny_all_network && abi >= 9 && error_pipe_path add_path_rule(ruleset_fd, error_pipe_path, ACCESS_FS_RESOLVE_UNIX) end @readable_paths.each do |path| allowed_access = File.directory?(path) ? READ_ACCESS_FS : FILE_READ_ACCESS_FS add_path_rule(ruleset_fd, path, allowed_access) end @writable_paths.each do |path| allowed_access = if File.directory?(path) allowed_write_access_fs else allowed_write_access_fs & FILE_WRITE_ACCESS_FS end add_path_rule(ruleset_fd, path, allowed_access & handled_access_fs) end raise_system_call_error("prctl") if self.class.set_no_new_privileges.negative? if self.class.landlock_restrict_self(ruleset_fd, 0).negative? raise_system_call_error("landlock_restrict_self") end ensure close_file_descriptor(ruleset_fd) end end |
#command(args, tmpdir) ⇒ Array<String, ::Pathname>
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
292 293 294 295 296 297 298 299 300 301 302 |
# File 'extend/os/linux/sandbox/landlock.rb', line 292 def command(args, tmpdir) paths = writable_paths @writable_paths = paths.keys | [File::NULL, tmpdir] @writable_paths.each { |path| prepare_writable_path(path, paths.fetch(path, :subpath)) } denied_read_paths = self.denied_read_paths @readable_paths = readable_paths(denied_read_paths) @deny_read = denied_read_paths.any? @deny_all_network = deny_all_network? @error_pipe_path = File.join(tmpdir, "socket") args end |