Blame SOURCES/pam-1.3.1-lastlog-unlimited-fsize.patch

43d219
From 3a3e70739834cd5cbd17469907ef718c81ae40c0 Mon Sep 17 00:00:00 2001
43d219
From: Carlos Santos <casantos@redhat.com>
43d219
Date: Wed, 11 Sep 2019 11:50:28 -0300
43d219
Subject: [PATCH] pam_lastlog: document the 'unlimited' option
43d219
43d219
Signed-off-by: Carlos Santos <casantos@redhat.com>
43d219
---
43d219
 modules/pam_lastlog/pam_lastlog.8.xml | 18 ++++++++++++++++++
43d219
 1 file changed, 18 insertions(+)
43d219
43d219
diff --git a/modules/pam_lastlog/pam_lastlog.8.xml b/modules/pam_lastlog/pam_lastlog.8.xml
43d219
index bc2e1be..f10e94a 100644
43d219
--- a/modules/pam_lastlog/pam_lastlog.8.xml
43d219
+++ b/modules/pam_lastlog/pam_lastlog.8.xml
43d219
@@ -48,6 +48,9 @@
43d219
       <arg choice="opt">
43d219
         inactive=<days>
43d219
       </arg>
43d219
+      <arg choice="opt">
43d219
+        unlimited
43d219
+      </arg>
43d219
     </cmdsynopsis>
43d219
   </refsynopsisdiv>
43d219
 
43d219
@@ -196,6 +199,18 @@
43d219
           </para>
43d219
         </listitem>
43d219
       </varlistentry>
43d219
+      <varlistentry>
43d219
+        <term>
43d219
+          <option>unlimited</option>
43d219
+        </term>
43d219
+        <listitem>
43d219
+          <para>
43d219
+	    If the <emphasis>fsize</emphasis> limit is set, this option can be
43d219
+	    used to override it, preventing failures on systems with large UID
43d219
+	    values that lead lastlog to become a huge sparse file.
43d219
+          </para>
43d219
+        </listitem>
43d219
+      </varlistentry>
43d219
     </variablelist>
43d219
   </refsect1>
43d219
 
43d219
@@ -300,6 +315,9 @@
43d219
   <refsect1 id='pam_lastlog-see_also'>
43d219
     <title>SEE ALSO</title>
43d219
     <para>
43d219
+      <citerefentry>
43d219
+	<refentrytitle>limits.conf</refentrytitle><manvolnum>5</manvolnum>
43d219
+      </citerefentry>,
43d219
       <citerefentry>
43d219
 	<refentrytitle>pam.conf</refentrytitle><manvolnum>5</manvolnum>
43d219
       </citerefentry>,
43d219
-- 
43d219
2.20.1
43d219
43d219
From 9349333a9ae958205294cd25e97fd6b4805bd82b Mon Sep 17 00:00:00 2001
43d219
From: Carlos Santos <casantos@redhat.com>
43d219
Date: Tue, 10 Sep 2019 23:08:30 -0300
43d219
Subject: [PATCH] pam_lastlog: prevent crash due to reduced 'fsize' limit
43d219
43d219
It a reduced fsize limit is set in /etc/security/limits.conf and
43d219
pam_limits is in use pam_lastlog may cause a crash, e.g.
43d219
43d219
    ----- begin /etc/pam.d/su ----
43d219
    auth        sufficient   pam_rootok.so
43d219
    auth        required     pam_wheel.so use_uid
43d219
    auth        required     pam_env.so
43d219
    auth        required     pam_unix.so nullok
43d219
    account     required     pam_unix.so
43d219
    password    required     pam_unix.so nullok
43d219
    session     required     pam_limits.so
43d219
    session     required     pam_env.so
43d219
    session     required     pam_unix.so
43d219
    session     optional     pam_lastlog.so
43d219
    ----- end /etc/pam.d/su -----
43d219
43d219
    ----- begin /etc/security/limits.d/fsize.conf -----
43d219
    * soft fsize 1710
43d219
    * hard fsize 1710
43d219
    ----- end /etc/security/limits.d/fsize.conf -----
43d219
43d219
    # id user1
43d219
    uid=1000(user1) gid=1000(user1) groups=1000(user1)
43d219
    # su - user1
43d219
    Last login: Wed Sep 11 01:52:44 UTC 2019 on console
43d219
    $ exit
43d219
    # id user2
43d219
    uid=60000(user2) gid=60000(user2) groups=60000(user2)
43d219
    # su - user2
43d219
    File size limit exceeded
43d219
43d219
This happens because pam_limits sets RLIMIT_FSIZE before pam_lastlog
43d219
attempts to write /var/log/lastlog, leading to a SIGXFSZ signal.
43d219
43d219
In order to fix this, and an 'unlimited' option, which leads to saving
43d219
the 'fsize' limit and set it to unlimited before writing lastlog. After
43d219
that, restore the saved value. If 'fsize' is already unlimited nothing
43d219
is done.
43d219
43d219
Failing to set the 'fsize' limit is not a fatal error.  With luck the
43d219
configured limit will suffice, so we try to write lastlog anyway, even
43d219
under the risk of dying due to a SIGXFSZ.
43d219
43d219
Failing to restore the 'fsize' limit is a fatal error, since we don't
43d219
want to keep it unlimited.
43d219
43d219
Signed-off-by: Carlos Santos <casantos@redhat.com>
43d219
---
43d219
 modules/pam_lastlog/pam_lastlog.c | 66 ++++++++++++++++++++++++++-----
43d219
 1 file changed, 57 insertions(+), 9 deletions(-)
43d219
43d219
diff --git a/modules/pam_lastlog/pam_lastlog.c b/modules/pam_lastlog/pam_lastlog.c
43d219
index e980c04..a135c9f 100644
43d219
--- a/modules/pam_lastlog/pam_lastlog.c
43d219
+++ b/modules/pam_lastlog/pam_lastlog.c
43d219
@@ -25,6 +25,8 @@
43d219
 #include <stdio.h>
43d219
 #include <string.h>
43d219
 #include <sys/types.h>
43d219
+#include <sys/time.h>
43d219
+#include <sys/resource.h>
43d219
 #include <syslog.h>
43d219
 #include <unistd.h>
43d219
 
43d219
@@ -82,15 +84,16 @@ struct lastlog {
43d219
 
43d219
 /* argument parsing */
43d219
 
43d219
-#define LASTLOG_DATE        01  /* display the date of the last login */
43d219
-#define LASTLOG_HOST        02  /* display the last host used (if set) */
43d219
-#define LASTLOG_LINE        04  /* display the last terminal used */
43d219
-#define LASTLOG_NEVER      010  /* display a welcome message for first login */
43d219
-#define LASTLOG_DEBUG      020  /* send info to syslog(3) */
43d219
-#define LASTLOG_QUIET      040  /* keep quiet about things */
43d219
-#define LASTLOG_WTMP      0100  /* log to wtmp as well as lastlog */
43d219
-#define LASTLOG_BTMP      0200  /* display failed login info from btmp */
43d219
-#define LASTLOG_UPDATE    0400  /* update the lastlog and wtmp files (default) */
43d219
+#define LASTLOG_DATE          01  /* display the date of the last login */
43d219
+#define LASTLOG_HOST          02  /* display the last host used (if set) */
43d219
+#define LASTLOG_LINE          04  /* display the last terminal used */
43d219
+#define LASTLOG_NEVER        010  /* display a welcome message for first login */
43d219
+#define LASTLOG_DEBUG        020  /* send info to syslog(3) */
43d219
+#define LASTLOG_QUIET        040  /* keep quiet about things */
43d219
+#define LASTLOG_WTMP        0100  /* log to wtmp as well as lastlog */
43d219
+#define LASTLOG_BTMP        0200  /* display failed login info from btmp */
43d219
+#define LASTLOG_UPDATE      0400  /* update the lastlog and wtmp files (default) */
43d219
+#define LASTLOG_UNLIMITED  01000  /* unlimited file size (ignore 'fsize' limit) */
43d219
 
43d219
 static int
43d219
 _pam_auth_parse(pam_handle_t *pamh, int flags, int argc, const char **argv,
43d219
@@ -158,6 +161,8 @@ _pam_session_parse(pam_handle_t *pamh, int flags, int argc, const char **argv)
43d219
 	    ctrl &= ~(LASTLOG_WTMP|LASTLOG_UPDATE);
43d219
 	} else if (!strcmp(*argv,"showfailed")) {
43d219
 	    ctrl |= LASTLOG_BTMP;
43d219
+	} else if (!strcmp(*argv,"unlimited")) {
43d219
+	    ctrl |= LASTLOG_UNLIMITED;
43d219
 	} else {
43d219
 	    pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv);
43d219
 	}
43d219
@@ -373,6 +378,12 @@ static int
43d219
 last_login_write(pam_handle_t *pamh, int announce, int last_fd,
43d219
 		 uid_t uid, const char *user)
43d219
 {
43d219
+    static struct rlimit no_limit = {
43d219
+	RLIM_INFINITY,
43d219
+	RLIM_INFINITY
43d219
+    };
43d219
+    struct rlimit old_limit;
43d219
+    int setrlimit_res;
43d219
     struct flock last_lock;
43d219
     struct lastlog last_login;
43d219
     time_t ll_time;
43d219
@@ -427,6 +438,31 @@ last_login_write(pam_handle_t *pamh, int announce, int last_fd,
43d219
         sleep(LASTLOG_IGNORE_LOCK_TIME);
43d219
     }
43d219
 
43d219
+    /*
43d219
+     * Failing to set the 'fsize' limit is not a fatal error. We try to write
43d219
+     * lastlog anyway, under the risk of dying due to a SIGXFSZ.
43d219
+     */
43d219
+    D(("setting limit for 'fsize'"));
43d219
+
43d219
+    if ((announce & LASTLOG_UNLIMITED) == 0) {    /* don't set to unlimted */
43d219
+	setrlimit_res = -1;
43d219
+    } else if (getrlimit(RLIMIT_FSIZE, &old_limit) == 0) {
43d219
+	if (old_limit.rlim_cur == RLIM_INFINITY) {    /* already unlimited */
43d219
+	    setrlimit_res = -1;
43d219
+	} else {
43d219
+	    setrlimit_res = setrlimit(RLIMIT_FSIZE, &no_limit);
43d219
+	    if (setrlimit_res != 0)
43d219
+		pam_syslog(pamh, LOG_WARNING, "Could not set limit for 'fsize': %m");
43d219
+	}
43d219
+    } else {
43d219
+	setrlimit_res = -1;
43d219
+	if (errno == EINVAL) {
43d219
+	    pam_syslog(pamh, LOG_INFO, "Limit for 'fsize' not supported: %m");
43d219
+	} else {
43d219
+	    pam_syslog(pamh, LOG_WARNING, "Could not get limit for 'fsize': %m");
43d219
+	}
43d219
+    }
43d219
+
43d219
     D(("writing to the lastlog file"));
43d219
     if (pam_modutil_write (last_fd, (char *) &last_login,
43d219
 			   sizeof (last_login)) != sizeof(last_login)) {
43d219
@@ -434,6 +470,18 @@ last_login_write(pam_handle_t *pamh, int announce, int last_fd,
43d219
 	retval = PAM_SERVICE_ERR;
43d219
     }
43d219
 
43d219
+    /*
43d219
+     * Failing to restore the 'fsize' limit is a fatal error.
43d219
+     */
43d219
+    D(("restoring limit for 'fsize'"));
43d219
+    if (setrlimit_res == 0) {
43d219
+	setrlimit_res = setrlimit(RLIMIT_FSIZE, &old_limit);
43d219
+	if (setrlimit_res != 0) {
43d219
+	    pam_syslog(pamh, LOG_ERR, "Could not restore limit for 'fsize': %m");
43d219
+	    retval = PAM_SERVICE_ERR;
43d219
+	}
43d219
+    }
43d219
+
43d219
     last_lock.l_type = F_UNLCK;
43d219
     (void) fcntl(last_fd, F_SETLK, &last_lock);        /* unlock */
43d219
     D(("unlocked"));
43d219
-- 
43d219
2.20.1
43d219