Adjust Print Compositor sandbox for Windows XPS printing
When printing modifiable content (e.g., HTML documents) on Windows with XPS instead of GDI, the Print Compositor utility process is requested to generate an XPS object model for the document. To do this, the Skia calls made by the Print Compositor in turn make drawing calls to the Windows XPS Print API. These will fail due to access-denied errors unless the sandbox settings are adjusted for the Print Compositor. Skia drawing for printing makes many calls into the API which are context aware. This requires the ability to open a printing context. With a regular sandbox, this would require relaxing the token level to USER_INTERACTIVE, which is very permissive. Rather than relax the sandbox that much, instead change the approach to use the Windows Low Privilege App Container. This maintains a strong sandbox while enabling access to the necessary system printing APIs for XPS. In addition to the obvious lpacPrinting capability, it also needs the lpacCom capability for XPS library initialization. This change in Windows sandboxing approach for the Print Compositor is a complete switch for the Print Compositor, including when printing is still being done using GDI. Introduce a separate & temporary control flag around this sandboxing change, so that it can be easily reverted to the old sandboxing method should it later be found that there is some unexpected impact to GDI printing. Bug: 40100562 Change-Id: Ibb3597987857ac2f0a34c5661839392cbfd98777 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1990336 Reviewed-by: Lei Zhang <thestig@chromium.org> Commit-Queue: Alan Screen <awscreen@chromium.org> Reviewed-by: Will Harris <wfh@chromium.org> Cr-Commit-Position: refs/heads/main@{#1283432}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
16cbf26db1
commit
353a12d12f
chrome/browser/printing
content/browser
sandbox/policy
@ -108,6 +108,7 @@
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
#include "printing/printing_utils.h"
|
||||
#include "sandbox/policy/features.h"
|
||||
#include "sandbox/policy/switches.h"
|
||||
#endif
|
||||
|
||||
@ -2207,16 +2208,6 @@ class PrintCompositorDocumentDataTypeBrowserTest
|
||||
PrintBrowserTest::SetUp();
|
||||
}
|
||||
|
||||
// TODO(crbug.com/40100562): Tests that generate XPS currently only succeed
|
||||
// if the test is run with sandboxing disabled. Remove this once sandboxing
|
||||
// changes for XPS are applied to the PrintCompositor service.
|
||||
void SetUpCommandLine(base::CommandLine* command_line) override {
|
||||
PrintBrowserTest::SetUpCommandLine(command_line);
|
||||
if (GetParam() == DocumentDataType::kXps) {
|
||||
command_line->AppendSwitch(sandbox::policy::switches::kNoSandbox);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
base::test::ScopedFeatureList scoped_feature_list_;
|
||||
};
|
||||
@ -2242,6 +2233,41 @@ IN_PROC_BROWSER_TEST_P(PrintCompositorDocumentDataTypeBrowserTest,
|
||||
EXPECT_THAT(print_preview_observer.last_document_composite_data_type(),
|
||||
testing::Optional(GetParam()));
|
||||
}
|
||||
|
||||
// Demonstrate that the Print Compositor still works using the legacy sandbox
|
||||
// method, should the `kPrintCompositorLPAC` flag be disabled.
|
||||
// TODO(crbug.com/40283514): Remove once LPAC sandboxing has been proven to
|
||||
// work even for GDI.
|
||||
class PrintCompositorLegacySandboxBrowserTest : public PrintBrowserTest {
|
||||
void SetUp() override {
|
||||
std::vector<base::test::FeatureRef> disabled_features;
|
||||
|
||||
disabled_features.push_back(
|
||||
sandbox::policy::features::kPrintCompositorLPAC);
|
||||
disabled_features.push_back(features::kUseXpsForPrinting);
|
||||
|
||||
scoped_feature_list_.InitWithFeatures(/*enabled_features=*/{},
|
||||
disabled_features);
|
||||
PrintBrowserTest::SetUp();
|
||||
}
|
||||
|
||||
private:
|
||||
base::test::ScopedFeatureList scoped_feature_list_;
|
||||
};
|
||||
|
||||
IN_PROC_BROWSER_TEST_F(PrintCompositorLegacySandboxBrowserTest,
|
||||
WindowDotPrint) {
|
||||
content::WebContents* web_contents =
|
||||
browser()->tab_strip_model()->GetActiveWebContents();
|
||||
|
||||
TestPrintPreviewObserver print_preview_observer(/*wait_for_loaded=*/true);
|
||||
content::ExecuteScriptAsync(web_contents->GetPrimaryMainFrame(),
|
||||
"window.print();");
|
||||
print_preview_observer.WaitUntilPreviewIsReady();
|
||||
|
||||
EXPECT_THAT(print_preview_observer.last_document_composite_data_type(),
|
||||
testing::Optional(DocumentDataType::kPdf));
|
||||
}
|
||||
#endif // BUILDFLAG(IS_WIN)
|
||||
|
||||
} // namespace printing
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "content/public/common/sandboxed_process_launcher_delegate.h"
|
||||
#include "content/utility/sandbox_delegate_data.mojom.h"
|
||||
#include "printing/buildflags/buildflags.h"
|
||||
#include "sandbox/policy/features.h"
|
||||
#include "sandbox/policy/mojom/sandbox.mojom.h"
|
||||
#include "sandbox/policy/win/sandbox_win.h"
|
||||
#include "sandbox/win/src/app_container.h"
|
||||
@ -263,6 +264,15 @@ bool UtilitySandboxedProcessLauncherDelegate::GetAppContainerId(
|
||||
case sandbox::mojom::Sandbox::kXrCompositing:
|
||||
*appcontainer_id = UtilityAppContainerId(cmd_line_);
|
||||
return true;
|
||||
#if BUILDFLAG(ENABLE_PRINTING)
|
||||
case sandbox::mojom::Sandbox::kPrintCompositor:
|
||||
if (base::FeatureList::IsEnabled(
|
||||
sandbox::policy::features::kPrintCompositorLPAC)) {
|
||||
*appcontainer_id = UtilityAppContainerId(cmd_line_);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
#endif
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@ -286,6 +296,14 @@ bool UtilitySandboxedProcessLauncherDelegate::DisableDefaultPolicy() {
|
||||
case sandbox::mojom::Sandbox::kOnDeviceModelExecution:
|
||||
// An LPAC policy is used for on-device model execution.
|
||||
return true;
|
||||
#if BUILDFLAG(ENABLE_PRINTING)
|
||||
case sandbox::mojom::Sandbox::kPrintCompositor:
|
||||
// Default policy is disabled for Print Compositor to allow the
|
||||
// application of specific LPAC sandbox policies, when that feature is
|
||||
// enabled.
|
||||
return base::FeatureList::IsEnabled(
|
||||
sandbox::policy::features::kPrintCompositorLPAC);
|
||||
#endif
|
||||
case sandbox::mojom::Sandbox::kWindowsSystemProxyResolver:
|
||||
// Default policy is disabled for Windows System Proxy Resolver process to
|
||||
// allow the application of specific LPAC sandbox policies.
|
||||
@ -394,6 +412,19 @@ bool UtilitySandboxedProcessLauncherDelegate::InitializeConfig(
|
||||
}
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(ENABLE_PRINTING)
|
||||
if (sandbox_type_ == sandbox::mojom::Sandbox::kPrintCompositor &&
|
||||
base::FeatureList::IsEnabled(
|
||||
sandbox::policy::features::kPrintCompositorLPAC)) {
|
||||
// LPAC sandbox is enabled, so do not use a restricted token.
|
||||
auto result = config->SetTokenLevel(sandbox::USER_UNPROTECTED,
|
||||
sandbox::USER_UNPROTECTED);
|
||||
if (result != sandbox::SBOX_ALL_OK) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return GetContentClient()->browser()->PreSpawnChild(
|
||||
config, sandbox_type_,
|
||||
ContentBrowserClient::ChildSpawnFlags::kChildSpawnFlagNone);
|
||||
|
@ -59,6 +59,11 @@ BASE_FEATURE(kGpuLPAC,
|
||||
"GpuLPAC",
|
||||
base::FEATURE_ENABLED_BY_DEFAULT);
|
||||
|
||||
// Enables Print Compositor Low Privilege AppContainer.
|
||||
BASE_FEATURE(kPrintCompositorLPAC,
|
||||
"PrintCompositorLPAC",
|
||||
base::FEATURE_ENABLED_BY_DEFAULT);
|
||||
|
||||
// Enables Renderer AppContainer
|
||||
BASE_FEATURE(kRendererAppContainer,
|
||||
"RendererAppContainer",
|
||||
|
@ -29,6 +29,7 @@ SANDBOX_POLICY_EXPORT BASE_DECLARE_FEATURE(kNetworkServiceFileAllowlist);
|
||||
SANDBOX_POLICY_EXPORT BASE_DECLARE_FEATURE(kWinSboxDisableExtensionPoints);
|
||||
SANDBOX_POLICY_EXPORT BASE_DECLARE_FEATURE(kGpuAppContainer);
|
||||
SANDBOX_POLICY_EXPORT BASE_DECLARE_FEATURE(kGpuLPAC);
|
||||
SANDBOX_POLICY_EXPORT BASE_DECLARE_FEATURE(kPrintCompositorLPAC);
|
||||
SANDBOX_POLICY_EXPORT BASE_DECLARE_FEATURE(kRendererAppContainer);
|
||||
SANDBOX_POLICY_EXPORT BASE_DECLARE_FEATURE(kWinSboxHighRendererJobMemoryLimits);
|
||||
SANDBOX_POLICY_EXPORT BASE_DECLARE_FEATURE(kWinSboxNetworkServiceSandboxIsLPAC);
|
||||
|
@ -506,6 +506,11 @@ std::wstring GetAppContainerProfileName(const std::string& appcontainer_id,
|
||||
case Sandbox::kOnDeviceModelExecution:
|
||||
sandbox_base_name = std::string("cr.sb.odm");
|
||||
break;
|
||||
#if BUILDFLAG(ENABLE_PRINTING)
|
||||
case Sandbox::kPrintCompositor:
|
||||
sandbox_base_name = std::string("cr.sb.prnc");
|
||||
break;
|
||||
#endif
|
||||
case Sandbox::kWindowsSystemProxyResolver:
|
||||
sandbox_base_name = std::string("cr.sb.pxy");
|
||||
break;
|
||||
@ -540,6 +545,11 @@ ResultCode SetupAppContainerProfile(AppContainer* container,
|
||||
sandbox_type != Sandbox::kMediaFoundationCdm &&
|
||||
sandbox_type != Sandbox::kNetwork &&
|
||||
sandbox_type != Sandbox::kOnDeviceModelExecution &&
|
||||
#if BUILDFLAG(ENABLE_PRINTING)
|
||||
!(sandbox_type == Sandbox::kPrintCompositor &&
|
||||
base::FeatureList::IsEnabled(
|
||||
sandbox::policy::features::kPrintCompositorLPAC)) &&
|
||||
#endif
|
||||
sandbox_type != Sandbox::kWindowsSystemProxyResolver) {
|
||||
return SBOX_ERROR_UNSUPPORTED;
|
||||
}
|
||||
@ -604,6 +614,14 @@ ResultCode SetupAppContainerProfile(AppContainer* container,
|
||||
container->SetEnableLowPrivilegeAppContainer(true);
|
||||
}
|
||||
|
||||
#if BUILDFLAG(ENABLE_PRINTING)
|
||||
if (sandbox_type == Sandbox::kPrintCompositor) {
|
||||
container->AddCapability(kLpacCom);
|
||||
container->AddCapability(L"lpacPrinting");
|
||||
container->SetEnableLowPrivilegeAppContainer(true);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (sandbox_type == Sandbox::kWindowsSystemProxyResolver) {
|
||||
container->AddCapability(base::win::WellKnownCapability::kInternetClient);
|
||||
container->AddCapability(kLpacServicesManagement);
|
||||
@ -917,6 +935,13 @@ bool SandboxWin::IsAppContainerEnabledForSandbox(
|
||||
return true;
|
||||
}
|
||||
|
||||
#if BUILDFLAG(ENABLE_PRINTING)
|
||||
if (sandbox_type == Sandbox::kPrintCompositor) {
|
||||
return base::FeatureList::IsEnabled(
|
||||
sandbox::policy::features::kPrintCompositorLPAC);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (sandbox_type == Sandbox::kWindowsSystemProxyResolver)
|
||||
return true;
|
||||
|
||||
|
Reference in New Issue
Block a user