]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
fstrim: ignore non-directory mountpoints
authorKarel Zak <kzak@redhat.com>
Thu, 5 Sep 2019 14:28:49 +0000 (16:28 +0200)
committerKarel Zak <kzak@redhat.com>
Thu, 5 Sep 2019 14:32:10 +0000 (16:32 +0200)
It seems better to silently ignore mount binds on file (= mountpoint
is not a directory).

This patch also fixes use-after-free bug from commit 402006fa6e.

Addresses: https://github.com/karelzak/util-linux/issues/857
Signed-off-by: Karel Zak <kzak@redhat.com>
sys-utils/fstrim.8
sys-utils/fstrim.c

index 7e39b33d759c43d0dd2fdbca049e0409593d325a..eba52ab9e9bba27088aea38823897a2caf55896a 100644 (file)
@@ -100,7 +100,7 @@ LVM setup, etc.  These reductions would not be reflected in fstrim_range.len
 option).
 .TP
 .B \-\-quiet
-Suppress error messages.  This option is meant to be used in systemd service
+Suppress trim operation (ioctl) error messages.  This option is meant to be used in systemd service
 file or in cron scripts to hide warnings that are result of known problems,
 such as NTFS driver
 reporting
index 2c11a317f05bfab73f23c27d13faea20392df3cf..e6d7af3ea9fcf59d34439460e470bbf9698a3c06 100644 (file)
@@ -65,11 +65,27 @@ struct fstrim_control {
                     dryrun : 1;
 };
 
+static int is_directory(const char *path, int silent)
+{
+       struct stat sb;
+
+       if (stat(path, &sb) == -1) {
+               if (!silent)
+                       warn(_("stat of %s failed"), path);
+               return 0;
+       }
+       if (!S_ISDIR(sb.st_mode)) {
+               if (!silent)
+                       warnx(_("%s: not a directory"), path);
+               return 0;
+       }
+       return 1;
+}
+
 /* returns: 0 = success, 1 = unsupported, < 0 = error */
 static int fstrim_filesystem(struct fstrim_control *ctl, const char *path, const char *devname)
 {
        int fd = -1, rc;
-       struct stat sb;
        struct fstrim_range range;
        char *rpath = realpath(path, NULL);
 
@@ -87,16 +103,6 @@ static int fstrim_filesystem(struct fstrim_control *ctl, const char *path, const
                rc = -errno;
                goto done;
        }
-       if (fstat(fd, &sb) == -1) {
-               warn(_("stat of %s failed"), path);
-               rc = -errno;
-               goto done;
-       }
-       if (!S_ISDIR(sb.st_mode)) {
-               warnx(_("%s: not a directory"), path);
-               rc = -EINVAL;
-               goto done;
-       }
 
        if (ctl->dryrun) {
                if (devname)
@@ -328,14 +334,15 @@ static int fstrim_all(struct fstrim_control *ctl)
                        continue;       /* overlaying mount */
 
                /* FITRIM on read-only filesystem can fail, and it can fail */
-               if (access(path, W_OK) != 0) {
+               if (access(tgt, W_OK) != 0) {
                        if (errno == EROFS)
                                continue;
                        if (errno == EACCES)
                                continue;
                }
 
-               if (!has_discard(src, &wholedisk))
+               if (!is_directory(tgt, 1) ||
+                   !has_discard(src, &wholedisk))
                        continue;
                cnt++;
 
@@ -384,7 +391,7 @@ static void __attribute__((__noreturn__)) usage(void)
        fputs(_(" -l, --length <num>  the number of bytes to discard\n"), out);
        fputs(_(" -m, --minimum <num> the minimum extent length to discard\n"), out);
        fputs(_(" -v, --verbose       print number of discarded bytes\n"), out);
-       fputs(_("     --quiet         suppress error messages\n"), out);
+       fputs(_("     --quiet         suppress trim error messages\n"), out);
        fputs(_(" -n, --dry-run       does everything, but trim\n"), out);
 
        fputs(USAGE_SEPARATOR, out);
@@ -475,6 +482,9 @@ int main(int argc, char **argv)
        if (all)
                return fstrim_all(&ctl);        /* MNT_EX_* codes */
 
+       if (!is_directory(path, 0))
+               return EXIT_FAILURE;
+
        rc = fstrim_filesystem(&ctl, path, NULL);
        if (rc == 1 && !ctl.quiet)
                warnx(_("%s: the discard operation is not supported"), path);