mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-21 22:53:37 +00:00
daemon: inspect_get_windows_group_policy
Windows group policy objects (GPOs) are restrictions that can be added
by an administrator to Windows to lock down various operations. From
our point of view the ones that matter involve restricting the ability
to inject device drivers.
Previously virt-v2v detected group policy here:
9bb2e7d470/convert/convert_windows.ml (L69)
We would like to report group policy through the libguestfs API and
tools such as virt-inspector, so move the code that is used to detect
group policy to libguestfs. A new API is introduced that returns
whether group policy was found (only for Windows guests) during
inspection of the software registry.
Fixes: https://issues.redhat.com/browse/RHEL-125846
This commit is contained in:
committed by
rwmjones
parent
355f8a5413
commit
1db2b7837f
@@ -450,6 +450,13 @@ and inspect_get_windows_current_control_set root =
|
||||
| None ->
|
||||
failwith "not a Windows guest, or CurrentControlSet could not be determined"
|
||||
|
||||
and inspect_get_windows_group_policy root =
|
||||
let root = search_for_root root in
|
||||
match root.inspection_data.windows_group_policy with
|
||||
| Some v -> v
|
||||
| None ->
|
||||
failwith "not a Windows guest, or software hive could not be parsed"
|
||||
|
||||
and inspect_is_live root = false
|
||||
|
||||
and inspect_is_netinst root = false
|
||||
|
||||
@@ -288,6 +288,54 @@ and check_windows_software_registry software_hive data =
|
||||
with
|
||||
Not_found -> ()
|
||||
);
|
||||
|
||||
(* If the Windows guest appears to be using group policy, since
|
||||
* group policy might be used to restrict driver injection.
|
||||
*
|
||||
* XXX If group policy is present, it may be possible to
|
||||
* remove the restriction on driver injection. Microsoft has
|
||||
* an article about this:
|
||||
* https://support.microsoft.com/uk-ua/help/2773300/stop-0x0000007b-error-after-you-use-a-group-policy-setting-to-prevent
|
||||
* Nikolay Ivanets pointed out that in addition to that you also
|
||||
* have to delete:
|
||||
* HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\DeviceInstall\Restrictions
|
||||
*)
|
||||
let has_group_policy =
|
||||
try
|
||||
(* NB This is a subtly different path from CurrentVersion path
|
||||
* we used above.
|
||||
*)
|
||||
let path = [ "Microsoft"; "Windows"; "CurrentVersion"; "Group Policy"; "History" ] in
|
||||
let node = get_node h root path in
|
||||
let children = Hivex.node_children h node in
|
||||
let children = Array.to_list children in
|
||||
let children =
|
||||
List.map (fun child -> Hivex.node_name h child) children in
|
||||
eprintf "check_windows_software_registry: \
|
||||
found HKLM\\SOFTWARE\\%s node with children: [%s]\n"
|
||||
(String.concat "\\" path)
|
||||
(String.concat ", " children);
|
||||
|
||||
(* Just assume any children looking like "{<GUID>}" mean that
|
||||
* some GPOs were installed.
|
||||
*
|
||||
* In future we might want to look for nodes which match:
|
||||
* History\{<GUID>}\<N> where <N> is a small integer (the order
|
||||
* in which policy objects were applied.
|
||||
*
|
||||
* For an example registry containing GPOs, see RHBZ#1219651.
|
||||
* See also: https://support.microsoft.com/en-us/kb/201453
|
||||
*)
|
||||
let is_gpo_guid name =
|
||||
let len = String.length name in
|
||||
len > 3 && name.[0] = '{' &&
|
||||
Char.isxdigit name.[1] && name.[len-1] = '}'
|
||||
in
|
||||
List.exists is_gpo_guid children
|
||||
with
|
||||
Not_found -> false in
|
||||
data.windows_group_policy <- Some has_group_policy;
|
||||
|
||||
with
|
||||
| Not_found ->
|
||||
if verbose () then
|
||||
|
||||
@@ -54,6 +54,7 @@ and inspection_data = {
|
||||
mutable windows_software_hive : string option;
|
||||
mutable windows_system_hive : string option;
|
||||
mutable windows_current_control_set : string option;
|
||||
mutable windows_group_policy : bool option;
|
||||
mutable drive_mappings : drive_mapping list;
|
||||
}
|
||||
and os_type =
|
||||
@@ -188,6 +189,8 @@ and string_of_inspection_data data =
|
||||
data.windows_system_hive;
|
||||
Option.iter (fun v -> bpf " windows_current_control_set: %s\n" v)
|
||||
data.windows_current_control_set;
|
||||
Option.iter (fun v -> bpf " windows_group_policy: %b\n" v)
|
||||
data.windows_group_policy;
|
||||
if data.drive_mappings <> [] then (
|
||||
let v =
|
||||
List.map (fun (a, b) -> sprintf "(%s, %s)" a b) data.drive_mappings in
|
||||
@@ -289,6 +292,7 @@ let null_inspection_data = {
|
||||
windows_software_hive = None;
|
||||
windows_system_hive = None;
|
||||
windows_current_control_set = None;
|
||||
windows_group_policy = None;
|
||||
drive_mappings = [];
|
||||
}
|
||||
let null_inspection_data () = { null_inspection_data with os_type = None }
|
||||
@@ -316,6 +320,8 @@ let merge_inspection_data child parent =
|
||||
merge child.windows_system_hive parent.windows_system_hive;
|
||||
parent.windows_current_control_set <-
|
||||
merge child.windows_current_control_set parent.windows_current_control_set;
|
||||
parent.windows_group_policy <-
|
||||
merge child.windows_group_policy parent.windows_group_policy;
|
||||
|
||||
(* This is what the old C code did, but I doubt that it's correct. *)
|
||||
parent.drive_mappings <- child.drive_mappings @ parent.drive_mappings
|
||||
|
||||
@@ -57,6 +57,7 @@ and inspection_data = {
|
||||
mutable windows_software_hive : string option;
|
||||
mutable windows_system_hive : string option;
|
||||
mutable windows_current_control_set : string option;
|
||||
mutable windows_group_policy : bool option;
|
||||
mutable drive_mappings : drive_mapping list;
|
||||
}
|
||||
(** During inspection, this data is collected incrementally for each
|
||||
|
||||
@@ -521,6 +521,28 @@ hive is a valid Windows Registry hive.
|
||||
|
||||
You can use C<guestfs_hivex_open> to read or write to the hive.
|
||||
|
||||
Please read L<guestfs(3)/INSPECTION> for more details.|} };
|
||||
|
||||
{ defaults with
|
||||
name = "inspect_get_windows_group_policy"; added = (1, 57, 6);
|
||||
style = RBool "hasgrouppolicy", [String (Mountable, "root")], [];
|
||||
impl = OCaml "Inspect.inspect_get_windows_group_policy";
|
||||
shortdesc = "return if Windows guest has group policy";
|
||||
longdesc = {|This returns true if the Windows guest
|
||||
has group policy. Group policy can interfere with device
|
||||
driver installation, preventing libguestfs features like
|
||||
driver injection from working.
|
||||
|
||||
Note that the presence of group policy is only an indication that
|
||||
there may be a problem with driver installation. As group policy
|
||||
is extremely complex and covers many different aspects of Windows
|
||||
configuration, and we make no attempt to parse it, presence of
|
||||
group policy should only raise a warning.
|
||||
|
||||
This call assumes that the guest is Windows and that the
|
||||
Registry could be examined by inspection. If this is not
|
||||
the case then an error is returned.
|
||||
|
||||
Please read L<guestfs(3)/INSPECTION> for more details.|} };
|
||||
|
||||
{ defaults with
|
||||
|
||||
@@ -523,6 +523,7 @@ let proc_nr = [
|
||||
518, "btrfs_scrub_full";
|
||||
519, "setfiles";
|
||||
520, "ntfs_chmod";
|
||||
521, "inspect_get_windows_group_policy";
|
||||
]
|
||||
|
||||
(* End of list. If adding a new entry, add it at the end of the list
|
||||
|
||||
@@ -1 +1 @@
|
||||
520
|
||||
521
|
||||
|
||||
Reference in New Issue
Block a user