diff --git a/SOURCES/pam-1.3.1-pam-keyinit-thread-safe.patch b/SOURCES/pam-1.3.1-pam-keyinit-thread-safe.patch
new file mode 100644
index 0000000..1f322a1
--- /dev/null
+++ b/SOURCES/pam-1.3.1-pam-keyinit-thread-safe.patch
@@ -0,0 +1,125 @@
+diff -up Linux-PAM-1.3.1/modules/pam_keyinit/pam_keyinit.c.pam_keyinit-thread-safe Linux-PAM-1.3.1/modules/pam_keyinit/pam_keyinit.c
+--- Linux-PAM-1.3.1/modules/pam_keyinit/pam_keyinit.c.pam_keyinit-thread-safe	2017-02-10 11:10:15.000000000 +0100
++++ Linux-PAM-1.3.1/modules/pam_keyinit/pam_keyinit.c	2022-04-25 12:10:28.071240439 +0200
+@@ -20,6 +20,7 @@
+ #include <security/pam_modutil.h>
+ #include <security/pam_ext.h>
+ #include <sys/syscall.h>
++#include <stdatomic.h>
+ 
+ #define KEY_SPEC_SESSION_KEYRING	-3 /* ID for session keyring */
+ #define KEY_SPEC_USER_KEYRING		-4 /* ID for UID-specific keyring */
+@@ -30,12 +31,12 @@
+ #define KEYCTL_REVOKE			3 /* revoke a key */
+ #define KEYCTL_LINK			8 /* link a key into a keyring */
+ 
+-static int my_session_keyring;
+-static int session_counter;
+-static int do_revoke;
+-static int revoke_as_uid;
+-static int revoke_as_gid;
+-static int xdebug = 0;
++static _Thread_local int my_session_keyring = 0;
++static _Atomic int session_counter = 0;
++static _Thread_local int do_revoke = 0;
++static _Thread_local uid_t revoke_as_uid;
++static _Thread_local gid_t revoke_as_gid;
++static _Thread_local int xdebug = 0;
+ 
+ static void debug(pam_handle_t *pamh, const char *fmt, ...)
+ 	__attribute__((format(printf, 2, 3)));
+@@ -65,6 +66,33 @@ static int error(pam_handle_t *pamh, con
+ 	return PAM_SESSION_ERR;
+ }
+ 
++static int pam_setreuid(uid_t ruid, uid_t euid)
++{
++#if defined(SYS_setreuid32)
++    return syscall(SYS_setreuid32, ruid, euid);
++#else
++    return syscall(SYS_setreuid, ruid, euid);
++#endif
++}
++
++static int pam_setregid(gid_t rgid, gid_t egid)
++{
++#if defined(SYS_setregid32)
++    return syscall(SYS_setregid32, rgid, egid);
++#else
++    return syscall(SYS_setregid, rgid, egid);
++#endif
++}
++
++static int pam_setresuid(uid_t ruid, uid_t euid, uid_t suid)
++{
++#if defined(SYS_setresuid32)
++    return syscall(SYS_setresuid32, ruid, euid, suid);
++#else
++    return syscall(SYS_setresuid, ruid, euid, suid);
++#endif
++}
++
+ /*
+  * initialise the session keyring for this process
+  */
+@@ -139,23 +167,25 @@ static void kill_keyrings(pam_handle_t *
+ 
+ 		/* switch to the real UID and GID so that we have permission to
+ 		 * revoke the key */
+-		if (revoke_as_gid != old_gid && setregid(-1, revoke_as_gid) < 0)
++		if (revoke_as_gid != old_gid && pam_setregid(-1, revoke_as_gid) < 0)
+ 			error(pamh, "Unable to change GID to %d temporarily\n",
+ 			      revoke_as_gid);
+ 
+-		if (revoke_as_uid != old_uid && setresuid(-1, revoke_as_uid, old_uid) < 0)
++		if (revoke_as_uid != old_uid && pam_setresuid(-1, revoke_as_uid, old_uid) < 0)
+ 			error(pamh, "Unable to change UID to %d temporarily\n",
+ 			      revoke_as_uid);
++			if (getegid() != old_gid && pam_setregid(-1, old_gid) < 0)
++				error(pamh, "Unable to change GID back to %d\n", old_gid);
+ 
+ 		syscall(__NR_keyctl,
+ 			KEYCTL_REVOKE,
+ 			my_session_keyring);
+ 
+ 		/* return to the orignal UID and GID (probably root) */
+-		if (revoke_as_uid != old_uid && setreuid(-1, old_uid) < 0)
++		if (revoke_as_uid != old_uid && pam_setreuid(-1, old_uid) < 0)
+ 			error(pamh, "Unable to change UID back to %d\n", old_uid);
+ 
+-		if (revoke_as_gid != old_gid && setregid(-1, old_gid) < 0)
++		if (revoke_as_gid != old_gid && pam_setregid(-1, old_gid) < 0)
+ 			error(pamh, "Unable to change GID back to %d\n", old_gid);
+ 
+ 		my_session_keyring = 0;
+@@ -210,14 +240,14 @@ int pam_sm_open_session(pam_handle_t *pa
+ 
+ 	/* switch to the real UID and GID so that the keyring ends up owned by
+ 	 * the right user */
+-	if (gid != old_gid && setregid(gid, -1) < 0) {
++	if (gid != old_gid && pam_setregid(gid, -1) < 0) {
+ 		error(pamh, "Unable to change GID to %d temporarily\n", gid);
+ 		return PAM_SESSION_ERR;
+ 	}
+ 
+-	if (uid != old_uid && setreuid(uid, -1) < 0) {
++	if (uid != old_uid && pam_setreuid(uid, -1) < 0) {
+ 		error(pamh, "Unable to change UID to %d temporarily\n", uid);
+-		if (setregid(old_gid, -1) < 0)
++		if (pam_setregid(old_gid, -1) < 0)
+ 			error(pamh, "Unable to change GID back to %d\n", old_gid);
+ 		return PAM_SESSION_ERR;
+ 	}
+@@ -225,10 +255,10 @@ int pam_sm_open_session(pam_handle_t *pa
+ 	ret = init_keyrings(pamh, force);
+ 
+ 	/* return to the orignal UID and GID (probably root) */
+-	if (uid != old_uid && setreuid(old_uid, -1) < 0)
++	if (uid != old_uid && pam_setreuid(old_uid, -1) < 0)
+ 		ret = error(pamh, "Unable to change UID back to %d\n", old_uid);
+ 
+-	if (gid != old_gid && setregid(old_gid, -1) < 0)
++	if (gid != old_gid && pam_setregid(old_gid, -1) < 0)
+ 		ret = error(pamh, "Unable to change GID back to %d\n", old_gid);
+ 
+ 	return ret;
diff --git a/SOURCES/pam-1.3.1-pam-motd-fix-memory-leak.patch b/SOURCES/pam-1.3.1-pam-motd-fix-memory-leak.patch
new file mode 100644
index 0000000..932633b
--- /dev/null
+++ b/SOURCES/pam-1.3.1-pam-motd-fix-memory-leak.patch
@@ -0,0 +1,57 @@
+From 62cd745d730e5ba13d5d7092ac566fc0b2148e61 Mon Sep 17 00:00:00 2001
+From: "Dmitry V. Levin" <ldv@altlinux.org>
+Date: Sun, 26 Apr 2020 11:12:59 +0000
+Subject: [PATCH] pam_motd: fix memory leak
+
+pam_motd used to leak memory allocated for each motd file
+successfully opened in try_to_display_directories_with_overrides.
+
+* modules/pam_motd/pam_motd.c
+(try_to_display_directories_with_overrides): Free abs_path.
+
+Fixes: f9c9c721 ("pam_motd: Support multiple motd paths specified, with filename overrides (#69)")
+---
+ modules/pam_motd/pam_motd.c | 20 ++++++++++----------
+ 1 file changed, 10 insertions(+), 10 deletions(-)
+
+diff --git a/modules/pam_motd/pam_motd.c b/modules/pam_motd/pam_motd.c
+index f0cd317d..3be129a5 100644
+--- a/modules/pam_motd/pam_motd.c
++++ b/modules/pam_motd/pam_motd.c
+@@ -259,23 +259,23 @@ static void try_to_display_directories_with_overrides(pam_handle_t *pamh,
+ 
+ 	for (j = 0; j < num_motd_dirs; j++) {
+ 	    char *abs_path = NULL;
++	    int fd;
+ 
+ 	    if (join_dir_strings(&abs_path, motd_dir_path_split[j],
+-		    dirnames_all[i]) < 0) {
++		    dirnames_all[i]) < 0 || abs_path == NULL) {
+ 		continue;
+ 	    }
+ 
+-	    if (abs_path != NULL) {
+-		int fd = open(abs_path, O_RDONLY, 0);
+-		if (fd >= 0) {
+-		    try_to_display_fd(pamh, fd);
+-		    close(fd);
++	    fd = open(abs_path, O_RDONLY, 0);
++	    _pam_drop(abs_path);
+ 
+-		    /* We displayed a file, skip to the next file name. */
+-		    break;
+-		}
++	    if (fd >= 0) {
++		try_to_display_fd(pamh, fd);
++		close(fd);
++
++		/* We displayed a file, skip to the next file name. */
++		break;
+ 	    }
+-	    _pam_drop(abs_path);
+ 	}
+     }
+ 
+-- 
+2.35.3
+
diff --git a/SOURCES/pam-1.3.1-pam-motd-fix-segmentation-fault.patch b/SOURCES/pam-1.3.1-pam-motd-fix-segmentation-fault.patch
new file mode 100644
index 0000000..af72866
--- /dev/null
+++ b/SOURCES/pam-1.3.1-pam-motd-fix-segmentation-fault.patch
@@ -0,0 +1,133 @@
+From 8eaf5570cf011148a0b55c53570df5edaafebdb0 Mon Sep 17 00:00:00 2001
+From: Robert Fairley <rfairley@users.noreply.github.com>
+Date: Wed, 21 Nov 2018 02:46:02 -0500
+Subject: [PATCH] pam_motd: Fix segmentation fault when no motd_dir specified
+ (#76)
+
+This fixes a regression introduced by #69, where motd_path was set
+to NULL and passed into strdup() if the motd_dir argument was
+not specified in the configuration file. This caused a segmentation
+fault.
+
+* modules/pam_motd/pam_motd.c: fix checks for NULL in arguments
+* xtests/Makefile.am: add test scripts and config file
+* xtests/tst-pam_motd.sh: add running tst-pam_motd4.sh
+* xtests/tst-pam_motd4.pamd: create
+* xtests/tst-pam_motd4.sh: create
+---
+ modules/pam_motd/pam_motd.c | 15 ++++++++++-----
+ xtests/Makefile.am          |  4 ++--
+ xtests/tst-pam_motd.sh      |  1 +
+ xtests/tst-pam_motd4.pamd   |  3 +++
+ xtests/tst-pam_motd4.sh     | 27 +++++++++++++++++++++++++++
+ 5 files changed, 43 insertions(+), 7 deletions(-)
+ create mode 100644 xtests/tst-pam_motd4.pamd
+ create mode 100755 xtests/tst-pam_motd4.sh
+
+diff --git a/modules/pam_motd/pam_motd.c b/modules/pam_motd/pam_motd.c
+index 1c1cfcfa..ec3ebd58 100644
+--- a/modules/pam_motd/pam_motd.c
++++ b/modules/pam_motd/pam_motd.c
+@@ -132,7 +132,6 @@ static int pam_split_string(const pam_handle_t *pamh, char *arg, char delim,
+ 	goto out;
+     }
+ 
+-
+     arg_extracted = strtok_r(arg, delim_str, &arg);
+     while (arg_extracted != NULL && i < num_strs) {
+ 	arg_split[i++] = arg_extracted;
+@@ -363,15 +362,21 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags,
+ 	motd_dir_path = default_motd_dir;
+     }
+ 
+-    motd_path_copy = strdup(motd_path);
++    if (motd_path != NULL) {
++	motd_path_copy = strdup(motd_path);
++    }
++
+     if (motd_path_copy != NULL) {
+-	if (pam_split_string(pamh, motd_path_copy, ':', &motd_path_split,
+-		&num_motd_paths) == 0) {
++	if (pam_split_string(pamh, motd_path_copy, ':',
++		&motd_path_split, &num_motd_paths) == 0) {
+ 	    goto out;
+ 	}
+     }
+ 
+-    motd_dir_path_copy = strdup(motd_dir_path);
++    if (motd_dir_path != NULL) {
++	motd_dir_path_copy = strdup(motd_dir_path);
++    }
++
+     if (motd_dir_path_copy != NULL) {
+ 	if (pam_split_string(pamh, motd_dir_path_copy, ':',
+ 		&motd_dir_path_split, &num_motd_dir_paths) == 0) {
+diff --git a/xtests/Makefile.am b/xtests/Makefile.am
+index 555d5e33..4d5aba3d 100644
+--- a/xtests/Makefile.am
++++ b/xtests/Makefile.am
+@@ -34,8 +34,8 @@ EXTRA_DIST = run-xtests.sh tst-pam_dispatch1.pamd tst-pam_dispatch2.pamd \
+ 	tst-pam_pwhistory1.pamd tst-pam_pwhistory1.sh \
+ 	tst-pam_time1.pamd time.conf \
+ 	tst-pam_motd.sh tst-pam_motd1.sh tst-pam_motd2.sh \
+-	tst-pam_motd3.sh tst-pam_motd1.pamd \
+-	tst-pam_motd2.pamd tst-pam_motd3.pamd
++	tst-pam_motd3.sh tst-pam_motd4.sh tst-pam_motd1.pamd \
++	tst-pam_motd2.pamd tst-pam_motd3.pamd tst-pam_motd4.pamd
+ 
+ XTESTS = tst-pam_dispatch1 tst-pam_dispatch2 tst-pam_dispatch3 \
+ 	tst-pam_dispatch4 tst-pam_dispatch5 \
+diff --git a/xtests/tst-pam_motd.sh b/xtests/tst-pam_motd.sh
+index 9b0c38f6..90801280 100755
+--- a/xtests/tst-pam_motd.sh
++++ b/xtests/tst-pam_motd.sh
+@@ -5,3 +5,4 @@ set -e
+ ./tst-pam_motd1.sh
+ ./tst-pam_motd2.sh
+ ./tst-pam_motd3.sh
++./tst-pam_motd4.sh
+diff --git a/xtests/tst-pam_motd4.pamd b/xtests/tst-pam_motd4.pamd
+new file mode 100644
+index 00000000..9dc311ad
+--- /dev/null
++++ b/xtests/tst-pam_motd4.pamd
+@@ -0,0 +1,3 @@
++#%PAM-1.0
++session    required    pam_permit.so
++session    optional    pam_motd.so motd=tst-pam_motd4.d/etc/motd
+diff --git a/xtests/tst-pam_motd4.sh b/xtests/tst-pam_motd4.sh
+new file mode 100755
+index 00000000..6022177f
+--- /dev/null
++++ b/xtests/tst-pam_motd4.sh
+@@ -0,0 +1,27 @@
++#!/bin/bash
++
++TST_DIR="tst-pam_motd4.d"
++
++function tst_cleanup() {
++    rm -rf "${TST_DIR}"
++    rm -f tst-pam_motd4.out
++}
++
++mkdir -p ${TST_DIR}/etc
++
++# Verify the case of single motd with no motd_dir given in tst-pam_motd4.pamd
++echo "motd: /etc/motd" > ${TST_DIR}/etc/motd
++
++./tst-pam_motd tst-pam_motd4 > tst-pam_motd4.out
++
++RET=$?
++
++motd_to_show_output=$(cat tst-pam_motd4.out | grep "motd: /etc/motd")
++if [ -z "${motd_to_show_output}" ];
++then
++    tst_cleanup
++    exit 1
++fi
++
++tst_cleanup
++exit $RET
+-- 
+2.35.1
+
diff --git a/SOURCES/pam-1.3.1-pam-motd-support-multiple-motd-paths.patch b/SOURCES/pam-1.3.1-pam-motd-support-multiple-motd-paths.patch
new file mode 100644
index 0000000..f81ecbe
--- /dev/null
+++ b/SOURCES/pam-1.3.1-pam-motd-support-multiple-motd-paths.patch
@@ -0,0 +1,691 @@
+diff -up Linux-PAM-1.3.1/modules/pam_motd/pam_motd.8.xml.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/modules/pam_motd/pam_motd.8.xml
+--- Linux-PAM-1.3.1/modules/pam_motd/pam_motd.8.xml.pam_motd-support-multiple-motd-paths1	2022-04-25 12:32:36.939663167 +0200
++++ Linux-PAM-1.3.1/modules/pam_motd/pam_motd.8.xml	2022-04-25 12:34:43.506582206 +0200
+@@ -21,6 +21,9 @@
+       <arg choice="opt">
+         motd=<replaceable>/path/filename</replaceable>
+       </arg>
++      <arg choice="opt">
++        motd_dir=<replaceable>/path/dirname.d</replaceable>
++      </arg>
+     </cmdsynopsis>
+   </refsynopsisdiv>
+ 
+@@ -31,18 +34,49 @@
+     <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 and
+-      all files from <filename>/etc/motd.d</filename> are
+-      shown. The message size is limited to 64KB.
++      login. By default, pam_motd shows files in the
++      following locations:
++    </para>
++    <para>
++      <simplelist type='vert'>
++        <member><filename>/etc/motd</filename></member>
++        <member><filename>/run/motd</filename></member>
++        <member><filename>/usr/lib/motd</filename></member>
++        <member><filename>/etc/motd.d/</filename></member>
++        <member><filename>/run/motd.d/</filename></member>
++        <member><filename>/usr/lib/motd.d/</filename></member>
++      </simplelist>
++    </para>
++    <para>
++      Each message size is limited to 64KB.
++    </para>
++    <para>
++      If <filename>/etc/motd</filename> does not exist,
++      then <filename>/run/motd</filename> is shown. If
++      <filename>/run/motd</filename> does not exist, then
++      <filename>/usr/lib/motd</filename> is shown.
++    </para>
++    <para>
++      Similar overriding behavior applies to the directories.
++      Files in <filename>/etc/motd.d/</filename> override files
++      with the same name in <filename>/run/motd.d/</filename> and
++      <filename>/usr/lib/motd.d/</filename>. Files in <filename>/run/motd.d/</filename>
++      override files with the same name in <filename>/usr/lib/motd.d/</filename>.
++    </para>
++    <para>
++      Files in the directories listed above are displayed in lexicographic
++      order by name. Moreover, the files are filtered by reading them with the
++      credentials of the target user authenticating on the system.
+     </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:
++      Creating a symbolic link as follows silences <filename>/usr/lib/motd.d/my_motd</filename>.
+     </para>
+     <para>
+-      <command>ln -sfn /dev/null /etc/motd.d/my_motd</command>
++      <command>ln -s /dev/null /etc/motd.d/my_motd</command>
+     </para>
+   </refsect1>
+ 
+@@ -56,8 +90,10 @@
+         </term>
+         <listitem>
+           <para>
+-	    The <filename>/path/filename</filename> file is displayed
+-            as message of the day.
++            The <filename>/path/filename</filename> file is displayed
++            as message of the day. Multiple paths to try can be
++            specified as a colon-separated list. By default this option
++            is set to <filename>/etc/motd:/run/motd:/usr/lib/motd</filename>.
+           </para>
+         </listitem>
+       </varlistentry>
+@@ -68,16 +104,17 @@
+         <listitem>
+           <para>
+             The <filename>/path/dirname.d</filename> directory is scanned
+-            and each file contained inside of it is displayed.
++            and each file contained inside of it is displayed. Multiple
++            directories to scan can be specified as a colon-separated list.
++            By default this option is set to <filename>/etc/motd.d:/run/motd.d:/usr/lib/motd.d</filename>.
+           </para>
+         </listitem>
+       </varlistentry>
+     </variablelist>
+     <para>
+-      When no options are given, the default is to display both
+-      <filename>/etc/motd</filename> and the contents of
+-      <filename>/etc/motd.d</filename>.  Specifying either option (or both)
+-      will disable this default behavior.
++      When no options are given, the default behavior applies for both
++      options. Specifying either option (or both) will disable the
++      default behavior for both options.
+     </para>
+   </refsect1>
+ 
+diff -up Linux-PAM-1.3.1/modules/pam_motd/pam_motd.c.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/modules/pam_motd/pam_motd.c
+--- Linux-PAM-1.3.1/modules/pam_motd/pam_motd.c.pam_motd-support-multiple-motd-paths1	2018-05-18 11:50:46.000000000 +0200
++++ Linux-PAM-1.3.1/modules/pam_motd/pam_motd.c	2022-04-25 12:32:36.947663225 +0200
+@@ -33,8 +33,8 @@
+  */
+ 
+ #define PAM_SM_SESSION
+-#define DEFAULT_MOTD	"/etc/motd"
+-#define DEFAULT_MOTD_D	"/etc/motd.d"
++#define DEFAULT_MOTD	"/etc/motd:/run/motd:/usr/lib/motd"
++#define DEFAULT_MOTD_D	"/etc/motd.d:/run/motd.d:/usr/lib/motd.d"
+ 
+ #include <security/pam_modules.h>
+ #include <security/pam_modutil.h>
+@@ -97,12 +97,235 @@ static void try_to_display_directory(pam
+     }
+ }
+ 
++/*
++ * Split a DELIM-separated string ARG into an array.
++ * Outputs a newly allocated array of strings OUT_ARG_SPLIT
++ * and the number of strings OUT_NUM_STRS.
++ * Returns 0 in case of error, 1 in case of success.
++ */
++static int pam_split_string(const pam_handle_t *pamh, char *arg, char delim,
++			    char ***out_arg_split, uint *out_num_strs)
++{
++    char *arg_extracted = NULL;
++    const char *arg_ptr = arg;
++    char **arg_split = NULL;
++    char delim_str[2];
++    int i = 0;
++    uint num_strs = 0;
++    int retval = 0;
++
++    delim_str[0] = delim;
++    delim_str[1] = '\0';
++
++    if (arg == NULL) {
++	goto out;
++    }
++
++    while (arg_ptr != NULL) {
++	num_strs++;
++	arg_ptr = strchr(arg_ptr + sizeof(const char), delim);
++    }
++
++    arg_split = (char **)calloc(num_strs, sizeof(char *));
++    if (arg_split == NULL) {
++	pam_syslog(pamh, LOG_CRIT, "pam_motd: failed to allocate string array");
++	goto out;
++    }
++
++
++    arg_extracted = strtok_r(arg, delim_str, &arg);
++    while (arg_extracted != NULL && i < num_strs) {
++	arg_split[i++] = arg_extracted;
++	arg_extracted = strtok_r(NULL, delim_str, &arg);
++    }
++
++    retval = 1;
++
++  out:
++    *out_num_strs = num_strs;
++    *out_arg_split = arg_split;
++
++    return retval;
++}
++
++/* Join A_STR and B_STR, inserting a "/" between them if one is not already trailing
++ * in A_STR or beginning B_STR. A pointer to a newly allocated string holding the
++ * joined string is returned in STRP_OUT.
++ * Returns -1 in case of error, or the number of bytes in the joined string in
++ * case of success. */
++static int join_dir_strings(char **strp_out, const char *a_str, const char *b_str)
++{
++    int has_sep = 0;
++    int retval = -1;
++    char *join_strp = NULL;
++    
++    if (strp_out == NULL || a_str == NULL || b_str == NULL) {
++	goto out;
++    }
++    if (strlen(a_str) == 0) {
++	goto out;
++    }
++
++    has_sep = (a_str[strlen(a_str) - 1] == '/') || (b_str[0] == '/');
++
++    retval = asprintf(&join_strp, "%s%s%s", a_str,
++	(has_sep == 1) ? "" : "/", b_str);
++
++    if (retval < 0) {
++	goto out;
++    }
++
++    *strp_out = join_strp;
++
++  out:
++    return retval;
++}
++
++static int compare_strings(const void * a, const void * b)
++{
++    const char *a_str = *(char **)a;
++    const char *b_str = *(char **)b;
++
++    if (a_str == NULL && b_str == NULL) {
++        return 0;
++    }
++    else if (a_str == NULL) {
++	return -1;
++    }
++    else if (b_str == NULL) {
++	return 1;
++    }
++    else {
++	return strcmp(a_str, b_str);
++    }
++}
++
++static int filter_dirents(const struct dirent *d)
++{
++    return (d->d_type == DT_REG || d->d_type == DT_LNK);
++}
++
++static void try_to_display_directories_with_overrides(pam_handle_t *pamh,
++	char **motd_dir_path_split, int num_motd_dirs)
++{
++    struct dirent ***dirscans = NULL;
++    int *dirscans_sizes = NULL;
++    int dirscans_size_total = 0;
++    char **dirnames_all = NULL;
++    int i;
++    int i_dirnames = 0;
++
++    if (pamh == NULL || motd_dir_path_split == NULL) {
++	goto out;
++    }
++    if (num_motd_dirs < 1) {
++	goto out;
++    }
++
++    if ((dirscans = (struct dirent ***)calloc(num_motd_dirs,
++	    sizeof(struct dirent **))) == NULL) {
++	pam_syslog(pamh, LOG_CRIT, "pam_motd: failed to allocate dirent arrays");
++	goto out;
++    }
++    if ((dirscans_sizes = (int *)calloc(num_motd_dirs, sizeof(int))) == NULL) {
++	pam_syslog(pamh, LOG_CRIT, "pam_motd: failed to allocate dirent array sizes");
++	goto out;
++    }
++
++    for (i = 0; i < num_motd_dirs; i++) {
++	dirscans_sizes[i] = scandir(motd_dir_path_split[i], &(dirscans[i]),
++		filter_dirents, alphasort);
++	if (dirscans_sizes[i] < 0) {
++	    pam_syslog(pamh, LOG_ERR, "pam_motd: error scanning directory %s", motd_dir_path_split[i]);
++	    dirscans_sizes[i] = 0;
++	}
++	dirscans_size_total += dirscans_sizes[i];
++    }
++
++    /* Allocate space for all file names found in the directories, including duplicates. */
++    if ((dirnames_all = (char **)calloc(dirscans_size_total,
++	    sizeof(char *))) == NULL) {
++	pam_syslog(pamh, LOG_CRIT, "pam_motd: failed to allocate dirname array");
++	goto out;
++    }
++
++    for (i = 0; i < dirscans_size_total; i++) {
++	dirnames_all[i] = NULL;
++    }
++
++    for (i = 0; i < num_motd_dirs; i++) {
++	int j;
++
++	for (j = 0; j < dirscans_sizes[i]; j++) {
++	    dirnames_all[i_dirnames] = dirscans[i][j]->d_name;
++	    i_dirnames++;
++	}
++    }
++
++    qsort(dirnames_all, dirscans_size_total,
++	    sizeof(const char *), compare_strings);
++
++    for (i = 0; i < dirscans_size_total; i++) {
++	int j;
++
++	if (dirnames_all[i] == NULL) {
++	    continue;
++	}
++
++	/* Skip duplicate file names. */
++	if (i > 0 && strcmp(dirnames_all[i], dirnames_all[i - 1]) == 0) {
++	    continue;
++	}
++
++	for (j = 0; j < num_motd_dirs; j++) {
++	    char *abs_path = NULL;
++
++	    if (join_dir_strings(&abs_path, motd_dir_path_split[j],
++		    dirnames_all[i]) < 0) {
++		continue;
++	    }
++
++	    if (abs_path != NULL) {
++		int fd = open(abs_path, O_RDONLY, 0);
++		if (fd >= 0) {
++		    try_to_display_fd(pamh, fd);
++		    close(fd);
++
++		    /* We displayed a file, skip to the next file name. */
++		    break;
++		}
++	    }
++	    _pam_drop(abs_path);
++	}
++    }
++
++  out:
++    _pam_drop(dirnames_all);
++    for (i = 0; i < num_motd_dirs; i++) {
++	int j;
++	for (j = 0; j < dirscans_sizes[i]; j++) {
++	    _pam_drop(dirscans[i][j]);
++	}
++	_pam_drop(dirscans[i]);
++    }
++    _pam_drop(dirscans_sizes);
++    _pam_drop(dirscans);
++
++    return;
++}
++
+ int pam_sm_open_session(pam_handle_t *pamh, int flags,
+ 			int argc, const char **argv)
+ {
+     int retval = PAM_IGNORE;
+     const char *motd_path = NULL;
++    char *motd_path_copy = NULL;
++    int num_motd_paths = 0;
++    char **motd_path_split = NULL;
+     const char *motd_dir_path = NULL;
++    char *motd_dir_path_copy = NULL;
++    int num_motd_dir_paths = 0;
++    char **motd_dir_path_split = NULL;
+ 
+     if (flags & PAM_SILENT) {
+ 	return retval;
+@@ -140,17 +363,47 @@ int pam_sm_open_session(pam_handle_t *pa
+ 	motd_dir_path = default_motd_dir;
+     }
+ 
+-    if (motd_path != NULL) {
+-	int fd = open(motd_path, O_RDONLY, 0);
++    motd_path_copy = strdup(motd_path);
++    if (motd_path_copy != NULL) {
++	if (pam_split_string(pamh, motd_path_copy, ':', &motd_path_split,
++		&num_motd_paths) == 0) {
++	    goto out;
++	}
++    }
++
++    motd_dir_path_copy = strdup(motd_dir_path);
++    if (motd_dir_path_copy != NULL) {
++	if (pam_split_string(pamh, motd_dir_path_copy, ':',
++		&motd_dir_path_split, &num_motd_dir_paths) == 0) {
++	    goto out;
++	}
++    }
++
++    if (motd_path_split != NULL) {
++	int i;
++
++	for (i = 0; i < num_motd_paths; i++) {
++	    int fd = open(motd_path_split[i], O_RDONLY, 0);
+ 
+-	if (fd >= 0) {
+-	    try_to_display_fd(pamh, fd);
+-	    close(fd);
++	    if (fd >= 0) {
++		try_to_display_fd(pamh, fd);
++		close(fd);
++
++		/* We found and displayed a file, move onto next filename. */
++		break;
++	    }
+ 	}
+     }
+ 
+-    if (motd_dir_path != NULL)
+-	try_to_display_directory(pamh, motd_dir_path);
++    if (motd_dir_path_split != NULL)
++	try_to_display_directories_with_overrides(pamh, motd_dir_path_split,
++		num_motd_dir_paths);
++
++  out:
++    _pam_drop(motd_path_copy);
++    _pam_drop(motd_path_split);
++    _pam_drop(motd_dir_path_copy);
++    _pam_drop(motd_dir_path_split);
+ 
+     return retval;
+ }
+diff -up Linux-PAM-1.3.1/xtests/Makefile.am.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/xtests/Makefile.am
+--- Linux-PAM-1.3.1/xtests/Makefile.am.pam_motd-support-multiple-motd-paths1	2017-02-10 11:10:15.000000000 +0100
++++ Linux-PAM-1.3.1/xtests/Makefile.am	2022-04-25 12:32:36.947663225 +0200
+@@ -32,7 +32,10 @@ EXTRA_DIST = run-xtests.sh tst-pam_dispa
+ 	tst-pam_substack5.pamd tst-pam_substack5a.pamd tst-pam_substack5.sh \
+ 	tst-pam_assemble_line1.pamd tst-pam_assemble_line1.sh \
+ 	tst-pam_pwhistory1.pamd tst-pam_pwhistory1.sh \
+-	tst-pam_time1.pamd time.conf
++	tst-pam_time1.pamd time.conf \
++	tst-pam_motd.sh tst-pam_motd1.sh tst-pam_motd2.sh \
++	tst-pam_motd3.sh tst-pam_motd1.pamd \
++	tst-pam_motd2.pamd tst-pam_motd3.pamd
+ 
+ XTESTS = tst-pam_dispatch1 tst-pam_dispatch2 tst-pam_dispatch3 \
+ 	tst-pam_dispatch4 tst-pam_dispatch5 \
+@@ -41,7 +44,7 @@ XTESTS = tst-pam_dispatch1 tst-pam_dispa
+ 	tst-pam_access1 tst-pam_access2 tst-pam_access3 \
+ 	tst-pam_access4 tst-pam_limits1 tst-pam_succeed_if1 \
+ 	tst-pam_group1 tst-pam_authfail tst-pam_authsucceed \
+-	tst-pam_pwhistory1 tst-pam_time1
++	tst-pam_pwhistory1 tst-pam_time1 tst-pam_motd
+ 
+ NOSRCTESTS = tst-pam_substack1 tst-pam_substack2 tst-pam_substack3 \
+ 	tst-pam_substack4 tst-pam_substack5 tst-pam_assemble_line1
+diff -up Linux-PAM-1.3.1/xtests/tst-pam_motd1.pamd.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/xtests/tst-pam_motd1.pamd
+--- Linux-PAM-1.3.1/xtests/tst-pam_motd1.pamd.pam_motd-support-multiple-motd-paths1	2022-04-25 12:32:36.947663225 +0200
++++ Linux-PAM-1.3.1/xtests/tst-pam_motd1.pamd	2022-04-25 12:32:36.947663225 +0200
+@@ -0,0 +1,3 @@
++#%PAM-1.0
++session    required    pam_permit.so
++session    optional    pam_motd.so motd=tst-pam_motd1.d/etc/motd motd_dir=tst-pam_motd1.d/etc/motd.d
+diff -up Linux-PAM-1.3.1/xtests/tst-pam_motd1.sh.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/xtests/tst-pam_motd1.sh
+--- Linux-PAM-1.3.1/xtests/tst-pam_motd1.sh.pam_motd-support-multiple-motd-paths1	2022-04-25 12:32:36.947663225 +0200
++++ Linux-PAM-1.3.1/xtests/tst-pam_motd1.sh	2022-04-25 12:32:36.947663225 +0200
+@@ -0,0 +1,36 @@
++#!/bin/bash
++
++TST_DIR="tst-pam_motd1.d"
++
++function tst_cleanup() {
++    rm -rf "${TST_DIR}"
++    rm -f tst-pam_motd1.out
++}
++
++mkdir -p ${TST_DIR}
++mkdir -p ${TST_DIR}/etc/motd.d
++
++# Verify the case of single motd and motd.d directory works
++echo "motd: /etc/motd" > ${TST_DIR}/etc/motd
++echo "motd: /etc/motd.d/test" > ${TST_DIR}/etc/motd.d/test
++
++./tst-pam_motd tst-pam_motd1 > tst-pam_motd1.out
++
++RET=$?
++
++motd_to_show_output=$(cat tst-pam_motd1.out | grep "motd: /etc/motd")
++if [ -z "${motd_to_show_output}" ];
++then
++    tst_cleanup
++    exit 1
++fi
++
++motd_dir_to_show_output=$(cat tst-pam_motd1.out | grep "motd: /etc/motd.d/test")
++if [ -z "${motd_dir_to_show_output}" ];
++then
++    tst_cleanup
++    exit 1
++fi
++
++tst_cleanup
++exit $RET
+diff -up Linux-PAM-1.3.1/xtests/tst-pam_motd2.pamd.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/xtests/tst-pam_motd2.pamd
+--- Linux-PAM-1.3.1/xtests/tst-pam_motd2.pamd.pam_motd-support-multiple-motd-paths1	2022-04-25 12:32:36.947663225 +0200
++++ Linux-PAM-1.3.1/xtests/tst-pam_motd2.pamd	2022-04-25 12:32:36.947663225 +0200
+@@ -0,0 +1,3 @@
++#%PAM-1.0
++session    required    pam_permit.so
++session optional    pam_motd.so    motd=tst-pam_motd2.d/etc/motd:tst-pam_motd2.d/run/motd:tst-pam_motd2.d/usr/lib/motd motd_dir=tst-pam_motd2.d/etc/motd.d:tst-pam_motd2.d/run/motd.d:tst-pam_motd2.d/usr/lib/motd.d
+diff -up Linux-PAM-1.3.1/xtests/tst-pam_motd2.sh.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/xtests/tst-pam_motd2.sh
+--- Linux-PAM-1.3.1/xtests/tst-pam_motd2.sh.pam_motd-support-multiple-motd-paths1	2022-04-25 12:32:36.947663225 +0200
++++ Linux-PAM-1.3.1/xtests/tst-pam_motd2.sh	2022-04-25 12:32:36.947663225 +0200
+@@ -0,0 +1,53 @@
++#!/bin/bash
++
++TST_DIR="tst-pam_motd2.d"
++
++function tst_cleanup() {
++    rm -rf "${TST_DIR}"
++    rm -f tst-pam_motd2.out
++}
++
++mkdir -p ${TST_DIR}
++mkdir -p ${TST_DIR}/etc/motd.d
++mkdir -p ${TST_DIR}/run/motd.d
++mkdir -p ${TST_DIR}/usr/lib/motd.d
++
++echo "motd: /etc/motd" > ${TST_DIR}/etc/motd
++echo "motd: /run/motd" > ${TST_DIR}/run/motd
++echo "motd: /usr/lib/motd" > ${TST_DIR}/usr/lib/motd
++
++# Drop a motd file in test directories such that every overriding
++# condition (for 3 directories in this case) will be seen.
++echo "motd: e0r0u1 in usr/lib - will show" > ${TST_DIR}/usr/lib/motd.d/e0r0u1.motd
++echo "motd: e0r1u0 in run - will show" > ${TST_DIR}/run/motd.d/e0r1u0.motd
++echo "motd: e0r1u1 in usr/lib - not show" > ${TST_DIR}/usr/lib/motd.d/e0r1u1.motd
++echo "motd: e0r1u1 in run - will show" > ${TST_DIR}/run/motd.d/e0r1u1.motd
++echo "motd: e1r0u0 in etc - will show" > ${TST_DIR}/etc/motd.d/e1r0u0.motd
++echo "motd: e1r0u1 in usr/lib - not show" > ${TST_DIR}/usr/lib/motd.d/e1r0u1.motd
++echo "motd: e1r0u1 in etc - will show" > ${TST_DIR}/etc/motd.d/e1r0u1.motd
++echo "motd: e1r1u0 in run - not show" > ${TST_DIR}/run/motd.d/e1r1u0.motd
++echo "motd: e1r1u0 in etc - will show" > ${TST_DIR}/etc/motd.d/e1r1u0.motd
++echo "motd: e1r1u1 in usr/lib - not show" > ${TST_DIR}/usr/lib/motd.d/e1r1u1.motd
++echo "motd: e1r1u1 in run - not show" > ${TST_DIR}/run/motd.d/e1r1u1.motd
++echo "motd: e1r1u1 in etc - will show" > ${TST_DIR}/etc/motd.d/e1r1u1.motd
++
++./tst-pam_motd tst-pam_motd2 > tst-pam_motd2.out
++
++RET=$?
++
++motd_to_show_output=$(cat tst-pam_motd2.out | grep "motd: /etc/motd")
++if [ -z "${motd_to_show_output}" ];
++then
++    tst_cleanup
++    exit 1
++fi
++
++motd_dir_not_show_output=$(cat tst-pam_motd2.out | grep "not show")
++if [ -n "${motd_dir_not_show_output}" ];
++then
++    tst_cleanup
++    exit 1
++fi
++
++tst_cleanup
++exit $RET
+diff -up Linux-PAM-1.3.1/xtests/tst-pam_motd3.pamd.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/xtests/tst-pam_motd3.pamd
+--- Linux-PAM-1.3.1/xtests/tst-pam_motd3.pamd.pam_motd-support-multiple-motd-paths1	2022-04-25 12:32:36.947663225 +0200
++++ Linux-PAM-1.3.1/xtests/tst-pam_motd3.pamd	2022-04-25 12:32:36.947663225 +0200
+@@ -0,0 +1,3 @@
++#%PAM-1.0
++session    required    pam_permit.so
++session optional    pam_motd.so    motd=tst-pam_motd3.d/etc/motd:tst-pam_motd3.d/run/motd:tst-pam_motd3.d/usr/lib/motd motd_dir=tst-pam_motd3.d/etc/motd.d:tst-pam_motd3.d/run/motd.d:tst-pam_motd3.d/usr/lib/motd.d
+diff -up Linux-PAM-1.3.1/xtests/tst-pam_motd3.sh.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/xtests/tst-pam_motd3.sh
+--- Linux-PAM-1.3.1/xtests/tst-pam_motd3.sh.pam_motd-support-multiple-motd-paths1	2022-04-25 12:32:36.947663225 +0200
++++ Linux-PAM-1.3.1/xtests/tst-pam_motd3.sh	2022-04-25 12:32:36.947663225 +0200
+@@ -0,0 +1,53 @@
++#!/bin/bash
++
++TST_DIR="tst-pam_motd3.d"
++
++function tst_cleanup() {
++    rm -rf "${TST_DIR}"
++    rm -f tst-pam_motd3.out
++}
++
++mkdir -p ${TST_DIR}
++mkdir -p ${TST_DIR}/etc/motd.d
++mkdir -p ${TST_DIR}/run/motd.d
++mkdir -p ${TST_DIR}/usr/lib/motd.d
++
++# Verify motd is still displayed when not overridden
++echo "motd: test-show in run - show" > ${TST_DIR}/run/motd.d/test-show.motd
++
++# Test overridden by a symlink to a file that isn't /dev/null; symlink target should show
++echo "motd: hidden-by-symlink in usr/lib - not show" > ${TST_DIR}/usr/lib/motd.d/hidden-by-symlink.motd
++echo "motd: test-from-symlink - show" > ${TST_DIR}/test-from-symlink.motd
++ln -sr ${TST_DIR}/test-from-symlink.motd ${TST_DIR}/run/motd.d/hidden-by-symlink.motd
++
++# Test hidden by a null symlink
++echo "motd: hidden-by-null-symlink in run - not show" > ${TST_DIR}/run/motd.d/hidden-by-null-symlink.motd
++ln -s /dev/null ${TST_DIR}/etc/motd.d/hidden-by-null-symlink.motd
++
++./tst-pam_motd tst-pam_motd3 > tst-pam_motd3.out
++
++RET=$?
++
++motd_dir_not_show_output=$(cat tst-pam_motd3.out | grep "not show")
++if [ -n "${motd_dir_not_show_output}" ];
++then
++    tst_cleanup
++    exit 1
++fi
++
++motd_test_show_output=$(cat tst-pam_motd3.out | grep "test-show.*- show")
++if [ -z "${motd_test_show_output}" ];
++then
++    tst_cleanup
++    exit 1
++fi
++
++motd_general_symlink_show_output=$(cat tst-pam_motd3.out | grep "test-from-symlink.*- show")
++if [ -z "${motd_general_symlink_show_output}" ];
++then
++    tst_cleanup
++    exit 1
++fi
++
++tst_cleanup
++exit $RET
+diff -up Linux-PAM-1.3.1/xtests/tst-pam_motd.c.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/xtests/tst-pam_motd.c
+--- Linux-PAM-1.3.1/xtests/tst-pam_motd.c.pam_motd-support-multiple-motd-paths1	2022-04-25 12:32:36.947663225 +0200
++++ Linux-PAM-1.3.1/xtests/tst-pam_motd.c	2022-04-25 12:32:36.947663225 +0200
+@@ -0,0 +1,69 @@
++/*
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, and the entire permission notice in its entirety,
++ *    including the disclaimer of warranties.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. The name of the author may not be used to endorse or promote
++ *    products derived from this software without specific prior
++ *    written permission.
++ *
++ * ALTERNATIVELY, this product may be distributed under the terms of
++ * the GNU Public License, in which case the provisions of the GPL are
++ * required INSTEAD OF the above restrictions.  (This clause is
++ * necessary due to a potential bad interaction between the GPL and
++ * the restrictions contained in a BSD-style copyright.)
++ *
++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ */
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <security/pam_appl.h>
++#include <security/pam_misc.h>
++
++static struct pam_conv conv = {
++    misc_conv,
++    NULL
++};
++
++int main(int argc, char *argv[])
++{
++    pam_handle_t *pamh=NULL;
++    char *tst_arg = NULL;
++    int retval;
++
++    if (argc > 1)
++	tst_arg = argv[1];
++
++    retval = pam_start(tst_arg, NULL, &conv, &pamh);
++
++    retval = pam_open_session(pamh, 0);
++
++    retval = pam_close_session(pamh, 0);
++
++    if (pam_end(pamh,retval) != PAM_SUCCESS) {     /* close Linux-PAM */
++	pamh = NULL;
++	exit(1);
++    }
++
++    return ( retval == PAM_SUCCESS ? 0:1 );       /* indicate success */
++}
+diff -up Linux-PAM-1.3.1/xtests/tst-pam_motd.sh.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/xtests/tst-pam_motd.sh
+--- Linux-PAM-1.3.1/xtests/tst-pam_motd.sh.pam_motd-support-multiple-motd-paths1	2022-04-25 12:32:36.947663225 +0200
++++ Linux-PAM-1.3.1/xtests/tst-pam_motd.sh	2022-04-25 12:32:36.947663225 +0200
+@@ -0,0 +1,7 @@
++#!/bin/bash
++
++set -e
++
++./tst-pam_motd1.sh
++./tst-pam_motd2.sh
++./tst-pam_motd3.sh
diff --git a/SOURCES/pam-1.3.1-pam-usertype-SYS_UID_MAX.patch b/SOURCES/pam-1.3.1-pam-usertype-SYS_UID_MAX.patch
new file mode 100644
index 0000000..4881a5e
--- /dev/null
+++ b/SOURCES/pam-1.3.1-pam-usertype-SYS_UID_MAX.patch
@@ -0,0 +1,75 @@
+diff -up Linux-PAM-1.3.1/configure.ac.pam-usertype-SYS_UID_MAX Linux-PAM-1.3.1/configure.ac
+--- Linux-PAM-1.3.1/configure.ac.pam-usertype-SYS_UID_MAX	2022-06-22 16:41:09.169146826 +0200
++++ Linux-PAM-1.3.1/configure.ac	2022-06-22 16:43:54.343373619 +0200
+@@ -615,12 +615,6 @@ if test x"$opt_uidmin" == x; then
+ fi
+ AC_DEFINE_UNQUOTED(PAM_USERTYPE_UIDMIN, $opt_uidmin, [Minimum regular user uid.])
+ 
+-AC_ARG_WITH([sysuidmin], AS_HELP_STRING([--with-sysuidmin=<number>],[default value for system user min uid (101)]), opt_sysuidmin=$withval)
+-if test x"$opt_sysuidmin" == x; then
+-    opt_sysuidmin=101
+-fi
+-AC_DEFINE_UNQUOTED(PAM_USERTYPE_SYSUIDMIN, $opt_sysuidmin, [Minimum system user uid.])
+-
+ AC_ARG_WITH([kerneloverflowuid], AS_HELP_STRING([--with-kernel-overflow-uid=<number>],[kernel overflow uid, default (uint16_t)-2=65534]), opt_kerneloverflowuid=$withval)
+ if test x"$opt_kerneloverflowuid" == x; then
+     opt_kerneloverflowuid=65534
+diff -up Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.8.xml.pam-usertype-SYS_UID_MAX Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.8.xml
+--- Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.8.xml.pam-usertype-SYS_UID_MAX	2022-06-22 16:41:09.155146722 +0200
++++ Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.8.xml	2022-06-22 16:41:09.169146826 +0200
+@@ -31,7 +31,7 @@
+       pam_usertype.so is designed to succeed or fail authentication
+       based on type of the account of the authenticated user.
+       The type of the account is decided with help of
+-      <emphasis>SYS_UID_MIN</emphasis> and <emphasis>SYS_UID_MAX</emphasis>
++      <emphasis>SYS_UID_MAX</emphasis>
+       settings in <emphasis>/etc/login.defs</emphasis>. One use is to select
+       whether to load other modules based on this test.
+     </para>
+diff -up Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.c.pam-usertype-SYS_UID_MAX Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.c
+--- Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.c.pam-usertype-SYS_UID_MAX	2022-06-22 16:41:09.155146722 +0200
++++ Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.c	2022-06-22 16:41:09.169146826 +0200
+@@ -277,7 +277,6 @@ static int
+ pam_usertype_is_system(pam_handle_t *pamh, uid_t uid)
+ {
+     uid_t uid_min;
+-    uid_t sys_min;
+     uid_t sys_max;
+ 
+     if (uid == (uid_t)-1) {
+@@ -285,21 +284,19 @@ pam_usertype_is_system(pam_handle_t *pam
+         return PAM_USER_UNKNOWN;
+     }
+ 
+-    if (uid <= 99) {
+-        /* Reserved. */
+-        return PAM_SUCCESS;
+-    }
+-
+     if (uid == PAM_USERTYPE_OVERFLOW_UID) {
+         /* nobody */
+         return PAM_SUCCESS;
+     }
+ 
+     uid_min = pam_usertype_get_id(pamh, "UID_MIN", PAM_USERTYPE_UIDMIN);
+-    sys_min = pam_usertype_get_id(pamh, "SYS_UID_MIN", PAM_USERTYPE_SYSUIDMIN);
+     sys_max = pam_usertype_get_id(pamh, "SYS_UID_MAX", uid_min - 1);
+ 
+-    return uid >= sys_min && uid <= sys_max ? PAM_SUCCESS : PAM_AUTH_ERR;
++    if (uid <= sys_max && uid < uid_min) {
++        return PAM_SUCCESS;
++    }
++
++    return PAM_AUTH_ERR;
+ }
+ 
+ static int
+@@ -336,7 +333,7 @@ pam_usertype_evaluate(struct pam_usertyp
+ 
+ /**
+  * Arguments:
+- * - issystem: uid in <SYS_UID_MIN, SYS_UID_MAX>
++ * - issystem: uid less than SYS_UID_MAX
+  * - isregular: not issystem
+  * - use_uid: use user that runs application not that is being authenticate (same as in pam_succeed_if)
+  * - audit: log unknown users to syslog
diff --git a/SOURCES/pamtmp.conf b/SOURCES/pamtmp.conf
index e94a860..e4cfe2a 100644
--- a/SOURCES/pamtmp.conf
+++ b/SOURCES/pamtmp.conf
@@ -1,3 +1,4 @@
 d /run/console 0755 root root -
 d /run/faillock 0755 root root -
 d /run/sepermit 0755 root root -
+d /run/motd.d 0755 root root -
diff --git a/SPECS/pam.spec b/SPECS/pam.spec
index 58d1b87..8b0ed82 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: 16%{?dist}.1
+Release: 22%{?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+.
@@ -69,12 +69,22 @@ Patch49: pam-1.3.1-namespace-gdm-doc.patch
 Patch50: pam-1.3.1-pam-userdb-prevent-garbage-characters-from-db.patch
 # https://github.com/linux-pam/linux-pam/commit/3234488f2c52a021eec87df1990d256314c21bff
 Patch51: pam-1.3.1-pam-limits-unlimited-value.patch
+# https://github.com/linux-pam/linux-pam/commit/a35e092e24ee7632346a0e1b4a203c04d4cd2c62
+Patch52: pam-1.3.1-pam-keyinit-thread-safe.patch
+# https://github.com/linux-pam/linux-pam/commit/f9c9c72121eada731e010ab3620762bcf63db08f
+Patch53: pam-1.3.1-pam-motd-support-multiple-motd-paths.patch
+# https://github.com/linux-pam/linux-pam/commit/8eaf5570cf011148a0b55c53570df5edaafebdb0
+Patch54: pam-1.3.1-pam-motd-fix-segmentation-fault.patch
+# https://github.com/linux-pam/linux-pam/commit/62cd745d730e5ba13d5d7092ac566fc0b2148e61
+Patch55: pam-1.3.1-pam-motd-fix-memory-leak.patch
 # Needed by the next patch. Already upstreamed
-Patch52: pam-1.3.1-pam-cc-compat.patch
-Patch53: pam-1.3.1-inline.patch
+Patch56: pam-1.3.1-pam-cc-compat.patch
+Patch57: pam-1.3.1-inline.patch
 # https://github.com/linux-pam/linux-pam/commit/9bcbe96d9e82a23d983c0618178a8dc25596ac2d
 # https://github.com/linux-pam/linux-pam/commit/fc867a9e22eac2c9a0ed0577776bba4df21c9aad
-Patch54: pam-1.3.1-faillock-load-conf-from-file.patch
+Patch58: pam-1.3.1-faillock-load-conf-from-file.patch
+# https://github.com/linux-pam/linux-pam/commit/370064ef6f99581b08d473a42bb3417d5dda3e4e
+Patch59: pam-1.3.1-pam-usertype-SYS_UID_MAX.patch
 
 %define _pamlibdir %{_libdir}
 %define _moduledir %{_libdir}/security
@@ -174,9 +184,14 @@ cp %{SOURCE18} .
 %patch49 -p1 -b .namespace-gdm-doc
 %patch50 -p1 -b .pam-userdb-prevent-garbage-characters-from-db
 %patch51 -p1 -b .pam-limits-unlimited-value
-%patch52 -p1 -b .pam-cc-compat
-%patch53 -p1 -b .inline
-%patch54 -p1 -b .faillock-load-conf-from-file
+%patch52 -p1 -b .pam-keyinit-thread-safe
+%patch53 -p1 -b .pam-motd-support-multiple-motd-paths
+%patch54 -p1 -b .pam-motd-fix-segmentation-fault
+%patch55 -p1 -b .pam-motd-fix-memory-leak
+%patch56 -p1 -b .pam-cc-compat
+%patch57 -p1 -b .inline
+%patch58 -p1 -b .faillock-load-conf-from-file
+%patch59 -p1 -b .pam-usertype-SYS_UID_MAX
 
 autoreconf -i
 
@@ -231,6 +246,9 @@ 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 -d -m 755 $RPM_BUILD_ROOT/var/run/faillock
+install -d -m 755 $RPM_BUILD_ROOT%{_sysconfdir}/motd.d
+install -d -m 755 $RPM_BUILD_ROOT/usr/lib/motd.d
+install -d -m 755 $RPM_BUILD_ROOT/run/motd.d 
 
 # Install man pages.
 install -m 644 %{SOURCE12} %{SOURCE13} %{SOURCE17} $RPM_BUILD_ROOT%{_mandir}/man5/
@@ -408,6 +426,9 @@ done
 %dir /var/run/sepermit
 %endif
 %dir /var/run/faillock
+%dir %{_sysconfdir}/motd.d
+%dir /run/motd.d
+%dir /usr/lib/motd.d 
 %{_prefix}/lib/tmpfiles.d/pam.conf
 %{_mandir}/man5/*
 %{_mandir}/man8/*
@@ -423,8 +444,25 @@ done
 %doc doc/specs/rfc86.0.txt
 
 %changelog
-* Tue Aug  2 2022 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-16.1
-- faillock: load configuration from file. Resolves: #2112889
+* Wed Jul 13 2022 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-22
+- Regenerate the /run/motd.d at each boot. Resolves: #2104878
+
+* Thu Jun 23 2022 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-21
+- pam_usertype: only use SYS_UID_MAX for system users. Resolves: #1949137
+
+* Thu May 26 2022 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-20
+- faillock: load configuration from file. Resolves: #1978029
+
+* Mon May 23 2022 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-19
+- Add the motd.d directories (empty) to silence warnings and to
+  provide proper ownership for them. Resolves: #2014458
+
+* Thu May 19 2022 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-18
+- pam_motd: fix memory leak. Resolves: #2014458
+
+* Tue May 17 2022 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-17
+- pam_keyinit: thread-safe implementation. Resolves: #1997969
+- pam_motd: support multiple motd paths specified, with filename overrides. Resolves: #2014458
 
 * Fri Jan 28 2022 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-16
 - pam_limits: "Unlimited" is not a valid value for RLIMIT_NOFILE. Resolves: #2047655