Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Y2038: query systemd-logind instead of utmp for username and tty (#2088) #2100

Merged
merged 3 commits into from Aug 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions configure.ac
Expand Up @@ -2491,6 +2491,7 @@ AS_IF([test "x$with_systemd" != xno], [
[*:yes],
AC_DEFINE([HAVE_LIBSYSTEMD], [1], [Define if libsystemd is available])
AC_DEFINE([USE_SYSTEMD], [1], [Define if systemd support is wanted ])
AC_CHECK_DECLS([sd_session_get_username], [], [], [#include <systemd/sd-login.h>])
)
])
AM_CONDITIONAL([HAVE_SYSTEMD], [test "x$have_systemd" = xyes])
Expand Down
9 changes: 8 additions & 1 deletion meson.build
Expand Up @@ -311,6 +311,11 @@ lib_systemd = dependency(
required : get_option('systemd'))
conf.set('HAVE_LIBSYSTEMD', lib_systemd.found() ? 1 : false)

have = cc.has_function(
'sd_session_get_username',
dependencies : lib_systemd)
conf.set('HAVE_DECL_SD_SESSION_GET_USERNAME', have ? 1 : false)

lib_udev = dependency(
'libudev',
required : get_option('systemd'))
Expand Down Expand Up @@ -2316,7 +2321,7 @@ exe = executable(
agetty_sources,
include_directories : includes,
link_with : [lib_common, logindefs_c],
dependencies : BSD ? lib_util : [],
dependencies : [BSD ? lib_util : [], lib_systemd],
install_dir : sbindir,
install : opt,
build_by_default : opt)
Expand Down Expand Up @@ -2362,6 +2367,7 @@ exe = executable(
wall_sources,
include_directories : includes,
link_with : [lib_common],
dependencies : [lib_systemd],
install_dir : usrbin_exec_dir,
install : opt,
build_by_default : opt)
Expand All @@ -2380,6 +2386,7 @@ exe = executable(
write_sources,
include_directories : includes,
link_with : [lib_common],
dependencies : [lib_systemd],
install_dir : usrbin_exec_dir,
install : opt,
build_by_default : opt)
Expand Down
12 changes: 12 additions & 0 deletions term-utils/Makemodule.am
Expand Up @@ -58,6 +58,10 @@ endif
if HAVE_ECONF
agetty_LDADD += -leconf
endif
if HAVE_SYSTEMD
agetty_LDADD += $(SYSTEMD_LIBS)
agetty_CFLAGS = $(SYSTEMD_CFLAGS)
endif
endif # BUILD_AGETTY


Expand Down Expand Up @@ -98,6 +102,10 @@ dist_noinst_DATA += term-utils/wall.1.adoc
wall_CFLAGS = $(SUID_CFLAGS) $(AM_CFLAGS)
wall_LDFLAGS = $(SUID_LDFLAGS) $(AM_LDFLAGS)
wall_LDADD = $(LDADD) libcommon.la
if HAVE_SYSTEMD
wall_LDADD += $(SYSTEMD_LIBS)
wall_CFLAGS += $(SYSTEMD_CFLAGS)
endif
if USE_TTY_GROUP
if MAKEINSTALL_DO_CHOWN
install-exec-hook-wall::
Expand All @@ -118,6 +126,10 @@ write_SOURCES = term-utils/write.c
write_CFLAGS = $(SUID_CFLAGS) $(AM_CFLAGS)
write_LDFLAGS = $(SUID_LDFLAGS) $(AM_LDFLAGS)
write_LDADD = $(LDADD) libcommon.la
if HAVE_SYSTEMD
write_LDADD += $(SYSTEMD_LIBS)
write_CFLAGS += $(SYSTEMD_CFLAGS)
endif

if USE_TTY_GROUP
if MAKEINSTALL_DO_CHOWN
Expand Down
28 changes: 22 additions & 6 deletions term-utils/agetty.c
Expand Up @@ -73,6 +73,11 @@
# endif
#endif

#ifdef USE_SYSTEMD
# include <systemd/sd-daemon.h>
# include <systemd/sd-login.h>
#endif

#ifdef __linux__
# include <sys/kd.h>
# define USE_SYSLOG
Expand Down Expand Up @@ -2864,12 +2869,23 @@ static void output_special_char(struct issue *ie,
case 'U':
{
int users = 0;
struct utmpx *ut;
setutxent();
while ((ut = getutxent()))
if (ut->ut_type == USER_PROCESS)
users++;
endutxent();
#ifdef USE_SYSTEMD
if (sd_booted() > 0) {
users = sd_get_sessions(NULL);
thkukuk marked this conversation as resolved.
Show resolved Hide resolved
if (users < 0)
users = 0;
} else {
#endif
users = 0;
struct utmpx *ut;
setutxent();
while ((ut = getutxent()))
if (ut->ut_type == USER_PROCESS)
users++;
endutxent();
#ifdef USE_SYSTEMD
}
github-advanced-security[bot] marked this conversation as resolved.
Fixed
Show resolved Hide resolved
#endif
if (c == 'U')
fprintf(ie->output, P_("%d user", "%d users", users), users);
else
Expand Down
39 changes: 39 additions & 0 deletions term-utils/wall.c
Expand Up @@ -61,6 +61,11 @@
#include <sys/types.h>
#include <grp.h>

#if defined(USE_SYSTEMD) && HAVE_DECL_SD_SESSION_GET_USERNAME == 1
# include <systemd/sd-login.h>
# include <systemd/sd-daemon.h>
#endif

#include "nls.h"
#include "xalloc.h"
#include "strutils.h"
Expand Down Expand Up @@ -246,6 +251,37 @@ int main(int argc, char **argv)

iov.iov_base = mbuf;
iov.iov_len = mbufsize;
#if defined(USE_SYSTEMD) && HAVE_DECL_SD_SESSION_GET_USERNAME == 1
if (sd_booted() > 0) {
char **sessions_list;
int sessions;

sessions = sd_get_sessions(&sessions_list);
if (sessions < 0)
errx(EXIT_FAILURE, _("error getting sessions: %s"),
strerror(-sessions));

for (int i = 0; i < sessions; i++) {
char *name, *tty;
int r;

if ((r = sd_session_get_username(sessions_list[i], &name)) < 0)
errx(EXIT_FAILURE, _("get user name failed: %s"), strerror (-r));

if (!(group_buf && !is_gr_member(name, group_buf))) {
if (sd_session_get_tty(sessions_list[i], &tty) >= 0) {
if ((p = ttymsg(&iov, 1, tty, timeout)) != NULL)
warnx("%s", p);

free(tty);
}
}
free(name);
free(sessions_list[i]);
}
free(sessions_list);
} else {
#endif
while((utmpptr = getutxent())) {
if (!utmpptr->ut_user[0])
continue;
Expand All @@ -269,6 +305,9 @@ int main(int argc, char **argv)
warnx("%s", p);
}
endutxent();
#if defined(USE_SYSTEMD) && HAVE_DECL_SD_SESSION_GET_USERNAME == 1
}
#endif
free(mbuf);
free_group_workspace(group_buf);
exit(EXIT_SUCCESS);
Expand Down
130 changes: 119 additions & 11 deletions term-utils/write.c
Expand Up @@ -59,6 +59,11 @@
#include <unistd.h>
#include <utmpx.h>

#if defined(USE_SYSTEMD) && HAVE_DECL_SD_SESSION_GET_USERNAME == 1
# include <systemd/sd-login.h>
# include <systemd/sd-daemon.h>
#endif

#include "c.h"
#include "carefulputc.h"
#include "closestream.h"
Expand Down Expand Up @@ -131,19 +136,56 @@ static int check_utmp(const struct write_control *ctl)
{
struct utmpx *u;
int res = 1;

utmpxname(_PATH_UTMP);
setutxent();

while ((u = getutxent())) {
if (strncmp(ctl->dst_login, u->ut_user, sizeof(u->ut_user)) == 0 &&
strncmp(ctl->dst_tty_name, u->ut_line, sizeof(u->ut_line)) == 0) {
res = 0;
break;
#if defined(USE_SYSTEMD) && HAVE_DECL_SD_SESSION_GET_USERNAME == 1
if (sd_booted() > 0) {
char **sessions_list;
int sessions = sd_get_sessions(&sessions_list);
if (sessions < 0)
errx(EXIT_FAILURE, _("error getting sessions: %s"),
strerror(-sessions));

for (int i = 0; i < sessions; i++) {

char *name, *tty;
int r;

if ((r = sd_session_get_username(sessions_list[i], &name)) < 0)
errx(EXIT_FAILURE, _("get user name failed: %s"), strerror (-r));
if (sd_session_get_tty(sessions_list[i], &tty) < 0) {
free(name);
continue;
}

if (strcmp(ctl->dst_login, name) == 0 &&
strcmp(ctl->dst_tty_name, tty) == 0) {
free(name);
free(tty);
res = 0;
break;
}
free(name);
free(tty);
}
for (int i = 0; i < sessions; i++)
free(sessions_list[i]);
free(sessions_list);
} else {
#endif
utmpxname(_PATH_UTMP);
setutxent();

while ((u = getutxent())) {
if (strncmp(ctl->dst_login, u->ut_user, sizeof(u->ut_user)) == 0 &&
strncmp(ctl->dst_tty_name, u->ut_line, sizeof(u->ut_line)) == 0) {
res = 0;
break;
}
}
}

endutxent();
endutxent();
#if defined(USE_SYSTEMD) && HAVE_DECL_SD_SESSION_GET_USERNAME == 1
}
#endif
return res;
}

Expand All @@ -163,6 +205,69 @@ static void search_utmp(struct write_control *ctl)
struct utmpx *u;
time_t best_atime = 0, tty_atime;
int num_ttys = 0, valid_ttys = 0, tty_writeable = 0, user_is_me = 0;

#if defined(USE_SYSTEMD) && HAVE_DECL_SD_SESSION_GET_USERNAME == 1
if (sd_booted() > 0) {
char path[256];
char **sessions_list;
int sessions = sd_get_sessions(&sessions_list);
if (sessions < 0)
errx(EXIT_FAILURE, _("error getting sessions: %s"),
strerror(-sessions));

for (int i = 0; i < sessions; i++) {
char *name, *tty;
int r;

if ((r = sd_session_get_username(sessions_list[i], &name)) < 0)
errx(EXIT_FAILURE, _("get user name failed: %s"), strerror (-r));

if (strcmp(ctl->dst_login, name) != 0) {
free(name);
continue;
}

if (sd_session_get_tty(sessions_list[i], &tty) < 0) {
free(name);
continue;
}

num_ttys++;
snprintf(path, sizeof(path), "/dev/%s", tty);
if (check_tty(path, &tty_writeable, &tty_atime, 0)) {
/* bad term? skip */
free(name);
free(tty);
continue;
}
if (ctl->src_uid && !tty_writeable) {
/* skip ttys with msgs off */
free(name);
free(tty);
continue;
}
if (strcmp(tty, ctl->src_tty_name) == 0) {
user_is_me = 1;
free(name);
free(tty);
/* don't write to yourself */
continue;
}
valid_ttys++;
if (best_atime < tty_atime) {
best_atime = tty_atime;
free(ctl->dst_tty_path);
ctl->dst_tty_path = xstrdup(path);
ctl->dst_tty_name = ctl->dst_tty_path + 5;
}
free(name);
free(tty);
}
for (int i = 0; i < sessions; i++)
free(sessions_list[i]);
free(sessions_list);
} else {
#endif
char path[sizeof(u->ut_line) + 6];

utmpxname(_PATH_UTMP);
Expand Down Expand Up @@ -197,6 +302,9 @@ static void search_utmp(struct write_control *ctl)
}

endutxent();
#if defined(USE_SYSTEMD) && HAVE_DECL_SD_SESSION_GET_USERNAME == 1
}
#endif
if (num_ttys == 0)
errx(EXIT_FAILURE, _("%s is not logged in"), ctl->dst_login);
if (valid_ttys == 0) {
Expand Down