Esempio n. 1
0
_public_ int sd_id128_get_boot(sd_id128_t *ret) {
        static thread_local sd_id128_t saved_boot_id;
        static thread_local bool saved_boot_id_valid = false;
        _cleanup_close_ int fd = -1;
        char buf[36];
        unsigned j;
        sd_id128_t t;
        char *p;
        int r;

        assert_return(ret, -EINVAL);

        if (saved_boot_id_valid) {
                *ret = saved_boot_id;
                return 0;
        }

        fd = open("/proc/sys/kernel/random/boot_id", O_RDONLY|O_CLOEXEC|O_NOCTTY);
        if (fd < 0)
                return -errno;

        r = loop_read_exact(fd, buf, 36, false);
        if (r < 0)
                return r;

        for (j = 0, p = buf; j < 16; j++) {
                int a, b;

                if (p >= buf + 35)
                        return -EIO;

                if (*p == '-') {
                        p++;
                        if (p >= buf + 35)
                                return -EIO;
                }

                a = unhexchar(p[0]);
                b = unhexchar(p[1]);

                if (a < 0 || b < 0)
                        return -EIO;

                t.bytes[j] = a << 4 | b;

                p += 2;
        }

        saved_boot_id = t;
        saved_boot_id_valid = true;

        *ret = t;
        return 0;
}
int dev_urandom(void *p, size_t n) {
#if 0 /* NM_IGNORED */
        static int have_syscall = -1;

        _cleanup_close_ int fd = -1;
        int r;

        /* Gathers some randomness from the kernel. This call will
         * never block, and will always return some data from the
         * kernel, regardless if the random pool is fully initialized
         * or not. It thus makes no guarantee for the quality of the
         * returned entropy, but is good enough for our usual usecases
         * of seeding the hash functions for hashtable */

        /* Use the getrandom() syscall unless we know we don't have
         * it, or when the requested size is too large for it. */
        if (have_syscall != 0 || (size_t) (int) n != n) {
                r = getrandom(p, n, GRND_NONBLOCK);
                if (r == (int) n) {
                        have_syscall = true;
                        return 0;
                }

                if (r < 0) {
                        if (errno == ENOSYS)
                                /* we lack the syscall, continue with
                                 * reading from /dev/urandom */
                                have_syscall = false;
                        else if (errno == EAGAIN)
                                /* not enough entropy for now. Let's
                                 * remember to use the syscall the
                                 * next time, again, but also read
                                 * from /dev/urandom for now, which
                                 * doesn't care about the current
                                 * amount of entropy.  */
                                have_syscall = true;
                        else
                                return -errno;
                } else
                        /* too short read? */
                        return -ENODATA;
        }
#else /* NM_IGNORED */
        _cleanup_close_ int fd = -1;
#endif /* NM_IGNORED */

        fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
        if (fd < 0)
                return errno == ENOENT ? -ENOSYS : -errno;

        return loop_read_exact(fd, p, n, true);
}
Esempio n. 3
0
_public_ int sd_id128_get_machine(sd_id128_t *ret) {
        static thread_local sd_id128_t saved_machine_id;
        static thread_local bool saved_machine_id_valid = false;
        _cleanup_close_ int fd = -1;
        char buf[33];
        unsigned j;
        sd_id128_t t;
        int r;

        assert_return(ret, -EINVAL);

        if (saved_machine_id_valid) {
                *ret = saved_machine_id;
                return 0;
        }

        fd = open("/etc/machine-id", O_RDONLY|O_CLOEXEC|O_NOCTTY);
        if (fd < 0)
                return -errno;

        r = loop_read_exact(fd, buf, 33, false);
        if (r < 0)
                return r;
        if (buf[32] !='\n')
                return -EIO;

        for (j = 0; j < 16; j++) {
                int a, b;

                a = unhexchar(buf[j*2]);
                b = unhexchar(buf[j*2+1]);

                if (a < 0 || b < 0)
                        return -EIO;

                t.bytes[j] = a << 4 | b;
        }

        saved_machine_id = t;
        saved_machine_id_valid = true;

        *ret = t;
        return 0;
}
Esempio n. 4
0
static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, void *userdata) {
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
        union autofs_v5_packet_union packet;
        Automount *a = AUTOMOUNT(userdata);
        struct stat st;
        Unit *trigger;
        int r;

        assert(a);
        assert(fd == a->pipe_fd);

        if (events != EPOLLIN) {
                log_unit_error(UNIT(a), "Got invalid poll event %"PRIu32" on pipe (fd=%d)", events, fd);
                goto fail;
        }

        r = loop_read_exact(a->pipe_fd, &packet, sizeof(packet), true);
        if (r < 0) {
                log_unit_error_errno(UNIT(a), r, "Invalid read from pipe: %m");
                goto fail;
        }

        switch (packet.hdr.type) {

        case autofs_ptype_missing_direct:

                if (packet.v5_packet.pid > 0) {
                        _cleanup_free_ char *p = NULL;

                        get_process_comm(packet.v5_packet.pid, &p);
                        log_unit_info(UNIT(a), "Got automount request for %s, triggered by %"PRIu32" (%s)", a->where, packet.v5_packet.pid, strna(p));
                } else
                        log_unit_debug(UNIT(a), "Got direct mount request on %s", a->where);

                r = set_ensure_allocated(&a->tokens, NULL);
                if (r < 0) {
                        log_unit_error(UNIT(a), "Failed to allocate token set.");
                        goto fail;
                }

                r = set_put(a->tokens, UINT_TO_PTR(packet.v5_packet.wait_queue_token));
                if (r < 0) {
                        log_unit_error_errno(UNIT(a), r, "Failed to remember token: %m");
                        goto fail;
                }

                automount_enter_runnning(a);
                break;

        case autofs_ptype_expire_direct:
                log_unit_debug(UNIT(a), "Got direct umount request on %s", a->where);

                automount_stop_expire(a);

                r = set_ensure_allocated(&a->expire_tokens, NULL);
                if (r < 0) {
                        log_unit_error(UNIT(a), "Failed to allocate token set.");
                        goto fail;
                }

                r = set_put(a->expire_tokens, UINT_TO_PTR(packet.v5_packet.wait_queue_token));
                if (r < 0) {
                        log_unit_error_errno(UNIT(a), r, "Failed to remember token: %m");
                        goto fail;
                }

                /* Before we do anything, let's see if somebody is playing games with us? */
                if (lstat(a->where, &st) < 0) {
                        log_unit_warning_errno(UNIT(a), errno, "Failed to stat automount point: %m");
                        goto fail;
                }

                if (!S_ISDIR(st.st_mode) || st.st_dev == a->dev_id) {
                        log_unit_info(UNIT(a), "Automount point already unmounted?");
                        automount_send_ready(a, a->expire_tokens, 0);
                        break;
                }

                trigger = UNIT_TRIGGER(UNIT(a));
                if (!trigger) {
                        log_unit_error(UNIT(a), "Unit to trigger vanished.");
                        goto fail;
                }

                r = manager_add_job(UNIT(a)->manager, JOB_STOP, trigger, JOB_REPLACE, &error, NULL);
                if (r < 0) {
                        log_unit_warning(UNIT(a), "Failed to queue umount startup job: %s", bus_error_message(&error, r));
                        goto fail;
                }
                break;

        default:
                log_unit_error(UNIT(a), "Received unknown automount request %i", packet.hdr.type);
                break;
        }

        return 0;

fail:
        automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES);
        return 0;
}
Esempio n. 5
0
int decompress_stream_lz4(int fdf, int fdt, off_t max_bytes) {

#ifdef HAVE_LZ4
        _cleanup_free_ char *buf = NULL, *out = NULL;
        size_t buf_size = 0;
        LZ4_streamDecode_t lz4_data = {};
        le32_t header;
        size_t total_in = sizeof(header), total_out = 0;

        assert(fdf >= 0);
        assert(fdt >= 0);

        out = malloc(4*LZ4_BUFSIZE);
        if (!out)
                return log_oom();

        for (;;) {
                ssize_t m;
                int r;

                r = loop_read_exact(fdf, &header, sizeof(header), false);
                if (r < 0)
                        return r;

                m = le32toh(header);
                if (m == 0)
                        break;

                /* We refuse to use a bigger decompression buffer than
                 * the one used for compression by 4 times. This means
                 * that compression buffer size can be enlarged 4
                 * times. This can be changed, but old binaries might
                 * not accept buffers compressed by newer binaries then.
                 */
                if (m > LZ4_COMPRESSBOUND(LZ4_BUFSIZE * 4)) {
                        log_error("Compressed stream block too big: %zd bytes", m);
                        return -EBADMSG;
                }

                total_in += sizeof(header) + m;

                if (!GREEDY_REALLOC(buf, buf_size, m))
                        return log_oom();

                r = loop_read_exact(fdf, buf, m, false);
                if (r < 0)
                        return r;

                r = LZ4_decompress_safe_continue(&lz4_data, buf, out, m, 4*LZ4_BUFSIZE);
                if (r <= 0)
                        log_error("LZ4 decompression failed.");

                total_out += r;

                if (max_bytes != -1 && total_out > (size_t) max_bytes) {
                        log_debug("Decompressed stream longer than %zd bytes", max_bytes);
                        return -EFBIG;
                }

                r = loop_write(fdt, out, r, false);
                if (r < 0)
                        return r;
        }

        log_debug("LZ4 decompression finished (%zu -> %zu bytes, %.1f%%)",
                  total_in, total_out,
                  (double) total_out / total_in * 100);

        return 0;
#else
        log_error("Cannot decompress file. Compiled without LZ4 support.");
        return -EPROTONOSUPPORT;
#endif
}