mirror of
https://github.com/systemd/systemd.git
synced 2025-09-06 05:44:41 +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:
4
TODO
4
TODO
@@ -55,10 +55,10 @@ F18:
|
|||||||
|
|
||||||
* selinux: merge systemd selinux access controls (dwalsh)
|
* selinux: merge systemd selinux access controls (dwalsh)
|
||||||
|
|
||||||
* make logind reserve tty6 or so for text logins, so that gdm never picks it up
|
|
||||||
|
|
||||||
Features:
|
Features:
|
||||||
|
|
||||||
|
* move cryptsetup key caching into kernel keyctl?
|
||||||
|
|
||||||
* make nspawn work without terminal
|
* make nspawn work without terminal
|
||||||
|
|
||||||
* hw watchdog: optionally try to use the preset watchdog timeout instead of always overriding it
|
* hw watchdog: optionally try to use the preset watchdog timeout instead of always overriding it
|
||||||
|
@@ -71,14 +71,15 @@
|
|||||||
|
|
||||||
<listitem><para>Takes a positive
|
<listitem><para>Takes a positive
|
||||||
integer. Configures how many virtual
|
integer. Configures how many virtual
|
||||||
terminals to allocate by default that
|
terminals (VTs) to allocate by default
|
||||||
-- when switched to --
|
that -- when switched to and
|
||||||
|
previously unused --
|
||||||
<literal>autovt</literal> services are
|
<literal>autovt</literal> services are
|
||||||
automatically spawned on. These
|
automatically spawned on. These
|
||||||
services are instantiated from the
|
services are instantiated from the
|
||||||
template
|
template unit
|
||||||
<filename>autovt@.service</filename>
|
<filename>autovt@.service</filename>
|
||||||
with the virtual terminal TTY name,
|
for the respective VT TTY name,
|
||||||
e.g. <filename>autovt@tty4.service</filename>. By
|
e.g. <filename>autovt@tty4.service</filename>. By
|
||||||
default
|
default
|
||||||
<filename>autovt@.service</filename>
|
<filename>autovt@.service</filename>
|
||||||
@@ -86,15 +87,49 @@
|
|||||||
<filename>getty@.service</filename>,
|
<filename>getty@.service</filename>,
|
||||||
i.e. login prompts are started
|
i.e. login prompts are started
|
||||||
dynamically as the user switches to
|
dynamically as the user switches to
|
||||||
unused virtual terminals. This
|
unused virtual terminals. Hence, this
|
||||||
parameter hence controls how many
|
parameter controls how many login
|
||||||
gettys are available on the virtual
|
<literal>gettys</literal> are
|
||||||
terminals. Defaults to 6. When set to
|
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
|
0, automatic spawning of
|
||||||
<literal>autovt</literal> services is
|
<literal>autovt</literal> services is
|
||||||
disabled. </para></listitem>
|
disabled. </para></listitem>
|
||||||
</varlistentry>
|
</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>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>KillUserProcesses=</varname></term>
|
<term><varname>KillUserProcesses=</varname></term>
|
||||||
|
|
||||||
|
@@ -15,6 +15,7 @@ struct ConfigPerfItem;
|
|||||||
%includes
|
%includes
|
||||||
%%
|
%%
|
||||||
Login.NAutoVTs, config_parse_unsigned, 0, offsetof(Manager, n_autovts)
|
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.KillUserProcesses, config_parse_bool, 0, offsetof(Manager, kill_user_processes)
|
||||||
Login.KillOnlyUsers, config_parse_strv, 0, offsetof(Manager, kill_only_users)
|
Login.KillOnlyUsers, config_parse_strv, 0, offsetof(Manager, kill_only_users)
|
||||||
Login.KillExcludeUsers, config_parse_strv, 0, offsetof(Manager, kill_exclude_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_vcsa_fd = -1;
|
||||||
m->udev_button_fd = -1;
|
m->udev_button_fd = -1;
|
||||||
m->epoll_fd = -1;
|
m->epoll_fd = -1;
|
||||||
|
m->reserve_vt_fd = -1;
|
||||||
|
|
||||||
m->n_autovts = 6;
|
m->n_autovts = 6;
|
||||||
|
m->reserve_vt = 6;
|
||||||
m->inhibit_delay_max = 5 * USEC_PER_SEC;
|
m->inhibit_delay_max = 5 * USEC_PER_SEC;
|
||||||
m->handle_power_key = HANDLE_NO_SESSION;
|
m->handle_power_key = HANDLE_NO_SESSION;
|
||||||
m->handle_sleep_key = HANDLE_TTY_SESSION;
|
m->handle_sleep_key = HANDLE_TTY_SESSION;
|
||||||
@@ -166,6 +168,9 @@ void manager_free(Manager *m) {
|
|||||||
if (m->epoll_fd >= 0)
|
if (m->epoll_fd >= 0)
|
||||||
close_nointr_nofail(m->epoll_fd);
|
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->controllers);
|
||||||
strv_free(m->reset_controllers);
|
strv_free(m->reset_controllers);
|
||||||
strv_free(m->kill_only_users);
|
strv_free(m->kill_only_users);
|
||||||
@@ -948,20 +953,28 @@ int manager_spawn_autovt(Manager *m, int vtnr) {
|
|||||||
assert(m);
|
assert(m);
|
||||||
assert(vtnr >= 1);
|
assert(vtnr >= 1);
|
||||||
|
|
||||||
if ((unsigned) vtnr > m->n_autovts)
|
if ((unsigned) vtnr > m->n_autovts &&
|
||||||
|
(unsigned) vtnr != m->reserve_vt)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
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);
|
r = vt_is_busy(vtnr);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
else if (r > 0)
|
else if (r > 0)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
if (asprintf(&name, "autovt@tty%i.service", vtnr) < 0) {
|
if (asprintf(&name, "autovt@tty%i.service", vtnr) < 0) {
|
||||||
log_error("Could not allocate service name.");
|
log_error("Could not allocate service name.");
|
||||||
r = -ENOMEM;
|
r = -ENOMEM;
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = bus_method_call_with_reply (
|
r = bus_method_call_with_reply (
|
||||||
m->bus,
|
m->bus,
|
||||||
"org.freedesktop.systemd1",
|
"org.freedesktop.systemd1",
|
||||||
@@ -980,6 +993,26 @@ finish:
|
|||||||
return r;
|
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) {
|
int manager_get_session_by_cgroup(Manager *m, const char *cgroup, Session **session) {
|
||||||
Session *s;
|
Session *s;
|
||||||
char *p;
|
char *p;
|
||||||
@@ -1450,6 +1483,9 @@ int manager_startup(Manager *m) {
|
|||||||
/* Remove stale objects before we start them */
|
/* Remove stale objects before we start them */
|
||||||
manager_gc(m, false);
|
manager_gc(m, false);
|
||||||
|
|
||||||
|
/* Reserve the special reserved VT */
|
||||||
|
manager_reserve_vt(m);
|
||||||
|
|
||||||
/* And start everything */
|
/* And start everything */
|
||||||
HASHMAP_FOREACH(seat, m->seats, i)
|
HASHMAP_FOREACH(seat, m->seats, i)
|
||||||
seat_start(seat);
|
seat_start(seat);
|
||||||
|
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
[Login]
|
[Login]
|
||||||
#NAutoVTs=6
|
#NAutoVTs=6
|
||||||
|
#ReserveVT=6
|
||||||
#KillUserProcesses=no
|
#KillUserProcesses=no
|
||||||
#KillOnlyUsers=
|
#KillOnlyUsers=
|
||||||
#KillExcludeUsers=root
|
#KillExcludeUsers=root
|
||||||
|
@@ -68,6 +68,9 @@ struct Manager {
|
|||||||
|
|
||||||
unsigned n_autovts;
|
unsigned n_autovts;
|
||||||
|
|
||||||
|
unsigned reserve_vt;
|
||||||
|
int reserve_vt_fd;
|
||||||
|
|
||||||
Seat *vtconsole;
|
Seat *vtconsole;
|
||||||
|
|
||||||
char *cgroup_path;
|
char *cgroup_path;
|
||||||
|
Reference in New Issue
Block a user