X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fmanager.c;h=a5b0ce002d1a0f292df4930504a7879345ffd1de;hb=e543deaeb5c4af128a27ea0a7e858dacefe32305;hp=cc12d6bf220ea7ca408c21ba002519f037723a75;hpb=48a21c9b37372e508fdf1f29a0b4dc90ea051ba3;p=elogind.git diff --git a/src/manager.c b/src/manager.c index cc12d6bf2..a5b0ce002 100644 --- a/src/manager.c +++ b/src/manager.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -38,6 +37,10 @@ #include #include +#ifdef HAVE_AUDIT +#include +#endif + #include "manager.h" #include "hashmap.h" #include "macro.h" @@ -47,7 +50,6 @@ #include "ratelimit.h" #include "cgroup.h" #include "mount-setup.h" -#include "utmp-wtmp.h" #include "unit-name.h" #include "dbus-unit.h" #include "dbus-job.h" @@ -202,6 +204,10 @@ int manager_new(ManagerRunningAs running_as, Manager **_m) { m->exit_code = _MANAGER_EXIT_CODE_INVALID; m->pin_cgroupfs_fd = -1; +#ifdef HAVE_AUDIT + m->audit_fd = -1; +#endif + m->signal_watch.fd = m->mount_watch.fd = m->udev_watch.fd = m->epoll_fd = m->dev_autofs_fd = -1; m->current_job_id = 1; /* start as id #1, so that we can leave #0 around as "null-like" value */ @@ -245,6 +251,11 @@ int manager_new(ManagerRunningAs running_as, Manager **_m) { if ((r = bus_init(m)) < 0) goto fail; +#ifdef HAVE_AUDIT + if ((m->audit_fd = audit_open()) < 0) + log_error("Failed to connect to audit log: %m"); +#endif + *_m = m; return 0; @@ -429,6 +440,11 @@ void manager_free(Manager *m) { if (m->notify_watch.fd >= 0) close_nointr_nofail(m->notify_watch.fd); +#ifdef HAVE_AUDIT + if (m->audit_fd >= 0) + audit_close(m->audit_fd); +#endif + free(m->notify_socket); lookup_paths_free(&m->lookup_paths); @@ -567,10 +583,6 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) { m->n_deserializing --; } - /* Now that the initial devices are available, let's see if we - * can write the utmp file */ - manager_write_utmp_reboot(m); - return r; } @@ -715,6 +727,20 @@ static void transaction_merge_and_delete_job(Manager *m, Job *j, Job *other, Job other->object_list = NULL; transaction_delete_job(m, other, true); } +static bool job_is_conflicted_by(Job *j) { + JobDependency *l; + + assert(j); + + /* Returns true if this job is pulled in by a least one + * ConflictedBy dependency. */ + + LIST_FOREACH(object, l, j->object_list) + if (l->conflicts) + return true; + + return false; +} static int delete_one_unmergeable_job(Manager *m, Job *j) { Job *k; @@ -738,7 +764,36 @@ static int delete_one_unmergeable_job(Manager *m, Job *j) { /* Ok, we found two that conflict, let's see if we can * drop one of them */ - if (!j->matters_to_anchor) + if (!j->matters_to_anchor && !k->matters_to_anchor) { + + /* Both jobs don't matter, so let's + * find the one that is smarter to + * remove. Let's think positive and + * rather remove stops then starts -- + * except if something is being + * stopped because it is conflicted by + * another unit in which case we + * rather remove the start. */ + + log_debug("Looking at job %s/%s conflicted_by=%s", j->unit->meta.id, job_type_to_string(j->type), yes_no(j->type == JOB_STOP && job_is_conflicted_by(j))); + log_debug("Looking at job %s/%s conflicted_by=%s", k->unit->meta.id, job_type_to_string(k->type), yes_no(k->type == JOB_STOP && job_is_conflicted_by(k))); + + if (j->type == JOB_STOP) { + + if (job_is_conflicted_by(j)) + d = k; + else + d = j; + + } else if (k->type == JOB_STOP) { + + if (job_is_conflicted_by(k)) + d = j; + else + d = k; + } + + } else if (!j->matters_to_anchor) d = j; else if (!k->matters_to_anchor) d = k; @@ -746,7 +801,7 @@ static int delete_one_unmergeable_job(Manager *m, Job *j) { return -ENOEXEC; /* Ok, we can drop one, so let's do so. */ - log_notice("Trying to fix job merging by deleting job %s/%s", d->unit->meta.id, job_type_to_string(d->type)); + log_debug("Fixing conflicting jobs by deleting job %s/%s", d->unit->meta.id, job_type_to_string(d->type)); transaction_delete_job(m, d, true); return 0; } @@ -1309,7 +1364,7 @@ void manager_transaction_unlink_job(Manager *m, Job *j, bool delete_dependencies job_dependency_free(j->object_list); if (other && delete_dependencies) { - log_info("Deleting job %s/%s as dependency of job %s/%s", + log_debug("Deleting job %s/%s as dependency of job %s/%s", other->unit->meta.id, job_type_to_string(other->type), j->unit->meta.id, job_type_to_string(j->type)); transaction_delete_job(m, other, delete_dependencies); @@ -1324,6 +1379,7 @@ static int transaction_add_job_and_dependencies( Job *by, bool matters, bool override, + bool conflicts, DBusError *e, Job **_ret) { Job *ret; @@ -1352,46 +1408,50 @@ static int transaction_add_job_and_dependencies( return -ENOMEM; /* Then, add a link to the job. */ - if (!job_dependency_new(by, ret, matters)) + if (!job_dependency_new(by, ret, matters, conflicts)) return -ENOMEM; if (is_new) { /* Finally, recursively add in all dependencies. */ if (type == JOB_START || type == JOB_RELOAD_OR_START) { SET_FOREACH(dep, ret->unit->meta.dependencies[UNIT_REQUIRES], i) - if ((r = transaction_add_job_and_dependencies(m, JOB_START, dep, ret, true, override, e, NULL)) < 0 && r != -EBADR) + if ((r = transaction_add_job_and_dependencies(m, JOB_START, dep, ret, true, override, false, e, NULL)) < 0 && r != -EBADR) goto fail; SET_FOREACH(dep, ret->unit->meta.dependencies[UNIT_REQUIRES_OVERRIDABLE], i) - if ((r = transaction_add_job_and_dependencies(m, JOB_START, dep, ret, !override, override, e, NULL)) < 0 && r != -EBADR) { + if ((r = transaction_add_job_and_dependencies(m, JOB_START, dep, ret, !override, override, false, e, NULL)) < 0 && r != -EBADR) { log_warning("Cannot add dependency job for unit %s, ignoring: %s", dep->meta.id, bus_error(e, r)); dbus_error_free(e); } SET_FOREACH(dep, ret->unit->meta.dependencies[UNIT_WANTS], i) - if ((r = transaction_add_job_and_dependencies(m, JOB_START, dep, ret, false, false, e, NULL)) < 0) { + if ((r = transaction_add_job_and_dependencies(m, JOB_START, dep, ret, false, false, false, e, NULL)) < 0) { log_warning("Cannot add dependency job for unit %s, ignoring: %s", dep->meta.id, bus_error(e, r)); dbus_error_free(e); } SET_FOREACH(dep, ret->unit->meta.dependencies[UNIT_REQUISITE], i) - if ((r = transaction_add_job_and_dependencies(m, JOB_VERIFY_ACTIVE, dep, ret, true, override, e, NULL)) < 0 && r != -EBADR) + if ((r = transaction_add_job_and_dependencies(m, JOB_VERIFY_ACTIVE, dep, ret, true, override, false, e, NULL)) < 0 && r != -EBADR) goto fail; SET_FOREACH(dep, ret->unit->meta.dependencies[UNIT_REQUISITE_OVERRIDABLE], i) - if ((r = transaction_add_job_and_dependencies(m, JOB_VERIFY_ACTIVE, dep, ret, !override, override, e, NULL)) < 0 && r != -EBADR) { + if ((r = transaction_add_job_and_dependencies(m, JOB_VERIFY_ACTIVE, dep, ret, !override, override, false, e, NULL)) < 0 && r != -EBADR) { log_warning("Cannot add dependency job for unit %s, ignoring: %s", dep->meta.id, bus_error(e, r)); dbus_error_free(e); } SET_FOREACH(dep, ret->unit->meta.dependencies[UNIT_CONFLICTS], i) - if ((r = transaction_add_job_and_dependencies(m, JOB_STOP, dep, ret, true, override, e, NULL)) < 0 && r != -EBADR) + if ((r = transaction_add_job_and_dependencies(m, JOB_STOP, dep, ret, true, override, true, e, NULL)) < 0 && r != -EBADR) + goto fail; + + SET_FOREACH(dep, ret->unit->meta.dependencies[UNIT_CONFLICTED_BY], i) + if ((r = transaction_add_job_and_dependencies(m, JOB_STOP, dep, ret, true, override, false, e, NULL)) < 0 && r != -EBADR) goto fail; } else if (type == JOB_STOP || type == JOB_RESTART || type == JOB_TRY_RESTART) { SET_FOREACH(dep, ret->unit->meta.dependencies[UNIT_REQUIRED_BY], i) - if ((r = transaction_add_job_and_dependencies(m, type, dep, ret, true, override, e, NULL)) < 0 && r != -EBADR) + if ((r = transaction_add_job_and_dependencies(m, type, dep, ret, true, override, false, e, NULL)) < 0 && r != -EBADR) goto fail; } @@ -1432,7 +1492,7 @@ static int transaction_add_isolate_jobs(Manager *m) { if (hashmap_get(m->transaction_jobs, u)) continue; - if ((r = transaction_add_job_and_dependencies(m, JOB_STOP, u, NULL, true, false, NULL, NULL)) < 0) + if ((r = transaction_add_job_and_dependencies(m, JOB_STOP, u, NULL, true, false, false, NULL, NULL)) < 0) log_warning("Cannot add isolate job for unit %s, ignoring: %s", u->meta.id, strerror(-r)); } @@ -1455,7 +1515,7 @@ int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, bool ove log_debug("Trying to enqueue job %s/%s", unit->meta.id, job_type_to_string(type)); - if ((r = transaction_add_job_and_dependencies(m, type, unit, NULL, true, override, e, &ret)) < 0) { + if ((r = transaction_add_job_and_dependencies(m, type, unit, NULL, true, override, false, e, &ret)) < 0) { transaction_abort(m); return r; } @@ -2186,70 +2246,25 @@ int manager_get_job_from_dbus_path(Manager *m, const char *s, Job **_j) { return 0; } -static bool manager_utmp_good(Manager *m) { - int r; - - assert(m); - - if ((r = mount_path_is_mounted(m, _PATH_UTMPX)) <= 0) { - - if (r < 0) - log_warning("Failed to determine whether " _PATH_UTMPX " is mounted: %s", strerror(-r)); - - return false; - } - - return true; -} - -void manager_write_utmp_reboot(Manager *m) { - int r; - - assert(m); +void manager_send_unit_audit(Manager *m, Unit *u, int type, bool success) { - if (m->utmp_reboot_written) - return; +#ifdef HAVE_AUDIT + char *p; - if (m->running_as != MANAGER_SYSTEM) + if (m->audit_fd < 0) return; - if (!manager_utmp_good(m)) - return; - - if ((r = utmp_put_reboot(m->startup_timestamp.realtime)) < 0) { - - if (r != -ENOENT && r != -EROFS) - log_warning("Failed to write utmp/wtmp: %s", strerror(-r)); - + if (!(p = unit_name_to_prefix_and_instance(u->meta.id))) { + log_error("Failed to allocate unit name for audit message: %s", strerror(ENOMEM)); return; } - m->utmp_reboot_written = true; -} - -void manager_write_utmp_runlevel(Manager *m, Unit *u) { - int runlevel, r; - - assert(m); - assert(u); - - if (u->meta.type != UNIT_TARGET) - return; + if (audit_log_user_comm_message(m->audit_fd, type, "", p, NULL, NULL, NULL, success) < 0) + log_error("Failed to send audit message: %m"); - if (m->running_as != MANAGER_SYSTEM) - return; - - if (!manager_utmp_good(m)) - return; + free(p); +#endif - if ((runlevel = target_get_runlevel(TARGET(u))) <= 0) - return; - - if ((r = utmp_put_runlevel(0, runlevel, 0)) < 0) { - - if (r != -ENOENT && r != -EROFS) - log_warning("Failed to write utmp/wtmp: %s", strerror(-r)); - } } void manager_dispatch_bus_name_owner_changed(