struct_types_[std::move(name)] = std::move(type_name);
}
+void CBodyGeneratorBase::GetRpcPortInternalAPIs(std::ofstream& stream) {
+ stream << SmartIndent(CB_RPC_PORT_INTERNAL_APIS);
+}
+
void CBodyGeneratorBase::GenIncludeLemHeaders(std::ofstream& stream) {
stream << SmartIndent(CB_LEM_HEADER);
}
std::string GetHandlePrefixReverse();
void GenRemoteExceptionDefinition(std::ofstream& stream);
void GenRemoteExceptionBase(std::ofstream& stream);
+ void GetRpcPortInternalAPIs(std::ofstream& stream);
private:
void AddTypeName(const Structure& st);
}
)__cpp_cb";
+constexpr const char CB_RPC_PORT_INTERNAL_APIS[] =
+R"__cpp_cb(
+
+typedef int (*rpc_port_get_peer_info_t)(rpc_port_h h, pid_t* pid, uid_t* uid);
+
+static rpc_port_get_peer_info_t rpc_port_get_peer_info;
+
+static bool rpc_port_internal_loaded;
+
+static void rpc_port_internal_init(void)
+{
+ if (rpc_port_internal_loaded)
+ return;
+
+ const char * symbol = "rpc_port_get_peer_info";
+ rpc_port_get_peer_info = dlsym(RTLD_DEFAULT, symbol);
+ if (rpc_port_get_peer_info == nullptr) {
+ _E("Failed to find symbol(%s). Please check rpc-port version", symbol);
+ return;
+ }
+
+ rpc_port_internal_loaded = true;
+}
+
+)__cpp_cb";
+
} // namespace version2
} // namespace tidl
GenLogDefinition(stream);
GenVersionDefinition(stream);
GenBaseDefinition(stream);
+ GenUidMinDefinition(stream);
+ GetRpcPortInternalAPIs(stream);
GenThreadEnableDefinition(stream);
GenInterfaceEnums(stream);
GenUnitMapDefinition(stream);
stream << SmartIndent(CB_DELEGATE_BASE);
}
+void CStubBodyGenerator::GenUidMinDefinition(std::ofstream& stream) {
+ stream << std::string(CB_UID_MIN_DEF);
+}
+
// @see #CB_THREAD_ENABLE_DEF
void CStubBodyGenerator::GenThreadEnableDefinition(std::ofstream& stream) {
if (!options_->IsThreadEnabled())
std::string GenAccessControlSet(const Interface& iface);
void GenDelegateDefinition(std::ofstream& stream);
void GenDelegateBase(std::ofstream& stream);
+ void GenUidMinDefinition(std::ofstream& stream);
std::string GenLemContext();
void GenLemDefinition(std::ofstream& stream);
void GenLemBase(std::ofstream& stream);
}
)__c_cb";
+constexpr const char CB_UID_MIN_DEF[] =
+R"__c_cb(
+#ifndef REGULAR_UID_MIN
+#define REGULAR_UID_MIN 5000
+#endif
+)__c_cb";
+
constexpr const char CB_THREAD_ENABLE_DEF[] =
R"__c_cb(
#define TIDL_THREAD_ENABLE 1
return RPC_PORT_ERROR_NONE;
}
+ rpc_port_internal_init();
+
g_rec_mutex_init(&__<NAME>.mutex);
__<NAME>.callback = *callback;
__<NAME>.user_data = user_data;
static const char *privileges[] = {
<PRIVILEGES>
};
+int ret;
+uid_t uid;
+pid_t pid;
*sync = <SYNC_TRUE_OR_FALSE>;
+
+if (ARRAY_SIZE(privileges) < 1)
+ return RPC_PORT_ERROR_NONE;
+
+ret = rpc_port_get_peer_info(h->port, &pid, &uid);
+if (ret == RPC_PORT_ERROR_NONE && uid < REGULAR_UID_MIN) {
+ _W("Bypass access control. pid(%d), uid(%u)", pid, uid);
+ return RPC_PORT_ERROR_NONE;
+}
+
for (size_t i = 0; i < ARRAY_SIZE(privileges); ++i) {
if (!g_hash_table_contains(h->privileges, privileges[i])) {
_E("Permission denied. %s : %s", h->sender, privileges[i]);
return std::string(CB_HEADER_REMOTE_EXCEPTION);
}
+std::string CppGeneratorBase::GenRpcPortInternals() {
+ return std::string(CB_RPC_PORT_INTERNAL_APIS);
+}
+
} // namespace version2
} // namespace tidl
std::string GenEnumerations(const Enums& enums);
std::string GenRemoteException();
std::string GenRemoteExceptionForHeader();
+ std::string GenRpcPortInternals();
private:
void AddTypeName(const Structure& st);
#define EXPORT_API extern "C" __attribute__ ((visibility("default")))
)__cpp_cb";
+constexpr const char CB_RPC_PORT_INTERNAL_APIS[] =
+R"__cpp_cb(
+using rpc_port_get_peer_info_t = int (*)(rpc_port_h h, pid_t* pid, uid_t* uid);
+
+rpc_port_get_peer_info_t rpc_port_get_peer_info;
+
+class RpcPortInternals {
+ public:
+ RpcPortInternals() {
+ std::string symbol = "rpc_port_get_peer_info";
+ rpc_port_get_peer_info = reinterpret_cast<rpc_port_get_peer_info_t>(
+ dlsym(RTLD_DEFAULT, symbol.c_str()));
+ if (rpc_port_get_peer_info == nullptr) {
+ _E("Failed to find symbol(%s). Please check rpc-port version", symbol.c_str());
+ return;
+ }
+ }
+};
+
+RpcPortInternals rpc_port_internals_;
+
+)__cpp_cb";
+
} // namespace version2
} // namespace tidl
void CppStubBodyGenerator::GenLemAnonymousNamespace(std::ofstream& stream) {
ReplaceAll(CB_LEM_ANONYMOUS_NAMESPACE)
.Change("<LEM_CONTEXT>", GenLemContext())
+ .Change("<RPC_PORT_INTERNALS>", GenRpcPortInternals())
.Transform([&](std::string code) { return SmartIndent(code); })
.Out(stream);
stream << NLine(1);
<IMPL_SERVICE_BASE_SET_PRIVILEGE_MAP>
}
-bool <CLS_NAME>::ServiceBase::CheckPrivileges(int method_id) {
+bool <CLS_NAME>::ServiceBase::CheckPrivileges(rpc_port_h port, int method_id) {
+ int ret;
+ uid_t uid;
+ pid_t pid;
+
auto found = privilege_map_.find(method_id);
if (found == privilege_map_.end())
return true;
+ ret = rpc_port_get_peer_info(port, &pid, &uid);
+ if(ret == RPC_PORT_ERROR_NONE && uid < kRegularUidMin) {
+ _W("Bypass access control. pid(%d), uid(%u)", pid, uid);
+ return true;
+ }
+
for (const auto& privilege : found->second) {
if (privileges_.find(privilege) == privileges_.end()) {
_E("%s does not exist", privilege.c_str());
constexpr const char CB_INTERFACE_SERVICE_BASE_DISPATCH_FUNC_ASYNC[] =
R"__cpp_cb(
void <IFACE_NAME>::ServiceBase::Dispatch<NAME>(rpc_port_h port, rpc_port_h callback_port, int seq_num, const UnitMap& unit_map) {
- if (!CheckPrivileges(static_cast<int>(MethodId::<NAME>))) {
+ if (!CheckPrivileges(port, static_cast<int>(MethodId::<NAME>))) {
_E("Permission denied");
return;
}
R"__cpp_cb(
void <IFACE_NAME>::ServiceBase::Dispatch<NAME>(rpc_port_h port, rpc_port_h callback_port, int seq_num, const UnitMap& unit_map) {
UnitMap map_;
- if (!CheckPrivileges(static_cast<int>(MethodId::<NAME>))) {
+ if (!CheckPrivileges(port, static_cast<int>(MethodId::<NAME>))) {
_E("Permission denied");
RemoteException remote_except(RPC_PORT_ERROR_PERMISSION_DENIED, "Permission denied");
map_.Write("[REMOTE_EXCEPTION]", remote_except);
R"__cpp_cb(
namespace {
+constexpr const uid_t kRegularUidMin = 5000;
+
rpc_port_parcel_h Clone(rpc_port_parcel_h parcel) {
void* raw = nullptr;
unsigned int size = 0;
<LEM_CONTEXT>
+<RPC_PORT_INTERNALS>
+
} // namespace
)__cpp_cb";
static bool PrivilegeInfoCb(const char* privilege_name, void* user_data);
void LoadPrivileges();
void SetPrivilegeMap();
- bool CheckPrivileges(int method_id);
+ bool CheckPrivileges(rpc_port_h port, int method_id);
<SERVICE_BASE_DISPATCH_FUNCS>
<SERVICE_BASE_IMPL_THREAD_MEMBER>
privilege_map: HashMap<i32, LinkedList<String>>,
privileges: HashSet<String>,
handler: Box<dyn ServiceHandler + Send>,
+ is_app:bool
}
impl Service {
privilege_map: HashMap::new(),
privileges: HashSet::new(),
handler: (factory)(peer),
+ is_app: true
};
service.load_privileges();
let sender = self.get_sender();
let ret = unsafe { app_info_create(CString::new(sender).unwrap().as_ptr() as *const c_char, &mut app_info) };
if ret != 0 {
+ self.is_app = false;
error!("app_info_create failed. ret({})", ret);
return;
}
fn check_privileges(&self, method_id: i32) -> bool {
info!("method_id {method_id}");
+ if self.is_app == false {
+ info!("Bypass access control");
+ return true;
+ }
+
match self.privilege_map.get(&method_id) {
Some(privileges) => {
for privilege in privileges {