summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2015-04-22 13:05:26 +0200
committerLennart Poettering <lennart@poettering.net>2015-04-22 13:27:53 +0200
commit03091baac3c37094af6a30be31e4962dd26f8404 (patch)
tree242e6ca2dcd35e96038e14663a673e3d30bf19c6
parent163ab2961268232e1cb49e990a8ccefe24b7649f (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.c21
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;