chiark / gitweb /
util: be a bit safer in path_is_safe()
[elogind.git] / src / shared / util.c
index 03edafb952c3b9969a9fab4bc7e492fd2784fd61..f904d03257f1b63e43d578ddd5c65b0b3aee744a 100644 (file)
@@ -350,7 +350,6 @@ int parse_uid(const char *s, uid_t* ret_uid) {
         int r;
 
         assert(s);
         int r;
 
         assert(s);
-        assert(ret_uid);
 
         r = safe_atolu(s, &ul);
         if (r < 0)
 
         r = safe_atolu(s, &ul);
         if (r < 0)
@@ -369,7 +368,9 @@ int parse_uid(const char *s, uid_t* ret_uid) {
         if (uid == (uid_t) 0xFFFF)
                 return -ENXIO;
 
         if (uid == (uid_t) 0xFFFF)
                 return -ENXIO;
 
-        *ret_uid = uid;
+        if (ret_uid)
+                *ret_uid = uid;
+
         return 0;
 }
 
         return 0;
 }
 
@@ -1700,7 +1701,7 @@ int parse_size(const char *t, off_t base, off_t *size) {
          * sometimes SI decimal suffixes. This function can parse
          * both. Which one is the right way depends on the
          * context. Wikipedia suggests that SI is customary for
          * sometimes SI decimal suffixes. This function can parse
          * both. Which one is the right way depends on the
          * context. Wikipedia suggests that SI is customary for
-         * hardrware metrics and network speeds, while IEC is
+         * hardware metrics and network speeds, while IEC is
          * customary for most data sizes used by software and volatile
          * (RAM) memory. Hence be careful which one you pick!
          *
          * customary for most data sizes used by software and volatile
          * (RAM) memory. Hence be careful which one you pick!
          *
@@ -3917,7 +3918,7 @@ bool path_is_safe(const char *p) {
         if (streq(p, "..") || startswith(p, "../") || endswith(p, "/..") || strstr(p, "/../"))
                 return false;
 
         if (streq(p, "..") || startswith(p, "../") || endswith(p, "/..") || strstr(p, "/../"))
                 return false;
 
-        if (strlen(p) > PATH_MAX)
+        if (strlen(p)+1 > PATH_MAX)
                 return false;
 
         /* The following two checks are not really dangerous, but hey, they still are confusing */
                 return false;
 
         /* The following two checks are not really dangerous, but hey, they still are confusing */
@@ -5923,9 +5924,22 @@ int fd_setcrtime(int fd, usec_t usec) {
 
 int chattr_fd(int fd, unsigned value, unsigned mask) {
         unsigned old_attr, new_attr;
 
 int chattr_fd(int fd, unsigned value, unsigned mask) {
         unsigned old_attr, new_attr;
+        struct stat st;
 
         assert(fd >= 0);
 
 
         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;
 
         if (mask == 0)
                 return 0;
 
@@ -5958,8 +5972,16 @@ int chattr_path(const char *p, unsigned value, unsigned mask) {
 }
 
 int read_attr_fd(int fd, unsigned *ret) {
 }
 
 int read_attr_fd(int fd, unsigned *ret) {
+        struct stat st;
+
         assert(fd >= 0);
 
         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;
 
         if (ioctl(fd, FS_IOC_GETFLAGS, ret) < 0)
                 return -errno;