blob: 71c34895dc5956903d2a3e107ecf1af6d246b84f [file] [log] [blame] [edit]
// Copyright 2023 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "vm_tools/concierge/shadercached_helper.h"
#include <shadercached/proto_bindings/shadercached.pb.h>
#include <base/strings/strcat.h>
#include <base/strings/stringprintf.h>
#include <dbus/bus.h>
#include <dbus/error.h>
#include <dbus/message.h>
#include <dbus/shadercached/dbus-constants.h>
#include "vm_tools/common/vm_id.h"
#include "vm_tools/concierge/dbus_proxy_util.h"
#include "vm_tools/concierge/vm_util.h"
namespace vm_tools::concierge {
namespace {
// Map root to nobody(65534), map chronos(1000) (user inside Borealis) to
// shadercached(333). VM having full CRUD access to the shared directory is fine
// because the shared path is wrapped inside a directory with correct
// permissions that is only editable by host shadercached. Mapping VM user to
// shadercached ensures shadercached has full access to all files and
// directories created by the VM.
constexpr char kShadercachedUidMap[] = "0 65534 1,1000 333 1";
constexpr char kShadercachedGidMap[] = "0 65534 1,1000 333 1";
constexpr char kShaderSharedDirTag[] = "precompiled_gpu_cache";
} // namespace
SharedDataParam CreateShaderSharedDataParam(base::FilePath data_dir) {
// Write performance is not a concern, we only need to make sure if a write
// happens from the guest side, it is guaranteed to be persisted in the host.
return SharedDataParam{
.data_dir = data_dir,
.tag = kShaderSharedDirTag,
.uid_map = kShadercachedUidMap,
.gid_map = kShadercachedGidMap,
.enable_caches = SharedDataParam::Cache::kNever,
.rewrite_security_xattrs = false,
.posix_acl = true,
};
}
base::expected<shadercached::PrepareShaderCacheResponse, std::string>
PrepareShaderCache(const VmId& vm_id,
scoped_refptr<dbus::Bus> bus_,
dbus::ObjectProxy* shadercached_proxy_) {
dbus::MethodCall method_call(shadercached::kShaderCacheInterface,
shadercached::kPrepareShaderCache);
dbus::MessageWriter shadercached_writer(&method_call);
shadercached::PrepareShaderCacheRequest prepare_request;
prepare_request.set_vm_name(vm_id.name());
prepare_request.set_vm_owner_id(vm_id.owner_id());
shadercached_writer.AppendProtoAsArrayOfBytes(prepare_request);
dbus::Error error;
auto dbus_response = CallDBusMethodWithErrorResponse(
bus_, shadercached_proxy_, &method_call,
dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, &error);
if (!dbus_response) {
return base::unexpected(
base::StringPrintf("%s %s: %s", shadercached::kShaderCacheInterface,
error.name().c_str(), error.message().c_str()));
}
shadercached::PrepareShaderCacheResponse response;
auto reader = dbus::MessageReader(dbus_response.get());
if (!reader.PopArrayOfBytesAsProto(&response)) {
return base::unexpected("Failed to parse PrepareShaderCacheResponse");
}
return base::ok(response);
}
std::string PurgeShaderCache(const VmId& vm_id,
scoped_refptr<dbus::Bus> bus_,
dbus::ObjectProxy* shadercached_proxy_) {
dbus::MethodCall method_call(shadercached::kShaderCacheInterface,
shadercached::kPurgeMethod);
dbus::MessageWriter shadercached_writer(&method_call);
shadercached::PurgeRequest purge_request;
purge_request.set_vm_name(vm_id.name());
purge_request.set_vm_owner_id(vm_id.owner_id());
shadercached_writer.AppendProtoAsArrayOfBytes(purge_request);
dbus::Error error;
auto dbus_response = CallDBusMethodWithErrorResponse(
bus_, shadercached_proxy_, &method_call,
dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, &error);
if (!dbus_response) {
return base::StringPrintf("%s %s: %s", shadercached::kShaderCacheInterface,
error.name().c_str(), error.message().c_str());
}
return "";
}
} // namespace vm_tools::concierge