add bundle copy check

Signed-off-by: ZhangJianxin <zhangjianxin23@huawei.com>
Change-Id: I67c49f128d3cb871e553ff70a5bcd6f04d118541
This commit is contained in:
ZhangJianxin 2024-10-26 18:22:56 +08:00
parent d85649559d
commit e68f1747d2
10 changed files with 178 additions and 47 deletions

View File

@ -60,7 +60,8 @@
"curl",
"libuv",
"resource_management",
"i18n"
"i18n",
"bundle_framework"
],
"third_party": []
},
@ -112,4 +113,4 @@
]
}
}
}
}

View File

@ -26,7 +26,8 @@
"ohos.permission.INTERACT_ACROSS_LOCAL_ACCOUNTS",
"ohos.permission.MANAGE_LOCAL_ACCOUNTS",
"ohos.permission.GET_DISTRIBUTED_ACCOUNTS",
"ohos.permission.GET_RUNNING_INFO"
"ohos.permission.GET_RUNNING_INFO",
"ohos.permission.GET_BUNDLE_INFO_PRIVILEGED"
],
"caps": [
"CAP_CHOWN"

View File

@ -21,6 +21,7 @@ rust_cxx("download_server_cxx_gen") {
"src/manage/network.rs",
"src/manage/query.rs",
"src/service/notification_bar.rs",
"src/task/bundle.rs",
"src/task/config.rs",
"src/task/info.rs",
"src/task/reason.rs",
@ -52,6 +53,7 @@ ohos_static_library("download_server_cxx") {
sources = [
"src/cxx/account.cpp",
"src/cxx/application_state_observer.cpp",
"src/cxx/bundle.cpp",
"src/cxx/c_request_database.cpp",
"src/cxx/c_string_wrapper.cpp",
"src/cxx/c_task_config.cpp",
@ -74,6 +76,8 @@ ohos_static_library("download_server_cxx") {
"ability_runtime:app_manager",
"access_token:libaccesstoken_sdk",
"access_token:libtokenid_sdk",
"bundle_framework:appexecfwk_base",
"bundle_framework:appexecfwk_core",
"c_utils:utils",
"certificate_manager:cert_manager_sdk",
"common_event_service:cesfwk_innerkits",

34
services/include/bundle.h Normal file
View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef REQUEST_BUNDLE_H
#define REQUEST_BUNDLE_H
#include <cstdint>
#include <string>
#include "bundle_mgr_interface.h"
#include "cxx.h"
#include "if_system_ability_manager.h"
#include "iremote_broker.h"
#include "iservice_registry.h"
#include "log.h"
#include "system_ability_definition.h"
#include "task/bundle.rs.h"
namespace OHOS::Request {
AppInfo GetNameAndIndex(int32_t uid);
} // namespace OHOS::Request
#endif // REQUEST_BUNDLE_H

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "bundle.h"
using namespace OHOS::AppExecFwk;
namespace OHOS::Request {
std::mutex appInfoMutex_;
AppInfo GetNameAndIndex(int32_t uid)
{
std::lock_guard<std::mutex> lockGuard(appInfoMutex_);
AppInfo appInfo;
appInfo.ret = false;
int32_t appIndex = 0;
std::string bundleName;
sptr<ISystemAbilityManager> systemAbilityManager =
SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
if (!systemAbilityManager) {
REQUEST_HILOGE("GetNameAndIndex, fail to get system ability mgr.");
return appInfo;
}
sptr<IRemoteObject> remoteObject = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
if (!remoteObject) {
REQUEST_HILOGE("GetNameAndIndex, fail to get bundle manager proxy.");
return appInfo;
}
sptr<IBundleMgr> bundleMgr = iface_cast<IBundleMgr>(remoteObject);
ErrCode ret = bundleMgr->GetNameAndIndexForUid(uid, bundleName, appIndex);
if (ret != ERR_OK) {
REQUEST_HILOGE("GetNameAndIndex, err ret: %{public}d", ret);
return appInfo;
}
REQUEST_HILOGI("GetNameAndIndex: %{public}d, %{public}s", appIndex, bundleName.c_str());
appInfo.ret = true;
appInfo.index = appIndex;
appInfo.name = rust::String(bundleName);
return appInfo;
}
} // namespace OHOS::Request

View File

@ -0,0 +1,35 @@
// Copyright (C) 2024 Huawei Device Co., Ltd.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#[allow(unused)]
#[cxx::bridge(namespace = "OHOS::Request")]
mod ffi {
struct AppInfo {
ret: bool,
index: i32,
name: String,
}
unsafe extern "C++" {
include!("bundle.h");
fn GetNameAndIndex(uid: i32) -> AppInfo;
}
}
pub(crate) fn get_name_and_index(uid: i32) -> Option<(i32, String)> {
let app_info = ffi::GetNameAndIndex(uid);
match app_info.ret {
true => Some((app_info.index, app_info.name)),
false => None,
}
}

View File

@ -22,9 +22,9 @@ cfg_oh! {
use crate::manage::SystemConfig;
use crate::utils::url_policy::check_url_domain;
}
use crate::task::config::{Action, TaskConfig};
use crate::task::files::{check_atomic_convert_path, convert_path};
use crate::task::ATOMIC_SERVICE;
use crate::task::files::{convert_bundle_name, convert_path};
const CONNECT_TIMEOUT: u64 = 60;
const SECONDS_IN_ONE_WEEK: u64 = 7 * 24 * 60 * 60;
@ -174,15 +174,12 @@ fn build_system_proxy(
fn build_task_certs(config: &TaskConfig) -> Result<Vec<Certificate>, Box<dyn Error + Send + Sync>> {
let uid = config.common_data.uid;
let bundle = config.bundle.as_str();
let paths = config.certs_path.as_slice();
let is_account = config.bundle_type == ATOMIC_SERVICE;
let atomic_account = config.atomic_account.as_str();
let bundle_and_account = check_atomic_convert_path(is_account, bundle, atomic_account);
let bundle_name = convert_bundle_name(config);
let mut certs = Vec::new();
for (idx, path) in paths.iter().enumerate() {
let path = convert_path(uid, &bundle_and_account, path);
let path = convert_path(uid, &bundle_name, path);
let cert = cvt_res_error!(
Certificate::from_path(&path).map_err(Box::new),
"Parse task cert failed - idx: {}, path: {}",

View File

@ -236,18 +236,13 @@ pub(crate) async fn download_inner(
#[cfg(not(test))]
fn check_file_exist(task: &Arc<RequestTask>) -> Result<(), TaskError> {
use crate::task::files::{check_atomic_convert_path, convert_path};
use crate::task::ATOMIC_SERVICE;
use crate::task::files::{convert_bundle_name, convert_path};
let config = task.config();
let bundle_and_account = check_atomic_convert_path(
config.bundle_type == ATOMIC_SERVICE,
config.bundle.as_str(),
config.atomic_account.as_str(),
);
let bundle_name = convert_bundle_name(config);
let real_path = convert_path(
config.common_data.uid,
&bundle_and_account,
&bundle_name,
&config.file_specs[0].path,
);
// Cannot compare because file_total_size will be changed when resume task.

View File

@ -18,6 +18,7 @@ use std::os::fd::FromRawFd;
use ylong_runtime::fs::File as AsyncFile;
use crate::task::bundle::get_name_and_index;
use crate::task::config::{Action, TaskConfig};
use crate::task::ATOMIC_SERVICE;
@ -53,10 +54,7 @@ impl AttachedFiles {
fn open_task_files(config: &TaskConfig) -> io::Result<(Files, Vec<i64>)> {
let tid = config.common_data.task_id;
let uid = config.common_data.uid;
let bundle = config.bundle.as_str();
let is_account = config.bundle_type == ATOMIC_SERVICE;
let atomic_account = config.atomic_account.as_str();
let bundle_and_account = check_atomic_convert_path(is_account, bundle, atomic_account);
let bundle_name = convert_bundle_name(config);
let mut files = Vec::new();
let mut sizes = Vec::new();
@ -74,7 +72,7 @@ fn open_task_files(config: &TaskConfig) -> io::Result<(Files, Vec<i64>)> {
}
} else {
cvt_res_error!(
open_file_readonly(uid, &bundle_and_account, &fs.path),
open_file_readonly(uid, &bundle_name, &fs.path),
"Open file RO failed - task_id: {}, idx: {}",
tid,
idx
@ -104,7 +102,7 @@ fn open_task_files(config: &TaskConfig) -> io::Result<(Files, Vec<i64>)> {
}
} else {
cvt_res_error!(
open_file_readwrite(uid, &bundle_and_account, &fs.path),
open_file_readwrite(uid, &bundle_name, &fs.path),
"Open file RW failed - task_id: {}, idx: {}",
tid,
idx
@ -122,15 +120,12 @@ fn open_task_files(config: &TaskConfig) -> io::Result<(Files, Vec<i64>)> {
fn open_body_files(config: &TaskConfig) -> io::Result<Files> {
let tid = config.common_data.task_id;
let uid = config.common_data.uid;
let bundle = config.bundle.as_str();
let is_account = config.bundle_type == ATOMIC_SERVICE;
let atomic_account = config.atomic_account.as_str();
let bundle_and_account = check_atomic_convert_path(is_account, bundle, atomic_account);
let bundle_name = convert_bundle_name(config);
let mut body_files = Vec::new();
for (idx, path) in config.body_file_paths.iter().enumerate() {
let file = cvt_res_error!(
open_file_readwrite(uid, &bundle_and_account, path),
open_file_readwrite(uid, &bundle_name, path),
"Open body_file failed - task_id: {}, idx: {}",
tid,
idx
@ -140,40 +135,28 @@ fn open_body_files(config: &TaskConfig) -> io::Result<Files> {
Ok(Files::new(body_files))
}
fn open_file_readwrite(uid: u64, bundle: &str, path: &str) -> io::Result<File> {
fn open_file_readwrite(uid: u64, bundle_name: &str, path: &str) -> io::Result<File> {
Ok(cvt_res_error!(
OpenOptions::new()
.read(true)
.append(true)
.open(convert_path(uid, bundle, path)),
.open(convert_path(uid, bundle_name, path)),
"open_file_readwrite failed"
))
}
fn open_file_readonly(uid: u64, bundle_and_account: &str, path: &str) -> io::Result<File> {
fn open_file_readonly(uid: u64, bundle_name: &str, path: &str) -> io::Result<File> {
Ok(cvt_res_error!(
OpenOptions::new()
.read(true)
.open(convert_path(uid, bundle_and_account, path)),
.open(convert_path(uid, bundle_name, path)),
"open_file_readonly failed"
))
}
pub(crate) fn check_atomic_convert_path(
is_account: bool,
bundle: &str,
atomic_account: &str,
) -> String {
if is_account {
format!("+auid-{}+{}", atomic_account, bundle)
} else {
bundle.to_string()
}
}
pub(crate) fn convert_path(uid: u64, bundle_and_account: &str, path: &str) -> String {
pub(crate) fn convert_path(uid: u64, bundle_name: &str, path: &str) -> String {
let uuid = uid / 200000;
let base_replace = format!("{}/base/{}", uuid, bundle_and_account);
let base_replace = format!("{}/base/{}", uuid, bundle_name);
let real_path = path
.replacen("storage", "app", 1)
.replacen("base", &base_replace, 1);
@ -181,6 +164,31 @@ pub(crate) fn convert_path(uid: u64, bundle_and_account: &str, path: &str) -> St
real_path
}
pub(crate) fn convert_bundle_name(config: &TaskConfig) -> String {
let is_account = config.bundle_type == ATOMIC_SERVICE;
let bundle_name = config.bundle.as_str();
if is_account {
let atomic_account = config.atomic_account.as_str();
format!("+auid-{}+{}", atomic_account, bundle_name)
} else {
let uid = config.common_data.uid;
check_app_clone_bundle_name(uid, bundle_name)
}
}
fn check_app_clone_bundle_name(uid: u64, bundle_name: &str) -> String {
let mut ret_name = bundle_name.to_string();
if let Some((index, name)) = get_name_and_index(uid as i32) {
if bundle_name != name {
info!("bundle name not matching. {:?}, {:?}", bundle_name, name);
}
if index > 0 {
ret_name = format!("+clone-{}+{}", index, bundle_name);
}
}
ret_name
}
pub(crate) struct Files(UnsafeCell<Vec<AsyncFile>>);
impl Files {

View File

@ -26,5 +26,6 @@ pub(crate) mod request_task;
pub(crate) const ATOMIC_SERVICE: u32 = 1;
pub(crate) mod client;
pub(crate) mod bundle;
pub(crate) mod ffi;
pub(crate) mod upload;