runshare 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}
|