From a2e7dfc73b547e6d360cef3d807e912af5ccc87d Mon Sep 17 00:00:00 2001 From: Cole Robinson Date: Sat, 6 Sep 2025 09:36:15 -0400 Subject: [PATCH] New API: ntfs_chmod Add an API to do the equivalent of `chmod [-r] MODE PATH` for NTFS filesystems. Files created on a linux ntfs-3g mount can not change permissions directly. New files and directories are created with rough windows equivalent of `chmod 777`. These wide open permissions can generate security warnings on windows after virt-v2v installs bits into `Program Files\Guestfs`. Behind the scenes we use `ntfssecaudit(8)` from `ntfsprogs` which is already part of the appliance. We only expose the chmod-style feature; the rest of `ntfssecaudit` is concerned reporting and managing fine grained windows security info which is way more than we need. Also note, `ntfssecaudit` needs to run on an unmounted partition so using this is more complicated than a traditional `chmod` call. Related: https://issues.redhat.com/browse/RHEL-104352 Signed-off-by: Cole Robinson --- daemon/ntfs.c | 31 +++++++++++++++++++++++++++++++ generator/actions_core.ml | 23 +++++++++++++++++++++++ generator/proc_nr.ml | 1 + gobject/Makefile.inc | 2 ++ lib/MAX_PROC_NR | 2 +- 5 files changed, 58 insertions(+), 1 deletion(-) diff --git a/daemon/ntfs.c b/daemon/ntfs.c index c22fbd1ea..108909982 100644 --- a/daemon/ntfs.c +++ b/daemon/ntfs.c @@ -329,3 +329,34 @@ do_ntfscat_i (const mountable_t *mountable, int64_t inode) return 0; } + +/* Takes optional arguments, consult optargs_bitmask. */ +int +do_ntfs_chmod (const char *device, int mode, const char *path, int recursive) +{ + const char *argv[MAX_ARGS]; + size_t i = 0; + int r; + CLEANUP_FREE char *err = NULL; + char mode_str[16]; + + snprintf (mode_str, sizeof mode_str, "%o", mode); + + ADD_ARG (argv, i, "ntfssecaudit"); + + if ((optargs_bitmask & GUESTFS_NTFS_CHMOD_RECURSIVE_BITMASK) && recursive) + ADD_ARG (argv, i, "-r"); + + ADD_ARG (argv, i, device); + ADD_ARG (argv, i, mode_str); + ADD_ARG (argv, i, path); + ADD_ARG (argv, i, NULL); + + r = commandvf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR, argv); + if (r == -1) { + reply_with_error ("ntfssecaudit %s %s %s: %s", device, mode_str, path, err); + return -1; + } + + return 0; +} diff --git a/generator/actions_core.ml b/generator/actions_core.ml index f869fde40..b4ec6db87 100644 --- a/generator/actions_core.ml +++ b/generator/actions_core.ml @@ -6616,6 +6616,29 @@ Restore the C (from a previous call to C) to C, overwriting any existing contents of this device." }; + { defaults with + name = "ntfs_chmod"; added = (1, 55, 13); + (* We don't use Pathname for `path` argument, since that implies + NEED_ROOT, and this command only operates on unmounted devices. + *) + style = RErr, [String (Device, "device"); Int "mode"; String (PlainString, "path")], [OBool "recursive"]; + optional = Some "ntfs3g"; + shortdesc = "change file permissions on NTFS filesystem"; + longdesc = {|Change file permissions on an NTFS filesystem with +a chmod-style permission mask, using L. Only numeric modes +are supported. + +I: When using this command from guestfish, C +by default would be decimal, unless you prefix it with +C<0> to get octal, ie. use C<0700> not C<700>. + +The C parameter is the NTFS partition device (eg. C). +This must be unmounted. +The C parameter is the permission mode (eg. C<0744>). +The C parameter is the file or directory path within the filesystem. +If the optional C flag is set, directory permissions are set +recursively.|} }; + { defaults with name = "set_label"; added = (1, 17, 9); style = RErr, [String (Mountable, "mountable"); String (PlainString, "label")], []; diff --git a/generator/proc_nr.ml b/generator/proc_nr.ml index 42624afef..bea19c5c7 100644 --- a/generator/proc_nr.ml +++ b/generator/proc_nr.ml @@ -522,6 +522,7 @@ let proc_nr = [ 517, "sh_out"; 518, "btrfs_scrub_full"; 519, "setfiles"; +520, "ntfs_chmod"; ] (* End of list. If adding a new entry, add it at the end of the list diff --git a/gobject/Makefile.inc b/gobject/Makefile.inc index b828113c6..00eeac4e1 100644 --- a/gobject/Makefile.inc +++ b/gobject/Makefile.inc @@ -97,6 +97,7 @@ guestfs_gobject_headers= \ include/guestfs-gobject/optargs-mktemp.h \ include/guestfs-gobject/optargs-mount_9p.h \ include/guestfs-gobject/optargs-mount_local.h \ + include/guestfs-gobject/optargs-ntfs_chmod.h \ include/guestfs-gobject/optargs-ntfsclone_out.h \ include/guestfs-gobject/optargs-ntfsfix.h \ include/guestfs-gobject/optargs-ntfsresize.h \ @@ -193,6 +194,7 @@ guestfs_gobject_sources= \ src/optargs-mktemp.c \ src/optargs-mount_9p.c \ src/optargs-mount_local.c \ + src/optargs-ntfs_chmod.c \ src/optargs-ntfsclone_out.c \ src/optargs-ntfsfix.c \ src/optargs-ntfsresize.c \ diff --git a/lib/MAX_PROC_NR b/lib/MAX_PROC_NR index 08f851b6e..2596e4ad8 100644 --- a/lib/MAX_PROC_NR +++ b/lib/MAX_PROC_NR @@ -1 +1 @@ -519 +520