bsdcapsicum.rb 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5d83ead7ffc798a1957614930e629c867be433fc59a7138327ccae20e2bb35d4
4
- data.tar.gz: 9b91b67471e6cd11ebc3eced51face9e8cae9f96136763666e110b175c4a8f55
3
+ metadata.gz: 68cc91e740a2c2e8586db3884729be9c4fcefe8de403876ff805ac2bdaa3575b
4
+ data.tar.gz: d71319a3f9a56b63faef409ea27647ea93796eedda15658ad28bf9a9cd395066
5
5
  SHA512:
6
- metadata.gz: 315f60aad74e7db220c09cedc03fa4072fbd483de4cf851c6351f0df599249fc7752d892fc304636f4ca08d80735c88f7bc366854d4323f582d7406760c9c40a
7
- data.tar.gz: ab6a6c0b337f9ddcbf98e97053379bba9c585d51ecc02b1cd72f55ef9add3be5bcf26d3d0da310d939230a9fb2bf66a483f3accefe94e3d4ad8c729efdefbc76
6
+ metadata.gz: 94b898fee6872449599545d87fd4d52e9231b6e6d7424d58d3bfc7b22e97c84d5b10719821581bc590822e49464703503a284d9205def2ccba65670d300f97d6
7
+ data.tar.gz: d3d0649cf733bd07ed0e66ee9bf223dbdee5c89a54b609e35583964a216bbd3136f2bfdf0d1988edc705c004ac1a2781a00316f08fd23f639054d83a56637318
data/README.md CHANGED
@@ -20,9 +20,9 @@ manual page for more details:
20
20
  #!/usr/bin/env ruby
21
21
  require "bsd/capsicum"
22
22
 
23
- print "In capability mode: ", BSD::Capsicum.in_capability_mode? ? "yes" : "no", "\n"
24
- print "Enter capability mode: ", BSD::Capsicum.enter! ? "ok" : "error", "\n"
25
- print "In capability mode: ", BSD::Capsicum.in_capability_mode? ? "yes" : "no", "\n"
23
+ print "In capability mode: ", (BSD::Capsicum.in_capability_mode? ? "yes" : "no"), "\n"
24
+ print "Enter capability mode: ", (BSD::Capsicum.enter! ? "ok" : "error"), "\n"
25
+ print "In capability mode: ", (BSD::Capsicum.in_capability_mode? ? "yes" : "no"), "\n"
26
26
 
27
27
  begin
28
28
  File.new(File::NULL)
@@ -37,7 +37,7 @@ end
37
37
  # Error: Not permitted in capability mode @ rb_sysopen - /dev/null (Errno::ECAPMODE)
38
38
  ```
39
39
 
40
- __IPC__
40
+ __Child process__
41
41
 
42
42
  By spawning a child process and then entering capability mode, restrictions can be
43
43
  limited to a child process (and its child processes, if any). This can be helpful in
@@ -48,15 +48,15 @@ certain tasks but with restrictions in place:
48
48
  #!/usr/bin/env ruby
49
49
  require "bsd/capsicum"
50
50
 
51
- print "[parent] In capability mode: ", BSD::Capsicum.in_capability_mode? ? "yes" : "no", "\n"
51
+ print "[parent] In capability mode: ", (BSD::Capsicum.in_capability_mode? ? "yes" : "no"), "\n"
52
52
  fork do
53
- print "[subprocess] Enter capability mode: ", BSD::Capsicum.enter! ? "ok" : "error", "\n"
54
- print "[subprocess] In capability mode: ", BSD::Capsicum.in_capability_mode? ? "yes" : "no", "\n"
53
+ print "[subprocess] Enter capability mode: ", (BSD::Capsicum.enter! ? "ok" : "error"), "\n"
54
+ print "[subprocess] In capability mode: ", (BSD::Capsicum.in_capability_mode? ? "yes" : "no"), "\n"
55
55
  print "[subprocess] Exit", "\n"
56
56
  exit 42
57
57
  end
58
58
  Process.wait
59
- print "[parent] In capability mode: ", BSD::Capsicum.in_capability_mode? ? "yes" : "no", "\n"
59
+ print "[parent] In capability mode: ", (BSD::Capsicum.in_capability_mode? ? "yes" : "no"), "\n"
60
60
 
61
61
  ##
62
62
  # [parent] In capability mode: no
@@ -71,8 +71,8 @@ __Rights__
71
71
  The
72
72
  [BSD::Capsicum.set_rights!](http://0x1eef.github.io/x/bsdcapsicum.rb/BSD/Capsicum.html#set_rights!-instance_method)
73
73
  method can reduce the capabilities of a file descriptor. The following
74
- example obtains a file descriptor in a parent process (with both read and
75
- write permissions), then limits the capabilities of the file descriptor
74
+ example obtains a file descriptor in a parent process (with full capabilities),
75
+ then limits the capabilities of the file descriptor
76
76
  in a child process to allow only read operations. See the
77
77
  [rights(4)](https://man.freebsd.org/cgi/man.cgi?query=rights&apropos=0&sektion=4&format=html)
78
78
  man page for a full list of capabilities:
@@ -84,13 +84,13 @@ require "bsd/capsicum"
84
84
  path = File.join(Dir.home, "bsdcapsicum.txt")
85
85
  file = File.open(path, File::CREAT | File::TRUNC | File::RDWR)
86
86
  file.sync = true
87
- print "[parent] obtain file descriptor (with read+write permissions)", "\n"
87
+ print "[parent] Obtain file descriptor (with all capabilities)", "\n"
88
88
  fork do
89
89
  BSD::Capsicum.set_rights!(file, %i[CAP_READ])
90
- print "[subprocess] reduce rights to read-only", "\n"
90
+ print "[subprocess] Reduce capabilities to read", "\n"
91
91
 
92
92
  file.gets
93
- print "[subprocess] read successful", "\n"
93
+ print "[subprocess] Read OK", "\n"
94
94
 
95
95
  begin
96
96
  file.write "foo"
@@ -100,14 +100,14 @@ fork do
100
100
  end
101
101
  Process.wait
102
102
  file.write "[parent] Hello from #{Process.pid}", "\n"
103
- print "[parent] write successful", "\n"
103
+ print "[parent] Write OK", "\n"
104
104
 
105
105
  ##
106
- # [parent] obtain file descriptor (with read+write permissions)
107
- # [subprocess] reduce rights to read-only
108
- # [subprocess] read successful
106
+ # [parent] Obtain file descriptor (with all capabilities)
107
+ # [subprocess] Reduce capabilities to read
108
+ # [subprocess] Read OK
109
109
  # [subprocess] Error: Capabilities insufficient @ io_write - /home/user/bsdcapsicum.txt (Errno::ENOTCAPABLE)
110
- # [parent] write successful
110
+ # [parent] Write OK
111
111
  ```
112
112
 
113
113
  ## Documentation
@@ -123,7 +123,9 @@ bsdcapsicum.rb is available via rubygems.org:
123
123
  ## Sources
124
124
 
125
125
  * [GitHub](https://github.com/0x1eef/bsdcapsicum.rb#readme)
126
- * [git.HardenedBSD.org](https://git.hardenedbsd.org/0x1eef/bsdcapsicum.rb#about)
126
+ * [GitLab](https://gitlab.com/0x1eef/bsdcapsicum.rb#about)
127
+ * [git.HardenedBSD.org/@0x1eef](https://git.hardenedbsd.org/0x1eef/bsdcapsicum.rb#about)
128
+ * [brew.bsd.cafe/@0x1eef](https://brew.bsd.cafe/0x1eef/bsdcapsicum.rb)
127
129
 
128
130
  ## See also
129
131
 
@@ -91,5 +91,9 @@ module BSD::Capsicum
91
91
  CAP_FCHDIR = 0x200000000000800
92
92
  CAP_FCNTL = 0x200000000008000
93
93
  # @endgroup
94
+
95
+ # @group Sizes
96
+ SIZEOF_CAP_RIGHTS_T = 16
97
+ # @endgroup
94
98
  end
95
99
  end
@@ -3,8 +3,16 @@
3
3
  module BSD::Capsicum
4
4
  module FFI
5
5
  require "fiddle"
6
+ require "fiddle/import"
6
7
  include Fiddle::Types
7
8
  include Constants
9
+ extend Fiddle::Importer
10
+ dlload Dir["/lib/libc.*"].first
11
+
12
+ extern "int cap_getmode(u_int*)"
13
+ extern "int cap_enter(void)"
14
+ extern "int cap_rights_limit(int, const cap_rights_t*)"
15
+ extern "cap_rights_t* __cap_rights_init(int version, cap_rights_t*, ...)"
8
16
 
9
17
  module_function
10
18
 
@@ -12,11 +20,7 @@ module BSD::Capsicum
12
20
  # Provides a Ruby interface for cap_enter(2)
13
21
  # @return [Integer]
14
22
  def cap_enter
15
- Fiddle::Function.new(
16
- libc["cap_enter"],
17
- [],
18
- INT
19
- ).call
23
+ self["cap_enter"].call
20
24
  end
21
25
 
22
26
  ##
@@ -24,45 +28,43 @@ module BSD::Capsicum
24
28
  # @param [Fiddle::Pointer] uintp
25
29
  # @return [Integer]
26
30
  def cap_getmode(uintp)
27
- Fiddle::Function.new(
28
- libc["cap_getmode"],
29
- [INTPTR_T],
30
- INT
31
- ).call(uintp)
31
+ self["cap_getmode"].call(uintp)
32
32
  end
33
33
 
34
34
  ##
35
35
  # Provides a Ruby interface for cap_rights_limit(2)
36
36
  # @param [Integer] fd
37
- # @param [Fiddle::Pointer] rights
37
+ # @param [Fiddle::Pointer] rightsp
38
38
  # @return [Integer]
39
- def cap_rights_limit(fd, rights)
40
- Fiddle::Function.new(
41
- libc["cap_rights_limit"],
42
- [INT, VOIDP],
43
- INT
44
- ).call(fd, rights)
39
+ def cap_rights_limit(fd, rightsp)
40
+ self["cap_rights_limit"].call(fd, rightsp)
45
41
  end
46
42
 
47
43
  ##
48
44
  # Provides a Ruby interface for cap_rights_init(2)
49
- # @param [Array<Integer>] rights
45
+ # @see BSD::Capsicum::Constants See Constants for a full list of capabilities
46
+ # @param [Fiddle::Pointer] rightsp
47
+ # A pointer to initialize the `cap_rights_t` structure
48
+ # @param [Array<Symbol, Integer>] capabilities
49
+ # An allowed set of capabilities
50
50
  # @return [Fiddle::Pointer]
51
- def cap_rights_init(*rights)
52
- voidp = Fiddle::Pointer.malloc(Fiddle::SIZEOF_VOIDP)
53
- varargs = rights.flat_map { [ULONG_LONG, (Symbol === _1) ? Constants.const_get(_1) : _1] }
54
- Fiddle::Function.new(
55
- libc["__cap_rights_init"],
56
- [INT, VOIDP, VARIADIC],
57
- VOIDP
58
- ).call(CAP_RIGHTS_VERSION, voidp, *varargs)
59
- voidp
51
+ # Returns a pointer to the structure `cap_rights_t`
52
+ def cap_rights_init(rightsp, *capabilities)
53
+ self["__cap_rights_init"].call(
54
+ CAP_RIGHTS_VERSION,
55
+ rightsp,
56
+ *capabilities.flat_map { |cap|
57
+ [ULONG_LONG, cap_all.include?(cap) ? const_get(cap) : cap]
58
+ }
59
+ )
60
60
  end
61
61
 
62
62
  ##
63
63
  # @api private
64
- def libc
65
- @libc ||= Fiddle.dlopen Dir["/lib/libc.*"].first
64
+ # @return [Array<Symbol>]
65
+ # Returns all known capabilities
66
+ def cap_all
67
+ @cap_all ||= Constants.constants.select { _1.to_s.start_with?("CAP_") }
66
68
  end
67
69
  end
68
70
  private_constant :FFI
@@ -4,5 +4,5 @@ module BSD
4
4
  end unless defined?(BSD)
5
5
 
6
6
  module BSD::Capsicum
7
- VERSION = "0.2.0"
7
+ VERSION = "0.3.0"
8
8
  end
data/lib/bsd/capsicum.rb CHANGED
@@ -44,26 +44,27 @@ module BSD::Capsicum
44
44
  alias_method :enter_capability_mode!, :enter!
45
45
 
46
46
  ##
47
- # Restrict the capabilities of a file descriptor
47
+ # Limit the capabilities of a file descriptor
48
48
  #
49
49
  # @see https://man.freebsd.org/cgi/man.cgi?query=cap_rights_limit&apropos=0&sektion=2&format=html cap_rights_limit(2)
50
50
  # @see BSD::Capsicum::Constants See Constants for a full list of capabilities
51
51
  # @example
52
- # # Restrict capabilities of STDOUT to read / write
52
+ # # Limit standard output capabilities to read and write
53
53
  # BSD::Capsicum.set_rights!(STDOUT, %i[CAP_READ CAP_WRITE])
54
54
  # @raise [SystemCallError]
55
55
  # Might raise a subclass of SystemCallError
56
56
  # @param [#to_i] io
57
57
  # An IO object
58
- # @param [Array<String>] rights
58
+ # @param [Array<Symbol, Integer>] capabilities
59
59
  # An allowed set of capabilities
60
60
  # @return [Boolean]
61
61
  # Returns true when successful
62
- def set_rights!(io, rights)
63
- voidp = FFI.cap_rights_init(*rights)
64
- FFI.cap_rights_limit(io.to_i, voidp).zero? ||
62
+ def set_rights!(io, capabilities)
63
+ rightsp = Fiddle::Pointer.malloc(Constants::SIZEOF_CAP_RIGHTS_T)
64
+ FFI.cap_rights_init(rightsp, *capabilities)
65
+ FFI.cap_rights_limit(io.to_i, rightsp).zero? ||
65
66
  raise(SystemCallError.new("cap_rights_limit", Fiddle.last_error))
66
67
  ensure
67
- voidp.call_free
68
+ rightsp.call_free
68
69
  end
69
70
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bsdcapsicum.rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thomas Hurst
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2024-06-27 00:00:00.000000000 Z
12
+ date: 2024-07-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: fiddle