static int tty_write__enter()

in elastic-ebpf/GPL/Events/Process/Probe.bpf.c [600:669]


static int tty_write__enter(struct kiocb *iocb, struct iov_iter *from)
{
    if (is_consumer()) {
        goto out;
    }

    struct file *f               = BPF_CORE_READ(iocb, ki_filp);
    struct tty_file_private *tfp = (struct tty_file_private *)BPF_CORE_READ(f, private_data);
    struct tty_struct *tty       = BPF_CORE_READ(tfp, tty);

    // Obtain the real TTY
    //
    // @link: link to another pty (master -> slave and vice versa)
    //
    // https://elixir.bootlin.com/linux/v5.19.9/source/drivers/tty/tty_io.c#L2643
    bool is_master             = false;
    struct ebpf_tty_dev master = {};
    struct ebpf_tty_dev slave  = {};
    if (BPF_CORE_READ(tty, driver, type) == TTY_DRIVER_TYPE_PTY &&
        BPF_CORE_READ(tty, driver, subtype) == PTY_TYPE_MASTER) {
        struct tty_struct *tmp = BPF_CORE_READ(tty, link);
        ebpf_tty_dev__fill(&master, tty);
        ebpf_tty_dev__fill(&slave, tmp);
        is_master = true;
    } else {
        ebpf_tty_dev__fill(&slave, tty);
    }

    if (slave.major == 0 && slave.minor == 0) {
        goto out;
    }

    if ((is_master && !(master.termios.c_lflag & ECHO)) && !(slave.termios.c_lflag & ECHO)) {
        goto out;
    }

    const struct iovec *iov;
    if (FIELD_OFFSET(iov_iter, __iov))
        iov = (const struct iovec *)((char *)from + FIELD_OFFSET(iov_iter, __iov));
    else if (bpf_core_field_exists(from->iov))
        iov = BPF_CORE_READ(from, iov);
    else
        goto out;
    u64 nr_segs = BPF_CORE_READ(from, nr_segs);
    nr_segs     = nr_segs > MAX_NR_SEGS ? MAX_NR_SEGS : nr_segs;

    if (nr_segs == 0) {
        u64 count = BPF_CORE_READ(from, count);
        (void)output_tty_event(&slave, (void *)iov, count);
        goto out;
    }

    for (int seg = 0; seg < nr_segs; seg++) {
        // NOTE(matt): this check needs to be here because the verifier
        // detects an infinite loop otherwise.
        if (seg >= MAX_NR_SEGS)
            goto out;

        struct iovec *cur_iov = (struct iovec *)&iov[seg];
        const char *base      = BPF_CORE_READ(cur_iov, iov_base);
        size_t len            = BPF_CORE_READ(cur_iov, iov_len);

        if (output_tty_event(&slave, base, len)) {
            goto out;
        }
    }

out:
    return 0;
}