bsdcapsicum.rb 0.3.0 → 0.4.1

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: 68cc91e740a2c2e8586db3884729be9c4fcefe8de403876ff805ac2bdaa3575b
4
- data.tar.gz: d71319a3f9a56b63faef409ea27647ea93796eedda15658ad28bf9a9cd395066
3
+ metadata.gz: 9f04ca5f787707b481203142fc23a60f7e3ce89042164d83237d8b712771d8f7
4
+ data.tar.gz: 7c1ab8542ec63f7577e4963cfc3429c18abe239d47052ee0bb9a9beb5b50ebda
5
5
  SHA512:
6
- metadata.gz: 94b898fee6872449599545d87fd4d52e9231b6e6d7424d58d3bfc7b22e97c84d5b10719821581bc590822e49464703503a284d9205def2ccba65670d300f97d6
7
- data.tar.gz: d3d0649cf733bd07ed0e66ee9bf223dbdee5c89a54b609e35583964a216bbd3136f2bfdf0d1988edc705c004ac1a2781a00316f08fd23f639054d83a56637318
6
+ metadata.gz: 84846a8ed8ee8cec16a4bd6f92d7953808843d6a4e9990c5bba9f1059b569e782ebefc6ff9b381d036b2f95f7a3369639f5816ae3387fd58bb52013ef9ec2de0
7
+ data.tar.gz: 849f83267b1e8e5fcdab263985c4add0d70a46d30b9ccdb1fcaabc3a4794bae746e737869532c9f0bc25881c97acdec90ec003d5e28e9d02ff741cefc977a847
data/README.md CHANGED
@@ -1,28 +1,43 @@
1
1
  ## About
2
2
 
3
- bsdcapsicum.rb provides Ruby bindings for
4
- [capsicum(4)](https://man.freebsd.org/cgi/man.cgi?query=capsicum&apropos=0&sektion=4&format=html).
3
+ bsdcapsicum.rb provides Ruby bindings for FreeBSD's
4
+ [capsicum(4)](https://man.freebsd.org/cgi/man.cgi?query=capsicum&apropos=0&sektion=4&format=html)
5
+ via
6
+ [fiddle](https://github.com/ruby/fiddle#readme). The capsicum framework
7
+ provides a sandbox model where a process can enter into a mode of operation
8
+ where it is exclusively capable of performing system calls on file descriptors
9
+ that have been acquired before entering capability mode. The file descriptors
10
+ can also be limited to a subset of system calls, and a file descriptor could
11
+ reference a file, a socket, or other IO objects.
5
12
 
6
13
  ## Examples
7
14
 
8
- __Capability mode__
15
+ ### BSD::Capsicum
16
+
17
+ #### Capability mode
9
18
 
10
19
  A process can enter into capability mode by calling
11
- [BSD::Capsicum.enter!](http://0x1eef.github.io/x/bsdcapsicum.rb/BSD/Capsicum.html#enter!-instance_method).
12
- After entering capability mode, the process has limited
13
- abilities. File descriptors acquired before entering into
14
- capability mode remain accessible and unrestricted, but
15
- their capabilites can be reduced. See the
20
+ the
21
+ [BSD::Capsicum.enter_capability_mode!](http://0x1eef.github.io/x/bsdcapsicum.rb/BSD/Capsicum.html#enter!-instance_method)
22
+ method. After entering capability mode, a process may only
23
+ issue system calls operating on file descriptors that have already
24
+ been acquired or by reading limited global system state.
25
+ File descriptors acquired before entering capability mode remain
26
+ fully capable but their capabilities can be reduced by calling
27
+ the
28
+ [BSD::Capsicum.permit!](http://0x1eef.github.io/x/bsdcapsicum.rb/BSD/Capsicum.html#permit!-instance_method)
29
+ method. See the
16
30
  [cap_enter(2)](https://man.freebsd.org/cgi/man.cgi?query=cap_enter&apropos=0&sektion=2&format=html)
17
- manual page for more details:
31
+ manual page or the rest of the README for more details:
18
32
 
19
33
  ```ruby
20
34
  #!/usr/bin/env ruby
21
35
  require "bsd/capsicum"
22
36
 
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"
37
+ print "In capability mode: ", (BSD::Capsicum.capability_mode? ? "yes" : "no"), "\n"
38
+ BSD::Capsicum.enter_capability_mode!
39
+ print "Enter capability mode: ok", "\n"
40
+ print "In capability mode: ", (BSD::Capsicum.capability_mode? ? "yes" : "no"), "\n"
26
41
 
27
42
  begin
28
43
  File.new(File::NULL)
@@ -37,65 +52,42 @@ end
37
52
  # Error: Not permitted in capability mode @ rb_sysopen - /dev/null (Errno::ECAPMODE)
38
53
  ```
39
54
 
40
- __Child process__
41
-
42
- By spawning a child process and then entering capability mode, restrictions can be
43
- limited to a child process (and its child processes, if any). This can be helpful in
44
- an architecture where a parent process can spawn one or more child processes to handle
45
- certain tasks but with restrictions in place:
46
-
47
- ```ruby
48
- #!/usr/bin/env ruby
49
- require "bsd/capsicum"
50
-
51
- print "[parent] In capability mode: ", (BSD::Capsicum.in_capability_mode? ? "yes" : "no"), "\n"
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"
55
- print "[subprocess] Exit", "\n"
56
- exit 42
57
- end
58
- Process.wait
59
- print "[parent] In capability mode: ", (BSD::Capsicum.in_capability_mode? ? "yes" : "no"), "\n"
60
-
61
- ##
62
- # [parent] In capability mode: no
63
- # [subprocess] Enter capability mode: ok
64
- # [subprocess] In capability mode: yes
65
- # [subprocess] Exit
66
- # [parent] In capability mode: no
67
- ```
68
-
69
- __Rights__
55
+ #### File descriptors
70
56
 
71
57
  The
72
- [BSD::Capsicum.set_rights!](http://0x1eef.github.io/x/bsdcapsicum.rb/BSD/Capsicum.html#set_rights!-instance_method)
73
- method can reduce the capabilities of a file descriptor. The following
74
- example obtains a file descriptor in a parent process (with full capabilities),
75
- then limits the capabilities of the file descriptor
58
+ [BSD::Capsicum::IO#permit!](http://0x1eef.github.io/x/bsdcapsicum.rb/BSD/Capsicum/IO.html#permit!-instance_method)
59
+ method can reduce the capabilities of a file descriptor by limiting what
60
+ system calls it can be used with. In that sense it is roughly similar to OpenBSD's
61
+ pledge but it operates on the file descriptor level rather than the process
62
+ level.
63
+ The following example obtains a file descriptor in a parent process (with
64
+ full capabilities), then limits the capabilities of the file descriptor
76
65
  in a child process to allow only read operations. See the
77
66
  [rights(4)](https://man.freebsd.org/cgi/man.cgi?query=rights&apropos=0&sektion=4&format=html)
78
- man page for a full list of capabilities:
67
+ and
68
+ [cap_rights_limit(2)](https://man.freebsd.org/cgi/man.cgi?query=cap_rights_limit&sektion=2&format=htmlman)
69
+ manual pages for more information:
79
70
 
80
71
  ``` ruby
81
72
  #!/usr/bin/env ruby
82
73
  require "bsd/capsicum"
74
+ require "tmpdir"
83
75
 
84
- path = File.join(Dir.home, "bsdcapsicum.txt")
76
+ path = File.join(Dir.tmpdir, "bsdcapsicum.txt")
85
77
  file = File.open(path, File::CREAT | File::TRUNC | File::RDWR)
86
78
  file.sync = true
87
- print "[parent] Obtain file descriptor (with all capabilities)", "\n"
79
+ print "[parent] Obtain file descriptor (with full capabilities)", "\n"
88
80
  fork do
89
- BSD::Capsicum.set_rights!(file, %i[CAP_READ])
90
- print "[subprocess] Reduce capabilities to read", "\n"
81
+ file.permit!(:read)
82
+ print "[child] Reduce capabilities to read", "\n"
91
83
 
92
84
  file.gets
93
- print "[subprocess] Read OK", "\n"
85
+ print "[child] Read OK", "\n"
94
86
 
95
87
  begin
96
88
  file.write "foo"
97
89
  rescue Errno::ENOTCAPABLE => ex
98
- print "[subprocess] Error: #{ex.message} (#{ex.class})", "\n"
90
+ print "[child] Error: #{ex.message} (#{ex.class})", "\n"
99
91
  end
100
92
  end
101
93
  Process.wait
@@ -103,13 +95,58 @@ file.write "[parent] Hello from #{Process.pid}", "\n"
103
95
  print "[parent] Write OK", "\n"
104
96
 
105
97
  ##
106
- # [parent] Obtain file descriptor (with all capabilities)
107
- # [subprocess] Reduce capabilities to read
108
- # [subprocess] Read OK
109
- # [subprocess] Error: Capabilities insufficient @ io_write - /home/user/bsdcapsicum.txt (Errno::ENOTCAPABLE)
98
+ # [parent] Obtain file descriptor (with full capabilities)
99
+ # [child] Reduce capabilities to read
100
+ # [child] Read OK
101
+ # [child] Error: Capabilities insufficient @ io_write - /tmp/bsdcapsicum.txt (Errno::ENOTCAPABLE)
110
102
  # [parent] Write OK
111
103
  ```
112
104
 
105
+ #### Fcntls
106
+
107
+ The
108
+ [BSD::Capsicum::IO#permit!](http://0x1eef.github.io/x/bsdcapsicum.rb/BSD/Capsicum/IO.html#permit!-instance_method)
109
+ method can limit the fcntls capabilities of a file descriptor by limiting what
110
+ fcntls operations it can be used with. This method requires the fcntl capability to already
111
+ be present, and it can limit fnctls operations to a smaller subset of operations.
112
+ The following example limits the fcntls capabilities of a file descriptor to allow
113
+ only the `GETFL` operation, and prevents the `SETFL` operation:
114
+
115
+ ```ruby
116
+ #!/usr/bin/env ruby
117
+ require "bsd/capsicum"
118
+ require "tmpdir"
119
+
120
+ path = File.join(Dir.tmpdir, "bsdcapsicum.txt")
121
+ file = File.open(path, File::CREAT | File::TRUNC | File::RDWR)
122
+ file.sync = true
123
+ print "Obtain file descriptor (with full capabilities)", "\n"
124
+
125
+ file.permit!(:fcntl)
126
+ print "Reduce capabilities to fcntl", "\n"
127
+
128
+ file.permit!(:GETFL, scope: :fcntl)
129
+ print "Reduces fcntl capabilties to GETFL", "\n"
130
+
131
+ flags = file.fcntl(Fcntl::F_GETFL)
132
+ print "Get fcntl flags: OK", "\n"
133
+
134
+ begin
135
+ print "Try to set fcntls flag ... ", "\n"
136
+ file.fcntl(Fcntl::F_SETFL, flags | Fcntl::O_APPEND)
137
+ rescue Errno::ENOTCAPABLE => ex
138
+ print "Error: #{ex.message} (#{ex.class})", "\n"
139
+ end
140
+
141
+ ##
142
+ # Obtain file descriptor (with full capabilities)
143
+ # Reduce capabilities to fcntl
144
+ # Reduce fcntl capabilties to fcntl_getfl
145
+ # Get fcntl flags: OK
146
+ # Try to set fcntls flag ...
147
+ # Error: Capabilities insufficient @ finish_narg - /tmp/bsdcapsicum.txt (Errno::ENOTCAPABLE)
148
+ ```
149
+
113
150
  ## Documentation
114
151
 
115
152
  A complete API reference is available at [0x1eef.github.io/x/bsdcapsicum.rb](https://0x1eef.github.io/x/bsdcapsicum.rb)
@@ -122,16 +159,30 @@ bsdcapsicum.rb is available via rubygems.org:
122
159
 
123
160
  ## Sources
124
161
 
125
- * [GitHub](https://github.com/0x1eef/bsdcapsicum.rb#readme)
126
- * [GitLab](https://gitlab.com/0x1eef/bsdcapsicum.rb#about)
162
+ * [github.com/@0x1eef](https://github.com/0x1eef/bsdcapsicum.rb#readme)
163
+ * [gitlab.com/@0x1eef](https://gitlab.com/0x1eef/bsdcapsicum.rb#about)
127
164
  * [git.HardenedBSD.org/@0x1eef](https://git.hardenedbsd.org/0x1eef/bsdcapsicum.rb#about)
128
165
  * [brew.bsd.cafe/@0x1eef](https://brew.bsd.cafe/0x1eef/bsdcapsicum.rb)
129
166
 
130
167
  ## See also
131
168
 
132
169
  * [Freaky/ruby-capsicum](https://github.com/Freaky/ruby-capsicum) <br>
133
- bsdcapsicum.rb is a fork of this project. It was a huge help both
134
- in terms of code and documentation.
170
+ bsdcapsicum.rb is a fork of this project.
171
+
172
+ ## Status
173
+
174
+ The following functions have an equivalent Ruby interface:
175
+
176
+ * [x] [cap_enter(2)](https://man.freebsd.org/cgi/man.cgi?query=cap_enter&apropos=0&sektion=2&format=html)
177
+ * [x] [cap_getmode(2)](https://man.freebsd.org/cgi/man.cgi?query=cap_getmode&apropos=0&sektion=2&format=html)
178
+ * [x] [cap_rights_limit(2)](https://man.freebsd.org/cgi/man.cgi?query=cap_rights_limit&sektion=2&format=html)
179
+ * [x] [cap_fcntls_limit(2)](https://man.freebsd.org/cgi/man.cgi?query=cap_fcntls_limit&sektion=2&format=html)
180
+
181
+ The following functions complement
182
+ [cap_rights_limit(2)](https://man.freebsd.org/cgi/man.cgi?query=cap_rights_limit&sektion=2&format=html)
183
+ but have not yet been implemented:
184
+
185
+ * [ ] [cap_ioctls_limit(2)](https://man.freebsd.org/cgi/man.cgi?query=cap_ioctls_limit&sektion=2&format=html)
135
186
 
136
187
  ## License
137
188
 
@@ -12,12 +12,24 @@ Gem::Specification.new do |spec|
12
12
  spec.summary = "Ruby bindings for FreeBSD's capsicum(4)"
13
13
  spec.homepage = "https://github.com/0x1eef/bsdcapsicum.rb"
14
14
  spec.licenses = ["0BSD", "MIT"]
15
- spec.files = Dir["lib/*.rb", "lib/**/*.rb", "README.md", "LICENSE", "LICENSE.ruby-capsicum", "*.gemspec"]
15
+ spec.executables = []
16
16
  spec.require_paths = ["lib"]
17
+ spec.files = Dir[
18
+ "*.gemspec",
19
+ "README.md",
20
+ "LICENSE",
21
+ "LICENSE.ruby-capsicum",
22
+ "lib/*.rb",
23
+ "lib/**/*.rb",
24
+ "share/**/*.rb",
25
+ "ext/**/*.rb",
26
+ "ext/**/*.c",
27
+ ].select { File.file?(_1) }
17
28
 
18
29
  spec.add_runtime_dependency "fiddle", "~> 1.1"
19
30
  spec.add_development_dependency "bundler", "~> 2.5"
20
31
  spec.add_development_dependency "rake", "~> 13.2"
32
+ spec.add_development_dependency "rake-compiler", "~> 1.2"
21
33
  spec.add_development_dependency "minitest", "~> 5.0"
22
34
  spec.add_development_dependency "standard", "~> 1.38"
23
35
  spec.add_development_dependency "test-cmd.rb", "~> 0.12"
@@ -0,0 +1,95 @@
1
+ #include <sys/capsicum.h>
2
+ #include <ruby.h>
3
+
4
+ void
5
+ Init_bsdcapsicum(void)
6
+ {
7
+ VALUE rb_mBSD = rb_const_get(rb_cObject, rb_intern("BSD"));
8
+ VALUE rb_mCapsicum = rb_const_get(rb_mBSD, rb_intern("Capsicum"));
9
+ VALUE rb_mFFI = rb_define_module_under(rb_mCapsicum, "FFI");
10
+
11
+ // @group File
12
+ rb_define_const(rb_mFFI, "CAP_READ", LONG2NUM(CAP_READ));
13
+ rb_define_const(rb_mFFI, "CAP_WRITE", LONG2NUM(CAP_WRITE));
14
+ rb_define_const(rb_mFFI, "CAP_SEEK", LONG2NUM(CAP_SEEK));
15
+ rb_define_const(rb_mFFI, "CAP_PREAD", LONG2NUM(CAP_PREAD));
16
+ rb_define_const(rb_mFFI, "CAP_PWRITE", LONG2NUM(CAP_PWRITE));
17
+ rb_define_const(rb_mFFI, "CAP_MMAP", LONG2NUM(CAP_MMAP));
18
+ rb_define_const(rb_mFFI, "CAP_CREATE", LONG2NUM(CAP_CREATE));
19
+ rb_define_const(rb_mFFI, "CAP_FEXECVE", LONG2NUM(CAP_FEXECVE));
20
+ rb_define_const(rb_mFFI, "CAP_FSYNC", LONG2NUM(CAP_FSYNC));
21
+ rb_define_const(rb_mFFI, "CAP_FTRUNCATE", LONG2NUM(CAP_FTRUNCATE));
22
+ rb_define_const(rb_mFFI, "CAP_FCHFLAGS", LONG2NUM(CAP_FCHFLAGS));
23
+ rb_define_const(rb_mFFI, "CAP_FCHMOD", LONG2NUM(CAP_FCHMOD));
24
+ rb_define_const(rb_mFFI, "CAP_FCHMODAT", LONG2NUM(CAP_FCHMODAT));
25
+ rb_define_const(rb_mFFI, "CAP_FCHOWN", LONG2NUM(CAP_FCHOWN));
26
+ rb_define_const(rb_mFFI, "CAP_FCHOWNAT", LONG2NUM(CAP_FCHOWNAT));
27
+ rb_define_const(rb_mFFI, "CAP_FLOCK", LONG2NUM(CAP_FLOCK));
28
+ rb_define_const(rb_mFFI, "CAP_FPATHCONF", LONG2NUM(CAP_FPATHCONF));
29
+ rb_define_const(rb_mFFI, "CAP_FSTAT", LONG2NUM(CAP_FSTAT));
30
+ rb_define_const(rb_mFFI, "CAP_FSTATAT", LONG2NUM(CAP_FSTATAT));
31
+ rb_define_const(rb_mFFI, "CAP_FSTATFS", LONG2NUM(CAP_FSTATFS));
32
+ rb_define_const(rb_mFFI, "CAP_FUTIMES", LONG2NUM(CAP_FUTIMES));
33
+ rb_define_const(rb_mFFI, "CAP_FUTIMESAT", LONG2NUM(CAP_FUTIMESAT));
34
+ // @endgroup
35
+
36
+ // @group Sockets
37
+ rb_define_const(rb_mFFI, "CAP_ACCEPT", LONG2NUM(CAP_ACCEPT));
38
+ rb_define_const(rb_mFFI, "CAP_BIND", LONG2NUM(CAP_BIND));
39
+ rb_define_const(rb_mFFI, "CAP_CONNECT", LONG2NUM(CAP_CONNECT));
40
+ rb_define_const(rb_mFFI, "CAP_GETPEERNAME", LONG2NUM(CAP_GETPEERNAME));
41
+ rb_define_const(rb_mFFI, "CAP_GETSOCKNAME", LONG2NUM(CAP_GETSOCKNAME));
42
+ rb_define_const(rb_mFFI, "CAP_GETSOCKOPT", LONG2NUM(CAP_GETSOCKOPT));
43
+ rb_define_const(rb_mFFI, "CAP_LISTEN", LONG2NUM(CAP_LISTEN));
44
+ rb_define_const(rb_mFFI, "CAP_PEELOFF", LONG2NUM(CAP_PEELOFF));
45
+ rb_define_const(rb_mFFI, "CAP_RECV", LONG2NUM(CAP_RECV));
46
+ rb_define_const(rb_mFFI, "CAP_SEND", LONG2NUM(CAP_SEND));
47
+ rb_define_const(rb_mFFI, "CAP_SETSOCKOPT", LONG2NUM(CAP_SETSOCKOPT));
48
+ rb_define_const(rb_mFFI, "CAP_SHUTDOWN", LONG2NUM(CAP_SHUTDOWN));
49
+ rb_define_const(rb_mFFI, "CAP_BINDAT", LONG2NUM(CAP_BINDAT));
50
+ rb_define_const(rb_mFFI, "CAP_SOCK_CLIENT", LONG2NUM(CAP_SOCK_CLIENT));
51
+ rb_define_const(rb_mFFI, "CAP_SOCK_SERVER", LONG2NUM(CAP_SOCK_SERVER));
52
+ // @endgroup
53
+
54
+ // @group ACL
55
+ rb_define_const(rb_mFFI, "CAP_ACL_CHECK", LONG2NUM(CAP_ACL_CHECK));
56
+ rb_define_const(rb_mFFI, "CAP_ACL_DELETE", LONG2NUM(CAP_ACL_DELETE));
57
+ rb_define_const(rb_mFFI, "CAP_ACL_GET", LONG2NUM(CAP_ACL_GET));
58
+ rb_define_const(rb_mFFI, "CAP_ACL_SET", LONG2NUM(CAP_ACL_SET));
59
+ // @endgroup
60
+
61
+ // @group Process
62
+ rb_define_const(rb_mFFI, "CAP_PDGETPID", LONG2NUM(CAP_PDGETPID));
63
+ rb_define_const(rb_mFFI, "CAP_PDKILL", LONG2NUM(CAP_PDKILL));
64
+ rb_define_const(rb_mFFI, "CAP_PDWAIT", LONG2NUM(CAP_PDWAIT));
65
+ // @endgroup
66
+
67
+ // @group Fcntl
68
+ rb_define_const(rb_mFFI, "CAP_FCNTL_GETFL", LONG2NUM(CAP_FCNTL_GETFL));
69
+ rb_define_const(rb_mFFI, "CAP_FCNTL_SETFL", LONG2NUM(CAP_FCNTL_SETFL));
70
+ rb_define_const(rb_mFFI, "CAP_FCNTL_GETOWN", LONG2NUM(CAP_FCNTL_GETOWN));
71
+ rb_define_const(rb_mFFI, "CAP_FCNTL_SETOWN", LONG2NUM(CAP_FCNTL_SETOWN));
72
+ // @endgroup
73
+
74
+ // @group Misc
75
+ rb_define_const(rb_mFFI, "CAP_CHFLAGSAT", LONG2NUM(CAP_CHFLAGSAT));
76
+ rb_define_const(rb_mFFI, "CAP_EVENT", LONG2NUM(CAP_EVENT));
77
+ rb_define_const(rb_mFFI, "CAP_IOCTL", LONG2NUM(CAP_IOCTL));
78
+ rb_define_const(rb_mFFI, "CAP_KQUEUE", LONG2NUM(CAP_KQUEUE));
79
+ rb_define_const(rb_mFFI, "CAP_LOOKUP", LONG2NUM(CAP_LOOKUP));
80
+ rb_define_const(rb_mFFI, "CAP_MAC_GET", LONG2NUM(CAP_MAC_GET));
81
+ rb_define_const(rb_mFFI, "CAP_MAC_SET", LONG2NUM(CAP_MAC_SET));
82
+ rb_define_const(rb_mFFI, "CAP_MKDIRAT", LONG2NUM(CAP_MKDIRAT));
83
+ rb_define_const(rb_mFFI, "CAP_MKFIFOAT", LONG2NUM(CAP_MKFIFOAT));
84
+ rb_define_const(rb_mFFI, "CAP_MKNODAT", LONG2NUM(CAP_MKNODAT));
85
+ rb_define_const(rb_mFFI, "CAP_SEM_GETVALUE", LONG2NUM(CAP_SEM_GETVALUE));
86
+ rb_define_const(rb_mFFI, "CAP_SEM_POST", LONG2NUM(CAP_SEM_POST));
87
+ rb_define_const(rb_mFFI, "CAP_SEM_WAIT", LONG2NUM(CAP_SEM_WAIT));
88
+ rb_define_const(rb_mFFI, "CAP_TTYHOOK", LONG2NUM(CAP_TTYHOOK));
89
+ rb_define_const(rb_mFFI, "CAP_UNLINKAT", LONG2NUM(CAP_UNLINKAT));
90
+ rb_define_const(rb_mFFI, "CAP_FSCK", LONG2NUM(CAP_FSCK));
91
+ rb_define_const(rb_mFFI, "CAP_FCHDIR", LONG2NUM(CAP_FCHDIR));
92
+ rb_define_const(rb_mFFI, "CAP_FCNTL", LONG2NUM(CAP_FCNTL));
93
+ rb_define_const(rb_mFFI, "CAP_RIGHTS_VERSION", LONG2NUM(CAP_RIGHTS_VERSION));
94
+ // @endgroup
95
+ }
@@ -0,0 +1,2 @@
1
+ require "mkmf"
2
+ create_makefile("bsdcapsicum.rb")
@@ -6,90 +6,99 @@ module BSD::Capsicum
6
6
  # by sys/capsicum.h and sys/caprights.h. Their
7
7
  # documentation can be found in the
8
8
  # [rights(4)](https://man.freebsd.org/cgi/man.cgi?query=rights&apropos=0&sektion=4&format=html)
9
- # man page
9
+ # man page, and they can be used with methods
10
+ # such as {BSD::Capsicum#permit! BSD::Capsicum#permit!}
10
11
  module Constants
11
12
  CAP_RIGHTS_VERSION = 0x0
12
13
 
13
14
  ##
14
15
  # @group File capabilties
15
- CAP_READ = 0x200000000000001
16
- CAP_WRITE = 0x200000000000002
17
- CAP_SEEK = 0x20000000000000c
18
- CAP_PREAD = 0x20000000000000d
19
- CAP_PWRITE = 0x20000000000000e
20
- CAP_MMAP = 0x200000000000010
21
- CAP_CREATE = 0x200000000000040
22
- CAP_FEXECVE = 0x200000000000080
23
- CAP_FSYNC = 0x200000000000100
24
- CAP_FTRUNCATE = 0x200000000000200
25
- CAP_FCHFLAGS = 0x200000000001000
26
- CAP_FCHMOD = 0x200000000002000
27
- CAP_FCHMODAT = 0x200000000002400
28
- CAP_FCHOWN = 0x200000000004000
29
- CAP_FCHOWNAT = 0x200000000004400
30
- CAP_FLOCK = 0x200000000010000
31
- CAP_FPATHCONF = 0x200000000020000
32
- CAP_FSTAT = 0x200000000080000
33
- CAP_FSTATAT = 0x200000000080400
34
- CAP_FSTATFS = 0x200000000100000
35
- CAP_FUTIMES = 0x200000000200000
36
- CAP_FUTIMESAT = 0x200000000200400
16
+ CAP_READ = FFI::CAP_READ
17
+ CAP_WRITE = FFI::CAP_WRITE
18
+ CAP_SEEK = FFI::CAP_SEEK
19
+ CAP_PREAD = FFI::CAP_PREAD
20
+ CAP_PWRITE = FFI::CAP_PWRITE
21
+ CAP_MMAP = FFI::CAP_MMAP
22
+ CAP_CREATE = FFI::CAP_CREATE
23
+ CAP_FEXECVE = FFI::CAP_FEXECVE
24
+ CAP_FSYNC = FFI::CAP_FSYNC
25
+ CAP_FTRUNCATE = FFI::CAP_FTRUNCATE
26
+ CAP_FCHFLAGS = FFI::CAP_FCHFLAGS
27
+ CAP_FCHMOD = FFI::CAP_FCHMOD
28
+ CAP_FCHMODAT = FFI::CAP_FCHMODAT
29
+ CAP_FCHOWN = FFI::CAP_FCHOWN
30
+ CAP_FCHOWNAT = FFI::CAP_FCHOWNAT
31
+ CAP_FLOCK = FFI::CAP_FLOCK
32
+ CAP_FPATHCONF = FFI::CAP_FPATHCONF
33
+ CAP_FSTAT = FFI::CAP_FSTAT
34
+ CAP_FSTATAT = FFI::CAP_FSTATAT
35
+ CAP_FSTATFS = FFI::CAP_FSTATFS
36
+ CAP_FUTIMES = FFI::CAP_FUTIMES
37
+ CAP_FUTIMESAT = FFI::CAP_FUTIMESAT
37
38
  # @endgroup
38
39
 
39
40
  ##
40
41
  # @group Socket capabilities
41
- CAP_ACCEPT = 0x200000020000000
42
- CAP_BIND = 0x200000040000000
43
- CAP_CONNECT = 0x200000080000000
44
- CAP_GETPEERNAME = 0x200000100000000
45
- CAP_GETSOCKNAME = 0x200000200000000
46
- CAP_GETSOCKOPT = 0x200000400000000
47
- CAP_LISTEN = 0x200000800000000
48
- CAP_PEELOFF = 0x200001000000000
49
- CAP_RECV = CAP_READ
50
- CAP_SEND = CAP_WRITE
51
- CAP_SETSOCKOPT = 0x200002000000000
52
- CAP_SHUTDOWN = 0x200004000000000
53
- CAP_BINDAT = 0x200008000000400
54
- CAP_SOCK_CLIENT = 0x200007780000003
55
- CAP_SOCK_SERVER = 0x200007f60000003
42
+ CAP_ACCEPT = FFI::CAP_ACCEPT
43
+ CAP_BIND = FFI::CAP_BIND
44
+ CAP_CONNECT = FFI::CAP_CONNECT
45
+ CAP_GETPEERNAME = FFI::CAP_GETPEERNAME
46
+ CAP_GETSOCKNAME = FFI::CAP_GETSOCKNAME
47
+ CAP_GETSOCKOPT = FFI::CAP_GETSOCKOPT
48
+ CAP_LISTEN = FFI::CAP_LISTEN
49
+ CAP_PEELOFF = FFI::CAP_PEELOFF
50
+ CAP_RECV = FFI::CAP_RECV
51
+ CAP_SEND = FFI::CAP_SEND
52
+ CAP_SETSOCKOPT = FFI::CAP_SETSOCKOPT
53
+ CAP_SHUTDOWN = FFI::CAP_SHUTDOWN
54
+ CAP_BINDAT = FFI::CAP_BINDAT
55
+ CAP_SOCK_CLIENT = FFI::CAP_SOCK_CLIENT
56
+ CAP_SOCK_SERVER = FFI::CAP_SOCK_SERVER
56
57
  # @endgroup
57
58
 
58
59
  ##
59
60
  # @group ACL capabilities
60
- CAP_ACL_CHECK = 0x400000000010000
61
- CAP_ACL_DELETE = 0x400000000020000
62
- CAP_ACL_GET = 0x400000000040000
63
- CAP_ACL_SET = 0x400000000080000
61
+ CAP_ACL_CHECK = FFI::CAP_ACL_CHECK
62
+ CAP_ACL_DELETE = FFI::CAP_ACL_DELETE
63
+ CAP_ACL_GET = FFI::CAP_ACL_GET
64
+ CAP_ACL_SET = FFI::CAP_ACL_SET
64
65
  # @endgroup
65
66
 
66
67
  ##
67
68
  # @group Process capabilities
68
- CAP_PDGETPID = 0x400000000000200
69
- CAP_PDKILL = 0x400000000000800
70
- CAP_PDWAIT = 0x400000000000400
69
+ CAP_PDGETPID = FFI::CAP_PDGETPID
70
+ CAP_PDKILL = FFI::CAP_PDKILL
71
+ CAP_PDWAIT = FFI::CAP_PDWAIT
72
+ # @endgroup
73
+
74
+ ##
75
+ # @group Fcntl capabilities
76
+ CAP_FCNTL_GETFL = FFI::CAP_FCNTL_GETFL
77
+ CAP_FCNTL_SETFL = FFI::CAP_FCNTL_SETFL
78
+ CAP_FCNTL_GETOWN = FFI::CAP_FCNTL_GETOWN
79
+ CAP_FCNTL_SETOWN = FFI::CAP_FCNTL_SETOWN
71
80
  # @endgroup
72
81
 
73
82
  ##
74
83
  # @group Uncategorized capabilities
75
- CAP_CHFLAGSAT = 0x200000000001400
76
- CAP_EVENT = 0x400000000000020
77
- CAP_IOCTL = 0x400000000000080
78
- CAP_KQUEUE = 0x400000000100040
79
- CAP_LOOKUP = 0x200000000000400
80
- CAP_MAC_GET = 0x400000000000001
81
- CAP_MAC_SET = 0x400000000000002
82
- CAP_MKDIRAT = 0x200000000800400
83
- CAP_MKFIFOAT = 0x200000001000400
84
- CAP_MKNODAT = 0x200000002000400
85
- CAP_SEM_GETVALUE = 0x400000000000004
86
- CAP_SEM_POST = 0x400000000000008
87
- CAP_SEM_WAIT = 0x400000000000010
88
- CAP_TTYHOOK = 0x400000000000100
89
- CAP_UNLINKAT = 0x200000010000400
90
- CAP_FSCK = 0x200000000040000
91
- CAP_FCHDIR = 0x200000000000800
92
- CAP_FCNTL = 0x200000000008000
84
+ CAP_CHFLAGSAT = FFI::CAP_CHFLAGSAT
85
+ CAP_EVENT = FFI::CAP_EVENT
86
+ CAP_IOCTL = FFI::CAP_IOCTL
87
+ CAP_KQUEUE = FFI::CAP_KQUEUE
88
+ CAP_LOOKUP = FFI::CAP_LOOKUP
89
+ CAP_MAC_GET = FFI::CAP_MAC_GET
90
+ CAP_MAC_SET = FFI::CAP_MAC_SET
91
+ CAP_MKDIRAT = FFI::CAP_MKDIRAT
92
+ CAP_MKFIFOAT = FFI::CAP_MKFIFOAT
93
+ CAP_MKNODAT = FFI::CAP_MKNODAT
94
+ CAP_SEM_GETVALUE = FFI::CAP_SEM_GETVALUE
95
+ CAP_SEM_POST = FFI::CAP_SEM_POST
96
+ CAP_SEM_WAIT = FFI::CAP_SEM_WAIT
97
+ CAP_TTYHOOK = FFI::CAP_TTYHOOK
98
+ CAP_UNLINKAT = FFI::CAP_UNLINKAT
99
+ CAP_FSCK = FFI::CAP_FSCK
100
+ CAP_FCHDIR = FFI::CAP_FCHDIR
101
+ CAP_FCNTL = FFI::CAP_FCNTL
93
102
  # @endgroup
94
103
 
95
104
  # @group Sizes
@@ -5,13 +5,13 @@ module BSD::Capsicum
5
5
  require "fiddle"
6
6
  require "fiddle/import"
7
7
  include Fiddle::Types
8
- include Constants
9
8
  extend Fiddle::Importer
10
9
  dlload Dir["/lib/libc.*"].first
11
10
 
12
11
  extern "int cap_getmode(u_int*)"
13
12
  extern "int cap_enter(void)"
14
13
  extern "int cap_rights_limit(int, const cap_rights_t*)"
14
+ extern "int cap_fcntls_limit(int, uint32_t)"
15
15
  extern "cap_rights_t* __cap_rights_init(int version, cap_rights_t*, ...)"
16
16
 
17
17
  module_function
@@ -40,6 +40,17 @@ module BSD::Capsicum
40
40
  self["cap_rights_limit"].call(fd, rightsp)
41
41
  end
42
42
 
43
+ ##
44
+ # Provides a Ruby interface for cap_fcntls_limit(2)
45
+ # @param [Integer] fd
46
+ # @param [Array<Integer>] capabilities
47
+ # An allowed set of capabilities
48
+ # @return [Integer]
49
+ def cap_fcntls_limit(fd, capabilities)
50
+ cap = Private.cap_lookup(capabilities, Private.cap_fcntls)
51
+ self["cap_fcntls_limit"].call(fd, cap.inject(&:|))
52
+ end
53
+
43
54
  ##
44
55
  # Provides a Ruby interface for cap_rights_init(2)
45
56
  # @see BSD::Capsicum::Constants See Constants for a full list of capabilities
@@ -47,24 +58,58 @@ module BSD::Capsicum
47
58
  # A pointer to initialize the `cap_rights_t` structure
48
59
  # @param [Array<Symbol, Integer>] capabilities
49
60
  # An allowed set of capabilities
61
+ # @raise [TypeError]
62
+ # When an unknown capability is provided
50
63
  # @return [Fiddle::Pointer]
51
64
  # Returns a pointer to the structure `cap_rights_t`
52
65
  def cap_rights_init(rightsp, *capabilities)
66
+ cap = Private.cap_lookup(capabilities, Private.cap_all)
53
67
  self["__cap_rights_init"].call(
54
68
  CAP_RIGHTS_VERSION,
55
69
  rightsp,
56
- *capabilities.flat_map { |cap|
57
- [ULONG_LONG, cap_all.include?(cap) ? const_get(cap) : cap]
58
- }
70
+ *cap.flat_map { [ULONG_LONG, _1] }
59
71
  )
60
72
  end
61
73
 
62
74
  ##
63
- # @api private
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_") }
75
+ # @api pricate
76
+ module Private
77
+ extend self
78
+ ##
79
+ # @api private
80
+ # @return [Array<Integer>]
81
+ # Returns a list of capabilities (as integers)
82
+ def cap_lookup(capabilities, allowed)
83
+ capabilities.flat_map do |cap|
84
+ if Integer === cap
85
+ cap
86
+ elsif allowed.include?(cap)
87
+ FFI.const_get(cap)
88
+ elsif allowed.include?(:"CAP_#{cap.upcase}")
89
+ FFI.const_get(:"CAP_#{cap.upcase}")
90
+ elsif allowed.include?(:"CAP_FCNTL_#{cap.upcase}")
91
+ FFI.const_get(:"CAP_FCNTL_#{cap.upcase}")
92
+ else
93
+ raise TypeError, "unknown capability: #{cap}"
94
+ end
95
+ end
96
+ end
97
+
98
+ ##
99
+ # @api private
100
+ # @return [Array<Symbol>]
101
+ # Returns all known capabilities
102
+ def cap_all
103
+ @cap_all ||= Constants.constants.select { _1.to_s.start_with?("CAP_") }
104
+ end
105
+
106
+ ##
107
+ # @api private
108
+ # @return [Array<Symbol>]
109
+ # Returns all known fcntl capabilities
110
+ def cap_fcntls
111
+ @cap_fcntls ||= Constants.constants.select { _1.to_s.start_with?("CAP_FCNTL_") }
112
+ end
68
113
  end
69
114
  end
70
115
  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.3.0"
7
+ VERSION = "0.4.1"
8
8
  end
data/lib/bsd/capsicum.rb CHANGED
@@ -4,14 +4,14 @@ module BSD
4
4
  end unless defined?(BSD)
5
5
 
6
6
  module BSD::Capsicum
7
+ require "bsdcapsicum.rb.so"
7
8
  require_relative "capsicum/version"
8
- require_relative "capsicum/constants"
9
9
  require_relative "capsicum/ffi"
10
+ require_relative "capsicum/constants"
10
11
  extend self
11
12
 
12
13
  ##
13
14
  # Check if we're in capability mode
14
- #
15
15
  # @see https://man.freebsd.org/cgi/man.cgi?query=cap_getmode&apropos=0&sektion=2&format=html cap_getmode(2)
16
16
  # @raise [SystemCallError]
17
17
  # Might raise a subclass of SystemCallError
@@ -31,7 +31,6 @@ module BSD::Capsicum
31
31
 
32
32
  ##
33
33
  # Enter a process into capability mode
34
- #
35
34
  # @see https://man.freebsd.org/cgi/man.cgi?query=cap_enter&apropos=0&sektion=2&format=html cap_enter(2)
36
35
  # @raise [SystemCallError]
37
36
  # Might raise a subclass of SystemCallError
@@ -42,29 +41,60 @@ module BSD::Capsicum
42
41
  raise(SystemCallError.new("cap_enter", Fiddle.last_error))
43
42
  end
44
43
  alias_method :enter_capability_mode!, :enter!
44
+ alias_method :enter_cap_mode!, :enter!
45
45
 
46
46
  ##
47
47
  # Limit the capabilities of a file descriptor
48
- #
49
48
  # @see https://man.freebsd.org/cgi/man.cgi?query=cap_rights_limit&apropos=0&sektion=2&format=html cap_rights_limit(2)
50
49
  # @see BSD::Capsicum::Constants See Constants for a full list of capabilities
51
50
  # @example
52
- # # Limit standard output capabilities to read and write
53
- # BSD::Capsicum.set_rights!(STDOUT, %i[CAP_READ CAP_WRITE])
51
+ # # Permit standard output operations to read and write
52
+ # BSD::Capsicum.permit!(STDOUT, :CAP_READ, :CAP_WRITE)
53
+ # # Ditto
54
+ # BSD::Capsicum.permit!(STDOUT, :read, :write)
54
55
  # @raise [SystemCallError]
55
56
  # Might raise a subclass of SystemCallError
56
- # @param [#to_i] io
57
+ # @param [#fileno,#to_i] io
57
58
  # An IO object
58
- # @param [Array<Symbol, Integer>] capabilities
59
+ # @param [Array<Symbol, Integer>] caps
59
60
  # An allowed set of capabilities
61
+ # @param [Symbol] scope
62
+ # The scope of the permit, either `nil` or `:fcntl`
60
63
  # @return [Boolean]
61
64
  # Returns true when successful
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? ||
66
- raise(SystemCallError.new("cap_rights_limit", Fiddle.last_error))
65
+ def permit!(io, *caps, scope: :rights)
66
+ if scope == :fcntl
67
+ FFI.cap_fcntls_limit(io.to_i, caps).zero? ||
68
+ raise(SystemCallError.new("cap_fcntls_limit", Fiddle.last_error))
69
+ elsif scope == :rights
70
+ rightsp = Fiddle::Pointer.malloc(Constants::SIZEOF_CAP_RIGHTS_T)
71
+ FFI.cap_rights_init(rightsp, *caps)
72
+ FFI.cap_rights_limit(io.to_i, rightsp).zero? ||
73
+ raise(SystemCallError.new("cap_rights_limit", Fiddle.last_error))
74
+ else
75
+ raise ArgumentError, "invalid scope: #{scope}"
76
+ end
67
77
  ensure
68
- rightsp.call_free
78
+ rightsp&.call_free
79
+ end
80
+
81
+ ##
82
+ # This module is included into Ruby's IO class
83
+ module IO
84
+ ##
85
+ # Limit the capabilities of a file descriptor
86
+ # @param [Array<Symbol, Integer>] caps
87
+ # An allowed set of capabilities
88
+ # @param [Symbol] scope
89
+ # The scope of the permit, either `nil` or `:fcntl`
90
+ # @see BSD::Capsicum::Constants See CAP_FCNTLS_* for a full list of capabilities
91
+ # @see BSD::Capsicum::Constants See CAP_* for a full list of capabilities
92
+ def permit!(*caps, scope: :rights)
93
+ BSD::Capsicum.permit!(self, *caps, scope:)
94
+ end
69
95
  end
70
96
  end
97
+
98
+ class IO
99
+ include BSD::Capsicum::IO
100
+ end
@@ -0,0 +1,19 @@
1
+ require "bundler/setup"
2
+ require "bsd/capsicum"
3
+
4
+ print "In capability mode: ", (BSD::Capsicum.capability_mode? ? "yes" : "no"), "\n"
5
+ BSD::Capsicum.enter_capability_mode!
6
+ print "Enter capability mode: ok", "\n"
7
+ print "In capability mode: ", (BSD::Capsicum.capability_mode? ? "yes" : "no"), "\n"
8
+
9
+ begin
10
+ File.new(File::NULL)
11
+ rescue Errno::ECAPMODE => ex
12
+ print "Error: #{ex.message} (#{ex.class})", "\n"
13
+ end
14
+
15
+ ##
16
+ # In capability mode: no
17
+ # Enter capability mode: ok
18
+ # In capability mode: yes
19
+ # Error: Not permitted in capability mode @ rb_sysopen - /dev/null (Errno::ECAPMODE)
@@ -0,0 +1,19 @@
1
+ require "bundler/setup"
2
+ require "bsd/capsicum"
3
+
4
+ print "[parent] In capability mode: ", (BSD::Capsicum.in_capability_mode? ? "yes" : "no"), "\n"
5
+ fork do
6
+ print "[child] Enter capability mode: ", (BSD::Capsicum.enter! ? "ok" : "error"), "\n"
7
+ print "[child] In capability mode: ", (BSD::Capsicum.in_capability_mode? ? "yes" : "no"), "\n"
8
+ print "[child] Exit", "\n"
9
+ exit 42
10
+ end
11
+ Process.wait
12
+ print "[parent] In capability mode: ", (BSD::Capsicum.in_capability_mode? ? "yes" : "no"), "\n"
13
+
14
+ ##
15
+ # [parent] In capability mode: no
16
+ # [child] Enter capability mode: ok
17
+ # [child] In capability mode: yes
18
+ # [child] Exit
19
+ # [parent] In capability mode: no
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env ruby
2
+ require "bsd/capsicum"
3
+ require "tmpdir"
4
+
5
+ path = File.join(Dir.tmpdir, "bsdcapsicum.txt")
6
+ file = File.open(path, File::CREAT | File::TRUNC | File::RDWR)
7
+ file.sync = true
8
+ print "[parent] Obtain file descriptor (with full capabilities)", "\n"
9
+ fork do
10
+ file.permit!(:read)
11
+ print "[child] Reduce capabilities to read", "\n"
12
+
13
+ file.gets
14
+ print "[child] Read OK", "\n"
15
+
16
+ begin
17
+ file.write "foo"
18
+ rescue Errno::ENOTCAPABLE => ex
19
+ print "[child] Error: #{ex.message} (#{ex.class})", "\n"
20
+ end
21
+ end
22
+ Process.wait
23
+ file.write "[parent] Hello from #{Process.pid}", "\n"
24
+ print "[parent] Write OK", "\n"
25
+
26
+ ##
27
+ # [parent] Obtain file descriptor (with full capabilities)
28
+ # [child] Reduce capabilities to read
29
+ # [child] Read OK
30
+ # [child] Error: Capabilities insufficient @ io_write - /tmp/bsdcapsicum.txt (Errno::ENOTCAPABLE)
31
+ # [parent] Write OK
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+ require "bsd/capsicum"
3
+ require "tmpdir"
4
+ require "fcntl"
5
+
6
+ path = File.join(Dir.tmpdir, "bsdcapsicum.txt")
7
+ file = File.open(path, File::CREAT | File::TRUNC | File::RDWR)
8
+ file.sync = true
9
+ print "Obtain file descriptor (with full capabilities)", "\n"
10
+
11
+ file.permit!(:fcntl)
12
+ print "Reduce capabilities to fcntl", "\n"
13
+
14
+ file.permit!(:GETFL, scope: :fcntl)
15
+ print "Reduces fcntl capabilties to GETFL", "\n"
16
+
17
+ flags = file.fcntl(Fcntl::F_GETFL)
18
+ print "Get fcntl flags: OK", "\n"
19
+
20
+ begin
21
+ print "Try to set fcntls flag ... ", "\n"
22
+ file.fcntl(Fcntl::F_SETFL, flags | Fcntl::O_APPEND)
23
+ rescue Errno::ENOTCAPABLE => ex
24
+ print "Error: #{ex.message} (#{ex.class})", "\n"
25
+ end
26
+
27
+ ##
28
+ # Obtain file descriptor (with full capabilities)
29
+ # Reduce capabilities to fcntl
30
+ # Reduce fcntl capabilties to fcntl_getfl
31
+ # Get fcntl flags: OK
32
+ # Try to set fcntls flag ...
33
+ # Error: Capabilities insufficient @ finish_narg - /tmp/bsdcapsicum.txt (Errno::ENOTCAPABLE)
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.3.0
4
+ version: 0.4.1
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-07-19 00:00:00.000000000 Z
12
+ date: 2025-04-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: fiddle
@@ -53,6 +53,20 @@ dependencies:
53
53
  - - "~>"
54
54
  - !ruby/object:Gem::Version
55
55
  version: '13.2'
56
+ - !ruby/object:Gem::Dependency
57
+ name: rake-compiler
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: '1.2'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '1.2'
56
70
  - !ruby/object:Gem::Dependency
57
71
  name: minitest
58
72
  requirement: !ruby/object:Gem::Requirement
@@ -120,11 +134,17 @@ files:
120
134
  - LICENSE.ruby-capsicum
121
135
  - README.md
122
136
  - bsdcapsicum.rb.gemspec
137
+ - ext/bsdcapsicum.rb/bsdcapsicum.c
138
+ - ext/bsdcapsicum.rb/extconf.rb
123
139
  - lib/bsd/capsicum.rb
124
140
  - lib/bsd/capsicum/constants.rb
125
141
  - lib/bsd/capsicum/ffi.rb
126
142
  - lib/bsd/capsicum/version.rb
127
143
  - lib/bsdcapsicum.rb
144
+ - share/examples/bsdcapsicum.rb/1_capability_mode_example.rb
145
+ - share/examples/bsdcapsicum.rb/2_fork_example.rb
146
+ - share/examples/bsdcapsicum.rb/3_set_rights_example.rb
147
+ - share/examples/bsdcapsicum.rb/4_fcntl_example.rb
128
148
  homepage: https://github.com/0x1eef/bsdcapsicum.rb
129
149
  licenses:
130
150
  - 0BSD
@@ -145,7 +165,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
145
165
  - !ruby/object:Gem::Version
146
166
  version: '0'
147
167
  requirements: []
148
- rubygems_version: 3.5.11
168
+ rubygems_version: 3.5.23
149
169
  signing_key:
150
170
  specification_version: 4
151
171
  summary: Ruby bindings for FreeBSD's capsicum(4)