--- bind/bin/named/server.c +++ bind/bin/named/server.c @@ -2680,8 +2680,12 @@ load_configuration(const char *filename, ns_server_t *server, "no source of entropy found"); } else { const char *randomdev = cfg_obj_asstring(obj); - result = isc_entropy_createfilesource(ns_g_entropy, + if (strcmp(randomdev, PATH_RANDOMDEV)) + result = isc_entropy_createfilesource(ns_g_entropy, randomdev); + else + result = isc_entropy_createfilefd(ns_g_entropy, + ns_os_open_randomdev(), ISC_FALSE, ISC_FALSE); if (result != ISC_R_SUCCESS) isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, @@ -2714,16 +2718,9 @@ load_configuration(const char *filename, ns_server_t *server, /* * Relinquish root privileges. */ - if (first_time) + if (first_time) { ns_os_changeuser(); - - /* - * Check that the working directory is writable. - */ - if (access(".", W_OK) != 0) { - isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, - NS_LOGMODULE_SERVER, ISC_LOG_ERROR, - "the working directory is not writable"); + ns_os_dropprivs(); } /* --- bind/bin/named/unix/include/named/os.h +++ bind/bin/named/unix/include/named/os.h @@ -53,6 +53,12 @@ void ns_os_preopenpidfile(const char *filename); void +ns_os_dropprivs(void); + +int +ns_os_open_randomdev(void); + +void ns_os_writepidfile(const char *filename, isc_boolean_t first_time); void ns_os_shutdown(void); --- bind/bin/named/unix/os.c +++ bind/bin/named/unix/os.c @@ -328,6 +328,19 @@ ns_os_init(const char *progname) { #endif } +int +ns_os_open_randomdev (void) +{ + static int fd = -1; + +#ifdef PATH_RANDOMDEV + if (fd < 0) + fd = open(PATH_RANDOMDEV, O_RDONLY | O_NONBLOCK, 0); +#endif + + return fd; +} + void ns_os_daemonize(void) { pid_t pid; @@ -448,6 +461,7 @@ ns_os_chroot(const char *root) { ns_smf_chroot = 0; #endif if (root != NULL) { + ns_os_open_randomdev(); if (chroot(root) < 0) { isc__strerror(errno, strbuf, sizeof(strbuf)); ns_main_earlyfatal("chroot(): %s", strbuf); @@ -567,6 +581,13 @@ ns_os_minprivs(void) { #endif } +void +ns_os_dropprivs(void) { +#if defined(HAVE_LINUX_CAPABILITY_H) && !defined(HAVE_LINUXTHREADS) + linux_setcaps(0); +#endif +} + static int safe_open(const char *filename, isc_boolean_t append) { int fd; --- bind/lib/isc/include/isc/entropy.h +++ bind/lib/isc/include/isc/entropy.h @@ -166,6 +166,9 @@ isc_entropy_createfilesource(isc_entropy_t *ent, const char *fname); * The file will never be opened/read again once EOF is reached. */ +isc_result_t +isc_entropy_createfilefd(isc_entropy_t *ent, int fd, isc_boolean_t is_usocket, isc_boolean_t is_connected); + void isc_entropy_destroysource(isc_entropysource_t **sourcep); /* --- bind/lib/isc/unix/entropy.c +++ bind/lib/isc/unix/entropy.c @@ -473,22 +473,82 @@ make_nonblock(int fd) { } isc_result_t +isc_entropy_createfilefd(isc_entropy_t *ent, int fd, isc_boolean_t is_usocket, isc_boolean_t is_connected) { + isc_result_t ret; + isc_entropysource_t *source; + + REQUIRE(VALID_ENTROPY(ent)); + REQUIRE(fd >= 0); + + LOCK(&ent->lock); + + source = isc_mem_get(ent->mctx, sizeof(isc_entropysource_t)); + if (source == NULL) { + (void) close(fd); + UNLOCK(&ent->lock); + return ISC_R_NOMEMORY; + } + + ret = make_nonblock(fd); + if (ret != ISC_R_SUCCESS) + goto closefd; + + /* + * From here down, no failures can occur. + */ + source->magic = SOURCE_MAGIC; + source->ent = ent; + source->total = 0; + source->bad = ISC_FALSE; + memset(source->name, 0, sizeof(source->name)); + ISC_LINK_INIT(source, link); + if (is_usocket) { + source->sources.usocket.handle = fd; + if (is_connected) + source->sources.usocket.status = + isc_usocketsource_connected; + else + source->sources.usocket.status = + isc_usocketsource_connecting; + source->sources.usocket.sz_to_recv = 0; + source->type = ENTROPY_SOURCETYPE_USOCKET; + } else { + source->sources.file.handle = fd; + source->type = ENTROPY_SOURCETYPE_FILE; + } + + /* + * Hook it into the entropy system. + */ + ISC_LIST_APPEND(ent->sources, source, link); + ent->nsources++; + + UNLOCK(&ent->lock); + return (ISC_R_SUCCESS); + + closefd: + (void)close(fd); + + if (source != NULL) + isc_mem_put(ent->mctx, source, sizeof(isc_entropysource_t)); + + UNLOCK(&ent->lock); + + return (ret); +} + +isc_result_t isc_entropy_createfilesource(isc_entropy_t *ent, const char *fname) { - int fd; struct stat _stat; isc_boolean_t is_usocket = ISC_FALSE; isc_boolean_t is_connected = ISC_FALSE; - isc_result_t ret; - isc_entropysource_t *source; + int fd; REQUIRE(VALID_ENTROPY(ent)); REQUIRE(fname != NULL); - LOCK(&ent->lock); - if (stat(fname, &_stat) < 0) { - ret = isc__errno2result(errno); - goto errout; + return isc__errno2result(errno); } /* * Solaris 2.5.1 does not have support for sockets (S_IFSOCK), @@ -511,14 +571,9 @@ isc_entropy_createfilesource(isc_entropy_t *ent, const char *fname) { fd = open(fname, O_RDONLY | PORT_NONBLOCK, 0); if (fd < 0) { - ret = isc__errno2result(errno); - goto errout; + return isc__errno2result(errno); } - ret = make_nonblock(fd); - if (ret != ISC_R_SUCCESS) - goto closefd; - if (is_usocket) { struct sockaddr_un sname; @@ -537,57 +592,12 @@ isc_entropy_createfilesource(isc_entropy_t *ent, const char *fname) { if (connect(fd, (struct sockaddr *) &sname, sizeof(struct sockaddr_un)) < 0) { if (errno != EINPROGRESS) { - ret = isc__errno2result(errno); - goto closefd; + (void) close(fd); + return isc__errno2result(errno); } } else is_connected = ISC_TRUE; } - source = isc_mem_get(ent->mctx, sizeof(isc_entropysource_t)); - if (source == NULL) { - ret = ISC_R_NOMEMORY; - goto closefd; - } - - /* - * From here down, no failures can occur. - */ - source->magic = SOURCE_MAGIC; - source->ent = ent; - source->total = 0; - source->bad = ISC_FALSE; - memset(source->name, 0, sizeof(source->name)); - ISC_LINK_INIT(source, link); - if (is_usocket) { - source->sources.usocket.handle = fd; - if (is_connected) - source->sources.usocket.status = - isc_usocketsource_connected; - else - source->sources.usocket.status = - isc_usocketsource_connecting; - source->sources.usocket.sz_to_recv = 0; - source->type = ENTROPY_SOURCETYPE_USOCKET; - } else { - source->sources.file.handle = fd; - source->type = ENTROPY_SOURCETYPE_FILE; - } - - /* - * Hook it into the entropy system. - */ - ISC_LIST_APPEND(ent->sources, source, link); - ent->nsources++; - - UNLOCK(&ent->lock); - return (ISC_R_SUCCESS); - - closefd: - (void)close(fd); - - errout: - UNLOCK(&ent->lock); - - return (ret); + return isc_entropy_createfilefd(ent, fd, is_usocket, is_connected); }