@@ -24,11 +24,11 @@
previous logins. */
struct lastlog
{
-#if __WORDSIZE_TIME64_COMPAT32
- int32_t ll_time;
+#if __WORDSIZE == 32
+ int64_t ll_time;
#else
__time_t ll_time;
#endif
- char ll_line[UT_LINESIZE];
- char ll_host[UT_HOSTSIZE];
+ char ll_line[UT_LINESIZE] __attribute_nonstring__;
+ char ll_host[UT_HOSTSIZE] __attribute_nonstring__;
};
@@ -31,7 +31,8 @@ headers := utmp.h bits/utmp.h lastlog.h pty.h \
routines := getlogin getlogin_r setlogin getlogin_r_chk \
getutent getutent_r getutid getutline getutid_r getutline_r \
utmp_file utmpname updwtmp getpt grantpt unlockpt ptsname \
- ptsname_r_chk utmp32 utmpx32 utmp-convert
+ ptsname_r_chk utmp32 utmpx32 utmp-convert \
+ lastlog_read lastlog_write
CFLAGS-grantpt.c += -DLIBEXECDIR='"$(libexecdir)"'
@@ -50,7 +51,7 @@ tests := tst-utmp tst-utmpx tst-grantpt tst-ptsname tst-getlogin tst-updwtmpx \
tst-pututxline-lockfail tst-pututxline-cache
tests-internal := tst-utmp32
-tests-container := tst-utmp32 tst-utmp-default
+tests-container := tst-utmp32 tst-utmp-default tst-lastlog
# Build the -lutil library with these extra functions.
extra-libs := libutil
@@ -45,6 +45,9 @@ libc {
__getlogin_r_chk;
__ptsname_r_chk;
}
+ GLIBC_2.33 {
+ lastlog_read; lastlog_write;
+ }
GLIBC_PRIVATE {
# Used on compat login from libutil.
__utmp_convert32to64;
similarity index 74%
rename from sysdeps/unix/sysv/linux/s390/bits/struct_lastlog.h
rename to login/lastlog-compat.h
@@ -1,4 +1,4 @@
-/* The 'struct lastlog' type.
+/* Compat lastlog definitions.
Copyright (C) 2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
@@ -16,19 +16,22 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#ifndef _UTMP_H
-# error "Never include <bits/struct_lastlog.h> directly; use <utmp.h> instead."
-#endif
+#ifndef _LASTLOG_COMPAT_H
+#define _LASTLOG_COMPAT_H 1
+
+#include <string.h>
-/* The structure describing an entry in the database of
- previous logins. */
-struct lastlog
+struct lastlog_compat
{
-#if __WORDSIZE == 32
- int64_t ll_time;
-#else
- __time_t ll_time;
-#endif
+ int32_t ll_time;
char ll_line[UT_LINESIZE];
char ll_host[UT_HOSTSIZE];
};
+
+static inline bool
+is_path_lastlog_compat (const char *file)
+{
+ return strcmp (file, "/var/log/lastlog") == 0;
+}
+
+#endif
new file mode 100644
@@ -0,0 +1,71 @@
+/* Read a lastlog entry.
+ Copyright (C) 2020 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <utmp.h>
+#include <stdbool.h>
+#include <not-cancel.h>
+#include <lastlog-compat.h>
+
+ssize_t
+lastlog_read (const char *file, uid_t uid, struct lastlog *ll)
+{
+ int fd = __open_nocancel (file, O_RDONLY | O_LARGEFILE | O_CLOEXEC);
+ if (fd == -1)
+ return -1;
+
+ size_t llsize;
+ struct lastlog_compat llcompat;
+ void *data;
+
+ if (is_path_lastlog_compat (file))
+ {
+ llsize = sizeof (struct lastlog_compat);
+ data = &llcompat;
+ }
+ else
+ {
+ llsize = sizeof (struct lastlog);
+ data = ll;
+ }
+
+ off64_t off = llsize * uid;
+ ssize_t r = __pread64_nocancel (fd, data, llsize, off);
+ __close_nocancel_nostatus (fd);
+
+ if (r == llsize && data == &llcompat)
+ {
+ ll->ll_time = llcompat.ll_time;
+ memcpy (ll->ll_line, llcompat.ll_line, UT_LINESIZE);
+ memcpy (ll->ll_host, llcompat.ll_host, UT_HOSTSIZE);
+ }
+
+ if (r == llsize)
+ {
+ if (data == &llcompat)
+ {
+ ll->ll_time = llcompat.ll_time;
+ memcpy (ll->ll_line, llcompat.ll_line, UT_LINESIZE);
+ memcpy (ll->ll_host, llcompat.ll_host, UT_HOSTSIZE);
+ }
+ /* We need to return the expected 'struct lastlog' size in case of
+ success. */
+ r = sizeof (struct lastlog);
+ }
+
+ return r;
+}
new file mode 100644
@@ -0,0 +1,59 @@
+/* Write a lastlog entry.
+ Copyright (C) 2020 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <utmp.h>
+#include <stdbool.h>
+#include <not-cancel.h>
+#include <lastlog-compat.h>
+
+ssize_t
+lastlog_write (const char *file, uid_t uid, const struct lastlog *ll)
+{
+ int fd = __open_nocancel (file, O_WRONLY | O_LARGEFILE | O_CLOEXEC);
+ if (fd == -1)
+ return -1;
+
+ size_t llsize;
+ struct lastlog_compat llcompat;
+ const void *data;
+
+ if (is_path_lastlog_compat (file))
+ {
+ llcompat.ll_time = ll->ll_time;
+ memcpy (llcompat.ll_line, ll->ll_line, UT_LINESIZE);
+ memcpy (llcompat.ll_host, ll->ll_host, UT_HOSTSIZE);
+ llsize = sizeof (struct lastlog_compat);
+ data = &llcompat;
+ }
+ else
+ {
+ llsize = sizeof (struct lastlog);
+ data = ll;
+ }
+
+ off64_t off = llsize * uid;
+ ssize_t r = __pwrite64_nocancel (fd, data, llsize, off);
+ __close_nocancel_nostatus (fd);
+
+ /* We need to return the expected 'struct lastlog' size in case of
+ success. */
+ if (r == llsize && data == &llcompat)
+ r = sizeof (struct lastlog);
+
+ return r;
+}
new file mode 100644
@@ -0,0 +1,79 @@
+/* Tests for lastlog read/write functions.
+ Copyright (C) 2020 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdlib.h>
+#include <string.h>
+#include <utmp.h>
+
+#include <support/check.h>
+#include <support/temp_file.h>
+
+#include <stdio.h>
+
+static struct
+{
+ uid_t uid;
+ struct lastlog ll;
+} entry[] =
+{
+ { 0, { .ll_time = 1000, .ll_line = "tty1" } },
+ { 1000, { .ll_time = 2000, .ll_line = "pts/0", .ll_host = "127.0.0.1" } },
+ { 20, { .ll_time = 3000, .ll_line = "pts/1", .ll_host = "192.168.0.1" } },
+ { 30, { .ll_time = 4000, .ll_line = "tty2" } },
+};
+const size_t entry_size = sizeof (entry) / sizeof (entry[0]);
+
+static void
+run_test (const char *filename)
+{
+ for (int n = 0; n < entry_size; n++)
+ TEST_COMPARE (lastlog_write (filename, entry[n].uid, &entry[n].ll),
+ sizeof (struct lastlog));
+
+ for (int n = 0; n < entry_size; n++)
+ {
+ struct lastlog ll;
+ TEST_COMPARE (lastlog_read (filename, entry[n].uid, &ll),
+ sizeof (struct lastlog));
+ TEST_COMPARE (ll.ll_time, entry[n].ll.ll_time);
+ TEST_COMPARE_BLOB (ll.ll_line, UT_LINESIZE,
+ entry[n].ll.ll_line, UT_LINESIZE);
+ TEST_COMPARE_BLOB (ll.ll_host, UT_HOSTSIZE,
+ entry[n].ll.ll_host, UT_HOSTSIZE);
+ }
+
+ /* Check with an non present uid. */
+ {
+ struct lastlog ll;
+ TEST_COMPARE (lastlog_read (filename, 4000, &ll), 0);
+ }
+}
+
+static int
+do_test (void)
+{
+ /* The path triggers the read/write of compat (32-bit ll_time) entries. */
+ run_test ("/var/run/lastlog");
+
+ /* Any other file handles new (64-bit ll_time) entries. */
+ run_test ("/var/run/lastlog.v2");
+
+ return 0;
+}
+
+#include <support/test-driver.c>
new file mode 100644
@@ -0,0 +1,6 @@
+mkdirp 0755 /var/run
+touch 0664 /var/run/lastlog
+touch 0664 /var/run/lastlog.v2
+
+# Must run localedef as root to write into default paths.
+su
@@ -91,6 +91,17 @@ extern int getutline_r (const struct utmp *__line,
#endif /* Use misc. */
+#ifdef __USE_GNU
+/* Read the struct lastlog LL with UID from file FILE. */
+extern ssize_t lastlog_read (const char *__file, uid_t __uid,
+ struct lastlog *__ll)
+ __THROW __nonnull ((1, 3));
+/* Write the struct lastlog LL with UID from file FILE. */
+extern ssize_t lastlog_write (const char *__file, uid_t __uid,
+ const struct lastlog *__ll)
+ __THROW __nonnull ((1, 3));
+#endif
+
__END_DECLS
#endif /* utmp.h */
@@ -46,7 +46,8 @@
#define _PATH_DRUM "/dev/drum"
#define _PATH_GSHADOW "/etc/gshadow"
#define _PATH_KMEM "/dev/kmem"
-#define _PATH_LASTLOG "/var/log/lastlog"
+#define _PATH_LASTLOG_VER ".v2"
+#define _PATH_LASTLOG "/var/log/lastlog" _PATH_LASTLOG_VER
#define _PATH_MAILDIR "/var/mail"
#define _PATH_MAN "/usr/share/man"
#define _PATH_MEM "/dev/mem"
@@ -2207,6 +2207,8 @@ GLIBC_2.33 getutmpx F
GLIBC_2.33 getutxent F
GLIBC_2.33 getutxid F
GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
GLIBC_2.33 lstat F
GLIBC_2.33 lstat64 F
GLIBC_2.33 mknod F
@@ -2175,6 +2175,8 @@ GLIBC_2.33 getutmpx F
GLIBC_2.33 getutxent F
GLIBC_2.33 getutxid F
GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
GLIBC_2.33 lstat F
GLIBC_2.33 lstat64 F
GLIBC_2.33 mknod F
@@ -2257,6 +2257,8 @@ GLIBC_2.33 getutmpx F
GLIBC_2.33 getutxent F
GLIBC_2.33 getutxid F
GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
GLIBC_2.33 lstat F
GLIBC_2.33 lstat64 F
GLIBC_2.33 mknod F
@@ -1935,6 +1935,8 @@ GLIBC_2.33 getutmpx F
GLIBC_2.33 getutxent F
GLIBC_2.33 getutxid F
GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
GLIBC_2.33 lstat F
GLIBC_2.33 lstat64 F
GLIBC_2.33 mknod F
@@ -156,6 +156,8 @@ GLIBC_2.33 getutmpx F
GLIBC_2.33 getutxent F
GLIBC_2.33 getutxid F
GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
GLIBC_2.33 lstat F
GLIBC_2.33 lstat64 F
GLIBC_2.33 mknod F
@@ -2119,6 +2119,8 @@ GLIBC_2.33 getutmpx F
GLIBC_2.33 getutxent F
GLIBC_2.33 getutxid F
GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
GLIBC_2.33 lstat F
GLIBC_2.33 lstat64 F
GLIBC_2.33 mknod F
@@ -2078,6 +2078,8 @@ GLIBC_2.33 getutmpx F
GLIBC_2.33 getutxent F
GLIBC_2.33 getutxid F
GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
GLIBC_2.33 lstat F
GLIBC_2.33 lstat64 F
GLIBC_2.33 mknod F
@@ -2244,6 +2244,8 @@ GLIBC_2.33 getutmpx F
GLIBC_2.33 getutxent F
GLIBC_2.33 getutxid F
GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
GLIBC_2.33 lstat F
GLIBC_2.33 lstat64 F
GLIBC_2.33 mknod F
@@ -2110,6 +2110,8 @@ GLIBC_2.33 getutmpx F
GLIBC_2.33 getutxent F
GLIBC_2.33 getutxid F
GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
GLIBC_2.33 lstat F
GLIBC_2.33 lstat64 F
GLIBC_2.33 mknod F
@@ -2190,6 +2190,8 @@ GLIBC_2.33 getutmpx F
GLIBC_2.33 getutxent F
GLIBC_2.33 getutxid F
GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
GLIBC_2.33 lstat F
GLIBC_2.33 lstat64 F
GLIBC_2.33 mknod F
@@ -2170,6 +2170,8 @@ GLIBC_2.33 getutmpx F
GLIBC_2.33 getutxent F
GLIBC_2.33 getutxid F
GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
GLIBC_2.33 lstat F
GLIBC_2.33 lstat64 F
GLIBC_2.33 mknod F
@@ -2161,6 +2161,8 @@ GLIBC_2.33 getutmpx F
GLIBC_2.33 getutxent F
GLIBC_2.33 getutxid F
GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
GLIBC_2.33 lstat F
GLIBC_2.33 lstat64 F
GLIBC_2.33 mknod F
@@ -2167,6 +2167,8 @@ GLIBC_2.33 getutmpx F
GLIBC_2.33 getutxent F
GLIBC_2.33 getutxid F
GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
GLIBC_2.33 lstat F
GLIBC_2.33 lstat64 F
GLIBC_2.33 mknod F
@@ -2161,6 +2161,8 @@ GLIBC_2.33 getutmpx F
GLIBC_2.33 getutxent F
GLIBC_2.33 getutxid F
GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
GLIBC_2.33 lstat F
GLIBC_2.33 lstat64 F
GLIBC_2.33 mknod F
@@ -2208,6 +2208,8 @@ GLIBC_2.33 getutmpx F
GLIBC_2.33 getutxent F
GLIBC_2.33 getutxid F
GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
GLIBC_2.33 lstat F
GLIBC_2.33 lstat64 F
GLIBC_2.33 mknod F
@@ -47,7 +47,8 @@
#define _PATH_GSHADOW "/etc/gshadow"
#define _PATH_KLOG "/proc/kmsg"
#define _PATH_KMEM "/dev/kmem"
-#define _PATH_LASTLOG "/var/log/lastlog"
+#define _PATH_LASTLOG_VER ".v2"
+#define _PATH_LASTLOG "/var/log/lastlog" _PATH_LASTLOG_VER
#define _PATH_MAILDIR "/var/mail"
#define _PATH_MAN "/usr/share/man"
#define _PATH_MEM "/dev/mem"
@@ -2217,6 +2217,8 @@ GLIBC_2.33 getutmpx F
GLIBC_2.33 getutxent F
GLIBC_2.33 getutxid F
GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
GLIBC_2.33 lstat F
GLIBC_2.33 lstat64 F
GLIBC_2.33 mknod F
@@ -2080,6 +2080,8 @@ GLIBC_2.33 getutmpx F
GLIBC_2.33 getutxent F
GLIBC_2.33 getutxid F
GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
GLIBC_2.33 lstat F
GLIBC_2.33 lstat64 F
GLIBC_2.33 mknod F
@@ -2370,6 +2370,8 @@ GLIBC_2.33 getutmpx F
GLIBC_2.33 getutxent F
GLIBC_2.33 getutxid F
GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
GLIBC_2.33 lstat F
GLIBC_2.33 lstat64 F
GLIBC_2.33 mknod F
@@ -2137,6 +2137,8 @@ GLIBC_2.33 getutmpx F
GLIBC_2.33 getutxent F
GLIBC_2.33 getutxid F
GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
GLIBC_2.33 lstat F
GLIBC_2.33 lstat64 F
GLIBC_2.33 mknod F
new file mode 100644
@@ -0,0 +1,38 @@
+/* Compat lastlog definitions. s390 definition.
+ Copyright (C) 2020 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _LASTLOG_COMPAT_H
+#define _LASTLOG_COMPAT_H 1
+
+/* The s390 changes its lastlog to 64-bit on glibc 2.9 without any handling
+ of old format. The is_path_lastlog_compat assumes 64-bit as default. */
+
+struct lastlog_compat
+{
+ int64_t ll_time;
+ char ll_line[UT_LINESIZE];
+ char ll_host[UT_HOSTSIZE];
+};
+
+static inline bool
+is_path_lastlog_compat (const char *file)
+{
+ return false;
+}
+
+#endif
@@ -2204,6 +2204,8 @@ GLIBC_2.33 fstat F
GLIBC_2.33 fstat64 F
GLIBC_2.33 fstatat F
GLIBC_2.33 fstatat64 F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
GLIBC_2.33 lstat F
GLIBC_2.33 lstat64 F
GLIBC_2.33 mknod F
@@ -2105,6 +2105,8 @@ GLIBC_2.33 fstat F
GLIBC_2.33 fstat64 F
GLIBC_2.33 fstatat F
GLIBC_2.33 fstatat64 F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
GLIBC_2.33 lstat F
GLIBC_2.33 lstat64 F
GLIBC_2.33 mknod F
@@ -2082,6 +2082,8 @@ GLIBC_2.33 getutmpx F
GLIBC_2.33 getutxent F
GLIBC_2.33 getutxid F
GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
GLIBC_2.33 lstat F
GLIBC_2.33 lstat64 F
GLIBC_2.33 mknod F
@@ -2206,6 +2206,8 @@ GLIBC_2.33 getutmpx F
GLIBC_2.33 getutxent F
GLIBC_2.33 getutxid F
GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
GLIBC_2.33 lstat F
GLIBC_2.33 lstat64 F
GLIBC_2.33 mknod F
@@ -2133,6 +2133,8 @@ GLIBC_2.33 getutmpx F
GLIBC_2.33 getutxent F
GLIBC_2.33 getutxid F
GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
GLIBC_2.33 lstat F
GLIBC_2.33 lstat64 F
GLIBC_2.33 mknod F
@@ -2091,6 +2091,8 @@ GLIBC_2.33 getutmpx F
GLIBC_2.33 getutxent F
GLIBC_2.33 getutxid F
GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
GLIBC_2.33 lstat F
GLIBC_2.33 lstat64 F
GLIBC_2.33 mknod F
@@ -2188,6 +2188,8 @@ GLIBC_2.33 getutmpx F
GLIBC_2.33 getutxent F
GLIBC_2.33 getutxid F
GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
GLIBC_2.33 lstat F
GLIBC_2.33 lstat64 F
GLIBC_2.33 mknod F