• Anton Protopopov's avatar
    ext4: ioctl: fix erroneous return value · fdde368e
    Anton Protopopov authored
    The ext4_ioctl_setflags() function which is used in the ioctls
    EXT4_IOC_SETFLAGS and EXT4_IOC_FSSETXATTR may return the positive value
    EPERM instead of -EPERM in case of error. This bug was introduced by a
    recent commit 9b7365fc.
    
    The following program can be used to illustrate the wrong behavior:
    
        #include <sys/types.h>
        #include <sys/ioctl.h>
        #include <sys/stat.h>
        #include <fcntl.h>
        #include <err.h>
    
        #define FS_IOC_GETFLAGS _IOR('f', 1, long)
        #define FS_IOC_SETFLAGS _IOW('f', 2, long)
        #define FS_IMMUTABLE_FL 0x00000010
    
        int main(void)
        {
            int fd;
            long flags;
    
            fd = open("file", O_RDWR|O_CREAT, 0600);
            if (fd < 0)
                err(1, "open");
    
            if (ioctl(fd, FS_IOC_GETFLAGS, &flags) < 0)
                err(1, "ioctl: FS_IOC_GETFLAGS");
    
            flags |= FS_IMMUTABLE_FL;
    
            if (ioctl(fd, FS_IOC_SETFLAGS, &flags) < 0)
                err(1, "ioctl: FS_IOC_SETFLAGS");
    
            warnx("ioctl returned no error");
    
            return 0;
        }
    
    Running it gives the following result:
    
        $ strace -e ioctl ./test
        ioctl(3, FS_IOC_GETFLAGS, 0x7ffdbd8bfd38) = 0
        ioctl(3, FS_IOC_SETFLAGS, 0x7ffdbd8bfd38) = 1
        test: ioctl returned no error
        +++ exited with 0 +++
    
    Running the program on a kernel with the bug fixed gives the proper result:
    
        $ strace -e ioctl ./test
        ioctl(3, FS_IOC_GETFLAGS, 0x7ffdd2768258) = 0
        ioctl(3, FS_IOC_SETFLAGS, 0x7ffdd2768258) = -1 EPERM (Operation not permitted)
        test: ioctl: FS_IOC_SETFLAGS: Operation not permitted
        +++ exited with 1 +++
    Signed-off-by: default avatarAnton Protopopov <a.s.protopopov@gmail.com>
    Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
    fdde368e
ioctl.c 22.8 KB