Class: Straycall::Policy::Filesystem
- Inherits:
-
Object
- Object
- Straycall::Policy::Filesystem
- Defined in:
- lib/straycall/policy/filesystem.rb
Constant Summary collapse
- AT_FDCWD =
-100
- WRITE_FLAGS =
Fcntl::O_WRONLY | Fcntl::O_RDWR | Fcntl::O_CREAT | Fcntl::O_TRUNC | Fcntl::O_APPEND
Instance Method Summary collapse
- #active? ⇒ Boolean
- #allow_write_under(path) ⇒ Object
- #allowed_write?(path) ⇒ Boolean
- #denied_read?(path) ⇒ Boolean
- #deny_read(path) ⇒ Object
- #deny_write_elsewhere! ⇒ Object
-
#initialize(cache_size: 4096) ⇒ Filesystem
constructor
A new instance of Filesystem.
- #marshal_dump ⇒ Object
- #marshal_load(values) ⇒ Object
- #read_denials? ⇒ Boolean
- #resolve(path, tid:, dirfd: AT_FDCWD) ⇒ Object
- #write?(flags) ⇒ Boolean
Constructor Details
#initialize(cache_size: 4096) ⇒ Filesystem
Returns a new instance of Filesystem.
11 12 13 14 15 16 17 18 19 20 |
# File 'lib/straycall/policy/filesystem.rb', line 11 def initialize(cache_size: 4096) raise ArgumentError, "cache_size must be positive" unless cache_size.is_a?(Integer) && cache_size.positive? @write_default = :allow @write_roots = [] @read_denials = [] @cache_size = cache_size @cache = {} @mutex = Mutex.new end |
Instance Method Details
#active? ⇒ Boolean
37 38 39 |
# File 'lib/straycall/policy/filesystem.rb', line 37 def active? @write_default == :deny || !@read_denials.empty? end |
#allow_write_under(path) ⇒ Object
22 23 24 25 |
# File 'lib/straycall/policy/filesystem.rb', line 22 def allow_write_under(path) @write_roots << normalize_config_path(path) clear_cache end |
#allowed_write?(path) ⇒ Boolean
49 50 51 52 53 |
# File 'lib/straycall/policy/filesystem.rb', line 49 def allowed_write?(path) cached([:write, path]) do @write_default == :allow || path.match?(%r{\A/proc/(?:self|\d+)/task/\d+/comm\z}) || @write_roots.any? { |root| under?(path, root) } end end |
#denied_read?(path) ⇒ Boolean
55 56 57 |
# File 'lib/straycall/policy/filesystem.rb', line 55 def denied_read?(path) cached([:read, path]) { @read_denials.any? { |root| under?(path, root) } } end |
#deny_read(path) ⇒ Object
32 33 34 35 |
# File 'lib/straycall/policy/filesystem.rb', line 32 def deny_read(path) @read_denials << normalize_config_path(path) clear_cache end |
#deny_write_elsewhere! ⇒ Object
27 28 29 30 |
# File 'lib/straycall/policy/filesystem.rb', line 27 def deny_write_elsewhere! @write_default = :deny clear_cache end |
#marshal_dump ⇒ Object
72 73 74 |
# File 'lib/straycall/policy/filesystem.rb', line 72 def marshal_dump [@write_default, @write_roots, @read_denials, @cache_size] end |
#marshal_load(values) ⇒ Object
76 77 78 79 80 |
# File 'lib/straycall/policy/filesystem.rb', line 76 def marshal_load(values) @write_default, @write_roots, @read_denials, @cache_size = values @cache = {} @mutex = Mutex.new end |
#read_denials? ⇒ Boolean
41 42 43 |
# File 'lib/straycall/policy/filesystem.rb', line 41 def read_denials? !@read_denials.empty? end |
#resolve(path, tid:, dirfd: AT_FDCWD) ⇒ Object
59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/straycall/policy/filesystem.rb', line 59 def resolve(path, tid:, dirfd: AT_FDCWD) return File.(path) if path.start_with?(File::SEPARATOR) base = if signed(dirfd) == AT_FDCWD File.readlink("/proc/#{tid}/cwd") else File.readlink("/proc/#{tid}/fd/#{signed(dirfd)}") end.delete_suffix(" (deleted)") File.(path, base) rescue SystemCallError => error raise PathResolutionError, "cannot resolve target path through /proc: #{error.}" end |
#write?(flags) ⇒ Boolean
45 46 47 |
# File 'lib/straycall/policy/filesystem.rb', line 45 def write?(flags) (flags & WRITE_FLAGS).positive? end |