~jamesodhunt/ubuntu/vivid/upstart/bug-1447756

« back to all changes in this revision

Viewing changes to init/control.c

  • Committer: Dimitri John Ledkov
  • Date: 2014-07-14 12:48:09 UTC
  • mfrom: (1436.2.6)
  • Revision ID: dimitri.ledkov@canonical.com-20140714124809-qgpmf0cj37x2b2we
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
63
63
 
64
64
#include "com.ubuntu.Upstart.h"
65
65
 
 
66
#ifdef ENABLE_CGROUPS
 
67
#include "cgroup.h"
 
68
#endif /* ENABLE_CGROUPS */
 
69
 
66
70
/* Prototypes for static functions */
67
71
static int   control_server_connect      (DBusServer *server, DBusConnection *conn);
68
72
static void  control_disconnected        (DBusConnection *conn);
975
979
}
976
980
 
977
981
/**
 
982
 * control_notify_cgroup_manager_address:
 
983
 * @data: not used,
 
984
 * @message: D-Bus connection and message received,
 
985
 * @address: D-Bus address that cgroup manager is connected to.
 
986
 *
 
987
 * Implements the NotifyCGroupManagerAddress method of the
 
988
 * com.ubuntu.Upstart interface.
 
989
 *
 
990
 * Called to allow the cgroup manager to be contacted,
 
991
 * thus enabling the cgroup stanza.
 
992
 *
 
993
 * Returns: zero on success, negative value on raised error.
 
994
 **/
 
995
int
 
996
control_notify_cgroup_manager_address (void            *data,
 
997
                                       NihDBusMessage  *message,
 
998
                                       const char      *address)
 
999
{
 
1000
        nih_assert (message);
 
1001
        nih_assert (address);
 
1002
 
 
1003
        if (! control_check_permission (message)) {
 
1004
                nih_dbus_error_raise_printf (
 
1005
                        DBUS_INTERFACE_UPSTART ".Error.PermissionDenied",
 
1006
                        _("You do not have permission to notify cgroup manager address"));
 
1007
                return -1;
 
1008
        }
 
1009
 
 
1010
#ifdef ENABLE_CGROUPS
 
1011
        if (! cgroup_support_enabled ())
 
1012
                return 0;
 
1013
 
 
1014
        /* Already called */
 
1015
        if (cgroup_manager_available ())
 
1016
                return 0;
 
1017
 
 
1018
        if (! cgroup_manager_set_address (address)) {
 
1019
                nih_dbus_error_raise_printf (DBUS_ERROR_NO_MEMORY,
 
1020
                                _("Out of Memory"));
 
1021
                return -1;
 
1022
        }
 
1023
 
 
1024
        nih_debug ("set cgroup manager address");
 
1025
 
 
1026
        if (! job_class_induct_jobs ()) {
 
1027
                nih_dbus_error_raise_printf (DBUS_ERROR_NO_MEMORY,
 
1028
                                _("Out of Memory"));
 
1029
                return -1;
 
1030
        }
 
1031
 
 
1032
#else
 
1033
        nih_debug ("cgroup support not available");
 
1034
#endif /* ENABLE_CGROUPS */
 
1035
 
 
1036
        return 0;
 
1037
}
 
1038
 
 
1039
/**
978
1040
 * control_bus_flush:
979
1041
 *
980
1042
 * Drain any remaining messages in the D-Bus queue.
1253
1315
}
1254
1316
 
1255
1317
/**
 
1318
 * control_set_env_list:
 
1319
 *
 
1320
 * @data: not used,
 
1321
 * @message: D-Bus connection and message received,
 
1322
 * @job_details: name and instance of job to apply operation to,
 
1323
 * @vars: array of name[/value] pairs of environment variables to set,
 
1324
 * @replace: TRUE if @name should be overwritten if already set, else
 
1325
 *  FALSE.
 
1326
 *
 
1327
 * Implements the SetEnvList method of the com.ubuntu.Upstart
 
1328
 * interface.
 
1329
 *
 
1330
 * Called to request Upstart store one or more name/value pairs.
 
1331
 *
 
1332
 * If @job_details is empty, change will be applied to all job
 
1333
 * environments, else only apply changes to specific job environment
 
1334
 * encoded within @job_details.
 
1335
 *
 
1336
 * Returns: zero on success, negative value on raised error.
 
1337
 **/
 
1338
int
 
1339
control_set_env_list (void            *data,
 
1340
                      NihDBusMessage  *message,
 
1341
                      char * const    *job_details,
 
1342
                      char * const    *vars,
 
1343
                      int              replace)
 
1344
{
 
1345
        Session         *session;
 
1346
        Job             *job = NULL;
 
1347
        char            *job_name = NULL;
 
1348
        char            *instance = NULL;
 
1349
        char * const    *var;
 
1350
 
 
1351
        nih_assert (message);
 
1352
        nih_assert (job_details);
 
1353
        nih_assert (vars);
 
1354
 
 
1355
        if (! control_check_permission (message)) {
 
1356
                nih_dbus_error_raise_printf (
 
1357
                        DBUS_INTERFACE_UPSTART ".Error.PermissionDenied",
 
1358
                        _("You do not have permission to modify job environment"));
 
1359
                return -1;
 
1360
        }
 
1361
 
 
1362
        if (job_details[0]) {
 
1363
                job_name = job_details[0];
 
1364
 
 
1365
                /* this can be a null value */
 
1366
                instance = job_details[1];
 
1367
        } else if (getpid () == 1) {
 
1368
                nih_dbus_error_raise_printf (
 
1369
                        DBUS_INTERFACE_UPSTART ".Error.PermissionDenied",
 
1370
                        _("Not permissible to modify PID 1 job environment"));
 
1371
                return -1;
 
1372
        }
 
1373
 
 
1374
        /* Verify that job name is valid */
 
1375
        if (job_name && ! strlen (job_name)) {
 
1376
                nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
 
1377
                                             _("Job may not be empty string"));
 
1378
                return -1;
 
1379
        }
 
1380
 
 
1381
        /* Get the relevant session */
 
1382
        session = session_from_dbus (NULL, message);
 
1383
 
 
1384
        /* Chroot sessions must not be able to influence
 
1385
         * the outside system.
 
1386
         */
 
1387
        if (session && session->chroot) {
 
1388
                nih_warn (_("Ignoring set env request from chroot session"));
 
1389
                return 0;
 
1390
        }
 
1391
 
 
1392
        /* Lookup the job */
 
1393
        control_get_job (session, job, job_name, instance);
 
1394
 
 
1395
        for (var = vars; var && *var; var++) {
 
1396
                nih_local char *envvar = NULL;
 
1397
 
 
1398
                if (! *var) {
 
1399
                        nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
 
1400
                                        _("Variable may not be empty string"));
 
1401
                        return -1;
 
1402
                }
 
1403
 
 
1404
                /* If variable does not contain a delimiter, add one to ensure
 
1405
                 * it gets entered into the job environment table. Without the
 
1406
                 * delimiter, the variable will be silently ignored unless it's
 
1407
                 * already set in inits environment. But in that case there is
 
1408
                 * no point in setting such a variable to its already existing
 
1409
                 * value.
 
1410
                 */
 
1411
                if (! strchr (*var, '=')) {
 
1412
                        envvar = NIH_MUST (nih_sprintf (NULL, "%s=", *var));
 
1413
                } else {
 
1414
                        envvar = NIH_MUST (nih_strdup (NULL, *var));
 
1415
                }
 
1416
 
 
1417
                if (job) {
 
1418
                        /* Modify job-specific environment */
 
1419
                        nih_assert (job->env);
 
1420
 
 
1421
                        NIH_MUST (environ_add (&job->env, job, NULL, replace, envvar));
 
1422
                } else if (job_class_environment_set (envvar, replace) < 0) {
 
1423
                        nih_return_no_memory_error (-1);
 
1424
                }
 
1425
        }
 
1426
 
 
1427
        return 0;
 
1428
}
 
1429
 
 
1430
/**
1256
1431
 * control_set_env:
1257
1432
 *
1258
1433
 * @data: not used,
1280
1455
                 const char      *var,
1281
1456
                 int              replace)
1282
1457
{
 
1458
        nih_local char **vars = NULL;
 
1459
        
 
1460
        if (! var) {
 
1461
                nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
 
1462
                                        _("Variable may not be empty string"));
 
1463
                return -1;
 
1464
        }
 
1465
 
 
1466
        vars = NIH_MUST (nih_str_array_new (NULL));
 
1467
 
 
1468
        NIH_MUST (nih_str_array_add (&vars, NULL, NULL, var));
 
1469
 
 
1470
        return control_set_env_list (data, message, job_details, vars, replace);
 
1471
}
 
1472
 
 
1473
/**
 
1474
 * control_unset_env_list:
 
1475
 *
 
1476
 * @data: not used,
 
1477
 * @message: D-Bus connection and message received,
 
1478
 * @job_details: name and instance of job to apply operation to,
 
1479
 * @names: array of variables to clear from the job environment array.
 
1480
 *
 
1481
 * Implements the UnsetEnvList method of the com.ubuntu.Upstart
 
1482
 * interface.
 
1483
 *
 
1484
 * Called to request Upstart remove one or more variables from the job
 
1485
 * environment array.
 
1486
 *
 
1487
 * Returns: zero on success, negative value on raised error.
 
1488
 **/
 
1489
int
 
1490
control_unset_env_list (void            *data,
 
1491
                        NihDBusMessage  *message,
 
1492
                        char * const    *job_details,
 
1493
                        char * const    *names)
 
1494
{
1283
1495
        Session         *session;
1284
1496
        Job             *job = NULL;
1285
1497
        char            *job_name = NULL;
1286
1498
        char            *instance = NULL;
1287
 
        nih_local char  *envvar = NULL;
 
1499
        char * const    *name;
1288
1500
 
1289
1501
        nih_assert (message);
1290
1502
        nih_assert (job_details);
 
1503
        nih_assert (names);
1291
1504
 
1292
1505
        if (! control_check_permission (message)) {
1293
1506
                nih_dbus_error_raise_printf (
1308
1521
                return -1;
1309
1522
        }
1310
1523
 
1311
 
        if (! var || ! *var) {
1312
 
                nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
1313
 
                                _("Variable may not be empty string"));
1314
 
                return -1;
1315
 
        }
1316
 
 
1317
1524
        /* Verify that job name is valid */
1318
1525
        if (job_name && ! strlen (job_name)) {
1319
1526
                nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
1328
1535
         * the outside system.
1329
1536
         */
1330
1537
        if (session && session->chroot) {
1331
 
                nih_warn (_("Ignoring set env request from chroot session"));
 
1538
                nih_warn (_("Ignoring unset env request from chroot session"));
1332
1539
                return 0;
1333
1540
        }
1334
1541
 
1335
1542
        /* Lookup the job */
1336
1543
        control_get_job (session, job, job_name, instance);
1337
1544
 
1338
 
        /* If variable does not contain a delimiter, add one to ensure
1339
 
         * it gets entered into the job environment table. Without the
1340
 
         * delimiter, the variable will be silently ignored unless it's
1341
 
         * already set in inits environment. But in that case there is
1342
 
         * no point in setting such a variable to its already existing
1343
 
         * value.
1344
 
         */
1345
 
        if (! strchr (var, '='))
1346
 
                envvar = NIH_MUST (nih_sprintf (NULL, "%s=", var));
1347
 
        else
1348
 
                envvar = NIH_MUST (nih_strdup (NULL, var));
1349
 
 
1350
 
        if (job) {
1351
 
                /* Modify job-specific environment */
1352
 
 
1353
 
                nih_assert (job->env);
1354
 
 
1355
 
                NIH_MUST (environ_add (&job->env, job, NULL, replace, envvar));
1356
 
                return 0;
 
1545
        for (name = names; name && *name; name++) {
 
1546
                if (! *name) {
 
1547
                        nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
 
1548
                                        _("Variable may not be empty string"));
 
1549
                        return -1;
 
1550
                }
 
1551
 
 
1552
                if (job) {
 
1553
                        /* Modify job-specific environment */
 
1554
                        nih_assert (job->env);
 
1555
 
 
1556
                        if (! environ_remove (&job->env, job, NULL, *name))
 
1557
                                return -1;
 
1558
                } else if (job_class_environment_unset (*name) < 0) {
 
1559
                        goto error;
 
1560
                }
1357
1561
        }
1358
1562
 
1359
 
        if (job_class_environment_set (envvar, replace) < 0)
1360
 
                nih_return_no_memory_error (-1);
1361
 
 
1362
1563
        return 0;
 
1564
 
 
1565
error:
 
1566
        nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
 
1567
                        "%s: %s",
 
1568
                        _("No such variable"), *name);
 
1569
        return -1;
1363
1570
}
1364
1571
 
1365
1572
/**
1384
1591
                   char * const    *job_details,
1385
1592
                   const char      *name)
1386
1593
{
1387
 
        Session         *session;
1388
 
        Job             *job = NULL;
1389
 
        char            *job_name = NULL;
1390
 
        char            *instance = NULL;
1391
 
 
1392
 
        nih_assert (message);
1393
 
        nih_assert (job_details);
1394
 
 
1395
 
        if (! control_check_permission (message)) {
1396
 
                nih_dbus_error_raise_printf (
1397
 
                        DBUS_INTERFACE_UPSTART ".Error.PermissionDenied",
1398
 
                        _("You do not have permission to modify job environment"));
1399
 
                return -1;
1400
 
        }
1401
 
 
1402
 
        if (! name || ! *name) {
1403
 
                nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
1404
 
                                _("Variable may not be empty string"));
1405
 
                return -1;
1406
 
        }
1407
 
 
1408
 
        if (job_details[0]) {
1409
 
                job_name = job_details[0];
1410
 
 
1411
 
                /* this can be a null value */
1412
 
                instance = job_details[1];
1413
 
        } else if (getpid () == 1) {
1414
 
                nih_dbus_error_raise_printf (
1415
 
                        DBUS_INTERFACE_UPSTART ".Error.PermissionDenied",
1416
 
                        _("Not permissible to modify PID 1 job environment"));
1417
 
                return -1;
1418
 
        }
1419
 
 
1420
 
        /* Verify that job name is valid */
1421
 
        if (job_name && ! strlen (job_name)) {
1422
 
                nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
1423
 
                                             _("Job may not be empty string"));
1424
 
                return -1;
1425
 
        }
1426
 
 
1427
 
        /* Get the relevant session */
1428
 
        session = session_from_dbus (NULL, message);
1429
 
 
1430
 
        /* Chroot sessions must not be able to influence
1431
 
         * the outside system.
1432
 
         */
1433
 
        if (session && session->chroot) {
1434
 
                nih_warn (_("Ignoring unset env request from chroot session"));
1435
 
                return 0;
1436
 
        }
1437
 
 
1438
 
        /* Lookup the job */
1439
 
        control_get_job (session, job, job_name, instance);
1440
 
 
1441
 
        if (job) {
1442
 
                /* Modify job-specific environment */
1443
 
 
1444
 
                nih_assert (job->env);
1445
 
 
1446
 
                if (! environ_remove (&job->env, job, NULL, name))
1447
 
                        return -1;
1448
 
 
1449
 
                return 0;
1450
 
        }
1451
 
 
1452
 
        if (job_class_environment_unset (name) < 0)
1453
 
                goto error;
1454
 
 
1455
 
        return 0;
1456
 
 
1457
 
error:
1458
 
        nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
1459
 
                        "%s: %s",
1460
 
                        _("No such variable"), name);
1461
 
        return -1;
 
1594
        nih_local char **names = NULL;
 
1595
 
 
1596
        if (! name) {
 
1597
                nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
 
1598
                                        _("Variable may not be empty string"));
 
1599
                return -1;
 
1600
        }
 
1601
        
 
1602
        names = NIH_MUST (nih_str_array_new (NULL));
 
1603
 
 
1604
        NIH_MUST (nih_str_array_add (&names, NULL, NULL, name));
 
1605
 
 
1606
        return control_unset_env_list (data, message, job_details, names);
1462
1607
}
1463
1608
 
1464
1609
/**