1053
/* Disallow users from restarting Upstart, unless they happen to
1054
* own this process (which they may do in the test scenario and
1055
* when running Upstart as a non-privileged user).
1057
if (session && session->user != uid) {
1058
nih_dbus_error_raise_printf (
1059
DBUS_INTERFACE_UPSTART ".Error.PermissionDenied",
1060
_("You do not have permission to request restart"));
1064
1114
nih_info (_("Restarting"));
1066
1116
stateful_reexec ();
1122
* control_notify_event_emitted
1124
* Re-emits an event over DBUS using the EventEmitted signal
1127
control_notify_event_emitted (Event *event)
1129
nih_assert (event != NULL);
1133
NIH_LIST_FOREACH (control_conns, iter) {
1134
NihListEntry *entry = (NihListEntry *)iter;
1135
DBusConnection *conn = (DBusConnection *)entry->data;
1137
NIH_ZERO (control_emit_event_emitted (conn, DBUS_PATH_UPSTART,
1138
event->name, event->env));
1143
* control_notify_restarted
1145
* DBUS signal sent when upstart has re-executed itself.
1148
control_notify_restarted (void)
1152
NIH_LIST_FOREACH (control_conns, iter) {
1153
NihListEntry *entry = (NihListEntry *)iter;
1154
DBusConnection *conn = (DBusConnection *)entry->data;
1156
NIH_ZERO (control_emit_restarted (conn, DBUS_PATH_UPSTART));
1164
* @message: D-Bus connection and message received,
1165
* @job_details: name and instance of job to apply operation to,
1166
* @var: name[/value] pair of environment variable to set,
1167
* @replace: TRUE if @name should be overwritten if already set, else
1170
* Implements the SetEnv method of the com.ubuntu.Upstart
1173
* Called to request Upstart store a particular name/value pair.
1175
* If @job_details is empty, change will be applied to all job
1176
* environments, else only apply changes to specific job environment
1177
* encoded within @job_details.
1179
* Returns: zero on success, negative value on raised error.
1182
control_set_env (void *data,
1183
NihDBusMessage *message,
1184
char * const *job_details,
1190
char *job_name = NULL;
1191
char *instance = NULL;
1192
nih_local char *envvar = NULL;
1194
nih_assert (message);
1195
nih_assert (job_details);
1198
if (job_details[0]) {
1199
job_name = job_details[0];
1201
/* this can be a null value */
1202
instance = job_details[1];
1203
} else if (getpid () == 1) {
1204
nih_dbus_error_raise_printf (
1205
DBUS_INTERFACE_UPSTART ".Error.PermissionDenied",
1206
_("Not permissible to modify PID 1 job environment"));
1210
if (! control_check_permission (message)) {
1211
nih_dbus_error_raise_printf (
1212
DBUS_INTERFACE_UPSTART ".Error.PermissionDenied",
1213
_("You do not have permission to modify job environment"));
1217
/* Verify that job name is valid */
1218
if (job_name && ! strlen (job_name)) {
1219
nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
1220
_("Job may not be empty string"));
1224
/* Get the relevant session */
1225
session = session_from_dbus (NULL, message);
1227
/* Chroot sessions must not be able to influence
1228
* the outside system.
1230
if (session && session->chroot) {
1231
nih_warn (_("Ignoring set env request from chroot session"));
1235
/* Lookup the job */
1236
control_get_job (session, job, job_name, instance);
1238
/* If variable does not contain a delimiter, add one to ensure
1239
* it gets entered into the job environment table. Without the
1240
* delimiter, the variable will be silently ignored unless it's
1241
* already set in inits environment. But in that case there is
1242
* no point in setting such a variable to its already existing
1245
if (! strchr (var, '='))
1246
envvar = NIH_MUST (nih_sprintf (NULL, "%s=", var));
1248
envvar = NIH_MUST (nih_strdup (NULL, var));
1251
/* Modify job-specific environment */
1253
nih_assert (job->env);
1255
NIH_MUST (environ_add (&job->env, job, NULL, replace, envvar));
1259
if (job_class_environment_set (envvar, replace) < 0)
1260
nih_return_no_memory_error (-1);
1266
* control_unset_env:
1269
* @message: D-Bus connection and message received,
1270
* @job_details: name and instance of job to apply operation to,
1271
* @name: variable to clear from the job environment array.
1273
* Implements the UnsetEnv method of the com.ubuntu.Upstart
1276
* Called to request Upstart remove a particular variable from the job
1277
* environment array.
1279
* Returns: zero on success, negative value on raised error.
1282
control_unset_env (void *data,
1283
NihDBusMessage *message,
1284
char * const *job_details,
1289
char *job_name = NULL;
1290
char *instance = NULL;
1292
nih_assert (message);
1293
nih_assert (job_details);
1296
if (! control_check_permission (message)) {
1297
nih_dbus_error_raise_printf (
1298
DBUS_INTERFACE_UPSTART ".Error.PermissionDenied",
1299
_("You do not have permission to modify job environment"));
1303
if (job_details[0]) {
1304
job_name = job_details[0];
1306
/* this can be a null value */
1307
instance = job_details[1];
1308
} else if (getpid () == 1) {
1309
nih_dbus_error_raise_printf (
1310
DBUS_INTERFACE_UPSTART ".Error.PermissionDenied",
1311
_("Not permissible to modify PID 1 job environment"));
1315
/* Verify that job name is valid */
1316
if (job_name && ! strlen (job_name)) {
1317
nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
1318
_("Job may not be empty string"));
1322
/* Get the relevant session */
1323
session = session_from_dbus (NULL, message);
1325
/* Chroot sessions must not be able to influence
1326
* the outside system.
1328
if (session && session->chroot) {
1329
nih_warn (_("Ignoring unset env request from chroot session"));
1333
/* Lookup the job */
1334
control_get_job (session, job, job_name, instance);
1337
/* Modify job-specific environment */
1339
nih_assert (job->env);
1341
if (! environ_remove (&job->env, job, NULL, name))
1347
if (job_class_environment_unset (name) < 0)
1353
nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
1355
_("No such variable"), name);
1363
* @message: D-Bus connection and message received,
1364
* @job_details: name and instance of job to apply operation to,
1365
* @name: name of environment variable to retrieve,
1366
* @value: value of @name.
1368
* Implements the GetEnv method of the com.ubuntu.Upstart
1371
* Called to obtain the value of a specified job environment variable.
1373
* Returns: zero on success, negative value on raised error.
1376
control_get_env (void *data,
1377
NihDBusMessage *message,
1378
char * const *job_details,
1385
char *job_name = NULL;
1386
char *instance = NULL;
1388
nih_assert (message != NULL);
1389
nih_assert (job_details);
1391
if (! control_check_permission (message)) {
1392
nih_dbus_error_raise_printf (
1393
DBUS_INTERFACE_UPSTART ".Error.PermissionDenied",
1394
_("You do not have permission to query job environment"));
1398
if (job_details[0]) {
1399
job_name = job_details[0];
1401
/* this can be a null value */
1402
instance = job_details[1];
1405
/* Verify that job name is valid */
1406
if (job_name && ! strlen (job_name)) {
1407
nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
1408
_("Job may not be empty string"));
1412
/* Get the relevant session */
1413
session = session_from_dbus (NULL, message);
1415
/* Chroot sessions must not be able to influence
1416
* the outside system.
1418
if (session && session->chroot) {
1419
nih_warn (_("Ignoring get env request from chroot session"));
1423
/* Lookup the job */
1424
control_get_job (session, job, job_name, instance);
1427
tmp = environ_get (job->env, name);
1431
*value = nih_strdup (message, tmp);
1433
nih_return_no_memory_error (-1);
1438
tmp = job_class_environment_get (name);
1443
*value = nih_strdup (message, tmp);
1445
nih_return_no_memory_error (-1);
1450
nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
1452
_("No such variable"), name);
1460
* @message: D-Bus connection and message received,
1461
* @job_details: name and instance of job to apply operation to,
1462
* @env: pointer to array of all job environment variables.
1464
* Implements the ListEnv method of the com.ubuntu.Upstart
1467
* Called to obtain an unsorted array of all environment variables
1468
* that will be set in a jobs environment.
1470
* Returns: zero on success, negative value on raised error.
1473
control_list_env (void *data,
1474
NihDBusMessage *message,
1475
char * const *job_details,
1480
char *job_name = NULL;
1481
char *instance = NULL;
1483
nih_assert (message);
1484
nih_assert (job_details);
1487
if (! control_check_permission (message)) {
1488
nih_dbus_error_raise_printf (
1489
DBUS_INTERFACE_UPSTART ".Error.PermissionDenied",
1490
_("You do not have permission to query job environment"));
1494
if (job_details[0]) {
1495
job_name = job_details[0];
1497
/* this can be a null value */
1498
instance = job_details[1];
1501
/* Verify that job name is valid */
1502
if (job_name && ! strlen (job_name)) {
1503
nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
1504
_("Job may not be empty string"));
1508
/* Get the relevant session */
1509
session = session_from_dbus (NULL, message);
1511
/* Lookup the job */
1512
control_get_job (session, job, job_name, instance);
1515
*env = nih_str_array_copy (job, NULL, job->env);
1517
nih_return_no_memory_error (-1);
1522
*env = job_class_environment_get_all (message);
1524
nih_return_no_memory_error (-1);
1530
* control_reset_env:
1533
* @message: D-Bus connection and message received,
1534
* @job_details: name and instance of job to apply operation to.
1536
* Implements the ResetEnv method of the com.ubuntu.Upstart
1539
* Called to reset the environment all subsequent jobs will run in to
1540
* the default minimal environment.
1542
* Returns: zero on success, negative value on raised error.
1545
control_reset_env (void *data,
1546
NihDBusMessage *message,
1547
char * const *job_details)
1551
char *job_name = NULL;
1552
char *instance = NULL;
1554
nih_assert (message);
1555
nih_assert (job_details);
1557
if (job_details[0]) {
1558
job_name = job_details[0];
1560
/* this can be a null value */
1561
instance = job_details[1];
1562
} else if (getpid () == 1) {
1563
nih_dbus_error_raise_printf (
1564
DBUS_INTERFACE_UPSTART ".Error.PermissionDenied",
1565
_("Not permissible to modify PID 1 job environment"));
1569
if (! control_check_permission (message)) {
1570
nih_dbus_error_raise_printf (
1571
DBUS_INTERFACE_UPSTART ".Error.PermissionDenied",
1572
_("You do not have permission to modify job environment"));
1576
/* Verify that job name is valid */
1577
if (job_name && ! strlen (job_name)) {
1578
nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
1579
_("Job may not be empty string"));
1583
/* Get the relevant session */
1584
session = session_from_dbus (NULL, message);
1586
/* Chroot sessions must not be able to influence
1587
* the outside system.
1589
if (session && session->chroot) {
1590
nih_warn (_("Ignoring reset env request from chroot session"));
1594
/* Lookup the job */
1595
control_get_job (session, job, job_name, instance);
1601
nih_free (job->env);
1605
job->env = job_class_environment (job, job->class, &len);
1607
nih_return_system_error (-1);
1612
job_class_environment_reset ();
1618
* control_get_origin_uid:
1619
* @message: D-Bus connection and message received,
1620
* @uid: returned uid value.
1622
* Returns TRUE: if @uid now contains uid corresponding to @message,
1626
control_get_origin_uid (NihDBusMessage *message, uid_t *uid)
1628
DBusError dbus_error;
1629
unsigned long unix_user = 0;
1632
nih_assert (message);
1635
dbus_error_init (&dbus_error);
1637
if (! message->message || ! message->connection)
1640
sender = dbus_message_get_sender (message->message);
1642
unix_user = dbus_bus_get_unix_user (message->connection, sender,
1644
if (unix_user == (unsigned long)-1) {
1645
dbus_error_free (&dbus_error);
1649
if (! dbus_connection_get_unix_user (message->connection,
1655
*uid = (uid_t)unix_user;
1661
* control_check_permission:
1663
* @message: D-Bus connection and message received.
1665
* Determine if caller should be allowed to make a control request.
1667
* Note that these permission checks rely on D-Bus to limit
1668
* session bus access to the same user.
1670
* Returns: TRUE if permission is granted, else FALSE.
1673
control_check_permission (NihDBusMessage *message)
1678
uid_t origin_uid = 0;
1680
nih_assert (message);
1685
ret = control_get_origin_uid (message, &origin_uid);
1687
/* Its possible that D-Bus might be unable to determine the user
1688
* making the request. In this case, deny the request unless
1689
* we're running as a Session Init or via the test harness.
1691
if ((ret && origin_uid == uid) || user_mode || (uid && pid != 1))
1698
* control_session_file_create:
1700
* Create session file if possible.
1702
* Errors are not fatal - the file is just not created.
1705
control_session_file_create (void)
1707
nih_local char *session_dir = NULL;
1711
nih_assert (control_server_address);
1713
session_dir = get_session_dir ();
1718
NIH_MUST (nih_strcat_sprintf (&session_file, NULL, "%s/%d%s",
1719
session_dir, (int)getpid (), SESSION_EXT));
1721
f = fopen (session_file, "w");
1723
nih_error ("%s: %s", _("unable to create session file"), session_file);
1727
ret = fprintf (f, SESSION_ENV "=%s\n", control_server_address);
1730
nih_error ("%s: %s", _("unable to write session file"), session_file);
1736
* control_session_file_remove:
1738
* Delete session file.
1740
* Errors are not fatal.
1743
control_session_file_remove (void)
1746
(void)unlink (session_file);
1750
* control_session_end:
1753
* @message: D-Bus connection and message received.
1755
* Implements the EndSession method of the com.ubuntu.Upstart
1758
* Called to request that Upstart stop all jobs and exit. Only
1759
* appropriate when running as a Session Init and user wishes to
1762
* Returns: zero on success, negative value on raised error.
1765
control_end_session (void *data,
1766
NihDBusMessage *message)
1770
nih_assert (message);
1772
/* Not supported at the system level */
1776
if (! control_check_permission (message)) {
1777
nih_dbus_error_raise_printf (
1778
DBUS_INTERFACE_UPSTART ".Error.PermissionDenied",
1779
_("You do not have permission to end session"));
1783
/* Get the relevant session */
1784
session = session_from_dbus (NULL, message);
1786
if (session && session->chroot) {
1787
nih_warn (_("Ignoring session end request from chroot session"));
1791
quiesce (QUIESCE_REQUESTER_SESSION);