summaryrefslogtreecommitdiff
path: root/src/shared/util.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2015-04-22 13:05:26 +0200
committerSven Eden <yamakuzure@gmx.net>2017-03-14 08:09:35 +0100
commite50b238ba361def3ce7987b0ca58f4f90e6dfd99 (patch)
treeba5c51eecbce0795c39dd0414edf556eff138fea /src/shared/util.c
parent4f903e3b2126cb46097fd6b4647718d07a4914f2 (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.
Diffstat (limited to 'src/shared/util.c')
-rw-r--r--src/shared/util.c21
1 files changed, 21 insertions, 0 deletions
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;