Date: Mon, 19 Sep 2005 14:01:21 GMT From: soc-bushman <soc-bushman@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 83906 for review Message-ID: <200509191401.j8JE1LBv045197@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=83906 Change 83906 by soc-bushman@soc-bushman_stinger on 2005/09/19 14:01:11 some minor fixes - preparing to start a new branch Affected files ... .. //depot/projects/soc2005/nsswitch_cached/release/cached-0.1/bin/cached.c#6 edit .. //depot/projects/soc2005/nsswitch_cached/release/cached-0.1/bin/mp_rs_query.c#5 edit .. //depot/projects/soc2005/nsswitch_cached/release/cached-0.1/bin/mp_rs_query.h#5 edit .. //depot/projects/soc2005/nsswitch_cached/release/cached-0.1/bin/mp_ws_query.c#5 edit .. //depot/projects/soc2005/nsswitch_cached/release/cached-0.1/bin/mp_ws_query.h#5 edit .. //depot/projects/soc2005/nsswitch_cached/release/cached-0.1/bin/protocol.h#4 edit .. //depot/projects/soc2005/nsswitch_cached/release/cached-0.1/bin/query.c#5 edit .. //depot/projects/soc2005/nsswitch_cached/release/cached-0.1/bin/query.h#5 edit .. //depot/projects/soc2005/nsswitch_cached/tests/nsdispatch_test/nsdispatch_test.c#7 edit Differences ... ==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.1/bin/cached.c#6 (text+ko) ==== @@ -207,6 +207,7 @@ memset(retval, 0, sizeof(struct runtime_env)); retval->sockfd = socket(PF_LOCAL, SOCK_STREAM, 0); + TRACE_INT(retval->sockfd); if (config->force_unlink == 1) unlink(config->socket_path); @@ -227,8 +228,13 @@ TRACE_OUT(init_runtime_env); return (NULL); } + + /* + * Here we're marking socket as non-blocking and setting its backlog + * to the maximum value + */ chmod(config->socket_path, config->socket_mode); - listen(retval->sockfd, 100); + listen(retval->sockfd, -1); fcntl(retval->sockfd, F_SETFL, O_NONBLOCK); retval->queue = kqueue(); @@ -262,26 +268,40 @@ struct query_state *qstate; struct sockaddr addr; - size_t addr_len; + socklen_t addr_len; int fd; int res; + + uid_t euid; + gid_t egid; TRACE_IN(accept_connection); addr_len = sizeof(struct sockaddr); fd = accept(event_data->ident, &addr, &addr_len); if (fd == -1) { - /* do something */ - TRACE_POINT(); + /* TODO: do something */ + TRACE_OUT(accept_connection); + return; + } + + if (getpeereid(fd, &euid, &egid) != 0) { + /* TODO: do something */ + TRACE_OUT(accept_connection); return; } - qstate = init_query_state(fd, sizeof(int)); - memset(&timeout, 0, sizeof(struct timespec)); + qstate = init_query_state(fd, sizeof(int), euid, egid); + if (qstate == NULL) { + /* TODO: do something */ + TRACE_OUT(accept_connection); + return; + } + memset(&timeout, 0, sizeof(struct timespec)); + EV_SET(&eventlist[0], fd, EVFILT_TIMER, EV_ADD | EV_ONESHOT, + 0, qstate->timeout.tv_sec * 1000, qstate); EV_SET(&eventlist[1], fd, EVFILT_READ, EV_ADD | EV_ONESHOT, NOTE_LOWAT, qstate->kevent_watermark, qstate); - EV_SET(&eventlist[0], fd, EVFILT_TIMER, EV_ADD | EV_ONESHOT, - 0, qstate->timeout.tv_sec * 1000, qstate); res = kevent(env->queue, eventlist, 2, NULL, 0, &timeout); TRACE_INT(res); TRACE_INT(fd); @@ -418,7 +438,7 @@ qstate->use_alternate_io = 0; if (qstate->use_alternate_io == 0) { - if (qstate->kevent_watermark > MAX_SOCKET_IO_SIZE) { + if (qstate->kevent_watermark > MAX_SOCKET_IO_SIZE) { if (qstate->io_buffer != NULL) free(qstate->io_buffer); ==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.1/bin/mp_rs_query.c#5 (text+ko) ==== @@ -92,7 +92,7 @@ return (-1); } - if (c_mp_rs_request->entry_length == 0) { + if (BUFSIZE_INVALID(c_mp_rs_request->entry_length)) { TRACE_OUT(on_mp_read_session_request_read1); return (-1); } @@ -158,7 +158,7 @@ return (-1); } - asprintf(&dec_cache_entry_name, "%s%s", qstate->euid_str, + asprintf(&dec_cache_entry_name, "%s%s", qstate->eid_str, qstate->config_entry->c_params->entry_name); assert(dec_cache_entry_name != NULL); ==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.1/bin/mp_rs_query.h#5 (text+ko) ==== ==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.1/bin/mp_ws_query.c#5 (text+ko) ==== @@ -94,7 +94,7 @@ return (-1); } - if (c_mp_ws_request->entry_length == 0) { + if (BUFSIZE_INVALID(c_mp_ws_request->entry_length)) { TRACE_OUT(on_mp_write_session_request_read1); return (-1); } @@ -161,7 +161,7 @@ return (-1); } - asprintf(&dec_cache_entry_name, "%s%s", qstate->euid_str, + asprintf(&dec_cache_entry_name, "%s%s", qstate->eid_str, qstate->config_entry->c_params->entry_name); assert(dec_cache_entry_name != NULL); @@ -303,6 +303,11 @@ TRACE_OUT(on_mp_write_session_write_request_read1); return (-1); } + + if (BUFSIZE_INVALID(write_request->data_size)) { + TRACE_OUT(on_mp_write_session_write_request_read1); + return (-1); + } write_request->data = (char *)malloc(write_request->data_size); assert(write_request->data != NULL); ==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.1/bin/mp_ws_query.h#5 (text+ko) ==== ==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.1/bin/protocol.h#4 (text+ko) ==== @@ -30,6 +30,13 @@ #include <stdlib.h> +/* maximum buffer size to receive - larger buffers are not allowed */ +#define MAX_BUFFER_SIZE (1 << 20) + +/* buffer size correctness checking routine */ +#define BUFSIZE_CORRECT(x) (((x) > 0) && ((x) < MAX_BUFFER_SIZE)) +#define BUFSIZE_INVALID(x) (!BUFSIZE_CORRECT(x)) + struct cache_write_request { char *entry; ==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.1/bin/query.c#5 (text+ko) ==== @@ -67,16 +67,15 @@ { struct msghdr cred_hdr; struct iovec iov; - int elem_type; + int elem_type; struct { struct cmsghdr hdr; struct cmsgcred creds; - } cmsg; + } cmsg; TRACE_IN(on_query_startup); assert(qstate != NULL); - assert(qstate != NULL); memset(&cred_hdr, 0, sizeof(struct msghdr)); cred_hdr.msg_iov = &iov; @@ -88,6 +87,7 @@ iov.iov_base = &elem_type; iov.iov_len = sizeof(int); + TRACE_INT(qstate->sockfd); if (recvmsg(qstate->sockfd, &cred_hdr, 0) == -1) { TRACE_OUT(on_query_startup); return (-1); @@ -101,19 +101,25 @@ } qstate->uid = cmsg.creds.cmcred_uid; - qstate->euid = cmsg.creds.cmcred_euid; - qstate->pid = cmsg.creds.cmcred_pid; - - if (asprintf(&qstate->euid_str, "%d_", qstate->euid) == -1) { - TRACE_OUT(on_query_startup); - return (-1); - } - qstate->euid_str_length = strlen(qstate->euid_str); + qstate->gid = cmsg.creds.cmcred_gid; TRACE_INT(qstate->uid); + TRACE_INT(qstate->gid); TRACE_INT(qstate->euid); - TRACE_INT(qstate->pid); + TRACE_INT(qstate->egid); +/* + This check is probably a bit redundant - per-user cache is always separated by + the euid/egid pair +*/ +#ifndef NO_STRICT_EID_CHECKING + if ((qstate->uid != qstate->euid) || + (qstate->gid != qstate->egid)) { + TRACE_OUT(on_query_startup); + return (-1); + } +#endif + switch (elem_type) { case CET_WRITE_REQUEST: qstate->process_func = on_write_request_read1; @@ -131,8 +137,8 @@ qstate->process_func = on_mp_read_session_request_read1; break; default: - elem_type = -1; - break; + TRACE_OUT(on_query_startup); + return (-1); } qstate->kevent_watermark = 0; @@ -211,9 +217,9 @@ return (-1); } - if ((write_request->entry_length == 0) || - (write_request->cache_key_length == 0) || - (write_request->data_size == 0)) { + if (BUFSIZE_INVALID(write_request->entry_length) || + BUFSIZE_INVALID(write_request->cache_key_length) || + BUFSIZE_INVALID(write_request->data_size)) { TRACE_OUT(on_write_request_read1); return (-1); } @@ -225,11 +231,11 @@ write_request->cache_key = (char *)malloc( write_request->cache_key_length + - qstate->euid_str_length + 1); + qstate->eid_str_length + 1); assert(write_request->cache_key != NULL); - memcpy(write_request->cache_key, qstate->euid_str, - qstate->euid_str_length); - memset(write_request->cache_key + qstate->euid_str_length, 0, + memcpy(write_request->cache_key, qstate->eid_str, + qstate->eid_str_length); + memset(write_request->cache_key + qstate->eid_str_length, 0, write_request->cache_key_length + 1); write_request->data = (char *)malloc(write_request->data_size); @@ -258,7 +264,7 @@ result = qstate->read_func(qstate, write_request->entry, write_request->entry_length); result += qstate->read_func(qstate, write_request->cache_key + - qstate->euid_str_length, write_request->cache_key_length); + qstate->eid_str_length, write_request->cache_key_length); result += qstate->read_func(qstate, write_request->data, write_request->data_size); @@ -345,7 +351,7 @@ if (result != sizeof(int)) { TRACE_OUT(on_write_response_write1); return (-1); - } + } finalize_comm_element(&qstate->request); finalize_comm_element(&qstate->response); @@ -381,8 +387,8 @@ return (-1); } - if ((read_request->entry_length == 0) || - (read_request->cache_key_length == 0)) { + if (BUFSIZE_INVALID(read_request->entry_length) || + BUFSIZE_INVALID(read_request->cache_key_length)) { TRACE_OUT(on_read_request_read1); return (-1); } @@ -394,11 +400,11 @@ read_request->cache_key = (char *)malloc( read_request->cache_key_length + - qstate->euid_str_length + 1); + qstate->eid_str_length + 1); assert(read_request->cache_key != NULL); - memcpy(read_request->cache_key, qstate->euid_str, - qstate->euid_str_length); - memset(read_request->cache_key + qstate->euid_str_length, 0, + memcpy(read_request->cache_key, qstate->eid_str, + qstate->eid_str_length); + memset(read_request->cache_key + qstate->eid_str_length, 0, read_request->cache_key_length + 1); qstate->kevent_watermark = read_request->entry_length + @@ -422,7 +428,7 @@ result = qstate->read_func(qstate, read_request->entry, read_request->entry_length); result += qstate->read_func(qstate, - read_request->cache_key + qstate->euid_str_length, + read_request->cache_key + qstate->eid_str_length, read_request->cache_key_length); if (result != qstate->kevent_watermark) { @@ -685,9 +691,18 @@ ssize_t result; TRACE_IN(query_socket_read); + if (qstate->socket_failed != 0) { + TRACE_POINT(); + return (-1); + } + result = read(qstate->sockfd, buf, nbytes); - TRACE_OUT(query_socket_read); + if ((result == -1) || (result < nbytes)) { + qstate->socket_failed = 1; + TRACE_POINT(); + } + TRACE_OUT(query_socket_read); return (result); } @@ -697,21 +712,23 @@ ssize_t result; TRACE_IN(query_socket_write); + if (qstate->socket_failed != 0) { + TRACE_POINT(); + return (-1); + } + result = write(qstate->sockfd, buf, nbytes); - if (result == -1) { - TRACE_INT(qstate->sockfd); - TRACE_PTR(buf); - TRACE_INT(nbytes); - TRACE_INT(errno); + if ((result == -1) || (result < nbytes)) { + qstate->socket_failed = 1; + TRACE_POINT(); } - TRACE_OUT(query_socket_write); - + TRACE_OUT(query_socket_write); return (result); } struct query_state * -init_query_state(int sockfd, size_t kevent_watermark) +init_query_state(int sockfd, size_t kevent_watermark, uid_t euid, gid_t egid) { struct query_state *retval; @@ -724,6 +741,18 @@ retval->kevent_filter = EVFILT_READ; retval->kevent_watermark = kevent_watermark; + retval->euid = euid; + retval->egid = egid; + retval->uid = retval->gid = -1; + + if (asprintf(&retval->eid_str, "%d_%d_", retval->euid, + retval->egid) == -1) { + free(retval); + TRACE_OUT(init_query_state); + return (NULL); + } + retval->eid_str_length = strlen(retval->eid_str); + init_comm_element(&retval->request, CET_UNDEFINED); init_comm_element(&retval->response, CET_UNDEFINED); retval->process_func = on_query_startup; @@ -744,8 +773,8 @@ destroy_query_state(struct query_state *qstate) { TRACE_IN(destroy_query_state); - if (qstate->euid_str != NULL) - free(qstate->euid_str); + if (qstate->eid_str != NULL) + free(qstate->eid_str); if (qstate->io_buffer != NULL) free(qstate->io_buffer); ==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.1/bin/query.h#5 (text+ko) ==== @@ -64,18 +64,20 @@ query_write_func write_func; /* data write function */ query_read_func read_func; /* data read function */ - char *euid_str; /* string version of the euid */ - size_t euid_str_length; + char *eid_str; /* the user-identifying string (euid_egid_) */ + size_t eid_str_length; - uid_t euid; /* euid of the caller, recevied via credentials */ - uid_t uid; /* uid of the caller, recevied via credentials */ - pid_t pid; /* pid of the caller, recevied via credentials */ + uid_t euid; /* euid of the caller, received via getpeereid */ + uid_t uid; /* uid of the caller, received via credentials */ + gid_t egid; /* egid of the caller, received via getpeereid */ + gid_t gid; /* gid of the caller received via credentials */ size_t io_buffer_size; size_t io_buffer_watermark; size_t kevent_watermark; /* bytes to be sent/received */ int sockfd; /* the unix socket to read/write */ - int kevent_filter; /* EVFILT_READ or EVFILT_WRITE */ + int kevent_filter; /* EVFILT_READ or EVFILT_WRITE */ + int socket_failed; /* set to 1 if the socket doesn't work correctly */ char *io_buffer; char *io_buffer_p; @@ -91,7 +93,7 @@ extern ssize_t query_socket_write(struct query_state *, const void *, size_t); -extern struct query_state *init_query_state(int, size_t); +extern struct query_state *init_query_state(int, size_t, uid_t, gid_t); extern void destroy_query_state(struct query_state *); extern struct configuration_entry *find_config_entry_by_name_and_euid( ==== //depot/projects/soc2005/nsswitch_cached/tests/nsdispatch_test/nsdispatch_test.c#7 (text+ko) ==== @@ -411,17 +411,17 @@ tsystem = __init_test_system("testing system testing :)"); assert(tsystem != NULL); -/* tinfo = __create_test_info("getservbyname_test", getservbyname_test, 1); + tinfo = __create_test_info("getservbyname_test", getservbyname_test, 1); assert(tinfo != NULL); - __register_test_info(tsystem, tinfo);*/ + __register_test_info(tsystem, tinfo); tinfo = __create_test_info("getpwnam_test", getpwnam_test, 1); assert(tinfo != NULL); __register_test_info(tsystem, tinfo); -/* tinfo = __create_test_info("getgrnam_test", getgrnam_test, 1); + tinfo = __create_test_info("getgrnam_test", getgrnam_test, 1); assert(tinfo != NULL); - __register_test_info(tsystem, tinfo);*/ + __register_test_info(tsystem, tinfo); /* tinfo = __create_test_info("getaddrinfo_test", getaddrinfo_test, 1); assert(tinfo != NULL); @@ -435,13 +435,13 @@ assert(tinfo != NULL); __register_test_info(tsystem, tinfo); */ -/* tinfo = __create_test_info("getprotoent_test", getprotoent_test, 1); + tinfo = __create_test_info("getprotoent_test", getprotoent_test, 1); assert(tinfo != NULL); - __register_test_info(tsystem, tinfo);*/ + __register_test_info(tsystem, tinfo); -/* tinfo = __create_test_info("getrpcent_test", getrpcent_test, 1); + tinfo = __create_test_info("getrpcent_test", getrpcent_test, 1); assert(tinfo != NULL); - __register_test_info(tsystem, tinfo);*/ + __register_test_info(tsystem, tinfo); __process_tests(tsystem, &passed, &failed); __test_log1("__process_tests returned, %d passed, %d failed\n", passed, failed);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200509191401.j8JE1LBv045197>