~ubuntu-branches/ubuntu/trusty/cgmanager/trusty-proposed

« back to all changes in this revision

Viewing changes to .pc/0001-add-current-fn-to-nih_error-msgs.patch/cgmanager-proxy.c

  • Committer: Package Import Robot
  • Author(s): Serge Hallyn
  • Date: 2014-03-19 00:18:56 UTC
  • Revision ID: package-import@ubuntu.com-20140319001856-16zufvvtbz7ka405
Tags: 0.20-0ubuntu5
* proxy: reconnect to cgmanager after disconnection (LP: #1294419)
* print function name in most error messages

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* cgmanager-proxy
 
2
 *
 
3
 * Copyright © 2013 Stphane Graber
 
4
 * Author: Stphane Graber <stgraber@ubuntu.com>
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License version 2, as
 
8
 * published by the Free Software Foundation.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License along
 
16
 * with this program; if not, write to the Free Software Foundation, Inc.,
 
17
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
18
 */
 
19
 
 
20
#include <frontend.h>
 
21
 
 
22
DBusConnection *server_conn;
 
23
 
 
24
bool master_running(void)
 
25
{
 
26
        NihError *err;
 
27
 
 
28
        /* is manager already running under cgmanager.lower */
 
29
        server_conn = nih_dbus_connect(CGPROXY_DBUS_PATH, NULL);
 
30
        if (server_conn) {
 
31
                dbus_connection_unref (server_conn);
 
32
                return true;
 
33
        }
 
34
        err = nih_error_get();
 
35
        nih_free(err);
 
36
 
 
37
        /* is manager running under cgmanager */
 
38
        server_conn = nih_dbus_connect(CGMANAGER_DBUS_PATH, NULL);
 
39
        if (server_conn) {
 
40
                dbus_connection_unref (server_conn);
 
41
                return true;
 
42
        }
 
43
        err = nih_error_get();
 
44
        nih_free(err);
 
45
        return false;
 
46
}
 
47
 
 
48
int setup_proxy(void)
 
49
{
 
50
        bool exists_upper = false, exists_lower = false;
 
51
        NihError *err;
 
52
 
 
53
        /*
 
54
         * If /sys/fs/cgroup/cgmanager.lower exists,
 
55
         *    if /sys/fs/cgroup/cgmanager exists, then exit (proxy already running)
 
56
         *    start up, connect to .lower
 
57
         * else
 
58
         *    if /sys/fs/cgroup/cgmanager exists, move it to /sys/fs/cgroup/cgmanager.lower
 
59
         *    start up and connect to .lower
 
60
         */
 
61
        server_conn = nih_dbus_connect(CGMANAGER_DBUS_PATH, NULL);
 
62
        if (server_conn) {
 
63
                exists_upper = true;
 
64
                dbus_connection_unref (server_conn);
 
65
        } else {
 
66
                err = nih_error_get();
 
67
                nih_free(err);
 
68
        }
 
69
        server_conn = nih_dbus_connect(CGPROXY_DBUS_PATH, NULL);
 
70
        if (server_conn) {
 
71
                exists_lower = true;
 
72
        } else {
 
73
                err = nih_error_get();
 
74
                nih_free(err);
 
75
        }
 
76
        if (exists_upper && exists_lower) {
 
77
                dbus_connection_unref (server_conn);
 
78
                nih_fatal("proxy already running");
 
79
                return -1;  // proxy already running
 
80
        }
 
81
        if (exists_lower)
 
82
                // we've got the sock we need, all set.
 
83
                return 0;
 
84
        if (exists_upper) {
 
85
                //move /sys/fs/cgroup/cgmanager to /sys/fs/cgroup/cgmanager.lower
 
86
                if (mkdir(CGPROXY_DIR, 0755) < 0 && errno != EEXIST) {
 
87
                        nih_fatal("failed to create lower sock");
 
88
                        return -1;
 
89
                }
 
90
                if (mount(CGMANAGER_DIR, CGPROXY_DIR, "none", MS_MOVE, 0) < 0) {
 
91
                        /* it wasn't a mount, meaning we are at the host
 
92
                         * level on an old kernel.  So rename it */
 
93
                        if (unlink(CGPROXY_SOCK) && errno != ENOENT)
 
94
                                nih_warn("failed to remove %s: %s", CGPROXY_SOCK,
 
95
                                        strerror(errno));
 
96
                        if (rmdir(CGPROXY_DIR) && errno != ENOENT)
 
97
                                nih_warn("failed to remove %s: %s", CGPROXY_DIR,
 
98
                                        strerror(errno));
 
99
                        if (rename(CGMANAGER_DIR, CGPROXY_DIR) < 0) {
 
100
                                nih_fatal("unable to rename the socket");
 
101
                                return -1;
 
102
                        }
 
103
                        if (mkdir(CGMANAGER_DIR, 0755) < 0) {
 
104
                                nih_fatal("unable to create socket dir");
 
105
                                return -1;
 
106
                        }
 
107
                }
 
108
        }
 
109
        server_conn = nih_dbus_connect(CGPROXY_DBUS_PATH, NULL);
 
110
        if (!server_conn) {
 
111
                err = nih_error_get();
 
112
                nih_fatal("Failed to open connection to %s: %s",
 
113
                                CGPROXY_DBUS_PATH, err->message);
 
114
                nih_free(err);
 
115
        }
 
116
        return 0;
 
117
}
 
118
 
 
119
static int checkmaster = FALSE;
 
120
 
 
121
bool send_dummy_msg(DBusConnection *conn)
 
122
{
 
123
        DBusMessage *message = NULL;
 
124
        DBusMessageIter iter;
 
125
        int a;
 
126
        message = dbus_message_new_method_call(dbus_bus_get_unique_name(conn),
 
127
                        "/org/linuxcontainers/cgmanager",
 
128
                        "org.linuxcontainers.cgmanager0_0", "Ping");
 
129
        dbus_message_set_no_reply(message, TRUE);
 
130
        dbus_message_iter_init_append(message, &iter);
 
131
        if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &a)) {
 
132
                nih_error("%s: out of memory", __func__);
 
133
                return false;
 
134
        }
 
135
        dbus_connection_send(conn, message, NULL);
 
136
        dbus_connection_flush(conn);
 
137
        dbus_message_unref(message);
 
138
        return true;
 
139
}
 
140
 
 
141
static DBusMessage *start_dbus_request(const char *method, int *sv)
 
142
{
 
143
        int optval = 1;
 
144
 
 
145
        if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sv) < 0) {
 
146
                nih_error("%s: Error creating socketpair: %s",
 
147
                        __func__, strerror(errno));
 
148
                return NULL;
 
149
        }
 
150
        if (setsockopt(sv[1], SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)) == -1) {
 
151
                nih_error("%s: setsockopt: %s", __func__, strerror(errno));
 
152
                goto err;
 
153
        }
 
154
        if (setsockopt(sv[0], SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)) == -1) {
 
155
                nih_error("%s: setsockopt: %s", __func__, strerror(errno));
 
156
                goto err;
 
157
        }
 
158
 
 
159
        return dbus_message_new_method_call(dbus_bus_get_unique_name(server_conn),
 
160
                        "/org/linuxcontainers/cgmanager",
 
161
                        "org.linuxcontainers.cgmanager0_0", method);
 
162
err:
 
163
        close(sv[0]);
 
164
        close(sv[1]);
 
165
        return NULL;
 
166
}
 
167
 
 
168
static bool complete_dbus_request(DBusMessage *message,
 
169
                int *sv, struct ucred *rcred, struct ucred *vcred)
 
170
{
 
171
        char buf[1];
 
172
 
 
173
        if (!dbus_connection_send(server_conn, message, NULL)) {
 
174
                nih_error("%s: failed to send dbus message", __func__);
 
175
                dbus_message_unref(message);
 
176
                return false;
 
177
        }
 
178
        dbus_connection_flush(server_conn);
 
179
        dbus_message_unref(message);
 
180
 
 
181
        if (recv(sv[0], buf, 1, 0) != 1) {
 
182
                nih_error("%s: Error getting reply from server over socketpair",
 
183
                          __func__);
 
184
                return false;
 
185
        }
 
186
        if (send_creds(sv[0], rcred)) {
 
187
                nih_error("%s: Error sending pid over SCM_CREDENTIAL",
 
188
                        __func__);
 
189
                return false;
 
190
        }
 
191
 
 
192
        if (!vcred) // this request only requires one scm_credential
 
193
                return true;
 
194
 
 
195
        if (recv(sv[0], buf, 1, 0) != 1) {
 
196
                nih_error("%s: Error getting reply from server over socketpair",
 
197
                        __func__);
 
198
                return false;
 
199
        }
 
200
        if (send_creds(sv[0], vcred)) {
 
201
                nih_error("%s: Error sending pid over SCM_CREDENTIAL",
 
202
                        __func__);
 
203
                return false;
 
204
        }
 
205
 
 
206
        return true;
 
207
}
 
208
 
 
209
int get_pid_cgroup_main (void *parent, const char *controller,
 
210
                struct ucred p, struct ucred r, struct ucred v, char **output)
 
211
{
 
212
        DBusMessage *message;
 
213
        DBusMessageIter iter;
 
214
        int sv[2], ret = -1;
 
215
        char s[MAXPATHLEN] = { 0 };
 
216
 
 
217
        if (memcmp(&p, &r, sizeof(struct ucred)) != 0) {
 
218
                nih_error("%s: proxy != requestor", __func__);
 
219
                return -1;
 
220
        }
 
221
 
 
222
        if (!(message = start_dbus_request("GetPidCgroupScm", sv))) {
 
223
                nih_error("%s: error starting dbus request", __func__);
 
224
                return -1;
 
225
        }
 
226
 
 
227
        dbus_message_iter_init_append(message, &iter);
 
228
        if (!dbus_message_iter_append_basic (&iter,
 
229
                        DBUS_TYPE_STRING,
 
230
                        &controller)) {
 
231
                nih_error("%s: out of memory", __func__);
 
232
                goto out;
 
233
        }
 
234
        if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_UNIX_FD, &sv[1])) {
 
235
                nih_error("%s: out of memory", __func__);
 
236
                goto out;
 
237
        }
 
238
 
 
239
        if (!complete_dbus_request(message, sv, &r, &v)) {
 
240
                nih_error("%s: error completing dbus request", __func__);
 
241
                goto out;
 
242
        }
 
243
 
 
244
        // TODO - switch to nih_io_message_recv?
 
245
        if (recv(sv[0], s, MAXPATHLEN-1, 0) <= 0)
 
246
                nih_error("%s: Error reading result from cgmanager",
 
247
                        __func__);
 
248
        else {
 
249
                *output = NIH_MUST( nih_strdup(parent, s) );
 
250
                ret = 0;
 
251
        }
 
252
out:
 
253
        close(sv[0]);
 
254
        close(sv[1]);
 
255
        return ret;
 
256
}
 
257
 
 
258
int do_move_pid_main (const char *controller, const char *cgroup,
 
259
                struct ucred p, struct ucred r, struct ucred v,
 
260
                const char *cmd)
 
261
{
 
262
        DBusMessage *message;
 
263
        DBusMessageIter iter;
 
264
        int sv[2], ret = -1;
 
265
        char buf[1];
 
266
 
 
267
        if (memcmp(&p, &r, sizeof(struct ucred)) != 0) {
 
268
                nih_error("%s: proxy != requestor", __func__);
 
269
                return -1;
 
270
        }
 
271
 
 
272
        if (!sane_cgroup(cgroup)) {
 
273
                nih_error("unsafe cgroup");
 
274
                return -1;
 
275
        }
 
276
 
 
277
        if (!(message = start_dbus_request(cmd, sv))) {
 
278
                nih_error("%s: error starting dbus request", __func__);
 
279
                return -1;
 
280
        }
 
281
 
 
282
        dbus_message_iter_init_append(message, &iter);
 
283
        if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
 
284
                                &controller)) {
 
285
                nih_error("%s: out of memory", __func__);
 
286
                goto out;
 
287
        }
 
288
        if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &cgroup)) {
 
289
                nih_error("%s: out of memory", __func__);
 
290
                goto out;
 
291
        }
 
292
        if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_UNIX_FD, &sv[1])) {
 
293
                nih_error("%s: out of memory", __func__);
 
294
                goto out;
 
295
        }
 
296
 
 
297
        if (!complete_dbus_request(message, sv, &r, &v)) {
 
298
                nih_error("%s: error completing dbus request", __func__);
 
299
                goto out;
 
300
        }
 
301
 
 
302
        if (recv(sv[0], buf, 1, 0) == 1 && *buf == '1')
 
303
                ret = 0;
 
304
out:
 
305
        close(sv[0]);
 
306
        close(sv[1]);
 
307
        return ret;
 
308
}
 
309
 
 
310
int move_pid_main (const char *controller, const char *cgroup,
 
311
                struct ucred p, struct ucred r, struct ucred v)
 
312
{
 
313
        if (!sane_cgroup(cgroup)) {
 
314
                nih_error("unsafe cgroup");
 
315
                return -1;
 
316
        }
 
317
        if (cgroup[0] == '/') {
 
318
                nih_error("uid %u tried to escape its cgroup", r.uid);
 
319
                return -1;
 
320
        }
 
321
 
 
322
        return do_move_pid_main(controller, cgroup, p, r, v, "MovePidScm");
 
323
}
 
324
 
 
325
int move_pid_abs_main (const char *controller, const char *cgroup,
 
326
                struct ucred p, struct ucred r, struct ucred v)
 
327
{
 
328
        if (r.uid) {
 
329
                nih_error("uid %u tried to escape", r.uid);
 
330
                return -1;
 
331
        }
 
332
        if (!sane_cgroup(cgroup)) {
 
333
                nih_error("unsafe cgroup");
 
334
                return -1;
 
335
        }
 
336
        return do_move_pid_main(controller, cgroup, p, r, v, "MovePidAbsScm");
 
337
}
 
338
 
 
339
int create_main (const char *controller, const char *cgroup, struct ucred p,
 
340
                struct ucred r, int32_t *existed)
 
341
{
 
342
        DBusMessage *message;
 
343
        DBusMessageIter iter;
 
344
        int sv[2], ret = -1;
 
345
        char buf[1];
 
346
 
 
347
        if (memcmp(&p, &r, sizeof(struct ucred)) != 0) {
 
348
                nih_error("%s: proxy != requestor", __func__);
 
349
                return -1;
 
350
        }
 
351
 
 
352
        if (!sane_cgroup(cgroup)) {
 
353
                nih_error("unsafe cgroup");
 
354
                return -1;
 
355
        }
 
356
 
 
357
        if (!(message = start_dbus_request("CreateScm", sv))) {
 
358
                nih_error("%s: error starting dbus request", __func__);
 
359
                return -1;
 
360
        }
 
361
 
 
362
        dbus_message_iter_init_append(message, &iter);
 
363
        if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &controller)) {
 
364
                nih_error("%s: out of memory", __func__);
 
365
                goto out;
 
366
        }
 
367
        if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &cgroup)) {
 
368
                nih_error("%s: out of memory", __func__);
 
369
                goto out;
 
370
        }
 
371
        if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_UNIX_FD, &sv[1])) {
 
372
                nih_error("%s: out of memory", __func__);
 
373
                goto out;
 
374
        }
 
375
 
 
376
        if (!complete_dbus_request(message, sv, &r, NULL)) {
 
377
                nih_error("%s: error completing dbus request", __func__);
 
378
                goto out;
 
379
        }
 
380
 
 
381
        if (recv(sv[0], buf, 1, 0) == 1 && (*buf == '1' || *buf == '2'))
 
382
                ret = 0;
 
383
        *existed = *buf == '2' ? 1 : -1;
 
384
out:
 
385
        close(sv[0]);
 
386
        close(sv[1]);
 
387
        return ret;
 
388
}
 
389
 
 
390
int chown_main (const char *controller, const char *cgroup,
 
391
                struct ucred p, struct ucred r, struct ucred v)
 
392
{
 
393
        DBusMessage *message;
 
394
        DBusMessageIter iter;
 
395
        int sv[2], ret = -1;
 
396
        char buf[1];
 
397
 
 
398
        if (memcmp(&p, &r, sizeof(struct ucred)) != 0) {
 
399
                nih_error("%s: proxy != requestor", __func__);
 
400
                return -1;
 
401
        }
 
402
 
 
403
        if (!sane_cgroup(cgroup)) {
 
404
                nih_error("unsafe cgroup");
 
405
                return -1;
 
406
        }
 
407
 
 
408
        if (!(message = start_dbus_request("ChownScm", sv))) {
 
409
                nih_error("%s: error starting dbus request", __func__);
 
410
                return -1;
 
411
        }
 
412
 
 
413
        dbus_message_iter_init_append(message, &iter);
 
414
        if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &controller)) {
 
415
                nih_error("%s: out of memory", __func__);
 
416
                goto out;
 
417
        }
 
418
        if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &cgroup)) {
 
419
                nih_error("%s: out of memory", __func__);
 
420
                goto out;
 
421
        }
 
422
        if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_UNIX_FD, &sv[1])) {
 
423
                nih_error("%s: out of memory", __func__);
 
424
                goto out;
 
425
        }
 
426
 
 
427
        if (!complete_dbus_request(message, sv, &r, &v)) {
 
428
                nih_error("%s: error completing dbus request", __func__);
 
429
                goto out;
 
430
        }
 
431
 
 
432
        if (recv(sv[0], buf, 1, 0) == 1 && *buf == '1')
 
433
                ret = 0;
 
434
out:
 
435
        close(sv[0]);
 
436
        close(sv[1]);
 
437
        return ret;
 
438
}
 
439
 
 
440
int chmod_main (const char *controller, const char *cgroup, const char *file,
 
441
                struct ucred p, struct ucred r, int mode)
 
442
{
 
443
        DBusMessage *message;
 
444
        DBusMessageIter iter;
 
445
        int sv[2], ret = -1;
 
446
        char buf[1];
 
447
 
 
448
        if (memcmp(&p, &r, sizeof(struct ucred)) != 0) {
 
449
                nih_error("%s: proxy != requestor", __func__);
 
450
                return -1;
 
451
        }
 
452
 
 
453
        if (!sane_cgroup(cgroup)) {
 
454
                nih_error("unsafe cgroup");
 
455
                return -1;
 
456
        }
 
457
 
 
458
        if (!(message = start_dbus_request("ChmodScm", sv))) {
 
459
                nih_error("%s: error starting dbus request", __func__);
 
460
                return -1;
 
461
        }
 
462
 
 
463
        dbus_message_iter_init_append(message, &iter);
 
464
        if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &controller)) {
 
465
                nih_error("%s: out of memory", __func__);
 
466
                goto out;
 
467
        }
 
468
        if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &cgroup)) {
 
469
                nih_error("%s: out of memory", __func__);
 
470
                goto out;
 
471
        }
 
472
        if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &file)) {
 
473
                nih_error("%s: out of memory", __func__);
 
474
                goto out;
 
475
        }
 
476
        if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &mode)) {
 
477
                nih_error("%s: out of memory", __func__);
 
478
                goto out;
 
479
        }
 
480
        if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_UNIX_FD, &sv[1])) {
 
481
                nih_error("%s: out of memory", __func__);
 
482
                goto out;
 
483
        }
 
484
 
 
485
        if (!complete_dbus_request(message, sv, &r, NULL)) {
 
486
                nih_error("%s: error completing dbus request", __func__);
 
487
                goto out;
 
488
        }
 
489
 
 
490
        if (recv(sv[0], buf, 1, 0) == 1 && *buf == '1')
 
491
                ret = 0;
 
492
out:
 
493
        close(sv[0]);
 
494
        close(sv[1]);
 
495
        return ret;
 
496
}
 
497
 
 
498
int get_value_main (void *parent, const char *controller, const char *cgroup,
 
499
                 const char *key, struct ucred p, struct ucred r, char **value)
 
500
{
 
501
        DBusMessage *message;
 
502
        DBusMessageIter iter;
 
503
        int sv[2], ret = -1;
 
504
        char output[MAXPATHLEN] = { 0 };
 
505
 
 
506
        if (memcmp(&p, &r, sizeof(struct ucred)) != 0) {
 
507
                nih_error("%s: proxy != requestor", __func__);
 
508
                return -1;
 
509
        }
 
510
 
 
511
        if (!sane_cgroup(cgroup)) {
 
512
                nih_error("unsafe cgroup");
 
513
                return -1;
 
514
        }
 
515
 
 
516
        if (!(message = start_dbus_request("GetValueScm", sv))) {
 
517
                nih_error("%s: error starting dbus request", __func__);
 
518
                return -1;
 
519
        }
 
520
 
 
521
        dbus_message_iter_init_append(message, &iter);
 
522
        if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &controller)) {
 
523
                nih_error("%s: out of memory", __func__);
 
524
                goto out;
 
525
        }
 
526
        if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &cgroup)) {
 
527
                nih_error("%s: out of memory", __func__);
 
528
                goto out;
 
529
        }
 
530
        if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key)) {
 
531
                nih_error("%s: out of memory", __func__);
 
532
                goto out;
 
533
        }
 
534
        if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_UNIX_FD, &sv[1])) {
 
535
                nih_error("%s: out of memory", __func__);
 
536
                goto out;
 
537
        }
 
538
 
 
539
        if (!complete_dbus_request(message, sv, &r, NULL)) {
 
540
                nih_error("%s: error completing dbus request", __func__);
 
541
                goto out;
 
542
        }
 
543
 
 
544
        if (recv(sv[0], output, MAXPATHLEN, 0) <= 0) {
 
545
                nih_error("%s: Failed reading string from cgmanager: %s",
 
546
                        __func__, strerror(errno));
 
547
        } else {
 
548
                *value = NIH_MUST( nih_strdup(parent, output) );
 
549
                ret = 0;
 
550
        }
 
551
out:
 
552
        close(sv[0]);
 
553
        close(sv[1]);
 
554
        return ret;
 
555
}
 
556
 
 
557
int set_value_main (const char *controller, const char *cgroup,
 
558
                 const char *key, const char *value, struct ucred p,
 
559
                 struct ucred r)
 
560
{
 
561
        DBusMessage *message;
 
562
        DBusMessageIter iter;
 
563
        int sv[2], ret = -1;
 
564
        char buf[1];
 
565
 
 
566
        if (memcmp(&p, &r, sizeof(struct ucred)) != 0) {
 
567
                nih_error("%s: proxy != requestor", __func__);
 
568
                return -1;
 
569
        }
 
570
 
 
571
        if (!sane_cgroup(cgroup)) {
 
572
                nih_error("unsafe cgroup");
 
573
                return -1;
 
574
        }
 
575
 
 
576
        if (!(message = start_dbus_request("SetValueScm", sv))) {
 
577
                nih_error("%s: error starting dbus request", __func__);
 
578
                return -1;
 
579
        }
 
580
 
 
581
        dbus_message_iter_init_append(message, &iter);
 
582
        if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &controller)) {
 
583
                nih_error("%s: out of memory", __func__);
 
584
                goto out;
 
585
        }
 
586
        if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &cgroup)) {
 
587
                nih_error("%s: out of memory", __func__);
 
588
                goto out;
 
589
        }
 
590
        if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key)) {
 
591
                nih_error("%s: out of memory", __func__);
 
592
                goto out;
 
593
        }
 
594
        if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value)) {
 
595
                nih_error("%s: out of memory", __func__);
 
596
                goto out;
 
597
        }
 
598
        if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_UNIX_FD, &sv[1])) {
 
599
                nih_error("%s: out of memory", __func__);
 
600
                goto out;
 
601
        }
 
602
 
 
603
        if (!complete_dbus_request(message, sv, &r, NULL)) {
 
604
                nih_error("%s: error completing dbus request", __func__);
 
605
                goto out;
 
606
        }
 
607
 
 
608
        if (recv(sv[0], buf, 1, 0) == 1 && *buf == '1')
 
609
                ret = 0;
 
610
out:
 
611
        close(sv[0]);
 
612
        close(sv[1]);
 
613
        return ret;
 
614
}
 
615
 
 
616
int remove_main (const char *controller, const char *cgroup, struct ucred p,
 
617
                struct ucred r, int recursive, int32_t *existed)
 
618
{
 
619
        DBusMessage *message;
 
620
        DBusMessageIter iter;
 
621
        int sv[2], ret = -1;
 
622
        char buf[1];
 
623
 
 
624
        if (memcmp(&p, &r, sizeof(struct ucred)) != 0) {
 
625
                nih_error("%s: proxy != requestor", __func__);
 
626
                return -1;
 
627
        }
 
628
 
 
629
        if (!sane_cgroup(cgroup)) {
 
630
                nih_error("unsafe cgroup");
 
631
                return -1;
 
632
        }
 
633
 
 
634
        if (!(message = start_dbus_request("RemoveScm", sv))) {
 
635
                nih_error("%s: error starting dbus request", __func__);
 
636
                return -1;
 
637
        }
 
638
 
 
639
        dbus_message_iter_init_append(message, &iter);
 
640
        if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &controller)) {
 
641
                nih_error("%s: out of memory", __func__);
 
642
                goto out;
 
643
        }
 
644
        if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &cgroup)) {
 
645
                nih_error("%s: out of memory", __func__);
 
646
                goto out;
 
647
        }
 
648
        if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &recursive)) {
 
649
                nih_error("%s: out of memory", __func__);
 
650
                goto out;
 
651
        }
 
652
        if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_UNIX_FD, &sv[1])) {
 
653
                nih_error("%s: out of memory", __func__);
 
654
                goto out;
 
655
        }
 
656
 
 
657
        if (!complete_dbus_request(message, sv, &r, NULL)) {
 
658
                nih_error("%s: error completing dbus request", __func__);
 
659
                goto out;
 
660
        }
 
661
 
 
662
        if (recv(sv[0], buf, 1, 0) == 1 && (*buf == '1' || *buf == '2'))
 
663
                ret = 0;
 
664
        *existed = *buf == '2' ? 1 : -1;
 
665
out:
 
666
        close(sv[0]);
 
667
        close(sv[1]);
 
668
        return ret;
 
669
}
 
670
 
 
671
int get_tasks_main (void *parent, const char *controller, const char *cgroup,
 
672
                    struct ucred p, struct ucred r, int32_t **pids)
 
673
{
 
674
        DBusMessage *message;
 
675
        DBusMessageIter iter;
 
676
        int sv[2], ret = -1;
 
677
        uint32_t nrpids;
 
678
        struct ucred tcred;
 
679
        int i;
 
680
 
 
681
        if (memcmp(&p, &r, sizeof(struct ucred)) != 0) {
 
682
                nih_error("%s: proxy != requestor", __func__);
 
683
                return -1;
 
684
        }
 
685
 
 
686
        if (!sane_cgroup(cgroup)) {
 
687
                nih_error("unsafe cgroup");
 
688
                return -1;
 
689
        }
 
690
 
 
691
        if (!(message = start_dbus_request("GetTasksScm", sv))) {
 
692
                nih_error("%s: error starting dbus request", __func__);
 
693
                return -1;
 
694
        }
 
695
 
 
696
        dbus_message_iter_init_append(message, &iter);
 
697
        if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &controller)) {
 
698
                nih_error("%s: out of memory", __func__);
 
699
                goto out;
 
700
        }
 
701
        if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &cgroup)) {
 
702
                nih_error("%s: out of memory", __func__);
 
703
                goto out;
 
704
        }
 
705
        if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_UNIX_FD, &sv[1])) {
 
706
                nih_error("%s: out of memory", __func__);
 
707
                goto out;
 
708
        }
 
709
 
 
710
        if (!complete_dbus_request(message, sv, &r, NULL)) {
 
711
                nih_error("%s: error completing dbus request", __func__);
 
712
                goto out;
 
713
        }
 
714
        if (recv(sv[0], &nrpids, sizeof(uint32_t), 0) != sizeof(uint32_t))
 
715
                goto out;
 
716
        if (nrpids == 0) {
 
717
                ret = 0;
 
718
                goto out;
 
719
        }
 
720
 
 
721
        *pids = NIH_MUST( nih_alloc(parent, nrpids * sizeof(uint32_t)) );
 
722
        for (i=0; i<nrpids; i++) {
 
723
                get_scm_creds_sync(sv[0], &tcred);
 
724
                if (tcred.pid == -1) {
 
725
                        nih_error("%s: Failed getting pid from server",
 
726
                                __func__);
 
727
                        goto out;
 
728
                }
 
729
                (*pids)[i] = tcred.pid;
 
730
        }
 
731
        ret = nrpids;
 
732
out:
 
733
        close(sv[0]);
 
734
        close(sv[1]);
 
735
        return ret;
 
736
}
 
737
 
 
738
int list_children_main (void *parent, const char *controller, const char *cgroup,
 
739
                    struct ucred p, struct ucred r, char ***output)
 
740
{
 
741
        DBusMessage *message;
 
742
        DBusMessageIter iter;
 
743
        int sv[2], ret = -1;
 
744
        uint32_t len;
 
745
        int32_t nrkids;
 
746
        nih_local char * paths = NULL;
 
747
        char *s;
 
748
        int i;
 
749
 
 
750
        *output = NULL;
 
751
        if (memcmp(&p, &r, sizeof(struct ucred)) != 0) {
 
752
                nih_error("%s: proxy != requestor", __func__);
 
753
                return -1;
 
754
        }
 
755
 
 
756
        if (!sane_cgroup(cgroup)) {
 
757
                nih_error("unsafe cgroup");
 
758
                return -1;
 
759
        }
 
760
 
 
761
        if (!(message = start_dbus_request("ListChildrenScm", sv))) {
 
762
                nih_error("%s: error starting dbus request", __func__);
 
763
                return -1;
 
764
        }
 
765
 
 
766
        dbus_message_iter_init_append(message, &iter);
 
767
        if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &controller)) {
 
768
                nih_error("%s: out of memory", __func__);
 
769
                goto out;
 
770
        }
 
771
        if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &cgroup)) {
 
772
                nih_error("%s: out of memory", __func__);
 
773
                goto out;
 
774
        }
 
775
        if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_UNIX_FD, &sv[1])) {
 
776
                nih_error("%s: out of memory", __func__);
 
777
                goto out;
 
778
        }
 
779
 
 
780
        if (!complete_dbus_request(message, sv, &r, NULL)) {
 
781
                nih_error("%s: error completing dbus request", __func__);
 
782
                goto out;
 
783
        }
 
784
 
 
785
        if (recv(sv[0], &nrkids, sizeof(int32_t), 0) != sizeof(int32_t))
 
786
                goto out;
 
787
        if (nrkids == 0) {
 
788
                ret = 0;
 
789
                goto out;
 
790
        }
 
791
        if (nrkids < 0) {
 
792
                nih_error("Server encountered an error: bad cgroup?");
 
793
                ret = -1;
 
794
                goto out;
 
795
        }
 
796
        if (recv(sv[0], &len, sizeof(uint32_t), 0) != sizeof(uint32_t))
 
797
                goto out;
 
798
 
 
799
        paths = nih_alloc(NULL, len);
 
800
        if (read(sv[0], paths, len) != len) {
 
801
                nih_error("%s: Failed getting paths from server", __func__);
 
802
                goto out;
 
803
        }
 
804
 
 
805
        *output = NIH_MUST( nih_alloc(parent, sizeof( char*)*(nrkids+1)) );
 
806
 
 
807
        s = paths;
 
808
        (*output)[nrkids] = NULL;
 
809
        for (i=0; i<nrkids; i++) {
 
810
                (*output)[i] = NIH_MUST( nih_strdup(parent, s) );
 
811
                s += strlen(s) + 1;
 
812
        }
 
813
        ret = nrkids;
 
814
out:
 
815
        close(sv[0]);
 
816
        close(sv[1]);
 
817
        return ret;
 
818
}
 
819
 
 
820
/**
 
821
 * options:
 
822
 *
 
823
 * Command-line options accepted by this program.
 
824
 **/
 
825
static NihOption options[] = {
 
826
        { 0, "daemon", N_("Detach and run in the background"),
 
827
          NULL, NULL, &daemonise, NULL },
 
828
        { 0, "check-master", N_("Check whether cgmanager is running"),
 
829
          NULL, NULL, &checkmaster, NULL },
 
830
 
 
831
        NIH_OPTION_LAST
 
832
};
 
833
 
 
834
int
 
835
main (int argc, char *argv[])
 
836
{
 
837
        char **         args;
 
838
        int             ret;
 
839
        DBusServer *    server;
 
840
        struct stat sb;
 
841
 
 
842
        nih_main_init (argv[0]);
 
843
 
 
844
        nih_option_set_synopsis (_("Control group proxy"));
 
845
        nih_option_set_help (_("The cgroup manager proxy"));
 
846
 
 
847
        args = nih_option_parser (NULL, argc, argv, options, FALSE);
 
848
        if (! args)
 
849
                exit (1);
 
850
 
 
851
        if (geteuid() != 0) {
 
852
                nih_error(_("Cgmanager proxy must be run as root"));
 
853
                exit(1);
 
854
        }
 
855
 
 
856
        /*
 
857
         * If we are called with checkmaster, then only check whether
 
858
         * cgmanager is running.  This is used by the init script to
 
859
         * determine whether to run cgmanager or cgproxy
 
860
         */
 
861
        if (checkmaster) {
 
862
                if (master_running())
 
863
                        exit(0);
 
864
                exit(1);
 
865
        }
 
866
        if (setup_proxy() < 0) {
 
867
                nih_fatal ("Failed to set up as proxy");
 
868
                exit(1);
 
869
        }
 
870
 
 
871
        /* Setup the DBus server */
 
872
        server = nih_dbus_server ( CGMANAGER_DBUS_PATH, client_connect,
 
873
                        client_disconnect);
 
874
        nih_assert (server != NULL);
 
875
 
 
876
        if (stat("/proc/self/ns/pid", &sb) == 0) {
 
877
                mypidns = read_pid_ns_link(getpid());
 
878
                setns_pid_supported = true;
 
879
        }
 
880
 
 
881
        if (stat("/proc/self/ns/user", &sb) == 0) {
 
882
                myuserns = read_user_ns_link(getpid());
 
883
                setns_user_supported = true;
 
884
        }
 
885
 
 
886
        /* Become daemon */
 
887
        if (daemonise) {
 
888
                if (nih_main_daemonise () < 0) {
 
889
                        NihError *err;
 
890
 
 
891
                        err = nih_error_get ();
 
892
                        nih_fatal ("%s: %s", _("Unable to become daemon"),
 
893
                                   err->message);
 
894
                        nih_free (err);
 
895
 
 
896
                        exit (1);
 
897
                }
 
898
        }
 
899
 
 
900
        /*
 
901
         * We have to send a message to force fd passing over the dbus
 
902
         * link to be negotiated.  Else when we try to attach an fd we'll
 
903
         * fail.
 
904
         */
 
905
        if (!send_dummy_msg(server_conn)) {
 
906
                nih_fatal("Failed to send opening ping to cgmanager");
 
907
                exit(1);
 
908
        }
 
909
 
 
910
        ret = nih_main_loop ();
 
911
 
 
912
        /* Destroy any PID file we may have created */
 
913
        if (daemonise) {
 
914
                nih_main_unlink_pidfile();
 
915
        }
 
916
 
 
917
        return ret;
 
918
}