@@ -197,6 +197,7 @@ AC_HAVE_SG_IO
AC_HAVE_HDIO_GETGEO
AC_CONFIG_SYSTEMD_SYSTEM_UNIT_DIR
AC_CONFIG_CROND_DIR
+AC_HAVE_GETFSLABEL
if test "$enable_blkid" = yes; then
AC_HAVE_BLKID_TOPO
@@ -117,6 +117,7 @@ HAVE_SYSTEMD = @have_systemd@
SYSTEMD_SYSTEM_UNIT_DIR = @systemd_system_unit_dir@
HAVE_CROND = @have_crond@
CROND_DIR = @crond_dir@
+HAVE_GETFSLABEL = @have_getfslabel@
GCCFLAGS = -funsigned-char -fno-strict-aliasing -Wall
# -Wbitwise -Wno-transparent-union -Wno-old-initializer -Wno-decl
@@ -429,3 +429,20 @@ AC_DEFUN([AC_PACKAGE_CHECK_LTO],
AC_SUBST(lto_cflags)
AC_SUBST(lto_ldflags)
])
+
+#
+# Check if we have the GETFSLABEL ioctl
+#
+AC_DEFUN([AC_HAVE_GETFSLABEL],
+ [ AC_MSG_CHECKING([for FS_IOC_GETFSLABEL])
+ AC_TRY_LINK([
+#define _GNU_SOURCE
+#include <linux/fs.h>
+ ], [
+ char label[FSLABEL_MAX];
+ ioctl(0, FS_IOC_GETFSLABEL, &label);
+ ], have_getfslabel=yes
+ AC_MSG_RESULT(yes),
+ AC_MSG_RESULT(no))
+ AC_SUBST(have_getfslabel)
+ ])
@@ -99,6 +99,10 @@ ifeq ($(HAVE_HDIO_GETGEO),yes)
LCFLAGS += -DHAVE_HDIO_GETGEO
endif
+ifeq ($(HAVE_GETFSLABEL),yes)
+LCFLAGS += -DHAVE_GETFSLABEL
+endif
+
LDIRT = $(XFS_SCRUB_ALL_PROG) *.service *.cron
default: depend $(LTCOMMAND) $(XFS_SCRUB_ALL_PROG) $(OPTIONAL_TARGETS)
@@ -11,6 +11,9 @@
#ifdef HAVE_LIBATTR
# include <attr/attributes.h>
#endif
+#ifdef HAVE_GETFSLABEL
+# include <linux/fs.h>
+#endif
#include "handle.h"
#include "list.h"
#include "path.h"
@@ -282,6 +285,54 @@ xfs_scrub_connections(
return *pmoveon ? 0 : XFS_ITERATE_INODES_ABORT;
}
+#ifdef HAVE_GETFSLABEL
+/*
+ * Check the filesystem label for Unicode normalization problems or misleading
+ * sequences.
+ */
+static bool
+xfs_scrub_fs_label(
+ struct scrub_ctx *ctx)
+{
+ char label[FSLABEL_MAX];
+ struct unicrash *uc = NULL;
+ bool moveon = true;
+ int error;
+
+ moveon = unicrash_fs_label_init(&uc, ctx);
+ if (!moveon)
+ return false;
+
+ /* Retrieve label; quietly bail if we don't support that. */
+ error = ioctl(ctx->mnt_fd, FS_IOC_GETFSLABEL, &label);
+ if (error) {
+ if (errno != EOPNOTSUPP && errno != ENOTTY) {
+ moveon = false;
+ perror(ctx->mntpoint);
+ }
+ goto out;
+ }
+
+ /* Ignore empty labels. */
+ if (label[0] == 0)
+ goto out;
+
+ /* Otherwise check for weirdness. */
+ if (uc)
+ moveon = unicrash_check_fs_label(uc, ctx->mntpoint, label);
+ else
+ moveon = xfs_scrub_check_name(ctx, ctx->mntpoint,
+ _("filesystem label"), label);
+ if (!moveon)
+ goto out;
+out:
+ unicrash_free(uc);
+ return moveon;
+}
+#else
+# define xfs_scrub_fs_label(c) (true)
+#endif /* HAVE_GETFSLABEL */
+
/* Check directory connectivity. */
bool
xfs_scan_connections(
@@ -296,6 +347,10 @@ _("Filesystem has errors, skipping connectivity checks."));
return true;
}
+ moveon = xfs_scrub_fs_label(ctx);
+ if (!moveon)
+ return false;
+
ret = xfs_scan_all_inodes(ctx, xfs_scrub_connections, &moveon);
if (!ret)
moveon = false;
@@ -465,6 +465,15 @@ unicrash_xattr_init(
is_only_root_writable(bstat));
}
+/* Initialize the collision detector for a filesystem label. */
+bool
+unicrash_fs_label_init(
+ struct unicrash **ucp,
+ struct scrub_ctx *ctx)
+{
+ return unicrash_init(ucp, ctx, false, 16, true);
+}
+
/* Free the crash detector. */
void
unicrash_free(
@@ -698,3 +707,18 @@ unicrash_check_xattr_name(
return __unicrash_check_name(uc, descr, _("extended attribute"),
attrname, 0);
}
+
+/*
+ * Check the fs label for unicode normalization problems or misleading bits.
+ */
+bool
+unicrash_check_fs_label(
+ struct unicrash *uc,
+ const char *descr,
+ const char *label)
+{
+ if (!uc)
+ return true;
+ return __unicrash_check_name(uc, descr, _("filesystem label"),
+ label, 0);
+}
@@ -17,17 +17,22 @@ bool unicrash_dir_init(struct unicrash **ucp, struct scrub_ctx *ctx,
struct xfs_bstat *bstat);
bool unicrash_xattr_init(struct unicrash **ucp, struct scrub_ctx *ctx,
struct xfs_bstat *bstat);
+bool unicrash_fs_label_init(struct unicrash **ucp, struct scrub_ctx *ctx);
void unicrash_free(struct unicrash *uc);
bool unicrash_check_dir_name(struct unicrash *uc, const char *descr,
struct dirent *dirent);
bool unicrash_check_xattr_name(struct unicrash *uc, const char *descr,
const char *attrname);
+bool unicrash_check_fs_label(struct unicrash *uc, const char *descr,
+ const char *label);
#else
# define unicrash_dir_init(u, c, b) (true)
# define unicrash_xattr_init(u, c, b) (true)
+# define unicrash_label_init(u, c) (true)
# define unicrash_free(u) do {(u) = (u);} while (0)
# define unicrash_check_dir_name(u, d, n) (true)
# define unicrash_check_xattr_name(u, d, n) (true)
+# define unicrash_check_fs_label(u, d, n) (true)
#endif /* HAVE_LIBICU */
#endif /* XFS_SCRUB_UNICRASH_H_ */