0201d8
From 637807410ae730436f9ca647092250ead70faa1c Mon Sep 17 00:00:00 2001
0201d8
From: Sumit Bose <sbose@redhat.com>
0201d8
Date: Mon, 2 Mar 2015 10:59:34 +0100
0201d8
Subject: [PATCH] extdom: make nss buffer configurable
0201d8
0201d8
The get*_r_wrapper() calls expect a maximum buffer size to avoid memory
0201d8
shortage if too many threads try to allocate buffers e.g. for large
0201d8
groups. With this patch this size can be configured by setting
0201d8
ipaExtdomMaxNssBufSize in the plugin config object
0201d8
cn=ipa_extdom_extop,cn=plugins,cn=config.
0201d8
0201d8
Related to https://fedorahosted.org/freeipa/ticket/4908
0201d8
0201d8
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
0201d8
---
0201d8
 .../ipa-extdom-extop/ipa_extdom.h                  |  1 +
0201d8
 .../ipa-extdom-extop/ipa_extdom_common.c           | 59 ++++++++++++++--------
0201d8
 .../ipa-extdom-extop/ipa_extdom_extop.c            | 10 ++++
0201d8
 3 files changed, 48 insertions(+), 22 deletions(-)
0201d8
0201d8
diff --git a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom.h b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom.h
0201d8
index 40bf933920fdd2ca19e5ef195aaa8fb820446cc5..d4c851169ddadc869a59c53075f9fc7f33321085 100644
0201d8
--- a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom.h
0201d8
+++ b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom.h
0201d8
@@ -150,6 +150,7 @@ struct extdom_res {
0201d8
 struct ipa_extdom_ctx {
0201d8
     Slapi_ComponentId *plugin_id;
0201d8
     char *base_dn;
0201d8
+    size_t max_nss_buf_size;
0201d8
 };
0201d8
 
0201d8
 struct domain_info {
0201d8
diff --git a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_common.c b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_common.c
0201d8
index cbe336963ffbafadd5a7b8029a65fafe506f75e8..47bcb179f04e08c64d92f55809b84f2d59622344 100644
0201d8
--- a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_common.c
0201d8
+++ b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_common.c
0201d8
@@ -49,9 +49,6 @@
0201d8
 
0201d8
 #define MAX(a,b) (((a)>(b))?(a):(b))
0201d8
 #define SSSD_DOMAIN_SEPARATOR '@'
0201d8
-#define MAX_BUF (1024*1024*1024)
0201d8
-
0201d8
-
0201d8
 
0201d8
 int get_buffer(size_t *_buf_len, char **_buf)
0201d8
 {
0201d8
@@ -464,7 +461,8 @@ static int pack_ber_sid(const char *sid, struct berval **berval)
0201d8
 
0201d8
 #define SSSD_SYSDB_SID_STR "objectSIDString"
0201d8
 
0201d8
-static int pack_ber_user(enum response_types response_type,
0201d8
+static int pack_ber_user(struct ipa_extdom_ctx *ctx,
0201d8
+                         enum response_types response_type,
0201d8
                          const char *domain_name, const char *user_name,
0201d8
                          uid_t uid, gid_t gid,
0201d8
                          const char *gecos, const char *homedir,
0201d8
@@ -529,7 +527,8 @@ static int pack_ber_user(enum response_types response_type,
0201d8
         }
0201d8
 
0201d8
         for (c = 0; c < ngroups; c++) {
0201d8
-            ret = getgrgid_r_wrapper(MAX_BUF, groups[c], &grp, &buf, &buf_len);
0201d8
+            ret = getgrgid_r_wrapper(ctx->max_nss_buf_size,
0201d8
+                                     groups[c], &grp, &buf, &buf_len);
0201d8
             if (ret != 0) {
0201d8
                 if (ret == ENOMEM || ret == ERANGE) {
0201d8
                     ret = LDAP_OPERATIONS_ERROR;
0201d8
@@ -691,7 +690,8 @@ static int pack_ber_name(const char *domain_name, const char *name,
0201d8
     return LDAP_SUCCESS;
0201d8
 }
0201d8
 
0201d8
-static int handle_uid_request(enum request_types request_type, uid_t uid,
0201d8
+static int handle_uid_request(struct ipa_extdom_ctx *ctx,
0201d8
+                              enum request_types request_type, uid_t uid,
0201d8
                               const char *domain_name, struct berval **berval)
0201d8
 {
0201d8
     int ret;
0201d8
@@ -721,7 +721,8 @@ static int handle_uid_request(enum request_types request_type, uid_t uid,
0201d8
 
0201d8
         ret = pack_ber_sid(sid_str, berval);
0201d8
     } else {
0201d8
-        ret = getpwuid_r_wrapper(MAX_BUF, uid, &pwd, &buf, &buf_len);
0201d8
+        ret = getpwuid_r_wrapper(ctx->max_nss_buf_size, uid, &pwd, &buf,
0201d8
+                                 &buf_len);
0201d8
         if (ret != 0) {
0201d8
             if (ret == ENOMEM || ret == ERANGE) {
0201d8
                 ret = LDAP_OPERATIONS_ERROR;
0201d8
@@ -744,7 +745,8 @@ static int handle_uid_request(enum request_types request_type, uid_t uid,
0201d8
             }
0201d8
         }
0201d8
 
0201d8
-        ret = pack_ber_user((request_type == REQ_FULL ? RESP_USER
0201d8
+        ret = pack_ber_user(ctx,
0201d8
+                            (request_type == REQ_FULL ? RESP_USER
0201d8
                                                       : RESP_USER_GROUPLIST),
0201d8
                             domain_name, pwd.pw_name, pwd.pw_uid,
0201d8
                             pwd.pw_gid, pwd.pw_gecos, pwd.pw_dir,
0201d8
@@ -758,7 +760,8 @@ done:
0201d8
     return ret;
0201d8
 }
0201d8
 
0201d8
-static int handle_gid_request(enum request_types request_type, gid_t gid,
0201d8
+static int handle_gid_request(struct ipa_extdom_ctx *ctx,
0201d8
+                              enum request_types request_type, gid_t gid,
0201d8
                               const char *domain_name, struct berval **berval)
0201d8
 {
0201d8
     int ret;
0201d8
@@ -787,7 +790,8 @@ static int handle_gid_request(enum request_types request_type, gid_t gid,
0201d8
 
0201d8
         ret = pack_ber_sid(sid_str, berval);
0201d8
     } else {
0201d8
-        ret = getgrgid_r_wrapper(MAX_BUF, gid, &grp, &buf, &buf_len);
0201d8
+        ret = getgrgid_r_wrapper(ctx->max_nss_buf_size, gid, &grp, &buf,
0201d8
+                                 &buf_len);
0201d8
         if (ret != 0) {
0201d8
             if (ret == ENOMEM || ret == ERANGE) {
0201d8
                 ret = LDAP_OPERATIONS_ERROR;
0201d8
@@ -823,7 +827,8 @@ done:
0201d8
     return ret;
0201d8
 }
0201d8
 
0201d8
-static int handle_sid_request(enum request_types request_type, const char *sid,
0201d8
+static int handle_sid_request(struct ipa_extdom_ctx *ctx,
0201d8
+                              enum request_types request_type, const char *sid,
0201d8
                               struct berval **berval)
0201d8
 {
0201d8
     int ret;
0201d8
@@ -874,7 +879,8 @@ static int handle_sid_request(enum request_types request_type, const char *sid,
0201d8
     switch(id_type) {
0201d8
     case SSS_ID_TYPE_UID:
0201d8
     case SSS_ID_TYPE_BOTH:
0201d8
-        ret = getpwnam_r_wrapper(MAX_BUF, fq_name, &pwd, &buf, &buf_len);
0201d8
+        ret = getpwnam_r_wrapper(ctx->max_nss_buf_size, fq_name, &pwd, &buf,
0201d8
+                                 &buf_len);
0201d8
         if (ret != 0) {
0201d8
             if (ret == ENOMEM || ret == ERANGE) {
0201d8
                 ret = LDAP_OPERATIONS_ERROR;
0201d8
@@ -897,14 +903,16 @@ static int handle_sid_request(enum request_types request_type, const char *sid,
0201d8
             }
0201d8
         }
0201d8
 
0201d8
-        ret = pack_ber_user((request_type == REQ_FULL ? RESP_USER
0201d8
+        ret = pack_ber_user(ctx,
0201d8
+                            (request_type == REQ_FULL ? RESP_USER
0201d8
                                                       : RESP_USER_GROUPLIST),
0201d8
                             domain_name, pwd.pw_name, pwd.pw_uid,
0201d8
                             pwd.pw_gid, pwd.pw_gecos, pwd.pw_dir,
0201d8
                             pwd.pw_shell, kv_list, berval);
0201d8
         break;
0201d8
     case SSS_ID_TYPE_GID:
0201d8
-        ret = getgrnam_r_wrapper(MAX_BUF, fq_name, &grp, &buf, &buf_len);
0201d8
+        ret = getgrnam_r_wrapper(ctx->max_nss_buf_size, fq_name, &grp, &buf,
0201d8
+                                 &buf_len);
0201d8
         if (ret != 0) {
0201d8
             if (ret == ENOMEM || ret == ERANGE) {
0201d8
                 ret = LDAP_OPERATIONS_ERROR;
0201d8
@@ -947,7 +955,8 @@ done:
0201d8
     return ret;
0201d8
 }
0201d8
 
0201d8
-static int handle_name_request(enum request_types request_type,
0201d8
+static int handle_name_request(struct ipa_extdom_ctx *ctx,
0201d8
+                               enum request_types request_type,
0201d8
                                const char *name, const char *domain_name,
0201d8
                                struct berval **berval)
0201d8
 {
0201d8
@@ -988,7 +997,8 @@ static int handle_name_request(enum request_types request_type,
0201d8
             goto done;
0201d8
         }
0201d8
 
0201d8
-        ret = getpwnam_r_wrapper(MAX_BUF, fq_name, &pwd, &buf, &buf_len);
0201d8
+        ret = getpwnam_r_wrapper(ctx->max_nss_buf_size, fq_name, &pwd, &buf,
0201d8
+                                 &buf_len);
0201d8
         if (ret == 0) {
0201d8
             if (request_type == REQ_FULL_WITH_GROUPS) {
0201d8
                 ret = sss_nss_getorigbyname(pwd.pw_name, &kv_list, &id_type);
0201d8
@@ -1002,7 +1012,8 @@ static int handle_name_request(enum request_types request_type,
0201d8
                     goto done;
0201d8
                 }
0201d8
             }
0201d8
-            ret = pack_ber_user((request_type == REQ_FULL ? RESP_USER
0201d8
+            ret = pack_ber_user(ctx,
0201d8
+                                (request_type == REQ_FULL ? RESP_USER
0201d8
                                                           : RESP_USER_GROUPLIST),
0201d8
                                 domain_name, pwd.pw_name, pwd.pw_uid,
0201d8
                                 pwd.pw_gid, pwd.pw_gecos, pwd.pw_dir,
0201d8
@@ -1015,7 +1026,8 @@ static int handle_name_request(enum request_types request_type,
0201d8
              * error codes which can indicate that the user was not found. To
0201d8
              * be on the safe side we fail back to the group lookup on all
0201d8
              * errors. */
0201d8
-            ret = getgrnam_r_wrapper(MAX_BUF, fq_name, &grp, &buf, &buf_len);
0201d8
+            ret = getgrnam_r_wrapper(ctx->max_nss_buf_size, fq_name, &grp, &buf,
0201d8
+                                     &buf_len);
0201d8
             if (ret != 0) {
0201d8
                 if (ret == ENOMEM || ret == ERANGE) {
0201d8
                     ret = LDAP_OPERATIONS_ERROR;
0201d8
@@ -1061,20 +1073,23 @@ int handle_request(struct ipa_extdom_ctx *ctx, struct extdom_req *req,
0201d8
 
0201d8
     switch (req->input_type) {
0201d8
     case INP_POSIX_UID:
0201d8
-        ret = handle_uid_request(req->request_type, req->data.posix_uid.uid,
0201d8
+        ret = handle_uid_request(ctx, req->request_type,
0201d8
+                                 req->data.posix_uid.uid,
0201d8
                                  req->data.posix_uid.domain_name, berval);
0201d8
 
0201d8
         break;
0201d8
     case INP_POSIX_GID:
0201d8
-        ret = handle_gid_request(req->request_type, req->data.posix_gid.gid,
0201d8
+        ret = handle_gid_request(ctx, req->request_type,
0201d8
+                                 req->data.posix_gid.gid,
0201d8
                                  req->data.posix_uid.domain_name, berval);
0201d8
 
0201d8
         break;
0201d8
     case INP_SID:
0201d8
-        ret = handle_sid_request(req->request_type, req->data.sid, berval);
0201d8
+        ret = handle_sid_request(ctx, req->request_type, req->data.sid, berval);
0201d8
         break;
0201d8
     case INP_NAME:
0201d8
-        ret = handle_name_request(req->request_type, req->data.name.object_name,
0201d8
+        ret = handle_name_request(ctx, req->request_type,
0201d8
+                                  req->data.name.object_name,
0201d8
                                   req->data.name.domain_name, berval);
0201d8
 
0201d8
         break;
0201d8
diff --git a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_extop.c b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_extop.c
0201d8
index aa66c145bc6cf2b77fdfe37be18da67588dc0439..e53f968db040a37fbd6a193f87b3671eeabda89d 100644
0201d8
--- a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_extop.c
0201d8
+++ b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_extop.c
0201d8
@@ -40,6 +40,8 @@
0201d8
 #include "ipa_extdom.h"
0201d8
 #include "util.h"
0201d8
 
0201d8
+#define DEFAULT_MAX_NSS_BUFFER (128*1024*1024)
0201d8
+
0201d8
 Slapi_PluginDesc ipa_extdom_plugin_desc = {
0201d8
     IPA_EXTDOM_FEATURE_DESC,
0201d8
     "FreeIPA project",
0201d8
@@ -185,6 +187,14 @@ static int ipa_extdom_init_ctx(Slapi_PBlock *pb, struct ipa_extdom_ctx **_ctx)
0201d8
         goto done;
0201d8
     }
0201d8
 
0201d8
+    ctx->max_nss_buf_size = slapi_entry_attr_get_uint(e,
0201d8
+                                                      "ipaExtdomMaxNssBufSize");
0201d8
+    if (ctx->max_nss_buf_size == 0) {
0201d8
+        ctx->max_nss_buf_size = DEFAULT_MAX_NSS_BUFFER;
0201d8
+    }
0201d8
+    LOG("Maximal nss buffer size set to [%d]!\n", ctx->max_nss_buf_size);
0201d8
+
0201d8
+    ret = 0;
0201d8
 
0201d8
 done:
0201d8
     if (ret) {
0201d8
-- 
0201d8
2.1.0
0201d8