diff options
author | Lennart Poettering <lennart@poettering.net> | 2012-09-17 12:39:16 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2012-09-17 12:39:16 +0200 |
commit | 98a77df5fe8591034c48e5d56d903ee268de37f9 (patch) | |
tree | f7e3bed02ed12414e71a0b250710d5b9ab7d080d | |
parent | 4db17f291c627c885de668200ff8cce2e57c933f (diff) |
logind: make sure there's always a getty available on TTY6
Previously, if X allocated all 6 TTYs (for multi-session for example) no
getty would be available anymore to guarantee console-based logins.
With the new ReserveVT= switch in logind.conf we can now choose one VT
(6 by default) that will always be subject to autovt-style activation,
i.e. we'll always have a getty on TTY6, and X will never take possession
of it.
-rw-r--r-- | TODO | 4 | ||||
-rw-r--r-- | man/logind.conf.xml | 51 | ||||
-rw-r--r-- | src/login/logind-gperf.gperf | 1 | ||||
-rw-r--r-- | src/login/logind.c | 48 | ||||
-rw-r--r-- | src/login/logind.conf | 1 | ||||
-rw-r--r-- | src/login/logind.h | 3 |
6 files changed, 92 insertions, 16 deletions
@@ -55,10 +55,10 @@ F18: * selinux: merge systemd selinux access controls (dwalsh) -* make logind reserve tty6 or so for text logins, so that gdm never picks it up - Features: +* move cryptsetup key caching into kernel keyctl? + * make nspawn work without terminal * hw watchdog: optionally try to use the preset watchdog timeout instead of always overriding it diff --git a/man/logind.conf.xml b/man/logind.conf.xml index 79a8932cea..304f570b1d 100644 --- a/man/logind.conf.xml +++ b/man/logind.conf.xml @@ -71,14 +71,15 @@ <listitem><para>Takes a positive integer. Configures how many virtual - terminals to allocate by default that - -- when switched to -- + terminals (VTs) to allocate by default + that -- when switched to and + previously unused -- <literal>autovt</literal> services are automatically spawned on. These services are instantiated from the - template + template unit <filename>autovt@.service</filename> - with the virtual terminal TTY name, + for the respective VT TTY name, e.g. <filename>autovt@tty4.service</filename>. By default <filename>autovt@.service</filename> @@ -86,12 +87,46 @@ <filename>getty@.service</filename>, i.e. login prompts are started dynamically as the user switches to - unused virtual terminals. This - parameter hence controls how many - gettys are available on the virtual - terminals. Defaults to 6. When set to + unused virtual terminals. Hence, this + parameter controls how many login + <literal>gettys</literal> are + available on the VTs. If a VT is + already used by some other subsystem + (for example a graphical login) this + kind of activation will not be + attempted. Note that the VT configured + in <varname>ReserveVT=</varname> is + always subject to this kind of + activation, even if it is not one of + VTs configured with the + <varname>NAutoVTs=</varname> + directive. Defaults to 6. When set to 0, automatic spawning of <literal>autovt</literal> services is + disabled. </para></listitem> + </varlistentry> + + <varlistentry> + <term><varname>ReserveVT=</varname></term> + + <listitem><para>Takes a positive + integer. Configures the number of one + virtual terminal that shall + unconditionally be reserved for + <filename>autovt@.service</filename> + activation (see above). The VT + selected with this option will be + marked busy unconditionally so that no + other subsystem will allocate it. This + functionality is useful to ensure that + regardless how many VTs are allocated + by other subsystems one login + <literal>getty</literal> is always + available. Defaults to 6 (with other + words: there'll always be a + <literal>getty</literal> available on + Alt-F6.). When set to 0, VT + reservation is disabled.</para></listitem> </varlistentry> diff --git a/src/login/logind-gperf.gperf b/src/login/logind-gperf.gperf index 72fdad739b..f12718cf4e 100644 --- a/src/login/logind-gperf.gperf +++ b/src/login/logind-gperf.gperf @@ -15,6 +15,7 @@ struct ConfigPerfItem; %includes %% Login.NAutoVTs, config_parse_unsigned, 0, offsetof(Manager, n_autovts) +Login.ReserveVT, config_parse_unsigned, 0, offsetof(Manager, reserve_vt) Login.KillUserProcesses, config_parse_bool, 0, offsetof(Manager, kill_user_processes) Login.KillOnlyUsers, config_parse_strv, 0, offsetof(Manager, kill_only_users) Login.KillExcludeUsers, config_parse_strv, 0, offsetof(Manager, kill_exclude_users) diff --git a/src/login/logind.c b/src/login/logind.c index 229af714f8..f72eb490fe 100644 --- a/src/login/logind.c +++ b/src/login/logind.c @@ -50,8 +50,10 @@ Manager *manager_new(void) { m->udev_vcsa_fd = -1; m->udev_button_fd = -1; m->epoll_fd = -1; + m->reserve_vt_fd = -1; m->n_autovts = 6; + m->reserve_vt = 6; m->inhibit_delay_max = 5 * USEC_PER_SEC; m->handle_power_key = HANDLE_NO_SESSION; m->handle_sleep_key = HANDLE_TTY_SESSION; @@ -166,6 +168,9 @@ void manager_free(Manager *m) { if (m->epoll_fd >= 0) close_nointr_nofail(m->epoll_fd); + if (m->reserve_vt_fd >= 0) + close_nointr_nofail(m->reserve_vt_fd); + strv_free(m->controllers); strv_free(m->reset_controllers); strv_free(m->kill_only_users); @@ -948,20 +953,28 @@ int manager_spawn_autovt(Manager *m, int vtnr) { assert(m); assert(vtnr >= 1); - if ((unsigned) vtnr > m->n_autovts) + if ((unsigned) vtnr > m->n_autovts && + (unsigned) vtnr != m->reserve_vt) return 0; - r = vt_is_busy(vtnr); - if (r < 0) - return r; - else if (r > 0) - return -EBUSY; + if ((unsigned) vtnr != m->reserve_vt) { + /* If this is the reserved TTY, we'll start the getty + * on it in any case, but otherwise only if it is not + * busy. */ + + r = vt_is_busy(vtnr); + if (r < 0) + return r; + else if (r > 0) + return -EBUSY; + } if (asprintf(&name, "autovt@tty%i.service", vtnr) < 0) { log_error("Could not allocate service name."); r = -ENOMEM; goto finish; } + r = bus_method_call_with_reply ( m->bus, "org.freedesktop.systemd1", @@ -980,6 +993,26 @@ finish: return r; } +static int manager_reserve_vt(Manager *m) { + _cleanup_free_ char *p = NULL; + + assert(m); + + if (m->reserve_vt <= 0) + return 0; + + if (asprintf(&p, "/dev/tty%u", m->reserve_vt) < 0) + return log_oom(); + + m->reserve_vt_fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK); + if (m->reserve_vt_fd < 0) { + log_warning("Failed to pin reserved VT: %m"); + return -errno; + } + + return 0; +} + int manager_get_session_by_cgroup(Manager *m, const char *cgroup, Session **session) { Session *s; char *p; @@ -1450,6 +1483,9 @@ int manager_startup(Manager *m) { /* Remove stale objects before we start them */ manager_gc(m, false); + /* Reserve the special reserved VT */ + manager_reserve_vt(m); + /* And start everything */ HASHMAP_FOREACH(seat, m->seats, i) seat_start(seat); diff --git a/src/login/logind.conf b/src/login/logind.conf index 78496a0ef1..db5dde47a0 100644 --- a/src/login/logind.conf +++ b/src/login/logind.conf @@ -9,6 +9,7 @@ [Login] #NAutoVTs=6 +#ReserveVT=6 #KillUserProcesses=no #KillOnlyUsers= #KillExcludeUsers=root diff --git a/src/login/logind.h b/src/login/logind.h index 24d705b541..8aa28a322c 100644 --- a/src/login/logind.h +++ b/src/login/logind.h @@ -68,6 +68,9 @@ struct Manager { unsigned n_autovts; + unsigned reserve_vt; + int reserve_vt_fd; + Seat *vtconsole; char *cgroup_path; |