Cannot open /dev/vfio/noiommu-0: Operation not permitted

130 views Asked by At

I am trying to open file /dev/vfio/noiommu-0 with read and write access (O_RDWR), but the error occurs.

char* filename = "/dev/vfio/noiommu-0";
int fd = open(filename, O_RDWR);
if (fd < 0)
    printf("Cannot open %s: %s\n", filename, strerror(errno));

The output is Cannot open /dev/vfio/noiommu-0: Operation not permitted

I've changed the permissions of the file to crw-rw-rw- and changed the owner of the file from root to myuser, but it didn't help. Also myuser has permissions to read upper folders.

Could you please explain why I cannot read and write to this file, and how can I overcome these issues?

2

There are 2 answers

0
Mikhail Malofeev On BEST ANSWER

Setting CAP_SYS_RAWIO capabilities solved the issue (source).

1
Harith On

The man page for open() lists the following reasons why a call to open() may return -1:

ERRORS         
       open(), openat(), and creat() can fail with the following errors:

       EACCES The requested access to the file is not allowed, or search
              permission is denied for one of the directories in the
              path prefix of pathname, or the file did not exist yet and
              write access to the parent directory is not allowed.  (See
              also path_resolution(7).)

       EACCES Where O_CREAT is specified, the protected_fifos or
              protected_regular sysctl is enabled, the file already
              exists and is a FIFO or regular file, the owner of the
              file is neither the current user nor the owner of the
              containing directory, and the containing directory is both
              world- or group-writable and sticky.  For details, see the
              descriptions of /proc/sys/fs/protected_fifos and
              /proc/sys/fs/protected_regular in proc(5).

       EBADF  (openat()) pathname is relative but dirfd is neither
              AT_FDCWD nor a valid file descriptor.

       EBUSY  O_EXCL was specified in flags and pathname refers to a
              block device that is in use by the system (e.g., it is
              mounted).

       EDQUOT Where O_CREAT is specified, the file does not exist, and
              the user's quota of disk blocks or inodes on the
              filesystem has been exhausted.

       EEXIST pathname already exists and O_CREAT and O_EXCL were used.

       EFAULT pathname points outside your accessible address space.

       EFBIG  See EOVERFLOW.

       EINTR  While blocked waiting to complete an open of a slow device
              (e.g., a FIFO; see fifo(7)), the call was interrupted by a
              signal handler; see signal(7).

       EINVAL The filesystem does not support the O_DIRECT flag.  See
              NOTES for more information.

       EINVAL Invalid value in flags.

       EINVAL O_TMPFILE was specified in flags, but neither O_WRONLY nor
              O_RDWR was specified.

       EINVAL O_CREAT was specified in flags and the final component
              ("basename") of the new file's pathname is invalid (e.g.,
              it contains characters not permitted by the underlying
              filesystem).

       EINVAL The final component ("basename") of pathname is invalid
              (e.g., it contains characters not permitted by the
              underlying filesystem).

       EISDIR pathname refers to a directory and the access requested
              involved writing (that is, O_WRONLY or O_RDWR is set).

       EISDIR pathname refers to an existing directory, O_TMPFILE and
              one of O_WRONLY or O_RDWR were specified in flags, but
              this kernel version does not provide the O_TMPFILE
              functionality.

       ELOOP  Too many symbolic links were encountered in resolving
              pathname.

       ELOOP  pathname was a symbolic link, and flags specified
              O_NOFOLLOW but not O_PATH.

       EMFILE The per-process limit on the number of open file
              descriptors has been reached (see the description of
              RLIMIT_NOFILE in getrlimit(2)).

       ENAMETOOLONG
              pathname was too long.

       ENFILE The system-wide limit on the total number of open files
              has been reached.

       ENODEV pathname refers to a device special file and no
              corresponding device exists.  (This is a Linux kernel bug;
              in this situation ENXIO must be returned.)

       ENOENT O_CREAT is not set and the named file does not exist.

       ENOENT A directory component in pathname does not exist or is a
              dangling symbolic link.

       ENOENT pathname refers to a nonexistent directory, O_TMPFILE and
              one of O_WRONLY or O_RDWR were specified in flags, but
              this kernel version does not provide the O_TMPFILE
              functionality.

       ENOMEM The named file is a FIFO, but memory for the FIFO buffer
              can't be allocated because the per-user hard limit on
              memory allocation for pipes has been reached and the
              caller is not privileged; see pipe(7).

       ENOMEM Insufficient kernel memory was available.

       ENOSPC pathname was to be created but the device containing
              pathname has no room for the new file.

       ENOTDIR
              A component used as a directory in pathname is not, in
              fact, a directory, or O_DIRECTORY was specified and
              pathname was not a directory.

       ENOTDIR
              (openat()) pathname is a relative pathname and dirfd is a
              file descriptor referring to a file other than a
              directory.

       ENXIO  O_NONBLOCK | O_WRONLY is set, the named file is a FIFO,
              and no process has the FIFO open for reading.

       ENXIO  The file is a device special file and no corresponding
              device exists.

       ENXIO  The file is a UNIX domain socket.

       EOPNOTSUPP
              The filesystem containing pathname does not support
              O_TMPFILE.

       EOVERFLOW
              pathname refers to a regular file that is too large to be
              opened.  The usual scenario here is that an application
              compiled on a 32-bit platform without
              -D_FILE_OFFSET_BITS=64 tried to open a file whose size
              exceeds (1<<31)-1 bytes; see also O_LARGEFILE above.  This
              is the error specified by POSIX.1; before Linux 2.6.24,
              Linux gave the error EFBIG for this case.

       EPERM  The O_NOATIME flag was specified, but the effective user
              ID of the caller did not match the owner of the file and
              the caller was not privileged.

       EPERM  The operation was prevented by a file seal; see fcntl(2).

       EROFS  pathname refers to a file on a read-only filesystem and
              write access was requested.

       ETXTBSY
              pathname refers to an executable image which is currently
              being executed and write access was requested.

       ETXTBSY
              pathname refers to a file that is currently in use as a
              swap file, and the O_TRUNC flag was specified.

       ETXTBSY
              pathname refers to a file that is currently being read by
              the kernel (e.g., for module/firmware loading), and write
              access was requested.

       EWOULDBLOCK
              The O_NONBLOCK flag was specified, and an incompatible
              lease was held on the file (see fcntl(2)).

How are you absolutely certain that it'd only ever fail with "Operation not permitted"?

Instead, call perror() after the call to open(), or print the result of strerror().