int journal_file_verify( JournalFile *f, const char *key, usec_t *first_contained, usec_t *last_validated, usec_t *last_contained, bool show_progress) { int r; Object *o; uint64_t p = 0, last_epoch = 0, last_tag_realtime = 0, last_sealed_realtime = 0; uint64_t entry_seqnum = 0, entry_monotonic = 0, entry_realtime = 0; sd_id128_t entry_boot_id; bool entry_seqnum_set = false, entry_monotonic_set = false, entry_realtime_set = false, found_main_entry_array = false; uint64_t n_weird = 0, n_objects = 0, n_entries = 0, n_data = 0, n_fields = 0, n_data_hash_tables = 0, n_field_hash_tables = 0, n_entry_arrays = 0, n_tags = 0; usec_t last_usec = 0; int data_fd = -1, entry_fd = -1, entry_array_fd = -1; unsigned i; bool found_last = false; #ifdef HAVE_GCRYPT uint64_t last_tag = 0; #endif assert(f); if (key) { #ifdef HAVE_GCRYPT r = journal_file_parse_verification_key(f, key); if (r < 0) { log_error("Failed to parse seed."); return r; } #else return -ENOTSUP; #endif } else if (f->seal) return -ENOKEY; data_fd = open_tmpfile("/var/tmp", O_RDWR | O_CLOEXEC); if (data_fd < 0) { log_error_errno(errno, "Failed to create data file: %m"); r = -errno; goto fail; } entry_fd = open_tmpfile("/var/tmp", O_RDWR | O_CLOEXEC); if (entry_fd < 0) { log_error_errno(errno, "Failed to create entry file: %m"); r = -errno; goto fail; } entry_array_fd = open_tmpfile("/var/tmp", O_RDWR | O_CLOEXEC); if (entry_array_fd < 0) { log_error_errno(errno, "Failed to create entry array file: %m"); r = -errno; goto fail; } if (le32toh(f->header->compatible_flags) & ~HEADER_COMPATIBLE_SUPPORTED) { log_error("Cannot verify file with unknown extensions."); r = -ENOTSUP; goto fail; } for (i = 0; i < sizeof(f->header->reserved); i++) if (f->header->reserved[i] != 0) { error(offsetof(Header, reserved[i]), "Reserved field is non-zero"); r = -EBADMSG; goto fail; } /* First iteration: we go through all objects, verify the * superficial structure, headers, hashes. */ p = le64toh(f->header->header_size); for (;;) { /* Early exit if there are no objects in the file, at all */ if (le64toh(f->header->tail_object_offset) == 0) break; if (show_progress) draw_progress(scale_progress(0x7FFF, p, le64toh(f->header->tail_object_offset)), &last_usec); r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &o); if (r < 0) { error(p, "Invalid object"); goto fail; } if (p > le64toh(f->header->tail_object_offset)) { error(offsetof(Header, tail_object_offset), "Invalid tail object pointer"); r = -EBADMSG; goto fail; } n_objects ++; r = journal_file_object_verify(f, p, o); if (r < 0) { error(p, "Invalid object contents: %s", strerror(-r)); goto fail; } if ((o->object.flags & OBJECT_COMPRESSED_XZ) && (o->object.flags & OBJECT_COMPRESSED_LZ4)) { error(p, "Objected with double compression"); r = -EINVAL; goto fail; } if ((o->object.flags & OBJECT_COMPRESSED_XZ) && !JOURNAL_HEADER_COMPRESSED_XZ(f->header)) { error(p, "XZ compressed object in file without XZ compression"); r = -EBADMSG; goto fail; } if ((o->object.flags & OBJECT_COMPRESSED_LZ4) && !JOURNAL_HEADER_COMPRESSED_LZ4(f->header)) { error(p, "LZ4 compressed object in file without LZ4 compression"); r = -EBADMSG; goto fail; } switch (o->object.type) { case OBJECT_DATA: r = write_uint64(data_fd, p); if (r < 0) goto fail; n_data++; break; case OBJECT_FIELD: n_fields++; break; case OBJECT_ENTRY: if (JOURNAL_HEADER_SEALED(f->header) && n_tags <= 0) { error(p, "First entry before first tag"); r = -EBADMSG; goto fail; } r = write_uint64(entry_fd, p); if (r < 0) goto fail; if (le64toh(o->entry.realtime) < last_tag_realtime) { error(p, "Older entry after newer tag"); r = -EBADMSG; goto fail; } if (!entry_seqnum_set && le64toh(o->entry.seqnum) != le64toh(f->header->head_entry_seqnum)) { error(p, "Head entry sequence number incorrect"); r = -EBADMSG; goto fail; } if (entry_seqnum_set && entry_seqnum >= le64toh(o->entry.seqnum)) { error(p, "Entry sequence number out of synchronization"); r = -EBADMSG; goto fail; } entry_seqnum = le64toh(o->entry.seqnum); entry_seqnum_set = true; if (entry_monotonic_set && sd_id128_equal(entry_boot_id, o->entry.boot_id) && entry_monotonic > le64toh(o->entry.monotonic)) { error(p, "Entry timestamp out of synchronization"); r = -EBADMSG; goto fail; } entry_monotonic = le64toh(o->entry.monotonic); entry_boot_id = o->entry.boot_id; entry_monotonic_set = true; if (!entry_realtime_set && le64toh(o->entry.realtime) != le64toh(f->header->head_entry_realtime)) { error(p, "Head entry realtime timestamp incorrect"); r = -EBADMSG; goto fail; } entry_realtime = le64toh(o->entry.realtime); entry_realtime_set = true; n_entries ++; break; case OBJECT_DATA_HASH_TABLE: if (n_data_hash_tables > 1) { error(p, "More than one data hash table"); r = -EBADMSG; goto fail; } if (le64toh(f->header->data_hash_table_offset) != p + offsetof(HashTableObject, items) || le64toh(f->header->data_hash_table_size) != le64toh(o->object.size) - offsetof(HashTableObject, items)) { error(p, "header fields for data hash table invalid"); r = -EBADMSG; goto fail; } n_data_hash_tables++; break; case OBJECT_FIELD_HASH_TABLE: if (n_field_hash_tables > 1) { error(p, "More than one field hash table"); r = -EBADMSG; goto fail; } if (le64toh(f->header->field_hash_table_offset) != p + offsetof(HashTableObject, items) || le64toh(f->header->field_hash_table_size) != le64toh(o->object.size) - offsetof(HashTableObject, items)) { error(p, "Header fields for field hash table invalid"); r = -EBADMSG; goto fail; } n_field_hash_tables++; break; case OBJECT_ENTRY_ARRAY: r = write_uint64(entry_array_fd, p); if (r < 0) goto fail; if (p == le64toh(f->header->entry_array_offset)) { if (found_main_entry_array) { error(p, "More than one main entry array"); r = -EBADMSG; goto fail; } found_main_entry_array = true; } n_entry_arrays++; break; case OBJECT_TAG: if (!JOURNAL_HEADER_SEALED(f->header)) { error(p, "Tag object in file without sealing"); r = -EBADMSG; goto fail; } if (le64toh(o->tag.seqnum) != n_tags + 1) { error(p, "Tag sequence number out of synchronization"); r = -EBADMSG; goto fail; } if (le64toh(o->tag.epoch) < last_epoch) { error(p, "Epoch sequence out of synchronization"); r = -EBADMSG; goto fail; } #ifdef HAVE_GCRYPT if (f->seal) { uint64_t q, rt; debug(p, "Checking tag %"PRIu64"...", le64toh(o->tag.seqnum)); rt = f->fss_start_usec + o->tag.epoch * f->fss_interval_usec; if (entry_realtime_set && entry_realtime >= rt + f->fss_interval_usec) { error(p, "tag/entry realtime timestamp out of synchronization"); r = -EBADMSG; goto fail; } /* OK, now we know the epoch. So let's now set * it, and calculate the HMAC for everything * since the last tag. */ r = journal_file_fsprg_seek(f, le64toh(o->tag.epoch)); if (r < 0) goto fail; r = journal_file_hmac_start(f); if (r < 0) goto fail; if (last_tag == 0) { r = journal_file_hmac_put_header(f); if (r < 0) goto fail; q = le64toh(f->header->header_size); } else q = last_tag; while (q <= p) { r = journal_file_move_to_object(f, OBJECT_UNUSED, q, &o); if (r < 0) goto fail; r = journal_file_hmac_put_object(f, OBJECT_UNUSED, o, q); if (r < 0) goto fail; q = q + ALIGN64(le64toh(o->object.size)); } /* Position might have changed, let's reposition things */ r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &o); if (r < 0) goto fail; if (memcmp(o->tag.tag, gcry_md_read(f->hmac, 0), TAG_LENGTH) != 0) { error(p, "Tag failed verification"); r = -EBADMSG; goto fail; } f->hmac_running = false; last_tag_realtime = rt; last_sealed_realtime = entry_realtime; } last_tag = p + ALIGN64(le64toh(o->object.size)); #endif last_epoch = le64toh(o->tag.epoch); n_tags ++; break; default: n_weird ++; } if (p == le64toh(f->header->tail_object_offset)) { found_last = true; break; } p = p + ALIGN64(le64toh(o->object.size)); }; if (!found_last && le64toh(f->header->tail_object_offset) != 0) { error(le64toh(f->header->tail_object_offset), "Tail object pointer dead"); r = -EBADMSG; goto fail; } if (n_objects != le64toh(f->header->n_objects)) { error(offsetof(Header, n_objects), "Object number mismatch"); r = -EBADMSG; goto fail; } if (n_entries != le64toh(f->header->n_entries)) { error(offsetof(Header, n_entries), "Entry number mismatch"); r = -EBADMSG; goto fail; } if (JOURNAL_HEADER_CONTAINS(f->header, n_data) && n_data != le64toh(f->header->n_data)) { error(offsetof(Header, n_data), "Data number mismatch"); r = -EBADMSG; goto fail; } if (JOURNAL_HEADER_CONTAINS(f->header, n_fields) && n_fields != le64toh(f->header->n_fields)) { error(offsetof(Header, n_fields), "Field number mismatch"); r = -EBADMSG; goto fail; } if (JOURNAL_HEADER_CONTAINS(f->header, n_tags) && n_tags != le64toh(f->header->n_tags)) { error(offsetof(Header, n_tags), "Tag number mismatch"); r = -EBADMSG; goto fail; } if (JOURNAL_HEADER_CONTAINS(f->header, n_entry_arrays) && n_entry_arrays != le64toh(f->header->n_entry_arrays)) { error(offsetof(Header, n_entry_arrays), "Entry array number mismatch"); r = -EBADMSG; goto fail; } if (!found_main_entry_array && le64toh(f->header->entry_array_offset) != 0) { error(0, "Missing entry array"); r = -EBADMSG; goto fail; } if (entry_seqnum_set && entry_seqnum != le64toh(f->header->tail_entry_seqnum)) { error(offsetof(Header, tail_entry_seqnum), "Invalid tail seqnum"); r = -EBADMSG; goto fail; } if (entry_monotonic_set && (!sd_id128_equal(entry_boot_id, f->header->boot_id) || entry_monotonic != le64toh(f->header->tail_entry_monotonic))) { error(0, "Invalid tail monotonic timestamp"); r = -EBADMSG; goto fail; } if (entry_realtime_set && entry_realtime != le64toh(f->header->tail_entry_realtime)) { error(0, "Invalid tail realtime timestamp"); r = -EBADMSG; goto fail; } /* Second iteration: we follow all objects referenced from the * two entry points: the object hash table and the entry * array. We also check that everything referenced (directly * or indirectly) in the data hash table also exists in the * entry array, and vice versa. Note that we do not care for * unreferenced objects. We only care that everything that is * referenced is consistent. */ r = verify_entry_array(f, data_fd, n_data, entry_fd, n_entries, entry_array_fd, n_entry_arrays, &last_usec, show_progress); if (r < 0) goto fail; r = verify_hash_table(f, data_fd, n_data, entry_fd, n_entries, entry_array_fd, n_entry_arrays, &last_usec, show_progress); if (r < 0) goto fail; if (show_progress) flush_progress(); mmap_cache_close_fd(f->mmap, data_fd); mmap_cache_close_fd(f->mmap, entry_fd); mmap_cache_close_fd(f->mmap, entry_array_fd); safe_close(data_fd); safe_close(entry_fd); safe_close(entry_array_fd); if (first_contained) *first_contained = le64toh(f->header->head_entry_realtime); if (last_validated) *last_validated = last_sealed_realtime; if (last_contained) *last_contained = le64toh(f->header->tail_entry_realtime); return 0; fail: if (show_progress) flush_progress(); log_error("File corruption detected at %s:"OFSfmt" (of %llu bytes, %"PRIu64"%%).", f->path, p, (unsigned long long) f->last_stat.st_size, 100 * p / f->last_stat.st_size); if (data_fd >= 0) { mmap_cache_close_fd(f->mmap, data_fd); safe_close(data_fd); } if (entry_fd >= 0) { mmap_cache_close_fd(f->mmap, entry_fd); safe_close(entry_fd); } if (entry_array_fd >= 0) { mmap_cache_close_fd(f->mmap, entry_array_fd); safe_close(entry_array_fd); } return r; }
void log_close_syslog(void) { syslog_fd = safe_close(syslog_fd); }
int manager_llmnr_ipv4_tcp_fd(Manager *m) { union sockaddr_union sa = { .in.sin_family = AF_INET, .in.sin_port = htobe16(LLMNR_PORT), }; static const int one = 1, pmtu = IP_PMTUDISC_DONT; int r; assert(m); if (m->llmnr_ipv4_tcp_fd >= 0) return m->llmnr_ipv4_tcp_fd; m->llmnr_ipv4_tcp_fd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); if (m->llmnr_ipv4_tcp_fd < 0) return -errno; /* RFC 4795, section 2.5. requires setting the TTL of TCP streams to 1 */ r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_TTL, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->llmnr_ipv4_tcp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } /* Disable Don't-Fragment bit in the IP header */ r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu)); if (r < 0) { r = -errno; goto fail; } r = bind(m->llmnr_ipv4_tcp_fd, &sa.sa, sizeof(sa.in)); if (r < 0) { r = -errno; goto fail; } r = listen(m->llmnr_ipv4_tcp_fd, SOMAXCONN); if (r < 0) { r = -errno; goto fail; } r = sd_event_add_io(m->event, &m->llmnr_ipv4_tcp_event_source, m->llmnr_ipv4_tcp_fd, EPOLLIN, on_llmnr_stream, m); if (r < 0) goto fail; return m->llmnr_ipv4_tcp_fd; fail: m->llmnr_ipv4_tcp_fd = safe_close(m->llmnr_ipv4_tcp_fd); return r; } int manager_llmnr_ipv6_tcp_fd(Manager *m) { union sockaddr_union sa = { .in6.sin6_family = AF_INET6, .in6.sin6_port = htobe16(LLMNR_PORT), }; static const int one = 1; int r; assert(m); if (m->llmnr_ipv6_tcp_fd >= 0) return m->llmnr_ipv6_tcp_fd; m->llmnr_ipv6_tcp_fd = socket(AF_INET6, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); if (m->llmnr_ipv6_tcp_fd < 0) return -errno; /* RFC 4795, section 2.5. requires setting the TTL of TCP streams to 1 */ r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->llmnr_ipv6_tcp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = bind(m->llmnr_ipv6_tcp_fd, &sa.sa, sizeof(sa.in6)); if (r < 0) { r = -errno; goto fail; } r = listen(m->llmnr_ipv6_tcp_fd, SOMAXCONN); if (r < 0) { r = -errno; goto fail; } r = sd_event_add_io(m->event, &m->llmnr_ipv6_tcp_event_source, m->llmnr_ipv6_tcp_fd, EPOLLIN, on_llmnr_stream, m); if (r < 0) { r = -errno; goto fail; } return m->llmnr_ipv6_tcp_fd; fail: m->llmnr_ipv6_tcp_fd = safe_close(m->llmnr_ipv6_tcp_fd); return r; }
void free_request(request ** list_head_addr, request * req) { if (req->buffer_end) return; dequeue(list_head_addr, req); /* dequeue from ready or block list */ if (req->buffer_end) FD_CLR(req->fd, &block_write_fdset); else { switch (req->status) { case PIPE_WRITE: case WRITE: FD_CLR(req->fd, &block_write_fdset); break; case PIPE_READ: FD_CLR(req->data_fd, &block_read_fdset); break; case BODY_WRITE: FD_CLR(req->post_data_fd, &block_write_fdset); break; default: FD_CLR(req->fd, &block_read_fdset); } } if (req->logline) /* access log */ log_access(req); if (req->data_mem) munmap(req->data_mem, req->filesize); if (req->data_fd) close(req->data_fd); if (req->response_status >= 400) status.errors++; if ((req->keepalive == KA_ACTIVE) && (req->response_status < 400) && (++req->kacount < ka_max)) { request *conn; conn = new_request(); conn->fd = req->fd; conn->status = READ_HEADER; conn->header_line = conn->client_stream; conn->time_last = time_counter; conn->kacount = req->kacount; #ifdef SERVER_SSL conn->ssl = req->ssl; /*MN*/ #endif /*SERVER_SSL*/ /* we don't need to reset the fd parms for conn->fd because we already did that for req */ /* for log file and possible use by CGI programs */ strcpy(conn->remote_ip_addr, req->remote_ip_addr); /* for possible use by CGI programs */ conn->remote_port = req->remote_port; if (req->local_ip_addr) conn->local_ip_addr = strdup(req->local_ip_addr); status.requests++; if (conn->kacount + 1 == ka_max) SQUASH_KA(conn); conn->pipeline_start = req->client_stream_pos - req->pipeline_start; if (conn->pipeline_start) { memcpy(conn->client_stream, req->client_stream + req->pipeline_start, conn->pipeline_start); enqueue(&request_ready, conn); } else block_request(conn); } else{ if (req->fd != -1) { status.connections--; safe_close(req->fd); } req->fd = -1; #ifdef SERVER_SSL SSL_free(req->ssl); #endif /*SERVER_SSL*/ } if (req->cgi_env) { int i = COMMON_CGI_VARS; req->cgi_env[req->cgi_env_index]=0; while (req->cgi_env[i]) { free(req->cgi_env[i++]); } free(req->cgi_env); } if (req->pathname) free(req->pathname); if (req->path_info) free(req->path_info); if (req->path_translated) free(req->path_translated); if (req->script_name) free(req->script_name); if (req->query_string) free(req->query_string); if (req->local_ip_addr) free(req->local_ip_addr); /* * need to clean up if anything went wrong */ if (req->post_file_name) { unlink(req->post_file_name); free(req->post_file_name); close(req->post_data_fd); req->post_data_fd = -1; req->post_file_name = NULL; } enqueue(&request_free, req); /* put request on the free list */ return; }
int main(int argc, char *argv[]) { const char *cmdline[9]; int i = 0, r = EXIT_FAILURE, q; pid_t pid; siginfo_t status; _cleanup_udev_unref_ struct udev *udev = NULL; _cleanup_udev_device_unref_ struct udev_device *udev_device = NULL; const char *device, *type; bool root_directory; int progress_pipe[2] = { -1, -1 }; char dash_c[2+10+1]; struct stat st; if (argc > 2) { log_error("This program expects one or no arguments."); return EXIT_FAILURE; } log_set_target(LOG_TARGET_AUTO); log_parse_environment(); log_open(); umask(0022); parse_proc_cmdline(parse_proc_cmdline_item); test_files(); if (!arg_force && arg_skip) return 0; udev = udev_new(); if (!udev) { log_oom(); return EXIT_FAILURE; } if (argc > 1) { device = argv[1]; root_directory = false; if (stat(device, &st) < 0) { log_error("Failed to stat '%s': %m", device); return EXIT_FAILURE; } udev_device = udev_device_new_from_devnum(udev, 'b', st.st_rdev); if (!udev_device) { log_error("Failed to detect device %s", device); return EXIT_FAILURE; } } else { struct timespec times[2]; /* Find root device */ if (stat("/", &st) < 0) { log_error("Failed to stat() the root directory: %m"); return EXIT_FAILURE; } /* Virtual root devices don't need an fsck */ if (major(st.st_dev) == 0) return EXIT_SUCCESS; /* check if we are already writable */ times[0] = st.st_atim; times[1] = st.st_mtim; if (utimensat(AT_FDCWD, "/", times, 0) == 0) { log_info("Root directory is writable, skipping check."); return EXIT_SUCCESS; } udev_device = udev_device_new_from_devnum(udev, 'b', st.st_dev); if (!udev_device) { log_error("Failed to detect root device."); return EXIT_FAILURE; } device = udev_device_get_devnode(udev_device); if (!device) { log_error("Failed to detect device node of root directory."); return EXIT_FAILURE; } root_directory = true; } type = udev_device_get_property_value(udev_device, "ID_FS_TYPE"); if (type) { r = fsck_exists(type); if (r == -ENOENT) { log_info("fsck.%s doesn't exist, not checking file system on %s", type, device); return EXIT_SUCCESS; } else if (r < 0) log_warning("fsck.%s cannot be used for %s: %s", type, device, strerror(-r)); } if (arg_show_progress) if (pipe(progress_pipe) < 0) { log_error("pipe(): %m"); return EXIT_FAILURE; } cmdline[i++] = "/sbin/fsck"; cmdline[i++] = arg_repair; cmdline[i++] = "-T"; /* * Since util-linux v2.25 fsck uses /run/fsck/<diskname>.lock files. * The previous versions use flock for the device and conflict with * udevd, see https://bugs.freedesktop.org/show_bug.cgi?id=79576#c5 */ cmdline[i++] = "-l"; if (!root_directory) cmdline[i++] = "-M"; if (arg_force) cmdline[i++] = "-f"; if (progress_pipe[1] >= 0) { snprintf(dash_c, sizeof(dash_c), "-C%i", progress_pipe[1]); char_array_0(dash_c); cmdline[i++] = dash_c; } cmdline[i++] = device; cmdline[i++] = NULL; pid = fork(); if (pid < 0) { log_error("fork(): %m"); goto finish; } else if (pid == 0) { /* Child */ if (progress_pipe[0] >= 0) safe_close(progress_pipe[0]); execv(cmdline[0], (char**) cmdline); _exit(8); /* Operational error */ } progress_pipe[1] = safe_close(progress_pipe[1]); if (progress_pipe[0] >= 0) { process_progress(progress_pipe[0]); progress_pipe[0] = -1; } q = wait_for_terminate(pid, &status); if (q < 0) { log_error("waitid(): %s", strerror(-q)); goto finish; } if (status.si_code != CLD_EXITED || (status.si_status & ~1)) { if (status.si_code == CLD_KILLED || status.si_code == CLD_DUMPED) log_error("fsck terminated by signal %s.", signal_to_string(status.si_status)); else if (status.si_code == CLD_EXITED) log_error("fsck failed with error code %i.", status.si_status); else log_error("fsck failed due to unknown reason."); if (status.si_code == CLD_EXITED && (status.si_status & 2) && root_directory) /* System should be rebooted. */ start_target(SPECIAL_REBOOT_TARGET); else if (status.si_code == CLD_EXITED && (status.si_status & 6)) /* Some other problem */ start_target(SPECIAL_EMERGENCY_TARGET); else { r = EXIT_SUCCESS; log_warning("Ignoring error."); } } else r = EXIT_SUCCESS; if (status.si_code == CLD_EXITED && (status.si_status & 1)) touch("/run/systemd/quotacheck"); finish: safe_close_pair(progress_pipe); return r; }
int bot_unix_fd_send(bot_t * bot, int fd, bot_gmod_elm_t * gmod) { char tag[132]; char cmsg_buf[sizeof(struct cmsghdr) + sizeof(long)]; struct sockaddr_un un; struct cmsghdr *cmsg; struct msghdr msg; struct iovec iov[2]; int sock; int op; if (!bot) return -1; debug(NULL, "bot_unix_fd_send: Entered: %s\n", gi->fd_unix_path); if (!_sNULL(global_info.fd_unix_path) || fd < 0) return -1; bz2(un); strlcpy_buf(un.sun_path, global_info.fd_unix_path); un.sun_family = AF_UNIX; sock = socket(AF_UNIX, SOCK_STREAM, 0); if (sock < 0) { perror("socket "); return -1; } if (connect(sock, (struct sockaddr *)&un, sizeof(un)) < 0) { perror("connect "); goto cleanup; } op = BOT_UNIX_OP_FDPASS; iov[0].iov_len = sizeof(int); iov[0].iov_base = &op; bz(tag); snprintf_buf(tag, "%s,%i", bot->tag, bot->ID); if (gmod) { if (_sNULL(gmod->trigger_ext)) { strlcatfmt_buf(tag, ",%s", gmod->trigger_ext); } } iov[1].iov_len = sizeof(tag); iov[1].iov_base = tag; msg.msg_name = 0; msg.msg_namelen = 0; msg.msg_control = cmsg_buf; msg.msg_controllen = sizeof cmsg_buf; msg.msg_iov = (struct iovec *)&iov; msg.msg_iovlen = 2; msg.msg_flags = 0; cmsg = (struct cmsghdr *)cmsg_buf; cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; msg.msg_controllen = cmsg->cmsg_len = sizeof(struct cmsghdr) + sizeof(long); *(int *)((void *)cmsg + sizeof(struct cmsghdr)) = fd; sleep(1); if (sendmsg(sock, &msg, 0) < 0) { perror("sendmsg "); goto cleanup; } safe_close(sock); return 0; cleanup: if (sock) safe_close(sock); return -1; }
struct iovec iov[2] = { { .iov_base = &a->family, .iov_len = sizeof(a->family) }, { .iov_base = &a->address, .iov_len = FAMILY_ADDRESS_SIZE(a->family) }, }; r = writev(pair[1], iov, 2); if (r < 0) _exit(EXIT_FAILURE); } pair[1] = safe_close(pair[1]); _exit(EXIT_SUCCESS); } pair[1] = safe_close(pair[1]); for (;;) { int family; ssize_t n; union in_addr_union in_addr; struct iovec iov[2]; struct msghdr mh = { .msg_iov = iov, .msg_iovlen = 2, }; iov[0] = (struct iovec) { .iov_base = &family, .iov_len = sizeof(family) }; iov[1] = (struct iovec) { .iov_base = &in_addr, .iov_len = sizeof(in_addr) }; n = recvmsg(pair[0], &mh, 0);
int write_string_file(const char *fn, const char *line, WriteStringFileFlags flags) { _cleanup_fclose_ FILE *f = NULL; int q, r; assert(fn); assert(line); if (flags & WRITE_STRING_FILE_ATOMIC) { assert(flags & WRITE_STRING_FILE_CREATE); r = write_string_file_atomic(fn, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE)); if (r < 0) goto fail; return r; } if (flags & WRITE_STRING_FILE_CREATE) { f = fopen(fn, "we"); if (!f) { r = -errno; goto fail; } } else { int fd; /* We manually build our own version of fopen(..., "we") that * works without O_CREAT */ fd = open(fn, O_WRONLY|O_CLOEXEC|O_NOCTTY); if (fd < 0) { r = -errno; goto fail; } f = fdopen(fd, "we"); if (!f) { r = -errno; safe_close(fd); goto fail; } } r = write_string_stream(f, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE)); if (r < 0) goto fail; return 0; fail: if (!(flags & WRITE_STRING_FILE_VERIFY_ON_FAILURE)) return r; f = safe_fclose(f); /* OK, the operation failed, but let's see if the right * contents in place already. If so, eat up the error. */ q = verify_file(fn, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE)); if (q <= 0) return r; return 0; }
k3d::bool_t savable_application_window::on_delete_event(GdkEventAny* event) { safe_close(); return true; }
int main(int argc, char *argv[]) { enum { MODE_BISECT, MODE_CHART, } mode = MODE_BISECT; Type type = TYPE_KDBUS; int i, pair[2] = { -1, -1 }; _cleanup_free_ char *name = NULL, *bus_name = NULL, *address = NULL, *server_name = NULL; _cleanup_close_ int bus_ref = -1; const char *unique; cpu_set_t cpuset; size_t result; sd_bus *b; pid_t pid; int r; for (i = 1; i < argc; i++) { if (streq(argv[i], "chart")) { mode = MODE_CHART; continue; } else if (streq(argv[i], "legacy")) { type = TYPE_LEGACY; continue; } else if (streq(argv[i], "direct")) { type = TYPE_DIRECT; continue; } assert_se(parse_sec(argv[i], &arg_loop_usec) >= 0); } assert_se(!MODE_BISECT || TYPE_KDBUS); assert_se(arg_loop_usec > 0); if (type == TYPE_KDBUS) { assert_se(asprintf(&name, "deine-mutter-%u", (unsigned) getpid()) >= 0); bus_ref = bus_kernel_create_bus(name, false, &bus_name); if (bus_ref == -ENOENT) exit(EXIT_TEST_SKIP); assert_se(bus_ref >= 0); address = strappend("kernel:path=", bus_name); assert_se(address); } else if (type == TYPE_LEGACY) { const char *e; e = secure_getenv("DBUS_SESSION_BUS_ADDRESS"); assert_se(e); address = strdup(e); assert_se(address); } r = sd_bus_new(&b); assert_se(r >= 0); if (type == TYPE_DIRECT) { assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, pair) >= 0); r = sd_bus_set_fd(b, pair[0], pair[0]); assert_se(r >= 0); r = sd_bus_set_server(b, true, SD_ID128_NULL); assert_se(r >= 0); } else { r = sd_bus_set_address(b, address); assert_se(r >= 0); r = sd_bus_set_bus_client(b, true); assert_se(r >= 0); } r = sd_bus_start(b); assert_se(r >= 0); if (type != TYPE_DIRECT) { r = sd_bus_get_unique_name(b, &unique); assert_se(r >= 0); server_name = strdup(unique); assert_se(server_name); } sync(); setpriority(PRIO_PROCESS, 0, -19); pid = fork(); assert_se(pid >= 0); if (pid == 0) { CPU_ZERO(&cpuset); CPU_SET(0, &cpuset); pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); safe_close(bus_ref); sd_bus_unref(b); switch (mode) { case MODE_BISECT: client_bisect(address, server_name); break; case MODE_CHART: client_chart(type, address, server_name, pair[1]); break; } _exit(0); } CPU_ZERO(&cpuset); CPU_SET(1, &cpuset); pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); server(b, &result); if (mode == MODE_BISECT) printf("Copying/memfd are equally fast at %zu bytes\n", result); assert_se(waitpid(pid, NULL, 0) == pid); safe_close(pair[1]); sd_bus_unref(b); return 0; }
int take_etc_passwd_lock(const char *root) { struct flock flock = { .l_type = F_WRLCK, .l_whence = SEEK_SET, .l_start = 0, .l_len = 0, }; const char *path; int fd, r; /* This is roughly the same as lckpwdf(), but not as awful. We * don't want to use alarm() and signals, hence we implement * our own trivial version of this. * * Note that shadow-utils also takes per-database locks in * addition to lckpwdf(). However, we don't given that they * are redundant as they invoke lckpwdf() first and keep * it during everything they do. The per-database locks are * awfully racy, and thus we just won't do them. */ if (root) path = prefix_roota(root, "/etc/.pwd.lock"); else path = "/etc/.pwd.lock"; fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0600); if (fd < 0) return -errno; r = fcntl(fd, F_SETLKW, &flock); if (r < 0) { safe_close(fd); return -errno; } return fd; } bool valid_user_group_name(const char *u) { const char *i; long sz; /* Checks if the specified name is a valid user/group name. */ if (isempty(u)) return false; if (!(u[0] >= 'a' && u[0] <= 'z') && !(u[0] >= 'A' && u[0] <= 'Z') && u[0] != '_') return false; for (i = u+1; *i; i++) { if (!(*i >= 'a' && *i <= 'z') && !(*i >= 'A' && *i <= 'Z') && !(*i >= '0' && *i <= '9') && *i != '_' && *i != '-') return false; } sz = sysconf(_SC_LOGIN_NAME_MAX); assert_se(sz > 0); if ((size_t) (i-u) > (size_t) sz) return false; if ((size_t) (i-u) > UT_NAMESIZE - 1) return false; return true; } bool valid_user_group_name_or_id(const char *u) { /* Similar as above, but is also fine with numeric UID/GID specifications, as long as they are in the right * range, and not the invalid user ids. */ if (isempty(u)) return false; if (valid_user_group_name(u)) return true; return parse_uid(u, NULL) >= 0; } bool valid_gecos(const char *d) { if (!d) return false; if (!utf8_is_valid(d)) return false; if (string_has_cc(d, NULL)) return false; /* Colons are used as field separators, and hence not OK */ if (strchr(d, ':')) return false; return true; } bool valid_home(const char *p) { if (isempty(p)) return false; if (!utf8_is_valid(p)) return false; if (string_has_cc(p, NULL)) return false; if (!path_is_absolute(p)) return false; if (!path_is_safe(p)) return false; /* Colons are used as field separators, and hence not OK */ if (strchr(p, ':')) return false; return true; } int maybe_setgroups(size_t size, const gid_t *list) { int r; /* Check if setgroups is allowed before we try to drop all the auxiliary groups */ if (size == 0) { /* Dropping all aux groups? */ _cleanup_free_ char *setgroups_content = NULL; bool can_setgroups; r = read_one_line_file("/proc/self/setgroups", &setgroups_content); if (r == -ENOENT) /* Old kernels don't have /proc/self/setgroups, so assume we can use setgroups */ can_setgroups = true; else if (r < 0) return r; else can_setgroups = streq(setgroups_content, "allow"); if (!can_setgroups) { log_debug("Skipping setgroups(), /proc/self/setgroups is set to 'deny'"); return 0; } } if (setgroups(size, list) < 0) return -errno; return 0; }
static int automount_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) { Automount *a = AUTOMOUNT(u); int r; assert(a); assert(fds); if (streq(key, "state")) { AutomountState state; state = automount_state_from_string(value); if (state < 0) log_unit_debug(u, "Failed to parse state value: %s", value); else a->deserialized_state = state; } else if (streq(key, "result")) { AutomountResult f; f = automount_result_from_string(value); if (f < 0) log_unit_debug(u, "Failed to parse result value: %s", value); else if (f != AUTOMOUNT_SUCCESS) a->result = f; } else if (streq(key, "dev-id")) { unsigned d; if (safe_atou(value, &d) < 0) log_unit_debug(u, "Failed to parse dev-id value: %s", value); else a->dev_id = (unsigned) d; } else if (streq(key, "token")) { unsigned token; if (safe_atou(value, &token) < 0) log_unit_debug(u, "Failed to parse token value: %s", value); else { r = set_ensure_allocated(&a->tokens, NULL); if (r < 0) { log_oom(); return 0; } r = set_put(a->tokens, UINT_TO_PTR(token)); if (r < 0) log_unit_error_errno(u, r, "Failed to add token to set: %m"); } } else if (streq(key, "expire-token")) { unsigned token; if (safe_atou(value, &token) < 0) log_unit_debug(u, "Failed to parse token value: %s", value); else { r = set_ensure_allocated(&a->expire_tokens, NULL); if (r < 0) { log_oom(); return 0; } r = set_put(a->expire_tokens, UINT_TO_PTR(token)); if (r < 0) log_unit_error_errno(u, r, "Failed to add expire token to set: %m"); } } else if (streq(key, "pipe-fd")) { int fd; if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd)) log_unit_debug(u, "Failed to parse pipe-fd value: %s", value); else { safe_close(a->pipe_fd); a->pipe_fd = fdset_remove(fds, fd); } } else log_unit_debug(u, "Unknown serialization key: %s", key); return 0; }
static void automount_enter_waiting(Automount *a) { _cleanup_close_ int ioctl_fd = -1; int p[2] = { -1, -1 }; char name[sizeof("systemd-")-1 + DECIMAL_STR_MAX(pid_t) + 1]; char options[sizeof("fd=,pgrp=,minproto=5,maxproto=5,direct")-1 + DECIMAL_STR_MAX(int) + DECIMAL_STR_MAX(gid_t) + 1]; bool mounted = false; int r, dev_autofs_fd; struct stat st; assert(a); assert(a->pipe_fd < 0); assert(a->where); set_clear(a->tokens); r = unit_fail_if_symlink(UNIT(a), a->where); if (r < 0) goto fail; (void) mkdir_p_label(a->where, 0555); unit_warn_if_dir_nonempty(UNIT(a), a->where); dev_autofs_fd = open_dev_autofs(UNIT(a)->manager); if (dev_autofs_fd < 0) { r = dev_autofs_fd; goto fail; } if (pipe2(p, O_NONBLOCK|O_CLOEXEC) < 0) { r = -errno; goto fail; } xsprintf(options, "fd=%i,pgrp="PID_FMT",minproto=5,maxproto=5,direct", p[1], getpgrp()); xsprintf(name, "systemd-"PID_FMT, getpid()); if (mount(name, a->where, "autofs", 0, options) < 0) { r = -errno; goto fail; } mounted = true; p[1] = safe_close(p[1]); if (stat(a->where, &st) < 0) { r = -errno; goto fail; } ioctl_fd = open_ioctl_fd(dev_autofs_fd, a->where, st.st_dev); if (ioctl_fd < 0) { r = ioctl_fd; goto fail; } r = autofs_protocol(dev_autofs_fd, ioctl_fd); if (r < 0) goto fail; r = autofs_set_timeout(dev_autofs_fd, ioctl_fd, a->timeout_idle_usec); if (r < 0) goto fail; /* Autofs fun fact: * * Unless we close the ioctl fd here, for some weird reason * the direct mount will not receive events from the * kernel. */ r = sd_event_add_io(UNIT(a)->manager->event, &a->pipe_event_source, p[0], EPOLLIN, automount_dispatch_io, a); if (r < 0) goto fail; (void) sd_event_source_set_description(a->pipe_event_source, "automount-io"); a->pipe_fd = p[0]; a->dev_id = st.st_dev; automount_set_state(a, AUTOMOUNT_WAITING); return; fail: log_unit_error_errno(UNIT(a), r, "Failed to initialize automounter: %m"); safe_close_pair(p); if (mounted) { r = repeat_unmount(a->where, MNT_DETACH); if (r < 0) log_error_errno(r, "Failed to unmount, ignoring: %m"); } automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES); }
static void automount_shutdown(Manager *m) { assert(m); m->dev_autofs_fd = safe_close(m->dev_autofs_fd); }
static void manager_free(Manager *m) { Session *session; User *u; Device *d; Seat *s; Inhibitor *i; Button *b; assert(m); while ((session = hashmap_first(m->sessions))) session_free(session); while ((u = hashmap_first(m->users))) user_free(u); while ((d = hashmap_first(m->devices))) device_free(d); while ((s = hashmap_first(m->seats))) seat_free(s); while ((i = hashmap_first(m->inhibitors))) inhibitor_free(i); while ((b = hashmap_first(m->buttons))) button_free(b); hashmap_free(m->devices); hashmap_free(m->seats); hashmap_free(m->sessions); hashmap_free(m->users); hashmap_free(m->inhibitors); hashmap_free(m->buttons); hashmap_free(m->user_units); hashmap_free(m->session_units); sd_event_source_unref(m->idle_action_event_source); sd_event_source_unref(m->inhibit_timeout_source); sd_event_source_unref(m->scheduled_shutdown_timeout_source); sd_event_source_unref(m->nologin_timeout_source); sd_event_source_unref(m->wall_message_timeout_source); sd_event_source_unref(m->console_active_event_source); sd_event_source_unref(m->udev_seat_event_source); sd_event_source_unref(m->udev_device_event_source); sd_event_source_unref(m->udev_vcsa_event_source); sd_event_source_unref(m->udev_button_event_source); sd_event_source_unref(m->lid_switch_ignore_event_source); safe_close(m->console_active_fd); udev_monitor_unref(m->udev_seat_monitor); udev_monitor_unref(m->udev_device_monitor); udev_monitor_unref(m->udev_vcsa_monitor); udev_monitor_unref(m->udev_button_monitor); udev_unref(m->udev); if (m->unlink_nologin) (void) unlink("/run/nologin"); bus_verify_polkit_async_registry_free(m->polkit_registry); sd_bus_unref(m->bus); sd_event_unref(m->event); safe_close(m->reserve_vt_fd); strv_free(m->kill_only_users); strv_free(m->kill_exclude_users); free(m->scheduled_shutdown_type); free(m->scheduled_shutdown_tty); free(m->wall_message); free(m->action_job); free(m); }
int journal_file_fss_load(JournalFile *f) { int r, fd = -1; char *p = NULL; struct stat st; FSSHeader *m = NULL; sd_id128_t machine; assert(f); if (!f->seal) return 0; r = sd_id128_get_machine(&machine); if (r < 0) return r; if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss", SD_ID128_FORMAT_VAL(machine)) < 0) return -ENOMEM; fd = open(p, O_RDWR|O_CLOEXEC|O_NOCTTY, 0600); if (fd < 0) { if (errno != ENOENT) log_error_errno(errno, "Failed to open %s: %m", p); r = -errno; goto finish; } if (fstat(fd, &st) < 0) { r = -errno; goto finish; } if (st.st_size < (off_t) sizeof(FSSHeader)) { r = -ENODATA; goto finish; } m = mmap(NULL, PAGE_ALIGN(sizeof(FSSHeader)), PROT_READ, MAP_SHARED, fd, 0); if (m == MAP_FAILED) { m = NULL; r = -errno; goto finish; } if (memcmp(m->signature, FSS_HEADER_SIGNATURE, 8) != 0) { r = -EBADMSG; goto finish; } if (m->incompatible_flags != 0) { r = -EPROTONOSUPPORT; goto finish; } if (le64toh(m->header_size) < sizeof(FSSHeader)) { r = -EBADMSG; goto finish; } if (le64toh(m->fsprg_state_size) != FSPRG_stateinbytes(le16toh(m->fsprg_secpar))) { r = -EBADMSG; goto finish; } f->fss_file_size = le64toh(m->header_size) + le64toh(m->fsprg_state_size); if ((uint64_t) st.st_size < f->fss_file_size) { r = -ENODATA; goto finish; } if (!sd_id128_equal(machine, m->machine_id)) { r = -EHOSTDOWN; goto finish; } if (le64toh(m->start_usec) <= 0 || le64toh(m->interval_usec) <= 0) { r = -EBADMSG; goto finish; } f->fss_file = mmap(NULL, PAGE_ALIGN(f->fss_file_size), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if (f->fss_file == MAP_FAILED) { f->fss_file = NULL; r = -errno; goto finish; } f->fss_start_usec = le64toh(f->fss_file->start_usec); f->fss_interval_usec = le64toh(f->fss_file->interval_usec); f->fsprg_state = (uint8_t*) f->fss_file + le64toh(f->fss_file->header_size); f->fsprg_state_size = le64toh(f->fss_file->fsprg_state_size); r = 0; finish: if (m) munmap(m, PAGE_ALIGN(sizeof(FSSHeader))); safe_close(fd); free(p); return r; }
void bot_evhook_unix_read(int fd, short event, void *arg) { dlist_t *dptr; bot_unix_node_t *bun; struct cmsghdr *hdr; struct msghdr msg; char cmsg_buf[sizeof(struct cmsghdr) + sizeof(long)]; struct iovec iov[2]; int passed_fd; int op; char tag[132]; if (!arg) { safe_close(fd); return; } dptr = (dlist_t *) arg; if (!dptr->data) { safe_close(fd); return; } bun = (bot_unix_node_t *) dlist_data(dptr); debug(NULL, "bot_evhook_unix_read: Entered\n"); bz2(msg); iov[0].iov_base = &op; iov[0].iov_len = sizeof(op); iov[1].iov_base = &tag; iov[1].iov_len = sizeof(tag); msg.msg_iov = (struct iovec *)&iov; msg.msg_iovlen = 2; msg.msg_control = cmsg_buf; msg.msg_controllen = sizeof(cmsg_buf); errno = 0; if (recvmsg(fd, &msg, 0) < 0) { perror("recvmsg: Entered "); bot_unix_node_destroy(dptr); return; } bz2(iov); if (msg.msg_iovlen > 0) { if (op == BOT_UNIX_OP_FDPASS || BOT_UNIX_OP_TAG) { strlcpy_buf(bun->tag, tag); bun->op = op; } else if (op == BOT_UNIX_OP_CLOSE) { } } if (op == BOT_UNIX_OP_FDPASS) { hdr = CMSG_FIRSTHDR(&msg); if (!hdr) { goto fdpass_cleanup; } if (hdr->cmsg_level != SOL_SOCKET || hdr->cmsg_type != SCM_RIGHTS) { goto fdpass_cleanup; } passed_fd = *(int *)CMSG_DATA(hdr); bun->passed_fd = passed_fd; bot_find_and_set_fd(bun->tag, bun->passed_fd); fdpass_cleanup: bot_unix_node_destroy(dptr); } sleep(1); return; }
int main(int argc, char **argv) { const char *vc; char *vc_keymap = NULL; char *vc_keymap_toggle = NULL; char *vc_font = NULL; char *vc_font_map = NULL; char *vc_font_unimap = NULL; int fd = -1; bool utf8; pid_t font_pid = 0, keymap_pid = 0; bool font_copy = false; int r = EXIT_FAILURE; log_set_target(LOG_TARGET_AUTO); log_parse_environment(); log_open(); umask(0022); if (argv[1]) vc = argv[1]; else { vc = "/dev/tty0"; font_copy = true; } fd = open_terminal(vc, O_RDWR|O_CLOEXEC); if (fd < 0) { log_error("Failed to open %s: %m", vc); goto finish; } if (!is_vconsole(fd)) { log_error("Device %s is not a virtual console.", vc); goto finish; } utf8 = is_locale_utf8(); r = parse_env_file("/etc/vconsole.conf", NEWLINE, "KEYMAP", &vc_keymap, "KEYMAP_TOGGLE", &vc_keymap_toggle, "FONT", &vc_font, "FONT_MAP", &vc_font_map, "FONT_UNIMAP", &vc_font_unimap, NULL); if (r < 0 && r != -ENOENT) log_warning("Failed to read /etc/vconsole.conf: %s", strerror(-r)); /* Let the kernel command line override /etc/vconsole.conf */ if (detect_container(NULL) <= 0) { r = parse_env_file("/proc/cmdline", WHITESPACE, "vconsole.keymap", &vc_keymap, "vconsole.keymap.toggle", &vc_keymap_toggle, "vconsole.font", &vc_font, "vconsole.font.map", &vc_font_map, "vconsole.font.unimap", &vc_font_unimap, NULL); if (r < 0 && r != -ENOENT) log_warning("Failed to read /proc/cmdline: %s", strerror(-r)); } if (utf8) enable_utf8(fd); else disable_utf8(fd); r = EXIT_FAILURE; if (keymap_load(vc, vc_keymap, vc_keymap_toggle, utf8, &keymap_pid) >= 0 && font_load(vc, vc_font, vc_font_map, vc_font_unimap, &font_pid) >= 0) r = EXIT_SUCCESS; finish: if (keymap_pid > 0) wait_for_terminate_and_warn(KBD_LOADKEYS, keymap_pid); if (font_pid > 0) { wait_for_terminate_and_warn(KBD_SETFONT, font_pid); if (font_copy) font_copy_to_all_vcs(fd); } free(vc_keymap); free(vc_font); free(vc_font_map); free(vc_font_unimap); safe_close(fd); return r; }
static int server(sd_bus *bus) { int r; bool client1_gone = false, client2_gone = false; while (!client1_gone || !client2_gone) { _cleanup_bus_message_unref_ sd_bus_message *m = NULL; pid_t pid = 0; const char *label = NULL; r = sd_bus_process(bus, &m); if (r < 0) { log_error_errno(r, "Failed to process requests: %m"); goto fail; } if (r == 0) { r = sd_bus_wait(bus, (uint64_t) -1); if (r < 0) { log_error_errno(r, "Failed to wait: %m"); goto fail; } continue; } if (!m) continue; sd_bus_creds_get_pid(sd_bus_message_get_creds(m), &pid); sd_bus_creds_get_selinux_context(sd_bus_message_get_creds(m), &label); log_info("Got message! member=%s pid="PID_FMT" label=%s", strna(sd_bus_message_get_member(m)), pid, strna(label)); /* bus_message_dump(m); */ /* sd_bus_message_rewind(m, true); */ if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "LowerCase")) { const char *hello; _cleanup_free_ char *lowercase = NULL; r = sd_bus_message_read(m, "s", &hello); if (r < 0) { log_error_errno(r, "Failed to get parameter: %m"); goto fail; } lowercase = strdup(hello); if (!lowercase) { r = log_oom(); goto fail; } ascii_strlower(lowercase); r = sd_bus_reply_method_return(m, "s", lowercase); if (r < 0) { log_error_errno(r, "Failed to send reply: %m"); goto fail; } } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient1")) { r = sd_bus_reply_method_return(m, NULL); if (r < 0) { log_error_errno(r, "Failed to send reply: %m"); goto fail; } client1_gone = true; } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient2")) { r = sd_bus_reply_method_return(m, NULL); if (r < 0) { log_error_errno(r, "Failed to send reply: %m"); goto fail; } client2_gone = true; } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "Slow")) { sleep(1); r = sd_bus_reply_method_return(m, NULL); if (r < 0) { log_error_errno(r, "Failed to send reply: %m"); goto fail; } } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "FileDescriptor")) { int fd; static const char x = 'X'; r = sd_bus_message_read(m, "h", &fd); if (r < 0) { log_error_errno(r, "Failed to get parameter: %m"); goto fail; } log_info("Received fd=%d", fd); if (write(fd, &x, 1) < 0) { log_error_errno(errno, "Failed to write to fd: %m"); safe_close(fd); goto fail; } r = sd_bus_reply_method_return(m, NULL); if (r < 0) { log_error_errno(r, "Failed to send reply: %m"); goto fail; } } else if (sd_bus_message_is_method_call(m, NULL, NULL)) { r = sd_bus_reply_method_error( m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method.")); if (r < 0) { log_error_errno(r, "Failed to send reply: %m"); goto fail; } } } r = 0; fail: if (bus) { sd_bus_flush(bus); sd_bus_unref(bus); } return r; }
static int pick_uid(char **suggested_paths, const char *name, uid_t *ret_uid) { /* Find a suitable free UID. We use the following strategy to find a suitable UID: * * 1. Initially, we try to read the UID of a number of specified paths. If any of these UIDs works, we use * them. We use in order to increase the chance of UID reuse, if StateDirectory=, CacheDirectory= or * LogsDirectory= are used, as reusing the UID these directories are owned by saves us from having to * recursively chown() them to new users. * * 2. If that didn't yield a currently unused UID, we hash the user name, and try to use that. This should be * pretty good, as the use ris by default derived from the unit name, and hence the same service and same * user should usually get the same UID as long as our hashing doesn't clash. * * 3. Finally, if that didn't work, we randomly pick UIDs, until we find one that is empty. * * Since the dynamic UID space is relatively small we'll stop trying after 100 iterations, giving up. */ enum { PHASE_SUGGESTED, /* the first phase, reusing directory ownership UIDs */ PHASE_HASHED, /* the second phase, deriving a UID from the username by hashing */ PHASE_RANDOM, /* the last phase, randomly picking UIDs */ } phase = PHASE_SUGGESTED; static const uint8_t hash_key[] = { 0x37, 0x53, 0x7e, 0x31, 0xcf, 0xce, 0x48, 0xf5, 0x8a, 0xbb, 0x39, 0x57, 0x8d, 0xd9, 0xec, 0x59 }; unsigned n_tries = 100, current_suggested = 0; int r; (void) mkdir("/run/systemd/dynamic-uid", 0755); for (;;) { char lock_path[STRLEN("/run/systemd/dynamic-uid/") + DECIMAL_STR_MAX(uid_t) + 1]; _cleanup_close_ int lock_fd = -1; uid_t candidate; ssize_t l; if (--n_tries <= 0) /* Give up retrying eventually */ return -EBUSY; switch (phase) { case PHASE_SUGGESTED: { struct stat st; if (!suggested_paths || !suggested_paths[current_suggested]) { /* We reached the end of the suggested paths list, let's try by hashing the name */ phase = PHASE_HASHED; continue; } if (stat(suggested_paths[current_suggested++], &st) < 0) continue; /* We can't read the UID of this path, but that doesn't matter, just try the next */ candidate = st.st_uid; break; } case PHASE_HASHED: /* A static user by this name does not exist yet. Let's find a free ID then, and use that. We * start with a UID generated as hash from the user name. */ candidate = UID_CLAMP_INTO_RANGE(siphash24(name, strlen(name), hash_key)); /* If this one fails, we should proceed with random tries */ phase = PHASE_RANDOM; break; case PHASE_RANDOM: /* Pick another random UID, and see if that works for us. */ random_bytes(&candidate, sizeof(candidate)); candidate = UID_CLAMP_INTO_RANGE(candidate); break; default: assert_not_reached("unknown phase"); } /* Make sure whatever we picked here actually is in the right range */ if (!uid_is_dynamic(candidate)) continue; xsprintf(lock_path, "/run/systemd/dynamic-uid/" UID_FMT, candidate); for (;;) { struct stat st; lock_fd = open(lock_path, O_CREAT|O_RDWR|O_NOFOLLOW|O_CLOEXEC|O_NOCTTY, 0600); if (lock_fd < 0) return -errno; r = flock(lock_fd, LOCK_EX|LOCK_NB); /* Try to get a BSD file lock on the UID lock file */ if (r < 0) { if (IN_SET(errno, EBUSY, EAGAIN)) goto next; /* already in use */ return -errno; } if (fstat(lock_fd, &st) < 0) return -errno; if (st.st_nlink > 0) break; /* Oh, bummer, we got the lock, but the file was unlinked between the time we opened it and * got the lock. Close it, and try again. */ lock_fd = safe_close(lock_fd); } /* Some superficial check whether this UID/GID might already be taken by some static user */ if (getpwuid(candidate) || getgrgid((gid_t) candidate) || search_ipc(candidate, (gid_t) candidate) != 0) { (void) unlink(lock_path); continue; } /* Let's store the user name in the lock file, so that we can use it for looking up the username for a UID */ l = pwritev(lock_fd, (struct iovec[2]) { IOVEC_INIT_STRING(name), IOVEC_INIT((char[1]) { '\n' }, 1), }, 2, 0);
int bus_machine_method_get_addresses(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; Machine *m = userdata; int r; assert(message); assert(m); r = sd_bus_message_new_method_return(message, &reply); if (r < 0) return r; r = sd_bus_message_open_container(reply, 'a', "(iay)"); if (r < 0) return r; switch (m->class) { case MACHINE_HOST: { _cleanup_free_ struct local_address *addresses = NULL; struct local_address *a; int n, i; n = local_addresses(NULL, 0, AF_UNSPEC, &addresses); if (n < 0) return n; for (a = addresses, i = 0; i < n; a++, i++) { r = sd_bus_message_open_container(reply, 'r', "iay"); if (r < 0) return r; r = sd_bus_message_append(reply, "i", addresses[i].family); if (r < 0) return r; r = sd_bus_message_append_array(reply, 'y', &addresses[i].address, FAMILY_ADDRESS_SIZE(addresses[i].family)); if (r < 0) return r; r = sd_bus_message_close_container(reply); if (r < 0) return r; } break; } case MACHINE_CONTAINER: { _cleanup_close_pair_ int pair[2] = { -1, -1 }; _cleanup_free_ char *us = NULL, *them = NULL; _cleanup_close_ int netns_fd = -1; const char *p; siginfo_t si; pid_t child; r = readlink_malloc("/proc/self/ns/net", &us); if (r < 0) return r; p = procfs_file_alloca(m->leader, "ns/net"); r = readlink_malloc(p, &them); if (r < 0) return r; if (streq(us, them)) return sd_bus_error_setf(error, BUS_ERROR_NO_PRIVATE_NETWORKING, "Machine %s does not use private networking", m->name); r = namespace_open(m->leader, NULL, NULL, &netns_fd, NULL, NULL); if (r < 0) return r; if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0) return -errno; child = fork(); if (child < 0) return sd_bus_error_set_errnof(error, errno, "Failed to fork(): %m"); if (child == 0) { _cleanup_free_ struct local_address *addresses = NULL; struct local_address *a; int i, n; pair[0] = safe_close(pair[0]); r = namespace_enter(-1, -1, netns_fd, -1, -1); if (r < 0) _exit(EXIT_FAILURE); n = local_addresses(NULL, 0, AF_UNSPEC, &addresses); if (n < 0) _exit(EXIT_FAILURE); for (a = addresses, i = 0; i < n; a++, i++) { struct iovec iov[2] = { { .iov_base = &a->family, .iov_len = sizeof(a->family) }, { .iov_base = &a->address, .iov_len = FAMILY_ADDRESS_SIZE(a->family) }, }; r = writev(pair[1], iov, 2); if (r < 0) _exit(EXIT_FAILURE); } pair[1] = safe_close(pair[1]); _exit(EXIT_SUCCESS); }
bool MachineMonitor::monitor_disk() { LOG.trace("%s: start to monitor machine disks.", _name.c_str()); std::string monitor_file = std::string(_matrix_root) + "/" + "monitor.tmp"; int fd = open(monitor_file.c_str(), O_CREAT | O_NONBLOCK | O_TRUNC | O_WRONLY, S_IRWXU); if (fd == -1) { LOG.warn("%s: create monitor tmp file failed with errno [%d]", _name.c_str(), errno); return false; } const char dump[] = "matrix will control the world!"; if(safe_timed_write_all(fd, dump, sizeof(dump) - 1, DISK_IO_TIMEOUT_MS) != sizeof(dump) - 1) { LOG.warn("%s: write to monitor tmp file failed with errno [%d]", _name.c_str(), errno); safe_close(fd); return false; } if (safe_close(fd) != 0) { LOG.warn("%s: close monitor tmp file failed with errno [%d]", _name.c_str(), errno); return false; } fd = open(monitor_file.c_str(), O_NONBLOCK | O_RDONLY); if (fd == -1) { LOG.warn("%s: open monitor tmp file failed with errno [%d]", _name.c_str(), errno); return false; } char buffer[sizeof(dump)]; if(safe_timed_read_all(fd, buffer, sizeof(buffer), DISK_IO_TIMEOUT_MS) != sizeof(dump) - 1) { LOG.warn("%s: read from monitor tmp file failed with errno [%d]", _name.c_str(), errno); safe_close(fd); return false; } if (safe_close(fd) != 0) { LOG.warn("%s: close monitor tmp file failed with errno [%d]", _name.c_str(), errno); return false; } buffer[sizeof(buffer) -1 ] = '\0'; if (strcmp(buffer, dump) != 0) { LOG.warn("%s: monitor tmp file content does not match.", _name.c_str()); return false; } return true; }
static int process_progress(int fd) { _cleanup_fclose_ FILE *console = NULL, *f = NULL; usec_t last = 0; bool locked = false; int clear = 0; f = fdopen(fd, "r"); if (!f) { safe_close(fd); return -errno; } console = fopen("/dev/console", "we"); if (!console) return -ENOMEM; while (!feof(f)) { int pass, m; unsigned long cur, max; _cleanup_free_ char *device = NULL; double p; usec_t t; if (fscanf(f, "%i %lu %lu %ms", &pass, &cur, &max, &device) != 4) break; /* Only show one progress counter at max */ if (!locked) { if (flock(fileno(console), LOCK_EX|LOCK_NB) < 0) continue; locked = true; } /* Only update once every 50ms */ t = now(CLOCK_MONOTONIC); if (last + 50 * USEC_PER_MSEC > t) continue; last = t; p = percent(pass, cur, max); fprintf(console, "\r%s: fsck %3.1f%% complete...\r%n", device, p, &m); fflush(console); if (m > clear) clear = m; } if (clear > 0) { unsigned j; fputc('\r', console); for (j = 0; j < (unsigned) clear; j++) fputc(' ', console); fputc('\r', console); fflush(console); } return 0; }
static int raw_pull_make_local_copy(RawPull *i) { _cleanup_free_ char *tp = NULL; _cleanup_close_ int dfd = -1; const char *p; int r; assert(i); assert(i->raw_job); if (!i->local) return 0; if (i->raw_job->etag_exists) { /* We have downloaded this one previously, reopen it */ assert(i->raw_job->disk_fd < 0); i->raw_job->disk_fd = open(i->final_path, O_RDONLY|O_NOCTTY|O_CLOEXEC); if (i->raw_job->disk_fd < 0) return log_error_errno(errno, "Failed to open vendor image: %m"); } else { /* We freshly downloaded the image, use it */ assert(i->raw_job->disk_fd >= 0); if (lseek(i->raw_job->disk_fd, SEEK_SET, 0) == (off_t) -1) return log_error_errno(errno, "Failed to seek to beginning of vendor image: %m"); } p = strjoina(i->image_root, "/", i->local, ".raw"); if (i->force_local) (void) rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME); r = tempfn_random(p, NULL, &tp); if (r < 0) return log_oom(); dfd = open(tp, O_WRONLY|O_CREAT|O_EXCL|O_NOCTTY|O_CLOEXEC, 0664); if (dfd < 0) return log_error_errno(errno, "Failed to create writable copy of image: %m"); /* Turn off COW writing. This should greatly improve * performance on COW file systems like btrfs, since it * reduces fragmentation caused by not allowing in-place * writes. */ r = chattr_fd(dfd, FS_NOCOW_FL, FS_NOCOW_FL); if (r < 0) log_warning_errno(r, "Failed to set file attributes on %s: %m", tp); r = copy_bytes(i->raw_job->disk_fd, dfd, (uint64_t) -1, COPY_REFLINK); if (r < 0) { unlink(tp); return log_error_errno(r, "Failed to make writable copy of image: %m"); } (void) copy_times(i->raw_job->disk_fd, dfd); (void) copy_xattr(i->raw_job->disk_fd, dfd); dfd = safe_close(dfd); r = rename(tp, p); if (r < 0) { r = log_error_errno(errno, "Failed to move writable image into place: %m"); unlink(tp); return r; } log_info("Created new local image '%s'.", i->local); if (i->roothash) { r = raw_pull_copy_auxiliary_file(i, ".roothash", &i->roothash_path); if (r < 0) return r; } if (i->settings) { r = raw_pull_copy_auxiliary_file(i, ".nspawn", &i->settings_path); if (r < 0) return r; } return 0; }
void log_close_kmsg(void) { kmsg_fd = safe_close(kmsg_fd); }
static void raw_pull_job_on_finished(PullJob *j) { RawPull *i; int r; assert(j); assert(j->userdata); i = j->userdata; if (j == i->roothash_job) { if (j->error != 0) log_info_errno(j->error, "Root hash file could not be retrieved, proceeding without."); } else if (j == i->settings_job) { if (j->error != 0) log_info_errno(j->error, "Settings file could not be retrieved, proceeding without."); } else if (j->error != 0 && j != i->signature_job) { if (j == i->checksum_job) log_error_errno(j->error, "Failed to retrieve SHA256 checksum, cannot verify. (Try --verify=no?)"); else log_error_errno(j->error, "Failed to retrieve image file. (Wrong URL?)"); r = j->error; goto finish; } /* This is invoked if either the download completed * successfully, or the download was skipped because we * already have the etag. In this case ->etag_exists is * true. * * We only do something when we got all three files */ if (!raw_pull_is_done(i)) return; if (i->signature_job && i->checksum_job->style == VERIFICATION_PER_DIRECTORY && i->signature_job->error != 0) { log_error_errno(j->error, "Failed to retrieve signature file, cannot verify. (Try --verify=no?)"); r = i->signature_job->error; goto finish; } if (i->roothash_job) i->roothash_job->disk_fd = safe_close(i->roothash_job->disk_fd); if (i->settings_job) i->settings_job->disk_fd = safe_close(i->settings_job->disk_fd); r = raw_pull_determine_path(i, ".raw", &i->final_path); if (r < 0) goto finish; if (!i->raw_job->etag_exists) { /* This is a new download, verify it, and move it into place */ assert(i->raw_job->disk_fd >= 0); raw_pull_report_progress(i, RAW_VERIFYING); r = pull_verify(i->raw_job, i->roothash_job, i->settings_job, i->checksum_job, i->signature_job); if (r < 0) goto finish; raw_pull_report_progress(i, RAW_UNPACKING); r = raw_pull_maybe_convert_qcow2(i); if (r < 0) goto finish; raw_pull_report_progress(i, RAW_FINALIZING); r = import_make_read_only_fd(i->raw_job->disk_fd); if (r < 0) goto finish; r = rename_noreplace(AT_FDCWD, i->temp_path, AT_FDCWD, i->final_path); if (r < 0) { log_error_errno(r, "Failed to rename raw file to %s: %m", i->final_path); goto finish; } i->temp_path = mfree(i->temp_path); if (i->roothash_job && i->roothash_job->error == 0) { r = raw_pull_rename_auxiliary_file(i, ".roothash", &i->roothash_temp_path, &i->roothash_path); if (r < 0) goto finish; } if (i->settings_job && i->settings_job->error == 0) { r = raw_pull_rename_auxiliary_file(i, ".nspawn", &i->settings_temp_path, &i->settings_path); if (r < 0) goto finish; } } raw_pull_report_progress(i, RAW_COPYING); r = raw_pull_make_local_copy(i); if (r < 0) goto finish; r = 0; finish: if (i->on_finished) i->on_finished(i, r, i->userdata); else sd_event_exit(i->event, r); }
int manager_llmnr_ipv4_udp_fd(Manager *m) { union sockaddr_union sa = { .in.sin_family = AF_INET, .in.sin_port = htobe16(LLMNR_PORT), }; static const int one = 1, pmtu = IP_PMTUDISC_DONT, ttl = 255; int r; assert(m); if (m->llmnr_ipv4_udp_fd >= 0) return m->llmnr_ipv4_udp_fd; m->llmnr_ipv4_udp_fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); if (m->llmnr_ipv4_udp_fd < 0) return -errno; /* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */ r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MULTICAST_LOOP, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->llmnr_ipv4_udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } /* Disable Don't-Fragment bit in the IP header */ r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu)); if (r < 0) { r = -errno; goto fail; } r = bind(m->llmnr_ipv4_udp_fd, &sa.sa, sizeof(sa.in)); if (r < 0) { r = -errno; goto fail; } r = sd_event_add_io(m->event, &m->llmnr_ipv4_udp_event_source, m->llmnr_ipv4_udp_fd, EPOLLIN, on_llmnr_packet, m); if (r < 0) goto fail; return m->llmnr_ipv4_udp_fd; fail: m->llmnr_ipv4_udp_fd = safe_close(m->llmnr_ipv4_udp_fd); return r; } int manager_llmnr_ipv6_udp_fd(Manager *m) { union sockaddr_union sa = { .in6.sin6_family = AF_INET6, .in6.sin6_port = htobe16(LLMNR_PORT), }; static const int one = 1, ttl = 255; int r; assert(m); if (m->llmnr_ipv6_udp_fd >= 0) return m->llmnr_ipv6_udp_fd; m->llmnr_ipv6_udp_fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); if (m->llmnr_ipv6_udp_fd < 0) return -errno; r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl)); if (r < 0) { r = -errno; goto fail; } /* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */ r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->llmnr_ipv6_udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = bind(m->llmnr_ipv6_udp_fd, &sa.sa, sizeof(sa.in6)); if (r < 0) { r = -errno; goto fail; } r = sd_event_add_io(m->event, &m->llmnr_ipv6_udp_event_source, m->llmnr_ipv6_udp_fd, EPOLLIN, on_llmnr_packet, m); if (r < 0) { r = -errno; goto fail; } return m->llmnr_ipv6_udp_fd; fail: m->llmnr_ipv6_udp_fd = safe_close(m->llmnr_ipv6_udp_fd); return r; } static int on_llmnr_stream_packet(DnsStream *s) { DnsScope *scope; assert(s); scope = manager_find_scope(s->manager, s->read_packet); if (!scope) { log_warning("Got LLMNR TCP packet on unknown scope. Ignroing."); return 0; } if (dns_packet_validate_query(s->read_packet) > 0) { log_debug("Got query packet for id %u", DNS_PACKET_ID(s->read_packet)); dns_scope_process_query(scope, s, s->read_packet); /* If no reply packet was set, we free the stream */ if (s->write_packet) return 0; } else log_debug("Invalid LLMNR TCP packet."); dns_stream_free(s); return 0; } static int on_llmnr_stream(sd_event_source *s, int fd, uint32_t revents, void *userdata) { DnsStream *stream; Manager *m = userdata; int cfd, r; cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC); if (cfd < 0) { if (errno == EAGAIN || errno == EINTR) return 0; return -errno; } r = dns_stream_new(m, &stream, DNS_PROTOCOL_LLMNR, cfd); if (r < 0) { safe_close(cfd); return r; } stream->on_packet = on_llmnr_stream_packet; return 0; }
static void busname_close_fd(BusName *n) { assert(n); n->starter_event_source = sd_event_source_unref(n->starter_event_source); n->starter_fd = safe_close(n->starter_fd); }
static void clock_state_release(ClockState *sp) { clock_state_release_timerfd(sp); sp->inotify_event_source = sd_event_source_unref(sp->inotify_event_source); sp->inotify_fd = safe_close(sp->inotify_fd); }
/* ---------------------------------------------------------------------- */ void PHRQ_io:: output_close(void) /* ---------------------------------------------------------------------- */ { safe_close(&output_ostream); }