0

GOAL: write in the trace_pipe only if openat is called with O_RDONLY flag. I've build the struct looking the format contained here /sys/kernel/debug/tracing/events/syscalls/sys_enter_open/format

PROBLEM I think I'm not accessing to the flags field because it looks like that the second if statement is always false. QUESTION: am I correctly accessing to the flags fields? Is there a way to print flags variable content?

struct syscalls_enter_openat_args {
    __u64 pad;
    int __syscall_nr;
    const char * filename;
    int flags;
    unsigned short modep;
};
SEC("tracepoint/syscalls/sys_enter_openat")
int bpf_sys(struct syscalls_enter_openat_args *ctx)
{
    char fmt[] = "llo\n";
    int flags = ctx->flags;

    if (flags){
        if (flags == O_RDONLY)
            bpf_trace_printk(fmt, sizeof(fmt)); 
    }
    return 0;
}
char _license[] SEC("license") = "GPL";
Maicake
  • 1,046
  • 10
  • 34
  • 1
    Not sure this is the cause of your issue, but usually you check a flag with `flags & O_RDONLY`, not `==`, just in case `flags` also contains other flags. Did you try that? – Qeole Aug 30 '19 at 08:46
  • Damn, thanks @Qeole. – Maicake Aug 30 '19 at 08:50

1 Answers1

1

So you mention that the following check always evaluates to false:

if (flags == O_RDONLY)

This may be because there are more flags than just O_RDONLY that are passed to openat() through the variable flags. From the openat() manual page:

The argument flags must include one of the following access modes: O_RDONLY, O_WRONLY, or O_RDWR. These request opening the file read-only, write-only, or read/write, respectively.

In addition, zero or more file creation flags and file status flags can be bitwise-or'd in flags. The file creation flags are O_CLOEXEC, O_CREAT, O_DIRECTORY, O_EXCL, O_NOCTTY, O_NOFOLLOW, O_TMPFILE, and O_TRUNC. The file status flags are all of the remaining flags listed below. The distinction between these two groups of flags is that the file creation flags affect the semantics of the open operation itself, while the file status flags affect the semantics of subsequent I/O operations. The file status flags can be retrieved and (in some cases) modified; see fcntl(2) for details.

So instead of checking if your flags are equal to O_RDONLY, you might want to check if they include the flag, by bit-masking it like this:

if (flags & O_RDONLY)

As for printing the value of flags, it is probably doable with something like this (not tested):

        char fmt[] = "flags: %x\n";
        int flags = ctx->flags;

        if (flags & O_RDONLY)
                bpf_trace_printk(fmt, sizeof(fmt), flags); 
Community
  • 1
  • 1
Qeole
  • 8,284
  • 1
  • 24
  • 52
  • Thanks, anyway I have a doubt, If I strace the program the call to openat includes ONLY O_RDONLY , no other flags are used. So I'd expecte flags=O_RDONLY – Maicake Aug 30 '19 at 12:41
  • Yeah, maybe you just have `O_RDONLY` (in which case checking with `==` should work indeed), and this was not the cause of your issue. Is your BPF program successfully loaded (`bpftool prog`)? Successfully attached (try `bpftool perf`)? Can you see messages from `bpf_trace_printk()` when `openat()` is run? Can you print the value for `flags` from your BPF program? – Qeole Aug 30 '19 at 14:15