runshare 0.1.0

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