diff options
author | Lennart Poettering <lennart@poettering.net> | 2015-04-22 13:05:26 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2015-04-22 13:27:53 +0200 |
commit | 03091baac3c37094af6a30be31e4962dd26f8404 (patch) | |
tree | 242e6ca2dcd35e96038e14663a673e3d30bf19c6 | |
parent | 163ab2961268232e1cb49e990a8ccefe24b7649f (diff) |
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.
-rw-r--r-- | src/shared/util.c | 21 |
1 files changed, 21 insertions, 0 deletions
diff --git a/src/shared/util.c b/src/shared/util.c index f14d9ee90b..4a044840bd 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -5988,9 +5988,22 @@ int same_fd(int a, int b) { 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; @@ -6023,8 +6036,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; |