From: Lennart Poettering Date: Wed, 22 Apr 2015 11:05:26 +0000 (+0200) Subject: util: make sure fd refers to regular file or directory when applying file attributes X-Git-Tag: v226.4~1^2~444 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=e50b238ba361def3ce7987b0ca58f4f90e6dfd99;p=elogind.git util: make sure fd refers to regular file or directory when applying file attributes Before invoking file system ioctls we need to make sure that the specified fd actually refers to a file system object, and not a device node or similar. Otherwise we might by accident invoke unrelated device driver ioctls. For example, DRM ioctls use the same ioctl numbers as the various file system ioctls. --- diff --git a/src/shared/util.c b/src/shared/util.c index ce23b4790..f9094cc7e 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -5923,9 +5923,22 @@ int fd_setcrtime(int fd, usec_t usec) { int chattr_fd(int fd, unsigned value, unsigned mask) { unsigned old_attr, new_attr; + struct stat st; assert(fd >= 0); + if (fstat(fd, &st) < 0) + return -errno; + + /* Explicitly check whether this is a regular file or + * directory. If it is anything else (such as a device node or + * fifo), then the ioctl will not hit the file systems but + * possibly drivers, where the ioctl might have different + * effects. Notably, DRM is using the same ioctl() number. */ + + if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode)) + return -ENOTTY; + if (mask == 0) return 0; @@ -5958,8 +5971,16 @@ int chattr_path(const char *p, unsigned value, unsigned mask) { } int read_attr_fd(int fd, unsigned *ret) { + struct stat st; + assert(fd >= 0); + if (fstat(fd, &st) < 0) + return -errno; + + if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode)) + return -ENOTTY; + if (ioctl(fd, FS_IOC_GETFLAGS, ret) < 0) return -errno;