Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2cce002c authored by Devin Moore's avatar Devin Moore Committed by Android (Google) Code Review
Browse files

Merge "Revert "Revert "Allow other processes to implement a UDS service..."" into main

parents c1ae85bc bee2e745
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
package {
    // See: http://go/android-license-faq
    // A large-scale-change added 'default_applicable_licenses' to import
    // all of the 'license_kinds' from "frameworks_native_license"
    // to get the below license kinds:
    //   SPDX-license-identifier-Apache-2.0
    default_applicable_licenses: ["frameworks_native_license"],
}

rust_library {
    name: "librpc_servicemanager",
    crate_name: "rpc_servicemanager",
    srcs: ["rpc_servicemanager.rs"],
    rustlibs: [
        "android.system.virtualmachineservice-rust",
        "libanyhow",
        "libbinder_rs",
        "liblibc",
        "liblog_rust",
        "librpcbinder_rs",
        "librustutils",
        "libvsock",
        "rpc_servicemanager_aidl-rust",
        "servicemanager_aidl-rust",
    ],
}
+195 −0
Original line number Diff line number Diff line
// Copyright 2025, The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Implementation of the AIDL interface `IServiceManager`.

use anyhow::Result;
use binder::{Accessor, BinderFeatures, Interface, Strong};
use libc::{sa_family_t, sockaddr_vm, AF_VSOCK};
use log::{error, info};
use rpc_servicemanager_aidl::aidl::android::os::IRpcProvider::{
    IRpcProvider, ServiceConnectionInfo::ServiceConnectionInfo,
};
use rpcbinder::{FileDescriptorTransportMode, RpcServer};
use rustutils::sockets::{android_get_control_socket, SocketError};
use servicemanager_aidl::aidl::android::os::IServiceManager::{
    BnServiceManager, CallerContext::CallerContext, IServiceManager,
};
use servicemanager_aidl::aidl::android::os::{
    ConnectionInfo::ConnectionInfo, IClientCallback::IClientCallback,
    IServiceCallback::IServiceCallback, Service::Service, ServiceDebugInfo::ServiceDebugInfo,
};
use std::os::unix::io::OwnedFd;
use vsock::VMADDR_CID_HOST;

// Name of the socket that libbinder is expecting IServiceManager to be served from
const RPC_SERVICEMANAGER_UDS_NAME: &str = "rpc_servicemanager";

/// Implementation of `IServiceManager`.
pub struct RpcServiceManager {
    provider_service: Strong<dyn IRpcProvider>,
}

impl IServiceManager for RpcServiceManager {
    fn getService(&self, _name: &str) -> binder::Result<Option<binder::SpIBinder>> {
        Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into())
    }
    fn getService2(&self, name: &str) -> binder::Result<Service> {
        let provider_service = self.provider_service.clone();

        let get_connection_info = move |inst: &str| {
            let connection_info = provider_service.getServiceConnectionInfo(inst).unwrap();
            match connection_info {
                ServiceConnectionInfo::Vsock(info) => {
                    let addr = sockaddr_vm {
                        svm_family: AF_VSOCK as sa_family_t,
                        svm_reserved1: 0,
                        svm_port: info.port as u32,
                        svm_cid: VMADDR_CID_HOST,
                        svm_zero: [0u8; 4],
                    };
                    Some(binder::ConnectionInfo::Vsock(addr))
                }
                #[allow(unreachable_patterns)]
                _ => {
                    error!("Unexpected ServiceConnectionInfo type!");
                    None
                }
            }
        };

        let accessor = Accessor::new(name, get_connection_info);

        Ok(Service::Accessor(accessor.as_binder()))
    }
    fn checkService(&self, _name: &str) -> binder::Result<Option<binder::SpIBinder>> {
        Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into())
    }
    fn checkService2(&self, _name: &str) -> binder::Result<Service> {
        Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into())
    }
    fn addService(
        &self,
        _name: &str,
        _service: &binder::SpIBinder,
        _allow_isolated: bool,
        _dump_priority: i32,
    ) -> binder::Result<()> {
        Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into())
    }
    fn listServices(&self, _dump_priority: i32) -> binder::Result<Vec<String>> {
        Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into())
    }
    fn registerForNotifications(
        &self,
        _name: &str,
        _callback: &binder::Strong<dyn IServiceCallback>,
    ) -> binder::Result<()> {
        Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into())
    }
    fn unregisterForNotifications(
        &self,
        _name: &str,
        _callback: &binder::Strong<dyn IServiceCallback>,
    ) -> binder::Result<()> {
        Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into())
    }
    fn isDeclared(&self, _name: &str) -> binder::Result<bool> {
        Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into())
    }
    fn getDeclaredInstances(&self, _iface: &str) -> binder::Result<Vec<String>> {
        Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into())
    }
    fn updatableViaApex(&self, _name: &str) -> binder::Result<Option<String>> {
        Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into())
    }
    fn getUpdatableNames(&self, _apex_name: &str) -> binder::Result<Vec<String>> {
        Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into())
    }
    fn getConnectionInfo(&self, _name: &str) -> binder::Result<Option<ConnectionInfo>> {
        Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into())
    }
    fn registerClientCallback(
        &self,
        _name: &str,
        _service: &binder::SpIBinder,
        _callback: &binder::Strong<dyn IClientCallback>,
    ) -> binder::Result<()> {
        Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into())
    }
    fn tryUnregisterService(
        &self,
        _name: &str,
        _service: &binder::SpIBinder,
    ) -> binder::Result<()> {
        Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into())
    }
    fn getServiceDebugInfo(&self) -> binder::Result<Vec<ServiceDebugInfo>> {
        Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into())
    }
    fn checkServiceAccess(&self, _: &CallerContext, _: &str, _: &str) -> binder::Result<bool> {
        Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into())
    }
}

impl Interface for RpcServiceManager {}

impl RpcServiceManager {
    /// Creates a new `RpcServiceManager` instance from the `IServiceManager` reference.
    fn new(provider_service: Strong<dyn IRpcProvider>) -> RpcServiceManager {
        Self { provider_service }
    }
}

/// Get the Unix Domain Socket file descriptor for RPC_SERVICEMANAGER_UDS_NAME
///
/// A client might need to do this in order to get an FD with the FD_CLOEXEC flag set before
/// it forks any other processes.
pub fn get_default_rpc_servicemanager_uds_fd() -> Result<OwnedFd, SocketError> {
    android_get_control_socket(RPC_SERVICEMANAGER_UDS_NAME)
}

/// Registers the `IServiceManager` service.
///
/// servicemanager_fd is an optional argument to provide the Unix Domain Socked file
/// descriptor to use for the server. If None is provided, then it will use the default
/// of RPC_SERVICEMANAGER_UDS_NAME to get the FD.
pub fn register_rpc_servicemanager(
    provider_service: Strong<dyn IRpcProvider>,
    servicemanager_fd: Option<OwnedFd>,
) -> Result<()> {
    let rpc_servicemanager_binder = BnServiceManager::new_binder(
        RpcServiceManager::new(provider_service),
        BinderFeatures::default(),
    );
    let servicemanager_fd = match servicemanager_fd {
        Some(fd) => fd,
        None => android_get_control_socket(RPC_SERVICEMANAGER_UDS_NAME)?,
    };
    let server =
        RpcServer::new_bound_socket(rpc_servicemanager_binder.as_binder(), servicemanager_fd)?;
    // Required for the FD being passed through libbinder's accessor binder
    server.set_supported_file_descriptor_transport_modes(&[FileDescriptorTransportMode::Unix]);

    info!("The RPC server '{}' is running.", RPC_SERVICEMANAGER_UDS_NAME);
    if let Err(e) = rustutils::system_properties::write("servicemanager.ready", "true") {
        error!("failed to set ro.servicemanager.ready {:?}", e);
    }

    // Move server reference into a background thread and run it forever.
    std::thread::spawn(move || {
        server.join();
    });
    Ok(())
}
+45 −2
Original line number Diff line number Diff line
@@ -857,7 +857,7 @@ cc_library_static {
    ],
}

// AIDL interface between libbinder and framework.jar
// ServiceManager AIDL interface between libbinder and framework.jar
filegroup {
    name: "libbinder_aidl",
    srcs: [
@@ -881,6 +881,15 @@ filegroup {
    visibility: [":__subpackages__"],
}

filegroup {
    name: "libbinder_rpc_aidl",
    srcs: [
        "aidl/android/os/IRpcProvider.aidl",
    ],
    path: "aidl",
    visibility: [":__subpackages__"],
}

aidl_interface {
    name: "packagemanager_aidl",
    unstable: true,
@@ -904,12 +913,44 @@ aidl_interface {
}

aidl_interface {
    name: "libbinder_aidl_test_stub",
    name: "servicemanager_aidl",
    unstable: true,
    local_include_dir: "aidl",
    srcs: [":libbinder_aidl"],
    vendor_available: true,
    backend: {
        cpp: {
            // libbinder exports this type itself so use that
            enabled: false,
        },
        rust: {
            enabled: true,
        },
        java: {
            enabled: false,
        },
    },
    visibility: [
        ":__subpackages__",
        "//system/tools/aidl:__subpackages__",
        "//frameworks/native/cmds/servicemanager/rpc_servicemanager",
    ],
}

aidl_interface {
    name: "rpc_servicemanager_aidl",
    unstable: true,
    local_include_dir: "aidl",
    srcs: [":libbinder_rpc_aidl"],
    vendor_available: true,
    backend: {
        rust: {
            enabled: true,
            apex_available: [
                "com.android.virt",
                "com.android.compos",
            ],
        },
        java: {
            enabled: false,
        },
@@ -917,6 +958,8 @@ aidl_interface {
    visibility: [
        ":__subpackages__",
        "//system/tools/aidl:__subpackages__",
        "//frameworks/native/cmds/servicemanager/rpc_servicemanager",
        "//packages/modules/Virtualization:__subpackages__",
    ],
}

+41 −9
Original line number Diff line number Diff line
@@ -19,6 +19,9 @@
#include <android/os/IAccessor.h>
#include <android/os/IServiceManager.h>
#include <binder/RpcSession.h>
#include <cutils/sockets.h>
#include <sys/socket.h>
#include <sys/un.h>

#if defined(__BIONIC__) && !defined(__ANDROID_VNDK__)
#include <android-base/properties.h>
@@ -26,6 +29,10 @@

namespace android {

// This is similar to the kernel binder servicemanager's context 0. It's the
// known socket that we expect the Unix Domain Socket servicemanager to be listening on.
const char kUdsServiceManagerName[] = ANDROID_SOCKET_DIR "/rpc_servicemanager";

#ifdef LIBBINDER_CLIENT_CACHE
constexpr bool kUseCache = true;
#else
@@ -488,15 +495,29 @@ Status BackendUnifiedServiceManager::checkServiceAccess(
[[clang::no_destroy]] static sp<BackendUnifiedServiceManager> gUnifiedServiceManager;

static bool hasOutOfProcessServiceManager() {
#ifndef BINDER_WITH_KERNEL_IPC
// We don't currently support kernel binder service management or UDS
// service management on host or when libbinder is compiled without any
// kernel binder suport. Please use setDefaultServiceManager for host
// processes that want to use service manager APIs.
#if !defined(BINDER_WITH_KERNEL_IPC) || !defined(__BIONIC__)
    return false;
#else
#if defined(__BIONIC__) && !defined(__ANDROID_VNDK__)
    return android::base::GetBoolProperty("servicemanager.installed", true);
#else
#ifdef __ANDROID_VNDK__
    return true;
#else
    return android::base::GetBoolProperty("servicemanager.installed", true);
#endif
#endif
#endif // BINDER_WITH_KERNEL_IPC
}

static sp<AidlServiceManager> getUdsServiceManager() {
    auto session = RpcSession::make();
    session->setFileDescriptorTransportMode(RpcSession::FileDescriptorTransportMode::UNIX);
    auto status = session->setupUnixDomainClient(kUdsServiceManagerName);
    if (status == OK) {
        return interface_cast<AidlServiceManager>(session->getRootObject());
    }
    return nullptr;
}

sp<BackendUnifiedServiceManager> getBackendUnifiedServiceManager() {
@@ -514,11 +535,22 @@ sp<BackendUnifiedServiceManager> getBackendUnifiedServiceManager() {

        sp<AidlServiceManager> sm = nullptr;
        while (hasOutOfProcessServiceManager() && sm == nullptr) {
            sm = interface_cast<AidlServiceManager>(
                    ProcessState::self()->getContextObject(nullptr));
            // There is either a kernel binder service manager, or an RPC binder
            // service manager
            sp<ProcessState> ps = ProcessState::selfIfKernelBinderEnabled();
            if (ps) {
                // Service management over kernel binder
                sm = interface_cast<AidlServiceManager>(ps->getContextObject(nullptr));
            } else {
                // Check for service management over Unix Domain Sockets
                sm = getUdsServiceManager();
            }

            if (sm == nullptr) {
                ALOGE("Waiting 1s on context object on %s.",
                      ProcessState::self()->getDriverName().c_str());
                std::string contextObjectName = ps
                        ? ps->getDriverName() + ", " + kUdsServiceManagerName
                        : kUdsServiceManagerName;
                ALOGE("Waiting 1s on context object(s) on %s.", contextObjectName.c_str());
                sleep(1);
            }
        }
+5 −0
Original line number Diff line number Diff line
@@ -117,6 +117,11 @@ sp<ProcessState> ProcessState::selfOrNull()
    return init(nullptr, false /*requireDefault*/);
}

sp<ProcessState> ProcessState::selfIfKernelBinderEnabled() {
    if (access(kDefaultDriver, R_OK) == -1) return nullptr;
    return init(kDefaultDriver, false /*requireDefault*/);
}

[[clang::no_destroy]] static sp<ProcessState> gProcess;
[[clang::no_destroy]] static std::mutex gProcessMutex;

Loading