typedef int (*rpc_port_parcel_write_fd_t)(rpc_port_parcel_h h, int fd);
typedef int (*rpc_port_parcel_read_fd_t)(rpc_port_parcel_h h, int* fd);
typedef int (*rpc_port_parcel_clone_t)(rpc_port_parcel_h* h, rpc_port_parcel_h origin);
+typedef int (*rpc_port_get_peer_info_t)(rpc_port_h h, pid_t* pid, uid_t* uid);
static rpc_port_parcel_reserve_t rpc_port_parcel_reserve;
static rpc_port_parcel_create_from_parcel_t rpc_port_parcel_create_from_parcel;
static rpc_port_parcel_write_fd_t rpc_port_parcel_write_fd;
static rpc_port_parcel_read_fd_t rpc_port_parcel_read_fd;
static rpc_port_parcel_clone_t rpc_port_parcel_clone;
+static rpc_port_get_peer_info_t rpc_port_get_peer_info;
static bool rpc_port_internal_loaded;
return;
}
+ 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;
}
#ifndef EXPORT_API
#define EXPORT_API extern "C" __attribute__ ((visibility("default")))
#endif
+
+#ifndef REGULAR_UID_MIN
+#define REGULAR_UID_MIN 5000
+#endif
+
<IS_THREAD_ENABLE?>
#define TIDL_THREAD_ENABLE 1
</IS_THREAD_ENABLE?>
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]);
using rpc_port_parcel_write_fd_t = int (*)(rpc_port_parcel_h h, int fd);
using rpc_port_parcel_read_fd_t = int (*)(rpc_port_parcel_h h, int* fd);
using rpc_port_parcel_clone_t = int (*)(rpc_port_parcel_h* h, rpc_port_parcel_h origin);
+using rpc_port_get_peer_info_t = int (*)(rpc_port_h h, pid_t* pid, uid_t* uid);
rpc_port_parcel_reserve_t rpc_port_parcel_reserve;
rpc_port_parcel_create_from_parcel_t rpc_port_parcel_create_from_parcel;
rpc_port_parcel_write_fd_t rpc_port_parcel_write_fd;
rpc_port_parcel_read_fd_t rpc_port_parcel_read_fd;
rpc_port_parcel_clone_t rpc_port_parcel_clone;
+rpc_port_get_peer_info_t rpc_port_get_peer_info;
class RpcPortInternals {
public:
_E("Failed to find symbol(%s). Please check rpc-port version", symbol.c_str());
return;
}
+
+ 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;
+ }
}
};
namespace {
+constexpr const uid_t kRegularUidMin = 5000;
+
bool IdleAddOnce(GMainContext* context, std::function<void()>* func) {
auto* source = g_idle_source_new();
if (source == nullptr) {
<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;
}
rpc_port_parcel_get_header(parcel_, &header_);
rpc_port_parcel_header_set_seq_num(header_, seq_num);
- 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");
UnitMap()
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*>
void Dispatch<NAME>(rpc_port_h port, rpc_port_h callback_port, int seq_num, const UnitMap& unit_map);
</SERVICE_BASE_DISPATCH_FUNCS*>
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 c_sender = CString::new(sender).unwrap();
let ret = unsafe { app_info_create(c_sender.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 {