From: Sangwan Kwon Date: Tue, 29 Oct 2019 05:53:56 +0000 (+0900) Subject: Add INSERT, DELETE features to osquery X-Git-Tag: accepted/tizen/unified/20200810.122954~173 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=6f62199a531c38c4ebd9e71cf46c8414852c0dd3;p=platform%2Fcore%2Fsecurity%2Fvist.git Add INSERT, DELETE features to osquery - DELETE statement logic - If the statement has a where clause, xFilter is called. (otherwise, xUpdate is called directly.) And xFilter calls VirtualTable::generate to find row matched with the where clause. When the row comes out, execute the delete statement through xUpdate. Signed-off-by: Sangwan Kwon --- diff --git a/src/osquery/sql/virtual_table.cpp b/src/osquery/sql/virtual_table.cpp index ee2d414..6509e98 100644 --- a/src/osquery/sql/virtual_table.cpp +++ b/src/osquery/sql/virtual_table.cpp @@ -125,6 +125,44 @@ bool getColumnValue(std::string& value, return true; } +/// PATCH START ////////////////////////////////////////////////////////////// +int serializeDeleteParameters(std::string& json_value_array, + VirtualTable* pVtab) { + auto content = pVtab->content; + if (content->constraints.size() <= 0) { + LOG(ERROR) << "Invalid constraints arguments"; + return SQLITE_ERROR; + } + + auto document = rapidjson::Document(); + document.SetArray(); + auto& allocator = document.GetAllocator(); + + for (std::size_t i = 0; i < content->constraints.size(); i++) { + for (auto& constraint : content->constraints[i]) { + auto key = constraint.first; + auto value = constraint.second.expr; + + if (!value.empty()) { + /// Since concrete table is not able to know the key, make alias. + rapidjson::Value jsonValue((key + ";" + value).c_str(), allocator); + document.PushBack(jsonValue, allocator); + } + } + } + + rapidjson::StringBuffer buffer; + buffer.Clear(); + + rapidjson::Writer writer(buffer); + document.Accept(writer); + + json_value_array = buffer.GetString(); + + return SQLITE_OK; +} +/// PATCH END ///////////////////////////////////////////////////////////////// + // Type-aware serializer to pass parameters between osquery and the extension int serializeUpdateParameters(std::string& json_value_array, size_t argc, @@ -341,6 +379,12 @@ int xUpdate(sqlite3_vtab* p, auto row_to_delete = sqlite3_value_int64(argv[0]); plugin_request.insert({"id", std::to_string(row_to_delete)}); +/// PATCH START ////////////////////////////////////////////////////////////// + std::string json_value_array; + /// serialize constraints + serializeDeleteParameters(json_value_array, reinterpret_cast(p)); + plugin_request.insert({"json_value_array", json_value_array}); +/// PATCH END //////////////////////////////////////////////////////////////// } else if (sqlite3_value_type(argv[0]) == SQLITE_NULL) { // This is an INSERT query; if the rowid has been generated for us, we'll // find it inside argv[1] @@ -464,6 +508,7 @@ int xUpdate(sqlite3_vtab* p, return SQLITE_ERROR; } +/* // INSERT actions must always return a valid rowid to sqlite if (plugin_request.at("action") == "insert") { std::string rowid; @@ -491,7 +536,7 @@ int xUpdate(sqlite3_vtab* p, } *pRowid = exp.take(); } - +*/ return SQLITE_OK; } diff --git a/tools/codegen/gentable.py b/tools/codegen/gentable.py index 12895d2..b61a91f 100755 --- a/tools/codegen/gentable.py +++ b/tools/codegen/gentable.py @@ -196,6 +196,8 @@ class TableState(Singleton): self.header = "" self.impl = "" self.function = "" + self.function_delete = "" + self.function_insert = "" self.function_update = "" self.class_name = "" self.description = "" @@ -284,6 +286,8 @@ class TableState(Singleton): header=self.header, impl=self.impl, function=self.function, + function_delete=self.function_delete, + function_insert=self.function_insert, function_update=self.function_update, class_name=self.class_name, attributes=self.attributes, @@ -442,7 +446,35 @@ def implementation(impl_string, generator=False): table.table_name, BIGINT))) sys.exit(1) -# patched +### patch start ########################################################### +def implementation_delete(impl_string, generator=False): + if impl_string is None: + table.function_delete = "" + else: + filename, function_delete = impl_string.split("@") + class_parts = function_delete.split("::")[::-1] + function_delete = class_parts[0] + class_name = class_parts[1] if len(class_parts) > 1 else "" + impl = "%s.cpp" % filename + table.impl = impl + table.function_delete = function_delete + table.class_name = class_name + table.generator = generator + +def implementation_insert(impl_string, generator=False): + if impl_string is None: + table.function_insert = "" + else: + filename, function_insert = impl_string.split("@") + class_parts = function_insert.split("::")[::-1] + function_insert = class_parts[0] + class_name = class_parts[1] if len(class_parts) > 1 else "" + impl = "%s.cpp" % filename + table.impl = impl + table.function_insert = function_insert + table.class_name = class_name + table.generator = generator + def implementation_update(impl_string, generator=False): if impl_string is None: table.function_update = "" @@ -457,6 +489,8 @@ def implementation_update(impl_string, generator=False): table.class_name = class_name table.generator = generator +### patch end ############################################################# + def main(): parser = argparse.ArgumentParser( "Generate C++ Table Plugin from specfile.") diff --git a/tools/codegen/templates/default.cpp.in b/tools/codegen/templates/default.cpp.in index d28ed88..574ce0d 100644 --- a/tools/codegen/templates/default.cpp.in +++ b/tools/codegen/templates/default.cpp.in @@ -5,6 +5,21 @@ * This source code is licensed in accordance with the terms specified in * the LICENSE file found in the root directory of this source tree. */ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd 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 + */ /* ** This file is generated. Do not modify it manually! @@ -24,23 +39,26 @@ namespace tables { void {{function}}(RowYield& yield, QueryContext& context); {% elif strongly_typed_rows %}\ osquery::TableRows {{function}}(QueryContext& context); +{% else %}\ +osquery::QueryData {{function}}(QueryContext& context); -/// patch start -{% if function_update != "" %}\ -osquery::QueryData {{function_update}}(QueryContext& context, +/// patch start ////////////////////////////////////////////////// +{% if function_delete != "" %}\ +osquery::QueryData {{function_delete}}(QueryContext& context, const PluginRequest& request); {% endif %}\ -/// patch end -{% else %}\ -osquery::QueryData {{function}}(QueryContext& context); +{% if function_insert != "" %}\ +osquery::QueryData {{function_insert}}(QueryContext& context, + const PluginRequest& request); +{% endif %}\ -/// patch start {% if function_update != "" %}\ osquery::QueryData {{function_update}}(QueryContext& context, const PluginRequest& request); {% endif %}\ -/// patch end + +/// patch end /////////////////////////////////////////////////// {% endif %}\ {% else %} @@ -144,14 +162,29 @@ class {{table_name_cc}}TablePlugin : public TablePlugin { return results; } -/// patch start +/// patch start ///////////////////////////////////////////////////// +{% if function_delete != "" %}\ + QueryData delete_(QueryContext& context, + const PluginRequest& request) override { + return tables::{{function_delete}}(context, request); + } +{% endif %}\ + +{% if function_insert != "" %}\ + QueryData insert(QueryContext& context, + const PluginRequest& request) override { + return tables::{{function_insert}}(context, request); + } +{% endif %}\ + {% if function_update != "" %}\ QueryData update(QueryContext& context, const PluginRequest& request) override { return tables::{{function_update}}(context, request); } {% endif %}\ -/// patch end + +/// patch end /////////////////////////////////////////////////////// {% endif %}\