summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>2022-08-02 17:00:16 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>2022-08-02 17:00:16 +0000
commitdb34050c74cc8d0a9f9bae17843deeaf379a41d6 (patch)
treefd2a40c14b0ee2323709afaed8619042af08f69f
parent5f6a66769d783a89ff15cc995bce2af433ffefd5 (diff)
1) The yp_bind/yp_unbind and internal _yp_dobind/_yp_unbind sequences shared
dom_binding structs between threads, which is unsafe -- example, dom_vers signalled retry events, and structs+socket would get deallocated in _yp_unbind. Change all yp_first (and similar) functions to understand that _yp_dobind now provides a private dom_binding and socket, which must be released using _yp_unbind. Use similar methods in the one-step yp_all function. 2) domainname caching in get* is not neccessary now that the domainname cannot change relative to ypconnect(2)'s decisions. Many fields in dom_binding struct become unused, so delete them. ok jmatthew, also tested by miod
-rw-r--r--lib/libc/gen/getgrent.c16
-rw-r--r--lib/libc/gen/getgrouplist.c7
-rw-r--r--lib/libc/gen/getnetgrent.c29
-rw-r--r--lib/libc/gen/getpwent.c26
-rw-r--r--lib/libc/yp/yp_all.c33
-rw-r--r--lib/libc/yp/yp_bind.c46
-rw-r--r--lib/libc/yp/yp_first.c6
-rw-r--r--lib/libc/yp/yp_get_default_domain.c24
-rw-r--r--lib/libc/yp/yp_maplist.c4
-rw-r--r--lib/libc/yp/yp_master.c4
-rw-r--r--lib/libc/yp/yp_order.c4
-rw-r--r--lib/libc/yp/ypinternal.h7
-rw-r--r--lib/libc/yp/ypmatch_cache.c6
13 files changed, 98 insertions, 114 deletions
diff --git a/lib/libc/gen/getgrent.c b/lib/libc/gen/getgrent.c
index 3b7c65bfdeb..106f6c3f9dd 100644
--- a/lib/libc/gen/getgrent.c
+++ b/lib/libc/gen/getgrent.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: getgrent.c,v 1.49 2022/07/17 03:10:47 deraadt Exp $ */
+/* $OpenBSD: getgrent.c,v 1.50 2022/08/02 17:00:15 deraadt Exp $ */
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
@@ -341,18 +341,8 @@ grscan(int search, gid_t gid, const char *name, struct group *p_gr,
}
#ifdef YP
if (line[0] == '+' || line[0] == '-') {
- if (__ypdomain == NULL &&
- yp_get_default_domain(&__ypdomain))
- goto parse;
- switch (yp_bind(__ypdomain)) {
- case 0:
- break;
- case YPERR_BADARGS:
- case YPERR_YPBIND:
- goto parse;
- default:
- return 0;
- }
+ if (!__ypdomain)
+ yp_get_default_domain(&__ypdomain);
}
if (line[0] == '+') {
switch (line[1]) {
diff --git a/lib/libc/gen/getgrouplist.c b/lib/libc/gen/getgrouplist.c
index b390449eef2..b23b937faf0 100644
--- a/lib/libc/gen/getgrouplist.c
+++ b/lib/libc/gen/getgrouplist.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: getgrouplist.c,v 1.29 2022/07/17 03:10:47 deraadt Exp $ */
+/* $OpenBSD: getgrouplist.c,v 1.30 2022/08/02 17:00:15 deraadt Exp $ */
/*
* Copyright (c) 2008 Ingo Schwarze <schwarze@usta.de>
* Copyright (c) 1991, 1993
@@ -223,9 +223,8 @@ getgrouplist(const char *uname, gid_t agroup, gid_t *groups, int *grpcnt)
}
/* Only access YP when there is no static entry. */
- if (!yp_bind(__ypdomain) &&
- !yp_match(__ypdomain, "netid.byname", key,
- (int)strlen(key), &ypdata, &ypdatalen))
+ if (!yp_match(__ypdomain, "netid.byname", key,
+ (int)strlen(key), &ypdata, &ypdatalen))
if (_parse_netid(ypdata, pwstore.pw_uid,
groups, &ngroups, maxgroups) == -1)
ret = -1;
diff --git a/lib/libc/gen/getnetgrent.c b/lib/libc/gen/getnetgrent.c
index bd02e09bdfe..26761bde493 100644
--- a/lib/libc/gen/getnetgrent.c
+++ b/lib/libc/gen/getnetgrent.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: getnetgrent.c,v 1.28 2016/09/24 12:43:37 millert Exp $ */
+/* $OpenBSD: getnetgrent.c,v 1.29 2022/08/02 17:00:15 deraadt Exp $ */
/*
* Copyright (c) 1994 Christos Zoulas
@@ -619,7 +619,8 @@ setnetgrent(const char *ng)
{
struct stringlist *sl;
#ifdef YP
- char *line;
+ static char *__ypdomain;
+ char *line = NULL;
#endif
char *ng_copy, *ypdom = NULL;
@@ -639,10 +640,12 @@ setnetgrent(const char *ng)
* We use yp if there is a "+" in the netgroup file, or if there is
* no netgroup file at all
*/
- if (_ng_db == NULL || lookup(NULL, "+", &line, _NG_KEYBYNAME) == 0)
- yp_get_default_domain(&ypdom);
- else
- free(line);
+ if (_ng_db == NULL || lookup(NULL, "+", &line, _NG_KEYBYNAME) == 0) {
+ if (!__ypdomain)
+ yp_get_default_domain(&__ypdomain);
+ ypdom = __ypdomain;
+ }
+ free(line);
#endif
ng_copy = strdup(ng);
if (ng_copy != NULL)
@@ -673,9 +676,10 @@ DEF_WEAK(getnetgrent);
int
innetgr(const char *grp, const char *host, const char *user, const char *domain)
{
- char *ypdom = NULL, *grpdup;
+ char *ypdom = NULL, *grpdup;
#ifdef YP
- char *line = NULL;
+ static char *__ypdomain;
+ char *line = NULL;
#endif
int found;
struct stringlist *sl;
@@ -688,10 +692,11 @@ innetgr(const char *grp, const char *host, const char *user, const char *domain)
* We use yp if there is a "+" in the netgroup file, or if there is
* no netgroup file at all
*/
- if (_ng_db == NULL)
- yp_get_default_domain(&ypdom);
- else if (lookup(NULL, "+", &line, _NG_KEYBYNAME) == 0)
- yp_get_default_domain(&ypdom);
+ if (_ng_db == NULL || lookup(NULL, "+", &line, _NG_KEYBYNAME) == 0) {
+ if (!__ypdomain)
+ yp_get_default_domain(&__ypdomain);
+ ypdom = __ypdomain;
+ }
free(line);
#endif
diff --git a/lib/libc/gen/getpwent.c b/lib/libc/gen/getpwent.c
index 7ddbe332e4c..24ac8f96c3a 100644
--- a/lib/libc/gen/getpwent.c
+++ b/lib/libc/gen/getpwent.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: getpwent.c,v 1.65 2022/07/17 03:10:47 deraadt Exp $ */
+/* $OpenBSD: getpwent.c,v 1.66 2022/08/02 17:00:15 deraadt Exp $ */
/*
* Copyright (c) 2008 Theo de Raadt
* Copyright (c) 1988, 1993
@@ -332,12 +332,8 @@ again:
int keylen, datalen, r, s;
char *key, *data = NULL;
- if (!__ypdomain) {
- if (_yp_check(&__ypdomain) == 0) {
- __ypmode = YPMODE_NONE;
- goto again;
- }
- }
+ if (!__ypdomain)
+ yp_get_default_domain(&__ypdomain);
switch (__ypmode) {
case YPMODE_FULL:
if (__ypcurrent) {
@@ -538,14 +534,8 @@ __has_ypmaster(void)
return (checked);
}
- if (!__ypdomain) {
- if (_yp_check(&__ypdomain) == 0) {
- saved_uid = uid;
- saved_euid = euid;
- checked = 0;
- return (checked); /* No domain. */
- }
- }
+ if (!__ypdomain)
+ yp_get_default_domain(&__ypdomain);
if (yp_first(__ypdomain, "master.passwd.byname",
&key, &keylen, &result, &resultlen)) {
@@ -583,10 +573,8 @@ __yppwlookup(int lookup, char *name, uid_t uid, struct passwd *pw,
break;
switch (pw->pw_name[0]) {
case '+':
- if (!__ypdomain) {
- if (_yp_check(&__ypdomain) == 0)
- continue;
- }
+ if (!__ypdomain)
+ yp_get_default_domain(&__ypdomain);
__ypproto_set(pw, &__yppbuf, *flagsp, &yp_pw_flags);
if (!map) {
if (lookup == LOOKUP_BYNAME) {
diff --git a/lib/libc/yp/yp_all.c b/lib/libc/yp/yp_all.c
index 04a6ebe2b49..204f085ccc8 100644
--- a/lib/libc/yp/yp_all.c
+++ b/lib/libc/yp/yp_all.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: yp_all.c,v 1.15 2022/07/18 02:31:19 deraadt Exp $ */
+/* $OpenBSD: yp_all.c,v 1.16 2022/08/02 16:59:29 deraadt Exp $ */
/*
* Copyright (c) 1992, 1993 Theo de Raadt <deraadt@theos.com>
* All rights reserved.
@@ -101,7 +101,7 @@ int
yp_all(const char *dom, const char *inmap, struct ypall_callback *incallback)
{
struct ypreq_nokey yprnk;
- struct dom_binding *ypbinding;
+ struct dom_binding ypbinding;
struct timeval tv;
int connected = 1;
u_long status;
@@ -118,24 +118,18 @@ again:
s = ypconnect(SOCK_STREAM);
if (s == -1)
return YPERR_DOMAIN; /* YP not running */
+ ypbinding.dom_socket = s;
+ ypbinding.dom_server_addr.sin_port = -1; /* don't consult portmap */
- ypbinding = calloc(1, sizeof *ypbinding);
- if (ypbinding == NULL) {
- close(s);
- return YPERR_RESRC;
- }
- ypbinding->dom_socket = s;
- ypbinding->dom_server_addr.sin_port = -1; /* don't consult portmap */
-
- ypbinding->dom_client = clnttcp_create(&ypbinding->dom_server_addr,
- YPPROG, YPVERS, &ypbinding->dom_socket, 0, 0);
- if (ypbinding->dom_client == NULL) {
- close(ypbinding->dom_socket);
- free(ypbinding);
+ ypbinding.dom_client = clnttcp_create(&ypbinding.dom_server_addr,
+ YPPROG, YPVERS, &ypbinding.dom_socket, 0, 0);
+ if (ypbinding.dom_client == NULL) {
+ close(ypbinding.dom_socket);
+ ypbinding.dom_socket = -1;
clnt_pcreateerror("clnttcp_create");
goto again;
}
- clnt_control(ypbinding->dom_client, CLSET_CONNECTED, &connected);
+ clnt_control(ypbinding.dom_client, CLSET_CONNECTED, &connected);
tv.tv_sec = _yplib_timeout;
tv.tv_usec = 0;
@@ -143,11 +137,10 @@ again:
yprnk.map = (char *)inmap;
ypresp_allfn = incallback->foreach;
ypresp_data = (void *) incallback->data;
- (void) clnt_call(ypbinding->dom_client, YPPROC_ALL,
+ (void) clnt_call(ypbinding.dom_client, YPPROC_ALL,
xdr_ypreq_nokey, &yprnk, _xdr_ypresp_all_seq, &status, tv);
- close(ypbinding->dom_socket);
- clnt_destroy(ypbinding->dom_client);
- free(ypbinding);
+ close(ypbinding.dom_socket);
+ clnt_destroy(ypbinding.dom_client);
if (status != YP_FALSE)
r = ypprot_err(status);
diff --git a/lib/libc/yp/yp_bind.c b/lib/libc/yp/yp_bind.c
index 15db9ea7730..af6775e96b8 100644
--- a/lib/libc/yp/yp_bind.c
+++ b/lib/libc/yp/yp_bind.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: yp_bind.c,v 1.31 2022/07/22 05:55:05 jsg Exp $ */
+/* $OpenBSD: yp_bind.c,v 1.32 2022/08/02 16:59:29 deraadt Exp $ */
/*
* Copyright (c) 1992, 1993, 1996 Theo de Raadt <deraadt@theos.com>
* All rights reserved.
@@ -43,13 +43,13 @@
#include <rpcsvc/ypclnt.h>
#include "ypinternal.h"
-static struct dom_binding *ypbinding;
char _yp_domain[HOST_NAME_MAX+1];
int _yplib_timeout = 10;
int
_yp_dobind(const char *dom, struct dom_binding **ypdb)
{
+ struct dom_binding *ypbinding;
struct timeval tv;
int connected = 1;
int s;
@@ -57,19 +57,15 @@ _yp_dobind(const char *dom, struct dom_binding **ypdb)
if (dom == NULL || strlen(dom) == 0)
return YPERR_BADARGS;
-again:
- if (ypbinding && ypbinding->dom_client)
- _yp_unbind(ypbinding);
+ ypbinding = calloc(1, sizeof (*ypbinding));
+ if (ypbinding == NULL)
+ return YPERR_RESRC;
+again:
s = ypconnect(SOCK_DGRAM);
- if (s == -1)
+ if (s == -1) {
+ free(ypbinding);
return YPERR_YPBIND; /* YP not running */
-
- free(ypbinding);
- ypbinding = calloc(1, sizeof *ypbinding);
- if (ypbinding == NULL) {
- close(s);
- return YPERR_RESRC;
}
ypbinding->dom_socket = s;
ypbinding->dom_server_addr.sin_port = -1; /* don't consult portmap */
@@ -80,14 +76,12 @@ again:
YPPROG, YPVERS, tv, &ypbinding->dom_socket);
if (ypbinding->dom_client == NULL) {
close(ypbinding->dom_socket);
- free(ypbinding);
- ypbinding = NULL;
+ ypbinding->dom_socket = -1;
clnt_pcreateerror("clntudp_create");
goto again;
}
clnt_control(ypbinding->dom_client, CLSET_CONNECTED, &connected);
- if (ypdb)
- *ypdb = ypbinding;
+ *ypdb = ypbinding;
return 0;
}
@@ -95,20 +89,30 @@ void
_yp_unbind(struct dom_binding *ypb)
{
close(ypb->dom_socket);
- ypb->dom_socket = -1;
- clnt_destroy(ypb->dom_client);
- ypb->dom_client = NULL;
+ if (ypb->dom_client)
+ clnt_destroy(ypb->dom_client);
+ free(ypb);
}
+/*
+ * Check if YP is running. But do not leave it active, because we
+ * may not return from libc with a fd active.
+ */
int
yp_bind(const char *dom)
{
- return _yp_dobind(dom, NULL);
+ struct dom_binding *ysd;
+ int r;
+
+ r = _yp_dobind(dom, &ysd);
+ if (r == 0)
+ _yp_unbind(ysd);
+ return r;
}
DEF_WEAK(yp_bind);
void
yp_unbind(const char *dom)
{
- _yp_unbind(ypbinding);
+ /* do nothing */
}
diff --git a/lib/libc/yp/yp_first.c b/lib/libc/yp/yp_first.c
index 2f24999043f..d4978ba2a57 100644
--- a/lib/libc/yp/yp_first.c
+++ b/lib/libc/yp/yp_first.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: yp_first.c,v 1.11 2015/09/13 20:57:28 guenther Exp $ */
+/* $OpenBSD: yp_first.c,v 1.12 2022/08/02 16:59:29 deraadt Exp $ */
/*
* Copyright (c) 1992, 1993 Theo de Raadt <deraadt@theos.com>
* All rights reserved.
@@ -41,7 +41,7 @@ yp_first(const char *indomain, const char *inmap, char **outkey, int *outkeylen,
{
struct ypresp_key_val yprkv;
struct ypreq_nokey yprnk;
- struct dom_binding *ysd;
+ struct dom_binding *ysd = NULL;
struct timeval tv;
int tries = 0, r;
@@ -69,7 +69,7 @@ again:
if (r != RPC_SUCCESS) {
if (tries++)
clnt_perror(ysd->dom_client, "yp_first: clnt_call");
- ysd->dom_vers = -1;
+ _yp_unbind(ysd);
goto again;
}
if (!(r = ypprot_err(yprkv.stat))) {
diff --git a/lib/libc/yp/yp_get_default_domain.c b/lib/libc/yp/yp_get_default_domain.c
index 8cf0dc9fbd9..7eba82d81f4 100644
--- a/lib/libc/yp/yp_get_default_domain.c
+++ b/lib/libc/yp/yp_get_default_domain.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: yp_get_default_domain.c,v 1.9 2015/09/13 20:57:28 guenther Exp $ */
+/* $OpenBSD: yp_get_default_domain.c,v 1.10 2022/08/02 16:59:30 deraadt Exp $ */
/*
* Copyright (c) 1992, 1993 Theo de Raadt <deraadt@theos.com>
* All rights reserved.
@@ -33,17 +33,27 @@
#include <rpcsvc/yp.h>
#include <rpcsvc/ypclnt.h>
#include "ypinternal.h"
+#include "thread_private.h"
+
+_THREAD_PRIVATE_KEY(yp_get_default_domain);
int
yp_get_default_domain(char **domp)
{
+ int r = 0;
+
+ _THREAD_PRIVATE_MUTEX_LOCK(yp_get_default_domain);
*domp = NULL;
- if (_yp_domain[0] == '\0')
- if (getdomainname(_yp_domain, sizeof _yp_domain))
- return YPERR_NODOM;
+ if (_yp_domain[0] == '\0') {
+ if (getdomainname(_yp_domain, sizeof _yp_domain) ||
+ _yp_domain[0] == '\0') {
+ r = YPERR_NODOM;
+ goto out;
+ }
+ }
*domp = _yp_domain;
- if (_yp_domain[0] == '\0')
- return YPERR_NODOM;
- return 0;
+out:
+ _THREAD_PRIVATE_MUTEX_UNLOCK(yp_get_default_domain);
+ return r;
}
DEF_WEAK(yp_get_default_domain);
diff --git a/lib/libc/yp/yp_maplist.c b/lib/libc/yp/yp_maplist.c
index 17bdefe103f..8a7afbbd32d 100644
--- a/lib/libc/yp/yp_maplist.c
+++ b/lib/libc/yp/yp_maplist.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: yp_maplist.c,v 1.9 2015/01/16 16:48:51 deraadt Exp $ */
+/* $OpenBSD: yp_maplist.c,v 1.10 2022/08/02 16:59:30 deraadt Exp $ */
/*
* Copyright (c) 1992, 1993 Theo de Raadt <deraadt@theos.com>
* All rights reserved.
@@ -56,7 +56,7 @@ again:
if (r != RPC_SUCCESS) {
if (tries++)
clnt_perror(ysd->dom_client, "yp_maplist: clnt_call");
- ysd->dom_vers = -1;
+ _yp_unbind(ysd);
goto again;
}
*outmaplist = ypml.maps;
diff --git a/lib/libc/yp/yp_master.c b/lib/libc/yp/yp_master.c
index 0d8f6787ccc..2200d721f42 100644
--- a/lib/libc/yp/yp_master.c
+++ b/lib/libc/yp/yp_master.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: yp_master.c,v 1.9 2015/01/16 16:48:51 deraadt Exp $ */
+/* $OpenBSD: yp_master.c,v 1.10 2022/08/02 16:59:30 deraadt Exp $ */
/*
* Copyright (c) 1992, 1993 Theo de Raadt <deraadt@theos.com>
* All rights reserved.
@@ -65,7 +65,7 @@ again:
if (r != RPC_SUCCESS) {
if (tries++)
clnt_perror(ysd->dom_client, "yp_master: clnt_call");
- ysd->dom_vers = -1;
+ _yp_unbind(ysd);
goto again;
}
if (!(r = ypprot_err(yprm.stat))) {
diff --git a/lib/libc/yp/yp_order.c b/lib/libc/yp/yp_order.c
index 696137ae0f4..522d5d7d264 100644
--- a/lib/libc/yp/yp_order.c
+++ b/lib/libc/yp/yp_order.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: yp_order.c,v 1.10 2015/01/16 16:48:51 deraadt Exp $ */
+/* $OpenBSD: yp_order.c,v 1.11 2022/08/02 16:59:30 deraadt Exp $ */
/*
* Copyright (c) 1992, 1993 Theo de Raadt <deraadt@theos.com>
* All rights reserved.
@@ -72,7 +72,7 @@ again:
}
if (r != RPC_SUCCESS) {
clnt_perror(ysd->dom_client, "yp_order: clnt_call");
- ysd->dom_vers = -1;
+ _yp_unbind(ysd);
goto again;
}
*outorder = ypro.ordernum;
diff --git a/lib/libc/yp/ypinternal.h b/lib/libc/yp/ypinternal.h
index 7be608d812c..5b7ed4103db 100644
--- a/lib/libc/yp/ypinternal.h
+++ b/lib/libc/yp/ypinternal.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ypinternal.h,v 1.13 2022/07/17 03:08:58 deraadt Exp $ */
+/* $OpenBSD: ypinternal.h,v 1.14 2022/08/02 16:59:30 deraadt Exp $ */
/*
* Copyright (c) 1992, 1993, 1996 Theo de Raadt <deraadt@theos.com>
@@ -31,14 +31,9 @@
* yp_prot.h and yp.h.
*/
struct dom_binding {
- struct dom_binding *dom_pnext;
- char dom_domain[YPMAXDOMAIN + 1];
struct sockaddr_in dom_server_addr;
- u_short dom_server_port;
int dom_socket;
CLIENT *dom_client;
- u_short dom_local_port;
- long dom_vers;
};
#define BINDINGDIR "/var/yp/binding"
diff --git a/lib/libc/yp/ypmatch_cache.c b/lib/libc/yp/ypmatch_cache.c
index 718a1bde927..1c2af4c7c69 100644
--- a/lib/libc/yp/ypmatch_cache.c
+++ b/lib/libc/yp/ypmatch_cache.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ypmatch_cache.c,v 1.17 2015/09/13 20:57:28 guenther Exp $ */
+/* $OpenBSD: ypmatch_cache.c,v 1.18 2022/08/02 16:59:30 deraadt Exp $ */
/*
* Copyright (c) 1992, 1993 Theo de Raadt <deraadt@theos.com>
* All rights reserved.
@@ -187,7 +187,7 @@ again:
if (r != RPC_SUCCESS) {
if (tries++)
clnt_perror(ysd->dom_client, "yp_match: clnt_call");
- ysd->dom_vers = -1;
+ _yp_unbind(ysd);
goto again;
}
if (!(r = ypprot_err(yprv.stat))) {
@@ -248,7 +248,7 @@ again:
if (r != RPC_SUCCESS) {
if (tries++)
clnt_perror(ysd->dom_client, "yp_next: clnt_call");
- ysd->dom_vers = -1;
+ _yp_unbind(ysd);
goto again;
}
if (!(r = ypprot_err(yprkv.stat))) {