[Kimchi-devel] [kimchi-devel][PATCH 6/7] Work around eventfd leak using multiprocessing

Aline Manera alinefm at linux.vnet.ibm.com
Thu Jan 22 17:50:09 UTC 2015


Reviewed-by: Aline Manera <alinefm at linux.vnet.ibm.com>

On 20/01/2015 06:45, lvroyce at linux.vnet.ibm.com wrote:
> From: Royce Lv <lvroyce at linux.vnet.ibm.com>
>
> When accessing kimchi server url with authentication every time(no session),
> kimchi server will deny service after about 1000 requests.
>    "GET /storagepools/default/storagevolumes/ HTTP/1.0" 200 563 "" ""
>       Failed to run command: id -Gn royce. [Errno 24] Too many open files
> After tracking with 'lsof', "eventfd" handler leak for kimchi server.
>
> This is because when using pam_start() to generate a pam file handler,
> it needs to be closed by pam_end().
> Unfortunately, PyPAM module only export start() function without end().
>
> This patch workaround leak by putting PAM authentication in
> a sub process, so that when it finishes execution,
> its opening file handler will be closed by system automatically.
>
> REF:
>      http://linux.die.net/man/3/pam_end
>      http://stackoverflow.com/questions/5125245/how-to-authenticate-a-user-using-pam
>
> Signed-off-by: Royce Lv <lvroyce at linux.vnet.ibm.com>
> ---
>   src/kimchi/auth.py | 65 +++++++++++++++++++++++++++++++-----------------------
>   1 file changed, 37 insertions(+), 28 deletions(-)
>
> diff --git a/src/kimchi/auth.py b/src/kimchi/auth.py
> index 22c5c81..8cdbe76 100644
> --- a/src/kimchi/auth.py
> +++ b/src/kimchi/auth.py
> @@ -145,35 +145,44 @@ class PAMUser(User):
>       @staticmethod
>       def authenticate(username, password, service="passwd"):
>           '''Returns True if authenticate is OK via PAM.'''
> -        def _pam_conv(auth, query_list, userData=None):
> -            resp = []
> -            for i in range(len(query_list)):
> -                query, qtype = query_list[i]
> -                if qtype == PAM.PAM_PROMPT_ECHO_ON:
> -                    resp.append((username, 0))
> -                elif qtype == PAM.PAM_PROMPT_ECHO_OFF:
> -                    resp.append((password, 0))
> -                elif qtype == PAM.PAM_PROMPT_ERROR_MSG:
> -                    cherrypy.log.error_log.error(
> -                        "PAM authenticate prompt error: %s" % query)
> -                    resp.append(('', 0))
> -                elif qtype == PAM.PAM_PROMPT_TEXT_INFO:
> -                    resp.append(('', 0))
> -                else:
> -                    return None
> -            return resp
> -
> -        auth = PAM.pam()
> -        auth.start(service)
> -        auth.set_item(PAM.PAM_USER, username)
> -        auth.set_item(PAM.PAM_CONV, _pam_conv)
> -        try:
> -            auth.authenticate()
> -        except PAM.error, (resp, code):
> -            msg_args = {'username': username, 'code': code}
> -            raise OperationFailed("KCHAUTH0001E", msg_args)
> +        def _auth(result):
> +            def _pam_conv(auth, query_list, userData=None):
> +                resp = []
> +                for i in range(len(query_list)):
> +                    query, qtype = query_list[i]
> +                    if qtype == PAM.PAM_PROMPT_ECHO_ON:
> +                        resp.append((username, 0))
> +                    elif qtype == PAM.PAM_PROMPT_ECHO_OFF:
> +                        resp.append((password, 0))
> +                    elif qtype == PAM.PAM_PROMPT_ERROR_MSG:
> +                        cherrypy.log.error_log.error(
> +                            "PAM authenticate prompt error: %s" % query)
> +                        resp.append(('', 0))
> +                    elif qtype == PAM.PAM_PROMPT_TEXT_INFO:
> +                        resp.append(('', 0))
> +                    else:
> +                        return None
> +                return resp
>
> -        return True
> +            result.value = False
> +            auth = PAM.pam()
> +            auth.start(service)
> +            auth.set_item(PAM.PAM_USER, username)
> +            auth.set_item(PAM.PAM_CONV, _pam_conv)
> +            try:
> +                auth.authenticate()
> +            except PAM.error, (resp, code):
> +                msg_args = {'username': username, 'code': code}
> +                raise OperationFailed("KCHAUTH0001E", msg_args)
> +
> +            result.value = True
> +
> +        result = multiprocessing.Value('i', 0, lock=False)
> +        p = multiprocessing.Process(target=_auth, args=(result, ))
> +        p.start()
> +        p.join()
> +
> +        return result.value
>
>
>   class LDAPUser(User):




More information about the Kimchi-devel mailing list