From a0443a87f5f49ea994e5e9ffd005e866ab67ae19 Mon Sep 17 00:00:00 2001
From: Stephen Gallagher <sgallagh@redhat.com>
Date: Fri, 17 Feb 2012 12:14:39 -0500
Subject: [PATCH 2/2] RESPONDERS: Make the fd_limit setting configurable

This code will now attempt first to see if it has privilege to set
the value as specified, and if not it will fall back to the
previous behavior. So on systems with the CAP_SYS_RESOURCE
capability granted to SSSD, it will be able to ignore the
limits.conf hard limit.

https://fedorahosted.org/sssd/ticket/1197
---
 src/config/SSSDConfig.py                |    1 +
 src/config/SSSDConfigTest.py            |    3 ++-
 src/config/etc/sssd.api.conf            |    1 +
 src/man/sssd.conf.5.xml                 |   17 +++++++++++++++++
 src/responder/common/responder_common.c |   19 ++++++++++++++++++-
 src/responder/nss/nsssrv.c              |   13 ++++++++++++-
 src/responder/pam/pamsrv.c              |   13 ++++++++++++-
 7 files changed, 63 insertions(+), 4 deletions(-)

diff --git a/src/config/SSSDConfig.py b/src/config/SSSDConfig.py
index a545800b85dc89497b1b4a299e0511ac804684d9..0ff5a6c05e2a606d067e3d105c98e7859ee1cd83 100644
--- a/src/config/SSSDConfig.py
+++ b/src/config/SSSDConfig.py
@@ -43,6 +43,7 @@ option_strings = {
     'timeout' : _('Ping timeout before restarting service'),
     'command' : _('Command to start service'),
     'reconnection_retries' : _('Number of times to attempt connection to Data Providers'),
+    'fd_limit' : _('The number of file descriptors that may be opened by this responder'),
 
     # [sssd]
     'services' : _('SSSD Services to start'),
diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py
index a64a73616cea8181e7f82a2ba55314c3444a4858..7e024caa05dc7164402bec63d4f08a7ee69aa634 100755
--- a/src/config/SSSDConfigTest.py
+++ b/src/config/SSSDConfigTest.py
@@ -272,7 +272,8 @@ class SSSDConfigTestSSSDService(unittest.TestCase):
             'debug_microseconds',
             'debug_to_files',
             'command',
-            'reconnection_retries']
+            'reconnection_retries',
+            'fd_limit']
 
         self.assertTrue(type(options) == dict,
                         "Options should be a dictionary")
diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf
index 93434635051204cbcaf5f9ab759e5fa3eb8e1860..155b8efefafaa627b5dae1e9d0e1b0da3904338e 100644
--- a/src/config/etc/sssd.api.conf
+++ b/src/config/etc/sssd.api.conf
@@ -9,6 +9,7 @@ debug_microseconds = bool, None, false
 debug_to_files = bool, None, false
 command = str, None, false
 reconnection_retries = int, None, false
+fd_limit = int, None, false
 
 [sssd]
 # Monitor service
diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
index abebf8473e2ac7bf787ee5eac4b184bded2b77c9..63e396a545f04b28b1bfb0ccc69b454aa83686e9 100644
--- a/src/man/sssd.conf.5.xml
+++ b/src/man/sssd.conf.5.xml
@@ -267,6 +267,23 @@
                     </listitem>
                 </varlistentry>
                 <varlistentry>
+                    <term>fd_limit</term>
+                    <listitem>
+                        <para>
+                            This option specifies the maximum number of file
+                            descriptors that may be opened at one time by this
+                            SSSD process. On systems where SSSD is granted the
+                            CAP_SYS_RESOURCE capability, this will be an
+                            absolute setting. On systems without this
+                            capability, the resulting value will be the lower
+                            value of this or the limits.conf "hard" limit.
+                        </para>
+                        <para>
+                            Default: 8192 (or limits.conf "hard" limit)
+                        </para>
+                    </listitem>
+                </varlistentry>
+                <varlistentry>
                     <term>command (string)</term>
                     <listitem>
                         <para>
diff --git a/src/responder/common/responder_common.c b/src/responder/common/responder_common.c
index 94a9fdb63078903260f3896feba37d32129e2814..a9b5d56b0676a405637bc2e06be4c7ee6938d71e 100644
--- a/src/responder/common/responder_common.c
+++ b/src/responder/common/responder_common.c
@@ -654,7 +654,24 @@ void responder_set_fd_limit(rlim_t fd_limit)
     struct rlimit current_limit, new_limit;
     int limret;
 
-    /* First determine the maximum hard limit */
+    /* First, let's see if we have permission to just set
+     * the value as-is.
+     */
+    new_limit.rlim_cur = fd_limit;
+    new_limit.rlim_max = fd_limit;
+    limret = setrlimit(RLIMIT_NOFILE, &new_limit);
+    if (limret == 0) {
+        DEBUG(SSSDBG_CONF_SETTINGS,
+              ("Maximum file descriptors set to [%d]\n",
+               new_limit.rlim_cur));
+        return;
+    }
+
+    /* We couldn't set the soft and hard limits to this
+     * value. Let's see how high we CAN set it.
+     */
+
+    /* Determine the maximum hard limit */
     limret = getrlimit(RLIMIT_NOFILE, &current_limit);
     if (limret == 0) {
         DEBUG(SSSDBG_TRACE_INTERNAL,
diff --git a/src/responder/nss/nsssrv.c b/src/responder/nss/nsssrv.c
index 3c23f1bf9c8d86f772f76dc120b5aed456fb316d..ef66b22fbf20cb1b7e4bedd0193fd4803abd2ebf 100644
--- a/src/responder/nss/nsssrv.c
+++ b/src/responder/nss/nsssrv.c
@@ -251,6 +251,7 @@ int nss_process_init(TALLOC_CTX *mem_ctx,
     struct nss_ctx *nctx;
     int ret, max_retries;
     int hret;
+    int fd_limit;
 
     nctx = talloc_zero(mem_ctx, struct nss_ctx);
     if (!nctx) {
@@ -309,7 +310,17 @@ int nss_process_init(TALLOC_CTX *mem_ctx,
     }
 
     /* Set up file descriptor limits */
-    responder_set_fd_limit(DEFAULT_NSS_FD_LIMIT);
+    ret = confdb_get_int(nctx->rctx->cdb, nctx->rctx,
+                         CONFDB_NSS_CONF_ENTRY,
+                         CONFDB_SERVICE_FD_LIMIT,
+                         DEFAULT_NSS_FD_LIMIT,
+                         &fd_limit);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_FATAL_FAILURE,
+              ("Failed to set up file descriptor limit\n"));
+        return ret;
+    }
+    responder_set_fd_limit(fd_limit);
 
     DEBUG(1, ("NSS Initialization complete\n"));
 
diff --git a/src/responder/pam/pamsrv.c b/src/responder/pam/pamsrv.c
index 2786fe4e0616d3a914e6639dc94e29b3f02a2025..6cb564a7a2793de2cf76f2aef8c83ef3dfdec75d 100644
--- a/src/responder/pam/pamsrv.c
+++ b/src/responder/pam/pamsrv.c
@@ -111,6 +111,7 @@ static int pam_process_init(TALLOC_CTX *mem_ctx,
     struct pam_ctx *pctx;
     int ret, max_retries;
     int id_timeout;
+    int fd_limit;
 
     pctx = talloc_zero(mem_ctx, struct pam_ctx);
     if (!pctx) {
@@ -186,7 +187,17 @@ static int pam_process_init(TALLOC_CTX *mem_ctx,
     }
 
     /* Set up file descriptor limits */
-    responder_set_fd_limit(DEFAULT_PAM_FD_LIMIT);
+    ret = confdb_get_int(pctx->rctx->cdb, pctx->rctx,
+                         CONFDB_PAM_CONF_ENTRY,
+                         CONFDB_SERVICE_FD_LIMIT,
+                         DEFAULT_PAM_FD_LIMIT,
+                         &fd_limit);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_FATAL_FAILURE,
+              ("Failed to set up file descriptor limit\n"));
+        return ret;
+    }
+    responder_set_fd_limit(fd_limit);
 
     ret = EOK;
 
-- 
1.7.7.6

