Skip to content

Commit

Permalink
Detect recursive NIS calls
Browse files Browse the repository at this point in the history
If the system is configured in such a way, that NIS is required
to contact the NIS server (most likely using a FQDN for the NIS
server and NIS for resolving host names), a call of do_ypcall()
and yp_all() can call themself again. This will lead to an
infinite recursion with a stack overflow crash.
If we detect this, bail out with an error.
  • Loading branch information
thkukuk committed Jun 4, 2018
1 parent 549f7b9 commit 4a062cf
Showing 1 changed file with 15 additions and 2 deletions.
17 changes: 15 additions & 2 deletions src/do_ypcall.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (C) 2014, 2017 Thorsten Kukuk
/* Copyright (C) 2014, 2017, 2018 Thorsten Kukuk
Author: Thorsten Kukuk <kukuk@suse.de>
This library is free software: you can redistribute it and/or
Expand Down Expand Up @@ -389,16 +389,22 @@ do_ypcall (const char *domain, u_long prog, xdrproc_t xargs,
dom_binding *ydb;
int status;
int saved_errno = errno;
static __thread int do_ypcall_rec = 0;

status = YPERR_YPERR;

/* if from_yp_call is set, we have a recursion from yp_all, means to
contact the NIS server, we need to do a NIS query first. Bail out
to avoid a deadlock or crash. */
if (from_yp_all == 1)
return status;
return YPERR_YPERR;

/* some if something else is calling NIS again */
if (do_ypcall_rec == 1)
return YPERR_YPERR;

pthread_mutex_lock (&ypbindlist_lock);
do_ypcall_rec = 1;
ydb = ypbindlist;
while (ydb != NULL)
{
Expand All @@ -411,6 +417,7 @@ do_ypcall (const char *domain, u_long prog, xdrproc_t xargs,
resp, &ydb, 0);
if (status == YPERR_SUCCESS)
{
do_ypcall_rec = 0;
pthread_mutex_unlock (&ypbindlist_lock);
errno = saved_errno;
return status;
Expand Down Expand Up @@ -451,6 +458,7 @@ do_ypcall (const char *domain, u_long prog, xdrproc_t xargs,
free (ydb);
}

do_ypcall_rec = 0;
errno = saved_errno;

return status;
Expand Down Expand Up @@ -555,6 +563,11 @@ yp_all (const char *indomain, const char *inmap,
try = 0;
res = YPERR_YPERR;

/* We are called by our self, which means something is resolved
via NIS which is necessary to contact the NIS server */
if (from_yp_all == 1)
return YPERR_YPERR;

pthread_mutex_lock (&ypbindlist_lock);
from_yp_all = 1; /* We are inside a lock, tell other functions of
the same thread. */
Expand Down

0 comments on commit 4a062cf

Please sign in to comment.