eminence / procfs

Rust library for reading the Linux procfs filesystem
Other
358 stars 105 forks source link

Process uid() fails on some kernels #265

Closed tatref closed 1 year ago

tatref commented 1 year ago

Tested on 2.6.39 UEK kernel on Oracle Linux 6 x86_64

Process::uid() generates Bad file descriptor. This is due to OFlags::PATH beeing used to open the /proc/<id> directory:

https://github.com/eminence/procfs/blob/86e5ba008aa0eff720ce87b9fe4410e23ec4674d/procfs/src/process/mod.rs#L149-L152 https://github.com/eminence/procfs/blob/86e5ba008aa0eff720ce87b9fe4410e23ec4674d/procfs/src/process/mod.rs#L221-L224

This flag does not give access to some syscall (fstat in this case).

From the manpage (https://man7.org/linux/man-pages/man2/open.2.html):

O_PATH (since Linux 2.6.39)
[...]
              other file operations read, write, fchmod, fchown, fgetxattr, ioctl, mmap fail with the
              error EBADF.

              The following operations can be performed on the resulting
              file descriptor:

              *  [fstat(2)](https://man7.org/linux/man-pages/man2/fstat.2.html) (since Linux 3.6).
              *  [fstatfs(2)](https://man7.org/linux/man-pages/man2/fstatfs.2.html) (since Linux 3.12).

So for kernels >= 2.6.39 but < 3.6, we should not set the OFlags::PATH flag. For kernels < 2.6.39, the flag seems to be ignored, so we can keep it. For kernels >= 3.6, the flag gives better performance, so we should keep it

Can we add a simple if kernel >= 3.6 { flags |= OFlags::PATH }? Or is there a better way to do it?

I don't know if this should be a compile-time check, or runtime. I would personally prefer a runtime check because I reuse a single binary over multiple server, but that's just my personal use-case.

eminence commented 1 year ago

Can we add a simple if kernel >= 3.6 { flags |= OFlags::PATH }?

I think we can do this, yes. The procfs::KERNEL lazy static was designed for this exact case (doing cheap checks on kernel version)

Thanks for testing on this old kernel, I don't have easy access to things this old :)

max-ag commented 2 months ago

The fix that was merged doesn't seem to be right.

When not using the O_PATH flag, the call to openat fails with Error: Too many levels of symbolic links (os error 40). In these cases, in procfs, when iterating FDs, you get an empty list.

Tested on kernels 2.6.39, and 2.6.32.