From d409d6327446d0ad5b361eaef4c5c3fd20cf374e Mon Sep 17 00:00:00 2001 From: Yanzhan Yang Date: Mon, 1 Jul 2019 21:09:14 +0800 Subject: [PATCH] add model obfuscate feature (#1718) * add model obfuscate feature * fix style * fix array length bug * add merge.sh to merge static library into one combined library * disable OpenMP for iOS --- CMakeLists.txt | 6 +++- src/common/types.h | 1 + src/common/util.cpp | 11 +++++++ src/common/util.h | 2 ++ src/framework/executor.cpp | 17 ++++++++++ src/pass/memory_optimize.cpp | 2 +- src/pass/memory_optimize.h | 7 +---- src/pass/model_obfuscate.cpp | 36 ++++++++++++++++++++++ src/pass/model_obfuscate.h | 36 ++++++++++++++++++++++ src/pass/pass_base.h | 27 ++++++++++++++++ test/net/test_net.cpp | 10 ++++++ test/test_include.h | 1 + tools/shell/merge.sh | 60 ++++++++++++++++++++++++++++++++++++ 13 files changed, 208 insertions(+), 8 deletions(-) create mode 100644 src/pass/model_obfuscate.cpp create mode 100644 src/pass/model_obfuscate.h create mode 100644 src/pass/pass_base.h create mode 100644 tools/shell/merge.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index 27b01993b3..0d25d5022f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,11 @@ cmake_minimum_required(VERSION 3.0.0) # basic build option -option(USE_OPENMP "build with openmp support" ON) +if(IS_IOS) + option(USE_OPENMP "build with openmp support" OFF) +else() + option(USE_OPENMP "build with openmp support" ON) +endif() option(USE_EXCEPTION "build with exception" ON) option(WITH_LOGGING "print logging for debug" OFF) option(WITH_SYMBOL "build with all symbols" ON) # turn off if use jni or ios io diff --git a/src/common/types.h b/src/common/types.h index bfffe91575..8c16eb62b7 100644 --- a/src/common/types.h +++ b/src/common/types.h @@ -141,6 +141,7 @@ enum MemoryOptimizationLevel { struct PaddleMobileConfigInternal { bool load_when_predict = false; MemoryOptimizationLevel memory_optimization_level = FullMemoryOptimization; + std::string model_obfuscate_key = ""; }; extern const char *G_OP_TYPE_CONV; diff --git a/src/common/util.cpp b/src/common/util.cpp index 728653ecf0..acdc42e879 100644 --- a/src/common/util.cpp +++ b/src/common/util.cpp @@ -32,4 +32,15 @@ char *ReadFileToBuff(std::string filename) { return data; } +int GetFileLength(std::string filename) { + FILE *file = fopen(filename.c_str(), "rb"); + PADDLE_MOBILE_ENFORCE(file != nullptr, "can't open file: %s ", + filename.c_str()); + fseek(file, 0, SEEK_END); + int size = ftell(file); + PADDLE_MOBILE_ENFORCE(size > 0, "file should not be empty"); + fclose(file); + return size; +} + } // namespace paddle_mobile diff --git a/src/common/util.h b/src/common/util.h index e4646c43f7..212362a52e 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -21,4 +21,6 @@ namespace paddle_mobile { char *ReadFileToBuff(std::string filename); +int GetFileLength(std::string filename); + } // namespace paddle_mobile diff --git a/src/framework/executor.cpp b/src/framework/executor.cpp index 296f8215b3..c06abc8416 100644 --- a/src/framework/executor.cpp +++ b/src/framework/executor.cpp @@ -30,6 +30,7 @@ limitations under the License. */ #include "framework/tensor.h" #include "memory/t_malloc.h" #include "pass/memory_optimize.h" +#include "pass/model_obfuscate.h" #ifdef PADDLE_MOBILE_CL #include "framework/cl/cl_image.h" #endif @@ -241,9 +242,17 @@ void Executor::InitCombineMemory() { if (program_.combined_params_buf && program_.combined_params_len) { origin_data = reinterpret_cast( const_cast(program_.combined_params_buf)); + if (config_.model_obfuscate_key != "") { + auto obfuscator = pass::ModelObfuscatePass(config_.model_obfuscate_key); + obfuscator.convert_data(origin_data, program_.combined_params_len); + } } else { self_alloc = true; origin_data = ReadFileToBuff(program_.para_path); + if (config_.model_obfuscate_key != "") { + auto obfuscator = pass::ModelObfuscatePass(config_.model_obfuscate_key); + obfuscator.convert_data(origin_data, GetFileLength(program_.para_path)); + } } PADDLE_MOBILE_ENFORCE(origin_data != nullptr, "data == nullptr"); char *data = origin_data; @@ -930,10 +939,18 @@ void Executor::InitCombineMemory() { if (program_.combined_params_buf && program_.combined_params_len) { LOG(kLOG_INFO) << "use outter memory"; origin_data = reinterpret_cast(program_.combined_params_buf); + if (config_.model_obfuscate_key != "") { + auto obfuscator = pass::ModelObfuscatePass(config_.model_obfuscate_key); + obfuscator.convert_data(origin_data, program_.combined_params_len); + } } else { LOG(kLOG_INFO) << " begin init combine memory"; self_alloc = true; origin_data = ReadFileToBuff(program_.para_path); + if (config_.model_obfuscate_key != "") { + auto obfuscator = pass::ModelObfuscatePass(config_.model_obfuscate_key); + obfuscator.convert_data(origin_data, GetFileLength(program_.para_path)); + } } PADDLE_MOBILE_ENFORCE(origin_data != nullptr, "origin_data==nullptr!!!"); float *data = reinterpret_cast(origin_data); diff --git a/src/pass/memory_optimize.cpp b/src/pass/memory_optimize.cpp index 3de5021bc9..dc14bac15b 100644 --- a/src/pass/memory_optimize.cpp +++ b/src/pass/memory_optimize.cpp @@ -13,8 +13,8 @@ See the License for the specific language governing permissions and limitations under the License. */ #include "pass/memory_optimize.h" -#include "framework/lod_tensor.h" #include +#include "framework/lod_tensor.h" namespace paddle_mobile { namespace pass { diff --git a/src/pass/memory_optimize.h b/src/pass/memory_optimize.h index 991419dc33..f0171c5ba6 100644 --- a/src/pass/memory_optimize.h +++ b/src/pass/memory_optimize.h @@ -19,6 +19,7 @@ limitations under the License. */ #include #include #include "framework/program/program.h" +#include "pass/pass_base.h" namespace paddle_mobile { namespace pass { @@ -29,12 +30,6 @@ typedef struct { bool visited; } VarNode; -class PassBase { - public: - PassBase() {} - virtual ~PassBase() {} -}; - // MemoryOptPass will analyze the program, and reuse memory between // variables as much as possible class MemoryOptPass : public PassBase { diff --git a/src/pass/model_obfuscate.cpp b/src/pass/model_obfuscate.cpp new file mode 100644 index 0000000000..913b93af25 --- /dev/null +++ b/src/pass/model_obfuscate.cpp @@ -0,0 +1,36 @@ +/* Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved. + +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 "pass/model_obfuscate.h" + +namespace paddle_mobile { +namespace pass { + +ModelObfuscatePass::ModelObfuscatePass(std::string key) { + for (auto c : key) { + acc *= base; + acc += (int)c; + acc %= stride; + } + acc += stride; +} + +void ModelObfuscatePass::convert_data(char *data, int len) { + for (int i = 0; i < len; i += acc) { + data[i] = 255 - data[i]; + } +} + +} // namespace pass +} // namespace paddle_mobile diff --git a/src/pass/model_obfuscate.h b/src/pass/model_obfuscate.h new file mode 100644 index 0000000000..6c2912e05a --- /dev/null +++ b/src/pass/model_obfuscate.h @@ -0,0 +1,36 @@ +/* Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved. + +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. */ + +#pragma once + +#include +#include "pass/pass_base.h" + +namespace paddle_mobile { +namespace pass { + +class ModelObfuscatePass : public PassBase { + public: + ModelObfuscatePass(std::string key); + void convert_data(char *data, int len); + int version = 1; + + private: + int acc = 0; + int base = 17; + int stride = 100; +}; + +} // namespace pass +} // namespace paddle_mobile diff --git a/src/pass/pass_base.h b/src/pass/pass_base.h new file mode 100644 index 0000000000..925fdb7d50 --- /dev/null +++ b/src/pass/pass_base.h @@ -0,0 +1,27 @@ +/* Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved. + +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. */ + +#pragma once + +namespace paddle_mobile { +namespace pass { + +class PassBase { + public: + PassBase() {} + virtual ~PassBase() {} +}; + +} // namespace pass +} // namespace paddle_mobile diff --git a/test/net/test_net.cpp b/test/net/test_net.cpp index 59a0e63d6e..2d87e1f725 100644 --- a/test/net/test_net.cpp +++ b/test/net/test_net.cpp @@ -14,6 +14,7 @@ limitations under the License. */ #include #include +#include #include "../test_helper.h" #include "../test_include.h" @@ -34,6 +35,15 @@ void test(int argc, char *argv[]) { config.memory_optimization_level = enable_memory_optimization ? MemoryOptimizationWithoutFeeds : NoMemoryOptimization; + + // save obfuscated model + // config.model_obfuscate_key = "asdf"; + // std::ofstream out_file("new-params", std::ofstream::binary); + // char *out_data = ReadFileToBuff("./checked_model/params"); + // int len = GetFileLength("./checked_model/params"); + // out_file.write(out_data, len); + // out_file.close(); + paddle_mobile::PaddleMobile paddle_mobile(config); paddle_mobile.SetThreadNum(1); diff --git a/test/test_include.h b/test/test_include.h index 7f45d6e2c4..e3d31d3253 100644 --- a/test/test_include.h +++ b/test/test_include.h @@ -20,6 +20,7 @@ limitations under the License. */ #include "./test_helper.h" #include "common/enforce.h" +#include "common/util.h" #include "common/log.h" #include "executor_for_test.h" #include "framework/ddim.h" diff --git a/tools/shell/merge.sh b/tools/shell/merge.sh new file mode 100644 index 0000000000..08c19d9286 --- /dev/null +++ b/tools/shell/merge.sh @@ -0,0 +1,60 @@ +#!/bin/sh + +# Combined all static libaries in the current directory into a single static library +# It is hardcoded to use the i386, armv7, and armv7s architectures; this can easily be changed via the 'archs' variable at the top +# The script takes a single argument, which is the name of the final, combined library to be created. +# +# For example: +# => combine_static_libraries.sh combined-library +# +# Script by Evan Schoenberg, Regular Rate and Rhythm Software +# Thanks to Claudiu Ursache for his blog post at http://www.cvursache.com/2013/10/06/Combining-Multi-Arch-Binaries/ which detailed the technique automated by this script +##### +# $1 = Name of output archive +##### + +# archs=(i386 armv7 armv7s) +archs=(armv7 arm64) +libraries=(*.a) +libtool="/usr/bin/libtool" + +echo "Combining ${libraries[*]}..." + +for library in ${libraries[*]} +do + lipo -info $library + + # Extract individual architectures for this library + for arch in ${archs[*]} + do + lipo -extract $arch $library -o ${library}_${arch}.a + done +done + +# Combine results of the same architecture into a library for that architecture +source_combined="" +for arch in ${archs[*]} +do + source_libraries="" + + for library in ${libraries[*]} + do + source_libraries="${source_libraries} ${library}_${arch}.a" + done + + $libtool -static ${source_libraries} -o "${1}_${arch}.a" + source_combined="${source_combined} ${1}_${arch}.a" + + # Delete intermediate files + rm ${source_libraries} +done + +# Merge the combined library for each architecture into a single fat binary +lipo -create $source_combined -o $1.a + +# Delete intermediate files +rm ${source_combined} + +# Show info on the output library as confirmation +echo "Combination complete." +lipo -info $1.a -- GitLab