From 9080c178e7340caea011d7b2899bb6b375b542f586123daa59ebeae3434c27c0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Josef=20M=C3=B6llers?=
Date: Thu, 1 Apr 2021 08:02:50 +0000
Subject: [PATCH] Accepting request 882509 from
home:jmoellers:branches:Linux-PAM
OBS-URL: https://build.opensuse.org/request/show/882509
OBS-URL: https://build.opensuse.org/package/show/Linux-PAM/pam?expand=0&rev=235
---
...3-make-nofile-unlimited-mean-nr_open.patch | 755 ++++++++++++++++++
pam.changes | 10 +
pam.spec | 2 +
3 files changed, 767 insertions(+)
create mode 100644 pam-bsc1181443-make-nofile-unlimited-mean-nr_open.patch
diff --git a/pam-bsc1181443-make-nofile-unlimited-mean-nr_open.patch b/pam-bsc1181443-make-nofile-unlimited-mean-nr_open.patch
new file mode 100644
index 0000000..7616282
--- /dev/null
+++ b/pam-bsc1181443-make-nofile-unlimited-mean-nr_open.patch
@@ -0,0 +1,755 @@
+Index: Linux-PAM-1.5.1/doc/sag/Linux-PAM_SAG.txt
+===================================================================
+--- Linux-PAM-1.5.1.orig/doc/sag/Linux-PAM_SAG.txt
++++ Linux-PAM-1.5.1/doc/sag/Linux-PAM_SAG.txt
+@@ -2171,6 +2171,9 @@ The fields listed above should be filled
+ All items support the values -1, unlimited or infinity indicating no limit,
+ except for priority, nice, and nonewprivs.
+
++If nofile is to be set to one of these values,
++it will be set to the contents of /proc/sys/fs/nr_open instead (see setrlimit(3)).
++
+ If a hard limit or soft limit of a resource is set to a valid value, but
+ outside of the supported range of the local system, the system may reject the
+ new limit or unexpected behavior may occur. If the control value required is
+Index: Linux-PAM-1.5.1/doc/sag/html/sag-pam_limits.html
+===================================================================
+--- Linux-PAM-1.5.1.orig/doc/sag/html/sag-pam_limits.html
++++ Linux-PAM-1.5.1/doc/sag/html/sag-pam_limits.html
+@@ -104,6 +104,9 @@
+ unlimited or infinity indicating no limit,
+ except for priority, nice,
+ and nonewprivs.
++ If nofile is to be set to one of these values,
++ it will be set to the contents of /proc/sys/fs/nr_open
instead
++ (see setrlimit(3)).
+
+ If a hard limit or soft limit of a resource is set to a valid value,
+ but outside of the supported range of the local system, the system
+Index: Linux-PAM-1.5.1/modules/pam_limits/limits.conf.5
+===================================================================
+--- Linux-PAM-1.5.1.orig/modules/pam_limits/limits.conf.5
++++ Linux-PAM-1.5.1/modules/pam_limits/limits.conf.5
+@@ -290,6 +290,8 @@ indicating no limit, except for
+ \fBpriority\fR,
+ \fBnice\fR, and
+ \fBnonewprivs\fR\&.
++If \fBnofile\fP is to be set to one of these values,
++it will be set to the contents of \fI/proc/sys/fs/nr_open\fP instead (see \fBsetrlimit\fP(3))\&.
+ .PP
+ If a hard limit or soft limit of a resource is set to a valid value, but outside of the supported range of the local system, the system may reject the new limit or unexpected behavior may occur\&. If the control value
+ \fIrequired\fR
+Index: Linux-PAM-1.5.1/modules/pam_limits/limits.conf.5.xml
+===================================================================
+--- Linux-PAM-1.5.1.orig/modules/pam_limits/limits.conf.5.xml
++++ Linux-PAM-1.5.1/modules/pam_limits/limits.conf.5.xml
+@@ -283,6 +283,8 @@
+ unlimited or infinity indicating no limit,
+ except for priority, nice,
+ and nonewprivs.
++ If nofile is to be set to one of these values,
++ it will be set to the contents of /proc/sys/fs/nr_open instead (see setrlimit(3)).
+
+
+ If a hard limit or soft limit of a resource is set to a valid value,
+Index: Linux-PAM-1.5.1/modules/pam_limits/pam_limits.c
+===================================================================
+--- Linux-PAM-1.5.1.orig/modules/pam_limits/pam_limits.c
++++ Linux-PAM-1.5.1/modules/pam_limits/pam_limits.c
+@@ -228,21 +228,21 @@ rlimit2str (int i)
+ /* Counts the number of user logins and check against the limit*/
+ static int
+ check_logins (pam_handle_t *pamh, const char *name, int limit, int ctrl,
+- struct pam_limit_s *pl)
++ struct pam_limit_s *pl)
+ {
+ struct utmp *ut;
+ int count;
+
+ if (ctrl & PAM_DEBUG_ARG) {
+- pam_syslog(pamh, LOG_DEBUG,
++ pam_syslog(pamh, LOG_DEBUG,
+ "checking logins for '%s' (maximum of %d)", name, limit);
+ }
+
+ if (limit < 0)
+- return 0; /* no limits imposed */
++ return 0; /* no limits imposed */
+ if (limit == 0) /* maximum 0 logins ? */ {
+- pam_syslog(pamh, LOG_WARNING, "No logins allowed for '%s'", name);
+- return LOGIN_ERR;
++ pam_syslog(pamh, LOG_WARNING, "No logins allowed for '%s'", name);
++ return LOGIN_ERR;
+ }
+
+ setutent();
+@@ -265,14 +265,14 @@ check_logins (pam_handle_t *pamh, const
+
+ while((ut = getutent())) {
+ #ifdef USER_PROCESS
+- if (ut->ut_type != USER_PROCESS) {
+- continue;
++ if (ut->ut_type != USER_PROCESS) {
++ continue;
+ }
+ #endif
+- if (ut->UT_USER[0] == '\0') {
+- continue;
++ if (ut->UT_USER[0] == '\0') {
++ continue;
+ }
+- if (!pl->flag_numsyslogins) {
++ if (!pl->flag_numsyslogins) {
+ char user[sizeof(ut->UT_USER) + 1];
+ user[0] = '\0';
+ strncat(user, ut->UT_USER, sizeof(ut->UT_USER));
+@@ -281,11 +281,11 @@ check_logins (pam_handle_t *pamh, const
+ || (pl->login_limit_def == LIMITS_DEF_GROUP)
+ || (pl->login_limit_def == LIMITS_DEF_DEFAULT))
+ && strcmp(name, user) != 0) {
+- continue;
++ continue;
+ }
+ if ((pl->login_limit_def == LIMITS_DEF_ALLGROUP)
+ && !pam_modutil_user_in_group_nam_nam(pamh, user, pl->login_group)) {
+- continue;
++ continue;
+ }
+ if (kill(ut->ut_pid, 0) == -1 && errno == ESRCH) {
+ /* process does not exist anymore */
+@@ -307,50 +307,50 @@ check_logins (pam_handle_t *pamh, const
+ } else {
+ pam_syslog(pamh, LOG_NOTICE, "Too many system logins (max %d)", limit);
+ }
+- return LOGIN_ERR;
++ return LOGIN_ERR;
+ }
+ return 0;
+ }
+
+ static const char *lnames[RLIM_NLIMITS] = {
+- [RLIMIT_CPU] = "Max cpu time",
+- [RLIMIT_FSIZE] = "Max file size",
+- [RLIMIT_DATA] = "Max data size",
+- [RLIMIT_STACK] = "Max stack size",
+- [RLIMIT_CORE] = "Max core file size",
+- [RLIMIT_RSS] = "Max resident set",
+- [RLIMIT_NPROC] = "Max processes",
+- [RLIMIT_NOFILE] = "Max open files",
+- [RLIMIT_MEMLOCK] = "Max locked memory",
++ [RLIMIT_CPU] = "Max cpu time",
++ [RLIMIT_FSIZE] = "Max file size",
++ [RLIMIT_DATA] = "Max data size",
++ [RLIMIT_STACK] = "Max stack size",
++ [RLIMIT_CORE] = "Max core file size",
++ [RLIMIT_RSS] = "Max resident set",
++ [RLIMIT_NPROC] = "Max processes",
++ [RLIMIT_NOFILE] = "Max open files",
++ [RLIMIT_MEMLOCK] = "Max locked memory",
+ #ifdef RLIMIT_AS
+- [RLIMIT_AS] = "Max address space",
++ [RLIMIT_AS] = "Max address space",
+ #endif
+ #ifdef RLIMIT_LOCKS
+- [RLIMIT_LOCKS] = "Max file locks",
++ [RLIMIT_LOCKS] = "Max file locks",
+ #endif
+ #ifdef RLIMIT_SIGPENDING
+- [RLIMIT_SIGPENDING] = "Max pending signals",
++ [RLIMIT_SIGPENDING] = "Max pending signals",
+ #endif
+ #ifdef RLIMIT_MSGQUEUE
+- [RLIMIT_MSGQUEUE] = "Max msgqueue size",
++ [RLIMIT_MSGQUEUE] = "Max msgqueue size",
+ #endif
+ #ifdef RLIMIT_NICE
+- [RLIMIT_NICE] = "Max nice priority",
++ [RLIMIT_NICE] = "Max nice priority",
+ #endif
+ #ifdef RLIMIT_RTPRIO
+- [RLIMIT_RTPRIO] = "Max realtime priority",
++ [RLIMIT_RTPRIO] = "Max realtime priority",
+ #endif
+ #ifdef RLIMIT_RTTIME
+- [RLIMIT_RTTIME] = "Max realtime timeout",
++ [RLIMIT_RTTIME] = "Max realtime timeout",
+ #endif
+ };
+
+ static int str2rlimit(char *name) {
+ int i;
+ if (!name || *name == '\0')
+- return -1;
++ return -1;
+ for(i = 0; i < RLIM_NLIMITS; i++) {
+- if (strcmp(name, lnames[i]) == 0) return i;
++ if (strcmp(name, lnames[i]) == 0) return i;
+ }
+ return -1;
+ }
+@@ -360,25 +360,25 @@ static rlim_t str2rlim_t(char *value) {
+
+ if (!value) return (rlim_t)rlimit;
+ if (strcmp(value, "unlimited") == 0) {
+- return RLIM_INFINITY;
++ return RLIM_INFINITY;
+ }
+ rlimit = strtoull(value, NULL, 10);
+ return (rlim_t)rlimit;
+ }
+
+ #define LIMITS_SKIP_WHITESPACE { \
+- /* step backwards over spaces */ \
+- pos--; \
+- while (pos && line[pos] == ' ') pos--; \
+- if (!pos) continue; \
+- line[pos+1] = '\0'; \
++ /* step backwards over spaces */ \
++ pos--; \
++ while (pos && line[pos] == ' ') pos--; \
++ if (!pos) continue; \
++ line[pos+1] = '\0'; \
+ }
+ #define LIMITS_MARK_ITEM(item) { \
+- /* step backwards over non-spaces */ \
+- pos--; \
+- while (pos && line[pos] != ' ') pos--; \
+- if (!pos) continue; \
+- item = line + pos + 1; \
++ /* step backwards over non-spaces */ \
++ pos--; \
++ while (pos && line[pos] != ' ') pos--; \
++ if (!pos) continue; \
++ item = line + pos + 1; \
+ }
+
+ static void parse_kernel_limits(pam_handle_t *pamh, struct pam_limit_s *pl, int ctrl)
+@@ -390,54 +390,54 @@ static void parse_kernel_limits(pam_hand
+ char *hard, *soft, *name;
+
+ if (!(limitsfile = fopen(proclimits, "r"))) {
+- pam_syslog(pamh, LOG_WARNING, "Could not read %s (%s), using PAM defaults", proclimits, strerror(errno));
+- return;
++ pam_syslog(pamh, LOG_WARNING, "Could not read %s (%s), using PAM defaults", proclimits, strerror(errno));
++ return;
+ }
+
+ while (fgets(line, 256, limitsfile)) {
+- int pos = strlen(line);
+- if (pos < 2) continue;
++ int pos = strlen(line);
++ if (pos < 2) continue;
++
++ /* drop trailing newline */
++ if (line[pos-1] == '\n') {
++ pos--;
++ line[pos] = '\0';
++ }
+
+- /* drop trailing newline */
+- if (line[pos-1] == '\n') {
+- pos--;
+- line[pos] = '\0';
+- }
+-
+- /* determine formatting boundary of limits report */
+- if (!maxlen && pam_str_skip_prefix(line, "Limit") != NULL) {
+- maxlen = pos;
+- continue;
+- }
+-
+- if (pos == maxlen) {
+- /* step backwards over "Units" name */
+- LIMITS_SKIP_WHITESPACE;
+- LIMITS_MARK_ITEM(hard); /* not a typo, units unused */
+- }
+-
+- /* step backwards over "Hard Limit" value */
+- LIMITS_SKIP_WHITESPACE;
+- LIMITS_MARK_ITEM(hard);
+-
+- /* step backwards over "Soft Limit" value */
+- LIMITS_SKIP_WHITESPACE;
+- LIMITS_MARK_ITEM(soft);
+-
+- /* step backwards over name of limit */
+- LIMITS_SKIP_WHITESPACE;
+- name = line;
+-
+- i = str2rlimit(name);
+- if (i < 0 || i >= RLIM_NLIMITS) {
+- if (ctrl & PAM_DEBUG_ARG)
+- pam_syslog(pamh, LOG_DEBUG, "Unknown kernel rlimit '%s' ignored", name);
+- continue;
+- }
+- pl->limits[i].limit.rlim_cur = str2rlim_t(soft);
+- pl->limits[i].limit.rlim_max = str2rlim_t(hard);
+- pl->limits[i].src_soft = LIMITS_DEF_KERNEL;
+- pl->limits[i].src_hard = LIMITS_DEF_KERNEL;
++ /* determine formatting boundary of limits report */
++ if (!maxlen && pam_str_skip_prefix(line, "Limit") != NULL) {
++ maxlen = pos;
++ continue;
++ }
++
++ if (pos == maxlen) {
++ /* step backwards over "Units" name */
++ LIMITS_SKIP_WHITESPACE;
++ LIMITS_MARK_ITEM(hard); /* not a typo, units unused */
++ }
++
++ /* step backwards over "Hard Limit" value */
++ LIMITS_SKIP_WHITESPACE;
++ LIMITS_MARK_ITEM(hard);
++
++ /* step backwards over "Soft Limit" value */
++ LIMITS_SKIP_WHITESPACE;
++ LIMITS_MARK_ITEM(soft);
++
++ /* step backwards over name of limit */
++ LIMITS_SKIP_WHITESPACE;
++ name = line;
++
++ i = str2rlimit(name);
++ if (i < 0 || i >= RLIM_NLIMITS) {
++ if (ctrl & PAM_DEBUG_ARG)
++ pam_syslog(pamh, LOG_DEBUG, "Unknown kernel rlimit '%s' ignored", name);
++ continue;
++ }
++ pl->limits[i].limit.rlim_cur = str2rlim_t(soft);
++ pl->limits[i].limit.rlim_max = str2rlim_t(hard);
++ pl->limits[i].src_soft = LIMITS_DEF_KERNEL;
++ pl->limits[i].src_hard = LIMITS_DEF_KERNEL;
+ }
+ fclose(limitsfile);
+ }
+@@ -486,6 +486,54 @@ static int init_limits(pam_handle_t *pam
+
+ return retval;
+ }
++/*
++ * Read the contents of /proc/sys/fs/
++ * return 1 if conversion succeeds, result is in *valuep
++ * return 0 if conversion fails.
++ */
++static int
++value_from_proc_sys_fs(const pam_handle_t *pamh, const char *name, rlim_t *valuep)
++{
++ char pathname[128];
++ char buf[128];
++ FILE *fp;
++ int retval;
++
++ retval = 0;
++
++ snprintf(pathname, sizeof(pathname), "/proc/sys/fs/%s", name);
++
++ if ((fp = fopen(pathname, "r")) != NULL) {
++ if (fgets(buf, sizeof(buf), fp) != NULL) {
++ char *endptr;
++
++#ifdef __USE_FILE_OFFSET64
++ *valuep = strtoull(buf, &endptr, 10);
++#else
++ *valuep = strtoul(buf, &endptr, 10);
++#endif
++
++ retval = (endptr != buf);
++ }
++
++ fclose(fp);
++ }
++
++ return retval;
++}
++
++/*
++ * Check if the string passed as the argument corresponds to
++ * "unlimited"
++ */
++static inline int
++is_unlimited(const char *lim_value)
++{
++ return strcmp(lim_value, "-1") == 0
++ || strcmp(lim_value, "-") == 0
++ || strcmp(lim_value, "unlimited") == 0
++ || strcmp(lim_value, "infinity") == 0;
++}
+
+ static void
+ process_limit (const pam_handle_t *pamh, int source, const char *lim_type,
+@@ -505,9 +553,9 @@ process_limit (const pam_handle_t *pamh,
+ limits_def_names[source]);
+
+ if (strcmp(lim_item, "cpu") == 0)
+- limit_item = RLIMIT_CPU;
++ limit_item = RLIMIT_CPU;
+ else if (strcmp(lim_item, "fsize") == 0)
+- limit_item = RLIMIT_FSIZE;
++ limit_item = RLIMIT_FSIZE;
+ else if (strcmp(lim_item, "data") == 0)
+ limit_item = RLIMIT_DATA;
+ else if (strcmp(lim_item, "stack") == 0)
+@@ -557,8 +605,8 @@ process_limit (const pam_handle_t *pamh,
+ } else if (strcmp(lim_item, "nonewprivs") == 0) {
+ limit_item = LIMIT_NONEWPRIVS;
+ } else {
+- pam_syslog(pamh, LOG_DEBUG, "unknown limit item '%s'", lim_item);
+- return;
++ pam_syslog(pamh, LOG_DEBUG, "unknown limit item '%s'", lim_item);
++ return;
+ }
+
+ if (strcmp(lim_type,"soft")==0)
+@@ -569,9 +617,10 @@ process_limit (const pam_handle_t *pamh,
+ limit_type=LIMIT_SOFT | LIMIT_HARD;
+ else if (limit_item != LIMIT_LOGIN && limit_item != LIMIT_NUMSYSLOGINS
+ && limit_item != LIMIT_NONEWPRIVS) {
+- pam_syslog(pamh, LOG_DEBUG, "unknown limit type '%s'", lim_type);
+- return;
++ pam_syslog(pamh, LOG_DEBUG, "unknown limit type '%s'", lim_type);
++ return;
+ }
++
+ if (limit_item == LIMIT_NONEWPRIVS) {
+ /* just require a bool-style 0 or 1 */
+ if (strcmp(lim_value, "0") == 0) {
+@@ -587,9 +636,7 @@ process_limit (const pam_handle_t *pamh,
+ #ifdef RLIMIT_NICE
+ && limit_item != RLIMIT_NICE
+ #endif
+- && (strcmp(lim_value, "-1") == 0
+- || strcmp(lim_value, "-") == 0 || strcmp(lim_value, "unlimited") == 0
+- || strcmp(lim_value, "infinity") == 0)) {
++ && is_unlimited(lim_value)) {
+ int_value = -1;
+ rlimit_value = RLIM_INFINITY;
+ } else if (limit_item == LIMIT_PRI || limit_item == LIMIT_LOGIN ||
+@@ -605,7 +652,7 @@ process_limit (const pam_handle_t *pamh,
+ pam_syslog(pamh, LOG_DEBUG,
+ "wrong limit value '%s' for limit type '%s'",
+ lim_value, lim_type);
+- return;
++ return;
+ }
+ } else {
+ #ifdef __USE_FILE_OFFSET64
+@@ -631,7 +678,7 @@ process_limit (const pam_handle_t *pamh,
+ }
+
+ switch(limit_item) {
+- case RLIMIT_CPU:
++ case RLIMIT_CPU:
+ if (rlimit_value != RLIM_INFINITY)
+ {
+ if (rlimit_value >= RLIM_INFINITY/60)
+@@ -639,17 +686,17 @@ process_limit (const pam_handle_t *pamh,
+ else
+ rlimit_value *= 60;
+ }
+- break;
+- case RLIMIT_FSIZE:
+- case RLIMIT_DATA:
+- case RLIMIT_STACK:
+- case RLIMIT_CORE:
+- case RLIMIT_RSS:
+- case RLIMIT_MEMLOCK:
++ break;
++ case RLIMIT_FSIZE:
++ case RLIMIT_DATA:
++ case RLIMIT_STACK:
++ case RLIMIT_CORE:
++ case RLIMIT_RSS:
++ case RLIMIT_MEMLOCK:
+ #ifdef RLIMIT_AS
+- case RLIMIT_AS:
++ case RLIMIT_AS:
+ #endif
+- if (rlimit_value != RLIM_INFINITY)
++ if (rlimit_value != RLIM_INFINITY)
+ {
+ if (rlimit_value >= RLIM_INFINITY/1024)
+ rlimit_value = RLIM_INFINITY;
+@@ -664,29 +711,42 @@ process_limit (const pam_handle_t *pamh,
+ if (int_value < -20)
+ int_value = -20;
+ rlimit_value = 20 - int_value;
+- break;
++ break;
+ #endif
++ case RLIMIT_NOFILE:
++ /*
++ * If nofile is to be set to "unlimited", try to set it to
++ * the value in /proc/sys/fs/nr_open instead.
++ */
++ if (rlimit_value == RLIM_INFINITY) {
++ if (!value_from_proc_sys_fs(pamh, "nr_open", &rlimit_value))
++ pam_syslog(pamh, LOG_DEBUG,
++ "Cannot set \"nofile\" to a sensible value");
++ else
++ pam_syslog(pamh, LOG_WARNING, "Setting \"nofile\" limit to %lu", (long unsigned) rlimit_value);
++ }
++ break;
+ }
+
+ if ( (limit_item != LIMIT_LOGIN)
+ && (limit_item != LIMIT_NUMSYSLOGINS)
+ && (limit_item != LIMIT_PRI)
+ && (limit_item != LIMIT_NONEWPRIVS) ) {
+- if (limit_type & LIMIT_SOFT) {
++ if (limit_type & LIMIT_SOFT) {
+ if (pl->limits[limit_item].src_soft < source) {
+- return;
++ return;
+ } else {
+- pl->limits[limit_item].limit.rlim_cur = rlimit_value;
+- pl->limits[limit_item].src_soft = source;
+- }
++ pl->limits[limit_item].limit.rlim_cur = rlimit_value;
++ pl->limits[limit_item].src_soft = source;
++ }
+ }
+- if (limit_type & LIMIT_HARD) {
++ if (limit_type & LIMIT_HARD) {
+ if (pl->limits[limit_item].src_hard < source) {
+- return;
+- } else {
+- pl->limits[limit_item].limit.rlim_max = rlimit_value;
+- pl->limits[limit_item].src_hard = source;
+- }
++ return;
++ } else {
++ pl->limits[limit_item].limit.rlim_max = rlimit_value;
++ pl->limits[limit_item].src_hard = source;
++ }
+ }
+ } else {
+ /* recent kernels support negative priority limits (=raise priority) */
+@@ -764,42 +824,42 @@ parse_config_file(pam_handle_t *pamh, co
+
+ /* check for the LIMITS_FILE */
+ if (ctrl & PAM_DEBUG_ARG)
+- pam_syslog(pamh, LOG_DEBUG, "reading settings from '%s'", CONF_FILE);
++ pam_syslog(pamh, LOG_DEBUG, "reading settings from '%s'", CONF_FILE);
+ fil = fopen(CONF_FILE, "r");
+ if (fil == NULL) {
+- pam_syslog (pamh, LOG_WARNING,
++ pam_syslog (pamh, LOG_WARNING,
+ "cannot read settings from %s: %m", CONF_FILE);
+- return PAM_SERVICE_ERR;
++ return PAM_SERVICE_ERR;
+ }
+
+ /* start the show */
+ while (fgets(buf, LINE_LENGTH, fil) != NULL) {
+- char domain[LINE_LENGTH];
+- char ltype[LINE_LENGTH];
+- char item[LINE_LENGTH];
+- char value[LINE_LENGTH];
+- int i;
+- int rngtype;
+- size_t j;
+- char *tptr,*line;
+- uid_t min_uid = (uid_t)-1, max_uid = (uid_t)-1;
+-
+- line = buf;
+- /* skip the leading white space */
+- while (*line && isspace(*line))
+- line++;
+-
+- /* Rip off the comments */
+- tptr = strchr(line,'#');
+- if (tptr)
+- *tptr = '\0';
+- /* Rip off the newline char */
+- tptr = strchr(line,'\n');
+- if (tptr)
+- *tptr = '\0';
+- /* Anything left ? */
+- if (!strlen(line))
+- continue;
++ char domain[LINE_LENGTH];
++ char ltype[LINE_LENGTH];
++ char item[LINE_LENGTH];
++ char value[LINE_LENGTH];
++ int i;
++ int rngtype;
++ size_t j;
++ char *tptr,*line;
++ uid_t min_uid = (uid_t)-1, max_uid = (uid_t)-1;
++
++ line = buf;
++ /* skip the leading white space */
++ while (*line && isspace(*line))
++ line++;
++
++ /* Rip off the comments */
++ tptr = strchr(line,'#');
++ if (tptr)
++ *tptr = '\0';
++ /* Rip off the newline char */
++ tptr = strchr(line,'\n');
++ if (tptr)
++ *tptr = '\0';
++ /* Anything left ? */
++ if (!strlen(line))
++ continue;
+
+ domain[0] = ltype[0] = item[0] = value[0] = '\0';
+
+@@ -807,23 +867,23 @@ parse_config_file(pam_handle_t *pamh, co
+ D(("scanned line[%d]: domain[%s], ltype[%s], item[%s], value[%s]",
+ i, domain, ltype, item, value));
+
+- for(j=0; j < strlen(ltype); j++)
+- ltype[j]=tolower(ltype[j]);
++ for(j=0; j < strlen(ltype); j++)
++ ltype[j]=tolower(ltype[j]);
+
+ if ((rngtype=parse_uid_range(pamh, domain, &min_uid, &max_uid)) < 0) {
+ pam_syslog(pamh, LOG_WARNING, "invalid uid range '%s' - skipped", domain);
+ continue;
+ }
+
+- if (i == 4) { /* a complete line */
++ if (i == 4) { /* a complete line */
+ for(j=0; j < strlen(item); j++)
+ item[j]=tolower(item[j]);
+ for(j=0; j < strlen(value); j++)
+ value[j]=tolower(value[j]);
+
+- if (strcmp(uname, domain) == 0) /* this user have a limit */
+- process_limit(pamh, LIMITS_DEF_USER, ltype, item, value, ctrl, pl);
+- else if (domain[0]=='@') {
++ if (strcmp(uname, domain) == 0) /* this user have a limit */
++ process_limit(pamh, LIMITS_DEF_USER, ltype, item, value, ctrl, pl);
++ else if (domain[0]=='@') {
+ if (ctrl & PAM_DEBUG_ARG) {
+ pam_syslog(pamh, LOG_DEBUG,
+ "checking if %s is in group %s",
+@@ -849,7 +909,7 @@ parse_config_file(pam_handle_t *pamh, co
+ process_limit(pamh, LIMITS_DEF_GROUP, ltype, item, value, ctrl,
+ pl);
+ }
+- } else if (domain[0]=='%') {
++ } else if (domain[0]=='%') {
+ if (ctrl & PAM_DEBUG_ARG) {
+ pam_syslog(pamh, LOG_DEBUG,
+ "checking if %s is in group %s",
+@@ -880,7 +940,7 @@ parse_config_file(pam_handle_t *pamh, co
+ case LIMIT_RANGE_MM:
+ pam_syslog(pamh, LOG_WARNING, "range unsupported for %%group matching - ignored");
+ }
+- } else {
++ } else {
+ switch(rngtype) {
+ case LIMIT_RANGE_NONE:
+ if (strcmp(domain, "*") == 0)
+@@ -951,8 +1011,8 @@ parse_config_file(pam_handle_t *pamh, co
+ }
+ fclose(fil);
+ return PAM_IGNORE;
+- } else {
+- pam_syslog(pamh, LOG_WARNING, "invalid line '%s' - skipped", line);
++ } else {
++ pam_syslog(pamh, LOG_WARNING, "invalid line '%s' - skipped", line);
+ }
+ }
+ fclose(fil);
+@@ -979,8 +1039,8 @@ static int setup_limits(pam_handle_t *pa
+ /* skip it if its not initialized */
+ continue;
+ }
+- if (pl->limits[i].limit.rlim_cur > pl->limits[i].limit.rlim_max)
+- pl->limits[i].limit.rlim_cur = pl->limits[i].limit.rlim_max;
++ if (pl->limits[i].limit.rlim_cur > pl->limits[i].limit.rlim_max)
++ pl->limits[i].limit.rlim_cur = pl->limits[i].limit.rlim_max;
+ res = setrlimit(i, &pl->limits[i].limit);
+ if (res != 0)
+ pam_syslog(pamh, LOG_ERR, "Could not set limit for '%s': %m",
+@@ -989,30 +1049,30 @@ static int setup_limits(pam_handle_t *pa
+ }
+
+ if (status) {
+- retval = LIMIT_ERR;
++ retval = LIMIT_ERR;
+ }
+
+ status = setpriority(PRIO_PROCESS, 0, pl->priority);
+ if (status != 0) {
+- pam_syslog(pamh, LOG_ERR, "Could not set limit for PRIO_PROCESS: %m");
+- retval = LIMIT_ERR;
++ pam_syslog(pamh, LOG_ERR, "Could not set limit for PRIO_PROCESS: %m");
++ retval = LIMIT_ERR;
+ }
+
+ if (uid == 0) {
+ D(("skip login limit check for uid=0"));
+ } else if (pl->login_limit > 0) {
+- if (check_logins(pamh, uname, pl->login_limit, ctrl, pl) == LOGIN_ERR) {
++ if (check_logins(pamh, uname, pl->login_limit, ctrl, pl) == LOGIN_ERR) {
+ #ifdef HAVE_LIBAUDIT
+ if (!(ctrl & PAM_NO_AUDIT)) {
+ pam_modutil_audit_write(pamh, AUDIT_ANOM_LOGIN_SESSIONS,
+ "pam_limits", PAM_PERM_DENIED);
+ /* ignore return value as we fail anyway */
+- }
++ }
+ #endif
+- retval |= LOGIN_ERR;
++ retval |= LOGIN_ERR;
+ }
+ } else if (pl->login_limit == 0) {
+- retval |= LOGIN_ERR;
++ retval |= LOGIN_ERR;
+ }
+
+ if (pl->nonewprivs) {
+@@ -1049,22 +1109,22 @@ pam_sm_open_session (pam_handle_t *pamh,
+ ctrl = _pam_parse(pamh, argc, argv, pl);
+ retval = pam_get_item( pamh, PAM_USER, (void*) &user_name );
+ if ( user_name == NULL || retval != PAM_SUCCESS ) {
+- pam_syslog(pamh, LOG_ERR, "open_session - error recovering username");
+- return PAM_SESSION_ERR;
++ pam_syslog(pamh, LOG_ERR, "open_session - error recovering username");
++ return PAM_SESSION_ERR;
+ }
+
+ pwd = pam_modutil_getpwnam(pamh, user_name);
+ if (!pwd) {
+- if (ctrl & PAM_DEBUG_ARG)
+- pam_syslog(pamh, LOG_WARNING,
++ if (ctrl & PAM_DEBUG_ARG)
++ pam_syslog(pamh, LOG_WARNING,
+ "open_session username '%s' does not exist", user_name);
+- return PAM_USER_UNKNOWN;
++ return PAM_USER_UNKNOWN;
+ }
+
+ retval = init_limits(pamh, pl, ctrl);
+ if (retval != PAM_SUCCESS) {
+- pam_syslog(pamh, LOG_ERR, "cannot initialize");
+- return PAM_ABORT;
++ pam_syslog(pamh, LOG_ERR, "cannot initialize");
++ return PAM_ABORT;
+ }
+
+ retval = parse_config_file(pamh, pwd->pw_name, pwd->pw_uid, pwd->pw_gid, ctrl, pl);
+@@ -1099,7 +1159,7 @@ pam_sm_open_session (pam_handle_t *pamh,
+ }
+ if (retval != PAM_SUCCESS)
+ goto out;
+- }
++ }
+ }
+
+ out:
+@@ -1115,7 +1175,7 @@ out:
+ pam_error(pamh, _("There were too many logins for '%s'."),
+ pwd->pw_name);
+ if (retval != LIMITED_OK) {
+- return PAM_PERM_DENIED;
++ return PAM_PERM_DENIED;
+ }
+
+ return PAM_SUCCESS;
diff --git a/pam.changes b/pam.changes
index 8c8680e..25b562a 100644
--- a/pam.changes
+++ b/pam.changes
@@ -1,3 +1,13 @@
+-------------------------------------------------------------------
+Wed Mar 31 11:43:17 UTC 2021 - Josef Möllers
+
+- pam_limits: "unlimited" is not a legitimate value for "nofile"
+ (see setrlimit(2)). So, when "nofile" is set to one of the
+ "unlimited" values, it is set to the contents of
+ "/proc/sys/fs/nr_open" instead.
+ Also changed the manpage of pam_limits to express this.
+ [bsc#1181443, pam-bsc1181443-make-nofile-unlimited-mean-nr_open.patch]
+
-------------------------------------------------------------------
Thu Feb 18 22:16:43 UTC 2021 - Thorsten Kukuk
diff --git a/pam.spec b/pam.spec
index 52a9852..1db726f 100644
--- a/pam.spec
+++ b/pam.spec
@@ -65,6 +65,7 @@ Patch6: pam_cracklib-removal.patch
Patch7: pam_tally2-removal.patch
Patch8: pam-bsc1177858-dont-free-environment-string.patch
Patch9: pam-pam_cracklib-add-usersubstr.patch
+Patch10: pam-bsc1181443-make-nofile-unlimited-mean-nr_open.patch
BuildRequires: audit-devel
BuildRequires: bison
BuildRequires: cracklib-devel
@@ -176,6 +177,7 @@ cp -a %{SOURCE12} .
%patch7 -R -p1
%patch8 -p1
%patch9 -p1
+%patch10 -p1
%if 0%{?usrmerged}
%patch99 -p1
%endif