hrr_rb_lxns 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +33 -0
- data/hrr_rb_lxns.gemspec +2 -0
- data/lib/hrr_rb_lxns/version.rb +1 -1
- data/lib/hrr_rb_lxns.rb +102 -4
- metadata +17 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f96ad9d7f1439e815c23aebf272ff8ca0984dba7ec9775e22483d33a390e82b1
|
4
|
+
data.tar.gz: 0eba5185a5c6c23660b69acd7982b5982830a50e2dad726b09c1f89f93325780
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: af3f529c576999c3f11371b0ea4ffaf59ad62f0500185a3b238026d41744251732f24d1123590f981d9eeb260188599358b626fd634d69f25a13aafe5cfbb694
|
7
|
+
data.tar.gz: d28a267db5871149c88a145aef192612d8f007826670ded888b5a96836593211431cf4d038e6fb314427ccefdc3dba7dd5b3439b14374f36a6d813dad201a0da
|
data/README.md
CHANGED
@@ -45,6 +45,39 @@ File.readlink "/proc/self/ns/uts" # => uts:[xxx]
|
|
45
45
|
File.readlink "/proc/self/ns/mnt" # => mnt:[yyy]
|
46
46
|
```
|
47
47
|
|
48
|
+
HrrRbLxns.unshare supports creating persistent namespaces files by bind-mount. The files are specified in an options hash. The keys which are available in the hash for each namespace are `:mount`, `:uts`, `:ipc`, `:network`, `:pid`, `:user`, `:cgroup`, and `:time`.
|
49
|
+
Note that files that namespaces are bind-mounted must exist. The library does just bind-mount, not create the files. And the files and their mount information are kept after the caller process is finished.
|
50
|
+
When unsharing pid namespace, the namespace file should be bind-mounted against the caller's child process. For this case, `:fork` option is supported.
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
File.readlink "/proc/self/ns/uts" # => uts:[aaa]
|
54
|
+
# Prepare an options hash to specify a file that namespaces are bind-mounted
|
55
|
+
options = {:uts => "/path/to/myns/uts"}
|
56
|
+
HrrRbLxns.unshare HrrRbLxns::NEWUTS, options # => 0
|
57
|
+
File.readlink "/proc/self/ns/uts" # => uts:[xxx]
|
58
|
+
File.stat(options[:uts]).ino # => xxx
|
59
|
+
|
60
|
+
# For mount namespace, the parent directory's propagation needs to be private
|
61
|
+
FileUtils.mkdir "/path/to/myns"
|
62
|
+
HrrRbMount.bind "/path/to/myns" "/path/to/myns"
|
63
|
+
HrrRbMount.make_private "/path/to/myns"
|
64
|
+
FileUtils.touch "/path/to/myns/mnt"
|
65
|
+
options = {:mount => "/path/to/myns/mnt"}
|
66
|
+
HrrRbLxns.unshare HrrRbLxns::NEWNS, options # => 0
|
67
|
+
|
68
|
+
# For pid namespace, :fork option is available
|
69
|
+
options = {:pid => "/path/to/myns/pid", :fork => true}
|
70
|
+
# .unshare method with :fork option works like Kernel.#fork after unshare(2)
|
71
|
+
if pid = HrrRbLxns.unshare HrrRbLxns::NEWPID, options
|
72
|
+
# In parent, .unshare returns the child process's PID (In this case, it is 1 because unsharing PID namespace)
|
73
|
+
# Do something
|
74
|
+
Process.waitpid pid
|
75
|
+
else
|
76
|
+
# In child, .unshare returns nil
|
77
|
+
# Do something
|
78
|
+
end
|
79
|
+
```
|
80
|
+
|
48
81
|
### Setns
|
49
82
|
|
50
83
|
HrrRbLxns.setns method wraps around setns(2) system call. The system call associate the caller process's namespace to an existing one, which is disassociated by some other process.
|
data/hrr_rb_lxns.gemspec
CHANGED
data/lib/hrr_rb_lxns/version.rb
CHANGED
data/lib/hrr_rb_lxns.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require "hrr_rb_lxns/version"
|
2
2
|
require "hrr_rb_lxns/hrr_rb_lxns"
|
3
|
+
require "hrr_rb_mount"
|
3
4
|
|
4
5
|
# Utilities working with Linux namespaces for CRuby.
|
5
6
|
module HrrRbLxns
|
@@ -33,14 +34,29 @@ module HrrRbLxns
|
|
33
34
|
# "U" : NEWUSER <br>
|
34
35
|
# "C" : NEWCGROUP <br>
|
35
36
|
# "T" : NEWTIME <br>
|
36
|
-
# @param options [Hash]
|
37
|
-
# @
|
37
|
+
# @param options [Hash] Optional arguments.
|
38
|
+
# @option options [String] :mount A persistent mount namespace to be created by bind mount.
|
39
|
+
# @option options [String] :uts A persistent uts namespace to be created by bind mount.
|
40
|
+
# @option options [String] :ipc A persistent ipc namespace to be created by bind mount.
|
41
|
+
# @option options [String] :network A persistent network namespace to be created by bind mount.
|
42
|
+
# @option options [String] :pid A persistent pid namespace to be created by bind mount.
|
43
|
+
# @option options [String] :user A persistent user namespace to be created by bind mount.
|
44
|
+
# @option options [String] :cgroup A persistent cgroup namespace to be created by bind mount.
|
45
|
+
# @option options [String] :time A persistent time namespace to be created by bind mount.
|
46
|
+
# @option options [Boolean] :fork If specified, the caller process forks after unshare.
|
47
|
+
# @return [Integer, nil] Usually 0. If :fork is specified in options, then PID of the child process in parent, nil in child (as same as Kernel.#fork).
|
38
48
|
# @raise [ArgumentError] When given flags argument is not appropriate.
|
39
49
|
# @raise [Errno::EXXX] In case unshare(2) system call failed.
|
40
|
-
|
41
50
|
def self.unshare flags, options={}
|
42
51
|
_flags = interpret_flags flags
|
43
|
-
|
52
|
+
bind_ns_files_from_child(_flags, options) do
|
53
|
+
if fork? options
|
54
|
+
__unshare__ _flags
|
55
|
+
fork
|
56
|
+
else
|
57
|
+
__unshare__ _flags
|
58
|
+
end
|
59
|
+
end
|
44
60
|
end
|
45
61
|
|
46
62
|
# A wrapper around setns(2) system call.
|
@@ -120,6 +136,88 @@ module HrrRbLxns
|
|
120
136
|
end
|
121
137
|
end
|
122
138
|
|
139
|
+
def self.fork? options
|
140
|
+
options[:fork]
|
141
|
+
end
|
142
|
+
|
143
|
+
def self.bind_ns_files? options
|
144
|
+
list = Array.new
|
145
|
+
list.push :ipc if const_defined?(:NEWIPC)
|
146
|
+
list.push :mount if const_defined?(:NEWNS)
|
147
|
+
list.push :network if const_defined?(:NEWNET)
|
148
|
+
list.push :pid if const_defined?(:NEWPID)
|
149
|
+
list.push :uts if const_defined?(:NEWUTS)
|
150
|
+
list.push :user if const_defined?(:NEWUSER)
|
151
|
+
list.push :cgroup if const_defined?(:NEWCGROUP)
|
152
|
+
list.push :time if const_defined?(:NEWTIME)
|
153
|
+
(list & options.keys).empty?.!
|
154
|
+
end
|
155
|
+
|
156
|
+
# In some cases, namespace files need to be created by an external process.
|
157
|
+
# Thus, this method calls fork and the child process creates the namespace files.
|
158
|
+
def self.bind_ns_files_from_child flags, options
|
159
|
+
if bind_ns_files? options
|
160
|
+
pid_to_bind = Process.pid
|
161
|
+
pid = nil
|
162
|
+
begin
|
163
|
+
io_r, io_w = IO.pipe
|
164
|
+
if pid = fork
|
165
|
+
ret = yield
|
166
|
+
io_w.write "1"
|
167
|
+
io_w.close
|
168
|
+
if pid_to_bind == Process.pid
|
169
|
+
_, status = Process.waitpid2 pid
|
170
|
+
raise Marshal.load(io_r.read) if status.exitstatus != 0
|
171
|
+
end
|
172
|
+
ret
|
173
|
+
else
|
174
|
+
begin
|
175
|
+
exit_status = true
|
176
|
+
io_r.read 1
|
177
|
+
bind_ns_files flags, options, pid_to_bind
|
178
|
+
rescue Exception => e
|
179
|
+
exit_status = false
|
180
|
+
io_w.write Marshal.dump(e)
|
181
|
+
ensure
|
182
|
+
exit! exit_status
|
183
|
+
end
|
184
|
+
end
|
185
|
+
ensure
|
186
|
+
io_w.write "1" rescue nil # just in case getting an error before io_w.write
|
187
|
+
io_w.close rescue nil
|
188
|
+
io_r.close rescue nil
|
189
|
+
if pid_to_bind == Process.pid
|
190
|
+
begin
|
191
|
+
Process.waitpid pid
|
192
|
+
rescue Errno::ECHILD
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
else
|
197
|
+
yield
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
def self.bind_ns_files flags, options, pid
|
202
|
+
list = Array.new
|
203
|
+
list.push ["ipc", NEWIPC, :ipc ] if const_defined?(:NEWIPC)
|
204
|
+
list.push ["mnt", NEWNS, :mount ] if const_defined?(:NEWNS)
|
205
|
+
list.push ["net", NEWNET, :network] if const_defined?(:NEWNET)
|
206
|
+
list.push ["pid", NEWPID, :pid ] if const_defined?(:NEWPID)
|
207
|
+
if File.exist? "/proc/#{pid}/ns/pid_for_children"
|
208
|
+
list.last[0] = "pid_for_children"
|
209
|
+
end
|
210
|
+
list.push ["uts", NEWUTS, :uts ] if const_defined?(:NEWUTS)
|
211
|
+
list.push ["user", NEWUSER, :user ] if const_defined?(:NEWUSER)
|
212
|
+
list.push ["cgroup", NEWCGROUP, :cgroup ] if const_defined?(:NEWCGROUP)
|
213
|
+
list.push ["time", NEWTIME, :time ] if const_defined?(:NEWTIME)
|
214
|
+
list.each do |name, flag, key|
|
215
|
+
if (flags & flag).zero?.! && options[key]
|
216
|
+
HrrRbMount.bind "/proc/#{pid}/ns/#{name}", options[key]
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
123
221
|
def self.do_setns nstype_file_h
|
124
222
|
nstype_file_h.each do |nstype, file|
|
125
223
|
File.open(file, File::RDONLY) do |f|
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hrr_rb_lxns
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- hirura
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-04-
|
12
|
-
dependencies:
|
11
|
+
date: 2020-04-30 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: hrr_rb_mount
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.3.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.3.0
|
13
27
|
description: Utilities working with Linux namespaces for CRuby.
|
14
28
|
email:
|
15
29
|
- hirura@gmail.com
|