summaryrefslogtreecommitdiff
path: root/modules/pam_limits
diff options
context:
space:
mode:
Diffstat (limited to 'modules/pam_limits')
-rw-r--r--modules/pam_limits/Makefile.am8
-rw-r--r--modules/pam_limits/Makefile.in51
-rw-r--r--modules/pam_limits/README14
-rw-r--r--modules/pam_limits/README.xml32
-rw-r--r--modules/pam_limits/limits.conf17
-rw-r--r--modules/pam_limits/limits.conf.582
-rw-r--r--modules/pam_limits/limits.conf.5.xml130
-rw-r--r--modules/pam_limits/pam_limits.820
-rw-r--r--modules/pam_limits/pam_limits.8.xml81
-rw-r--r--modules/pam_limits/pam_limits.c433
10 files changed, 624 insertions, 244 deletions
diff --git a/modules/pam_limits/Makefile.am b/modules/pam_limits/Makefile.am
index 911b07b3..3a3b5e01 100644
--- a/modules/pam_limits/Makefile.am
+++ b/modules/pam_limits/Makefile.am
@@ -15,12 +15,16 @@ dist_check_SCRIPTS = tst-pam_limits
TESTS = $(dist_check_SCRIPTS)
securelibdir = $(SECUREDIR)
+if HAVE_VENDORDIR
+secureconfdir = $(VENDOR_SCONFIGDIR)
+else
secureconfdir = $(SCONFIGDIR)
+endif
limits_conf_dir = $(SCONFIGDIR)/limits.d
AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
- -DLIMITS_FILE_DIR=\"$(limits_conf_dir)/*.conf\" \
- -DLIMITS_FILE=\"$(SCONFIGDIR)/limits.conf\" $(WARN_CFLAGS)
+ -DLIMITS_FILE_DIR=\"$(limits_conf_dir)\" \
+ $(WARN_CFLAGS)
AM_LDFLAGS = -no-undefined -avoid-version -module
if HAVE_VERSIONING
AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
diff --git a/modules/pam_limits/Makefile.in b/modules/pam_limits/Makefile.in
index ac06d6c0..7b515b83 100644
--- a/modules/pam_limits/Makefile.in
+++ b/modules/pam_limits/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -96,18 +96,21 @@ host_triplet = @host@
@HAVE_VERSIONING_TRUE@am__append_1 = -Wl,--version-script=$(srcdir)/../modules.map
subdir = modules/pam_limits
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \
- $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \
- $(top_srcdir)/m4/japhar_grep_cflags.m4 \
+am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \
+ $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/iconv.m4 \
+ $(top_srcdir)/m4/intlmacosx.m4 \
$(top_srcdir)/m4/jh_path_xml_catalog.m4 \
$(top_srcdir)/m4/ld-O1.m4 $(top_srcdir)/m4/ld-as-needed.m4 \
- $(top_srcdir)/m4/ld-no-undefined.m4 $(top_srcdir)/m4/lib-ld.m4 \
+ $(top_srcdir)/m4/ld-no-undefined.m4 \
+ $(top_srcdir)/m4/ld-z-now.m4 $(top_srcdir)/m4/lib-ld.m4 \
$(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \
$(top_srcdir)/m4/libprelude.m4 $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
$(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \
- $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/configure.ac
+ $(top_srcdir)/m4/progtest.m4 \
+ $(top_srcdir)/m4/warn_lang_flags.m4 \
+ $(top_srcdir)/m4/warnings.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(dist_check_SCRIPTS) \
@@ -376,6 +379,7 @@ am__set_TESTS_bases = \
bases='$(TEST_LOGS)'; \
bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \
bases=`echo $$bases`
+AM_TESTSUITE_SUMMARY_HEADER = ' for $(PACKAGE_STRING)'
RECHECK_LOGS = $(TEST_LOGS)
AM_RECURSIVE_TARGETS = check recheck
TEST_SUITE_LOG = test-suite.log
@@ -420,10 +424,14 @@ CC_FOR_BUILD = @CC_FOR_BUILD@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
+CRYPTO_LIBS = @CRYPTO_LIBS@
+CRYPT_CFLAGS = @CRYPT_CFLAGS@
+CRYPT_LIBS = @CRYPT_LIBS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
+DOCBOOK_RNG = @DOCBOOK_RNG@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
@@ -433,12 +441,16 @@ ECONF_CFLAGS = @ECONF_CFLAGS@
ECONF_LIBS = @ECONF_LIBS@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
+EXE_CFLAGS = @EXE_CFLAGS@
+EXE_LDFLAGS = @EXE_LDFLAGS@
FGREP = @FGREP@
+FILECMD = @FILECMD@
FO2PDF = @FO2PDF@
GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
GMSGFMT = @GMSGFMT@
GMSGFMT_015 = @GMSGFMT_015@
GREP = @GREP@
+HTML_STYLESHEET = @HTML_STYLESHEET@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
@@ -452,7 +464,6 @@ LEX = @LEX@
LEXLIB = @LEXLIB@
LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
LIBAUDIT = @LIBAUDIT@
-LIBCRACK = @LIBCRACK@
LIBCRYPT = @LIBCRYPT@
LIBDB = @LIBDB@
LIBDL = @LIBDL@
@@ -471,12 +482,14 @@ LIBSELINUX = @LIBSELINUX@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN_S = @LN_S@
+LOGIND_CFLAGS = @LOGIND_CFLAGS@
LTLIBICONV = @LTLIBICONV@
LTLIBINTL = @LTLIBINTL@
LTLIBOBJS = @LTLIBOBJS@
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
+MAN_STYLESHEET = @MAN_STYLESHEET@
MKDIR_P = @MKDIR_P@
MSGFMT = @MSGFMT@
MSGFMT_015 = @MSGFMT_015@
@@ -499,8 +512,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
-PIE_CFLAGS = @PIE_CFLAGS@
-PIE_LDFLAGS = @PIE_LDFLAGS@
+PDF_STYLESHEET = @PDF_STYLESHEET@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
@@ -511,11 +523,16 @@ SECUREDIR = @SECUREDIR@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
+STRINGPARAM_PROFILECONDITIONS = @STRINGPARAM_PROFILECONDITIONS@
STRINGPARAM_VENDORDIR = @STRINGPARAM_VENDORDIR@
STRIP = @STRIP@
+SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@
+SYSTEMD_LIBS = @SYSTEMD_LIBS@
TIRPC_CFLAGS = @TIRPC_CFLAGS@
TIRPC_LIBS = @TIRPC_LIBS@
+TXT_STYLESHEET = @TXT_STYLESHEET@
USE_NLS = @USE_NLS@
+VENDOR_SCONFIGDIR = @VENDOR_SCONFIGDIR@
VERSION = @VERSION@
WARN_CFLAGS = @WARN_CFLAGS@
XGETTEXT = @XGETTEXT@
@@ -560,7 +577,6 @@ htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
-libc_cv_fpie = @libc_cv_fpie@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
@@ -568,9 +584,6 @@ localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
-pam_cv_ld_O1 = @pam_cv_ld_O1@
-pam_cv_ld_as_needed = @pam_cv_ld_as_needed@
-pam_cv_ld_no_undefined = @pam_cv_ld_no_undefined@
pam_xauth_path = @pam_xauth_path@
pdfdir = @pdfdir@
prefix = @prefix@
@@ -580,6 +593,7 @@ sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
+systemdunitdir = @systemdunitdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
@@ -592,11 +606,12 @@ XMLS = README.xml limits.conf.5.xml pam_limits.8.xml
dist_check_SCRIPTS = tst-pam_limits
TESTS = $(dist_check_SCRIPTS)
securelibdir = $(SECUREDIR)
-secureconfdir = $(SCONFIGDIR)
+@HAVE_VENDORDIR_FALSE@secureconfdir = $(SCONFIGDIR)
+@HAVE_VENDORDIR_TRUE@secureconfdir = $(VENDOR_SCONFIGDIR)
limits_conf_dir = $(SCONFIGDIR)/limits.d
AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
- -DLIMITS_FILE_DIR=\"$(limits_conf_dir)/*.conf\" \
- -DLIMITS_FILE=\"$(SCONFIGDIR)/limits.conf\" $(WARN_CFLAGS)
+ -DLIMITS_FILE_DIR=\"$(limits_conf_dir)\" \
+ $(WARN_CFLAGS)
AM_LDFLAGS = -no-undefined -avoid-version -module $(am__append_1)
securelib_LTLIBRARIES = pam_limits.la
@@ -982,7 +997,7 @@ $(TEST_SUITE_LOG): $(TEST_LOGS)
test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \
fi; \
echo "$${col}$$br$${std}"; \
- echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \
+ echo "$${col}Testsuite summary"$(AM_TESTSUITE_SUMMARY_HEADER)"$${std}"; \
echo "$${col}$$br$${std}"; \
create_testsuite_report --maybe-color; \
echo "$$col$$br$$std"; \
diff --git a/modules/pam_limits/README b/modules/pam_limits/README
index 6aabd54f..dc560eff 100644
--- a/modules/pam_limits/README
+++ b/modules/pam_limits/README
@@ -15,6 +15,18 @@ concatenated together in the order of parsing. If a config file is explicitly
specified with a module option then the files in the above directory are not
parsed.
+By default limits are taken from the /etc/security/limits.conf config file or,
+if that one is not present, the file %vendordir%/security/limits.conf. Then
+individual *.conf files from the /etc/security/limits.d/ and %vendordir%/
+security/limits.d directories are read. If /etc/security/limits.d/
+@filename@.conf exists, then %vendordir%/security/limits.d/@filename@.conf will
+not be used. All limits.d/*.conf files are sorted by their @filename@.conf in
+lexicographic order regardless of which of the directories they reside in. The
+effect of the individual files is the same as if all the files were
+concatenated together in the order of parsing. If a config file is explicitly
+specified with the config option the files in the above directories are not
+parsed.
+
The module must not be called by a multithreaded application.
If Linux PAM is compiled with audit support the module will report when it
@@ -56,12 +68,14 @@ These are some example lines which might be specified in /etc/security/
limits.conf.
* soft core 0
+root hard core 100000
* hard nofile 512
@student hard nproc 20
@faculty soft nproc 20
@faculty hard nproc 50
ftp hard nproc 0
@student - maxlogins 4
+@student - nonewprivs 1
:123 hard cpu 5000
@500: soft cpu 10000
600:700 hard locks 10
diff --git a/modules/pam_limits/README.xml b/modules/pam_limits/README.xml
index 964a5a21..25a463cc 100644
--- a/modules/pam_limits/README.xml
+++ b/modules/pam_limits/README.xml
@@ -1,39 +1,23 @@
-<?xml version="1.0" encoding='UTF-8'?>
-<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
-"http://www.docbook.org/xml/4.3/docbookx.dtd"
-[
-<!--
-<!ENTITY pamlimits SYSTEM "pam_limits.8.xml">
--->
-<!--
-<!ENTITY limitsconf SYSTEM "limits.conf.5.xml">
--->
-]>
+<article xmlns="http://docbook.org/ns/docbook" version="5.0">
-<article>
-
- <articleinfo>
+ <info>
<title>
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
- href="pam_limits.8.xml" xpointer='xpointer(//refnamediv[@id = "pam_limits-name"]/*)'/>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="pam_limits.8.xml" xpointer='xpointer(id("pam_limits-name")/*)'/>
</title>
- </articleinfo>
+ </info>
<section>
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
- href="pam_limits.8.xml" xpointer='xpointer(//refsect1[@id = "pam_limits-description"]/*)'/>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="pam_limits.8.xml" xpointer='xpointer(id("pam_limits-description")/*)'/>
</section>
<section>
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
- href="pam_limits.8.xml" xpointer='xpointer(//refsect1[@id = "pam_limits-options"]/*)'/>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="pam_limits.8.xml" xpointer='xpointer(id("pam_limits-options")/*)'/>
</section>
<section>
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
- href="limits.conf.5.xml" xpointer='xpointer(//refsect1[@id = "limits.conf-examples"]/*)'/>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="limits.conf.5.xml" xpointer='xpointer(id("limits.conf-examples")/*)'/>
</section>
-</article>
+</article> \ No newline at end of file
diff --git a/modules/pam_limits/limits.conf b/modules/pam_limits/limits.conf
index be621a7c..6b3865cb 100644
--- a/modules/pam_limits/limits.conf
+++ b/modules/pam_limits/limits.conf
@@ -1,5 +1,16 @@
# /etc/security/limits.conf
#
+#This file sets the resource limits for the users logged in via PAM.
+#It does not affect resource limits of the system services.
+#
+#Also note that configuration files in /etc/security/limits.d directory,
+#which are read in alphabetical order, override the settings in this
+#file in case the domain is the same or more specific.
+#That means, for example, that setting a limit for wildcard domain here
+#can be overridden with a wildcard setting in a config file in the
+#subdirectory, but a user specific setting here can be overridden only
+#with a user specific setting in the subdirectory.
+#
#Each line describes a limit for a user in the form:
#
#<domain> <type> <item> <value>
@@ -11,6 +22,9 @@
# - the wildcard *, for default entry
# - the wildcard %, can be also used with %group syntax,
# for maxlogin limit
+# - NOTE: group and wildcard limits are not applied to root.
+# To apply a limit to the root user, <domain> must be
+# the literal username root.
#
#<type> can have the two values:
# - "soft" for enforcing the soft limits
@@ -35,16 +49,19 @@
# - msgqueue - max memory used by POSIX message queues (bytes)
# - nice - max nice priority allowed to raise to values: [-20, 19]
# - rtprio - max realtime priority
+# - chroot - change root to directory (Debian-specific)
#
#<domain> <type> <item> <value>
#
#* soft core 0
+#root hard core 100000
#* hard rss 10000
#@student hard nproc 20
#@faculty soft nproc 20
#@faculty hard nproc 50
#ftp hard nproc 0
+#ftp - chroot /ftp
#@student - maxlogins 4
# End of file
diff --git a/modules/pam_limits/limits.conf.5 b/modules/pam_limits/limits.conf.5
index f527fec8..c9c41876 100644
--- a/modules/pam_limits/limits.conf.5
+++ b/modules/pam_limits/limits.conf.5
@@ -1,13 +1,13 @@
'\" t
.\" Title: limits.conf
.\" Author: [see the "AUTHOR" section]
-.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
-.\" Date: 06/08/2020
+.\" Generator: DocBook XSL Stylesheets v1.79.2 <http://docbook.sf.net/>
+.\" Date: 05/07/2023
.\" Manual: Linux-PAM Manual
-.\" Source: Linux-PAM Manual
+.\" Source: Linux-PAM
.\" Language: English
.\"
-.TH "LIMITS\&.CONF" "5" "06/08/2020" "Linux-PAM Manual" "Linux\-PAM Manual"
+.TH "LIMITS\&.CONF" "5" "05/07/2023" "Linux\-PAM" "Linux\-PAM Manual"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
@@ -50,7 +50,7 @@ The syntax of the lines is as follows:
.PP
The fields listed above should be filled as follows:
.PP
-\fB<domain>\fR
+<domain>
.RS 4
.sp
.RS 4
@@ -145,19 +145,23 @@ a gid specified as
\fB%:\fR\fI<gid>\fR
applicable to maxlogins limit only\&. It limits the total number of logins of all users that are member of the group with the specified gid\&.
.RE
+.sp
+\fBNOTE:\fR
+group and wildcard limits are not applied to the root user\&. To set a limit for the root user, this field must contain the literal username
+\fBroot\fR\&.
.RE
.PP
-\fB<type>\fR
+<type>
.RS 4
.PP
-\fBhard\fR
+hard
.RS 4
for enforcing
\fBhard\fR
resource limits\&. These limits are set by the superuser and enforced by the Kernel\&. The user cannot raise his requirement of system resources above such values\&.
.RE
.PP
-\fBsoft\fR
+soft
.RS 4
for enforcing
\fBsoft\fR
@@ -168,7 +172,7 @@ limits\&. The values specified with this token can be thought of as
values, for normal system usage\&.
.RE
.PP
-\fB\-\fR
+\-
.RS 4
for enforcing both
\fBsoft\fR
@@ -180,100 +184,110 @@ Note, if you specify a type of \*(Aq\-\*(Aq but neglect to supply the item and v
.RE
.RE
.PP
-\fB<item>\fR
+<item>
.RS 4
.PP
-\fBcore\fR
+core
.RS 4
limits the core file size (KB)
.RE
.PP
-\fBdata\fR
+data
.RS 4
maximum data size (KB)
.RE
.PP
-\fBfsize\fR
+fsize
.RS 4
maximum filesize (KB)
.RE
.PP
-\fBmemlock\fR
+memlock
.RS 4
maximum locked\-in\-memory address space (KB)
.RE
.PP
-\fBnofile\fR
+nofile
.RS 4
maximum number of open file descriptors
.RE
.PP
-\fBrss\fR
+rss
.RS 4
maximum resident set size (KB) (Ignored in Linux 2\&.4\&.30 and higher)
.RE
.PP
-\fBstack\fR
+stack
.RS 4
maximum stack size (KB)
.RE
.PP
-\fBcpu\fR
+cpu
.RS 4
maximum CPU time (minutes)
.RE
.PP
-\fBnproc\fR
+nproc
.RS 4
maximum number of processes
.RE
.PP
-\fBas\fR
+as
.RS 4
address space limit (KB)
.RE
.PP
-\fBmaxlogins\fR
+maxlogins
.RS 4
maximum number of logins for this user (this limit does not apply to user with
\fIuid=0\fR)
.RE
.PP
-\fBmaxsyslogins\fR
+maxsyslogins
.RS 4
maximum number of all logins on system; user is not allowed to log\-in if total number of all user logins is greater than specified number (this limit does not apply to user with
\fIuid=0\fR)
.RE
.PP
-\fBpriority\fR
+nonewprivs
+.RS 4
+value of 0 or 1; if set to 1 disables acquiring new privileges by invoking prctl(PR_SET_NO_NEW_PRIVS)
+.RE
+.PP
+priority
.RS 4
the priority to run user process with (negative values boost process priority)
.RE
.PP
-\fBlocks\fR
+locks
.RS 4
maximum locked files (Linux 2\&.4 and higher)
.RE
.PP
-\fBsigpending\fR
+sigpending
.RS 4
maximum number of pending signals (Linux 2\&.6 and higher)
.RE
.PP
-\fBmsgqueue\fR
+msgqueue
.RS 4
maximum memory used by POSIX message queues (bytes) (Linux 2\&.6 and higher)
.RE
.PP
-\fBnice\fR
+nice
.RS 4
maximum nice priority allowed to raise to (Linux 2\&.6\&.12 and higher) values: [\-20,19]
.RE
.PP
-\fBrtprio\fR
+rtprio
.RS 4
maximum realtime priority allowed for non\-privileged processes (Linux 2\&.6\&.12 and higher)
.RE
+.PP
+\fBchroot\fR
+.RS 4
+the directory to chroot the user to
+.RE
.RE
.PP
All items support the values
@@ -282,9 +296,11 @@ All items support the values
or
\fIinfinity\fR
indicating no limit, except for
-\fBpriority\fR
-and
-\fBnice\fR\&.
+\fBpriority\fR,
+\fBnice\fR, and
+\fBnonewprivs\fR\&. If
+\fBnofile\fR
+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))\&.
.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
@@ -315,12 +331,14 @@ These are some example lines which might be specified in
.\}
.nf
* soft core 0
+root hard core 100000
* hard nofile 512
@student hard nproc 20
@faculty soft nproc 20
@faculty hard nproc 50
ftp hard nproc 0
@student \- maxlogins 4
+@student \- nonewprivs 1
:123 hard cpu 5000
@500: soft cpu 10000
600:700 hard locks 10
@@ -333,7 +351,7 @@ ftp hard nproc 0
.PP
\fBpam_limits\fR(8),
\fBpam.d\fR(5),
-\fBpam\fR(8),
+\fBpam\fR(7),
\fBgetrlimit\fR(2),
\fBgetrlimit\fR(3p)
.SH "AUTHOR"
diff --git a/modules/pam_limits/limits.conf.5.xml b/modules/pam_limits/limits.conf.5.xml
index 380a1399..d3893350 100644
--- a/modules/pam_limits/limits.conf.5.xml
+++ b/modules/pam_limits/limits.conf.5.xml
@@ -1,13 +1,10 @@
-<?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="limits.conf">
+<refentry xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="limits.conf">
<refmeta>
<refentrytitle>limits.conf</refentrytitle>
<manvolnum>5</manvolnum>
- <refmiscinfo class="sectdesc">Linux-PAM Manual</refmiscinfo>
+ <refmiscinfo class="source">Linux-PAM</refmiscinfo>
+ <refmiscinfo class="manual">Linux-PAM Manual</refmiscinfo>
</refmeta>
<refnamediv>
@@ -15,7 +12,7 @@
<refpurpose>configuration file for the pam_limits module</refpurpose>
</refnamediv>
- <refsect1 id='limits.conf-description'>
+ <refsect1 xml:id="limits.conf-description">
<title>DESCRIPTION</title>
<para>
The <emphasis>pam_limits.so</emphasis> module applies ulimit limits,
@@ -38,7 +35,7 @@
<variablelist>
<varlistentry>
<term>
- <option>&lt;domain&gt;</option>
+ &lt;domain&gt;
</term>
<listitem>
<itemizedlist>
@@ -49,38 +46,35 @@
</listitem>
<listitem>
<para>
- a groupname, with <emphasis remap='B'>@group</emphasis> syntax.
+ a groupname, with <emphasis remap="B">@group</emphasis> syntax.
This should not be confused with netgroups.
</para>
</listitem>
<listitem>
<para>
- the wildcard <emphasis remap='B'>*</emphasis>, for default entry.
+ the wildcard <emphasis remap="B">*</emphasis>, for default entry.
</para>
</listitem>
<listitem>
<para>
- the wildcard <emphasis remap='B'>%</emphasis>, for maxlogins limit only,
- can also be used with <emphasis remap='B'>%group</emphasis> syntax. If the
- <emphasis remap='B'>%</emphasis> wildcard is used alone it is identical
- to using <emphasis remap='B'>*</emphasis> with maxsyslogins limit. With
- a group specified after <emphasis remap='B'>%</emphasis> it limits the total
+ the wildcard <emphasis remap="B">%</emphasis>, for maxlogins limit only,
+ can also be used with <emphasis remap="B">%group</emphasis> syntax. If the
+ <emphasis remap="B">%</emphasis> wildcard is used alone it is identical
+ to using <emphasis remap="B">*</emphasis> with maxsyslogins limit. With
+ a group specified after <emphasis remap="B">%</emphasis> it limits the total
number of logins of all users that are member of the group.
</para>
</listitem>
<listitem>
<para>
- an uid range specified as <replaceable>&lt;min_uid&gt;</replaceable><emphasis
- remap='B'>:</emphasis><replaceable>&lt;max_uid&gt;</replaceable>. If min_uid
+ an uid range specified as <replaceable>&lt;min_uid&gt;</replaceable><emphasis remap="B">:</emphasis><replaceable>&lt;max_uid&gt;</replaceable>. If min_uid
is omitted, the match is exact for the max_uid. If max_uid is omitted, all
uids greater than or equal min_uid match.
</para>
</listitem>
<listitem>
<para>
- a gid range specified as <emphasis
- remap='B'>@</emphasis><replaceable>&lt;min_gid&gt;</replaceable><emphasis
- remap='B'>:</emphasis><replaceable>&lt;max_gid&gt;</replaceable>. If min_gid
+ a gid range specified as <emphasis remap="B">@</emphasis><replaceable>&lt;min_gid&gt;</replaceable><emphasis remap="B">:</emphasis><replaceable>&lt;max_gid&gt;</replaceable>. If min_gid
is omitted, the match is exact for the max_gid. If max_gid is omitted, all
gids greater than or equal min_gid match. For the exact match all groups including
the user's supplementary groups are examined. For the range matches only
@@ -89,50 +83,54 @@
</listitem>
<listitem>
<para>
- a gid specified as <emphasis
- remap='B'>%:</emphasis><replaceable>&lt;gid&gt;</replaceable> applicable
+ a gid specified as <emphasis remap="B">%:</emphasis><replaceable>&lt;gid&gt;</replaceable> applicable
to maxlogins limit only. It limits the total number of logins of all users
that are member of the group with the specified gid.
</para>
</listitem>
</itemizedlist>
+ <para>
+ <emphasis remap='B'>NOTE:</emphasis> group and wildcard limits are not
+ applied to the root user. To set a limit for the root user, this field
+ must contain the literal username <emphasis remap='B'>root</emphasis>.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term>
- <option>&lt;type&gt;</option>
+ &lt;type&gt;
</term>
<listitem>
<variablelist>
<varlistentry>
- <term><option>hard</option></term>
+ <term>hard</term>
<listitem>
<para>
- for enforcing <emphasis remap='B'>hard</emphasis> resource limits.
+ for enforcing <emphasis remap="B">hard</emphasis> resource limits.
These limits are set by the superuser and enforced by the Kernel.
The user cannot raise his requirement of system resources above such values.
</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>soft</option></term>
+ <term>soft</term>
<listitem>
<para>
- for enforcing <emphasis remap='B'>soft</emphasis> resource limits.
+ for enforcing <emphasis remap="B">soft</emphasis> resource limits.
These limits are ones that the user can move up or down within the
- permitted range by any pre-existing <emphasis remap='B'>hard</emphasis>
+ permitted range by any pre-existing <emphasis remap="B">hard</emphasis>
limits. The values specified with this token can be thought of as
<emphasis>default</emphasis> values, for normal system usage.
</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>-</option></term>
+ <term>-</term>
<listitem>
<para>
- for enforcing both <emphasis remap='B'>soft</emphasis> and
- <emphasis remap='B'>hard</emphasis> resource limits together.
+ for enforcing both <emphasis remap="B">soft</emphasis> and
+ <emphasis remap="B">hard</emphasis> resource limits together.
</para>
<para>
Note, if you specify a type of '-' but neglect to supply the
@@ -147,79 +145,79 @@
<varlistentry>
<term>
- <option>&lt;item&gt;</option>
+ &lt;item&gt;
</term>
<listitem>
<variablelist>
<varlistentry>
- <term><option>core</option></term>
+ <term>core</term>
<listitem>
<para>limits the core file size (KB)</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>data</option></term>
+ <term>data</term>
<listitem>
<para>maximum data size (KB)</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>fsize</option></term>
+ <term>fsize</term>
<listitem>
<para>maximum filesize (KB)</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>memlock</option></term>
+ <term>memlock</term>
<listitem>
<para>maximum locked-in-memory address space (KB)</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>nofile</option></term>
+ <term>nofile</term>
<listitem>
<para>maximum number of open file descriptors</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>rss</option></term>
+ <term>rss</term>
<listitem>
<para>maximum resident set size (KB) (Ignored in Linux 2.4.30 and higher)</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>stack</option></term>
+ <term>stack</term>
<listitem>
<para>maximum stack size (KB)</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>cpu</option></term>
+ <term>cpu</term>
<listitem>
<para>maximum CPU time (minutes)</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>nproc</option></term>
+ <term>nproc</term>
<listitem>
<para>maximum number of processes</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>as</option></term>
+ <term>as</term>
<listitem>
<para>address space limit (KB)</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>maxlogins</option></term>
+ <term>maxlogins</term>
<listitem>
<para>maximum number of logins for this user (this limit does
not apply to user with <emphasis>uid=0</emphasis>)</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>maxsyslogins</option></term>
+ <term>maxsyslogins</term>
<listitem>
<para>maximum number of all logins on system; user is not
allowed to log-in if total number of all user logins is
@@ -228,44 +226,57 @@
</listitem>
</varlistentry>
<varlistentry>
- <term><option>priority</option></term>
+ <term>nonewprivs</term>
+ <listitem>
+ <para>value of 0 or 1; if set to 1 disables acquiring new
+ privileges by invoking prctl(PR_SET_NO_NEW_PRIVS)</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>priority</term>
<listitem>
<para>the priority to run user process with (negative
values boost process priority)</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>locks</option></term>
+ <term>locks</term>
<listitem>
<para>maximum locked files (Linux 2.4 and higher)</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>sigpending</option></term>
+ <term>sigpending</term>
<listitem>
<para>maximum number of pending signals (Linux 2.6 and higher)</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>msgqueue</option></term>
+ <term>msgqueue</term>
<listitem>
<para>maximum memory used by POSIX message queues (bytes)
(Linux 2.6 and higher)</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>nice</option></term>
+ <term>nice</term>
<listitem>
<para>maximum nice priority allowed to raise to (Linux 2.6.12 and higher) values: [-20,19]</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>rtprio</option></term>
+ <term>rtprio</term>
<listitem>
<para>maximum realtime priority allowed for non-privileged processes
(Linux 2.6.12 and higher)</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>chroot</option></term>
+ <listitem>
+ <para>the directory to chroot the user to</para>
+ </listitem>
+ </varlistentry>
</variablelist>
</listitem>
</varlistentry>
@@ -274,7 +285,10 @@
<para>
All items support the values <emphasis>-1</emphasis>,
<emphasis>unlimited</emphasis> or <emphasis>infinity</emphasis> indicating no limit,
- except for <emphasis remap='B'>priority</emphasis> and <emphasis remap='B'>nice</emphasis>.
+ except for <emphasis remap="B">priority</emphasis>, <emphasis remap="B">nice</emphasis>,
+ and <emphasis remap="B">nonewprivs</emphasis>.
+ If <emphasis remap="B">nofile</emphasis> 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)).
</para>
<para>
If a hard limit or soft limit of a resource is set to a valid value,
@@ -299,7 +313,7 @@
</para>
<para>
In the <emphasis>limits</emphasis> configuration file, the
- '<emphasis remap='B'>#</emphasis>' character introduces a comment
+ '<emphasis remap="B">#</emphasis>' character introduces a comment
- after which the rest of the line is ignored.
</para>
<para>
@@ -309,7 +323,7 @@
</para>
</refsect1>
- <refsect1 id="limits.conf-examples">
+ <refsect1 xml:id="limits.conf-examples">
<title>EXAMPLES</title>
<para>
These are some example lines which might be specified in
@@ -317,33 +331,35 @@
</para>
<programlisting>
* soft core 0
+root hard core 100000
* hard nofile 512
@student hard nproc 20
@faculty soft nproc 20
@faculty hard nproc 50
ftp hard nproc 0
@student - maxlogins 4
+@student - nonewprivs 1
:123 hard cpu 5000
@500: soft cpu 10000
600:700 hard locks 10
</programlisting>
</refsect1>
- <refsect1 id="limits.conf-see_also">
+ <refsect1 xml:id="limits.conf-see_also">
<title>SEE ALSO</title>
<para>
<citerefentry><refentrytitle>pam_limits</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>pam.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>pam</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>pam</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
<citerefentry><refentrytitle>getrlimit</refentrytitle><manvolnum>2</manvolnum></citerefentry>,
<citerefentry><refentrytitle>getrlimit</refentrytitle><manvolnum>3p</manvolnum></citerefentry>
</para>
</refsect1>
- <refsect1 id="limits.conf-author">
+ <refsect1 xml:id="limits.conf-author">
<title>AUTHOR</title>
<para>
pam_limits was initially written by Cristian Gafton &lt;gafton@redhat.com&gt;
</para>
</refsect1>
-</refentry>
+</refentry> \ No newline at end of file
diff --git a/modules/pam_limits/pam_limits.8 b/modules/pam_limits/pam_limits.8
index fbbacc66..f971b64c 100644
--- a/modules/pam_limits/pam_limits.8
+++ b/modules/pam_limits/pam_limits.8
@@ -1,13 +1,13 @@
'\" t
.\" Title: pam_limits
.\" Author: [see the "AUTHORS" section]
-.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
-.\" Date: 06/08/2020
+.\" Generator: DocBook XSL Stylesheets v1.79.2 <http://docbook.sf.net/>
+.\" Date: 05/07/2023
.\" Manual: Linux-PAM Manual
-.\" Source: Linux-PAM Manual
+.\" Source: Linux-PAM
.\" Language: English
.\"
-.TH "PAM_LIMITS" "8" "06/08/2020" "Linux-PAM Manual" "Linux-PAM Manual"
+.TH "PAM_LIMITS" "8" "05/07/2023" "Linux\-PAM" "Linux\-PAM Manual"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
@@ -49,27 +49,27 @@ The module must not be called by a multithreaded application\&.
If Linux PAM is compiled with audit support the module will report when it denies access based on limit of maximum number of concurrent login sessions\&.
.SH "OPTIONS"
.PP
-\fBconf=\fR\fB\fI/path/to/limits\&.conf\fR\fR
+conf=/path/to/limits\&.conf
.RS 4
Indicate an alternative limits\&.conf style configuration file to override the default\&.
.RE
.PP
-\fBdebug\fR
+debug
.RS 4
Print debug information\&.
.RE
.PP
-\fBset_all\fR
+set_all
.RS 4
Set the limits for which no value is specified in the configuration file to the one from the process with the PID 1\&. Please note that if the init process is systemd these limits will not be the kernel default limits and this option should not be used\&.
.RE
.PP
-\fButmp_early\fR
+utmp_early
.RS 4
Some broken applications actually allocate a utmp entry for the user before the user is admitted to the system\&. If some of the services you are configuring PAM for do this, you can selectively use this module argument to compensate for this behavior and at the same time maintain system\-wide consistency with a single limits\&.conf file\&.
.RE
.PP
-\fBnoaudit\fR
+noaudit
.RS 4
Do not report exceeded maximum logins count to the audit subsystem\&.
.RE
@@ -146,7 +146,7 @@ Replace "login" for each service you are using this module\&.
.PP
\fBlimits.conf\fR(5),
\fBpam.d\fR(5),
-\fBpam\fR(8)\&.
+\fBpam\fR(7)\&.
.SH "AUTHORS"
.PP
pam_limits was initially written by Cristian Gafton <gafton@redhat\&.com>
diff --git a/modules/pam_limits/pam_limits.8.xml b/modules/pam_limits/pam_limits.8.xml
index bc46cbf4..8f026f0a 100644
--- a/modules/pam_limits/pam_limits.8.xml
+++ b/modules/pam_limits/pam_limits.8.xml
@@ -1,16 +1,13 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
-
-<refentry id='pam_limits'>
+<refentry xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="pam_limits">
<refmeta>
<refentrytitle>pam_limits</refentrytitle>
<manvolnum>8</manvolnum>
- <refmiscinfo class='setdesc'>Linux-PAM Manual</refmiscinfo>
+ <refmiscinfo class="source">Linux-PAM</refmiscinfo>
+ <refmiscinfo class="manual">Linux-PAM Manual</refmiscinfo>
</refmeta>
- <refnamediv id='pam_limits-name'>
+ <refnamediv xml:id="pam_limits-name">
<refname>pam_limits</refname>
<refpurpose>
PAM module to limit resources
@@ -20,35 +17,35 @@
<!-- body begins here -->
<refsynopsisdiv>
- <cmdsynopsis id="pam_limits-cmdsynopsis">
+ <cmdsynopsis xml:id="pam_limits-cmdsynopsis" sepchar=" ">
<command>pam_limits.so</command>
- <arg choice="opt">
+ <arg choice="opt" rep="norepeat">
conf=<replaceable>/path/to/limits.conf</replaceable>
</arg>
- <arg choice="opt">
+ <arg choice="opt" rep="norepeat">
debug
</arg>
- <arg choice="opt">
+ <arg choice="opt" rep="norepeat">
set_all
</arg>
- <arg choice="opt">
+ <arg choice="opt" rep="norepeat">
utmp_early
</arg>
- <arg choice="opt">
+ <arg choice="opt" rep="norepeat">
noaudit
</arg>
</cmdsynopsis>
</refsynopsisdiv>
- <refsect1 id="pam_limits-description">
+ <refsect1 xml:id="pam_limits-description">
<title>DESCRIPTION</title>
<para>
The pam_limits PAM module sets limits on the system resources that can be
obtained in a user-session. Users of <emphasis>uid=0</emphasis> are affected
by this limits, too.
</para>
- <para>
+ <para condition="without_vendordir">
By default limits are taken from the <filename>/etc/security/limits.conf</filename>
config file. Then individual *.conf files from the <filename>/etc/security/limits.d/</filename>
directory are read. The files are parsed one after another in the order of "C" locale.
@@ -57,6 +54,23 @@
If a config file is explicitly specified with a module option then the
files in the above directory are not parsed.
</para>
+ <para condition="with_vendordir">
+ By default limits are taken from the <filename>/etc/security/limits.conf</filename>
+ config file or, if that one is not present, the file
+ <filename>%vendordir%/security/limits.conf</filename>.
+ Then individual <filename>*.conf</filename> files from the
+ <filename>/etc/security/limits.d/</filename> and
+ <filename>%vendordir%/security/limits.d</filename> directories are read.
+ If <filename>/etc/security/limits.d/@filename@.conf</filename> exists, then
+ <filename>%vendordir%/security/limits.d/@filename@.conf</filename> will not be used.
+ All <filename>limits.d/*.conf</filename> files are sorted by their
+ <filename>@filename@.conf</filename> in lexicographic order regardless of which
+ of the directories they reside in.
+ The effect of the individual files is the same as if all the files were
+ concatenated together in the order of parsing.
+ If a config file is explicitly specified with the <option>config</option>
+ option the files in the above directories are not parsed.
+ </para>
<para>
The module must not be called by a multithreaded application.
</para>
@@ -67,12 +81,12 @@
</para>
</refsect1>
- <refsect1 id="pam_limits-options">
+ <refsect1 xml:id="pam_limits-options">
<title>OPTIONS</title>
<variablelist>
<varlistentry>
<term>
- <option>conf=<replaceable>/path/to/limits.conf</replaceable></option>
+ conf=/path/to/limits.conf
</term>
<listitem>
<para>
@@ -83,7 +97,7 @@
</varlistentry>
<varlistentry>
<term>
- <option>debug</option>
+ debug
</term>
<listitem>
<para>
@@ -93,7 +107,7 @@
</varlistentry>
<varlistentry>
<term>
- <option>set_all</option>
+ set_all
</term>
<listitem>
<para>
@@ -107,7 +121,7 @@
</varlistentry>
<varlistentry>
<term>
- <option>utmp_early</option>
+ utmp_early
</term>
<listitem>
<para>
@@ -122,7 +136,7 @@
</varlistentry>
<varlistentry>
<term>
- <option>noaudit</option>
+ noaudit
</term>
<listitem>
<para>
@@ -133,14 +147,14 @@
</variablelist>
</refsect1>
- <refsect1 id="pam_limits-types">
+ <refsect1 xml:id="pam_limits-types">
<title>MODULE TYPES PROVIDED</title>
<para>
Only the <option>session</option> module type is provided.
</para>
</refsect1>
- <refsect1 id="pam_limits-return_values">
+ <refsect1 xml:id="pam_limits-return_values">
<title>RETURN VALUES</title>
<variablelist>
<varlistentry>
@@ -202,19 +216,26 @@
</variablelist>
</refsect1>
- <refsect1 id="pam_limits-files">
+ <refsect1 xml:id="pam_limits-files">
<title>FILES</title>
<variablelist>
<varlistentry>
- <term><filename>/etc/security/limits.conf</filename></term>
+ <term>/etc/security/limits.conf</term>
<listitem>
<para>Default configuration file</para>
</listitem>
</varlistentry>
+ <varlistentry condition="with_vendordir">
+ <term>%vendordir%/security/limits.conf</term>
+ <listitem>
+ <para>Default configuration file if
+ <filename>/etc/security/limits.conf</filename> does not exist.</para>
+ </listitem>
+ </varlistentry>
</variablelist>
</refsect1>
- <refsect1 id='pam_limits-examples'>
+ <refsect1 xml:id="pam_limits-examples">
<title>EXAMPLES</title>
<para>
For the services you need resources limits (login for example) put a
@@ -233,7 +254,7 @@ session required pam_limits.so
</para>
</refsect1>
- <refsect1 id="pam_limits-see_also">
+ <refsect1 xml:id="pam_limits-see_also">
<title>SEE ALSO</title>
<para>
<citerefentry>
@@ -243,15 +264,15 @@ session required pam_limits.so
<refentrytitle>pam.d</refentrytitle><manvolnum>5</manvolnum>
</citerefentry>,
<citerefentry>
- <refentrytitle>pam</refentrytitle><manvolnum>8</manvolnum>
+ <refentrytitle>pam</refentrytitle><manvolnum>7</manvolnum>
</citerefentry>.
</para>
</refsect1>
- <refsect1 id="pam_limits-authors">
+ <refsect1 xml:id="pam_limits-authors">
<title>AUTHORS</title>
<para>
pam_limits was initially written by Cristian Gafton &lt;gafton@redhat.com&gt;
</para>
</refsect1>
-</refentry>
+</refentry> \ No newline at end of file
diff --git a/modules/pam_limits/pam_limits.c b/modules/pam_limits/pam_limits.c
index b791cdce..da83b705 100644
--- a/modules/pam_limits/pam_limits.c
+++ b/modules/pam_limits/pam_limits.c
@@ -13,7 +13,7 @@
* See end for Copyright information
*/
-#if !defined(linux) && !defined(__linux)
+#ifndef __linux__
#warning THIS CODE IS KNOWN TO WORK ONLY ON LINUX !!!
#endif
@@ -28,6 +28,7 @@
#include <syslog.h>
#include <stdarg.h>
#include <signal.h>
+#include <sys/prctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/resource.h>
@@ -46,10 +47,23 @@
#include <libaudit.h>
#endif
+
+#ifndef PR_SET_NO_NEW_PRIVS
+# define PR_SET_NO_NEW_PRIVS 38 /* from <linux/prctl.h> */
+#endif
+
+#ifndef MLOCK_LIMIT
+#ifdef __FreeBSD_kernel__
+#define MLOCK_LIMIT RLIM_INFINITY
+#else
+#define MLOCK_LIMIT (64*1024)
+#endif
+#endif
+
/* Module defines */
#define LINE_LENGTH 1024
-#define LIMITS_DEF_USER 0 /* limit was set by an user entry */
+#define LIMITS_DEF_USER 0 /* limit was set by a user entry */
#define LIMITS_DEF_GROUP 1 /* limit was set by a group entry */
#define LIMITS_DEF_ALLGROUP 2 /* limit was set by a group entry */
#define LIMITS_DEF_ALL 3 /* limit was set by an all entry */
@@ -83,11 +97,14 @@ struct user_limits_struct {
/* internal data */
struct pam_limit_s {
+ int root; /* running as root? */
int login_limit; /* the max logins limit */
int login_limit_def; /* which entry set the login limit */
int flag_numsyslogins; /* whether to limit logins only for a
specific user or to count all logins */
int priority; /* the priority to run user process with */
+ int nonewprivs; /* whether to prctl(PR_SET_NO_NEW_PRIVS) */
+ char chroot_dir[8092]; /* directory to chroot into */
struct user_limits_struct limits[RLIM_NLIMITS];
const char *conf_file;
int utmp_after_pam_call;
@@ -98,6 +115,8 @@ struct pam_limit_s {
#define LIMIT_NUMSYSLOGINS RLIM_NLIMITS+2
#define LIMIT_PRI RLIM_NLIMITS+3
+#define LIMIT_NONEWPRIVS RLIM_NLIMITS+4
+#define LIMIT_CHROOT RLIM_NLIMITS+5
#define LIMIT_SOFT 1
#define LIMIT_HARD 2
@@ -116,9 +135,14 @@ struct pam_limit_s {
#define PAM_SET_ALL 0x0010
/* Limits from globbed files. */
-#define LIMITS_CONF_GLOB LIMITS_FILE_DIR
+#define LIMITS_CONF_GLOB (LIMITS_FILE_DIR "/*.conf")
-#define CONF_FILE (pl->conf_file != NULL)?pl->conf_file:LIMITS_FILE
+#define LIMITS_FILE (SCONFIGDIR "/limits.conf")
+
+#ifdef VENDOR_SCONFIGDIR
+#define VENDOR_LIMITS_FILE (VENDOR_SCONFIGDIR "/limits.conf")
+#define VENDOR_LIMITS_CONF_GLOB (VENDOR_SCONFIGDIR "/limits.d/*.conf")
+#endif
static int
_pam_parse (const pam_handle_t *pamh, int argc, const char **argv,
@@ -271,8 +295,8 @@ check_logins (pam_handle_t *pamh, const char *name, int limit, int ctrl,
}
if (!pl->flag_numsyslogins) {
char user[sizeof(ut->UT_USER) + 1];
- user[0] = '\0';
- strncat(user, ut->UT_USER, sizeof(ut->UT_USER));
+ memcpy(user, ut->UT_USER, sizeof(ut->UT_USER));
+ user[sizeof(ut->UT_USER)] = '\0';
if (((pl->login_limit_def == LIMITS_DEF_USER)
|| (pl->login_limit_def == LIMITS_DEF_GROUP)
@@ -437,15 +461,32 @@ static void parse_kernel_limits(pam_handle_t *pamh, struct pam_limit_s *pl, int
pl->limits[i].src_hard = LIMITS_DEF_KERNEL;
}
fclose(limitsfile);
+
+ /* Cap the default soft nofile limit read from pid 1 to FD_SETSIZE
+ * since larger values can cause problems with fd_set overflow and
+ * systemd sets itself higher. */
+ if (pl->limits[RLIMIT_NOFILE].src_soft == LIMITS_DEF_KERNEL &&
+ pl->limits[RLIMIT_NOFILE].limit.rlim_cur > FD_SETSIZE) {
+ pl->limits[RLIMIT_NOFILE].limit.rlim_cur = FD_SETSIZE;
+ }
}
static int init_limits(pam_handle_t *pamh, struct pam_limit_s *pl, int ctrl)
{
int i;
int retval = PAM_SUCCESS;
+ static int mlock_limit = 0;
D(("called."));
+ pl->root = 0;
+
+ if (mlock_limit == 0) {
+ mlock_limit = sysconf(_SC_PAGESIZE);
+ if (mlock_limit < MLOCK_LIMIT)
+ mlock_limit = MLOCK_LIMIT;
+ }
+
for(i = 0; i < RLIM_NLIMITS; i++) {
int r = getrlimit(i, &pl->limits[i].limit);
if (r == -1) {
@@ -461,18 +502,68 @@ static int init_limits(pam_handle_t *pamh, struct pam_limit_s *pl, int ctrl)
}
#ifdef __linux__
- if (ctrl & PAM_SET_ALL) {
- parse_kernel_limits(pamh, pl, ctrl);
+ parse_kernel_limits(pamh, pl, ctrl);
+#endif
- for(i = 0; i < RLIM_NLIMITS; i++) {
+ for(i = 0; i < RLIM_NLIMITS; i++) {
if (pl->limits[i].supported &&
(pl->limits[i].src_soft == LIMITS_DEF_NONE ||
pl->limits[i].src_hard == LIMITS_DEF_NONE)) {
- pam_syslog(pamh, LOG_WARNING, "Did not find kernel RLIMIT for %s, using PAM default", rlimit2str(i));
+#ifdef __linux__
+ pam_syslog(pamh, LOG_WARNING, "Did not find kernel RLIMIT for %s, using PAM default", rlimit2str(i));
+#endif
+ pl->limits[i].src_soft = LIMITS_DEF_DEFAULT;
+ pl->limits[i].src_hard = LIMITS_DEF_DEFAULT;
+ switch(i) {
+ case RLIMIT_CPU:
+ case RLIMIT_FSIZE:
+ case RLIMIT_DATA:
+ case RLIMIT_RSS:
+ case RLIMIT_NPROC:
+#ifdef RLIMIT_AS
+ case RLIMIT_AS:
+#endif
+#ifdef RLIMIT_LOCKS
+ case RLIMIT_LOCKS:
+#endif
+ pl->limits[i].limit.rlim_cur = RLIM_INFINITY;
+ pl->limits[i].limit.rlim_max = RLIM_INFINITY;
+ break;
+ case RLIMIT_MEMLOCK:
+ pl->limits[i].limit.rlim_cur = mlock_limit;
+ pl->limits[i].limit.rlim_max = mlock_limit;
+ break;
+#ifdef RLIMIT_SIGPENDING
+ case RLIMIT_SIGPENDING:
+ pl->limits[i].limit.rlim_cur = 16382;
+ pl->limits[i].limit.rlim_max = 16382;
+ break;
+#endif
+#ifdef RLIMIT_MSGQUEUE
+ case RLIMIT_MSGQUEUE:
+ pl->limits[i].limit.rlim_cur = 819200;
+ pl->limits[i].limit.rlim_max = 819200;
+ break;
+#endif
+ case RLIMIT_CORE:
+ pl->limits[i].limit.rlim_cur = 0;
+ pl->limits[i].limit.rlim_max = RLIM_INFINITY;
+ break;
+ case RLIMIT_STACK:
+ pl->limits[i].limit.rlim_cur = 8192*1024;
+ pl->limits[i].limit.rlim_max = RLIM_INFINITY;
+ break;
+ case RLIMIT_NOFILE:
+ pl->limits[i].limit.rlim_cur = 1024;
+ pl->limits[i].limit.rlim_max = 1024;
+ break;
+ default:
+ pl->limits[i].src_soft = LIMITS_DEF_NONE;
+ pl->limits[i].src_hard = LIMITS_DEF_NONE;
+ break;
+ }
}
- }
}
-#endif
errno = 0;
pl->priority = getpriority (PRIO_PROCESS, 0);
@@ -481,6 +572,43 @@ static int init_limits(pam_handle_t *pamh, struct pam_limit_s *pl, int ctrl)
pl->login_limit = -2;
pl->login_limit_def = LIMITS_DEF_NONE;
+ pl->chroot_dir[0] = '\0';
+
+ return retval;
+}
+
+/*
+ * Read the contents of <pathname> and return it in *valuep
+ * return 1 if conversion succeeds, result is in *valuep
+ * return 0 if conversion fails, *valuep is untouched.
+ */
+static int
+value_from_file(const char *pathname, rlim_t *valuep)
+{
+ char buf[128];
+ FILE *fp;
+ int retval;
+
+ retval = 0;
+
+ if ((fp = fopen(pathname, "r")) != NULL) {
+ if (fgets(buf, sizeof(buf), fp) != NULL) {
+ char *endptr;
+ unsigned long long value;
+
+ errno = 0;
+ value = strtoull(buf, &endptr, 10);
+ if (endptr != buf &&
+ (value != ULLONG_MAX || errno == 0) &&
+ (unsigned long long) (rlim_t) value == value) {
+ *valuep = (rlim_t) value;
+ retval = 1;
+ }
+ }
+
+ fclose(fp);
+ }
+
return retval;
}
@@ -551,6 +679,10 @@ process_limit (const pam_handle_t *pamh, int source, const char *lim_type,
pl->flag_numsyslogins = 1;
} else if (strcmp(lim_item, "priority") == 0) {
limit_item = LIMIT_PRI;
+ } else if (strcmp(lim_item, "nonewprivs") == 0) {
+ limit_item = LIMIT_NONEWPRIVS;
+ } else if (strcmp(lim_item, "chroot") == 0) {
+ limit_item = LIMIT_CHROOT;
} else {
pam_syslog(pamh, LOG_DEBUG, "unknown limit item '%s'", lim_item);
return;
@@ -562,11 +694,23 @@ process_limit (const pam_handle_t *pamh, int source, const char *lim_type,
limit_type=LIMIT_HARD;
else if (strcmp(lim_type,"-")==0)
limit_type=LIMIT_SOFT | LIMIT_HARD;
- else if (limit_item != LIMIT_LOGIN && limit_item != LIMIT_NUMSYSLOGINS) {
+ 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;
}
- if (limit_item != LIMIT_PRI
+ if (limit_item == LIMIT_NONEWPRIVS) {
+ /* just require a bool-style 0 or 1 */
+ if (strcmp(lim_value, "0") == 0) {
+ int_value = 0;
+ } else if (strcmp(lim_value, "1") == 0) {
+ int_value = 1;
+ } else {
+ pam_syslog(pamh, LOG_DEBUG,
+ "wrong limit value '%s' for limit type '%s'",
+ lim_value, lim_type);
+ }
+ } else if (limit_item != LIMIT_PRI
#ifdef RLIMIT_NICE
&& limit_item != RLIMIT_NICE
#endif
@@ -588,9 +732,9 @@ process_limit (const pam_handle_t *pamh, int source, const char *lim_type,
pam_syslog(pamh, LOG_DEBUG,
"wrong limit value '%s' for limit type '%s'",
lim_value, lim_type);
- return;
+ return;
}
- } else {
+ } else if (limit_item != LIMIT_CHROOT) {
#ifdef __USE_FILE_OFFSET64
rlimit_value = strtoull (lim_value, &endptr, 10);
#else
@@ -649,11 +793,30 @@ process_limit (const pam_handle_t *pamh, int source, const char *lim_type,
rlimit_value = 20 - int_value;
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_file("/proc/sys/fs/nr_open", &rlimit_value))
+ pam_syslog(pamh, LOG_WARNING,
+ "Cannot set \"nofile\" to a sensible value");
+ else if (ctrl & PAM_DEBUG_ARG)
+ pam_syslog(pamh, LOG_DEBUG, "Setting \"nofile\" limit to %llu",
+ (unsigned long long) rlimit_value);
+ }
+ break;
}
- if ( (limit_item != LIMIT_LOGIN)
+ if (limit_item == LIMIT_CHROOT) {
+ strncpy(pl->chroot_dir, value_orig, sizeof(pl->chroot_dir)-1);
+ pl->chroot_dir[sizeof(pl->chroot_dir)-1]='\0';
+ }
+ else if ( (limit_item != LIMIT_LOGIN)
&& (limit_item != LIMIT_NUMSYSLOGINS)
- && (limit_item != LIMIT_PRI) ) {
+ && (limit_item != LIMIT_PRI)
+ && (limit_item != LIMIT_NONEWPRIVS) ) {
if (limit_type & LIMIT_SOFT) {
if (pl->limits[limit_item].src_soft < source) {
return;
@@ -674,14 +837,16 @@ process_limit (const pam_handle_t *pamh, int source, const char *lim_type,
/* recent kernels support negative priority limits (=raise priority) */
if (limit_item == LIMIT_PRI) {
- pl->priority = int_value;
+ pl->priority = int_value;
+ } else if (limit_item == LIMIT_NONEWPRIVS) {
+ pl->nonewprivs = int_value;
} else {
- if (pl->login_limit_def < source) {
- return;
- } else {
- pl->login_limit = int_value;
- pl->login_limit_def = source;
- }
+ if (pl->login_limit_def < source) {
+ return;
+ } else {
+ pl->login_limit = int_value;
+ pl->login_limit_def = source;
+ }
}
}
return;
@@ -737,18 +902,22 @@ parse_uid_range(pam_handle_t *pamh, const char *domain,
static int
parse_config_file(pam_handle_t *pamh, const char *uname, uid_t uid, gid_t gid,
- int ctrl, struct pam_limit_s *pl)
+ int ctrl, struct pam_limit_s *pl, const int conf_file_set_by_user)
{
FILE *fil;
char buf[LINE_LENGTH];
- /* check for the LIMITS_FILE */
+ /* check for the conf_file */
if (ctrl & PAM_DEBUG_ARG)
- pam_syslog(pamh, LOG_DEBUG, "reading settings from '%s'", CONF_FILE);
- fil = fopen(CONF_FILE, "r");
+ pam_syslog(pamh, LOG_DEBUG, "reading settings from '%s'", pl->conf_file);
+ fil = fopen(pl->conf_file, "r");
if (fil == NULL) {
- pam_syslog (pamh, LOG_WARNING,
- "cannot read settings from %s: %m", CONF_FILE);
+ if (errno == ENOENT && !conf_file_set_by_user)
+ return PAM_SUCCESS; /* file is not there and it has not been set by the conf= argument */
+
+ pam_syslog(pamh, LOG_WARNING,
+ "cannot read settings from %s: %s", pl->conf_file,
+ strerror(errno));
return PAM_SERVICE_ERR;
}
@@ -803,7 +972,7 @@ parse_config_file(pam_handle_t *pamh, const char *uname, uid_t uid, gid_t gid,
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]=='@') {
+ else if (domain[0]=='@' && !pl->root) {
if (ctrl & PAM_DEBUG_ARG) {
pam_syslog(pamh, LOG_DEBUG,
"checking if %s is in group %s",
@@ -829,7 +998,7 @@ parse_config_file(pam_handle_t *pamh, const char *uname, uid_t uid, gid_t gid,
process_limit(pamh, LIMITS_DEF_GROUP, ltype, item, value, ctrl,
pl);
}
- } else if (domain[0]=='%') {
+ } else if (domain[0]=='%' && !pl->root) {
if (ctrl & PAM_DEBUG_ARG) {
pam_syslog(pamh, LOG_DEBUG,
"checking if %s is in group %s",
@@ -863,7 +1032,7 @@ parse_config_file(pam_handle_t *pamh, const char *uname, uid_t uid, gid_t gid,
} else {
switch(rngtype) {
case LIMIT_RANGE_NONE:
- if (strcmp(domain, "*") == 0)
+ if (strcmp(domain, "*") == 0 && !pl->root)
process_limit(pamh, LIMITS_DEF_DEFAULT, ltype, item, value, ctrl,
pl);
break;
@@ -962,9 +1131,21 @@ static int setup_limits(pam_handle_t *pamh,
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",
- rlimit2str(i));
+ if (res != 0 && (i != RLIMIT_NOFILE
+ || pl->limits[i].limit.rlim_cur != RLIM_INFINITY))
+ {
+ int save_errno = errno;
+ pam_syslog(pamh, LOG_DEBUG,
+ "Could not set limit for '%s' to soft=%d, hard=%d:"
+ " %m; uid=%lu,euid=%lu", rlimit2str(i),
+ pl->limits[i].limit.rlim_cur,
+ pl->limits[i].limit.rlim_max,
+ (unsigned long) getuid(),
+ (unsigned long) geteuid());
+ errno = save_errno;
+ }
+ if (res == -1 && errno == EPERM)
+ continue;
status |= res;
}
@@ -995,36 +1176,151 @@ static int setup_limits(pam_handle_t *pamh,
retval |= LOGIN_ERR;
}
+ if (pl->nonewprivs) {
+ if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
+ pam_syslog(pamh, LOG_ERR, "Could not set prctl(PR_SET_NO_NEW_PRIVS): %m");
+ retval |= LIMIT_ERR;
+ }
+ }
+
+ if (!retval && pl->chroot_dir[0]) {
+ i = chdir(pl->chroot_dir);
+ if (i == 0)
+ i = chroot(pl->chroot_dir);
+ if (i == 0)
+ i = chdir("/");
+ if (i != 0)
+ retval = LIMIT_ERR;
+ }
return retval;
}
+/* --- evaluting all files in VENDORDIR/security/limits.d and /etc/security/limits.d --- */
+static const char *
+base_name(const char *path)
+{
+ const char *base = strrchr(path, '/');
+ return base ? base+1 : path;
+}
+
+static int
+compare_filename(const void *a, const void *b)
+{
+ return strcmp(base_name(* (const char * const *) a),
+ base_name(* (const char * const *) b));
+}
+
+/* Evaluating a list of files which have to be parsed in the right order:
+ *
+ * - If etc/security/limits.d/@filename@.conf exists, then
+ * %vendordir%/security/limits.d/@filename@.conf should not be used.
+ * - All files in both limits.d directories are sorted by their @filename@.conf in
+ * lexicographic order regardless of which of the directories they reside in. */
+static char **
+read_limits_dir(pam_handle_t *pamh)
+{
+ glob_t globbuf;
+ size_t i=0;
+ int glob_rv = glob(LIMITS_CONF_GLOB, GLOB_ERR | GLOB_NOSORT, NULL, &globbuf);
+ char **file_list;
+ size_t file_list_size = glob_rv == 0 ? globbuf.gl_pathc : 0;
+
+#ifdef VENDOR_LIMITS_CONF_GLOB
+ glob_t globbuf_vendor;
+ int glob_rv_vendor = glob(VENDOR_LIMITS_CONF_GLOB, GLOB_ERR | GLOB_NOSORT, NULL, &globbuf_vendor);
+ if (glob_rv_vendor == 0)
+ file_list_size += globbuf_vendor.gl_pathc;
+#endif
+ file_list = malloc((file_list_size + 1) * sizeof(char*));
+ if (file_list == NULL) {
+ pam_syslog(pamh, LOG_ERR, "Cannot allocate memory for file list: %m");
+#ifdef VENDOR_ACCESS_CONF_GLOB
+ if (glob_rv_vendor == 0)
+ globfree(&globbuf_vendor);
+#endif
+ if (glob_rv == 0)
+ globfree(&globbuf);
+ return NULL;
+ }
+
+ if (glob_rv == 0) {
+ for (i = 0; i < globbuf.gl_pathc; i++) {
+ file_list[i] = strdup(globbuf.gl_pathv[i]);
+ if (file_list[i] == NULL) {
+ pam_syslog(pamh, LOG_ERR, "strdup failed: %m");
+ break;
+ }
+ }
+ }
+#ifdef VENDOR_LIMITS_CONF_GLOB
+ if (glob_rv_vendor == 0) {
+ for (size_t j = 0; j < globbuf_vendor.gl_pathc; j++) {
+ if (glob_rv == 0 && globbuf.gl_pathc > 0) {
+ int double_found = 0;
+ for (size_t k = 0; k < globbuf.gl_pathc; k++) {
+ if (strcmp(base_name(globbuf.gl_pathv[k]),
+ base_name(globbuf_vendor.gl_pathv[j])) == 0) {
+ double_found = 1;
+ break;
+ }
+ }
+ if (double_found)
+ continue;
+ }
+ file_list[i] = strdup(globbuf_vendor.gl_pathv[j]);
+ if (file_list[i] == NULL) {
+ pam_syslog(pamh, LOG_ERR, "strdup failed: %m");
+ break;
+ }
+ i++;
+ }
+ globfree(&globbuf_vendor);
+ }
+#endif
+ file_list[i] = NULL;
+ qsort(file_list, i, sizeof(char *), compare_filename);
+ if (glob_rv == 0)
+ globfree(&globbuf);
+
+ return file_list;
+}
+
/* now the session stuff */
int
pam_sm_open_session (pam_handle_t *pamh, int flags UNUSED,
int argc, const char **argv)
{
- int retval;
- int i;
- int glob_rc;
+ int retval, i;
char *user_name;
struct passwd *pwd;
int ctrl;
struct pam_limit_s plstruct;
struct pam_limit_s *pl = &plstruct;
- glob_t globbuf;
- const char *oldlocale;
D(("called."));
memset(pl, 0, sizeof(*pl));
- memset(&globbuf, 0, sizeof(globbuf));
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;
- }
+ }
+
+ int conf_file_set_by_user = (pl->conf_file != NULL);
+ if (pl->conf_file == NULL) {
+ pl->conf_file = LIMITS_FILE;
+#ifdef VENDOR_LIMITS_FILE
+ /*
+ * Check whether LIMITS_FILE file is available.
+ * If it does not exist, fall back to VENDOR_LIMITS_FILE file.
+ */
+ struct stat buffer;
+ if (stat(pl->conf_file, &buffer) != 0 && errno == ENOENT)
+ pl->conf_file = VENDOR_LIMITS_FILE;
+#endif
+ }
pwd = pam_modutil_getpwnam(pamh, user_name);
if (!pwd) {
@@ -1040,46 +1336,41 @@ pam_sm_open_session (pam_handle_t *pamh, int flags UNUSED,
return PAM_ABORT;
}
- retval = parse_config_file(pamh, pwd->pw_name, pwd->pw_uid, pwd->pw_gid, ctrl, pl);
+ if (pwd->pw_uid == 0)
+ pl->root = 1;
+ retval = parse_config_file(pamh, pwd->pw_name, pwd->pw_uid, pwd->pw_gid,
+ ctrl, pl, conf_file_set_by_user);
if (retval == PAM_IGNORE) {
- D(("the configuration file ('%s') has an applicable '<domain> -' entry", CONF_FILE));
+ D(("the configuration file ('%s') has an applicable '<domain> -' entry", pl->conf_file));
return PAM_SUCCESS;
}
- if (retval != PAM_SUCCESS || pl->conf_file != NULL)
+ if (retval != PAM_SUCCESS || conf_file_set_by_user)
/* skip reading limits.d if config file explicitly specified */
goto out;
/* Read subsequent *.conf files, if they exist. */
-
- /* set the LC_COLLATE so the sorting order doesn't depend
- on system locale */
-
- oldlocale = setlocale(LC_COLLATE, "C");
- glob_rc = glob(LIMITS_CONF_GLOB, GLOB_ERR, NULL, &globbuf);
-
- if (oldlocale != NULL)
- setlocale (LC_COLLATE, oldlocale);
-
- if (!glob_rc) {
- /* Parse the *.conf files. */
- for (i = 0; globbuf.gl_pathv[i] != NULL; i++) {
- pl->conf_file = globbuf.gl_pathv[i];
- retval = parse_config_file(pamh, pwd->pw_name, pwd->pw_uid, pwd->pw_gid, ctrl, pl);
- if (retval == PAM_IGNORE) {
- D(("the configuration file ('%s') has an applicable '<domain> -' entry", pl->conf_file));
- globfree(&globbuf);
- return PAM_SUCCESS;
- }
- if (retval != PAM_SUCCESS)
- goto out;
+ char **filename_list = read_limits_dir(pamh);
+ if (filename_list != NULL) {
+ for (i = 0; filename_list[i] != NULL; i++) {
+ pl->conf_file = filename_list[i];
+ retval = parse_config_file(pamh, pwd->pw_name, pwd->pw_uid, pwd->pw_gid, ctrl, pl, 0);
+ if (retval != PAM_SUCCESS)
+ break;
}
+ for (i = 0; filename_list[i] != NULL; i++)
+ free(filename_list[i]);
+ free(filename_list);
+ }
+
+ if (retval == PAM_IGNORE) {
+ D(("the configuration file ('%s') has an applicable '<domain> -' entry", pl->conf_file));
+ return PAM_SUCCESS;
}
out:
- globfree(&globbuf);
if (retval != PAM_SUCCESS)
{
- pam_syslog(pamh, LOG_ERR, "error parsing the configuration file: '%s' ",CONF_FILE);
+ pam_syslog(pamh, LOG_ERR, "error parsing the configuration file: '%s' ", pl->conf_file);
return retval;
}