]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_io: allow open file permissions to be changed
authorDave Chinner <dchinner@redhat.com>
Wed, 12 Dec 2018 17:42:40 +0000 (11:42 -0600)
committerEric Sandeen <sandeen@redhat.com>
Wed, 12 Dec 2018 17:42:40 +0000 (11:42 -0600)
I need to be able to open a file read-write, then change the
permissions on the file to read-only to check that copy_file_range
returns EPERM correctly in that case. This can't be done as root,
because root ignores file permissions, but as a normal user we can't
open a 0444 file for writing and so can't actually test writing to
a read-only file without some method of "open read-write, change
permissions to read-only, try to write to file through open
read-write file".

So, allow adding or removing write permissions on an open file.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
[sandeen: Move man page entry to FILE section]
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
io/open.c
man/man8/xfs_io.8

index 21c0e054f8d2c604498b16dbffcca2cb281d1e28..f5fbd2c4fe452d1262310deff9449a2ecdf28f7d 100644 (file)
--- a/io/open.c
+++ b/io/open.c
@@ -44,6 +44,7 @@ static cmdinfo_t chproj_cmd;
 static cmdinfo_t lsproj_cmd;
 static cmdinfo_t extsize_cmd;
 static cmdinfo_t inode_cmd;
+static cmdinfo_t chmod_cmd;
 static prid_t prid;
 static long extsize;
 
@@ -809,6 +810,48 @@ inode_f(
        return 0;
 }
 
+static void
+chmod_help(void)
+{
+       printf(_(
+"\n"
+" Change the read/write permissions on the current file\n"
+"\n"
+" Options:\n"
+" -r -- make the file read only (0444 permissions)\n"
+" -w -- make the file read/write (0664 permissions)\n"
+"\n"));
+}
+
+static int
+chmod_f(
+       int             argc,
+       char            **argv)
+{
+       mode_t          mode = S_IRUSR | S_IRGRP | S_IROTH;
+       int             c;
+
+       while ((c = getopt(argc, argv, "rw")) != EOF) {
+               switch (c) {
+               case 'r':
+                       break;
+               case 'w':
+                       mode |= S_IWUSR | S_IWGRP;
+                       break;
+               default:
+                       return command_usage(&chmod_cmd);
+               }
+       }
+
+       if (argc != optind)
+               return command_usage(&chmod_cmd);
+
+       if (fchmod(file->fd, mode) < 0) {
+               exitcode = 1;
+               perror("fchmod");
+       }
+       return 0;
+}
 void
 open_init(void)
 {
@@ -871,10 +914,21 @@ open_init(void)
                _("Query inode number usage in the filesystem");
        inode_cmd.help = inode_help;
 
+       chmod_cmd.name = "chmod";
+       chmod_cmd.cfunc = chmod_f;
+       chmod_cmd.args = _("-r | -w");
+       chmod_cmd.argmin = 1;
+       chmod_cmd.argmax = 1;
+       chmod_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK | CMD_FLAG_ONESHOT;
+       chmod_cmd.oneline =
+               _("change the read/write permissions on the currently open file");
+       chmod_cmd.help = chmod_help;
+
        add_command(&open_cmd);
        add_command(&close_cmd);
        add_command(&chproj_cmd);
        add_command(&lsproj_cmd);
        add_command(&extsize_cmd);
        add_command(&inode_cmd);
+       add_command(&chmod_cmd);
 }
index a37ed3c249b640cbf8641b18342bfe6c17e35056..fbf50df578097fad872def1e079454c4c7bb8dea 100644 (file)
@@ -191,6 +191,15 @@ See the
 .B close
 command.
 .TP
+.B chmod \-r | \-w
+Change the mode of the currently open file. The
+.B \-r
+option will set the file permissions to read-only (0444), whilst the
+.B \-w
+option will set the file permissions to read-write (0644). This allows xfs_io to
+set up mismatches between the file permissions and the open file descriptor
+read/write mode to exercise permission checks inside various syscalls.
+.TP
 .BI "pread [ \-b " bsize " ] [ \-v ] [ \-FBR [ \-Z " seed " ] ] [ \-V " vectors " ] " "offset length"
 Reads a range of bytes in a specified blocksize from the given
 .IR offset .