Fix a timing issue of app labels changed event 15/319415/4
authorHwankyu Jhun <h.jhun@samsung.com>
Wed, 23 Oct 2024 01:11:34 +0000 (10:11 +0900)
committerHwanKyu Jhun <h.jhun@samsung.com>
Wed, 23 Oct 2024 01:26:27 +0000 (01:26 +0000)
If the launchpad-process-pool receives app labels changed event before the lux,
it causes the failure issue of calling the security_manager_prepare_app2().
When getting the app labels changed event, the lux notifies that to the
launchpad-process-pool. And then, the launchpad-process-pool kills and
executes the loader processes.

Change-Id: Idb8fb7e812a1467c8702e07c2fb06e09a3ff963b
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
src/launchpad-process-pool/launchpad.cc
src/launchpad-process-pool/launchpad.hh
src/launchpad-process-pool/loader_manager.cc
src/launchpad-process-pool/loader_manager.hh
src/launchpad-process-pool/lux_manager.cc
src/launchpad-process-pool/lux_manager.hh
src/lux/src/lux/app_labels_monitor.rs
src/lux/src/lux/mod.rs
src/lux/src/main.rs

index 4203658eaa489c44cf357ba632beef1b03f665b2..3250803d15989ff88e401337362a7b4a85c4cb34 100644 (file)
@@ -691,6 +691,10 @@ void Launchpad::OnLuxSigchld(pid_t pid, int status) {
   SignalManager::GetInst().HandleSigchld(pid, status);
 }
 
+void Launchpad::OnLuxAppLabelsChanged() {
+  LoaderManager::GetInst().HandleAppLabelsChanged();
+}
+
 void Launchpad::OnLoaderPrepared(LoaderContext* loader_context) {
   _W("Loader is prepared. name(%s), pid(%d)",
      loader_context->GetLoaderName().c_str(), loader_context->GetPid());
index 89b72fe93cf42e84df3c6c1c2070bd6d77323a09..24244ead4df02596f54d563a23ae7fff4d81e5e5 100644 (file)
@@ -95,6 +95,7 @@ class Launchpad : public IOChannel::IEvent,
   void OnLoaderPrepared(LoaderContext* loader_context) override;
   void OnLoaderLaunched(LoaderContext* loader_context) override;
   void OnLuxSigchld(pid_t pid, int status) override;
+  void OnLuxAppLabelsChanged() override;
 
  private:
   int argc_;
index f7b42713492aec6f876b063b3a456908d42e54b6..9df3f57b2ed18e715d34236f23d885c2acb8e755 100644 (file)
@@ -435,7 +435,7 @@ LoaderManager::LoaderManager() : sequencer_(new Sequencer(this)) {}
 
 LoaderManager::~LoaderManager() { Dispose(); }
 
-void LoaderManager::OnAppLabelsChanged() {
+void LoaderManager::HandleAppLabelsChanged() {
   _W("BEGIN");
   LoaderExecutor::GetInst().DisposeCandidateProcess();
   for (auto& context : loader_contexts_) {
@@ -459,6 +459,8 @@ void LoaderManager::OnAppLabelsChanged() {
   _W("END");
 }
 
+void LoaderManager::OnAppLabelsChanged() {}
+
 void LoaderManager::OnMemoryStatusChanged(bool low_memory,
                                           bool should_check_pss) {
   if (should_check_pss)
index a433670d81512b1163c474b136311cf4ab1aeb07..065b77b872086f4efe1bfa2379d0842069175ac8 100644 (file)
@@ -83,6 +83,7 @@ class LoaderManager : public AppDefinedLoaderInfoManager::IEvent,
   std::shared_ptr<LoaderContext> FindLoaderContextFromName(
       const std::string& loader_name);
   std::shared_ptr<LoaderContext> FindLoaderContextFromPid(pid_t pid);
+  void HandleAppLabelsChanged();
 
  private:
   LoaderManager();
index 946f8ff045d7185ad7eb57eb6eea4931edd0adb1..cb041fb1ad4731234f3e6f0a6c52fe20a79439c3 100644 (file)
@@ -47,14 +47,6 @@ void LuxManager::Init() {
 
   if (!Prepare()) return;
 
-  try {
-    sigchld_channel_.reset(new IOChannel(sigchld_socket_->GetFd(),
-                                         IOChannel::IOCondition::IO_IN, this));
-  } catch (const Exception& e) {
-    _E("Exception occurs. error=%s", e.what());
-    return;
-  }
-
   disposed_ = false;
 }
 
@@ -62,55 +54,121 @@ void LuxManager::Dispose() {
   if (disposed_) return;
 
   Kill();
-  sigchld_channel_.reset();
-  sigchld_socket_.reset();
-  read_socket_.reset();
-  write_socket_.reset();
+  IgnoreEvents();
+  ClosePipeFds();
   disposed_ = true;
 }
 
-bool LuxManager::Prepare() {
-  if (pid_ > 0) return false;
+bool LuxManager::PreparePipeFds() {
+  read_fd_ = -1;
+  write_fd_ = -1;
+  sigchld_fd_ = -1;
+  label_monitor_fd_ = -1;
 
   int pipe_fd[2];
   if (CreatePipe(&pipe_fd) != 0) return false;
 
   read_socket_.reset(new Socket(pipe_fd[0]));
-  int write_fd = pipe_fd[1];
+  write_fd_ = pipe_fd[1];
 
   if (CreatePipe(&pipe_fd) != 0) {
-    close(write_fd);
+    ClosePipeFds();
     return false;
   }
 
-  int read_fd = pipe_fd[0];
+  read_fd_ = pipe_fd[0];
   write_socket_.reset(new Socket(pipe_fd[1]));
 
   if (CreatePipe(&pipe_fd) != 0) {
-    close(read_fd);
-    close(write_fd);
+    ClosePipeFds();
     return false;
   }
 
-  int sigchld_fd = pipe_fd[0];
+  sigchld_fd_ = pipe_fd[0];
   sigchld_socket_.reset(new Socket(pipe_fd[1]));
 
-  _W("read_socket=%d, write_socket=%d, sigchld_socket=%d",
-     read_socket_->GetFd(), write_socket_->GetFd(), sigchld_socket_->GetFd());
+  if (CreatePipe(&pipe_fd) != 0) {
+    ClosePipeFds();
+    return false;
+  }
+
+  label_monitor_fd_ = pipe_fd[0];
+  label_monitor_socket_.reset(new Socket(pipe_fd[1]));
+  return true;
+}
+
+void LuxManager::ClosePipeFds() {
+  if (label_monitor_fd_ > -1) {
+    close(label_monitor_fd_);
+    label_monitor_fd_ = -1;
+  }
+
+  if (sigchld_fd_ > -1) {
+    close(sigchld_fd_);
+    sigchld_fd_ = -1;
+  }
+
+  if (read_fd_ > -1) {
+    close(read_fd_);
+    read_fd_ = -1;
+  }
+
+  if (write_fd_ > -1) {
+    close(write_fd_);
+    write_fd_ = -1;
+  }
+
+  label_monitor_socket_.reset();
+  sigchld_socket_.reset();
+  read_socket_.reset();
+  write_socket_.reset();
+}
+
+bool LuxManager::ListenEvents() {
+  try {
+    sigchld_channel_.reset(new IOChannel(sigchld_socket_->GetFd(),
+                                         IOChannel::IOCondition::IO_IN, this));
+    label_monitor_channel_.reset(new IOChannel(
+        label_monitor_socket_->GetFd(), IOChannel::IOCondition::IO_IN, this));
+  } catch (const Exception& e) {
+    _E("Exception occurs. error=%s", e.what());
+    return false;
+  }
+
+  return true;
+}
+
+void LuxManager::IgnoreEvents() {
+  sigchld_channel_.reset();
+  label_monitor_channel_.reset();
+}
+
+bool LuxManager::Prepare() {
+  if (pid_ > 0) return false;
+
+  if (!PreparePipeFds()) return false;
+
+  _W("read_socket=%d, write_socket=%d, sigchld_socket=%d, "
+     "label_monitor_socket=%d",
+     read_socket_->GetFd(), write_socket_->GetFd(), sigchld_socket_->GetFd(),
+     label_monitor_socket_->GetFd());
   pid_ = Executor::Execute();
   if (pid_ < 0) {
     _E("Failed to execute lux. errno(%d)", errno);
-    close(sigchld_fd);
-    close(read_fd);
-    close(write_fd);
+    ClosePipeFds();
     return false;
   }
 
   _W("Lux process=%d", pid_);
-  sigchld_socket_.reset(new Socket(sigchld_fd));
-  read_socket_.reset(new Socket(read_fd));
-  write_socket_.reset(new Socket(write_fd));
-  return true;
+  label_monitor_socket_.reset(new Socket(label_monitor_fd_));
+  label_monitor_fd_ = -1;
+  sigchld_socket_.reset(new Socket(sigchld_fd_));
+  sigchld_fd_ = -1;
+  read_socket_.reset(new Socket(read_fd_));
+  read_fd_ = -1;
+  write_socket_.reset(new Socket(write_fd_));
+  write_fd_ = -1;
+  return ListenEvents();
 }
 
 bool LuxManager::IsPrepared() const {
@@ -146,10 +204,8 @@ pid_t LuxManager::SendAndReceive(const tizen_base::Parcel& parcel) {
 void LuxManager::HandleSigchld(pid_t pid) {
   if (pid_ != pid) return;
 
-  sigchld_channel_.reset();
-  sigchld_socket_.reset();
-  read_socket_.reset();
-  write_socket_.reset();
+  IgnoreEvents();
+  ClosePipeFds();
   pid_ = -1;
   Prepare();
 }
@@ -187,8 +243,8 @@ void LuxManager::Kill() {
 
   pid_ = -1;
 }
-void LuxManager::OnIOEventReceived(int fd, int condition) {
-  _D("fd=%d, condition=%d", fd, condition);
+
+void LuxManager::HandleSigChldEvent() {
   size_t data_size = 0;
   int ret =
       sigchld_socket_->Read(static_cast<void*>(&data_size), sizeof(data_size));
@@ -213,19 +269,50 @@ void LuxManager::OnIOEventReceived(int fd, int condition) {
   if (listener_) listener_->OnLuxSigchld(pid, status);
 }
 
+void LuxManager::HandleAppLabelsChangedEvent() {
+  size_t data_size = 0;
+  int ret = label_monitor_socket_->Read(static_cast<void*>(&data_size),
+                                        sizeof(data_size));
+  if (ret != 0) {
+    _E("Failed to receive the data. error=%d", ret);
+    return;
+  }
+
+  std::vector<uint8_t> data(data_size);
+  ret = label_monitor_socket_->Read(data.data(), data_size);
+  if (ret != 0) {
+    _E("Failed to receive the data. error=%d", ret);
+    return;
+  }
+
+  tizen_base::Parcel parcel(data.data(), data.size());
+  parcel.ReadInt32(&ret);
+  _W("[AppLabelsChanged] ret=%d", ret);
+  if (listener_) listener_->OnLuxAppLabelsChanged();
+}
+
+void LuxManager::OnIOEventReceived(int fd, int condition) {
+  _D("fd=%d, condition=%d", fd, condition);
+  if (fd == sigchld_socket_->GetFd()) HandleSigChldEvent();
+  else if (fd == label_monitor_socket_->GetFd()) HandleAppLabelsChangedEvent();
+}
+
 void LuxManager::OnExecution() {
   CPUBoostController::DoBoost(getpid(), CPUBoostController::Level::Strong, -1,
                               true);
   std::vector<int> except_fds{read_socket_->GetFd(), write_socket_->GetFd(),
-                              sigchld_socket_->GetFd()};
+                              sigchld_socket_->GetFd(),
+                              label_monitor_socket_->GetFd()};
   Util::CloseAllFds(except_fds);
 
   std::string rfd = std::to_string(read_socket_->RemoveFd());
   std::string wfd = std::to_string(write_socket_->RemoveFd());
   std::string sfd = std::to_string(sigchld_socket_->RemoveFd());
+  std::string lfd = std::to_string(label_monitor_socket_->RemoveFd());
   setenv("LUX_READ_FD", rfd.c_str(), 1);
   setenv("LUX_WRITE_FD", wfd.c_str(), 1);
   setenv("LUX_SIGCHLD_FD", sfd.c_str(), 1);
+  setenv("LUX_LABEL_MONITOR_FD", lfd.c_str(), 1);
 
   std::vector<char*> args;
   args.push_back(const_cast<char*>(kPathLux));
index 0c5ddae2c89a6c96f18f0ec73c2509c203d0ef13..18bfbfca0f1afd153c0e59c9d1475b5223360949 100644 (file)
@@ -38,6 +38,7 @@ class LuxManager : public IOChannel::IEvent,
    public:
     virtual ~IEvent() = default;
     virtual void OnLuxSigchld(pid_t pid, int status) = 0;
+    virtual void OnLuxAppLabelsChanged() = 0;
   };
 
   LuxManager(const LuxManager&) = delete;
@@ -59,10 +60,16 @@ class LuxManager : public IOChannel::IEvent,
   LuxManager();
   ~LuxManager();
 
+  bool PreparePipeFds();
+  void ClosePipeFds();
+  bool ListenEvents();
+  void IgnoreEvents();
   int CreatePipe(int (*pipe_fd)[2]);
   void Kill();
   void HandleServerEvent();
   void HandleClientEvent(int condition);
+  void HandleSigChldEvent();
+  void HandleAppLabelsChangedEvent();
   void OnIOEventReceived(int fd, int condition) override;
   void OnExecution() override;
 
@@ -74,6 +81,12 @@ class LuxManager : public IOChannel::IEvent,
   std::unique_ptr<Socket> write_socket_;
   std::unique_ptr<Socket> sigchld_socket_;
   std::unique_ptr<IOChannel> sigchld_channel_;
+  std::unique_ptr<Socket> label_monitor_socket_;
+  std::unique_ptr<IOChannel> label_monitor_channel_;
+  int read_fd_ = -1;
+  int write_fd_ = -1;
+  int sigchld_fd_ = -1;
+  int label_monitor_fd_ = -1;
 };
 
 }  // namespace launchpad
index 30d6fb25e3d0a59cea656e498ca086aca7a8eb3c..a7585ca01d97e495c0055410256317f39bed6514 100644 (file)
@@ -21,6 +21,7 @@ extern "C" {
 pub struct AppLabelsMonitor {
     handle: *mut c_void,
     source_id: c_uint,
+    write_fd: i32,
     disposed: bool,
 }
 
@@ -36,22 +37,25 @@ extern "C" fn app_labels_monitor_callback(
     data: *mut c_void,
 ) -> glib_sys::gboolean {
     unsafe {
+        debug!("BEGIN");
         let handle: &mut AppLabelsMonitor = &mut *(data as *mut AppLabelsMonitor);
         handle.process();
+        debug!("END");
         G_SOURCE_CONTINUE
     }
 }
 
 impl AppLabelsMonitor {
     pub fn new() -> Self {
-        AppLabelsMonitor { handle: ptr::null_mut(), source_id: 0, disposed: true }
+        AppLabelsMonitor { handle: ptr::null_mut(), source_id: 0, write_fd: -1, disposed: true }
     }
 
-    pub fn init(&mut self) -> Result<(), ()> {
+    pub fn init(&mut self, write_fd: i32) -> Result<(), ()> {
         if !self.disposed {
             return Ok(());
         }
 
+        self.write_fd = write_fd;
         let mut fd: i32 = -1;
         let ret = unsafe { security_manager_app_labels_monitor_init(&mut self.handle) };
         if ret != SECURITY_MANAGER_SUCCESS {
@@ -105,10 +109,45 @@ impl AppLabelsMonitor {
               self.handle = ptr::null_mut();
             }
         }
+
+        if self.write_fd > -1 {
+            unsafe {
+                close(self.write_fd);
+                self.write_fd = -1;
+            }
+        }
+
         self.disposed = true;
     }
 
     fn process(&mut self) {
-        unsafe { security_manager_app_labels_monitor_process(self.handle) };
+        let ret = unsafe { security_manager_app_labels_monitor_process(self.handle) };
+        let mut parcel = Parcel::new();
+        parcel.write_i32(ret as i32);
+        self.write_parcel(&mut parcel);
+    }
+
+    fn write_parcel(&mut self, parcel: &mut Parcel) -> Result<(), ()> {
+        let mut data = parcel.get_raw_data().unwrap();
+        let mut data_size: c_ulong = (data.len() as usize).try_into().unwrap();
+        let nbytes = unsafe {
+            write(
+                self.write_fd,
+                (&mut data_size as *mut c_ulong).cast::<u8>() as *mut c_void,
+                mem::size_of::<c_ulong>(),
+            )
+        };
+        if nbytes < 0 {
+            error!("Failed to write data size");
+            return Err(());
+        }
+
+        let nbytes = unsafe { write(self.write_fd, data.as_mut_ptr() as *mut _, data.len()) };
+        if nbytes < 0 {
+            error!("Failed to write data");
+            return Err(());
+        }
+
+        Ok(())
     }
 }
index 2f79c2a709c0e6804f945642728b747406d978d3..66981bbb80370c48cea1b25198c494c3048e0b9d 100644 (file)
@@ -114,7 +114,7 @@ impl Lux {
         }
     }
 
-    pub fn run(&mut self, read_fd: i32, write_fd: i32, sigchld_fd: i32) -> Result<(), ()> {
+    pub fn run(&mut self, read_fd: i32, write_fd: i32, sigchld_fd: i32, label_monitor_fd: i32) -> Result<(), ()> {
         self.read_fd = read_fd;
         self.write_fd = write_fd;
         self.sigchld_manager.init(sigchld_fd);
@@ -131,7 +131,7 @@ impl Lux {
             return Err(());
         }
 
-        self.app_labels_monitor.init();
+        self.app_labels_monitor.init(label_monitor_fd);
         self.region_format_config.listen();
         self.language_config.listen();
         self.clear_boosting();
index c360bf2e7af36762804e78307717a3dbd252cf13..4427536fab038129e0fd0bae47ea8e69d957ae90 100644 (file)
@@ -23,13 +23,17 @@ fn main() {
         .ok()
         .and_then(|fd| fd.parse::<i32>().ok())
         .unwrap_or(-1);
+    let label_monitor_fd = env::var("LUX_LABEL_MONITOR_FD")
+        .ok()
+        .and_then(|fd| fd.parse::<i32>().ok())
+        .unwrap_or(-1);
 
-    if read_fd < 0 || write_fd < 0 || sigchld_fd < 0 {
-        print!("Failed to find read/write fds. {read_fd} : {write_fd} : {sigchld_fd}");
+    if read_fd < 0 || write_fd < 0 || sigchld_fd < 0 || label_monitor_fd < 0 {
+        print!("Failed to find read/write fds. {read_fd} : {write_fd} : {sigchld_fd} : {label_monitor_fd}");
         std::process::exit(-1);
     }
 
-    debug!("read_fd={}, write_fd={}, sigchld_fd={}", read_fd, write_fd, sigchld_fd);
+    debug!("read_fd={}, write_fd={}, sigchld_fd={}, label_monitor_fd={}", read_fd, write_fd, sigchld_fd, label_monitor_fd);
     let mut lux = Lux::new();
-    lux.run(read_fd, write_fd, sigchld_fd);
+    lux.run(read_fd, write_fd, sigchld_fd, label_monitor_fd);
 }