mirror of
https://github.com/systemd/systemd.git
synced 2024-12-22 17:35:35 +03:00
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.
This commit is contained in:
parent
4db17f291c
commit
98a77df5fe
4
TODO
4
TODO
@ -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
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
[Login]
|
||||
#NAutoVTs=6
|
||||
#ReserveVT=6
|
||||
#KillUserProcesses=no
|
||||
#KillOnlyUsers=
|
||||
#KillExcludeUsers=root
|
||||
|
@ -68,6 +68,9 @@ struct Manager {
|
||||
|
||||
unsigned n_autovts;
|
||||
|
||||
unsigned reserve_vt;
|
||||
int reserve_vt_fd;
|
||||
|
||||
Seat *vtconsole;
|
||||
|
||||
char *cgroup_path;
|
||||
|
Loading…
Reference in New Issue
Block a user