Add access control for daemon 36/322736/5
authorjusung son <jusung07.son@samsung.com>
Tue, 15 Apr 2025 07:24:38 +0000 (16:24 +0900)
committerjusung son <jusung07.son@samsung.com>
Mon, 28 Apr 2025 06:00:02 +0000 (15:00 +0900)
Change-Id: I08489012b2c46c72a8ac311a69daec2e7e35468d
Signed-off-by: jusung son <jusung07.son@samsung.com>
idlc/gen/version2/c_body_generator_base_cb.hh
idlc/gen/version2/c_stub_body_generator_cb.hh
idlc/gen/version2/cpp_generator_base_cb.hh
idlc/gen/version2/cpp_stub_body_generator_cb.hh
idlc/gen/version2/cpp_stub_header_generator_cb.hh
idlc/gen/version2/rs_stub_gen_cb.h

index 879edb405804634e93c2c0549724e50101120709..5d16a96b87008a1c3246b51f93c19f091d87d524 100644 (file)
@@ -1476,6 +1476,7 @@ typedef int (*rpc_port_parcel_set_reader_t)(rpc_port_parcel_h h, unsigned int re
 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;
@@ -1487,6 +1488,7 @@ static rpc_port_parcel_set_reader_t rpc_port_parcel_set_reader;
 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;
 
@@ -1566,6 +1568,13 @@ static void rpc_port_internal_init(void)
       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;
 }
 
index 86cce7f4fb5c5f9dd66a902c5406ef3c4a5e33b2..460a0248cf2f940598a38647bc100d2f2a889032 100644 (file)
@@ -84,6 +84,11 @@ R"__c_cb(
 #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?>
@@ -1798,8 +1803,21 @@ R"__c_cb(
 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]);
index 02b27e645a3661ec6213a6054329fd6a02ba11a7..af5239d4dde82d03d0e535be9a80d70446b53d93 100644 (file)
@@ -965,6 +965,7 @@ using rpc_port_parcel_set_reader_t = int (*)(rpc_port_parcel_h h, unsigned int r
 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;
@@ -976,6 +977,7 @@ rpc_port_parcel_set_reader_t rpc_port_parcel_set_reader;
 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:
@@ -1061,6 +1063,14 @@ class RpcPortInternals {
       _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;
+    }
   }
 };
 
index d05f7ffd64cbabf7d1714b21dae125d2b58ad55f..0ed537f09a617315a0fe7ab58f98606fbe0a44e6 100644 (file)
@@ -63,6 +63,8 @@ R"__cpp_cb(
 
 namespace {
 
+constexpr const uid_t kRegularUidMin = 5000;
+
 bool IdleAddOnce(GMainContext* context, std::function<void()>* func) {
   auto* source = g_idle_source_new();
   if (source == nullptr) {
@@ -324,11 +326,20 @@ void <CLS_NAME>::ServiceBase::SetPrivilegeMap() {
   <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());
@@ -524,7 +535,7 @@ active_object_->Send(std::make_shared<Job>(port, callback_port, parcel, std::mov
 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;
   }
@@ -551,7 +562,7 @@ void <IFACE_NAME>::ServiceBase::Dispatch<NAME>(rpc_port_h port, rpc_port_h callb
   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()
index d0a91ee141e708b153f834df0848f5e29ce40981..06efe23a2fb8ccb436f623df054cfa9660e658e8 100644 (file)
@@ -361,7 +361,7 @@ class <CLS_NAME> : public LocalExecution::IEvent {
     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*>
index 05c1b8aece22a0fdcf2861573394d4733447986d..75c905f91afcfcc0f5554ab69db06ba7a29259ce 100644 (file)
@@ -377,6 +377,7 @@ pub mod <MOD_NAME> {
         privilege_map: HashMap<i32, LinkedList<String>>,
         privileges: HashSet<String>,
         handler: Box<dyn ServiceHandler + Send>,
+        is_app:bool
     }
 
     impl Service {
@@ -392,6 +393,7 @@ pub mod <MOD_NAME> {
                 privilege_map: HashMap::new(),
                 privileges: HashSet::new(),
                 handler: (factory)(peer),
+                is_app: true
             };
 
             service.load_privileges();
@@ -462,6 +464,7 @@ pub mod <MOD_NAME> {
             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;
             }
@@ -502,6 +505,11 @@ pub mod <MOD_NAME> {
 
         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 {