Print this page
8158 Want named threads API
9857 proc manpages should have LIBRARY section
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/ldapcachemgr/cachemgr_change.c
+++ new/usr/src/cmd/ldapcachemgr/cachemgr_change.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 + *
25 + * Copyright 2018 Joyent, Inc.
24 26 */
25 27
26 28 #include <strings.h>
27 29 #include <stdlib.h>
28 30 #include <syslog.h>
29 31 #include <errno.h>
30 32 #include <libintl.h>
31 33 #include <door.h>
32 34 #include <sys/types.h>
33 35 #include <sys/stat.h>
34 36 #include <fcntl.h>
35 37 #include <procfs.h>
38 +#include <pthread.h>
36 39 #include "cachemgr.h"
37 40
38 41 extern admin_t current_admin;
39 42
40 43 #define CLEANUP_WAIT_TIME 60
41 44
42 45 typedef enum cleanup_type {
43 46 CLEANUP_ALL = 1,
44 47 CLEANUP_BY_PID = 2
45 48 } cleanup_type_t;
46 49
47 50 typedef struct cleanup_op {
48 51 pid_t pid;
49 52 cleanup_type_t type;
50 53 } cleanup_op_t;
51 54
52 55 typedef struct main_nscd_struct {
53 56 pid_t pid; /* main nscd pid */
54 57 thread_t tid; /* main nscd tid */
55 58 int in_progress; /* A main nscd thread is */
56 59 /* waiting for change or */
57 60 /* copying data */
58 61 int is_waiting_cleanup; /* A main nscd thread is */
59 62 /* waiting for another main */
60 63 /* nscd thread to be cleaned */
61 64 /* up */
62 65 } main_nscd_t;
63 66
64 67 static chg_info_t chg = { DEFAULTMUTEX, DEFAULTCV, 0, NULL, NULL, NULL, 0 };
65 68
66 69 static main_nscd_t chg_main_nscd = {0, 0, 0, 0};
67 70 static mutex_t chg_main_nscd_lock = DEFAULTMUTEX;
68 71 static cond_t chg_main_nscd_cv = DEFAULTCV;
69 72
70 73 /*
71 74 * The cookie of the configuration and its mutex
72 75 */
73 76 static ldap_get_chg_cookie_t config_cookie = {0, 0};
74 77 static mutex_t config_cookie_lock = DEFAULTMUTEX;
75 78
76 79 static void cleanup_thread_by_pid(pid_t pid);
77 80
78 81 ldap_get_chg_cookie_t
79 82 chg_config_cookie_get(void)
80 83 {
81 84 ldap_get_chg_cookie_t cookie;
82 85 (void) mutex_lock(&config_cookie_lock);
83 86 cookie = config_cookie;
84 87 (void) mutex_unlock(&config_cookie_lock);
85 88 return (cookie);
86 89 }
87 90
88 91 static void
89 92 chg_config_cookie_increment_seq_num(void)
90 93 {
91 94 (void) mutex_lock(&config_cookie_lock);
92 95 config_cookie.seq_num++;
93 96 (void) mutex_unlock(&config_cookie_lock);
94 97 }
95 98
96 99 void
97 100 chg_config_cookie_set(ldap_get_chg_cookie_t *cookie)
98 101 {
99 102 (void) mutex_lock(&config_cookie_lock);
100 103 config_cookie.mgr_pid = cookie->mgr_pid;
101 104 config_cookie.seq_num = cookie->seq_num;
102 105 (void) mutex_unlock(&config_cookie_lock);
103 106 }
104 107 static boolean_t
105 108 chg_cookie_equal(ldap_get_chg_cookie_t *c1, ldap_get_chg_cookie_t *c2)
106 109 {
107 110 if (c1->mgr_pid == c2->mgr_pid && c1->seq_num == c2->seq_num)
108 111 return (B_TRUE);
109 112 else
110 113 return (B_FALSE);
111 114 }
112 115 /*
113 116 * Create a node in the list and output the node. The caller can NOT free it.
114 117 */
115 118 static int
116 119 waiting_list_add(chg_info_t *info, pid_t pid, thread_t tid,
117 120 waiting_list_t **wlp)
118 121 {
119 122
120 123 waiting_list_t *wl;
121 124
122 125 *wlp = NULL;
123 126
124 127 if ((wl = (waiting_list_t *)calloc(1, sizeof (waiting_list_t)))
125 128 == NULL) {
126 129 logit("waiting_list_add: No memory. pid %ld tid %d\n",
127 130 pid, tid);
128 131 return (CHG_NO_MEMORY);
129 132 }
130 133
131 134 wl->pid = pid;
132 135 wl->tid = tid;
133 136
134 137 if (info->chg_w_first == NULL) {
135 138 info->chg_w_first = wl;
136 139 info->chg_w_last = wl;
137 140 } else {
138 141 info->chg_w_last->next = wl;
139 142 wl->prev = info->chg_w_last;
140 143 info->chg_w_last = wl;
141 144 }
142 145 *wlp = wl;
143 146 return (CHG_SUCCESS);
144 147 }
145 148
146 149 /*
147 150 * Find a node with matching tid in the list and remove it from the list.
148 151 */
149 152 static int
150 153 waiting_list_delete(chg_info_t *info, thread_t tid)
151 154 {
152 155 waiting_list_t *wl;
153 156
154 157 for (wl = info->chg_w_first; wl != NULL; wl = wl->next) {
155 158 if (wl->tid == tid) {
156 159 if (wl->next == NULL) {
157 160 if (wl->prev == NULL) {
158 161 info->chg_w_first = NULL;
159 162 info->chg_w_last = NULL;
160 163 } else {
161 164 wl->prev->next = NULL;
162 165 info->chg_w_last = wl->prev;
163 166 }
164 167 } else {
165 168 if (wl->prev == NULL) {
166 169 wl->next->prev = NULL;
167 170 info->chg_w_first = wl->next;
168 171 } else {
169 172 wl->prev->next = wl->next;
170 173 wl->next->prev = wl->prev;
171 174 }
172 175 }
173 176 free(wl);
174 177 return (CHG_SUCCESS);
175 178 }
176 179 }
177 180 return (CHG_NOT_FOUND_IN_WAITING_LIST);
178 181 }
179 182
180 183 /*
181 184 * Delete the thread from the waiting list and remove data when the list
182 185 * is empty.
183 186 */
184 187 static void
185 188 waiting_list_cleanup(chg_info_t *chg, thread_t tid)
186 189 {
187 190 int rc;
188 191
189 192 rc = waiting_list_delete(chg, tid);
190 193
191 194 if (rc == CHG_SUCCESS && chg->chg_w_first == NULL) {
192 195 free(chg->chg_data);
193 196 chg->chg_data = NULL;
194 197 chg->chg_wakeup = 0;
195 198 }
196 199 }
197 200
198 201 /*
199 202 * Set flag by pid so it can be cleaned up.
200 203 */
201 204 static void
202 205 waiting_list_set_cleanup(chg_info_t *info, pid_t pid)
203 206 {
204 207 waiting_list_t *wl;
205 208
206 209 for (wl = info->chg_w_first; wl != NULL; wl = wl->next) {
207 210 if (wl->pid == pid) {
208 211 wl->cleanup = 1;
209 212 break;
210 213 }
211 214 }
212 215 }
213 216
214 217 /*
215 218 * Return: 1 - door client is dead, 0 - door client is alive
216 219 */
217 220 static int
218 221 door_client_dead(void)
219 222 {
220 223 ucred_t *uc = NULL;
221 224 int rc;
222 225
223 226 if (door_ucred(&uc) == -1 && errno == EINVAL) {
224 227 rc = 1;
225 228 } else {
226 229 rc = 0;
227 230 }
228 231 if (uc)
229 232 ucred_free(uc);
230 233
231 234 return (rc);
232 235 }
233 236
234 237 /*
235 238 * This function handles GETSTATUSCHANGE call from main nscd.
236 239 * The call can be a START op or STOP op. A cookie is sent from main nscd too.
237 240 * The static global variable main_nscd keeps record of pid, tid and some flags.
238 241 * If the thread is door_return(), main_nscd.pid, main_nscd.tid are set to 0.
239 242 * When the call is START op, it checks if main_nscd.pid is 0. If it is, it
240 243 * proceeds to wait for the change notification. If it's not, which means
241 244 * another main nscd handling thread is still around. It sends broadcast to
242 245 * clean up that thread and wait until the cleanup is done then proceeds to
243 246 * wait for the change notification. If same main nscd sends START op
244 247 * repeatedly, it'll be rejected.
245 248 * It also checks the cookie from main nscd. If it's not the same as
246 249 * ldap_cachemgr's cookie, door returns config change.
247 250 * If the door call is STOP op, it creates a thread to clean up main nscd START
248 251 * thread so it won't be blocking.
249 252 * In waiting for the change notification phase, the thread is waken up by
250 253 * the notification threads or by the cleanup threads.
251 254 * If it's a notification, it copies data to the stack then door return.
252 255 * If it's a cleanup, door_client_dead() is called to verify it then
253 256 * door return.
254 257 */
255 258 int
256 259 chg_get_statusChange(LineBuf *info, ldap_call_t *in, pid_t nscd_pid)
257 260 {
258 261 int rc = CHG_SUCCESS, another_main_nscd_thread_alive = 0;
259 262 int len, return_now;
260 263 thread_t this_tid = thr_self();
261 264 waiting_list_t *wl = NULL;
262 265 ldap_get_change_out_t *cout;
263 266 ldap_get_chg_cookie_t cookie;
264 267
265 268 info->str = NULL;
266 269 info->len = 0;
267 270
268 271 if (in->ldap_u.get_change.op == NS_STATUS_CHANGE_OP_START) {
269 272
270 273 (void) mutex_lock(&chg_main_nscd_lock);
271 274 if (chg_main_nscd.pid != 0) {
272 275 if (nscd_pid != chg_main_nscd.pid) {
273 276 /*
274 277 * This is the case that nscd doesn't shut down
275 278 * properly(e.g. core) and STOP op is not sent,
276 279 * the thread handling it is still around and
277 280 * not cleaned up yet.
278 281 * Test if the thread is still alive.
279 282 * If it is, clean it up.
280 283 * For thr_kill, if sig is 0, a validity check
281 284 * is done for the existence of the target
282 285 * thread; no signal is sent.
283 286 */
284 287 if (thr_kill(chg_main_nscd.tid, 0) == 0) {
285 288 another_main_nscd_thread_alive = 1;
286 289 cleanup_thread_by_pid(
287 290 chg_main_nscd.pid);
288 291 }
289 292 } else if (chg_main_nscd.in_progress ||
290 293 chg_main_nscd.is_waiting_cleanup) {
291 294 /*
292 295 * Same nscd pid can only send door call
293 296 * one at a time and wait for ldap_cachemgr to
294 297 * return change data. If it's the same pid
295 298 * again, it's an nscd error.
296 299 */
297 300 (void) mutex_unlock(&chg_main_nscd_lock);
298 301 return (CHG_NSCD_REPEATED_CALL);
299 302 }
300 303 }
301 304 /*
302 305 * Wait for another thread to be cleaned up if it's alive.
303 306 * After that this cond var is waken up.
304 307 */
305 308 if (another_main_nscd_thread_alive) {
306 309 while (chg_main_nscd.in_progress) {
307 310 chg_main_nscd.is_waiting_cleanup = 1;
308 311 (void) cond_wait(&chg_main_nscd_cv,
309 312 &chg_main_nscd_lock);
310 313 }
311 314 }
312 315
313 316 /*
314 317 * Replace pid and tid and set the flag.
315 318 */
316 319 chg_main_nscd.is_waiting_cleanup = 0;
317 320 chg_main_nscd.pid = nscd_pid;
318 321 chg_main_nscd.tid = this_tid;
319 322 chg_main_nscd.in_progress = 1;
320 323 (void) mutex_unlock(&chg_main_nscd_lock);
321 324
322 325 cookie = chg_config_cookie_get();
323 326
324 327 if (!chg_cookie_equal(&cookie, &in->ldap_u.get_change.cookie)) {
325 328 /*
326 329 * different cookie, set new cookie and
327 330 * return door call right away
328 331 */
329 332 len = sizeof (ldap_get_change_out_t);
330 333 if ((cout = calloc(1, len)) == NULL) {
331 334 rc = CHG_NO_MEMORY;
332 335 } else {
333 336 cout->type = NS_STATUS_CHANGE_TYPE_CONFIG;
334 337 cout->cookie = cookie;
335 338 info->str = (char *)cout;
336 339 info->len = len;
337 340 }
338 341
339 342 } else {
340 343 (void) mutex_lock(&chg.chg_lock);
341 344
342 345 /* wait for the change notification */
343 346 rc = waiting_list_add(&chg, nscd_pid, this_tid, &wl);
344 347 if (rc == CHG_SUCCESS) {
345 348 return_now = 0;
346 349 while (!chg.chg_wakeup) {
347 350 if (wl->cleanup ||
348 351 door_client_dead()) {
349 352 return_now = 1;
350 353 break;
351 354 }
352 355 (void) cond_wait(&chg.chg_cv,
353 356 &chg.chg_lock);
354 357 }
355 358 /* Check if door client is still alive again */
356 359 if (!return_now && !wl->cleanup &&
357 360 !door_client_dead()) {
358 361 /* copy data to buffer */
359 362 if ((info->str = malloc(
360 363 chg.chg_data_size)) == NULL) {
361 364 rc = CHG_NO_MEMORY;
362 365 } else {
363 366 (void) memcpy(info->str,
364 367 chg.chg_data,
365 368 chg.chg_data_size);
366 369 info->len = chg.chg_data_size;
367 370 }
368 371 }
369 372 waiting_list_cleanup(&chg, this_tid);
370 373 }
371 374 (void) mutex_unlock(&chg.chg_lock);
372 375 }
373 376
374 377
375 378 /*
376 379 * Reset pid, tid and flag, send wakeup signal.
377 380 */
378 381 (void) mutex_lock(&chg_main_nscd_lock);
379 382 chg_main_nscd.pid = 0;
380 383 chg_main_nscd.tid = 0;
381 384 chg_main_nscd.in_progress = 0;
382 385 if (chg_main_nscd.is_waiting_cleanup)
383 386 (void) cond_broadcast(&chg_main_nscd_cv);
384 387
385 388 (void) mutex_unlock(&chg_main_nscd_lock);
386 389
387 390 } else if (in->ldap_u.get_change.op == NS_STATUS_CHANGE_OP_STOP) {
388 391
389 392 cleanup_thread_by_pid(nscd_pid);
390 393 rc = CHG_SUCCESS;
391 394
392 395 } else {
393 396 rc = CHG_INVALID_PARAM;
394 397 }
395 398 if (rc == CHG_EXCEED_MAX_THREADS)
396 399 cleanup_thread_by_pid(0);
397 400
398 401 return (rc);
399 402 }
400 403
401 404 /*
402 405 * This function copies the header and data stream to the buffer
403 406 * then send broadcast to wake up the chg_get_statusChange() threads.
404 407 */
405 408 int
406 409 chg_notify_statusChange(char *str)
407 410 {
408 411 ldap_get_change_out_t *cout = (ldap_get_change_out_t *)str;
409 412
410 413 cout->cookie = chg_config_cookie_get();
411 414
412 415 (void) mutex_lock(&chg.chg_lock);
413 416 if (chg.chg_w_first != NULL && chg.chg_wakeup == 0) {
414 417
415 418 if (chg.chg_data) {
416 419 free(chg.chg_data);
417 420 chg.chg_data = NULL;
418 421 }
419 422
420 423 chg.chg_data = str;
421 424
422 425 if (cout->type == NS_STATUS_CHANGE_TYPE_CONFIG)
423 426 chg.chg_data_size = sizeof (ldap_get_change_out_t);
424 427 else
425 428 /* NS_STATUS_CHANGE_TYPE_SERVER */
426 429 chg.chg_data_size = sizeof (ldap_get_change_out_t) -
427 430 sizeof (int) + cout->data_size;
428 431
429 432 chg.chg_wakeup = 1;
430 433 (void) cond_broadcast(&chg.chg_cv);
431 434 }
432 435 (void) mutex_unlock(&chg.chg_lock);
433 436
434 437 return (CHG_SUCCESS);
435 438 }
436 439
437 440 /*
438 441 * This is called when the configuration is refreshed.
439 442 * The new configuration is different from the current one, a notification
440 443 * is sent tochg_get_statusChange() threads.
441 444 */
442 445 void
443 446 chg_test_config_change(ns_config_t *new, int *change_status)
444 447 {
445 448 int changed = 0;
446 449 LineBuf new_cfg, cur_cfg;
447 450 ns_ldap_error_t *errp = NULL;
448 451 ldap_config_out_t *new_out, *cur_out;
449 452 ldap_get_change_out_t *cout;
450 453
451 454 (void) memset(&new_cfg, 0, sizeof (LineBuf));
452 455 (void) memset(&cur_cfg, 0, sizeof (LineBuf));
453 456 /*
454 457 * Flatten the config data of the newly downloaded config and
455 458 * current default config and compare both.
456 459 */
457 460 if ((errp = __ns_ldap_LoadDoorInfo(&new_cfg, NULL, new, 0)) != NULL) {
458 461 __ns_ldap_freeError(&errp);
459 462 /* error, assume the config is changed */
460 463 changed = 1;
461 464 } else if ((errp = __ns_ldap_LoadDoorInfo(&cur_cfg, NULL, NULL, 0))
462 465 != NULL) {
463 466 __ns_ldap_freeError(&errp);
464 467 /* error, assume the config is changed */
465 468 changed = 1;
466 469 }
467 470 if (changed == 0) {
468 471 new_out = (ldap_config_out_t *)new_cfg.str;
469 472 cur_out = (ldap_config_out_t *)cur_cfg.str;
470 473 if (strcmp(new_out->config_str, cur_out->config_str) != 0) {
471 474 changed = 1;
472 475 if (current_admin.debug_level >= DBG_PROFILE_REFRESH) {
473 476 logit("config changed.\n");
474 477 }
475 478 }
476 479 }
477 480 if (cur_cfg.str)
478 481 free(cur_cfg.str);
479 482 if (new_cfg.str)
480 483 free(new_cfg.str);
481 484
482 485 if (changed) {
483 486
484 487 if ((cout = calloc(1, sizeof (ldap_get_change_out_t)))
485 488 == NULL) {
486 489 logit("chg_test_config_change: No Memory\n");
487 490 } else {
488 491 /*
489 492 * Replace the currentdefault config with the new
490 493 * config
491 494 */
492 495 __s_api_init_config(new);
493 496 chg_config_cookie_increment_seq_num();
494 497 cout->type = NS_STATUS_CHANGE_TYPE_CONFIG;
495 498 /*
496 499 * cout->cookie is set by
497 500 * chg_notify_statusChange
498 501 */
499 502 (void) chg_notify_statusChange((char *)cout);
500 503 }
501 504 } else {
502 505 __s_api_destroy_config(new);
503 506 }
504 507
505 508 *change_status = changed;
506 509 }
507 510
508 511 /*
509 512 * Wake up chg_get_statusChange() threads to clean up the threads
510 513 * that main nscd doesn't exist on the other of door anymore or
511 514 * the thread is marked as cleanup.
512 515 */
513 516 static void
514 517 cleanup_threads(chg_info_t *chg, pid_t pid, cleanup_type_t type)
515 518 {
516 519 (void) mutex_lock(&chg->chg_lock);
517 520 if (type == CLEANUP_BY_PID)
518 521 waiting_list_set_cleanup(chg, pid);
519 522 /*
520 523 * wake up threads without setting chg.chg_wakeup.
521 524 * It's for cleanup purpose, not for notifying changes.
522 525 */
523 526 (void) cond_broadcast(&chg->chg_cv);
524 527 (void) mutex_unlock(&chg->chg_lock);
525 528 }
526 529 /*
527 530 * If arg is NULL, it loops forever,
↓ open down ↓ |
482 lines elided |
↑ open up ↑ |
528 531 * else it calls cleanup_threads once and exits.
529 532 */
530 533 void *
531 534 chg_cleanup_waiting_threads(void *arg)
532 535 {
533 536 cleanup_op_t *op = (cleanup_op_t *)arg;
534 537 cleanup_type_t type = 0;
535 538 pid_t pid;
536 539 int always = 1, waiting;
537 540
541 + (void) pthread_setname_np(pthread_self(), "chg_cleanup_thr");
542 +
538 543 if (op == NULL) {
539 544 waiting = 1;
540 545 type = CLEANUP_ALL;
541 546 pid = 0;
542 547 } else {
543 548 waiting = 0;
544 549 type = op->type;
545 550 pid = op->pid;
546 551 }
547 552
548 553 while (always) {
549 554 if (waiting)
550 555 (void) sleep(CLEANUP_WAIT_TIME);
551 556 cleanup_threads(&chg, pid, type);
552 557 if (!waiting)
553 558 break;
554 559 }
555 560
556 561 if (op)
557 562 free(op);
558 563
559 564 thr_exit(NULL);
560 565 return (NULL);
561 566 }
562 567 /*
563 568 * The door server thead which has the door client pid will be marked
564 569 * as to be clean up. If pid is 0, no marking and just clean up all.
565 570 */
566 571 static void
567 572 cleanup_thread_by_pid(pid_t pid)
568 573 {
569 574 cleanup_op_t *op;
570 575
571 576 if ((op = malloc(sizeof (cleanup_op_t))) == NULL)
572 577 return;
573 578
574 579 op->pid = pid;
575 580 /* clean up all if pid is 0 */
576 581 if (pid == 0)
577 582 op->type = CLEANUP_ALL;
578 583 else
579 584 op->type = CLEANUP_BY_PID;
580 585
581 586 if (thr_create(NULL, 0, chg_cleanup_waiting_threads,
582 587 (void *)op, THR_BOUND|THR_DETACHED, NULL) != 0) {
583 588 free(op);
584 589 logit("thr_create failed for cleanup_thread_by_pid(%ld)\n",
585 590 pid);
586 591 }
587 592 }
588 593
589 594 /*
590 595 * Output a psinfo of an nscd process with process id pid
591 596 * Return: 0 - Can't find the process or it's not nscd
592 597 * 1 - psinfo found
593 598 * Note: If info is NULL, returns 0 or 1 only and no output from info.
594 599 */
595 600 static int
596 601 get_nscd_psinfo(pid_t pid, psinfo_t *info)
597 602 {
598 603 psinfo_t pinfo;
599 604 char fname[MAXPATHLEN];
600 605 ssize_t ret;
601 606 int fd;
602 607
603 608 if (snprintf(fname, MAXPATHLEN, "/proc/%d/psinfo", pid) > 0) {
604 609 if ((fd = open(fname, O_RDONLY)) >= 0) {
605 610 ret = read(fd, &pinfo, sizeof (psinfo_t));
606 611 (void) close(fd);
607 612 if ((ret == sizeof (psinfo_t)) &&
608 613 (strcmp(pinfo.pr_fname, "nscd") == 0)) {
609 614 if (info)
610 615 *info = pinfo;
611 616 return (1);
612 617 }
613 618 }
614 619 }
615 620 return (0);
616 621 }
617 622 /*
618 623 * If the parent process is nscd and euid is 0, it's a peruser nscd.
619 624 */
620 625 static int
621 626 is_peruser_nscd(pid_t pid)
622 627 {
623 628 pid_t ppid;
624 629 psinfo_t pinfo;
625 630
626 631 if (get_nscd_psinfo(pid, &pinfo)) {
627 632 ppid = pinfo.pr_ppid;
628 633 if (get_nscd_psinfo(ppid, &pinfo) && pinfo.pr_euid == 0)
629 634 /*
630 635 * get psinfo of parent forker nscd
631 636 */
632 637 return (1);
633 638 else
634 639 return (0);
635 640 } else {
636 641 return (0);
637 642 }
638 643 }
639 644 /*
640 645 * Check if the door client making door call is a nscd or peruser nscd and
641 646 * output door client's pid.
642 647 */
643 648 int
644 649 chg_is_called_from_nscd_or_peruser_nscd(char *dc_str, pid_t *pidp)
645 650 {
646 651 int rc;
647 652 uid_t euid;
648 653 pid_t pid;
649 654 ucred_t *uc = NULL;
650 655
651 656 if (door_ucred(&uc) != 0) {
652 657 rc = errno;
653 658 logit("door_ucred() call failed %s\n", strerror(rc));
654 659 return (0);
655 660 }
656 661 euid = ucred_geteuid(uc);
657 662 pid = *pidp = ucred_getpid(uc);
658 663
659 664 if ((euid == 0 && is_called_from_nscd(pid)) ||
660 665 is_peruser_nscd(pid)) {
661 666 if (current_admin.debug_level >= DBG_ALL)
662 667 logit("ldap_cachemgr received %s call from pid %ld, "
663 668 "uid %u, euid %u\n", dc_str, pid,
664 669 ucred_getruid(uc), euid);
665 670 rc = 1;
666 671 } else {
667 672 if (current_admin.debug_level >= DBG_CANT_FIND)
668 673 logit("%s call failed(cred): caller pid %ld, uid %u, "
669 674 "euid %u\n", dc_str, pid,
670 675 ucred_getruid(uc), euid);
671 676
672 677 rc = 0;
673 678 }
674 679
675 680 ucred_free(uc);
676 681
677 682 return (rc);
678 683 }
↓ open down ↓ |
131 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX