]> www.infradead.org Git - users/hch/xfsprogs.git/commitdiff
xfs_scrub: allow auxiliary pathnames for sandboxing
authorDarrick J. Wong <djwong@kernel.org>
Wed, 3 Jul 2024 21:21:14 +0000 (14:21 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 9 Jul 2024 22:36:59 +0000 (15:36 -0700)
In the next patch, we'll tighten up the security on the xfs_scrub
service so that it can't escape.  However, sandboxing the service
involves making the host filesystem as inaccessible as possible, with
the filesystem to scrub bind mounted onto a known location within the
sandbox.  Hence we need one path for reporting and a new -M argument to
tell scrub what it should actually be trying to open.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
man/man8/xfs_scrub.8
scrub/phase1.c
scrub/vfs.c
scrub/xfs_scrub.c
scrub/xfs_scrub.h

index b9f253e1b079a9ed352ff92404cf876b10c4ee57..6154011271e6f3295e5fd831f9fdd6f61505bc34 100644 (file)
@@ -4,7 +4,7 @@ xfs_scrub \- check and repair the contents of a mounted XFS filesystem
 .SH SYNOPSIS
 .B xfs_scrub
 [
-.B \-abCemnTvx
+.B \-abCeMmnTvx
 ]
 .I mount-point
 .br
@@ -79,6 +79,13 @@ behavior.
 .B \-k
 Do not call TRIM on the free space.
 .TP
+.BI \-M " real-mount-point"
+Open the this path for issuing scrub system calls to the kernel.
+The positional
+.I mount-point
+parameter will be used for displaying informational messages and logging.
+This parameter exists to enable process sandboxing for service mode.
+.TP
 .BI \-m " file"
 Search this file for mounted filesystems instead of /etc/mtab.
 .TP
index 1b3f6e8eb4f337b8c3b426b7a2ae365543c301c7..516d929d6268b887ad2dd2c5691914d3551ebaaf 100644 (file)
@@ -146,7 +146,7 @@ phase1_func(
         * CAP_SYS_ADMIN, which we probably need to do anything fancy
         * with the (XFS driver) kernel.
         */
-       error = -xfd_open(&ctx->mnt, ctx->mntpoint,
+       error = -xfd_open(&ctx->mnt, ctx->actual_mntpoint,
                        O_RDONLY | O_NOATIME | O_DIRECTORY);
        if (error) {
                if (error == EPERM)
@@ -199,7 +199,7 @@ _("Not an XFS filesystem."));
                return error;
        }
 
-       error = path_to_fshandle(ctx->mntpoint, &ctx->fshandle,
+       error = path_to_fshandle(ctx->actual_mntpoint, &ctx->fshandle,
                        &ctx->fshandle_len);
        if (error) {
                str_errno(ctx, _("getting fshandle"));
index 22c19485a2dae1237b9600caf19bbc41231052f8..fca9a4cf35689c34b3febc5bf15eec76c3a3f94b 100644 (file)
@@ -249,7 +249,7 @@ scan_fs_tree(
                goto out_cond;
        }
 
-       ret = queue_subdir(ctx, &sft, &wq, ctx->mntpoint, true);
+       ret = queue_subdir(ctx, &sft, &wq, ctx->actual_mntpoint, true);
        if (ret) {
                str_liberror(ctx, ret, _("queueing directory scan"));
                goto out_wq;
index 296d814eceebcab2ae1a3a985c1c1b271e44110a..d7cef115deea4ef40901caae5caeb0baef62ea01 100644 (file)
@@ -725,7 +725,7 @@ main(
        pthread_mutex_init(&ctx.lock, NULL);
        ctx.mode = SCRUB_MODE_REPAIR;
        ctx.error_action = ERRORS_CONTINUE;
-       while ((c = getopt(argc, argv, "a:bC:de:km:no:TvxV")) != EOF) {
+       while ((c = getopt(argc, argv, "a:bC:de:kM:m:no:TvxV")) != EOF) {
                switch (c) {
                case 'a':
                        ctx.max_errors = cvt_u64(optarg, 10);
@@ -769,6 +769,9 @@ main(
                case 'k':
                        want_fstrim = false;
                        break;
+               case 'M':
+                       ctx.actual_mntpoint = optarg;
+                       break;
                case 'm':
                        mtab = optarg;
                        break;
@@ -823,6 +826,8 @@ main(
                usage();
 
        ctx.mntpoint = argv[optind];
+       if (!ctx.actual_mntpoint)
+               ctx.actual_mntpoint = ctx.mntpoint;
 
        stdout_isatty = isatty(STDOUT_FILENO);
        stderr_isatty = isatty(STDERR_FILENO);
@@ -840,7 +845,7 @@ main(
                return SCRUB_RET_OPERROR;
 
        /* Find the mount record for the passed-in argument. */
-       if (stat(argv[optind], &ctx.mnt_sb) < 0) {
+       if (stat(ctx.actual_mntpoint, &ctx.mnt_sb) < 0) {
                fprintf(stderr,
                        _("%s: could not stat: %s: %s\n"),
                        progname, argv[optind], strerror(errno));
@@ -863,7 +868,7 @@ main(
        }
 
        fs_table_initialise(0, NULL, 0, NULL);
-       fsp = fs_table_lookup_mount(ctx.mntpoint);
+       fsp = fs_table_lookup_mount(ctx.actual_mntpoint);
        if (!fsp) {
                fprintf(stderr, _("%s: Not a XFS mount point.\n"),
                                ctx.mntpoint);
index 7d48f4bad9ce9a2540fcc22f7a9b13e1fa6fd0e1..b0aa9fcc67b72651219af35a50c279f595cd01e7 100644 (file)
@@ -38,9 +38,12 @@ enum error_action {
 struct scrub_ctx {
        /* Immutable scrub state. */
 
-       /* Strings we need for presentation */
+       /* Mountpoint we use for presentation */
        char                    *mntpoint;
 
+       /* Actual VFS path to the filesystem */
+       char                    *actual_mntpoint;
+
        /* Mountpoint info */
        struct stat             mnt_sb;
        struct statvfs          mnt_sv;