Merge tag 'android-security-11.0.0_r49' into int/11/fp3

Android security 11.0.0 release 49

* tag 'android-security-11.0.0_r49':
  Fix UAF problem in wificond

Change-Id: Ib493dc0b09925986e4e16f31a6b756a4d0f9aa14
diff --git a/Android.bp b/Android.bp
index 0578933..c320326 100644
--- a/Android.bp
+++ b/Android.bp
@@ -50,6 +50,8 @@
         "libutils",
         "libwifi-system-iface",
         "android.system.wifi.keystore@1.0",
+        "libvndksupport",
+        "libprocessgroup",
     ],
     static_libs: [
         "libwificond", // Wificond daemon
@@ -93,6 +95,16 @@
         "libwificond_nl",
         "libwificond_event_loop",
     ],
+    arch: {
+        arm: {
+            cppflags: [
+                "-Wall",
+                "-Werror",
+                "-Wno-unused-parameter",
+                "-DARCH_ARM_32",
+            ],
+        },
+    }
 }
 
 //
diff --git a/client_interface_impl.cpp b/client_interface_impl.cpp
index 38a59ff..d715a40 100644
--- a/client_interface_impl.cpp
+++ b/client_interface_impl.cpp
@@ -91,6 +91,10 @@
   client_interface_->bssid_.fill(0);
 }
 
+void MlmeEventHandlerImpl::OnChSwitchNotify() {
+  client_interface_->RefreshAssociateFreq();
+}
+
 void MlmeEventHandlerImpl::OnDisassociate(unique_ptr<MlmeDisassociateEvent> event) {
   client_interface_->is_associated_ = false;
   client_interface_->bssid_.fill(0);
@@ -132,6 +136,8 @@
           on_frame_tx_status_event_handler_ = [](bool was_acked) {};
         }
       });
+    netlink_utils_->SubscribeChannelSwitchEvent(interface_index_,
+	std::bind(&ClientInterfaceImpl::OnChannelSwitchEvent, this, _1));
 
   netlink_utils_->SubscribeChannelSwitchEvent(interface_index_,
       std::bind(&ClientInterfaceImpl::OnChannelSwitchEvent, this, _1));
diff --git a/client_interface_impl.h b/client_interface_impl.h
index 4ecbf1d..8cf2c7c 100644
--- a/client_interface_impl.h
+++ b/client_interface_impl.h
@@ -48,6 +48,7 @@
   void OnAssociate(std::unique_ptr<MlmeAssociateEvent> event) override;
   void OnDisconnect(std::unique_ptr<MlmeDisconnectEvent> event) override;
   void OnDisassociate(std::unique_ptr<MlmeDisassociateEvent> event) override;
+  void OnChSwitchNotify() override;
 
  private:
   ClientInterfaceImpl* client_interface_;
diff --git a/main.cpp b/main.cpp
index 0c17edf..965aa03 100644
--- a/main.cpp
+++ b/main.cpp
@@ -103,6 +103,7 @@
   android::IPCThreadState::self()->handlePolledCommands();
 }
 
+
 int main(int argc, char** argv) {
   android::base::InitLogging(argv, android::base::LogdLogger(android::base::SYSTEM));
   LOG(INFO) << "wificond is starting up...";
diff --git a/net/mlme_event_handler.h b/net/mlme_event_handler.h
index 3587604..cf1e793 100644
--- a/net/mlme_event_handler.h
+++ b/net/mlme_event_handler.h
@@ -35,6 +35,7 @@
   virtual void OnAssociate(std::unique_ptr<MlmeAssociateEvent> event) = 0;
   virtual void OnDisconnect(std::unique_ptr<MlmeDisconnectEvent> event) = 0;
   virtual void OnDisassociate(std::unique_ptr<MlmeDisassociateEvent> event) = 0;
+  virtual void OnChSwitchNotify();
 
 };
 
diff --git a/net/netlink_manager.cpp b/net/netlink_manager.cpp
index 0238f0b..1fa66c4 100644
--- a/net/netlink_manager.cpp
+++ b/net/netlink_manager.cpp
@@ -47,7 +47,7 @@
 // netlink.h suggests NLMSG_GOODSIZE to be at most 8192 bytes.
 constexpr int kReceiveBufferSize = 8 * 1024;
 constexpr uint32_t kBroadcastSequenceNumber = 0;
-constexpr int kMaximumNetlinkMessageWaitMilliSeconds = 300;
+constexpr int kMaximumNetlinkMessageWaitMilliSeconds = 1000;
 uint8_t ReceiveBuffer[kReceiveBufferSize];
 
 void AppendPacket(vector<unique_ptr<const NL80211Packet>>* vec,
@@ -642,6 +642,10 @@
     }
     return;
   }
+  if (command == NL80211_CMD_CH_SWITCH_NOTIFY) {
+    handler->second->OnChSwitchNotify();
+    return;
+  }
 
 }
 
diff --git a/net/netlink_utils.cpp b/net/netlink_utils.cpp
index c31249d..47b56dc 100644
--- a/net/netlink_utils.cpp
+++ b/net/netlink_utils.cpp
@@ -53,7 +53,7 @@
 uint32_t k5GHzFrequencyLowerBound = 5000;
 // This upper bound will exclude any 5.9Ghz channels which belong to 802.11p
 // for "vehicular communication systems".
-uint32_t k5GHzFrequencyUpperBound = 5865;
+uint32_t k5GHzFrequencyUpperBound = 5885;
 
 uint32_t k6GHzFrequencyLowerBound = 5925;
 uint32_t k6GHzFrequencyUpperBound = 7125;
@@ -104,6 +104,7 @@
   supports_high_accuracy_oneshot_scan =
       IsExtFeatureFlagSet(ext_feature_flags_bytes,
                           NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN);
+
   // TODO (b/112029045) check if sending frame at specified MCS is supported
   supports_tx_mgmt_frame_mcs = false;
   supports_ext_sched_scan_relative_rssi =
@@ -123,8 +124,8 @@
 
 NetlinkUtils::~NetlinkUtils() {}
 
-bool NetlinkUtils::GetWiphyIndex(uint32_t* out_wiphy_index,
-                                 const std::string& iface_name) {
+bool NetlinkUtils::GetWiphyIndices(std::vector<uint32_t>* wiphy_index_list,
+                                   const std::string& iface_name) {
   NL80211Packet get_wiphy(
       netlink_manager_->GetFamilyId(),
       NL80211_CMD_GET_WIPHY,
@@ -161,14 +162,29 @@
                  << static_cast<int>(packet->GetCommand());
       return false;
     }
-    if (!packet->GetAttributeValue(NL80211_ATTR_WIPHY, out_wiphy_index)) {
+    uint32_t wiphy_index;
+    if (!packet->GetAttributeValue(NL80211_ATTR_WIPHY, &wiphy_index)) {
       LOG(ERROR) << "Failed to get wiphy index from reply message";
       return false;
     }
+    wiphy_index_list->push_back(wiphy_index);
   }
   return true;
 }
 
+bool NetlinkUtils::GetWiphyIndex(uint32_t* out_wiphy_index,
+                                 const std::string& iface_name) {
+  std::vector<uint32_t> wiphy_index_list;
+
+  if (!GetWiphyIndices(&wiphy_index_list, iface_name)) {
+    LOG(ERROR) << "Failed to get wiphy indices";
+    return false;
+  }
+
+  *out_wiphy_index = wiphy_index_list.back();
+  return true;
+}
+
 bool NetlinkUtils::GetWiphyIndex(uint32_t* out_wiphy_index) {
   return GetWiphyIndex(out_wiphy_index, "");
 }
@@ -723,6 +739,9 @@
       // Return invalid tx rate to avoid breaking the get station cmd
       tx_bitrate = 0;
     }
+  } else {
+      LOG(ERROR) << "Failed to get NL80211_STA_INFO_TX_BITRATE";
+      return false;
   }
   NL80211NestedAttr rx_bitrate_attr(0);
   uint32_t rx_bitrate = 0;
diff --git a/net/netlink_utils.h b/net/netlink_utils.h
index df92e7d..53d9a48 100644
--- a/net/netlink_utils.h
+++ b/net/netlink_utils.h
@@ -172,6 +172,7 @@
 class MlmeEventHandler;
 class NetlinkManager;
 class NL80211Packet;
+class NL80211NestedAttr;
 
 // Provides NL80211 helper functions.
 class NetlinkUtils {
@@ -192,6 +193,12 @@
   virtual bool GetWiphyIndex(uint32_t* out_wiphy_index,
                              const std::string& iface_name);
 
+  // Get a list of wiphy indices for all registered wiphys from kernel.
+  // |*wiphy_index_list| returns the list of indices
+  // Returns true on success
+  virtual bool GetWiphyIndices(std::vector<uint32_t>* wiphy_index_list,
+                               const std::string& iface_name);
+
   // Get wifi interfaces info from kernel.
   // |wiphy_index| is the wiphy index we get using GetWiphyIndex().
   // |interface_info| returns a vector of InterfaceInfo structs with
diff --git a/scanning/scanner_impl.cpp b/scanning/scanner_impl.cpp
index 83eceb2..1266a98 100644
--- a/scanning/scanner_impl.cpp
+++ b/scanning/scanner_impl.cpp
@@ -74,6 +74,7 @@
       scan_started_(false),
       pno_scan_started_(false),
       nodev_counter_(0),
+      enetdown_counter_(0),
       interface_index_(interface_index),
       scan_capabilities_(scan_capabilities),
       wiphy_features_(wiphy_features),
@@ -179,12 +180,19 @@
         nodev_counter_ ++;
         LOG(WARNING) << "Scan failed with error=nodev. counter=" << nodev_counter_;
     }
-    CHECK(error_code != ENODEV || nodev_counter_ <= 3)
-        << "Driver is in a bad state, restarting wificond";
+
+    if (error_code == ENETDOWN) {
+        enetdown_counter_++;
+        LOG(WARNING) << "Scan failed with error=iface down. counter=" << enetdown_counter_;
+    }
+    CHECK((error_code != ENODEV || nodev_counter_ <= 3) &&
+          (error_code != ENETDOWN || enetdown_counter_ <= 10))
+          << "Driver is in a bad state, restarting wificond";
     *out_success = false;
     return Status::ok();
   }
   nodev_counter_ = 0;
+  enetdown_counter_ = 0;
   scan_started_ = true;
   *out_success = true;
   return Status::ok();
@@ -291,9 +299,15 @@
         nodev_counter_ ++;
         LOG(WARNING) << "Pno Scan failed with error=nodev. counter=" << nodev_counter_;
     }
+    if (error_code == ENETDOWN) {
+        enetdown_counter_++;
+        LOG(WARNING) << "Pno Scan failed with error=iface down. counter= "
+                     << enetdown_counter_;
+    }
     LOG(ERROR) << "Failed to start pno scan";
-    CHECK(error_code != ENODEV || nodev_counter_ <= 3)
-        << "Driver is in a bad state, restarting wificond";
+    CHECK((error_code != ENODEV || nodev_counter_ <= 3) &&
+          (error_code != ENETDOWN || enetdown_counter_ <= 10))
+          << "Driver is in a bad state, restarting wificond";
     return false;
   }
   string freq_string;
@@ -307,6 +321,7 @@
   }
   LOG(INFO) << "Pno scan started " << freq_string;
   nodev_counter_ = 0;
+  enetdown_counter_ = 0;
   pno_scan_started_ = true;
   return true;
 }
diff --git a/scanning/scanner_impl.h b/scanning/scanner_impl.h
index 6e23ea7..e8ab17b 100644
--- a/scanning/scanner_impl.h
+++ b/scanning/scanner_impl.h
@@ -94,6 +94,7 @@
   android::net::wifi::nl80211::PnoSettings pno_settings_;
 
   uint32_t nodev_counter_;
+  uint32_t enetdown_counter_;
   const uint32_t interface_index_;
 
   // Scanning relevant capability information for this wiphy/interface.
diff --git a/server.cpp b/server.cpp
index 97fbd1e..5f0de94 100644
--- a/server.cpp
+++ b/server.cpp
@@ -23,6 +23,7 @@
 #include <android-base/strings.h>
 #include <binder/IPCThreadState.h>
 #include <binder/PermissionCache.h>
+#include <net/if.h>
 
 #include "wificond/logging_utils.h"
 #include "wificond/net/netlink_utils.h"
@@ -51,13 +52,16 @@
 namespace {
 
 constexpr const char* kPermissionDump = "android.permission.DUMP";
+constexpr const char* kBaseIfName = "wlan0";
 
 }  // namespace
 
 Server::Server(unique_ptr<InterfaceTool> if_tool,
                NetlinkUtils* netlink_utils,
                ScanUtils* scan_utils)
-    : if_tool_(std::move(if_tool)),
+    : base_ifname_(kBaseIfName),
+      base_wiphy_index_(0),
+      if_tool_(std::move(if_tool)),
       netlink_utils_(netlink_utils),
       scan_utils_(scan_utils) {
 }
@@ -92,10 +96,14 @@
 Status Server::createApInterface(const std::string& iface_name,
                                  sp<IApInterface>* created_interface) {
   InterfaceInfo interface;
-  if (!SetupInterface(iface_name, &interface)) {
+  uint32_t wiphy_index;
+
+  if (!SetupInterface(iface_name, &interface, &wiphy_index)) {
     return Status::ok();  // Logging was done internally
   }
 
+  LOG(DEBUG) << "createApInterface: wiphy_index " << wiphy_index << " iface_name " << iface_name;
+
   unique_ptr<ApInterfaceImpl> ap_interface(new ApInterfaceImpl(
       interface.name,
       interface.index,
@@ -104,6 +112,7 @@
   *created_interface = ap_interface->GetBinder();
   BroadcastApInterfaceReady(ap_interface->GetBinder());
   ap_interfaces_[iface_name] = std::move(ap_interface);
+  wiphy_indexes_[iface_name] = wiphy_index;
 
   return Status::ok();
 }
@@ -117,18 +126,29 @@
     ap_interfaces_.erase(iter);
     *out_success = true;
   }
+
+  const auto iter_wi = wiphy_indexes_.find(iface_name);
+  if (iter_wi != wiphy_indexes_.end()) {
+    LOG(DEBUG) << "tearDownApInterface: erasing wiphy_index for iface_name " << iface_name;
+    wiphy_indexes_.erase(iter_wi);
+  }
+
   return Status::ok();
 }
 
 Status Server::createClientInterface(const std::string& iface_name,
                                      sp<IClientInterface>* created_interface) {
   InterfaceInfo interface;
-  if (!SetupInterface(iface_name, &interface)) {
+  uint32_t wiphy_index;
+
+  if (!SetupInterface(iface_name, &interface, &wiphy_index)) {
     return Status::ok();  // Logging was done internally
   }
 
+  LOG(DEBUG) << "createClientInterface: wiphy_index " << wiphy_index << " iface_name " << iface_name;
+
   unique_ptr<ClientInterfaceImpl> client_interface(new ClientInterfaceImpl(
-      wiphy_index_,
+      wiphy_index,
       interface.name,
       interface.index,
       interface.mac_address,
@@ -138,6 +158,7 @@
   *created_interface = client_interface->GetBinder();
   BroadcastClientInterfaceReady(client_interface->GetBinder());
   client_interfaces_[iface_name] = std::move(client_interface);
+  wiphy_indexes_[iface_name] = wiphy_index;
 
   return Status::ok();
 }
@@ -151,6 +172,13 @@
     client_interfaces_.erase(iter);
     *out_success = true;
   }
+
+  const auto iter_wi = wiphy_indexes_.find(iface_name);
+  if (iter_wi != wiphy_indexes_.end()) {
+    LOG(DEBUG) << "tearDownClientInterface: erasing wiphy_index for iface_name " << iface_name;
+    wiphy_indexes_.erase(iter_wi);
+  }
+
   return Status::ok();
 }
 
@@ -167,7 +195,10 @@
 
   MarkDownAllInterfaces();
 
-  netlink_utils_->UnsubscribeRegDomainChange(wiphy_index_);
+  for (auto& it : wiphy_indexes_) {
+    netlink_utils_->UnsubscribeRegDomainChange(it.second);
+  }
+  wiphy_indexes_.clear();
 
   return Status::ok();
 }
@@ -197,11 +228,11 @@
   }
 
   stringstream ss;
-  ss << "Current wiphy index: " << wiphy_index_ << endl;
   ss << "Cached interfaces list from kernel message: " << endl;
   for (const auto& iface : interfaces_) {
     ss << "Interface index: " << iface.index
        << ", name: " << iface.name
+       << ", wiphy index: " << wiphy_indexes_[iface.name]
        << ", mac address: "
        << LoggingUtils::GetMacString(iface.mac_address) << endl;
   }
@@ -230,13 +261,11 @@
 }
 
 void Server::MarkDownAllInterfaces() {
-  uint32_t wiphy_index;
-  vector<InterfaceInfo> interfaces;
-  if (netlink_utils_->GetWiphyIndex(&wiphy_index) &&
-      netlink_utils_->GetInterfaces(wiphy_index, &interfaces)) {
-    for (InterfaceInfo& interface : interfaces) {
-      if_tool_->SetUpState(interface.name.c_str(), false);
-    }
+  std::string iface_name;
+
+  for (auto& it : wiphy_indexes_) {
+    iface_name = it.first;
+    if_tool_->SetUpState(iface_name.c_str(), false);
   }
 }
 
@@ -246,7 +275,7 @@
   ScanCapabilities scan_capabilities_ignored;
   WiphyFeatures wiphy_features_ignored;
 
-  if (!netlink_utils_->GetWiphyInfo(wiphy_index_, &band_info,
+  if (!netlink_utils_->GetWiphyInfo(base_wiphy_index_, &band_info,
                                     &scan_capabilities_ignored,
                                     &wiphy_features_ignored)) {
     LOG(ERROR) << "Failed to get wiphy info from kernel";
@@ -265,7 +294,7 @@
   ScanCapabilities scan_capabilities_ignored;
   WiphyFeatures wiphy_features_ignored;
 
-  if (!netlink_utils_->GetWiphyInfo(wiphy_index_, &band_info,
+  if (!netlink_utils_->GetWiphyInfo(base_wiphy_index_, &band_info,
                                     &scan_capabilities_ignored,
                                     &wiphy_features_ignored)) {
     LOG(ERROR) << "Failed to get wiphy info from kernel";
@@ -284,7 +313,7 @@
   ScanCapabilities scan_capabilities_ignored;
   WiphyFeatures wiphy_features_ignored;
 
-  if (!netlink_utils_->GetWiphyInfo(wiphy_index_, &band_info,
+  if (!netlink_utils_->GetWiphyInfo(base_wiphy_index_, &band_info,
                                     &scan_capabilities_ignored,
                                     &wiphy_features_ignored)) {
     LOG(ERROR) << "Failed to get wiphy info from kernel";
@@ -303,7 +332,7 @@
   ScanCapabilities scan_capabilities_ignored;
   WiphyFeatures wiphy_features_ignored;
 
-  if (!netlink_utils_->GetWiphyInfo(wiphy_index_, &band_info,
+  if (!netlink_utils_->GetWiphyInfo(base_wiphy_index_, &band_info,
                                     &scan_capabilities_ignored,
                                     &wiphy_features_ignored)) {
     LOG(ERROR) << "Failed to get wiphy info from kernel";
@@ -319,7 +348,9 @@
 Status Server::getDeviceWiphyCapabilities(
     const std::string& iface_name,
     std::unique_ptr<DeviceWiphyCapabilities>* capabilities) {
-  if (!RefreshWiphyIndex(iface_name)) {
+  uint32_t wiphy_index;
+  if (!netlink_utils_->GetWiphyIndex(&wiphy_index, iface_name)) {
+    LOG(ERROR) << "Failed to get wiphy index";
     capabilities = nullptr;
     return Status::ok();
   }
@@ -328,7 +359,7 @@
   ScanCapabilities scan_capabilities_ignored;
   WiphyFeatures wiphy_features_ignored;
 
-  if (!netlink_utils_->GetWiphyInfo(wiphy_index_, &band_info,
+  if (!netlink_utils_->GetWiphyInfo(wiphy_index, &band_info,
                                     &scan_capabilities_ignored,
                                     &wiphy_features_ignored)) {
     LOG(ERROR) << "Failed to get wiphy info from kernel";
@@ -350,23 +381,30 @@
 }
 
 bool Server::SetupInterface(const std::string& iface_name,
-                            InterfaceInfo* interface) {
-  if (!RefreshWiphyIndex(iface_name)) {
+                            InterfaceInfo* interface,
+                            uint32_t *wiphy_index) {
+  if (!netlink_utils_->GetWiphyIndex(wiphy_index, iface_name)) {
+    LOG(ERROR) << "Failed to get wiphy index";
     return false;
   }
 
   netlink_utils_->SubscribeRegDomainChange(
-          wiphy_index_,
+          *wiphy_index,
           std::bind(&Server::OnRegDomainChanged,
           this,
           _1));
 
   interfaces_.clear();
-  if (!netlink_utils_->GetInterfaces(wiphy_index_, &interfaces_)) {
-    LOG(ERROR) << "Failed to get interfaces info from kernel";
+  if (!netlink_utils_->GetInterfaces(*wiphy_index, &interfaces_)) {
+    LOG(ERROR) << "Failed to get interfaces info from kernel for iface_name " << iface_name << " wiphy_index " << *wiphy_index;
     return false;
   }
 
+  if (iface_name == base_ifname_) {
+    base_wiphy_index_ = *wiphy_index;
+    LOG(INFO) << "setting base_wiphy_index_ to " << base_wiphy_index_;
+  }
+
   for (const auto& iface : interfaces_) {
     if (iface.name == iface_name) {
       *interface = iface;
@@ -378,14 +416,6 @@
   return false;
 }
 
-bool Server::RefreshWiphyIndex(const std::string& iface_name) {
-  if (!netlink_utils_->GetWiphyIndex(&wiphy_index_, iface_name)) {
-    LOG(ERROR) << "Failed to get wiphy index";
-    return false;
-  }
-  return true;
-}
-
 void Server::OnRegDomainChanged(std::string& country_code) {
   if (country_code.empty()) {
     LOG(INFO) << "Regulatory domain changed";
@@ -399,7 +429,7 @@
   BandInfo band_info;
   ScanCapabilities scan_capabilities;
   WiphyFeatures wiphy_features;
-  netlink_utils_->GetWiphyInfo(wiphy_index_,
+  netlink_utils_->GetWiphyInfo(base_wiphy_index_,
                                &band_info,
                                &scan_capabilities,
                                &wiphy_features);
diff --git a/server.h b/server.h
index 982bf12..ecebe37 100644
--- a/server.h
+++ b/server.h
@@ -104,8 +104,8 @@
   // interface on behalf of createApInterace(), it is Hostapd that configure
   // the interface to Ap mode later.
   // Returns true on success, false otherwise.
-  bool SetupInterface(const std::string& iface_name, InterfaceInfo* interface);
-  bool RefreshWiphyIndex(const std::string& iface_num);
+  bool SetupInterface(const std::string& iface_name, InterfaceInfo* interface,
+      uint32_t *wiphy_index);
   void LogSupportedBands();
   void OnRegDomainChanged(std::string& country_code);
   void BroadcastClientInterfaceReady(
@@ -118,11 +118,13 @@
       android::sp<android::net::wifi::nl80211::IApInterface> network_interface);
   void MarkDownAllInterfaces();
 
+  const std::string base_ifname_;
+  uint32_t base_wiphy_index_;
   const std::unique_ptr<wifi_system::InterfaceTool> if_tool_;
   NetlinkUtils* const netlink_utils_;
   ScanUtils* const scan_utils_;
 
-  uint32_t wiphy_index_;
+  std::map<std::string, uint32_t> wiphy_indexes_;
   std::map<std::string, std::unique_ptr<ApInterfaceImpl>> ap_interfaces_;
   std::map<std::string, std::unique_ptr<ClientInterfaceImpl>> client_interfaces_;
   std::vector<android::sp<android::net::wifi::nl80211::IInterfaceEventCallback>>