runshare 0.1.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 +7 -0
- data/.gitignore +21 -0
- data/.rspec +3 -0
- data/.travis.yml +7 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +38 -0
- data/LICENSE.txt +21 -0
- data/README.md +103 -0
- data/Rakefile +14 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/ext/runshare/extconf.rb +33 -0
- data/ext/runshare/include/all-io.h +115 -0
- data/ext/runshare/include/c.h +479 -0
- data/ext/runshare/include/caputils.h +34 -0
- data/ext/runshare/include/namespace.h +56 -0
- data/ext/runshare/include/pathnames.h +218 -0
- data/ext/runshare/include/pwdutils.h +14 -0
- data/ext/runshare/include/signames.h +8 -0
- data/ext/runshare/include/strutils.h +393 -0
- data/ext/runshare/runshare.c +261 -0
- data/ext/runshare/unshare.c +498 -0
- data/ext/runshare/unshare.h +82 -0
- data/lib/runshare/version.rb +3 -0
- data/lib/runshare.rb +7 -0
- data/runshare.gemspec +44 -0
- metadata +231 -0
@@ -0,0 +1,261 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
|
3
|
+
#include "unshare.h"
|
4
|
+
|
5
|
+
#include "include/c.h"
|
6
|
+
#include "include/pwdutils.h"
|
7
|
+
#include "include/strutils.h"
|
8
|
+
|
9
|
+
/* we only need some defines missing in sys/mount.h, no libmount linkage */
|
10
|
+
#include <libmount/libmount.h>
|
11
|
+
|
12
|
+
static VALUE rb_mRUnshare;
|
13
|
+
|
14
|
+
enum {
|
15
|
+
CLONE_NEWUSER,
|
16
|
+
CLONE_NEWCGROUP,
|
17
|
+
CLONE_NEWIPC,
|
18
|
+
CLONE_NEWUTS,
|
19
|
+
CLONE_NEWNET,
|
20
|
+
CLONE_NEWPID,
|
21
|
+
CLONE_NEWNS,
|
22
|
+
CLONE_NEWTIME,
|
23
|
+
FORK_ON_CLONE,
|
24
|
+
WAIT_FORK,
|
25
|
+
MOUNT_PROC,
|
26
|
+
NEW_ROOT,
|
27
|
+
NEW_DIR,
|
28
|
+
MAP_ROOT_USER,
|
29
|
+
MAP_CURRENT_USER,
|
30
|
+
MAP_USER,
|
31
|
+
MAP_GROUP,
|
32
|
+
KEEP_CAPS,
|
33
|
+
SET_UID,
|
34
|
+
SET_GID,
|
35
|
+
SET_GROUPS,
|
36
|
+
PROPAGATION,
|
37
|
+
FORCE_BOOTTIME,
|
38
|
+
FORCE_MONOTONIC,
|
39
|
+
KILL_CHILD,
|
40
|
+
// list end marker
|
41
|
+
FLAGS_COUNT
|
42
|
+
};
|
43
|
+
|
44
|
+
static ID id_clone_newuser;
|
45
|
+
static ID id_clone_newcgroup;
|
46
|
+
static ID id_clone_newipc;
|
47
|
+
static ID id_clone_newuts;
|
48
|
+
static ID id_clone_newnet;
|
49
|
+
static ID id_clone_newpid;
|
50
|
+
static ID id_clone_newns;
|
51
|
+
static ID id_clone_newtime;
|
52
|
+
static ID id_fork;
|
53
|
+
static ID id_wait;
|
54
|
+
static ID id_mount_proc;
|
55
|
+
static ID id_new_root;
|
56
|
+
static ID id_new_dir;
|
57
|
+
static ID id_map_root_user;
|
58
|
+
static ID id_map_current_user;
|
59
|
+
static ID id_map_user;
|
60
|
+
static ID id_map_group;
|
61
|
+
static ID id_keep_caps;
|
62
|
+
static ID id_set_uid;
|
63
|
+
static ID id_set_gid;
|
64
|
+
static ID id_set_groups;
|
65
|
+
static ID id_propagation;
|
66
|
+
static ID id_force_boottime;
|
67
|
+
static ID id_force_monotonic;
|
68
|
+
static ID id_kill_child;
|
69
|
+
|
70
|
+
static ID rb_unshare_keywords[FLAGS_COUNT];
|
71
|
+
|
72
|
+
static int
|
73
|
+
setgroups_str2id(const char *str) {
|
74
|
+
size_t i;
|
75
|
+
|
76
|
+
for (i = 0; i < ARRAY_SIZE(setgroups_strings); i++)
|
77
|
+
if (strcmp(str, setgroups_strings[i]) == 0)
|
78
|
+
return i;
|
79
|
+
|
80
|
+
errx(EXIT_FAILURE, _("unsupported --setgroups argument '%s'"), str);
|
81
|
+
return 0;
|
82
|
+
}
|
83
|
+
|
84
|
+
static unsigned long
|
85
|
+
parse_propagation(const char *str) {
|
86
|
+
size_t i;
|
87
|
+
static const struct prop_opts {
|
88
|
+
const char *name;
|
89
|
+
unsigned long flag;
|
90
|
+
} opts[] = {
|
91
|
+
{"slave", MS_REC | MS_SLAVE},
|
92
|
+
{"private", MS_REC | MS_PRIVATE},
|
93
|
+
{"shared", MS_REC | MS_SHARED},
|
94
|
+
{"unchanged", 0}
|
95
|
+
};
|
96
|
+
|
97
|
+
for (i = 0; i < ARRAY_SIZE(opts); i++) {
|
98
|
+
if (strcmp(opts[i].name, str) == 0)
|
99
|
+
return opts[i].flag;
|
100
|
+
}
|
101
|
+
|
102
|
+
errx(EXIT_FAILURE, _("unsupported propagation mode: %s"), str);
|
103
|
+
|
104
|
+
return 0;
|
105
|
+
}
|
106
|
+
|
107
|
+
static void
|
108
|
+
ensure_string_ne(VALUE v, const char *err) {
|
109
|
+
if (!RB_TYPE_P(v, RUBY_T_STRING) || (RSTRING_LEN(v)<1)) {
|
110
|
+
rb_raise(rb_eArgError, err);
|
111
|
+
}
|
112
|
+
}
|
113
|
+
|
114
|
+
static uid_t
|
115
|
+
get_user(const char *s, const char *err) {
|
116
|
+
struct passwd *pw;
|
117
|
+
char *buf = NULL;
|
118
|
+
uid_t ret;
|
119
|
+
|
120
|
+
pw = xgetpwnam(s, &buf);
|
121
|
+
if (pw) {
|
122
|
+
ret = pw->pw_uid;
|
123
|
+
free(pw);
|
124
|
+
free(buf);
|
125
|
+
} else {
|
126
|
+
ret = strtoul_or_err(s, err);
|
127
|
+
}
|
128
|
+
|
129
|
+
return ret;
|
130
|
+
}
|
131
|
+
|
132
|
+
static gid_t
|
133
|
+
get_group(const char *s, const char *err) {
|
134
|
+
struct group *gr;
|
135
|
+
char *buf = NULL;
|
136
|
+
gid_t ret;
|
137
|
+
|
138
|
+
gr = xgetgrnam(s, &buf);
|
139
|
+
if (gr) {
|
140
|
+
ret = gr->gr_gid;
|
141
|
+
free(gr);
|
142
|
+
free(buf);
|
143
|
+
} else {
|
144
|
+
ret = strtoul_or_err(s, err);
|
145
|
+
}
|
146
|
+
|
147
|
+
return ret;
|
148
|
+
}
|
149
|
+
|
150
|
+
static VALUE
|
151
|
+
rb_unshare(int argc, VALUE *argv, VALUE self) {
|
152
|
+
VALUE opt = Qnil;
|
153
|
+
|
154
|
+
struct rb_unshare_args args = {
|
155
|
+
.set_groups = SETGROUPS_NONE,
|
156
|
+
.map_user = -1,
|
157
|
+
.map_group = -1,
|
158
|
+
.propagation = UNSHARE_PROPAGATION_DEFAULT
|
159
|
+
};
|
160
|
+
|
161
|
+
rb_scan_args(argc, argv, "0:", &opt);
|
162
|
+
|
163
|
+
if (!NIL_P(opt)) {
|
164
|
+
VALUE kwvals[FLAGS_COUNT];
|
165
|
+
|
166
|
+
rb_get_kwargs(opt, rb_unshare_keywords, 0, FLAGS_COUNT, kwvals);
|
167
|
+
|
168
|
+
if (kwvals[CLONE_NEWUSER] != Qundef) args.clone_newuser = RTEST(kwvals[CLONE_NEWUSER]);
|
169
|
+
if (kwvals[CLONE_NEWCGROUP] != Qundef) args.clone_newcgroup = RTEST(kwvals[CLONE_NEWCGROUP]);
|
170
|
+
if (kwvals[CLONE_NEWIPC] != Qundef) args.clone_newipc = RTEST(kwvals[CLONE_NEWIPC]);
|
171
|
+
if (kwvals[CLONE_NEWUTS] != Qundef) args.clone_newuts = RTEST(kwvals[CLONE_NEWUTS]);
|
172
|
+
if (kwvals[CLONE_NEWNET] != Qundef) args.clone_newnet = RTEST(kwvals[CLONE_NEWNET]);
|
173
|
+
if (kwvals[CLONE_NEWPID] != Qundef) args.clone_newpid = RTEST(kwvals[CLONE_NEWPID]);
|
174
|
+
if (kwvals[CLONE_NEWNS] != Qundef) args.clone_newns = RTEST(kwvals[CLONE_NEWNS]);
|
175
|
+
if (kwvals[CLONE_NEWTIME] != Qundef) args.clone_newtime = RTEST(kwvals[CLONE_NEWTIME]);
|
176
|
+
if (kwvals[FORK_ON_CLONE] != Qundef) args.fork = RTEST(kwvals[FORK_ON_CLONE]);
|
177
|
+
if (kwvals[WAIT_FORK] != Qundef) args.wait = RTEST(kwvals[WAIT_FORK]);
|
178
|
+
args.mount_proc = kwvals[MOUNT_PROC];
|
179
|
+
if (args.mount_proc != Qundef) ensure_string_ne(args.mount_proc, "invalid mount type");
|
180
|
+
args.root = kwvals[NEW_ROOT];
|
181
|
+
if (args.root != Qundef) ensure_string_ne(args.root, "invalid root type");
|
182
|
+
args.new_dir = kwvals[NEW_DIR];
|
183
|
+
if (args.new_dir != Qundef) ensure_string_ne(args.new_dir, "invalid new dir type");
|
184
|
+
if (kwvals[MAP_ROOT_USER] != Qundef) args.map_root_user = RTEST(kwvals[MAP_ROOT_USER]);
|
185
|
+
if (kwvals[MAP_CURRENT_USER] != Qundef) args.map_current_user = RTEST(kwvals[MAP_CURRENT_USER]);
|
186
|
+
if (kwvals[MAP_USER] != Qundef) {
|
187
|
+
args.map_user = get_user(StringValueCStr(kwvals[MAP_USER]), _("failed to parse uid"));
|
188
|
+
}
|
189
|
+
if (kwvals[MAP_GROUP] != Qundef) {
|
190
|
+
args.map_group = get_group(StringValueCStr(kwvals[MAP_GROUP]), _("failed to parse gid"));
|
191
|
+
}
|
192
|
+
if (kwvals[KEEP_CAPS] != Qundef) args.keep_caps = RTEST(kwvals[KEEP_CAPS]);
|
193
|
+
if (kwvals[SET_UID] != Qundef) args.set_uid = NUM2UIDT(kwvals[SET_UID]);
|
194
|
+
if (kwvals[SET_GID] != Qundef) args.set_gid = NUM2GIDT(kwvals[SET_GID]);
|
195
|
+
if (kwvals[SET_GROUPS] != Qundef) args.set_groups = setgroups_str2id(StringValueCStr(kwvals[SET_GROUPS]));
|
196
|
+
if (kwvals[PROPAGATION] != Qundef) args.propagation = parse_propagation(StringValueCStr(kwvals[PROPAGATION]));
|
197
|
+
if (kwvals[FORCE_BOOTTIME] != Qundef) args.force_boottime = RTEST(kwvals[FORCE_BOOTTIME]);
|
198
|
+
if (kwvals[FORCE_MONOTONIC] != Qundef) args.force_monotonic = RTEST(kwvals[FORCE_MONOTONIC]);
|
199
|
+
if (kwvals[KILL_CHILD] != Qundef) args.kill_child = RTEST(kwvals[KILL_CHILD]);
|
200
|
+
}
|
201
|
+
|
202
|
+
return INT2FIX(rb_unshare_internal(args));
|
203
|
+
}
|
204
|
+
|
205
|
+
void
|
206
|
+
Init_runshare(void) {
|
207
|
+
rb_mRUnshare = rb_define_module("RUnshare");
|
208
|
+
rb_define_singleton_method(rb_mRUnshare, "unshare", rb_unshare, -1);
|
209
|
+
|
210
|
+
id_clone_newuser = rb_intern("clone_newuser");
|
211
|
+
id_clone_newcgroup = rb_intern("clone_newcgroup");
|
212
|
+
id_clone_newipc = rb_intern("clone_newipc");
|
213
|
+
id_clone_newuts = rb_intern("clone_newuts");
|
214
|
+
id_clone_newnet = rb_intern("clone_newnet");
|
215
|
+
id_clone_newpid = rb_intern("clone_newpid");
|
216
|
+
id_clone_newns = rb_intern("clone_newns");
|
217
|
+
id_clone_newtime = rb_intern("clone_newtime");
|
218
|
+
id_fork = rb_intern("fork");
|
219
|
+
id_wait = rb_intern("wait");
|
220
|
+
id_mount_proc = rb_intern("mount_proc");
|
221
|
+
id_new_root = rb_intern("root");
|
222
|
+
id_new_dir = rb_intern("new_dir");
|
223
|
+
id_map_root_user = rb_intern("map_root_user");
|
224
|
+
id_map_current_user = rb_intern("map_current_user");
|
225
|
+
id_map_user = rb_intern("map_user");
|
226
|
+
id_map_group = rb_intern("map_group");
|
227
|
+
id_keep_caps = rb_intern("keep_caps");
|
228
|
+
id_set_uid = rb_intern("set_uid");
|
229
|
+
id_set_gid = rb_intern("set_gid");
|
230
|
+
id_set_groups = rb_intern("set_groups");
|
231
|
+
id_propagation = rb_intern("propagation");
|
232
|
+
id_force_boottime = rb_intern("force_boottime");
|
233
|
+
id_force_monotonic = rb_intern("force_monotonic");
|
234
|
+
id_kill_child = rb_intern("kill_child");
|
235
|
+
|
236
|
+
rb_unshare_keywords[CLONE_NEWUSER] = id_clone_newuser;
|
237
|
+
rb_unshare_keywords[CLONE_NEWCGROUP] = id_clone_newcgroup;
|
238
|
+
rb_unshare_keywords[CLONE_NEWIPC] = id_clone_newipc;
|
239
|
+
rb_unshare_keywords[CLONE_NEWUTS] = id_clone_newuts;
|
240
|
+
rb_unshare_keywords[CLONE_NEWNET] = id_clone_newnet;
|
241
|
+
rb_unshare_keywords[CLONE_NEWPID] = id_clone_newpid;
|
242
|
+
rb_unshare_keywords[CLONE_NEWNS] = id_clone_newns;
|
243
|
+
rb_unshare_keywords[CLONE_NEWTIME] = id_clone_newtime;
|
244
|
+
rb_unshare_keywords[FORK_ON_CLONE] = id_fork;
|
245
|
+
rb_unshare_keywords[WAIT_FORK] = id_wait;
|
246
|
+
rb_unshare_keywords[MOUNT_PROC] = id_mount_proc;
|
247
|
+
rb_unshare_keywords[NEW_ROOT] = id_new_root;
|
248
|
+
rb_unshare_keywords[NEW_DIR] = id_new_dir;
|
249
|
+
rb_unshare_keywords[MAP_ROOT_USER] = id_map_root_user;
|
250
|
+
rb_unshare_keywords[MAP_CURRENT_USER] = id_map_current_user;
|
251
|
+
rb_unshare_keywords[MAP_USER] = id_map_user;
|
252
|
+
rb_unshare_keywords[MAP_GROUP] = id_map_group;
|
253
|
+
rb_unshare_keywords[KEEP_CAPS] = id_keep_caps;
|
254
|
+
rb_unshare_keywords[SET_UID] = id_set_uid;
|
255
|
+
rb_unshare_keywords[SET_GID] = id_set_gid;
|
256
|
+
rb_unshare_keywords[SET_GROUPS] = id_set_groups;
|
257
|
+
rb_unshare_keywords[PROPAGATION] = id_propagation;
|
258
|
+
rb_unshare_keywords[FORCE_BOOTTIME] = id_force_boottime;
|
259
|
+
rb_unshare_keywords[FORCE_MONOTONIC] = id_force_monotonic;
|
260
|
+
rb_unshare_keywords[KILL_CHILD] = id_kill_child;
|
261
|
+
}
|