summaryrefslogtreecommitdiff
path: root/nsswitch/stress-nss-libwbclient.c
diff options
context:
space:
mode:
authorRalph Boehme <slow@samba.org>2022-10-31 16:19:21 +0100
committerRalph Boehme <slow@samba.org>2023-01-05 11:33:37 +0000
commit347f75499e832dc669268c5c1b0368224dbf0374 (patch)
tree5d8434d60b66ba8a25b1171f779702572405c005 /nsswitch/stress-nss-libwbclient.c
parent29a99e5e123465145f0faf66bddd94ecc26d15ff (diff)
downloadsamba-347f75499e832dc669268c5c1b0368224dbf0374.tar.gz
nsswitch/stress-nss-libwbclient: also test after fork
Signed-off-by: Ralph Boehme <slow@samba.org> Reviewed-by: Stefan Metzmacher <metze@samba.org>
Diffstat (limited to 'nsswitch/stress-nss-libwbclient.c')
-rw-r--r--nsswitch/stress-nss-libwbclient.c152
1 files changed, 152 insertions, 0 deletions
diff --git a/nsswitch/stress-nss-libwbclient.c b/nsswitch/stress-nss-libwbclient.c
index df1d85c9c40..35818530886 100644
--- a/nsswitch/stress-nss-libwbclient.c
+++ b/nsswitch/stress-nss-libwbclient.c
@@ -30,6 +30,9 @@
#include <sys/types.h>
#include <pwd.h>
#include <wbclient.h>
+#include <sys/socket.h>
+#include <errno.h>
+#include <assert.h>
#define RUNTIME 10
@@ -46,8 +49,11 @@ static void *query_nss_thread(void *ptr)
{
struct thread_state *state = ptr;
char buf[1024];
+ ssize_t nread, nwritten;
+ int p[2];
int rc;
struct passwd pwd, *result;
+ pid_t pid;
while (time(NULL) < state->timeout) {
rc = getpwnam_r(state->username,
@@ -73,6 +79,82 @@ static void *query_nss_thread(void *ptr)
}
pthread_mutex_unlock(&state->lock);
}
+
+ rc = socketpair(AF_UNIX, SOCK_STREAM, 0, p);
+ if (rc != 0) {
+ state->fail = true;
+ return NULL;
+ }
+
+ /*
+ * Check getpwnam_r() still works after a fork,
+ * both in parent and child.
+ */
+
+ pid = fork();
+ if (pid == -1) {
+ return NULL;
+ }
+ if (pid == 0) {
+ /* Child */
+ rc = getpwnam_r(state->username,
+ &pwd,
+ buf,
+ sizeof(buf),
+ &result);
+ if (rc != 0 || result == NULL) {
+ fprintf(stderr,
+ "getpwnam_r failed with rc='%s' result=%p\n",
+ strerror(rc),
+ result);
+ rc = 1;
+ nwritten = write(p[0], &rc, sizeof(int));
+ assert(nwritten == sizeof(int));
+ exit(1);
+ }
+ printf("child: getpwnam_r in child succeeded\n");
+ rc = 0;
+ nwritten = write(p[0], &rc, sizeof(int));
+ assert(nwritten == sizeof(int));
+ exit(1);
+ }
+
+ /* Parent */
+
+ /* Check result from child */
+ nread = read(p[1], &rc, sizeof(int));
+ if (nread != sizeof(int)) {
+ fprintf(stderr,
+ "read from child failed with errno='%s' nread=%zd\n",
+ strerror(errno),
+ nread);
+ state->fail = true;
+ return NULL;
+ }
+
+ if (rc != 0) {
+ fprintf(stderr,
+ "getpwnam_r failed in the child\n");
+ state->fail = true;
+ return NULL;
+ }
+ printf("parent: getpwnam_r in child succeeded\n");
+
+ /* Verify getpwnam_r() in parent after fork */
+ rc = getpwnam_r(state->username,
+ &pwd,
+ buf,
+ sizeof(buf),
+ &result);
+ if (rc != 0 || result == NULL) {
+ fprintf(stderr,
+ "getpwnam_r failed with rc='%s' result=%p\n",
+ strerror(rc),
+ result);
+ state->fail = true;
+ return NULL;
+ }
+ printf("parent: getpwnam_r in parent succeeded\n");
return NULL;
}
@@ -81,6 +163,10 @@ static void *query_wbc_thread(void *ptr)
struct thread_state *state = ptr;
struct passwd *ppwd;
wbcErr wbc_status;
+ pid_t pid;
+ ssize_t nread, nwritten;
+ int p[2];
+ int rc;
while (time(NULL) < state->timeout) {
wbc_status = wbcGetpwnam(state->username, &ppwd);
@@ -102,6 +188,72 @@ static void *query_wbc_thread(void *ptr)
}
pthread_mutex_unlock(&state->lock);
}
+
+ rc = socketpair(AF_UNIX, SOCK_STREAM, 0, p);
+ if (rc != 0) {
+ state->fail = true;
+ return NULL;
+ }
+
+ /*
+ * Check wbcGetpwnam() still works after a fork,
+ * both in parent and child.
+ */
+
+ pid = fork();
+ if (pid == -1) {
+ return NULL;
+ }
+ if (pid == 0) {
+ /* Child */
+ wbc_status = wbcGetpwnam(state->username, &ppwd);
+ if (!WBC_ERROR_IS_OK(wbc_status)) {
+ fprintf(stderr,
+ "wbcGetpwnam failed with %s\n",
+ wbcErrorString(wbc_status));
+ rc = 1;
+ nwritten = write(p[0], &rc, sizeof(int));
+ assert(nwritten == sizeof(int));
+ exit(1);
+ }
+ printf("child: wbcGetpwnam in child succeeded\n");
+ rc = 0;
+ nwritten = write(p[0], &rc, sizeof(int));
+ assert(nwritten == sizeof(int));
+ exit(1);
+ }
+
+ /* Parent */
+
+ /* Check result from child */
+ nread = read(p[1], &rc, sizeof(int));
+ if (nread != sizeof(int)) {
+ fprintf(stderr,
+ "read from child failed with errno='%s' nread=%zd\n",
+ strerror(errno),
+ nread);
+ state->fail = true;
+ return NULL;
+ }
+
+ if (rc != 0) {
+ fprintf(stderr,
+ "wbcGetpwnam failed in the child\n");
+ state->fail = true;
+ return NULL;
+ }
+ printf("parent: wbcGetpwnam in child succeeded\n");
+
+ /* Verify wbcGetpwnam() in parent after fork */
+ wbc_status = wbcGetpwnam(state->username, &ppwd);
+ if (!WBC_ERROR_IS_OK(wbc_status)) {
+ fprintf(stderr,
+ "wbcGetpwnam failed with %s\n",
+ wbcErrorString(wbc_status));
+ state->fail = true;
+ return NULL;
+ }
+ printf("parent: wbcGetpwnam in parent succeeded\n");
return NULL;
}