pledge 1.1.0 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +8 -0
- data/README.rdoc +73 -12
- data/Rakefile +10 -9
- data/ext/pledge/extconf.rb +3 -1
- data/ext/pledge/pledge.c +42 -0
- data/lib/unveil.rb +71 -0
- data/spec/pledge_spec.rb +8 -15
- metadata +45 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f794b6f397a93e9eaabdfff4928f49537fb0a45b55c042c7dc27c46d27918f5a
|
4
|
+
data.tar.gz: a0291c2d672594938292c7a6a83cc111d3c54679ea412c679e28087b8a870a89
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9242a1de3c01334a60cb13ab98410dbe533e089228cf1a7a7cfdbb55a6d1ca7614aacbb306974ff85db1165b02a68e292ee9704038e41e9fab5100cccc7b68dc
|
7
|
+
data.tar.gz: e51bf3d1b375e5eba599052423fce0438cb21b3810b8dd38d6a26d7543bba2db8e8547edd0b53bbab99c999dfdead8b6f68e88620cfd9368a0c67bfcdf1c3d37
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
=== 1.3.0 (2022-12-19)
|
2
|
+
|
3
|
+
* Allow installation on platforms not supporting pledge, raising NotImplementedError when calling pledge/unveil methods in that case (jcs) (#3)
|
4
|
+
|
5
|
+
=== 1.2.0 (2019-07-07)
|
6
|
+
|
7
|
+
* Add unveil library and Pledge.unveil for access to unveil(2) to control file system access (jeremyevans)
|
8
|
+
|
1
9
|
=== 1.1.0 (2019-04-25)
|
2
10
|
|
3
11
|
* Support execpromises as optional second argument to Pledge.pledge (jeremyevans)
|
data/README.rdoc
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
= pledge
|
2
2
|
|
3
|
-
pledge exposes OpenBSD's pledge(2)
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
pledge exposes OpenBSD's pledge(2) and unveil(2) system
|
4
|
+
calls to ruby. pledge(2) allows a program to restrict the
|
5
|
+
types of operations the program can do, and unveil(2)
|
6
|
+
restricts access to the file system.
|
7
|
+
|
8
|
+
Unlike other similar systems, pledge and unveil are
|
9
|
+
designed for programs that need to use a wide variety of
|
10
|
+
operations and file access on initialization, but
|
8
11
|
a fewer number after initialization (when user input will
|
9
12
|
be accepted).
|
10
13
|
|
11
|
-
|
12
|
-
argument for execpromises on OpenBSD 6.3+.
|
13
|
-
|
14
|
-
== Usage
|
14
|
+
== pledge
|
15
15
|
|
16
16
|
First, you need to require the library
|
17
17
|
|
@@ -53,8 +53,6 @@ in other classes:
|
|
53
53
|
Object.send(:include, Pledge)
|
54
54
|
pledge("rpath")
|
55
55
|
|
56
|
-
== Options
|
57
|
-
|
58
56
|
See the pledge(2) man page for a description of the allowed
|
59
57
|
promises in the strings passed to +Pledge.pledge+.
|
60
58
|
|
@@ -63,6 +61,69 @@ promise is added automatically to the current process's promises,
|
|
63
61
|
as ruby does not function without it, but it is not added to
|
64
62
|
the execpromises (as you can execute non-ruby programs).
|
65
63
|
|
64
|
+
== unveil
|
65
|
+
|
66
|
+
First, you need to require the library
|
67
|
+
|
68
|
+
require 'unveil'
|
69
|
+
|
70
|
+
Then you can use +Pledge.unveil+ as the interface to the unveil(2)
|
71
|
+
system call. You pass +Pledge.unveil+ a hash of paths and permissions,
|
72
|
+
for those paths, and it calls unveil(2) with the path and permissions
|
73
|
+
for each entry.
|
74
|
+
|
75
|
+
The permissions should be a string with the following characters:
|
76
|
+
|
77
|
+
r :: Allow read access to existing files and directories
|
78
|
+
w :: Allow write access to existing files and directories
|
79
|
+
x :: Allow execute access to programs
|
80
|
+
c :: Allow create access for new files and directories
|
81
|
+
|
82
|
+
You can use the empty string as permissions if you want to allow no access
|
83
|
+
to the given path, even if you have granted some access to a folder above
|
84
|
+
the given folder. You can use a value of +:gem+ to allow read access to
|
85
|
+
the directory for the gem specified by the key.
|
86
|
+
|
87
|
+
+Pledge.unveil+ locks the file system access to the specified paths. If
|
88
|
+
you want to specify which paths to allow in multiple places in your
|
89
|
+
program, use +Pledge.unveil_without_lock+ for the initial calls and
|
90
|
+
+Pledge.unveil+ for the final call.
|
91
|
+
|
92
|
+
If +Pledge.unveil+ is called with an empty hash, it adds an unveil of +/+
|
93
|
+
with no permissions, which denies all access to the file system if
|
94
|
+
+unveil_without_lock+ was not called previously with paths.
|
95
|
+
|
96
|
+
Example:
|
97
|
+
|
98
|
+
Pledge.unveil(
|
99
|
+
'/home/foo/bar' => 'r',
|
100
|
+
'/home/foo/bar/data' => 'rwc',
|
101
|
+
'/bin' => 'x',
|
102
|
+
'/home/foo/bar/secret' => '',
|
103
|
+
'rack' => :gem
|
104
|
+
)
|
105
|
+
|
106
|
+
The value of :gem is mostly mostly needed if the gem uses autoload or
|
107
|
+
other forms of runtime requires. This allows read access to
|
108
|
+
all files in the gem's folder, not just the gem's require paths,
|
109
|
+
so it works correctly for gems that access data (e.g. templates)
|
110
|
+
outside of the gem's require paths.
|
111
|
+
|
112
|
+
If you plan to use pledge and unveil together, you should
|
113
|
+
unveil before pledging, unless you use the +unveil+
|
114
|
+
promise when pledging.
|
115
|
+
|
116
|
+
=== Issues with unveil and File.realpath
|
117
|
+
|
118
|
+
+Pledge.unveil+ does not work with +File.realpath+ on Ruby <2.7.
|
119
|
+
The Ruby ports officially supported by OpenBSD have had support to
|
120
|
+
allow them to work together backported, as long as you are running
|
121
|
+
OpenBSD 6.6+ (or 6.5-current after July 2019). As +require+ uses
|
122
|
+
+File.realpath+, this means in most cases where you would want to
|
123
|
+
use the +:gem+ support, it will not actually work correctly unless
|
124
|
+
you are using Ruby 2.7+ or an OpenBSD package with the backported
|
125
|
+
support.
|
126
|
+
|
66
127
|
== Reporting issues/bugs
|
67
128
|
|
68
129
|
This library uses GitHub Issues for tracking issues/bugs:
|
@@ -81,7 +142,7 @@ To get a copy:
|
|
81
142
|
|
82
143
|
== Requirements
|
83
144
|
|
84
|
-
* OpenBSD 5.9+
|
145
|
+
* OpenBSD 5.9+ (6.4+ for unveil, but 6.6+ recommended)
|
85
146
|
* ruby 1.8.7+
|
86
147
|
* rake-compiler (if compiling)
|
87
148
|
|
data/Rakefile
CHANGED
@@ -1,13 +1,6 @@
|
|
1
|
-
require "rake"
|
2
1
|
require "rake/clean"
|
3
2
|
|
4
|
-
CLEAN.include %w'
|
5
|
-
|
6
|
-
desc "Do a full cleaning"
|
7
|
-
task :distclean do
|
8
|
-
CLEAN.include %w'tmp pkg tame*.gem lib/*.so'
|
9
|
-
Rake::Task[:clean].invoke
|
10
|
-
end
|
3
|
+
CLEAN.include %w'lib/*.so tmp coverage'
|
11
4
|
|
12
5
|
desc "Build the gem"
|
13
6
|
task :package do
|
@@ -17,12 +10,20 @@ end
|
|
17
10
|
desc "Run specs"
|
18
11
|
task :spec => :compile do
|
19
12
|
ruby = ENV['RUBY'] ||= FileUtils::RUBY
|
20
|
-
sh %{#{ruby} spec/pledge_spec.rb}
|
13
|
+
sh %{#{ruby} #{"-w" if RUBY_VERSION >= '3'} spec/pledge_spec.rb}
|
21
14
|
end
|
22
15
|
|
23
16
|
desc "Run specs"
|
24
17
|
task :default => :spec
|
25
18
|
|
19
|
+
desc "Run specs with coverage"
|
20
|
+
task :spec_cov => [:compile] do
|
21
|
+
ruby = ENV['RUBY'] ||= FileUtils::RUBY
|
22
|
+
ENV['COVERAGE'] = '1'
|
23
|
+
FileUtils.rm_rf('coverage')
|
24
|
+
sh %{#{ruby} spec/unveil_spec.rb}
|
25
|
+
end
|
26
|
+
|
26
27
|
begin
|
27
28
|
require 'rake/extensiontask'
|
28
29
|
Rake::ExtensionTask.new('pledge')
|
data/ext/pledge/extconf.rb
CHANGED
data/ext/pledge/pledge.c
CHANGED
@@ -5,6 +5,7 @@
|
|
5
5
|
static VALUE ePledgeInvalidPromise;
|
6
6
|
static VALUE ePledgePermissionIncreaseAttempt;
|
7
7
|
static VALUE ePledgeError;
|
8
|
+
static VALUE ePledgeUnveilError;
|
8
9
|
|
9
10
|
static VALUE rb_pledge(int argc, VALUE* argv, VALUE pledge_class) {
|
10
11
|
VALUE promises = Qnil;
|
@@ -12,6 +13,7 @@ static VALUE rb_pledge(int argc, VALUE* argv, VALUE pledge_class) {
|
|
12
13
|
const char * prom = NULL;
|
13
14
|
const char * execprom = NULL;
|
14
15
|
|
16
|
+
#ifdef HAVE_PLEDGE
|
15
17
|
rb_scan_args(argc, argv, "11", &promises, &execpromises);
|
16
18
|
|
17
19
|
if (!NIL_P(promises)) {
|
@@ -40,10 +42,44 @@ static VALUE rb_pledge(int argc, VALUE* argv, VALUE pledge_class) {
|
|
40
42
|
rb_raise(ePledgeError, "pledge error");
|
41
43
|
}
|
42
44
|
}
|
45
|
+
#else
|
46
|
+
rb_raise(rb_eNotImpError, "pledge not supported");
|
47
|
+
#endif
|
43
48
|
|
44
49
|
return Qnil;
|
45
50
|
}
|
46
51
|
|
52
|
+
#ifdef HAVE_UNVEIL
|
53
|
+
static VALUE check_unveil(const char * path, const char * perm) {
|
54
|
+
if (unveil(path, perm) != 0) {
|
55
|
+
switch(errno) {
|
56
|
+
case EINVAL:
|
57
|
+
rb_raise(ePledgeUnveilError, "invalid permissions value");
|
58
|
+
case EPERM:
|
59
|
+
rb_raise(ePledgeUnveilError, "attempt to increase permissions, path not accessible, or unveil already locked");
|
60
|
+
case E2BIG:
|
61
|
+
rb_raise(ePledgeUnveilError, "per-process limit for unveiled paths reached");
|
62
|
+
case ENOENT:
|
63
|
+
rb_raise(ePledgeUnveilError, "directory in the path does not exist");
|
64
|
+
default:
|
65
|
+
rb_raise(ePledgeUnveilError, "unveil error");
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
return Qnil;
|
70
|
+
}
|
71
|
+
|
72
|
+
static VALUE rb_unveil(VALUE pledge_class, VALUE path, VALUE perm) {
|
73
|
+
SafeStringValue(path);
|
74
|
+
SafeStringValue(perm);
|
75
|
+
return check_unveil(RSTRING_PTR(path), RSTRING_PTR(perm));
|
76
|
+
}
|
77
|
+
|
78
|
+
static VALUE rb_finalize_unveil(VALUE pledge_class) {
|
79
|
+
return check_unveil(NULL, NULL);
|
80
|
+
}
|
81
|
+
#endif
|
82
|
+
|
47
83
|
void Init_pledge(void) {
|
48
84
|
VALUE cPledge;
|
49
85
|
cPledge = rb_define_module("Pledge");
|
@@ -52,4 +88,10 @@ void Init_pledge(void) {
|
|
52
88
|
ePledgeError = rb_define_class_under(cPledge, "Error", rb_eStandardError);
|
53
89
|
ePledgeInvalidPromise = rb_define_class_under(cPledge, "InvalidPromise", ePledgeError);
|
54
90
|
ePledgePermissionIncreaseAttempt = rb_define_class_under(cPledge, "PermissionIncreaseAttempt", ePledgeError);
|
91
|
+
|
92
|
+
#ifdef HAVE_UNVEIL
|
93
|
+
rb_define_private_method(cPledge, "_unveil", rb_unveil, 2);
|
94
|
+
rb_define_private_method(cPledge, "_finalize_unveil!", rb_finalize_unveil, 0);
|
95
|
+
ePledgeUnveilError = rb_define_class_under(cPledge, "UnveilError", rb_eStandardError);
|
96
|
+
#endif
|
55
97
|
}
|
data/lib/unveil.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
require_relative 'pledge'
|
4
|
+
|
5
|
+
module Pledge
|
6
|
+
# Limit access to the file system using unveil(2). +paths+ should be a hash
|
7
|
+
# where keys are paths and values are the access permissions for that path. Each
|
8
|
+
# value should be a string with the following characters specifying what
|
9
|
+
# permissions are allowed:
|
10
|
+
#
|
11
|
+
# r :: Allow read access to existing files and directories
|
12
|
+
# w :: Allow write access to existing files and directories
|
13
|
+
# c :: Allow create/delete access for new files and directories
|
14
|
+
# x :: Allow execute access to programs
|
15
|
+
#
|
16
|
+
# You can use the empty string as permissions if you want to allow no access
|
17
|
+
# to the given path, even if you have granted some access to a folder above
|
18
|
+
# the given folder. You can use a value of +:gem+ to allow read access to
|
19
|
+
# the directory for the gem specified by the key.
|
20
|
+
#
|
21
|
+
# If called with an empty hash, adds an unveil of +/+ with no permissions,
|
22
|
+
# which denies all access to the file system if +unveil_without_lock+
|
23
|
+
# was not called previously.
|
24
|
+
def unveil(paths)
|
25
|
+
# :nocov:
|
26
|
+
raise NotImplementedError, "unveil not supported" unless Pledge.respond_to?(:_unveil, true)
|
27
|
+
# :nocov:
|
28
|
+
|
29
|
+
if paths.empty?
|
30
|
+
paths = {'/'=>''}
|
31
|
+
end
|
32
|
+
|
33
|
+
unveil_without_lock(paths)
|
34
|
+
_finalize_unveil!
|
35
|
+
end
|
36
|
+
|
37
|
+
# Same as unveil, but allows for future calls to unveil or unveil_without_lock.
|
38
|
+
def unveil_without_lock(paths)
|
39
|
+
# :nocov:
|
40
|
+
raise NotImplementedError, "unveil not supported" unless Pledge.respond_to?(:_unveil, true)
|
41
|
+
# :nocov:
|
42
|
+
|
43
|
+
paths = Hash[paths]
|
44
|
+
|
45
|
+
paths.to_a.each do |path, perm|
|
46
|
+
unless path.is_a?(String)
|
47
|
+
raise UnveilError, "unveil path is not a string: #{path.inspect}"
|
48
|
+
end
|
49
|
+
|
50
|
+
case perm
|
51
|
+
when :gem
|
52
|
+
unless spec = Gem.loaded_specs[path]
|
53
|
+
raise UnveilError, "cannot unveil gem #{path} as it is not loaded"
|
54
|
+
end
|
55
|
+
|
56
|
+
paths.delete(path)
|
57
|
+
paths[spec.full_gem_path] = 'r'
|
58
|
+
when String
|
59
|
+
# nothing to do
|
60
|
+
else
|
61
|
+
raise UnveilError, "unveil permission is not a string: #{perm.inspect}"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
paths.each do |path, perm|
|
66
|
+
_unveil(path, perm)
|
67
|
+
end
|
68
|
+
|
69
|
+
nil
|
70
|
+
end
|
71
|
+
end
|
data/spec/pledge_spec.rb
CHANGED
@@ -1,11 +1,4 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require 'rubygems'
|
4
|
-
ENV['MT_NO_PLUGINS'] = '1' # Work around stupid autoloading of plugins
|
5
|
-
gem 'minitest'
|
6
|
-
require 'minitest/autorun'
|
7
|
-
|
8
|
-
RUBY = ENV['RUBY'] || 'ruby'
|
1
|
+
require_relative 'unveil_spec'
|
9
2
|
|
10
3
|
describe "Pledge.pledge" do
|
11
4
|
def execpledged(promises, execpromises, code)
|
@@ -41,7 +34,7 @@ describe "Pledge.pledge" do
|
|
41
34
|
proc{Pledge.pledge("foo")}.must_raise Pledge::InvalidPromise
|
42
35
|
end
|
43
36
|
|
44
|
-
it "should raise a Pledge::PermissionIncreaseAttempt if attempting to increase
|
37
|
+
it "should raise a Pledge::PermissionIncreaseAttempt if attempting to increase permissions" do
|
45
38
|
pledged("begin; Pledge.pledge('rpath'); rescue Pledge::PermissionIncreaseAttempt; exit 0; end; exit 1")
|
46
39
|
end
|
47
40
|
|
@@ -73,8 +66,8 @@ describe "Pledge.pledge" do
|
|
73
66
|
|
74
67
|
it "should allow dns lookups if dns is used" do
|
75
68
|
with_lib('socket') do
|
76
|
-
unpledged("
|
77
|
-
pledged("
|
69
|
+
unpledged("Addrinfo.getaddrinfo('google.com', nil)")
|
70
|
+
pledged("Addrinfo.getaddrinfo('google.com', nil)", "dns")
|
78
71
|
end
|
79
72
|
end
|
80
73
|
|
@@ -121,9 +114,9 @@ describe "Pledge.pledge" do
|
|
121
114
|
end
|
122
115
|
|
123
116
|
it "should handle both promises and execpromises arguments" do
|
124
|
-
execpledged("proc exec rpath", "stdio rpath", "exit(`cat MIT-LICENSE` == File.read('MIT-LICENSE')
|
125
|
-
execpledged("proc exec", "stdio rpath", "$stderr.reopen('/dev/null', 'w'); exit(`cat MIT-LICENSE` == File.read('MIT-LICENSE')
|
126
|
-
execpledged("proc exec rpath", "stdio", "$stderr.reopen('/dev/null', 'w'); exit(`cat MIT-LICENSE` == File.read('MIT-LICENSE')
|
117
|
+
execpledged("proc exec rpath", "stdio rpath", "exit(`cat MIT-LICENSE` == File.read('MIT-LICENSE'))").must_equal true
|
118
|
+
execpledged("proc exec", "stdio rpath", "$stderr.reopen('/dev/null', 'w'); exit(`cat MIT-LICENSE` == File.read('MIT-LICENSE'))").must_equal false
|
119
|
+
execpledged("proc exec rpath", "stdio", "$stderr.reopen('/dev/null', 'w'); exit(`cat MIT-LICENSE` == File.read('MIT-LICENSE'))").must_equal false
|
127
120
|
end
|
128
121
|
|
129
122
|
it "should handle nil arguments" do
|
@@ -133,6 +126,6 @@ describe "Pledge.pledge" do
|
|
133
126
|
execpledged("", nil, "`cat MIT-LICENSE`").must_equal false
|
134
127
|
execpledged(nil, "stdio rpath", "`cat MIT-LICENSE`").must_equal true
|
135
128
|
execpledged(nil, "stdio", "File.read('MIT-LICENSE')").must_equal true
|
136
|
-
execpledged(nil, "stdio", "$stderr.reopen('/dev/null', 'w'); exit(`cat MIT-LICENSE` == File.read('MIT-LICENSE')
|
129
|
+
execpledged(nil, "stdio", "$stderr.reopen('/dev/null', 'w'); exit(`cat MIT-LICENSE` == File.read('MIT-LICENSE'))").must_equal false
|
137
130
|
end
|
138
131
|
end
|
metadata
CHANGED
@@ -1,23 +1,50 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pledge
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Evans
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
12
|
-
dependencies:
|
11
|
+
date: 2022-12-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: minitest-global_expectations
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake-compiler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
13
41
|
description: |
|
14
|
-
pledge exposes OpenBSD's pledge(2) system
|
15
|
-
program to restrict the types of operations the program
|
16
|
-
|
17
|
-
pledge
|
18
|
-
use a wide variety of operations on initialization, but
|
19
|
-
|
20
|
-
be accepted).
|
42
|
+
pledge exposes OpenBSD's pledge(2) and unveil(2) system calls to Ruby, allowing
|
43
|
+
a program to restrict the types of operations the program can do, and the file
|
44
|
+
system access the program has, after the point of call. Unlike other similar
|
45
|
+
systems, pledge and unveil are specifically designed for programs that need to
|
46
|
+
use a wide variety of operations on initialization, but a fewer number after
|
47
|
+
initialization (when user input will be accepted).
|
21
48
|
email: code@jeremyevans.net
|
22
49
|
executables: []
|
23
50
|
extensions:
|
@@ -33,18 +60,19 @@ files:
|
|
33
60
|
- Rakefile
|
34
61
|
- ext/pledge/extconf.rb
|
35
62
|
- ext/pledge/pledge.c
|
63
|
+
- lib/unveil.rb
|
36
64
|
- spec/pledge_spec.rb
|
37
65
|
homepage: https://github.com/jeremyevans/ruby-pledge
|
38
66
|
licenses:
|
39
67
|
- MIT
|
40
68
|
metadata: {}
|
41
|
-
post_install_message:
|
69
|
+
post_install_message:
|
42
70
|
rdoc_options:
|
43
71
|
- "--quiet"
|
44
72
|
- "--line-numbers"
|
45
73
|
- "--inline-source"
|
46
74
|
- "--title"
|
47
|
-
- 'pledge: restrict system operations on OpenBSD'
|
75
|
+
- 'pledge: restrict system operations and file system access on OpenBSD'
|
48
76
|
- "--main"
|
49
77
|
- README.rdoc
|
50
78
|
require_paths:
|
@@ -53,15 +81,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
53
81
|
requirements:
|
54
82
|
- - ">="
|
55
83
|
- !ruby/object:Gem::Version
|
56
|
-
version: 1.
|
84
|
+
version: 1.9.2
|
57
85
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
86
|
requirements:
|
59
87
|
- - ">="
|
60
88
|
- !ruby/object:Gem::Version
|
61
89
|
version: '0'
|
62
90
|
requirements: []
|
63
|
-
rubygems_version: 3.
|
64
|
-
signing_key:
|
91
|
+
rubygems_version: 3.3.26
|
92
|
+
signing_key:
|
65
93
|
specification_version: 4
|
66
|
-
summary: Restrict system operations on OpenBSD
|
94
|
+
summary: Restrict system operations and file system access on OpenBSD
|
67
95
|
test_files: []
|