diff --git a/SOURCES/pam-1.3.1-authtok-verify-fix.patch b/SOURCES/pam-1.3.1-authtok-verify-fix.patch
new file mode 100644
index 0000000..6c40cdc
--- /dev/null
+++ b/SOURCES/pam-1.3.1-authtok-verify-fix.patch
@@ -0,0 +1,88 @@
+From 27d04a849fd9f9cfd4b35eb80d687817830183df Mon Sep 17 00:00:00 2001
+From: Tomas Mraz <tmraz@fedoraproject.org>
+Date: Wed, 7 Aug 2019 12:22:55 +0200
+Subject: [PATCH] pam_get_authtok_verify: Avoid duplicate password verification
+
+If password was already verified by previous modules in the stack
+it does not need to be verified by pam_get_authtok_verify either.
+
+* libpam/pam_get_authtok.c (pam_get_authtok_internal): Set the authtok_verified
+  appropriately.
+  (pam_get_authtok_verify): Do not prompt if authtok_verified is set and
+  set it when the password is verified.
+* libpam/pam_private.h: Add authtok_verified to the pam handle struct.
+* libpam/pam_start.c (pam_start): Initialize authtok_verified.
+---
+ libpam/pam_get_authtok.c | 10 ++++++++++
+ libpam/pam_private.h     |  1 +
+ libpam/pam_start.c       |  1 +
+ 3 files changed, 12 insertions(+)
+
+diff --git a/libpam/pam_get_authtok.c b/libpam/pam_get_authtok.c
+index 800c6e5..99eb25f 100644
+--- a/libpam/pam_get_authtok.c
++++ b/libpam/pam_get_authtok.c
+@@ -140,6 +140,8 @@ pam_get_authtok_internal (pam_handle_t *pamh, int item,
+     }
+   else if (chpass)
+     {
++      pamh->authtok_verified = 0;
++
+       retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp[0],
+ 			   PROMPT1, authtok_type,
+ 			   strlen (authtok_type) > 0?" ":"");
+@@ -184,6 +186,9 @@ pam_get_authtok_internal (pam_handle_t *pamh, int item,
+   if (retval != PAM_SUCCESS)
+     return retval;
+ 
++  if (chpass > 1)
++    pamh->authtok_verified = 1;
++
+   return pam_get_item(pamh, item, (const void **)authtok);
+ }
+ 
+@@ -214,6 +219,9 @@ pam_get_authtok_verify (pam_handle_t *pamh, const char **authtok,
+   if (authtok == NULL || pamh->choice != PAM_CHAUTHTOK)
+     return PAM_SYSTEM_ERR;
+ 
++  if (pamh->authtok_verified)
++    return pam_get_item (pamh, PAM_AUTHTOK, (const void **)authtok);
++
+   if (prompt != NULL)
+     {
+       retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp,
+@@ -252,5 +260,7 @@ pam_get_authtok_verify (pam_handle_t *pamh, const char **authtok,
+   if (retval != PAM_SUCCESS)
+     return retval;
+ 
++  pamh->authtok_verified = 1;
++
+   return pam_get_item(pamh, PAM_AUTHTOK, (const void **)authtok);
+ }
+diff --git a/libpam/pam_private.h b/libpam/pam_private.h
+index 7ff9f75..58a26f5 100644
+--- a/libpam/pam_private.h
++++ b/libpam/pam_private.h
+@@ -172,6 +172,7 @@ struct pam_handle {
+ #ifdef HAVE_LIBAUDIT
+     int audit_state;             /* keep track of reported audit messages */
+ #endif
++    int authtok_verified;
+ };
+ 
+ /* Values for select arg to _pam_dispatch() */
+diff --git a/libpam/pam_start.c b/libpam/pam_start.c
+index 328416d..e27c64b 100644
+--- a/libpam/pam_start.c
++++ b/libpam/pam_start.c
+@@ -94,6 +94,7 @@ int pam_start (
+ #endif
+     (*pamh)->xdisplay = NULL;
+     (*pamh)->authtok_type = NULL;
++    (*pamh)->authtok_verified = 0;
+     memset (&((*pamh)->xauth), 0, sizeof ((*pamh)->xauth));
+ 
+     if (((*pamh)->pam_conversation = (struct pam_conv *)
+-- 
+2.20.1
+
diff --git a/SOURCES/pam-1.3.1-faillock-update.patch b/SOURCES/pam-1.3.1-faillock-update.patch
new file mode 100644
index 0000000..c001f48
--- /dev/null
+++ b/SOURCES/pam-1.3.1-faillock-update.patch
@@ -0,0 +1,1186 @@
+diff -up Linux-PAM-1.3.1/modules/pam_faillock/faillock.c.faillock-update Linux-PAM-1.3.1/modules/pam_faillock/faillock.c
+--- Linux-PAM-1.3.1/modules/pam_faillock/faillock.c.faillock-update	2019-10-16 16:49:27.026893768 +0200
++++ Linux-PAM-1.3.1/modules/pam_faillock/faillock.c	2019-12-16 17:55:27.042001068 +0100
+@@ -1,5 +1,6 @@
+ /*
+  * Copyright (c) 2010 Tomas Mraz <tmraz@redhat.com>
++ * Copyright (c) 2010, 2016, 2017 Red Hat, Inc.
+  *
+  * Redistribution and use in source and binary forms, with or without
+  * modification, are permitted provided that the following conditions
+@@ -47,6 +48,8 @@
+ 
+ #include "faillock.h"
+ 
++#define ignore_return(x) if (1==((int)x)) {;}
++
+ int
+ open_tally (const char *dir, const char *user, uid_t uid, int create)
+ {
+@@ -54,7 +57,7 @@ open_tally (const char *dir, const char
+ 	int flags = O_RDWR;
+ 	int fd;
+ 
+-	if (strstr(user, "../") != NULL)
++	if (dir == NULL || strstr(user, "../") != NULL)
+ 	/* just a defensive programming as the user must be a
+ 	 * valid user on the system anyway
+ 	 */
+@@ -83,7 +86,7 @@ open_tally (const char *dir, const char
+ 		while (flock(fd, LOCK_EX) == -1 && errno == EINTR);
+ 		if (fstat(fd, &st) == 0) {
+ 			if (st.st_uid != uid) {
+-				fchown(fd, uid, -1);
++				ignore_return(fchown(fd, uid, -1));
+ 			}
+ 		}
+ 	}
+@@ -121,7 +124,7 @@ read_tally(int fd, struct tally_data *ta
+ 		if (count >= MAX_RECORDS)
+ 			break;
+ 	}
+-	while (chunk == CHUNK_SIZE); 
++	while (chunk == CHUNK_SIZE);
+ 
+ 	tallies->records = data;
+ 	tallies->count = count;
+diff -up Linux-PAM-1.3.1/modules/pam_faillock/faillock.conf.5.xml.faillock-update Linux-PAM-1.3.1/modules/pam_faillock/faillock.conf.5.xml
+--- Linux-PAM-1.3.1/modules/pam_faillock/faillock.conf.5.xml.faillock-update	2019-10-16 17:34:58.073276020 +0200
++++ Linux-PAM-1.3.1/modules/pam_faillock/faillock.conf.5.xml	2019-10-16 16:26:05.000000000 +0200
+@@ -0,0 +1,243 @@
++<?xml version="1.0" encoding='UTF-8'?>
++<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
++	"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">
++
++<refentry id="faillock.conf">
++
++  <refmeta>
++    <refentrytitle>faillock.conf</refentrytitle>
++    <manvolnum>5</manvolnum>
++    <refmiscinfo class="sectdesc">Linux-PAM Manual</refmiscinfo>
++  </refmeta>
++
++  <refnamediv id="faillock.conf-name">
++    <refname>faillock.conf</refname>
++    <refpurpose>pam_faillock configuration file</refpurpose>
++  </refnamediv>
++
++  <refsect1 id="faillock.conf-description">
++
++    <title>DESCRIPTION</title>
++    <para>
++       <emphasis remap='B'>faillock.conf</emphasis> provides a way to configure the
++       default settings for locking the user after multiple failed authentication attempts.
++       This file is read by the <emphasis>pam_faillock</emphasis> module and is the
++       preferred method over configuring <emphasis>pam_faillock</emphasis> directly.
++    </para>
++    <para>
++       The file has a very simple <emphasis>name = value</emphasis> format with possible comments
++       starting with <emphasis>#</emphasis> character. The whitespace at the beginning of line, end
++       of line, and around the <emphasis>=</emphasis> sign is ignored.
++    </para>
++  </refsect1>
++
++  <refsect1 id="faillock.conf-options">
++
++    <title>OPTIONS</title>
++         <variablelist>
++            <varlistentry>
++              <term>
++                <option>dir=<replaceable>/path/to/tally-directory</replaceable></option>
++              </term>
++              <listitem>
++                <para>
++                  The directory where the user files with the failure records are kept. The
++                  default is <filename>/var/run/faillock</filename>.
++                </para>
++              </listitem>
++            </varlistentry>
++            <varlistentry>
++              <term>
++                <option>audit</option>
++              </term>
++              <listitem>
++                <para>
++                  Will log the user name into the system log if the user is not found.
++                </para>
++              </listitem>
++            </varlistentry>
++            <varlistentry>
++              <term>
++                <option>silent</option>
++              </term>
++              <listitem>
++                <para>
++                  Don't print informative messages to the user. Please note that when
++                  this option is not used there will be difference in the authentication
++                  behavior for users which exist on the system and non-existing users.
++                </para>
++              </listitem>
++            </varlistentry>
++            <varlistentry>
++              <term>
++                <option>no_log_info</option>
++              </term>
++              <listitem>
++                <para>
++                  Don't log informative messages via <citerefentry><refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
++                </para>
++              </listitem>
++            </varlistentry>
++            <varlistentry>
++              <term>
++                <option>local_users_only</option>
++              </term>
++              <listitem>
++                <para>
++                  Only track failed user authentications attempts for local users
++                  in /etc/passwd and ignore centralized (AD, IdM, LDAP, etc.) users.
++                  The <citerefentry><refentrytitle>faillock</refentrytitle><manvolnum>8</manvolnum></citerefentry>
++                  command will also no longer track user failed
++                  authentication attempts. Enabling this option will prevent a
++                  double-lockout scenario where a user is locked out locally and
++                  in the centralized mechanism.
++                </para>
++              </listitem>
++            </varlistentry>
++            <varlistentry>
++              <term>
++                <option>deny=<replaceable>n</replaceable></option>
++              </term>
++              <listitem>
++                <para>
++                  Deny access if the number of consecutive authentication failures
++                  for this user during the recent interval exceeds
++                  <replaceable>n</replaceable>. The default is 3.
++                </para>
++              </listitem>
++            </varlistentry>
++            <varlistentry>
++              <term>
++                <option>fail_interval=<replaceable>n</replaceable></option>
++              </term>
++              <listitem>
++                <para>
++                  The length of the interval during which the consecutive
++                  authentication failures must happen for the user account
++                  lock out is <replaceable>n</replaceable> seconds.
++                  The default is 900 (15 minutes).
++                </para>
++              </listitem>
++            </varlistentry>
++            <varlistentry>
++              <term>
++                <option>unlock_time=<replaceable>n</replaceable></option>
++              </term>
++              <listitem>
++                <para>
++                  The access will be reenabled after
++                  <replaceable>n</replaceable> seconds after the lock out.
++                  The value 0 has the same meaning as value
++                  <emphasis>never</emphasis> - the access
++                  will not be reenabled without resetting the faillock
++                  entries by the <citerefentry><refentrytitle>faillock</refentrytitle><manvolnum>8</manvolnum></citerefentry> command.
++                  The default is 600 (10 minutes).
++                </para>
++                <para>
++                  Note that the default directory that <emphasis>pam_faillock</emphasis>
++                  uses is usually cleared on system boot so the access will be also reenabled
++                  after system reboot. If that is undesirable a different tally directory
++                  must be set with the <option>dir</option> option.
++                </para>
++                <para>
++                  Also note that it is usually undesirable to permanently lock
++                  out the users as they can become easily a target of denial of service
++                  attack unless the usernames are random and kept secret to potential
++                  attackers.
++                </para>
++              </listitem>
++            </varlistentry>
++            <varlistentry>
++              <term>
++                <option>even_deny_root</option>
++              </term>
++              <listitem>
++                <para>
++                  Root account can become locked as well as regular accounts.
++                </para>
++              </listitem>
++            </varlistentry>
++            <varlistentry>
++              <term>
++                <option>root_unlock_time=<replaceable>n</replaceable></option>
++              </term>
++              <listitem>
++                <para>
++                  This option implies <option>even_deny_root</option> option.
++                  Allow access after <replaceable>n</replaceable> seconds
++                  to root account after the account is locked. In case the
++                  option is not specified the value is the same as of the
++                  <option>unlock_time</option> option.
++                </para>
++              </listitem>
++            </varlistentry>
++            <varlistentry>
++              <term>
++                <option>admin_group=<replaceable>name</replaceable></option>
++              </term>
++              <listitem>
++                <para>
++                  If a group name is specified with this option, members
++                  of the group will be handled by this module the same as
++                  the root account (the options <option>even_deny_root</option>
++                  and <option>root_unlock_time</option> will apply to them.
++                  By default the option is not set.
++                </para>
++              </listitem>
++            </varlistentry>
++        </variablelist>
++  </refsect1>
++
++  <refsect1 id='faillock.conf-examples'>
++    <title>EXAMPLES</title>
++    <para>
++      /etc/security/faillock.conf file example:
++    </para>
++    <programlisting>
++deny=4
++unlock_time=1200
++silent
++    </programlisting>
++  </refsect1>
++
++  <refsect1 id="faillock.conf-files">
++    <title>FILES</title>
++    <variablelist>
++      <varlistentry>
++        <term><filename>/etc/security/faillock.conf</filename></term>
++        <listitem>
++          <para>the config file for custom options</para>
++        </listitem>
++      </varlistentry>
++    </variablelist>
++  </refsect1>
++
++  <refsect1 id='faillock.conf-see_also'>
++    <title>SEE ALSO</title>
++    <para>
++      <citerefentry>
++        <refentrytitle>faillock</refentrytitle><manvolnum>8</manvolnum>
++      </citerefentry>,
++      <citerefentry>
++        <refentrytitle>pam_faillock</refentrytitle><manvolnum>8</manvolnum>
++      </citerefentry>,
++      <citerefentry>
++        <refentrytitle>pam.conf</refentrytitle><manvolnum>5</manvolnum>
++      </citerefentry>,
++      <citerefentry>
++        <refentrytitle>pam.d</refentrytitle><manvolnum>5</manvolnum>
++      </citerefentry>,
++      <citerefentry>
++        <refentrytitle>pam</refentrytitle><manvolnum>8</manvolnum>
++      </citerefentry>
++    </para>
++  </refsect1>
++
++  <refsect1 id='faillock.conf-author'>
++    <title>AUTHOR</title>
++      <para>
++        pam_faillock was written by Tomas Mraz. The support for faillock.conf was written by Brian Ward.
++      </para>
++  </refsect1>
++
++</refentry>
+diff -up Linux-PAM-1.3.1/modules/pam_faillock/faillock.conf.faillock-update Linux-PAM-1.3.1/modules/pam_faillock/faillock.conf
+--- Linux-PAM-1.3.1/modules/pam_faillock/faillock.conf.faillock-update	2019-10-16 17:34:50.607405060 +0200
++++ Linux-PAM-1.3.1/modules/pam_faillock/faillock.conf	2019-10-16 16:26:05.000000000 +0200
+@@ -0,0 +1,62 @@
++# Configuration for locking the user after multiple failed
++# authentication attempts.
++#
++# The directory where the user files with the failure records are kept.
++# The default is /var/run/faillock.
++# dir = /var/run/faillock
++#
++# Will log the user name into the system log if the user is not found.
++# Enabled if option is present.
++# audit
++#
++# Don't print informative messages.
++# Enabled if option is present.
++# silent
++#
++# Don't log informative messages via syslog.
++# Enabled if option is present.
++# no_log_info
++#
++# Only track failed user authentications attempts for local users
++# in /etc/passwd and ignore centralized (AD, IdM, LDAP, etc.) users.
++# The `faillock` command will also no longer track user failed
++# authentication attempts. Enabling this option will prevent a
++# double-lockout scenario where a user is locked out locally and
++# in the centralized mechanism.
++# Enabled if option is present.
++# local_users_only
++#
++# Deny access if the number of consecutive authentication failures
++# for this user during the recent interval exceeds n tries.
++# The default is 3.
++# deny = 3
++#
++# The length of the interval during which the consecutive
++# authentication failures must happen for the user account
++# lock out is <replaceable>n</replaceable> seconds.
++# The default is 900 (15 minutes).
++# fail_interval = 900
++#
++# The access will be reenabled after n seconds after the lock out.
++# The value 0 has the same meaning as value `never` - the access
++# will not be reenabled without resetting the faillock
++# entries by the `faillock` command.
++# The default is 600 (10 minutes).
++# unlock_time = 600
++#
++# Root account can become locked as well as regular accounts.
++# Enabled if option is present.
++# even_deny_root
++#
++# This option implies the `even_deny_root` option.
++# Allow access after n seconds to root account after the
++# account is locked. In case the option is not specified
++# the value is the same as of the `unlock_time` option.
++# root_unlock_time = 900
++#
++# If a group name is specified with this option, members
++# of the group will be handled by this module the same as
++# the root account (the options `even_deny_root>` and
++# `root_unlock_time` will apply to them.
++# By default, the option is not set.
++# admin_group = <admin_group_name>
+diff -up Linux-PAM-1.3.1/modules/pam_faillock/faillock.h.faillock-update Linux-PAM-1.3.1/modules/pam_faillock/faillock.h
+--- Linux-PAM-1.3.1/modules/pam_faillock/faillock.h.faillock-update	2019-10-16 16:49:27.026893768 +0200
++++ Linux-PAM-1.3.1/modules/pam_faillock/faillock.h	2019-10-16 16:51:40.431628566 +0200
+@@ -65,6 +65,7 @@ struct tally_data {
+ };
+ 
+ #define FAILLOCK_DEFAULT_TALLYDIR "/var/run/faillock"
++#define FAILLOCK_DEFAULT_CONF "/etc/security/faillock.conf"
+ 
+ int open_tally(const char *dir, const char *user, uid_t uid, int create);
+ int read_tally(int fd, struct tally_data *tallies);
+diff -up Linux-PAM-1.3.1/modules/pam_faillock/Makefile.am.faillock-update Linux-PAM-1.3.1/modules/pam_faillock/Makefile.am
+--- Linux-PAM-1.3.1/modules/pam_faillock/Makefile.am.faillock-update	2019-10-16 16:49:27.026893768 +0200
++++ Linux-PAM-1.3.1/modules/pam_faillock/Makefile.am	2019-10-16 16:50:15.065078080 +0200
+@@ -1,6 +1,6 @@
+ #
+ # Copyright (c) 2005, 2006, 2007, 2009 Thorsten Kukuk <kukuk@thkukuk.de>
+-# Copyright (c) 2008 Red Hat, Inc.
++# Copyright (c) 2008, 2018 Red Hat, Inc.
+ # Copyright (c) 2010 Tomas Mraz <tmraz@redhat.com>
+ #
+ 
+@@ -9,8 +9,8 @@ MAINTAINERCLEANFILES = $(MANS) README
+ 
+ EXTRA_DIST = README $(MANS) $(XMLS) tst-pam_faillock
+ 
+-man_MANS = pam_faillock.8 faillock.8
+-XMLS = README.xml pam_faillock.8.xml faillock.8.xml
++man_MANS = pam_faillock.8 faillock.8 faillock.conf.5
++XMLS = README.xml pam_faillock.8.xml faillock.8.xml faillock.conf.5.xml
+ 
+ TESTS = tst-pam_faillock
+ 
+@@ -31,6 +31,8 @@ endif
+ faillock_LDFLAGS = -Wl,-z,now @PIE_LDFLAGS@
+ faillock_LDADD = -L$(top_builddir)/libpam -lpam $(LIBAUDIT)
+ 
++secureconf_DATA = faillock.conf
++
+ securelib_LTLIBRARIES = pam_faillock.la
+ sbin_PROGRAMS = faillock
+ 
+diff -up Linux-PAM-1.3.1/modules/pam_faillock/pam_faillock.8.xml.faillock-update Linux-PAM-1.3.1/modules/pam_faillock/pam_faillock.8.xml
+--- Linux-PAM-1.3.1/modules/pam_faillock/pam_faillock.8.xml.faillock-update	2019-10-16 16:49:27.030893701 +0200
++++ Linux-PAM-1.3.1/modules/pam_faillock/pam_faillock.8.xml	2019-10-16 16:53:39.544606052 +0200
+@@ -126,141 +126,13 @@
+                 </para>
+               </listitem>
+             </varlistentry>
+-            <varlistentry>
+-              <term>
+-                <option>dir=<replaceable>/path/to/tally-directory</replaceable></option>
+-              </term>
+-              <listitem>
+-                <para>
+-                  The directory where the user files with the failure records are kept. The
+-                  default is <filename>/var/run/faillock</filename>.
+-                </para>
+-              </listitem>
+-            </varlistentry>
+-            <varlistentry>
+-              <term>
+-                <option>audit</option>
+-              </term>
+-              <listitem>
+-                <para>
+-                  Will log the user name into the system log if the user is not found.
+-                </para>
+-              </listitem>
+-            </varlistentry>
+-            <varlistentry>
+-              <term>
+-                <option>silent</option>
+-              </term>
+-              <listitem>
+-                <para>
+-                  Don't print informative messages. This option is implicite
+-                  in the <emphasis>authfail</emphasis> and <emphasis>authsucc</emphasis>
+-                  functions.
+-                </para>
+-              </listitem>
+-            </varlistentry>
+-            <varlistentry>
+-              <term>
+-                <option>no_log_info</option>
+-              </term>
+-              <listitem>
+-                <para>
+-                  Don't log informative messages via <citerefentry><refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
+-                </para>
+-              </listitem>
+-            </varlistentry>
+-            <varlistentry>
+-              <term>
+-                <option>deny=<replaceable>n</replaceable></option>
+-              </term>
+-              <listitem>
+-                <para>
+-                  Deny access if the number of consecutive authentication failures
+-                  for this user during the recent interval exceeds
+-                  <replaceable>n</replaceable>. The default is 3.
+-                </para>
+-              </listitem>
+-            </varlistentry>
+-            <varlistentry>
+-              <term>
+-                <option>fail_interval=<replaceable>n</replaceable></option>
+-              </term>
+-              <listitem>
+-                <para>
+-                  The length of the interval during which the consecutive
+-                  authentication failures must happen for the user account
+-                  lock out is <replaceable>n</replaceable> seconds.
+-                  The default is 900 (15 minutes).
+-                </para>
+-              </listitem>
+-            </varlistentry>
+-            <varlistentry>
+-              <term>
+-                <option>unlock_time=<replaceable>n</replaceable></option>
+-              </term>
+-              <listitem>
+-                <para>
+-                  The access will be reenabled after
+-                  <replaceable>n</replaceable> seconds after the lock out.
+-                  The value 0 has the same meaning as value
+-                  <emphasis>never</emphasis> - the access
+-                  will not be reenabled without resetting the faillock
+-                  entries by the <citerefentry><refentrytitle>faillock</refentrytitle><manvolnum>8</manvolnum></citerefentry> command.
+-                  The default is 600 (10 minutes).
+-                </para>
+-                <para>
+-                  Note that the default directory that <emphasis>pam_faillock</emphasis>
+-                  uses is usually cleared on system boot so the access will be also reenabled
+-                  after system reboot. If that is undesirable a different tally directory
+-                  must be set with the <option>dir</option> option.
+-                </para>
+-                <para>
+-                  Also note that it is usually undesirable to permanently lock
+-                  out the users as they can become easily a target of denial of service
+-                  attack unless the usernames are random and kept secret to potential
+-                  attackers.
+-                </para>
+-              </listitem>
+-            </varlistentry>
+-            <varlistentry>
+-              <term>
+-                <option>even_deny_root</option>
+-              </term>
+-              <listitem>
+-                <para>
+-                  Root account can become locked as well as regular accounts.
+-                </para>
+-              </listitem>
+-            </varlistentry>
+-            <varlistentry>
+-              <term>
+-                <option>root_unlock_time=<replaceable>n</replaceable></option>
+-              </term>
+-              <listitem>
+-                <para>
+-                  This option implies <option>even_deny_root</option> option.
+-                  Allow access after <replaceable>n</replaceable> seconds
+-                  to root account after the account is locked. In case the
+-                  option is not specified the value is the same as of the
+-                  <option>unlock_time</option> option.
+-                </para>
+-              </listitem>
+-            </varlistentry>
+-            <varlistentry>
+-              <term>
+-                <option>admin_group=<replaceable>name</replaceable></option>
+-              </term>
+-              <listitem>
+-                <para>
+-                  If a group name is specified with this option, members
+-                  of the group will be handled by this module the same as
+-                  the root account (the options <option>even_deny_root></option>
+-                  and <option>root_unlock_time</option> will apply to them.
+-                  By default the option is not set.
+-                </para>
+-              </listitem>
+-            </varlistentry>
+         </variablelist>
++        <para>
++          The options for configuring the module behavior are described in the 
++          <citerefentry><refentrytitle>faillock.conf</refentrytitle><manvolnum>5</manvolnum>
++          </citerefentry> manual page. The options specified on the module command
++          line override the values from the configuration file.
++        </para>
+   </refsect1>
+ 
+   <refsect1 id="pam_faillock-types">
+@@ -306,19 +178,23 @@
+   <refsect1 id='pam_faillock-notes'>
+     <title>NOTES</title>
+     <para>
+-      <emphasis>pam_faillock</emphasis> setup in the PAM stack is different
++      Configuring options on the module command line is not recommend. The
++      <emphasis>/etc/security/faillock.conf</emphasis> should be used instead.
++    </para>
++    <para>
++      The setup of <emphasis>pam_faillock</emphasis> in the PAM stack is different
+       from the <emphasis>pam_tally2</emphasis> module setup.
+     </para>
+     <para>
+-      The individual files with the failure records are created as owned by
++      Individual files with the failure records are created as owned by
+       the user. This allows <emphasis remap='B'>pam_faillock.so</emphasis> module
+       to work correctly when it is called from a screensaver.
+     </para>
+     <para>
+       Note that using the module in <option>preauth</option> without the
+-      <option>silent</option> option or with <emphasis>requisite</emphasis>
+-      control field leaks an information about existence or
+-      non-existence of an user account in the system because
++      <option>silent</option> option specified in <filename>/etc/security/faillock.conf</filename>
++      or with <emphasis>requisite</emphasis> control field leaks an information about
++      existence or non-existence of an user account in the system because
+       the failures are not recorded for the unknown users. The message
+       about the user account being locked is never displayed for nonexisting
+       user accounts allowing the adversary to infer that a particular account
+@@ -341,15 +217,26 @@
+       be added to tell the user that his login is blocked by the module and also to abort
+       the authentication without even asking for password in such case.
+     </para>
++    <para>
++      /etc/security/faillock.conf file example:
++    </para>
++    <programlisting>
++deny=4
++unlock_time=1200
++silent
++    </programlisting>
++    <para>
++      /etc/pam.d/config file example:
++    </para>
+     <programlisting>
+ auth     required       pam_securetty.so
+ auth     required       pam_env.so
+ auth     required       pam_nologin.so
+-# optionally call: auth requisite pam_faillock.so preauth deny=4 even_deny_root unlock_time=1200
++# optionally call: auth requisite pam_faillock.so preauth
+ # to display the message about account being locked
+ auth     [success=1 default=bad] pam_unix.so
+-auth     [default=die]  pam_faillock.so authfail deny=4 even_deny_root unlock_time=1200
+-auth     sufficient     pam_faillock.so authsucc deny=4 even_deny_root unlock_time=1200
++auth     [default=die]  pam_faillock.so authfail
++auth     sufficient     pam_faillock.so authsucc
+ auth     required       pam_deny.so
+ account  required       pam_unix.so
+ password required       pam_unix.so shadow
+@@ -361,17 +248,18 @@ session  required       pam_selinux.so o
+     <para>
+       In the second example the module is called both in the <emphasis>auth</emphasis>
+       and <emphasis>account</emphasis> phases and the module gives the authenticating
+-      user message when the account is locked 
++      user message when the account is locked if <option>silent</option> option is not
++      specified in the <filename>faillock.conf</filename>.
+     </para>
+     <programlisting>
+ auth     required       pam_securetty.so
+ auth     required       pam_env.so
+ auth     required       pam_nologin.so
+-auth     required       pam_faillock.so preauth silent deny=4 even_deny_root unlock_time=1200
++auth     required       pam_faillock.so preauth
+ # optionally use requisite above if you do not want to prompt for the password
+-# on locked accounts, possibly with removing the silent option as well
++# on locked accounts
+ auth     sufficient     pam_unix.so
+-auth     [default=die]  pam_faillock.so authfail deny=4 even_deny_root unlock_time=1200
++auth     [default=die]  pam_faillock.so authfail
+ auth     required       pam_deny.so
+ account  required       pam_faillock.so
+ # if you drop the above call to pam_faillock.so the lock will be done also
+@@ -394,6 +282,12 @@ session  required       pam_selinux.so o
+           <para>the files logging the authentication failures for users</para>
+         </listitem>
+       </varlistentry>
++      <varlistentry>
++        <term><filename>/etc/security/faillock.conf</filename></term>
++        <listitem>
++          <para>the config file for pam_faillock options</para>
++        </listitem>
++      </varlistentry>
+     </variablelist>
+   </refsect1>
+ 
+@@ -404,6 +298,9 @@ session  required       pam_selinux.so o
+         <refentrytitle>faillock</refentrytitle><manvolnum>8</manvolnum>
+       </citerefentry>,
+       <citerefentry>
++        <refentrytitle>faillock.conf</refentrytitle><manvolnum>5</manvolnum>
++      </citerefentry>,
++      <citerefentry>
+         <refentrytitle>pam.conf</refentrytitle><manvolnum>5</manvolnum>
+       </citerefentry>,
+       <citerefentry>
+diff -up Linux-PAM-1.3.1/modules/pam_faillock/pam_faillock.c.faillock-update Linux-PAM-1.3.1/modules/pam_faillock/pam_faillock.c
+--- Linux-PAM-1.3.1/modules/pam_faillock/pam_faillock.c.faillock-update	2019-10-16 16:49:27.030893701 +0200
++++ Linux-PAM-1.3.1/modules/pam_faillock/pam_faillock.c	2019-12-16 17:55:11.403270018 +0100
+@@ -1,5 +1,6 @@
+ /*
+- * Copyright (c) 2010, 2017 Tomas Mraz <tmraz@redhat.com>
++ * Copyright (c) 2010, 2017, 2019 Tomas Mraz <tmraz@redhat.com>
++ * Copyright (c) 2010, 2017, 2019 Red Hat, Inc.
+  *
+  * Redistribution and use in source and binary forms, with or without
+  * modification, are permitted provided that the following conditions
+@@ -43,6 +44,7 @@
+ #include <time.h>
+ #include <pwd.h>
+ #include <syslog.h>
++#include <ctype.h>
+ 
+ #ifdef HAVE_LIBAUDIT
+ #include <libaudit.h>
+@@ -66,8 +68,14 @@
+ #define FAILLOCK_FLAG_SILENT		0x4
+ #define FAILLOCK_FLAG_NO_LOG_INFO	0x8
+ #define FAILLOCK_FLAG_UNLOCKED		0x10
++#define FAILLOCK_FLAG_LOCAL_ONLY	0x20
+ 
+ #define MAX_TIME_INTERVAL 604800 /* 7 days */
++#define FAILLOCK_CONF_MAX_LINELEN 1023
++#define FAILLOCK_ERROR_CONF_OPEN -3
++#define FAILLOCK_ERROR_CONF_MALFORMED -4
++
++#define PATH_PASSWD "/etc/passwd"
+ 
+ struct options {
+ 	unsigned int action;
+@@ -76,117 +84,295 @@ struct options {
+ 	unsigned int fail_interval;
+ 	unsigned int unlock_time;
+ 	unsigned int root_unlock_time;
+-	const char *dir;
++	char *dir;
++	const char *conf;
+ 	const char *user;
+-	const char *admin_group;
++	char *admin_group;
+ 	int failures;
+ 	uint64_t latest_time;
+ 	uid_t uid;
+ 	int is_admin;
+ 	uint64_t now;
++	int fatal_error;
+ };
+ 
++int read_config_file(
++	pam_handle_t *pamh,
++	struct options *opts,
++	const char *cfgfile
++);
++
++void set_conf_opt(
++	pam_handle_t *pamh,
++	struct options *opts,
++	const char *name,
++	const char *value
++);
++
+ static void
+ args_parse(pam_handle_t *pamh, int argc, const char **argv,
+ 		int flags, struct options *opts)
+ {
+ 	int i;
++	int rv;
+ 	memset(opts, 0, sizeof(*opts));
+ 
+-	opts->dir = FAILLOCK_DEFAULT_TALLYDIR;
++	opts->dir = strdup(FAILLOCK_DEFAULT_TALLYDIR);
++	opts->conf = FAILLOCK_DEFAULT_CONF;
+ 	opts->deny = 3;
+ 	opts->fail_interval = 900;
+ 	opts->unlock_time = 600;
+ 	opts->root_unlock_time = MAX_TIME_INTERVAL+1;
+ 
+-	for (i = 0; i < argc; ++i) {
++	if ((rv=read_config_file(pamh, opts, opts->conf)) != PAM_SUCCESS) {
++		pam_syslog(pamh, LOG_DEBUG,
++					"Configuration file missing");
++	}
+ 
+-		if (strncmp(argv[i], "dir=", 4) == 0) {
+-			if (argv[i][4] != '/') {
+-				pam_syslog(pamh, LOG_ERR,
+-					"Tally directory is not absolute path (%s); keeping default", argv[i]);
+-	        	} else {
+-			        opts->dir = argv[i]+4;
+-			}
+-		} 
+-		else if (strncmp(argv[i], "deny=", 5) == 0) {
+-			if (sscanf(argv[i]+5, "%hu", &opts->deny) != 1) {
+-				pam_syslog(pamh, LOG_ERR,
+-					"Bad number supplied for deny argument");
+-        		}
+-		}
+-		else if (strncmp(argv[i], "fail_interval=", 14) == 0) {
+-			unsigned int temp;
+-			if (sscanf(argv[i]+14, "%u", &temp) != 1 ||
+-				temp > MAX_TIME_INTERVAL) {
+-				pam_syslog(pamh, LOG_ERR,
+-					"Bad number supplied for fail_interval argument");
+-	        	} else {
+-				opts->fail_interval = temp;
+-			}
++	for (i = 0; i < argc; ++i) {
++		if (strcmp(argv[i], "preauth") == 0) {
++			opts->action = FAILLOCK_ACTION_PREAUTH;
++		}
++		else if (strcmp(argv[i], "authfail") == 0) {
++			opts->action = FAILLOCK_ACTION_AUTHFAIL;
++		}
++		else if (strcmp(argv[i], "authsucc") == 0) {
++			opts->action = FAILLOCK_ACTION_AUTHSUCC;
+ 		}
+-		else if (strncmp(argv[i], "unlock_time=", 12) == 0) {
+-			unsigned int temp;
++		else {
++			char buf[FAILLOCK_CONF_MAX_LINELEN + 1];
++			char *val;
+ 
+-			if (strcmp(argv[i]+12, "never") == 0) {
+-				opts->unlock_time = 0;
+-			}
+-			else if (sscanf(argv[i]+12, "%u", &temp) != 1 ||
+-				temp > MAX_TIME_INTERVAL) {
+-				pam_syslog(pamh, LOG_ERR,
+-					"Bad number supplied for unlock_time argument");
++			strncpy(buf, argv[i], sizeof(buf) - 1);
++			buf[sizeof(buf) - 1] = '\0';
++
++			val = strchr(buf, '=');
++			if (val != NULL) {
++				*val = '\0';
++				++val;
+ 			}
+ 			else {
+-				opts->unlock_time = temp;
++				val = buf + sizeof(buf) - 1;
+ 			}
++			set_conf_opt(pamh, opts, buf, val);
+ 		}
+-		else if (strncmp(argv[i], "root_unlock_time=", 17) == 0) {
+-			unsigned int temp;
++	}
+ 
+-			if (strcmp(argv[i]+17, "never") == 0) {
+-				opts->root_unlock_time = 0;
+-			}
+-			else if (sscanf(argv[i]+17, "%u", &temp) != 1 ||
+-				temp > MAX_TIME_INTERVAL) {
+-				pam_syslog(pamh, LOG_ERR,
+-					"Bad number supplied for root_unlock_time argument");
++	if (opts->root_unlock_time == MAX_TIME_INTERVAL+1)
++		opts->root_unlock_time = opts->unlock_time;
++	if (flags & PAM_SILENT)
++		opts->flags |= FAILLOCK_FLAG_SILENT;
++
++	if (opts->dir == NULL) {
++		pam_syslog(pamh, LOG_CRIT, "Error allocating memory: %m");
++		opts->fatal_error = 1;
++	}
++}
++
++/* parse a single configuration file */
++int
++read_config_file(pam_handle_t *pamh, struct options *opts, const char *cfgfile)
++{
++	FILE *f;
++	char linebuf[FAILLOCK_CONF_MAX_LINELEN+1];
++
++	f = fopen(cfgfile, "r");
++	if (f == NULL) {
++		/* ignore non-existent default config file */
++		if (errno == ENOENT && strcmp(cfgfile, FAILLOCK_DEFAULT_CONF) == 0)
++			return 0;
++		return FAILLOCK_ERROR_CONF_OPEN;
++	}
++
++	while (fgets(linebuf, sizeof(linebuf), f) != NULL) {
++		size_t len;
++		char *ptr;
++		char *name;
++		int eq;
++
++		len = strlen(linebuf);
++		/* len cannot be 0 unless there is a bug in fgets */
++		if (len && linebuf[len - 1] != '\n' && !feof(f)) {
++			(void) fclose(f);
++			return FAILLOCK_ERROR_CONF_MALFORMED;
++		}
++
++		if ((ptr=strchr(linebuf, '#')) != NULL) {
++			*ptr = '\0';
++		} else {
++			ptr = linebuf + len;
++		}
++
++		/* drop terminating whitespace including the \n */
++		while (ptr > linebuf) {
++			if (!isspace(*(ptr-1))) {
++				*ptr = '\0';
++				break;
++			}
++			--ptr;
++		}
++
++		/* skip initial whitespace */
++		for (ptr = linebuf; isspace(*ptr); ptr++);
++		if (*ptr == '\0')
++			continue;
++
++		/* grab the key name */
++		eq = 0;
++		name = ptr;
++		while (*ptr != '\0') {
++			if (isspace(*ptr) || *ptr == '=') {
++				eq = *ptr == '=';
++				*ptr = '\0';
++				++ptr;
++				break;
++			}
++			++ptr;
++		}
++
++		/* grab the key value */
++		while (*ptr != '\0') {
++			if (*ptr != '=' || eq) {
++				if (!isspace(*ptr)) {
++					break;
++				}
+ 			} else {
+-				opts->root_unlock_time = temp;
++				eq = 1;
+ 			}
++			++ptr;
+ 		}
+-		else if (strncmp(argv[i], "admin_group=", 12) == 0) {
+-			opts->admin_group = argv[i] + 12;
++
++		/* set the key:value pair on opts */
++		set_conf_opt(pamh, opts, name, ptr);
++	}
++
++	(void)fclose(f);
++	return PAM_SUCCESS;
++}
++
++void set_conf_opt(pam_handle_t *pamh, struct options *opts, const char *name, const char *value)
++{
++	if (strcmp(name, "dir") == 0) {
++		if (value[0] != '/') {
++			pam_syslog(pamh, LOG_ERR,
++				"Tally directory is not absolute path (%s); keeping default", value);
++		} else {
++			free(opts->dir);
++			opts->dir = strdup(value);
+ 		}
+- 		else if (strcmp(argv[i], "preauth") == 0) {
+-			opts->action = FAILLOCK_ACTION_PREAUTH;
++	}
++	else if (strcmp(name, "deny") == 0) {
++		if (sscanf(value, "%hu", &opts->deny) != 1) {
++			pam_syslog(pamh, LOG_ERR,
++				"Bad number supplied for deny argument");
++		}
++	}
++	else if (strcmp(name, "fail_interval") == 0) {
++		unsigned int temp;
++		if (sscanf(value, "%u", &temp) != 1 ||
++			temp > MAX_TIME_INTERVAL) {
++			pam_syslog(pamh, LOG_ERR,
++				"Bad number supplied for fail_interval argument");
++		} else {
++			opts->fail_interval = temp;
+ 		}
+- 		else if (strcmp(argv[i], "authfail") == 0) {
+-			opts->action = FAILLOCK_ACTION_AUTHFAIL;
++	}
++	else if (strcmp(name, "unlock_time") == 0) {
++		unsigned int temp;
++
++		if (strcmp(value, "never") == 0) {
++			opts->unlock_time = 0;
+ 		}
+-	 	else if (strcmp(argv[i], "authsucc") == 0) {
+-			opts->action = FAILLOCK_ACTION_AUTHSUCC;
++		else if (sscanf(value, "%u", &temp) != 1 ||
++			temp > MAX_TIME_INTERVAL) {
++			pam_syslog(pamh, LOG_ERR,
++				"Bad number supplied for unlock_time argument");
+ 		}
+-	 	else if (strcmp(argv[i], "even_deny_root") == 0) {
+-			opts->flags |= FAILLOCK_FLAG_DENY_ROOT;
++		else {
++			opts->unlock_time = temp;
+ 		}
+-	 	else if (strcmp(argv[i], "audit") == 0) {
+-			opts->flags |= FAILLOCK_FLAG_AUDIT;
++	}
++	else if (strcmp(name, "root_unlock_time") == 0) {
++		unsigned int temp;
++
++		if (strcmp(value, "never") == 0) {
++			opts->root_unlock_time = 0;
+ 		}
+-	 	else if (strcmp(argv[i], "silent") == 0) {
+-			opts->flags |= FAILLOCK_FLAG_SILENT;
++		else if (sscanf(value, "%u", &temp) != 1 ||
++			temp > MAX_TIME_INTERVAL) {
++			pam_syslog(pamh, LOG_ERR,
++				"Bad number supplied for root_unlock_time argument");
++		} else {
++			opts->root_unlock_time = temp;
+ 		}
+-	 	else if (strcmp(argv[i], "no_log_info") == 0) {
+-			opts->flags |= FAILLOCK_FLAG_NO_LOG_INFO;
++	}
++	else if (strcmp(name, "admin_group") == 0) {
++		free(opts->admin_group);
++		opts->admin_group = strdup(value);
++		if (opts->admin_group == NULL) {
++			opts->fatal_error = 1;
++			pam_syslog(pamh, LOG_CRIT, "Error allocating memory: %m");
+ 		}
+-		else {
+-			pam_syslog(pamh, LOG_ERR, "Unknown option: %s", argv[i]);
++	}
++	else if (strcmp(name, "even_deny_root") == 0) {
++		opts->flags |= FAILLOCK_FLAG_DENY_ROOT;
++	}
++	else if (strcmp(name, "audit") == 0) {
++		opts->flags |= FAILLOCK_FLAG_AUDIT;
++	}
++	else if (strcmp(name, "silent") == 0) {
++		opts->flags |= FAILLOCK_FLAG_SILENT;
++	}
++	else if (strcmp(name, "no_log_info") == 0) {
++		opts->flags |= FAILLOCK_FLAG_NO_LOG_INFO;
++	}
++	else if (strcmp(name, "local_users_only") == 0) {
++		opts->flags |= FAILLOCK_FLAG_LOCAL_ONLY;
++	}
++	else {
++		pam_syslog(pamh, LOG_ERR, "Unknown option: %s", name);
++	}
++}
++
++static int check_local_user (pam_handle_t *pamh, const char *user)
++{
++	struct passwd pw, *pwp;
++	char buf[4096];
++	int found = 0;
++	FILE *fp;
++	int errn;
++
++	fp = fopen(PATH_PASSWD, "r");
++	if (fp == NULL) {
++		pam_syslog(pamh, LOG_ERR, "unable to open %s: %m",
++			   PATH_PASSWD);
++		return -1;
++	}
++
++	for (;;) {
++		errn = fgetpwent_r(fp, &pw, buf, sizeof (buf), &pwp);
++		if (errn == ERANGE) {
++			pam_syslog(pamh, LOG_WARNING, "%s contains very long lines; corrupted?",
++				   PATH_PASSWD);
++			/* we can continue here as next call will read further */
++			continue;
++		}
++		if (errn != 0)
++			break;
++		if (strcmp(pwp->pw_name, user) == 0) {
++			found = 1;
++			break;
+ 		}
+ 	}
+ 
+-	if (opts->root_unlock_time == MAX_TIME_INTERVAL+1)
+-		opts->root_unlock_time = opts->unlock_time;
+-	if (flags & PAM_SILENT)
+-		opts->flags |= FAILLOCK_FLAG_SILENT;
++	fclose (fp);
++
++	if (errn != 0 && errn != ENOENT) {
++		pam_syslog(pamh, LOG_ERR, "unable to enumerate local accounts: %m");
++		return -1;
++	} else {
++		return found;
++	}
+ }
+ 
+ static int get_pam_user(pam_handle_t *pamh, struct options *opts)
+@@ -393,7 +579,7 @@ write_tally(pam_handle_t *pamh, struct o
+ 
+ 	strncpy(tallies->records[oldest].source, source, sizeof(tallies->records[oldest].source));
+ 	/* source does not have to be null terminated */
+-	
++
+ 	tallies->records[oldest].time = opts->now;
+ 
+ 	++failures;
+@@ -468,6 +654,13 @@ tally_cleanup(struct tally_data *tallies
+ 	free(tallies->records);
+ }
+ 
++static void
++opts_cleanup(struct options *opts)
++{
++	free(opts->dir);
++	free(opts->admin_group);
++}
++
+ /*---------------------------------------------------------------------*/
+ 
+ PAM_EXTERN int
+@@ -481,39 +674,49 @@ pam_sm_authenticate(pam_handle_t *pamh,
+ 	memset(&tallies, 0, sizeof(tallies));
+ 
+ 	args_parse(pamh, argc, argv, flags, &opts);
++	if (opts.fatal_error) {
++		rv = PAM_BUF_ERR;
++		goto err;
++	}
+ 
+ 	pam_fail_delay(pamh, 2000000);	/* 2 sec delay for on failure */
+ 
+ 	if ((rv=get_pam_user(pamh, &opts)) != PAM_SUCCESS) {
+-		return rv;
++		goto err;
+ 	}
+ 
+-	switch (opts.action) {
+-		case FAILLOCK_ACTION_PREAUTH:
+-			rv = check_tally(pamh, &opts, &tallies, &fd);
+-			if (rv == PAM_AUTH_ERR && !(opts.flags & FAILLOCK_FLAG_SILENT)) {
+-				faillock_message(pamh, &opts);
+-			}
+-                        break;
+-
+-		case FAILLOCK_ACTION_AUTHSUCC:
+-			rv = check_tally(pamh, &opts, &tallies, &fd);
+-			if (rv == PAM_SUCCESS) {
+-				reset_tally(pamh, &opts, &fd);
+-			}
+-                        break;
+-
+-		case FAILLOCK_ACTION_AUTHFAIL:
+-			rv = check_tally(pamh, &opts, &tallies, &fd);
+-			if (rv == PAM_SUCCESS) {
+-				rv = PAM_IGNORE; /* this return value should be ignored */
+-				write_tally(pamh, &opts, &tallies, &fd);
+-			}
+-			break;
++	if (!(opts.flags & FAILLOCK_FLAG_LOCAL_ONLY) ||
++		check_local_user (pamh, opts.user) != 0) {
++		switch (opts.action) {
++			case FAILLOCK_ACTION_PREAUTH:
++				rv = check_tally(pamh, &opts, &tallies, &fd);
++				if (rv == PAM_AUTH_ERR && !(opts.flags & FAILLOCK_FLAG_SILENT)) {
++					faillock_message(pamh, &opts);
++				}
++				break;
++
++			case FAILLOCK_ACTION_AUTHSUCC:
++				rv = check_tally(pamh, &opts, &tallies, &fd);
++				if (rv == PAM_SUCCESS) {
++					reset_tally(pamh, &opts, &fd);
++				}
++				break;
++
++			case FAILLOCK_ACTION_AUTHFAIL:
++				rv = check_tally(pamh, &opts, &tallies, &fd);
++				if (rv == PAM_SUCCESS) {
++					rv = PAM_IGNORE; /* this return value should be ignored */
++					write_tally(pamh, &opts, &tallies, &fd);
++				}
++				break;
++		}
+ 	}
+ 
+ 	tally_cleanup(&tallies, fd);
+ 
++err:
++	opts_cleanup(&opts);
++
+ 	return rv;
+ }
+ 
+@@ -540,18 +743,29 @@ pam_sm_acct_mgmt(pam_handle_t *pamh, int
+ 
+ 	args_parse(pamh, argc, argv, flags, &opts);
+ 
++	if (opts.fatal_error) {
++		rv = PAM_BUF_ERR;
++		goto err;
++	}
++
+ 	opts.action = FAILLOCK_ACTION_AUTHSUCC;
+ 
+ 	if ((rv=get_pam_user(pamh, &opts)) != PAM_SUCCESS) {
+-		return rv;
++		goto err;
+ 	}
+ 
+-	check_tally(pamh, &opts, &tallies, &fd); /* for auditing */
+-	reset_tally(pamh, &opts, &fd);
++	if (!(opts.flags & FAILLOCK_FLAG_LOCAL_ONLY) ||
++		check_local_user (pamh, opts.user) != 0) {
++		check_tally(pamh, &opts, &tallies, &fd); /* for auditing */
++		reset_tally(pamh, &opts, &fd);
++	}
+ 
+ 	tally_cleanup(&tallies, fd);
+ 
+-	return PAM_SUCCESS;
++err:
++	opts_cleanup(&opts);
++
++	return rv;
+ }
+ 
+ /*-----------------------------------------------------------------------*/
diff --git a/SOURCES/pam-1.3.1-fds-closing.patch b/SOURCES/pam-1.3.1-fds-closing.patch
new file mode 100644
index 0000000..7f5f772
--- /dev/null
+++ b/SOURCES/pam-1.3.1-fds-closing.patch
@@ -0,0 +1,70 @@
+diff -up Linux-PAM-1.3.1/libpam/pam_modutil_sanitize.c.fds-closing Linux-PAM-1.3.1/libpam/pam_modutil_sanitize.c
+--- Linux-PAM-1.3.1/libpam/pam_modutil_sanitize.c.fds-closing	2017-02-10 11:10:15.000000000 +0100
++++ Linux-PAM-1.3.1/libpam/pam_modutil_sanitize.c	2019-10-16 16:07:31.259021159 +0200
+@@ -10,6 +10,7 @@
+ #include <fcntl.h>
+ #include <syslog.h>
+ #include <sys/resource.h>
++#include <dirent.h>
+ 
+ /*
+  * Creates a pipe, closes its write end, redirects fd to its read end.
+@@ -116,27 +117,45 @@ redirect_out(pam_handle_t *pamh, enum pa
+ static void
+ close_fds(void)
+ {
++	DIR *dir = NULL;
++	struct dirent *dent;
++	int dfd = -1;
++	int fd;
++	struct rlimit rlim;
++
+ 	/*
+ 	 * An arbitrary upper limit for the maximum file descriptor number
+ 	 * returned by RLIMIT_NOFILE.
+ 	 */
+-	const int MAX_FD_NO = 65535;
++	const unsigned int MAX_FD_NO = 65535;
+ 
+ 	/* The lower limit is the same as for _POSIX_OPEN_MAX. */
+-	const int MIN_FD_NO = 20;
++	const unsigned int MIN_FD_NO = 20;
+ 
+-	int fd;
+-	struct rlimit rlim;
+-
+-	if (getrlimit(RLIMIT_NOFILE, &rlim) || rlim.rlim_max > MAX_FD_NO)
+-		fd = MAX_FD_NO;
+-	else if (rlim.rlim_max < MIN_FD_NO)
+-		fd = MIN_FD_NO;
+-	else
+-		fd = rlim.rlim_max - 1;
++	/* If /proc is mounted, we can optimize which fd can be closed. */
++	if ((dir = opendir("/proc/self/fd")) != NULL) {
++		if ((dfd = dirfd(dir)) >= 0) {
++			while ((dent = readdir(dir)) != NULL) {
++				fd = atoi(dent->d_name);
++				if (fd > STDERR_FILENO && fd != dfd)
++					close(fd);
++			}
++		}
++		closedir(dir);
++	}
++
++	/* If /proc isn't available, fallback to the previous behavior. */
++	if (dfd < 0) {
++		if (getrlimit(RLIMIT_NOFILE, &rlim) || rlim.rlim_max > MAX_FD_NO)
++			fd = MAX_FD_NO;
++		else if (rlim.rlim_max < MIN_FD_NO)
++			fd = MIN_FD_NO;
++		else
++			fd = rlim.rlim_max - 1;
+ 
+-	for (; fd > STDERR_FILENO; --fd)
+-		close(fd);
++		for (; fd > STDERR_FILENO; --fd)
++			close(fd);
++	}
+ }
+ 
+ int
diff --git a/SOURCES/pam-1.3.1-lastlog-no-showfailed.patch b/SOURCES/pam-1.3.1-lastlog-no-showfailed.patch
new file mode 100644
index 0000000..6b68d9d
--- /dev/null
+++ b/SOURCES/pam-1.3.1-lastlog-no-showfailed.patch
@@ -0,0 +1,82 @@
+From c426914fa166ffb0482b6f6ad659ddf17d5dfaa1 Mon Sep 17 00:00:00 2001
+From: Nir Soffer <nsoffer@redhat.com>
+Date: Wed, 9 Jan 2019 23:41:16 +0200
+Subject: [PATCH] pam_lastlog: Improve silent option documentation
+
+The silent option explicitly silents only the last login message and not
+bad logins. Add a note to the manual to make this clear.
+
+* modules/pam_lastlog/pam_lastlog.8.xml: Clearify "silent showfailed"
+---
+ modules/pam_lastlog/pam_lastlog.8.xml | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/modules/pam_lastlog/pam_lastlog.8.xml b/modules/pam_lastlog/pam_lastlog.8.xml
+index c8f247e..bc2e1be 100644
+--- a/modules/pam_lastlog/pam_lastlog.8.xml
++++ b/modules/pam_lastlog/pam_lastlog.8.xml
+@@ -102,6 +102,7 @@
+           <para>
+             Don't inform the user about any previous login,
+             just update the <filename>/var/log/lastlog</filename> file.
++            This option does not affect display of bad login attempts.
+           </para>
+         </listitem>
+       </varlistentry>
+-- 
+2.20.1
+
+From 7d036249a9772c546ede1f38ad68b3f1575216d6 Mon Sep 17 00:00:00 2001
+From: Nir Soffer <nsoffer@redhat.com>
+Date: Sun, 6 Jan 2019 00:36:27 +0200
+Subject: [PATCH] pam_lastlog: Respect PAM_SILENT flag
+
+pam_lastlog module will not log info about failed login if the session
+was opened with PAM_SILENT flag.
+
+Example use case enabled by this change:
+
+    sudo --non-interactive program
+
+If this command is run by another program expecting specific output from
+the command run by sudo, the unexpected info about failed logins will
+break this program.
+
+* modules/pam_lastlog/pam_lastlog.c: Respect silent option.
+  (_pam_session_parse): Unset LASTLOG_BTMP if PAM_SILENT is set.
+---
+ modules/pam_lastlog/pam_lastlog.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/modules/pam_lastlog/pam_lastlog.c b/modules/pam_lastlog/pam_lastlog.c
+index 18bf7be..e980c04 100644
+--- a/modules/pam_lastlog/pam_lastlog.c
++++ b/modules/pam_lastlog/pam_lastlog.c
+@@ -135,11 +135,6 @@ _pam_session_parse(pam_handle_t *pamh, int flags, int argc, const char **argv)
+ {
+     int ctrl=(LASTLOG_DATE|LASTLOG_HOST|LASTLOG_LINE|LASTLOG_WTMP|LASTLOG_UPDATE);
+ 
+-    /* does the appliction require quiet? */
+-    if (flags & PAM_SILENT) {
+-	ctrl |= LASTLOG_QUIET;
+-    }
+-
+     /* step through arguments */
+     for (; argc-- > 0; ++argv) {
+ 
+@@ -168,6 +163,12 @@ _pam_session_parse(pam_handle_t *pamh, int flags, int argc, const char **argv)
+ 	}
+     }
+ 
++    /* does the appliction require quiet? */
++    if (flags & PAM_SILENT) {
++	ctrl |= LASTLOG_QUIET;
++	ctrl &= ~LASTLOG_BTMP;
++    }
++
+     D(("ctrl = %o", ctrl));
+     return ctrl;
+ }
+-- 
+2.20.1
+
diff --git a/SOURCES/pam-1.3.1-lastlog-unlimited-fsize.patch b/SOURCES/pam-1.3.1-lastlog-unlimited-fsize.patch
new file mode 100644
index 0000000..1067d6f
--- /dev/null
+++ b/SOURCES/pam-1.3.1-lastlog-unlimited-fsize.patch
@@ -0,0 +1,227 @@
+From 3a3e70739834cd5cbd17469907ef718c81ae40c0 Mon Sep 17 00:00:00 2001
+From: Carlos Santos <casantos@redhat.com>
+Date: Wed, 11 Sep 2019 11:50:28 -0300
+Subject: [PATCH] pam_lastlog: document the 'unlimited' option
+
+Signed-off-by: Carlos Santos <casantos@redhat.com>
+---
+ modules/pam_lastlog/pam_lastlog.8.xml | 18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+diff --git a/modules/pam_lastlog/pam_lastlog.8.xml b/modules/pam_lastlog/pam_lastlog.8.xml
+index bc2e1be..f10e94a 100644
+--- a/modules/pam_lastlog/pam_lastlog.8.xml
++++ b/modules/pam_lastlog/pam_lastlog.8.xml
+@@ -48,6 +48,9 @@
+       <arg choice="opt">
+         inactive=&lt;days&gt;
+       </arg>
++      <arg choice="opt">
++        unlimited
++      </arg>
+     </cmdsynopsis>
+   </refsynopsisdiv>
+ 
+@@ -196,6 +199,18 @@
+           </para>
+         </listitem>
+       </varlistentry>
++      <varlistentry>
++        <term>
++          <option>unlimited</option>
++        </term>
++        <listitem>
++          <para>
++	    If the <emphasis>fsize</emphasis> limit is set, this option can be
++	    used to override it, preventing failures on systems with large UID
++	    values that lead lastlog to become a huge sparse file.
++          </para>
++        </listitem>
++      </varlistentry>
+     </variablelist>
+   </refsect1>
+ 
+@@ -300,6 +315,9 @@
+   <refsect1 id='pam_lastlog-see_also'>
+     <title>SEE ALSO</title>
+     <para>
++      <citerefentry>
++	<refentrytitle>limits.conf</refentrytitle><manvolnum>5</manvolnum>
++      </citerefentry>,
+       <citerefentry>
+ 	<refentrytitle>pam.conf</refentrytitle><manvolnum>5</manvolnum>
+       </citerefentry>,
+-- 
+2.20.1
+
+From 9349333a9ae958205294cd25e97fd6b4805bd82b Mon Sep 17 00:00:00 2001
+From: Carlos Santos <casantos@redhat.com>
+Date: Tue, 10 Sep 2019 23:08:30 -0300
+Subject: [PATCH] pam_lastlog: prevent crash due to reduced 'fsize' limit
+
+It a reduced fsize limit is set in /etc/security/limits.conf and
+pam_limits is in use pam_lastlog may cause a crash, e.g.
+
+    ----- begin /etc/pam.d/su ----
+    auth        sufficient   pam_rootok.so
+    auth        required     pam_wheel.so use_uid
+    auth        required     pam_env.so
+    auth        required     pam_unix.so nullok
+    account     required     pam_unix.so
+    password    required     pam_unix.so nullok
+    session     required     pam_limits.so
+    session     required     pam_env.so
+    session     required     pam_unix.so
+    session     optional     pam_lastlog.so
+    ----- end /etc/pam.d/su -----
+
+    ----- begin /etc/security/limits.d/fsize.conf -----
+    * soft fsize 1710
+    * hard fsize 1710
+    ----- end /etc/security/limits.d/fsize.conf -----
+
+    # id user1
+    uid=1000(user1) gid=1000(user1) groups=1000(user1)
+    # su - user1
+    Last login: Wed Sep 11 01:52:44 UTC 2019 on console
+    $ exit
+    # id user2
+    uid=60000(user2) gid=60000(user2) groups=60000(user2)
+    # su - user2
+    File size limit exceeded
+
+This happens because pam_limits sets RLIMIT_FSIZE before pam_lastlog
+attempts to write /var/log/lastlog, leading to a SIGXFSZ signal.
+
+In order to fix this, and an 'unlimited' option, which leads to saving
+the 'fsize' limit and set it to unlimited before writing lastlog. After
+that, restore the saved value. If 'fsize' is already unlimited nothing
+is done.
+
+Failing to set the 'fsize' limit is not a fatal error.  With luck the
+configured limit will suffice, so we try to write lastlog anyway, even
+under the risk of dying due to a SIGXFSZ.
+
+Failing to restore the 'fsize' limit is a fatal error, since we don't
+want to keep it unlimited.
+
+Signed-off-by: Carlos Santos <casantos@redhat.com>
+---
+ modules/pam_lastlog/pam_lastlog.c | 66 ++++++++++++++++++++++++++-----
+ 1 file changed, 57 insertions(+), 9 deletions(-)
+
+diff --git a/modules/pam_lastlog/pam_lastlog.c b/modules/pam_lastlog/pam_lastlog.c
+index e980c04..a135c9f 100644
+--- a/modules/pam_lastlog/pam_lastlog.c
++++ b/modules/pam_lastlog/pam_lastlog.c
+@@ -25,6 +25,8 @@
+ #include <stdio.h>
+ #include <string.h>
+ #include <sys/types.h>
++#include <sys/time.h>
++#include <sys/resource.h>
+ #include <syslog.h>
+ #include <unistd.h>
+ 
+@@ -82,15 +84,16 @@ struct lastlog {
+ 
+ /* argument parsing */
+ 
+-#define LASTLOG_DATE        01  /* display the date of the last login */
+-#define LASTLOG_HOST        02  /* display the last host used (if set) */
+-#define LASTLOG_LINE        04  /* display the last terminal used */
+-#define LASTLOG_NEVER      010  /* display a welcome message for first login */
+-#define LASTLOG_DEBUG      020  /* send info to syslog(3) */
+-#define LASTLOG_QUIET      040  /* keep quiet about things */
+-#define LASTLOG_WTMP      0100  /* log to wtmp as well as lastlog */
+-#define LASTLOG_BTMP      0200  /* display failed login info from btmp */
+-#define LASTLOG_UPDATE    0400  /* update the lastlog and wtmp files (default) */
++#define LASTLOG_DATE          01  /* display the date of the last login */
++#define LASTLOG_HOST          02  /* display the last host used (if set) */
++#define LASTLOG_LINE          04  /* display the last terminal used */
++#define LASTLOG_NEVER        010  /* display a welcome message for first login */
++#define LASTLOG_DEBUG        020  /* send info to syslog(3) */
++#define LASTLOG_QUIET        040  /* keep quiet about things */
++#define LASTLOG_WTMP        0100  /* log to wtmp as well as lastlog */
++#define LASTLOG_BTMP        0200  /* display failed login info from btmp */
++#define LASTLOG_UPDATE      0400  /* update the lastlog and wtmp files (default) */
++#define LASTLOG_UNLIMITED  01000  /* unlimited file size (ignore 'fsize' limit) */
+ 
+ static int
+ _pam_auth_parse(pam_handle_t *pamh, int flags, int argc, const char **argv,
+@@ -158,6 +161,8 @@ _pam_session_parse(pam_handle_t *pamh, int flags, int argc, const char **argv)
+ 	    ctrl &= ~(LASTLOG_WTMP|LASTLOG_UPDATE);
+ 	} else if (!strcmp(*argv,"showfailed")) {
+ 	    ctrl |= LASTLOG_BTMP;
++	} else if (!strcmp(*argv,"unlimited")) {
++	    ctrl |= LASTLOG_UNLIMITED;
+ 	} else {
+ 	    pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv);
+ 	}
+@@ -373,6 +378,12 @@ static int
+ last_login_write(pam_handle_t *pamh, int announce, int last_fd,
+ 		 uid_t uid, const char *user)
+ {
++    static struct rlimit no_limit = {
++	RLIM_INFINITY,
++	RLIM_INFINITY
++    };
++    struct rlimit old_limit;
++    int setrlimit_res;
+     struct flock last_lock;
+     struct lastlog last_login;
+     time_t ll_time;
+@@ -427,6 +438,31 @@ last_login_write(pam_handle_t *pamh, int announce, int last_fd,
+         sleep(LASTLOG_IGNORE_LOCK_TIME);
+     }
+ 
++    /*
++     * Failing to set the 'fsize' limit is not a fatal error. We try to write
++     * lastlog anyway, under the risk of dying due to a SIGXFSZ.
++     */
++    D(("setting limit for 'fsize'"));
++
++    if ((announce & LASTLOG_UNLIMITED) == 0) {    /* don't set to unlimted */
++	setrlimit_res = -1;
++    } else if (getrlimit(RLIMIT_FSIZE, &old_limit) == 0) {
++	if (old_limit.rlim_cur == RLIM_INFINITY) {    /* already unlimited */
++	    setrlimit_res = -1;
++	} else {
++	    setrlimit_res = setrlimit(RLIMIT_FSIZE, &no_limit);
++	    if (setrlimit_res != 0)
++		pam_syslog(pamh, LOG_WARNING, "Could not set limit for 'fsize': %m");
++	}
++    } else {
++	setrlimit_res = -1;
++	if (errno == EINVAL) {
++	    pam_syslog(pamh, LOG_INFO, "Limit for 'fsize' not supported: %m");
++	} else {
++	    pam_syslog(pamh, LOG_WARNING, "Could not get limit for 'fsize': %m");
++	}
++    }
++
+     D(("writing to the lastlog file"));
+     if (pam_modutil_write (last_fd, (char *) &last_login,
+ 			   sizeof (last_login)) != sizeof(last_login)) {
+@@ -434,6 +470,18 @@ last_login_write(pam_handle_t *pamh, int announce, int last_fd,
+ 	retval = PAM_SERVICE_ERR;
+     }
+ 
++    /*
++     * Failing to restore the 'fsize' limit is a fatal error.
++     */
++    D(("restoring limit for 'fsize'"));
++    if (setrlimit_res == 0) {
++	setrlimit_res = setrlimit(RLIMIT_FSIZE, &old_limit);
++	if (setrlimit_res != 0) {
++	    pam_syslog(pamh, LOG_ERR, "Could not restore limit for 'fsize': %m");
++	    retval = PAM_SERVICE_ERR;
++	}
++    }
++
+     last_lock.l_type = F_UNLCK;
+     (void) fcntl(last_fd, F_SETLK, &last_lock);        /* unlock */
+     D(("unlocked"));
+-- 
+2.20.1
+
diff --git a/SOURCES/pam-1.3.1-motd-manpage.patch b/SOURCES/pam-1.3.1-motd-manpage.patch
new file mode 100644
index 0000000..b8e2a1e
--- /dev/null
+++ b/SOURCES/pam-1.3.1-motd-manpage.patch
@@ -0,0 +1,25 @@
+diff -up Linux-PAM-1.3.1/modules/pam_motd/pam_motd.8.xml.motd-manpage Linux-PAM-1.3.1/modules/pam_motd/pam_motd.8.xml
+--- Linux-PAM-1.3.1/modules/pam_motd/pam_motd.8.xml.motd-manpage	2018-05-18 11:50:46.000000000 +0200
++++ Linux-PAM-1.3.1/modules/pam_motd/pam_motd.8.xml	2019-12-19 10:29:36.243558251 +0100
+@@ -31,10 +31,19 @@
+     <para>
+       pam_motd is a PAM module that can be used to display
+       arbitrary motd (message of the day) files after a successful
+-      login. By default the <filename>/etc/motd</filename> file is
++      login. By default the <filename>/etc/motd</filename> file and
++      all files from <filename>/etc/motd.d</filename> are
+       shown. The message size is limited to 64KB.
+     </para>
+-
++    <para>
++      To silence a message,
++      a symbolic link with target <filename>/dev/null</filename>
++      may be placed in <filename>/etc/motd.d</filename> with
++      the same filename as the message to be silenced. Example:
++    </para>
++    <para>
++      <command>ln -sfn /dev/null /etc/motd.d/my_motd</command>
++    </para>
+   </refsect1>
+ 
+   <refsect1 id="pam_motd-options">
diff --git a/SOURCES/pam-1.3.1-namespace-mntopts.patch b/SOURCES/pam-1.3.1-namespace-mntopts.patch
new file mode 100644
index 0000000..3249157
--- /dev/null
+++ b/SOURCES/pam-1.3.1-namespace-mntopts.patch
@@ -0,0 +1,131 @@
+diff --git a/modules/pam_namespace/namespace.conf.5.xml b/modules/pam_namespace/namespace.conf.5.xml
+index c7698cb..a94b49e 100644
+--- a/modules/pam_namespace/namespace.conf.5.xml
++++ b/modules/pam_namespace/namespace.conf.5.xml
+@@ -122,9 +122,14 @@
+     <para><emphasis>mntopts</emphasis>=<replaceable>value</replaceable>
+       - value of this flag is passed to the mount call when the tmpfs mount is
+       done. It allows for example the specification of the maximum size of the
+-      tmpfs instance that is created by the mount call. See <citerefentry>
+-      <refentrytitle>mount</refentrytitle><manvolnum>8</manvolnum>
+-      </citerefentry> for details.
++      tmpfs instance that is created by the mount call. In addition to
++      options specified in the <citerefentry>
++      <refentrytitle>tmpfs</refentrytitle><manvolnum>5</manvolnum>
++      </citerefentry> manual the <emphasis>nosuid</emphasis>,
++      <emphasis>noexec</emphasis>, and <emphasis>nodev</emphasis> flags
++      can be used to respectively disable setuid bit effect, disable running
++      executables, and disable devices to be interpreted on the mounted
++      tmpfs filesystem.
+     </para>
+ 
+     <para>
+diff --git a/modules/pam_namespace/pam_namespace.c b/modules/pam_namespace/pam_namespace.c
+index f541f89..660c7a1 100644
+--- a/modules/pam_namespace/pam_namespace.c
++++ b/modules/pam_namespace/pam_namespace.c
+@@ -230,6 +230,73 @@ static int parse_iscript_params(char *params, struct polydir_s *poly)
+     return 0;
+ }
+ 
++struct mntflag {
++    const char *name;
++    size_t len;
++    unsigned long flag;
++};
++
++#define LITERAL_AND_LEN(x) x, sizeof(x) - 1
++
++static const struct mntflag mntflags[] = {
++	{ LITERAL_AND_LEN("noexec"), MS_NOEXEC },
++	{ LITERAL_AND_LEN("nosuid"), MS_NOSUID },
++	{ LITERAL_AND_LEN("nodev"), MS_NODEV }
++    };
++
++static int filter_mntopts(const char *opts, char **filtered,
++		unsigned long *mountflags)
++{
++    size_t origlen = strlen(opts);
++    const char *end;
++    char *dest;
++
++    dest = *filtered = NULL;
++    *mountflags = 0;
++
++    if (origlen == 0)
++	return 0;
++
++    do {
++	size_t len;
++	int i;
++
++	end = strchr(opts, ',');
++	if (end == NULL) {
++	    len = strlen(opts);
++	} else {
++	    len = end - opts;
++	}
++
++	for (i = 0; i < (int)(sizeof(mntflags)/sizeof(mntflags[0])); i++) {
++	    if (mntflags[i].len != len)
++		continue;
++	    if (memcmp(mntflags[i].name, opts, len) == 0) {
++		*mountflags |= mntflags[i].flag;
++		opts = end;
++		break;
++	    }
++	}
++
++	if (opts != end) {
++	    if (dest != NULL) {
++		*dest = ',';
++		++dest;
++	    } else {
++		dest = *filtered = calloc(1, origlen + 1);
++		if (dest == NULL)
++		    return -1;
++	    }
++	    memcpy(dest, opts, len);
++	    dest += len;
++	}
++
++	opts = end + 1;
++    } while (end != NULL);
++
++    return 0;
++}
++
+ static int parse_method(char *method, struct polydir_s *poly,
+ 		struct instance_data *idata)
+ {
+@@ -289,7 +356,8 @@ static int parse_method(char *method, struct polydir_s *poly,
+ 					break;
+ 				}
+ 				free(poly->mount_opts); /* if duplicate mntopts specified */
+-				if ((poly->mount_opts = strdup(flag+namelen+1)) == NULL) {
++				poly->mount_opts = NULL;
++				if (filter_mntopts(flag+namelen+1, &poly->mount_opts, &poly->mount_flags) != 0) {
+ 					pam_syslog(idata->pamh, LOG_CRIT, "Memory allocation error");
+ 					return -1;
+ 				}
+@@ -1484,7 +1552,7 @@ static int ns_setup(struct polydir_s *polyptr,
+     }
+ 
+     if (polyptr->method == TMPFS) {
+-	if (mount("tmpfs", polyptr->dir, "tmpfs", 0, polyptr->mount_opts) < 0) {
++	if (mount("tmpfs", polyptr->dir, "tmpfs", polyptr->mount_flags, polyptr->mount_opts) < 0) {
+ 	    pam_syslog(idata->pamh, LOG_ERR, "Error mounting tmpfs on %s, %m",
+ 		polyptr->dir);
+             return PAM_SESSION_ERR;
+diff --git a/modules/pam_namespace/pam_namespace.h b/modules/pam_namespace/pam_namespace.h
+index 47ebcc3..1522386 100644
+--- a/modules/pam_namespace/pam_namespace.h
++++ b/modules/pam_namespace/pam_namespace.h
+@@ -166,6 +166,7 @@ struct polydir_s {
+     unsigned int flags;			/* polydir flags */
+     char *init_script;			/* path to init script */
+     char *mount_opts;			/* mount options for tmpfs mount */
++    unsigned long mount_flags;		/* mount flags for tmpfs mount */
+     uid_t owner;			/* user which should own the polydir */
+     gid_t group;			/* group which should own the polydir */
+     mode_t mode;			/* mode of the polydir */
diff --git a/SOURCES/pam-1.3.1-tty-audit-manfix.patch b/SOURCES/pam-1.3.1-tty-audit-manfix.patch
new file mode 100644
index 0000000..3d17963
--- /dev/null
+++ b/SOURCES/pam-1.3.1-tty-audit-manfix.patch
@@ -0,0 +1,33 @@
+From e31dd6c7d0faa7a06d3ebd50a0b6957b9f822d15 Mon Sep 17 00:00:00 2001
+From: Tomas Mraz <tmraz@fedoraproject.org>
+Date: Wed, 7 Aug 2019 18:13:57 +0200
+Subject: [PATCH] pam_tty_audit: Manual page clarification about password
+ logging
+
+* modules/pam_tty_audit/pam_tty_audit.8.xml: Explanation why passwords
+can be sometimes logged even when the option is not set.
+---
+ modules/pam_tty_audit/pam_tty_audit.8.xml | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/modules/pam_tty_audit/pam_tty_audit.8.xml b/modules/pam_tty_audit/pam_tty_audit.8.xml
+index 59a3406..e346c68 100644
+--- a/modules/pam_tty_audit/pam_tty_audit.8.xml
++++ b/modules/pam_tty_audit/pam_tty_audit.8.xml
+@@ -149,6 +149,13 @@
+       greater than or equal to <replaceable>min_uid</replaceable> will be
+       matched.
+     </para>
++    <para>
++      Please note that passwords in some circumstances may be logged by TTY auditing
++      even if the <option>log_passwd</option> is not used. For example, all input to
++      an ssh session will be logged - even if there is a password being typed into
++      some software running at the remote host because only the local TTY state
++      affects the local TTY auditing.
++    </para>
+   </refsect1>
+ 
+   <refsect1 id='pam_tty_audit-examples'>
+-- 
+2.20.1
+
diff --git a/SOURCES/pam-1.3.1-unix-improve-logging.patch b/SOURCES/pam-1.3.1-unix-improve-logging.patch
new file mode 100644
index 0000000..682b4d5
--- /dev/null
+++ b/SOURCES/pam-1.3.1-unix-improve-logging.patch
@@ -0,0 +1,57 @@
+From a6845905869ccabb5eb802be37241eabec085dc7 Mon Sep 17 00:00:00 2001
+From: Tomas Mraz <tmraz@fedoraproject.org>
+Date: Mon, 14 Oct 2019 16:52:46 +0200
+Subject: [PATCH] pam_unix: Add logging useful for debugging problems
+
+Two messages added about obtaining the username are guarded
+by the debug option as these should not be normally
+logged - they can be useful for debugging but they do not
+indicate any special condition.
+
+The message about authenticating user with blank password is
+still just LOG_DEBUG priority but it is logged unconditionally
+because it is somewhat extraordinary condition to have an user
+with blank password.
+
+* modules/pam_unix/pam_unix_auth.c (pam_sm_authenticate): Replace
+  D() macro calls which are not enabled on production builds with
+  regular pam_syslog() calls.
+---
+ modules/pam_unix/pam_unix_auth.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/modules/pam_unix/pam_unix_auth.c b/modules/pam_unix/pam_unix_auth.c
+index 681e49d..3fca945 100644
+--- a/modules/pam_unix/pam_unix_auth.c
++++ b/modules/pam_unix/pam_unix_auth.c
+@@ -130,15 +130,16 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
+ 			AUTH_RETURN;
+ 		}
+ 		if (on(UNIX_DEBUG, ctrl))
+-			D(("username [%s] obtained", name));
++			pam_syslog(pamh, LOG_DEBUG, "username [%s] obtained", name);
+ 	} else {
+-		D(("trouble reading username"));
+ 		if (retval == PAM_CONV_AGAIN) {
+ 			D(("pam_get_user/conv() function is not ready yet"));
+ 			/* it is safe to resume this function so we translate this
+ 			 * retval to the value that indicates we're happy to resume.
+ 			 */
+ 			retval = PAM_INCOMPLETE;
++		} else if (on(UNIX_DEBUG, ctrl)) {
++			pam_syslog(pamh, LOG_DEBUG, "could not obtain username");
+ 		}
+ 		AUTH_RETURN;
+ 	}
+@@ -146,7 +147,7 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
+ 	/* if this user does not have a password... */
+ 
+ 	if (_unix_blankpasswd(pamh, ctrl, name)) {
+-		D(("user '%s' has blank passwd", name));
++		pam_syslog(pamh, LOG_DEBUG, "user [%s] has blank password; authenticated without it", name);
+ 		name = NULL;
+ 		retval = PAM_SUCCESS;
+ 		AUTH_RETURN;
+-- 
+2.20.1
+
diff --git a/SPECS/pam.spec b/SPECS/pam.spec
index 7eb2c7f..315e533 100644
--- a/SPECS/pam.spec
+++ b/SPECS/pam.spec
@@ -3,7 +3,7 @@
 Summary: An extensible library which provides authentication for applications
 Name: pam
 Version: 1.3.1
-Release: 4%{?dist}
+Release: 8%{?dist}
 # The library is BSD licensed with option to relicense as GPLv2+
 # - this option is redundant as the BSD license allows that anyway.
 # pam_timestamp, pam_loginuid, and pam_console modules are GPLv2+.
@@ -44,6 +44,15 @@ Patch32: pam-1.2.1-console-devname.patch
 Patch33: pam-1.3.0-unix-nomsg.patch
 Patch34: pam-1.3.1-coverity.patch
 Patch35: pam-1.3.1-console-build.patch
+Patch36: pam-1.3.1-faillock-update.patch
+Patch37: pam-1.3.1-namespace-mntopts.patch
+Patch38: pam-1.3.1-lastlog-no-showfailed.patch
+Patch39: pam-1.3.1-lastlog-unlimited-fsize.patch
+Patch40: pam-1.3.1-unix-improve-logging.patch
+Patch41: pam-1.3.1-tty-audit-manfix.patch
+Patch42: pam-1.3.1-fds-closing.patch
+Patch43: pam-1.3.1-authtok-verify-fix.patch
+Patch44: pam-1.3.1-motd-manpage.patch
 
 %define _pamlibdir %{_libdir}
 %define _moduledir %{_libdir}/security
@@ -127,6 +136,15 @@ cp %{SOURCE18} .
 %patch33 -p1 -b .nomsg
 %patch34 -p1 -b .coverity
 %patch35 -p1 -b .console-build
+%patch36 -p1 -b .faillock-update
+%patch37 -p1 -b .mntopts
+%patch38 -p1 -b .no-showfailed
+%patch39 -p1 -b .unlimited-fsize
+%patch40 -p1 -b .improve-logging
+%patch41 -p1 -b .tty-audit-manfix
+%patch42 -p1 -b .fds-closing
+%patch43 -p1 -b .authtok-verify-fix
+%patch44 -p1 -b .motd-manpage
 autoreconf -i
 
 %build
@@ -152,6 +170,9 @@ for readme in modules/pam_*/README ; do
 	cp -f ${readme} doc/txts/README.`dirname ${readme} | sed -e 's|^modules/||'`
 done
 
+rm -rf doc/txts/README.pam_tally*
+rm -rf doc/sag/html/*pam_tally*
+
 # Install the binaries, libraries, and modules.
 make install DESTDIR=$RPM_BUILD_ROOT LDCONFIG=:
 
@@ -176,7 +197,6 @@ install -m 644 %{SOURCE10} $RPM_BUILD_ROOT%{_pamconfdir}/config-util
 install -m 644 %{SOURCE16} $RPM_BUILD_ROOT%{_pamconfdir}/postlogin
 install -m 600 /dev/null $RPM_BUILD_ROOT%{_secconfdir}/opasswd
 install -d -m 755 $RPM_BUILD_ROOT/var/log
-install -m 600 /dev/null $RPM_BUILD_ROOT/var/log/tallylog
 install -d -m 755 $RPM_BUILD_ROOT/var/run/faillock
 
 # Install man pages.
@@ -336,6 +356,7 @@ done
 %config(noreplace) %{_secconfdir}/chroot.conf
 %config %{_secconfdir}/console.perms
 %config(noreplace) %{_secconfdir}/console.handlers
+%config(noreplace) %{_secconfdir}/faillock.conf
 %config(noreplace) %{_secconfdir}/group.conf
 %config(noreplace) %{_secconfdir}/limits.conf
 %dir %{_secconfdir}/limits.d
@@ -352,7 +373,6 @@ done
 %config(noreplace) %{_secconfdir}/sepermit.conf
 %dir /var/run/sepermit
 %endif
-%ghost %verify(not md5 size mtime) /var/log/tallylog
 %dir /var/run/faillock
 %{_prefix}/lib/tmpfiles.d/pam.conf
 %{_mandir}/man5/*
@@ -369,6 +389,24 @@ done
 %doc doc/specs/rfc86.0.txt
 
 %changelog
+* Thu Dec 19 2019 Tomáš Mráz <tmraz@redhat.com> 1.3.1-8
+- pam_motd: Document how to properly silence unwanted motd messages
+
+* Mon Dec 16 2019 Tomáš Mráz <tmraz@redhat.com> 1.3.1-6
+- pam_faillock: Fix regression in admin_group support
+
+* Wed Oct 16 2019 Tomáš Mráz <tmraz@redhat.com> 1.3.1-5
+- pam_faillock: Support configuration file /etc/security/faillock.conf
+- pam_faillock: Support local_users_only option
+- pam_namespace: Support noexec, nosuid and nodev flags for tmpfs mounts
+- Drop tallylog and pam_tally[2] documentation
+- pam_lastlog: Do not display failed attempts with PAM_SILENT flag
+- pam_lastlog: Support unlimited option to override fsize limit
+- pam_unix: Log if user authenticated without password
+- pam_tty_audit: Improve manual page
+- Optimize closing fds when spawning helpers
+- Fix duplicate password verification in pam_authtok_verify()
+
 * Fri Dec  7 2018 Tomáš Mráz <tmraz@redhat.com> 1.3.1-4
 - Drop pam_tally2 which was obsoleted and deprecated long time ago