int uwsgi_is_a_keep_mount(char *mp) { struct uwsgi_string_list *usl = uwsgi.ns_keep_mount; while(usl) { char *colon = strchr(usl->value, ':'); if (colon) { if (!strcmp(colon+1, mp)) { return 1; } } else { // slip first part if (!uwsgi_startswith(usl->value, uwsgi.ns, strlen(uwsgi.ns))) { char *skipped = usl->value + strlen(uwsgi.ns); if (uwsgi.ns[strlen(uwsgi.ns)-1] == '/') { skipped--; } if (!strcmp(skipped, mp)) { return 1; } } else { if (!strcmp(usl->value, mp)) { return 1; } } } usl = usl->next; } return 0; }
void uwsgi_imperial_monitor_glob_init(struct uwsgi_emperor_scanner *ues) { if (chdir(uwsgi.cwd)) { uwsgi_error("chdir()"); exit(1); } uwsgi.emperor_absolute_dir = uwsgi.cwd; if (!uwsgi_startswith(ues->arg, "glob://", 7)) { ues->arg += 7; } }
void uwsgi_imperial_monitor_directory_init(struct uwsgi_emperor_scanner *ues) { if (!uwsgi_startswith(ues->arg, "dir://", 6)) { ues->arg += 6; } if (chdir(ues->arg)) { uwsgi_error("chdir()"); exit(1); } uwsgi.emperor_absolute_dir = uwsgi_malloc(PATH_MAX + 1); if (realpath(".", uwsgi.emperor_absolute_dir) == NULL) { uwsgi_error("realpath()"); exit(1); } }
void uwsgi_corerouter_setup_sockets(struct uwsgi_corerouter *ucr) { struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets; while (ugs) { if (!strcmp(ucr->name, ugs->owner)) { if (!ugs->subscription) { if (ugs->name[0] == '=') { int shared_socket = atoi(ugs->name+1); if (shared_socket >= 0) { ugs->fd = uwsgi_get_shared_socket_fd_by_num(shared_socket); ugs->shared = 1; if (ugs->fd == -1) { uwsgi_log("unable to use shared socket %d\n", shared_socket); exit(1); } ugs->name = uwsgi_getsockname(ugs->fd); } } else if (!uwsgi_startswith("fd://", ugs->name, 5 )) { int fd_socket = atoi(ugs->name+5); if (fd_socket >= 0) { ugs->fd = fd_socket; ugs->name = uwsgi_getsockname(ugs->fd); if (!ugs->name) { uwsgi_log("unable to use file descriptor %d as socket\n", fd_socket); exit(1); } } } else { ugs->port = strchr(ugs->name, ':'); if (ugs->fd == -1) { if (ugs->port) { ugs->fd = bind_to_tcp(ugs->name, uwsgi.listen_queue, ugs->port); ugs->port++; ugs->port_len = strlen(ugs->port); } else { ugs->fd = bind_to_unix(ugs->name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket); } } } // put socket in non-blocking mode uwsgi_socket_nb(ugs->fd); uwsgi_log("%s bound on %s fd %d\n", ucr->name, ugs->name, ugs->fd); } else if (ugs->subscription) { if (ugs->fd == -1) { if (strchr(ugs->name, ':')) { ugs->fd = bind_to_udp(ugs->name, 0, 0); } else { ugs->fd = bind_to_unix_dgram(ugs->name); } uwsgi_socket_nb(ugs->fd); } uwsgi_log("%s subscription server bound on %s fd %d\n", ucr->name, ugs->name, ugs->fd); } } ugs = ugs->next; } }
char *uwsgi_format_airbrake_backtrace(struct uwsgi_thread *ut) { struct uwsgi_airbrake_config *uacc = (struct uwsgi_airbrake_config *) ut->data; xmlChar *xmlbuff; int buffersize; xmlDocPtr doc = NULL; xmlNodePtr notice_node = NULL, node = NULL, line_node = NULL, errnode = NULL; char *msg = NULL; doc = xmlNewDoc(BAD_CAST "1.0"); notice_node = xmlNewNode(NULL, BAD_CAST "notice"); xmlNewProp(notice_node, BAD_CAST "version", BAD_CAST "2.3"); xmlDocSetRootElement(doc, notice_node); xmlNewChild(notice_node, NULL, BAD_CAST "api-key", BAD_CAST uacc->apikey); node = xmlNewChild(notice_node, NULL, BAD_CAST "notifier", NULL); xmlNewChild(node, NULL, BAD_CAST "name", BAD_CAST "uWSGI"); xmlNewChild(node, NULL, BAD_CAST "version", BAD_CAST UWSGI_VERSION); xmlNewChild(node, NULL, BAD_CAST "url", BAD_CAST "https://github.com/unbit/uwsgi"); // request env node = xmlNewChild(notice_node, NULL, BAD_CAST "request", NULL); node = xmlNewChild(node, NULL, BAD_CAST "cgi-data", NULL); line_node = xmlNewChild(node, NULL, BAD_CAST "var", BAD_CAST UWSGI_VERSION); xmlNewProp(line_node, BAD_CAST "key", BAD_CAST "uwsgi_version"); line_node = xmlNewChild(node, NULL, BAD_CAST "var", BAD_CAST __VERSION__); xmlNewProp(line_node, BAD_CAST "key", BAD_CAST "compiled_with_version"); struct utsname uuts; #ifdef __sun__ if (uname(&uuts) < 0) { #else if (uname(&uuts)) { #endif uwsgi_error("uname()"); } else { line_node = xmlNewChild(node, NULL, BAD_CAST "var", BAD_CAST uuts.sysname); xmlNewProp(line_node, BAD_CAST "key", BAD_CAST "os_sysname"); char *os_version = uwsgi_concat3(uuts.release, "-", uuts.version); line_node = xmlNewChild(node, NULL, BAD_CAST "var", BAD_CAST os_version); xmlNewProp(line_node, BAD_CAST "key", BAD_CAST "os_version"); free(os_version); line_node = xmlNewChild(node, NULL, BAD_CAST "var", BAD_CAST uuts.machine); xmlNewProp(line_node, BAD_CAST "key", BAD_CAST "machine"); line_node = xmlNewChild(node, NULL, BAD_CAST "var", BAD_CAST uuts.nodename); xmlNewProp(line_node, BAD_CAST "key", BAD_CAST "nodename"); } // end request env node = xmlNewChild(notice_node, NULL, BAD_CAST "server-environment", NULL); xmlNewChild(node, NULL, BAD_CAST "app-version", BAD_CAST UWSGI_VERSION); if (uacc->env) { xmlNewChild(node, NULL, BAD_CAST "environment-name", BAD_CAST uacc->env); } else { xmlNewChild(node, NULL, BAD_CAST "environment-name", BAD_CAST UWSGI_VERSION); } errnode = xmlNewChild(notice_node, NULL, BAD_CAST "error", NULL); xmlNewChild(errnode, NULL, BAD_CAST "class", BAD_CAST "RuntimeError"); node = xmlNewChild(errnode, NULL, BAD_CAST "backtrace", NULL); char *ctx = NULL; char *text = uwsgi_str(ut->buf); char *p = strtok_r(text, "\n", &ctx); while (p) { // skip log messages if (!uwsgi_startswith(p, "***", 3)) goto next; // backtrace line looks like this: uwsgi(simple_loop_run+0xc5) [0x451555] // we take binary/lib as filename // and extract method name from remaining string char *n = strchr(p, '('); if (n) { *n = 0; char *pls = strchr(n+1, '+'); if (pls) { *pls = 0; } if (!strcmp("uwsgi_backtrace", n+1) || !strcmp("what_i_am_doing", n+1)) { goto next; } else if (!strcmp("uwsgi_fpe", n+1)) { msg = uwsgi_concat4("uWSGI FPE at ", n+1, " in ", p); goto next; } if (!msg) { if (strlen(n+1)) { msg = uwsgi_concat4("uWSGI segfault at ", n+1, " in ", p); } else { // method name might be missing msg = uwsgi_concat2("uWSGI segfault in ", p); } } // skip empty lines if (!p) goto next; line_node = xmlNewChild(node, NULL, BAD_CAST "line", NULL); if ((n+1)[0] == ')') { xmlNewProp(line_node, BAD_CAST "method", BAD_CAST "()"); } else { xmlNewProp(line_node, BAD_CAST "method", BAD_CAST n+1); } xmlNewProp(line_node, BAD_CAST "file", BAD_CAST p); //xmlNewProp(line_node, BAD_CAST "number", BAD_CAST "0"); } next: p = strtok_r(NULL, "\n", &ctx); } xmlNewChild(errnode, NULL, BAD_CAST "message", BAD_CAST msg); xmlDocDumpFormatMemory(doc, &xmlbuff, &buffersize, 1); xmlFreeDoc(doc); xmlCleanupParser(); xmlMemoryDump(); free(msg); free(text); return (char *) xmlbuff; } static void uwsgi_airbrake_loop(struct uwsgi_thread *ut) { int interesting_fd; ut->buf = uwsgi_malloc(uwsgi.log_master_bufsize); CURL *curl = curl_easy_init(); // ARGH !!! if (!curl) return; curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]); curl_easy_setopt(curl, CURLOPT_TIMEOUT, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]); curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL); curl_easy_setopt(curl, CURLOPT_READDATA, ut); curl_easy_setopt(curl, CURLOPT_POST, 1L); struct curl_slist *expect = NULL; expect = curl_slist_append(expect, "Expect:"); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, expect); curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); struct uwsgi_airbrake_config *uacc = (struct uwsgi_airbrake_config *) ut->data; char *opts = uwsgi_str(uacc->arg); // fill curl options char *ctx = NULL; char *p = strtok_r(opts, ";", &ctx); while(p) { uwsgi_airbrake_setopt(curl, uwsgi_str(p), uacc); p = strtok_r(NULL, ";", &ctx); } for(;;) { int ret = event_queue_wait(ut->queue, -1, &interesting_fd); if (ret < 0) return; if (ret == 0) continue; if (interesting_fd != ut->pipe[1]) continue; ssize_t rlen = read(ut->pipe[1], ut->buf, uwsgi.log_master_bufsize); if (rlen <= 0) continue; ut->pos = 0; ut->len = (size_t) rlen; ut->custom0 = 0; char *notice = uwsgi_format_airbrake_backtrace(ut); curl_slist_append(expect, "Accept: */*"); curl_slist_append(expect, "Content-Type: text/xml; charset=utf-8"); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, expect); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, notice); curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strlen(notice)); curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t) ut->len); CURLcode res = curl_easy_perform(curl); if (res != CURLE_OK) { uwsgi_log_alarm("-curl] curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } free(notice); } }
void uwsgi_corerouter_setup_sockets(struct uwsgi_corerouter *ucr) { struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets; while (ugs) { if (!strcmp(ucr->name, ugs->owner)) { #ifdef UWSGI_SCTP if (!ugs->subscription && !ugs->sctp) { #else if (!ugs->subscription) { #endif if (ugs->name[0] == '=') { int shared_socket = atoi(ugs->name+1); if (shared_socket >= 0) { ugs->fd = uwsgi_get_shared_socket_fd_by_num(shared_socket); ugs->shared = 1; if (ugs->fd == -1) { uwsgi_log("unable to use shared socket %d\n", shared_socket); exit(1); } ugs->name = uwsgi_getsockname(ugs->fd); } } else if (!uwsgi_startswith("fd://", ugs->name, 5 )) { int fd_socket = atoi(ugs->name+5); if (fd_socket >= 0) { ugs->fd = fd_socket; ugs->name = uwsgi_getsockname(ugs->fd); if (!ugs->name) { uwsgi_log("unable to use file descriptor %d as socket\n", fd_socket); exit(1); } } } else { ugs->port = strchr(ugs->name, ':'); if (ugs->fd == -1) { if (ugs->port) { ugs->fd = bind_to_tcp(ugs->name, uwsgi.listen_queue, ugs->port); ugs->port++; ugs->port_len = strlen(ugs->port); } else { ugs->fd = bind_to_unix(ugs->name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket); } } } // put socket in non-blocking mode uwsgi_socket_nb(ugs->fd); uwsgi_log("%s bound on %s fd %d\n", ucr->name, ugs->name, ugs->fd); } else if (ugs->subscription) { if (ugs->fd == -1) { if (strchr(ugs->name, ':')) { ugs->fd = bind_to_udp(ugs->name, 0, 0); } else { ugs->fd = bind_to_unix_dgram(ugs->name); } uwsgi_socket_nb(ugs->fd); } uwsgi_log("%s subscription server bound on %s fd %d\n", ucr->name, ugs->name, ugs->fd); } #ifdef UWSGI_SCTP else if (ugs->sctp) { if (ugs->fd == -1) { ugs->fd = bind_to_sctp(ugs->name); } uwsgi_log("%s SCTP server bound on %s fd %d\n", gw_id, ugs->name, ugs->fd); } #endif } ugs = ugs->next; } } void *uwsgi_corerouter_setup_event_queue(struct uwsgi_corerouter *ucr, int id) { ucr->queue = event_queue_init(); struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets; while (ugs) { if (!strcmp(ucr->name, ugs->owner)) { if (!ucr->cheap || ugs->subscription) { event_queue_add_fd_read(ucr->queue, ugs->fd); } ugs->gateway = &ushared->gateways[id]; } ugs = ugs->next; } return event_queue_alloc(ucr->nevents); }
void uwsgi_add_socket_from_fd(struct uwsgi_socket *uwsgi_sock, int fd) { socklen_t socket_type_len; union uwsgi_sockaddr_ptr gsa, isa; union uwsgi_sockaddr usa; int abstract = 0; socket_type_len = sizeof(struct sockaddr_un); gsa.sa = &usa.sa; if (!getsockname(fd, gsa.sa, &socket_type_len)) { if (socket_type_len <= 2) { // unbound socket return; } if (gsa.sa->sa_family == AF_UNIX) { if (usa.sa_un.sun_path[0] == 0) abstract = 1; // is it a zerg ? if (uwsgi_sock->name == NULL) { uwsgi_sock->fd = fd; uwsgi_sock->family = AF_UNIX; uwsgi_sock->bound = 1; uwsgi_sock->name = uwsgi_concat2(usa.sa_un.sun_path + abstract, ""); if (uwsgi.zerg) { uwsgi_log("uwsgi zerg socket %d attached to UNIX address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), usa.sa_un.sun_path + abstract, uwsgi_sock->fd); } else { uwsgi_log("uwsgi socket %d attached to UNIX address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), usa.sa_un.sun_path + abstract, uwsgi_sock->fd); } return; } if (!uwsgi_startswith(uwsgi_sock->name, "fd://", 5)) { if (atoi(uwsgi_sock->name + 5) == fd) { uwsgi_sock->fd = fd; uwsgi_sock->family = AF_UNIX; uwsgi_sock->bound = 1; uwsgi_sock->name = uwsgi_str(usa.sa_un.sun_path + abstract); uwsgi_log("uwsgi socket %d inherited UNIX address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd); } } else if (!strcmp(usa.sa_un.sun_path + abstract, uwsgi_sock->name + abstract)) { uwsgi_sock->fd = fd; uwsgi_sock->family = AF_UNIX; uwsgi_sock->bound = 1; uwsgi_log("uwsgi socket %d inherited UNIX address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd); } } else if (gsa.sa->sa_family == AF_INET) { char *computed_addr; char computed_port[6]; isa.sa_in = (struct sockaddr_in *) &usa; char ipv4a[INET_ADDRSTRLEN + 1]; memset(ipv4a, 0, INET_ADDRSTRLEN + 1); memset(computed_port, 0, 6); if (snprintf(computed_port, 6, "%d", ntohs(isa.sa_in->sin_port)) > 0) { if (inet_ntop(AF_INET, (const void *) &isa.sa_in->sin_addr.s_addr, ipv4a, INET_ADDRSTRLEN)) { if (!strcmp("0.0.0.0", ipv4a)) { computed_addr = uwsgi_concat2(":", computed_port); } else { computed_addr = uwsgi_concat3(ipv4a, ":", computed_port); } // is it a zerg ? if (uwsgi_sock->name == NULL) { uwsgi_sock->fd = fd; uwsgi_sock->family = AF_INET; uwsgi_sock->bound = 1; uwsgi_sock->name = uwsgi_concat2(computed_addr, ""); if (uwsgi.zerg) { uwsgi_log("uwsgi zerg socket %d attached to INET address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), computed_addr, uwsgi_sock->fd); } else { uwsgi_log("uwsgi socket %d attached to INET address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), computed_addr, uwsgi_sock->fd); } free(computed_addr); return; } char *asterisk = strchr(uwsgi_sock->name, '*'); int match = 1; if (asterisk) { asterisk[0] = 0; match = strncmp(computed_addr, uwsgi_sock->name, strlen(uwsgi_sock->name)); asterisk[0] = '*'; } else { if (!uwsgi_startswith(uwsgi_sock->name, "fd://", 5)) { if (atoi(uwsgi_sock->name + 5) == fd) { uwsgi_sock->fd = fd; uwsgi_sock->family = AF_INET; uwsgi_sock->bound = 1; uwsgi_sock->name = uwsgi_str(computed_addr); uwsgi_log("uwsgi socket %d inherited INET address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd); match = 1; } } else { match = strcmp(computed_addr, uwsgi_sock->name); } } if (!match) { uwsgi_sock->fd = fd; uwsgi_sock->family = AF_INET; uwsgi_sock->bound = 1; uwsgi_log("uwsgi socket %d inherited INET address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd); } free(computed_addr); } } } #ifdef UWSGI_IPV6 else if (gsa.sa->sa_family == AF_INET6) { char *computed_addr; char computed_port[6]; isa.sa_in6 = (struct sockaddr_in6 *) &usa; char ipv6a[INET6_ADDRSTRLEN + 1]; memset(ipv6a, 0, INET_ADDRSTRLEN + 1); memset(computed_port, 0, 6); int match = 0; if (snprintf(computed_port, 6, "%d", ntohs(isa.sa_in6->sin6_port)) > 0) { if (inet_ntop(AF_INET6, (const void *) &isa.sa_in6->sin6_addr.s6_addr, ipv6a, INET6_ADDRSTRLEN)) { uwsgi_log("ipv6a = %s\n", ipv6a); if (!strcmp("::", ipv6a)) { computed_addr = uwsgi_concat2("[::]:", computed_port); } else { computed_addr = uwsgi_concat4("[", ipv6a, "]:", computed_port); } // is it a zerg ? if (uwsgi_sock->name == NULL) { uwsgi_sock->fd = fd; uwsgi_sock->family = AF_INET6; uwsgi_sock->bound = 1; uwsgi_sock->name = uwsgi_concat2(computed_addr, ""); if (uwsgi.zerg) { uwsgi_log("uwsgi zerg socket %d attached to INET6 address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), computed_addr, uwsgi_sock->fd); } else { uwsgi_log("uwsgi socket %d attached to INET6 address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), computed_addr, uwsgi_sock->fd); } free(computed_addr); return; } if (!uwsgi_startswith(uwsgi_sock->name, "fd://", 5)) { if (atoi(uwsgi_sock->name + 5) == fd) { uwsgi_sock->fd = fd; uwsgi_sock->family = AF_INET6; uwsgi_sock->bound = 1; uwsgi_sock->name = uwsgi_str(computed_addr); uwsgi_log("uwsgi socket %d inherited INET address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd); match = 1; } } else { match = strcmp(computed_addr, uwsgi_sock->name); } if (!match) { uwsgi_sock->fd = fd; uwsgi_sock->family = AF_INET; uwsgi_sock->bound = 1; uwsgi_log("uwsgi socket %d inherited INET6 address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd); } free(computed_addr); } } } #endif } }
struct uwsgi_socket *uwsgi_new_socket(char *name) { struct uwsgi_socket *uwsgi_sock = uwsgi.sockets, *old_uwsgi_sock; struct sockaddr_in sin; socklen_t socket_type_len; if (!uwsgi_sock) { uwsgi.sockets = uwsgi_malloc(sizeof(struct uwsgi_socket)); uwsgi_sock = uwsgi.sockets; } else { while (uwsgi_sock) { old_uwsgi_sock = uwsgi_sock; uwsgi_sock = uwsgi_sock->next; } uwsgi_sock = uwsgi_malloc(sizeof(struct uwsgi_socket)); old_uwsgi_sock->next = uwsgi_sock; } memset(uwsgi_sock, 0, sizeof(struct uwsgi_socket)); uwsgi_sock->name = name; uwsgi_sock->fd = -1; if (!name) return uwsgi_sock; if (name[0] == '=') { int shared_socket = atoi(uwsgi_sock->name + 1); if (shared_socket >= 0) { struct uwsgi_socket *uss = uwsgi_get_shared_socket_by_num(shared_socket); if (!uss) { uwsgi_log("unable to use shared socket %d\n", shared_socket); exit(1); } uwsgi_sock->bound = 1; uwsgi_sock->shared = 1; uwsgi_sock->from_shared = shared_socket; return uwsgi_sock; } } if (!uwsgi_startswith(name, "fd://", 5)) { uwsgi_add_socket_from_fd(uwsgi_sock, atoi(name + 5)); return uwsgi_sock; } char *tcp_port = strrchr(name, ':'); if (tcp_port) { // INET socket, check for 0 port if (tcp_port[1] == 0 || tcp_port[1] == '0') { uwsgi_sock->fd = bind_to_tcp(name, uwsgi.listen_queue, tcp_port); uwsgi_sock->family = AF_INET; uwsgi_sock->bound = 1; uwsgi_sock->auto_port = 1; socket_type_len = sizeof(struct sockaddr_in); if (getsockname(uwsgi_sock->fd, (struct sockaddr *) &sin, &socket_type_len)) { uwsgi_error("getsockname()"); exit(1); } char *auto_port = uwsgi_num2str(ntohs(sin.sin_port)); uwsgi_sock->name = uwsgi_concat3n(name, tcp_port - name, ":", 1, auto_port, strlen(auto_port)); } // is it fd 0 ? else if (tcp_port[1] == ':') { uwsgi_sock->fd = 0; uwsgi_sock->family = AF_INET; uwsgi_sock->bound = 1; socket_type_len = sizeof(struct sockaddr_in); if (getsockname(0, (struct sockaddr *) &sin, &socket_type_len)) { uwsgi_error("getsockname()"); exit(1); } char *auto_port = uwsgi_num2str(ntohs(sin.sin_port)); char *auto_ip = inet_ntoa(sin.sin_addr); uwsgi_sock->name = uwsgi_concat3n(auto_ip, strlen(auto_ip), ":", 1, auto_port, strlen(auto_port)); } } return uwsgi_sock; }
void linux_namespace_jail() { char *ns_tmp_mountpoint = NULL, *ns_tmp_mountpoint2 = NULL; if (getpid() != 1) { uwsgi_log("your kernel does not support linux pid namespace\n"); exit(1); } char *ns_hostname = strchr(uwsgi.ns, ':'); if (ns_hostname) { ns_hostname[0] = 0; ns_hostname++; if (sethostname(ns_hostname, strlen(ns_hostname))) { uwsgi_error("sethostname()"); } } FILE *procmounts; char line[1024]; int unmounted = 1; char *delim0, *delim1; if (chdir(uwsgi.ns)) { uwsgi_error("chdir()"); exit(1); } if (strcmp(uwsgi.ns, "/")) { ns_tmp_mountpoint = uwsgi_concat2(uwsgi.ns, "/.uwsgi_ns_tmp_mountpoint"); mkdir(ns_tmp_mountpoint, S_IRWXU); ns_tmp_mountpoint2 = uwsgi_concat2(ns_tmp_mountpoint, "/.uwsgi_ns_tmp_mountpoint"); mkdir(ns_tmp_mountpoint2, S_IRWXU); if (mount(uwsgi.ns, ns_tmp_mountpoint, "none", MS_BIND, NULL)) { uwsgi_error("mount()"); } if (chdir(ns_tmp_mountpoint)) { uwsgi_error("chdir()"); } if (pivot_root(".", ns_tmp_mountpoint2)) { uwsgi_error("pivot_root()"); exit(1); } if (chdir("/")) { uwsgi_error("chdir()"); exit(1); } } uwsgi_log("remounting /proc\n"); if (mount("proc", "/proc", "proc", 0, NULL)) { uwsgi_error("mount()"); } struct uwsgi_string_list *usl = uwsgi.ns_keep_mount; while(usl) { // bind mounting keep-mount items char *keep_mountpoint = usl->value; char *destination = strchr(usl->value, ':'); if (destination) { keep_mountpoint = uwsgi_concat2n(usl->value, destination - usl->value, "", 0); } char *ks = uwsgi_concat2("/.uwsgi_ns_tmp_mountpoint", keep_mountpoint); if (!destination) { destination = usl->value; // skip first part of the name if under the jail if (!uwsgi_startswith(destination, uwsgi.ns, strlen(uwsgi.ns))) { if (uwsgi.ns[strlen(uwsgi.ns)-1] == '/') { destination += strlen(uwsgi.ns)-1; } else { destination += strlen(uwsgi.ns); } } } else { free(keep_mountpoint); destination++; } uwsgi_log("remounting %s to %s\n", ks+25, destination); if (mount(ks, destination, "none", MS_BIND, NULL)) { uwsgi_error("mount()"); } free(ks); usl = usl->next; } while (unmounted) { unmounted = 0; procmounts = fopen("/proc/self/mounts", "r"); while (fgets(line, 1024, procmounts) != NULL) { delim0 = strchr(line, ' '); delim0++; delim1 = strchr(delim0, ' '); *delim1 = 0; // and now check for keep-mounts if (uwsgi_is_a_keep_mount(delim0)) continue; if (!strcmp(delim0, "/") || !strcmp(delim0, "/proc")) continue; if (!umount(delim0)) { unmounted++; } } fclose(procmounts); } if (rmdir("/.uwsgi_ns_tmp_mountpoint/.uwsgi_ns_tmp_mountpoint")) { uwsgi_error("rmdir()"); } if (rmdir("/.uwsgi_ns_tmp_mountpoint")) { uwsgi_error("rmdir()"); } if (strcmp(uwsgi.ns, "/")) { free(ns_tmp_mountpoint2); free(ns_tmp_mountpoint); } }
ffi_type *uwsgi_libffi_get_type(char *what, size_t *skip) { if (!uwsgi_startswith(what, "int:", 4)) { *skip = 4; return &ffi_type_sint32;} if (!uwsgi_startswith(what, "sint:", 5)) { *skip = 5; return &ffi_type_sint32;} if (!uwsgi_startswith(what, "uint:", 5)) { *skip = 5;return &ffi_type_uint32;} return &ffi_type_pointer; }
void *uwsgi_request_subhandler_pump(struct wsgi_request *wsgi_req, struct uwsgi_app *wi) { PyObject *zero; int i; PyObject *pydictkey, *pydictvalue; char *port = memchr(wsgi_req->host, ':', wsgi_req->host_len); if (port) { zero = PyString_FromStringAndSize(wsgi_req->host, (port-wsgi_req->host)); PyDict_SetItemString(wsgi_req->async_environ, "server_name", zero); Py_DECREF(zero); zero = PyString_FromStringAndSize(port, wsgi_req->host_len-((port+1)-wsgi_req->host)); PyDict_SetItemString(wsgi_req->async_environ, "server_port", zero); Py_DECREF(zero); } else { zero = PyString_FromStringAndSize(wsgi_req->host, wsgi_req->host_len); PyDict_SetItemString(wsgi_req->async_environ, "server_name", zero); Py_DECREF(zero); zero = PyString_FromStringAndSize("80", 2); PyDict_SetItemString(wsgi_req->async_environ, "server_port", zero); Py_DECREF(zero); } zero = PyString_FromStringAndSize(wsgi_req->remote_addr, wsgi_req->remote_addr_len); PyDict_SetItemString(wsgi_req->async_environ, "remote_addr", zero); Py_DECREF(zero); zero = PyString_FromStringAndSize(wsgi_req->path_info, wsgi_req->path_info_len); PyDict_SetItemString(wsgi_req->async_environ, "uri", zero); Py_DECREF(zero); if (wsgi_req->query_string_len > 0) { zero = PyString_FromStringAndSize(wsgi_req->query_string, wsgi_req->query_string_len); PyDict_SetItemString(wsgi_req->async_environ, "query_string", zero); Py_DECREF(zero); } zero = PyString_FromStringAndSize(uwsgi_lower(wsgi_req->method, wsgi_req->method_len), wsgi_req->method_len); PyDict_SetItemString(wsgi_req->async_environ, "method", zero); Py_DECREF(zero); if (wsgi_req->post_cl > 0) { PyDict_SetItemString(wsgi_req->async_environ, "content_length", PyInt_FromLong(wsgi_req->post_cl)); if (wsgi_req->content_type_len > 0) { zero = PyString_FromStringAndSize(wsgi_req->content_type, wsgi_req->content_type_len); PyDict_SetItemString(wsgi_req->async_environ, "content_type", zero); Py_DECREF(zero); } } PyObject *headers = PyDict_New(); for (i = 0; i < wsgi_req->var_cnt; i += 2) { #ifdef UWSGI_DEBUG uwsgi_debug("%.*s: %.*s\n", wsgi_req->hvec[i].iov_len, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i+1].iov_len, wsgi_req->hvec[i+1].iov_base); #endif if (wsgi_req->hvec[i].iov_len < 6) continue; if (!uwsgi_startswith(wsgi_req->hvec[i].iov_base, "HTTP_", 5)) { (void) uwsgi_lower(wsgi_req->hvec[i].iov_base+5, wsgi_req->hvec[i].iov_len-5); #ifdef PYTHREE pydictkey = PyUnicode_DecodeLatin1(wsgi_req->hvec[i].iov_base+5, wsgi_req->hvec[i].iov_len-5, NULL); pydictvalue = PyUnicode_DecodeLatin1(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len, NULL); #else pydictkey = PyString_FromStringAndSize(wsgi_req->hvec[i].iov_base+5, wsgi_req->hvec[i].iov_len-5); pydictvalue = PyString_FromStringAndSize(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len); #endif PyObject *old_value = PyDict_GetItem(headers, pydictkey); if (old_value) { if (PyString_Check(old_value)) { PyObject *new_value = PyList_New(0); PyList_Append(new_value, old_value); old_value = new_value; PyDict_SetItem(headers, pydictkey, old_value); Py_DECREF(old_value); } PyList_Append(old_value, pydictvalue); } else { PyDict_SetItem(headers, pydictkey, pydictvalue); } Py_DECREF(pydictkey); Py_DECREF(pydictvalue); } } PyDict_SetItemString(wsgi_req->async_environ, "headers", headers); Py_DECREF(headers); // create wsgi.input custom object wsgi_req->async_input = (PyObject *) PyObject_New(uwsgi_Input, &uwsgi_InputType); ((uwsgi_Input*)wsgi_req->async_input)->wsgi_req = wsgi_req; PyDict_SetItemString(wsgi_req->async_environ, "body", wsgi_req->async_input); if (wsgi_req->scheme_len > 0) { zero = PyString_FromStringAndSize(wsgi_req->scheme, wsgi_req->scheme_len); } else if (wsgi_req->https_len > 0) { if (!strncasecmp(wsgi_req->https, "on", 2) || wsgi_req->https[0] == '1') { zero = PyString_FromString("https"); } else { zero = PyString_FromString("http"); } } else { zero = PyString_FromString("http"); } PyDict_SetItemString(wsgi_req->async_environ, "scheme", zero); Py_DECREF(zero); wsgi_req->async_app = wi->callable; // export .env only in non-threaded mode if (uwsgi.threads < 2) { PyDict_SetItemString(up.embedded_dict, "env", wsgi_req->async_environ); } PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.version", wi->uwsgi_version); if (uwsgi.cores > 1) { PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.core", PyInt_FromLong(wsgi_req->async_id)); } PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.node", wi->uwsgi_node); // call PyTuple_SetItem(wsgi_req->async_args, 0, wsgi_req->async_environ); return python_call(wsgi_req->async_app, wsgi_req->async_args, uwsgi.catch_exceptions, wsgi_req); }