static void test_cg_get_keyed_attribute(void) { _cleanup_free_ char *val = NULL; char *vals3[3] = {}, *vals3a[3] = {}; int i, r; r = cg_get_keyed_attribute("cpu", "/init.scope", "no_such_file", STRV_MAKE("no_such_attr"), &val); if (r == -ENOMEDIUM) { log_info_errno(r, "Skipping most of %s, /sys/fs/cgroup not accessible: %m", __func__); return; } assert_se(r == -ENOENT); assert_se(val == NULL); if (access("/sys/fs/cgroup/init.scope/cpu.stat", R_OK) < 0) { log_info_errno(errno, "Skipping most of %s, /init.scope/cpu.stat not accessible: %m", __func__); return; } assert_se(cg_get_keyed_attribute("cpu", "/init.scope", "cpu.stat", STRV_MAKE("no_such_attr"), &val) == -ENXIO); assert_se(val == NULL); assert_se(cg_get_keyed_attribute("cpu", "/init.scope", "cpu.stat", STRV_MAKE("usage_usec"), &val) == 0); log_info("cpu /init.scope cpu.stat [usage_usec] → \"%s\"", val); assert_se(cg_get_keyed_attribute("cpu", "/init.scope", "cpu.stat", STRV_MAKE("usage_usec", "no_such_attr"), vals3) == -ENXIO); assert_se(cg_get_keyed_attribute("cpu", "/init.scope", "cpu.stat", STRV_MAKE("usage_usec", "usage_usec"), vals3) == -ENXIO); assert_se(cg_get_keyed_attribute("cpu", "/init.scope", "cpu.stat", STRV_MAKE("usage_usec", "user_usec", "system_usec"), vals3) == 0); log_info("cpu /init.scope cpu.stat [usage_usec user_usec system_usec] → \"%s\", \"%s\", \"%s\"", vals3[0], vals3[1], vals3[2]); assert_se(cg_get_keyed_attribute("cpu", "/init.scope", "cpu.stat", STRV_MAKE("system_usec", "user_usec", "usage_usec"), vals3a) == 0); log_info("cpu /init.scope cpu.stat [system_usec user_usec usage_usec] → \"%s\", \"%s\", \"%s\"", vals3a[0], vals3a[1], vals3a[2]); for (i = 0; i < 3; i++) { free(vals3[i]); free(vals3a[i]); } }
static void on_finished(DckImport *import, int error, void *userdata) { sd_event *event = userdata; assert(import); if (error == 0) log_info("Operation completed successfully."); else log_info_errno(error, "Operation failed: %m"); sd_event_exit(event, error); }
static int pipe_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) { int *counter = userdata; int r; (*counter) --; r = sd_rtnl_message_get_errno(m); log_info_errno(r, "%d left in pipe. got reply: %m", *counter); assert_se(r >= 0); return 1; }
static void test_get_group_creds_one(const char *id, const char *name, gid_t gid) { gid_t rgid = GID_INVALID; int r; log_info("/* %s(\"%s\", \"%s\", "GID_FMT") */", __func__, id, name, gid); r = get_group_creds(&id, &rgid, 0); log_info_errno(r, "got \"%s\", "GID_FMT": %m", id, rgid); if (!synthesize_nobody() && streq(name, NOBODY_GROUP_NAME)) { log_info("(skipping detailed tests because nobody is not synthesized)"); return; } assert_se(r == 0); assert_se(streq_ptr(id, name)); assert_se(rgid == gid); }
static void test_decompress_startswith(int compression, compress_blob_t compress, decompress_sw_t decompress_sw, const char *data, size_t data_len, bool may_fail) { char compressed[512]; size_t csize = 512; size_t usize = 0; _cleanup_free_ char *decompressed = NULL; int r; log_info("/* testing decompress_startswith with %s on %s text*/", object_compressed_to_string(compression), data); r = compress(data, data_len, compressed, &csize); if (r == -ENOBUFS) { log_info_errno(r, "compression failed: %m"); assert_se(may_fail); return; } assert_se(r == 0); assert_se(decompress_sw(compressed, csize, (void **) &decompressed, &usize, data, strlen(data), '\0') > 0); assert_se(decompress_sw(compressed, csize, (void **) &decompressed, &usize, data, strlen(data), 'w') == 0); assert_se(decompress_sw(compressed, csize, (void **) &decompressed, &usize, "barbarbar", 9, ' ') == 0); assert_se(decompress_sw(compressed, csize, (void **) &decompressed, &usize, data, strlen(data), '\0') > 0); }
static int parse_argv(int argc, char *argv[]) { static const struct option options[] = { { "timeout", required_argument, NULL, 't' }, { "exit-if-exists", required_argument, NULL, 'E' }, { "version", no_argument, NULL, 'V' }, { "help", no_argument, NULL, 'h' }, { "seq-start", required_argument, NULL, 's' }, /* removed */ { "seq-end", required_argument, NULL, 'e' }, /* removed */ { "quiet", no_argument, NULL, 'q' }, /* removed */ {} }; int c, r; while ((c = getopt_long(argc, argv, "t:E:Vhs:e:q", options, NULL)) >= 0) { switch (c) { case 't': r = parse_sec(optarg, &arg_timeout); if (r < 0) return log_error_errno(r, "Failed to parse timeout value '%s': %m", optarg); break; case 'E': arg_exists = optarg; break; case 'V': return print_version(); case 'h': return help(); case 's': case 'e': case 'q': return log_info_errno(SYNTHETIC_ERRNO(EINVAL), "Option -%c no longer supported.", c); case '?': return -EINVAL; default: assert_not_reached("Unknown option."); } } return 1; }
static void test_compress_decompress(int compression, compress_blob_t compress, decompress_blob_t decompress, const char *data, size_t data_len, bool may_fail) { char compressed[512]; size_t csize = 512; size_t usize = 0; _cleanup_free_ char *decompressed = NULL; int r; log_info("/* testing %s %s blob compression/decompression */", object_compressed_to_string(compression), data); r = compress(data, data_len, compressed, &csize); if (r == -ENOBUFS) { log_info_errno(r, "compression failed: %m"); assert_se(may_fail); } else { assert_se(r == 0); r = decompress(compressed, csize, (void **) &decompressed, &usize, &csize, 0); assert_se(r == 0); assert_se(decompressed); assert_se(memcmp(decompressed, data, data_len) == 0); } r = decompress("garbage", 7, (void **) &decompressed, &usize, &csize, 0); assert_se(r < 0); /* make sure to have the minimal lz4 compressed size */ r = decompress("00000000\1g", 9, (void **) &decompressed, &usize, &csize, 0); assert_se(r < 0); r = decompress("\100000000g", 9, (void **) &decompressed, &usize, &csize, 0); assert_se(r < 0); memzero(decompressed, usize); }
static int process_event(Server *s, struct epoll_event *ev) { int r; Fifo *f; assert(s); if (!(ev->events & EPOLLIN)) { log_info("Got invalid event from epoll. (3)"); return -EIO; } f = (Fifo*) ev->data.ptr; r = fifo_process(f); if (r < 0) { log_info_errno(r, "Got error on fifo: %m"); fifo_free(f); return r; } return 0; }
static void test_get_user_creds_one(const char *id, const char *name, uid_t uid, gid_t gid, const char *home, const char *shell) { const char *rhome = NULL; const char *rshell = NULL; uid_t ruid = UID_INVALID; gid_t rgid = GID_INVALID; int r; log_info("/* %s(\"%s\", \"%s\", "UID_FMT", "GID_FMT", \"%s\", \"%s\") */", __func__, id, name, uid, gid, home, shell); r = get_user_creds(&id, &ruid, &rgid, &rhome, &rshell, 0); log_info_errno(r, "got \"%s\", "UID_FMT", "GID_FMT", \"%s\", \"%s\": %m", id, ruid, rgid, strnull(rhome), strnull(rshell)); if (!synthesize_nobody() && streq(name, NOBODY_USER_NAME)) { log_info("(skipping detailed tests because nobody is not synthesized)"); return; } assert_se(r == 0); assert_se(streq_ptr(id, name)); assert_se(ruid == uid); assert_se(rgid == gid); assert_se(path_equal(rhome, home)); assert_se(path_equal(rshell, shell)); }
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); }
static void test_nameinfo_pretty(void) { _cleanup_free_ char *stdin_name = NULL, *localhost = NULL; union sockaddr_union s = { .in.sin_family = AF_INET, .in.sin_port = 0, .in.sin_addr.s_addr = htonl(INADDR_ANY), }; int r; union sockaddr_union c = {}; socklen_t slen = sizeof(c.in), clen = sizeof(c.in); _cleanup_close_ int sfd = -1, cfd = -1; r = getnameinfo_pretty(STDIN_FILENO, &stdin_name); log_info_errno(r, "No connection remote: %m"); assert_se(r < 0); sfd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, 0); assert_se(sfd >= 0); assert_se(bind(sfd, &s.sa, sizeof(s.in)) == 0); /* find out the port number */ assert_se(getsockname(sfd, &s.sa, &slen) == 0); assert_se(listen(sfd, 1) == 0); assert_se(asynchronous_job(connect_thread, &s) == 0); log_debug("Accepting new connection on fd:%d", sfd); cfd = accept4(sfd, &c.sa, &clen, SOCK_CLOEXEC); assert_se(cfd >= 0); r = getnameinfo_pretty(cfd, &localhost); log_info("Connection from %s", localhost); assert_se(r == 0); } static void test_sockaddr_equal(void) { union sockaddr_union a = { .in.sin_family = AF_INET, .in.sin_port = 0, .in.sin_addr.s_addr = htonl(INADDR_ANY), }; union sockaddr_union b = { .in.sin_family = AF_INET, .in.sin_port = 0, .in.sin_addr.s_addr = htonl(INADDR_ANY), }; union sockaddr_union c = { .in.sin_family = AF_INET, .in.sin_port = 0, .in.sin_addr.s_addr = htonl(1234), }; union sockaddr_union d = { .in6.sin6_family = AF_INET6, .in6.sin6_port = 0, .in6.sin6_addr = IN6ADDR_ANY_INIT, }; assert_se(sockaddr_equal(&a, &a)); assert_se(sockaddr_equal(&a, &b)); assert_se(sockaddr_equal(&d, &d)); assert_se(!sockaddr_equal(&a, &c)); assert_se(!sockaddr_equal(&b, &c)); } int main(int argc, char *argv[]) { log_set_max_level(LOG_DEBUG); test_socket_address_parse(); test_socket_address_parse_netlink(); test_socket_address_equal(); test_socket_address_get_path(); test_socket_address_is(); test_socket_address_is_netlink(); test_in_addr_is_null(); test_in_addr_prefix_intersect(); test_in_addr_prefix_next(); test_in_addr_to_string(); test_nameinfo_pretty(); test_sockaddr_equal(); return 0; }
static void tar_pull_job_on_finished(PullJob *j) { TarPull *i; int r; assert(j); assert(j->userdata); i = j->userdata; 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. */ if (!tar_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; } i->tar_job->disk_fd = safe_close(i->tar_job->disk_fd); if (i->settings_job) i->settings_job->disk_fd = safe_close(i->settings_job->disk_fd); r = tar_pull_determine_path(i, NULL, &i->final_path); if (r < 0) goto finish; if (i->tar_pid > 0) { r = wait_for_terminate_and_check("tar", i->tar_pid, WAIT_LOG); i->tar_pid = 0; if (r < 0) goto finish; if (r != EXIT_SUCCESS) { r = -EIO; goto finish; } } if (!i->tar_job->etag_exists) { /* This is a new download, verify it, and move it into place */ tar_pull_report_progress(i, TAR_VERIFYING); r = pull_verify(i->tar_job, NULL, i->settings_job, i->checksum_job, i->signature_job); if (r < 0) goto finish; tar_pull_report_progress(i, TAR_FINALIZING); r = import_make_read_only(i->temp_path); 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 to final image name to %s: %m", i->final_path); goto finish; } i->temp_path = mfree(i->temp_path); if (i->settings_job && i->settings_job->error == 0) { /* Also move the settings file into place, if it exists. Note that we do so only if we also * moved the tar file in place, to keep things strictly in sync. */ assert(i->settings_temp_path); /* Regenerate final name for this auxiliary file, we might know the etag of the file now, and * we should incorporate it in the file name if we can */ i->settings_path = mfree(i->settings_path); r = tar_pull_determine_path(i, ".nspawn", &i->settings_path); if (r < 0) goto finish; r = import_make_read_only(i->settings_temp_path); if (r < 0) goto finish; r = rename_noreplace(AT_FDCWD, i->settings_temp_path, AT_FDCWD, i->settings_path); if (r < 0) { log_error_errno(r, "Failed to rename settings file to %s: %m", i->settings_path); goto finish; } i->settings_temp_path = mfree(i->settings_temp_path); } } tar_pull_report_progress(i, TAR_COPYING); r = tar_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); }
static void tar_pull_job_on_finished(PullJob *j) { TarPull *i; int r; assert(j); assert(j->userdata); i = j->userdata; 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) { if (j == i->checksum_job) log_error_errno(j->error, "Failed to retrieve SHA256 checksum, cannot verify. (Try --verify=no?)"); else if (j == i->signature_job) log_error_errno(j->error, "Failed to retrieve signature file, 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. */ if (!tar_pull_is_done(i)) return; i->tar_job->disk_fd = safe_close(i->tar_job->disk_fd); if (i->settings_job) i->settings_job->disk_fd = safe_close(i->settings_job->disk_fd); if (i->tar_pid > 0) { r = wait_for_terminate_and_warn("tar", i->tar_pid, true); i->tar_pid = 0; if (r < 0) goto finish; if (r > 0) { r = -EIO; goto finish; } } if (!i->tar_job->etag_exists) { /* This is a new download, verify it, and move it into place */ tar_pull_report_progress(i, TAR_VERIFYING); r = pull_verify(i->tar_job, i->settings_job, i->checksum_job, i->signature_job); if (r < 0) goto finish; tar_pull_report_progress(i, TAR_FINALIZING); r = import_make_read_only(i->temp_path); 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 to final image name: %m"); goto finish; } i->temp_path = mfree(i->temp_path); if (i->settings_job && i->settings_job->error == 0 && !i->settings_job->etag_exists) { assert(i->settings_temp_path); assert(i->settings_path); /* Also move the settings file into place, if * it exist. Note that we do so only if we * also moved the tar file in place, to keep * things strictly in sync. */ r = import_make_read_only(i->settings_temp_path); if (r < 0) goto finish; r = rename_noreplace(AT_FDCWD, i->settings_temp_path, AT_FDCWD, i->settings_path); if (r < 0) { log_error_errno(r, "Failed to rename settings file: %m"); goto finish; } i->settings_temp_path = mfree(i->settings_temp_path); } } tar_pull_report_progress(i, TAR_COPYING); r = tar_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); }
static int save_external_coredump( const char *context[_CONTEXT_MAX], int input_fd, char **ret_filename, int *ret_node_fd, int *ret_data_fd, uint64_t *ret_size, bool *ret_truncated) { _cleanup_free_ char *fn = NULL, *tmp = NULL; _cleanup_close_ int fd = -1; uint64_t rlimit, process_limit, max_size; struct stat st; uid_t uid; int r; assert(context); assert(ret_filename); assert(ret_node_fd); assert(ret_data_fd); assert(ret_size); r = parse_uid(context[CONTEXT_UID], &uid); if (r < 0) return log_error_errno(r, "Failed to parse UID: %m"); r = safe_atou64(context[CONTEXT_RLIMIT], &rlimit); if (r < 0) return log_error_errno(r, "Failed to parse resource limit '%s': %m", context[CONTEXT_RLIMIT]); if (rlimit < page_size()) { /* Is coredumping disabled? Then don't bother saving/processing the coredump. * Anything below PAGE_SIZE cannot give a readable coredump (the kernel uses * ELF_EXEC_PAGESIZE which is not easily accessible, but is usually the same as PAGE_SIZE. */ return log_info_errno(SYNTHETIC_ERRNO(EBADSLT), "Resource limits disable core dumping for process %s (%s).", context[CONTEXT_PID], context[CONTEXT_COMM]); } process_limit = MAX(arg_process_size_max, storage_size_max()); if (process_limit == 0) return log_debug_errno(SYNTHETIC_ERRNO(EBADSLT), "Limits for coredump processing and storage are both 0, not dumping core."); /* Never store more than the process configured, or than we actually shall keep or process */ max_size = MIN(rlimit, process_limit); r = make_filename(context, &fn); if (r < 0) return log_error_errno(r, "Failed to determine coredump file name: %m"); (void) mkdir_p_label("/var/lib/systemd/coredump", 0755); fd = open_tmpfile_linkable(fn, O_RDWR|O_CLOEXEC, &tmp); if (fd < 0) return log_error_errno(fd, "Failed to create temporary file for coredump %s: %m", fn); r = copy_bytes(input_fd, fd, max_size, 0); if (r < 0) { log_error_errno(r, "Cannot store coredump of %s (%s): %m", context[CONTEXT_PID], context[CONTEXT_COMM]); goto fail; } *ret_truncated = r == 1; if (*ret_truncated) log_struct(LOG_INFO, LOG_MESSAGE("Core file was truncated to %zu bytes.", max_size), "SIZE_LIMIT=%zu", max_size, "MESSAGE_ID=" SD_MESSAGE_TRUNCATED_CORE_STR); if (fstat(fd, &st) < 0) { log_error_errno(errno, "Failed to fstat core file %s: %m", coredump_tmpfile_name(tmp)); goto fail; } if (lseek(fd, 0, SEEK_SET) == (off_t) -1) { log_error_errno(errno, "Failed to seek on %s: %m", coredump_tmpfile_name(tmp)); goto fail; } #if HAVE_XZ || HAVE_LZ4 /* If we will remove the coredump anyway, do not compress. */ if (arg_compress && !maybe_remove_external_coredump(NULL, st.st_size)) { _cleanup_free_ char *fn_compressed = NULL, *tmp_compressed = NULL; _cleanup_close_ int fd_compressed = -1; fn_compressed = strappend(fn, COMPRESSED_EXT); if (!fn_compressed) { log_oom(); goto uncompressed; } fd_compressed = open_tmpfile_linkable(fn_compressed, O_RDWR|O_CLOEXEC, &tmp_compressed); if (fd_compressed < 0) { log_error_errno(fd_compressed, "Failed to create temporary file for coredump %s: %m", fn_compressed); goto uncompressed; } r = compress_stream(fd, fd_compressed, -1); if (r < 0) { log_error_errno(r, "Failed to compress %s: %m", coredump_tmpfile_name(tmp_compressed)); goto fail_compressed; } r = fix_permissions(fd_compressed, tmp_compressed, fn_compressed, context, uid); if (r < 0) goto fail_compressed; /* OK, this worked, we can get rid of the uncompressed version now */ if (tmp) unlink_noerrno(tmp); *ret_filename = TAKE_PTR(fn_compressed); /* compressed */ *ret_node_fd = TAKE_FD(fd_compressed); /* compressed */ *ret_data_fd = TAKE_FD(fd); /* uncompressed */ *ret_size = (uint64_t) st.st_size; /* uncompressed */ return 0; fail_compressed: if (tmp_compressed) (void) unlink(tmp_compressed); } uncompressed: #endif r = fix_permissions(fd, tmp, fn, context, uid); if (r < 0) goto fail; *ret_filename = TAKE_PTR(fn); *ret_data_fd = TAKE_FD(fd); *ret_node_fd = -1; *ret_size = (uint64_t) st.st_size; return 0; fail: if (tmp) (void) unlink(tmp); return r; }