kernel: Reformat code using clang-format (#347)
* The coding format is too messy, reformat to improve readability and get closer to Linux kernel coding style. * While at it, update .clang-format file to linux-mainline state.
This commit is contained in:
@@ -1,10 +1,10 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
#
|
#
|
||||||
# clang-format configuration file. Intended for clang-format >= 4.
|
# clang-format configuration file. Intended for clang-format >= 11.
|
||||||
#
|
#
|
||||||
# For more information, see:
|
# For more information, see:
|
||||||
#
|
#
|
||||||
# Documentation/process/clang-format.rst
|
# Documentation/dev-tools/clang-format.rst
|
||||||
# https://clang.llvm.org/docs/ClangFormat.html
|
# https://clang.llvm.org/docs/ClangFormat.html
|
||||||
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
|
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
|
||||||
#
|
#
|
||||||
@@ -13,7 +13,7 @@ AccessModifierOffset: -4
|
|||||||
AlignAfterOpenBracket: Align
|
AlignAfterOpenBracket: Align
|
||||||
AlignConsecutiveAssignments: false
|
AlignConsecutiveAssignments: false
|
||||||
AlignConsecutiveDeclarations: false
|
AlignConsecutiveDeclarations: false
|
||||||
#AlignEscapedNewlines: Left # Unknown to clang-format-4.0
|
AlignEscapedNewlines: Left
|
||||||
AlignOperands: true
|
AlignOperands: true
|
||||||
AlignTrailingComments: false
|
AlignTrailingComments: false
|
||||||
AllowAllParametersOfDeclarationOnNextLine: false
|
AllowAllParametersOfDeclarationOnNextLine: false
|
||||||
@@ -37,24 +37,24 @@ BraceWrapping:
|
|||||||
AfterObjCDeclaration: false
|
AfterObjCDeclaration: false
|
||||||
AfterStruct: false
|
AfterStruct: false
|
||||||
AfterUnion: false
|
AfterUnion: false
|
||||||
#AfterExternBlock: false # Unknown to clang-format-5.0
|
AfterExternBlock: false
|
||||||
BeforeCatch: false
|
BeforeCatch: false
|
||||||
BeforeElse: false
|
BeforeElse: false
|
||||||
IndentBraces: false
|
IndentBraces: false
|
||||||
#SplitEmptyFunction: true # Unknown to clang-format-4.0
|
SplitEmptyFunction: true
|
||||||
#SplitEmptyRecord: true # Unknown to clang-format-4.0
|
SplitEmptyRecord: true
|
||||||
#SplitEmptyNamespace: true # Unknown to clang-format-4.0
|
SplitEmptyNamespace: true
|
||||||
BreakBeforeBinaryOperators: None
|
BreakBeforeBinaryOperators: None
|
||||||
BreakBeforeBraces: Custom
|
BreakBeforeBraces: Custom
|
||||||
#BreakBeforeInheritanceComma: false # Unknown to clang-format-4.0
|
BreakBeforeInheritanceComma: false
|
||||||
BreakBeforeTernaryOperators: false
|
BreakBeforeTernaryOperators: false
|
||||||
BreakConstructorInitializersBeforeComma: false
|
BreakConstructorInitializersBeforeComma: false
|
||||||
#BreakConstructorInitializers: BeforeComma # Unknown to clang-format-4.0
|
BreakConstructorInitializers: BeforeComma
|
||||||
BreakAfterJavaFieldAnnotations: false
|
BreakAfterJavaFieldAnnotations: false
|
||||||
BreakStringLiterals: false
|
BreakStringLiterals: false
|
||||||
ColumnLimit: 80
|
ColumnLimit: 80
|
||||||
CommentPragmas: '^ IWYU pragma:'
|
CommentPragmas: '^ IWYU pragma:'
|
||||||
#CompactNamespaces: false # Unknown to clang-format-4.0
|
CompactNamespaces: false
|
||||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||||
ConstructorInitializerIndentWidth: 8
|
ConstructorInitializerIndentWidth: 8
|
||||||
ContinuationIndentWidth: 8
|
ContinuationIndentWidth: 8
|
||||||
@@ -62,39 +62,61 @@ Cpp11BracedListStyle: false
|
|||||||
DerivePointerAlignment: false
|
DerivePointerAlignment: false
|
||||||
DisableFormat: false
|
DisableFormat: false
|
||||||
ExperimentalAutoDetectBinPacking: false
|
ExperimentalAutoDetectBinPacking: false
|
||||||
#FixNamespaceComments: false # Unknown to clang-format-4.0
|
FixNamespaceComments: false
|
||||||
|
|
||||||
# Taken from:
|
# Taken from:
|
||||||
# git grep -h '^#define [^[:space:]]*for_each[^[:space:]]*(' include/ \
|
# git grep -h '^#define [^[:space:]]*for_each[^[:space:]]*(' include/ tools/ \
|
||||||
# | sed "s,^#define \([^[:space:]]*for_each[^[:space:]]*\)(.*$, - '\1'," \
|
# | sed "s,^#define \([^[:space:]]*for_each[^[:space:]]*\)(.*$, - '\1'," \
|
||||||
# | sort | uniq
|
# | LC_ALL=C sort -u
|
||||||
ForEachMacros:
|
ForEachMacros:
|
||||||
|
- '__ata_qc_for_each'
|
||||||
|
- '__bio_for_each_bvec'
|
||||||
|
- '__bio_for_each_segment'
|
||||||
|
- '__evlist__for_each_entry'
|
||||||
|
- '__evlist__for_each_entry_continue'
|
||||||
|
- '__evlist__for_each_entry_from'
|
||||||
|
- '__evlist__for_each_entry_reverse'
|
||||||
|
- '__evlist__for_each_entry_safe'
|
||||||
|
- '__for_each_mem_range'
|
||||||
|
- '__for_each_mem_range_rev'
|
||||||
|
- '__for_each_thread'
|
||||||
|
- '__hlist_for_each_rcu'
|
||||||
|
- '__map__for_each_symbol_by_name'
|
||||||
|
- '__pci_bus_for_each_res0'
|
||||||
|
- '__pci_bus_for_each_res1'
|
||||||
|
- '__pci_dev_for_each_res0'
|
||||||
|
- '__pci_dev_for_each_res1'
|
||||||
|
- '__perf_evlist__for_each_entry'
|
||||||
|
- '__perf_evlist__for_each_entry_reverse'
|
||||||
|
- '__perf_evlist__for_each_entry_safe'
|
||||||
|
- '__rq_for_each_bio'
|
||||||
|
- '__shost_for_each_device'
|
||||||
|
- '__sym_for_each'
|
||||||
|
- '_for_each_counter'
|
||||||
- 'apei_estatus_for_each_section'
|
- 'apei_estatus_for_each_section'
|
||||||
- 'ata_for_each_dev'
|
- 'ata_for_each_dev'
|
||||||
- 'ata_for_each_link'
|
- 'ata_for_each_link'
|
||||||
- '__ata_qc_for_each'
|
|
||||||
- 'ata_qc_for_each'
|
- 'ata_qc_for_each'
|
||||||
- 'ata_qc_for_each_raw'
|
- 'ata_qc_for_each_raw'
|
||||||
- 'ata_qc_for_each_with_internal'
|
- 'ata_qc_for_each_with_internal'
|
||||||
- 'ax25_for_each'
|
- 'ax25_for_each'
|
||||||
- 'ax25_uid_for_each'
|
- 'ax25_uid_for_each'
|
||||||
- '__bio_for_each_bvec'
|
|
||||||
- 'bio_for_each_bvec'
|
- 'bio_for_each_bvec'
|
||||||
- 'bio_for_each_bvec_all'
|
- 'bio_for_each_bvec_all'
|
||||||
|
- 'bio_for_each_folio_all'
|
||||||
- 'bio_for_each_integrity_vec'
|
- 'bio_for_each_integrity_vec'
|
||||||
- '__bio_for_each_segment'
|
|
||||||
- 'bio_for_each_segment'
|
- 'bio_for_each_segment'
|
||||||
- 'bio_for_each_segment_all'
|
- 'bio_for_each_segment_all'
|
||||||
- 'bio_list_for_each'
|
- 'bio_list_for_each'
|
||||||
- 'bip_for_each_vec'
|
- 'bip_for_each_vec'
|
||||||
- 'bitmap_for_each_clear_region'
|
|
||||||
- 'bitmap_for_each_set_region'
|
|
||||||
- 'blkg_for_each_descendant_post'
|
|
||||||
- 'blkg_for_each_descendant_pre'
|
|
||||||
- 'blk_queue_for_each_rl'
|
|
||||||
- 'bond_for_each_slave'
|
- 'bond_for_each_slave'
|
||||||
- 'bond_for_each_slave_rcu'
|
- 'bond_for_each_slave_rcu'
|
||||||
|
- 'bpf_for_each'
|
||||||
|
- 'bpf_for_each_reg_in_vstate'
|
||||||
|
- 'bpf_for_each_reg_in_vstate_mask'
|
||||||
- 'bpf_for_each_spilled_reg'
|
- 'bpf_for_each_spilled_reg'
|
||||||
|
- 'bpf_object__for_each_map'
|
||||||
|
- 'bpf_object__for_each_program'
|
||||||
- 'btree_for_each_safe128'
|
- 'btree_for_each_safe128'
|
||||||
- 'btree_for_each_safe32'
|
- 'btree_for_each_safe32'
|
||||||
- 'btree_for_each_safe64'
|
- 'btree_for_each_safe64'
|
||||||
@@ -102,6 +124,8 @@ ForEachMacros:
|
|||||||
- 'card_for_each_dev'
|
- 'card_for_each_dev'
|
||||||
- 'cgroup_taskset_for_each'
|
- 'cgroup_taskset_for_each'
|
||||||
- 'cgroup_taskset_for_each_leader'
|
- 'cgroup_taskset_for_each_leader'
|
||||||
|
- 'cpu_aggr_map__for_each_idx'
|
||||||
|
- 'cpufreq_for_each_efficient_entry_idx'
|
||||||
- 'cpufreq_for_each_entry'
|
- 'cpufreq_for_each_entry'
|
||||||
- 'cpufreq_for_each_entry_idx'
|
- 'cpufreq_for_each_entry_idx'
|
||||||
- 'cpufreq_for_each_valid_entry'
|
- 'cpufreq_for_each_valid_entry'
|
||||||
@@ -109,8 +133,30 @@ ForEachMacros:
|
|||||||
- 'css_for_each_child'
|
- 'css_for_each_child'
|
||||||
- 'css_for_each_descendant_post'
|
- 'css_for_each_descendant_post'
|
||||||
- 'css_for_each_descendant_pre'
|
- 'css_for_each_descendant_pre'
|
||||||
|
- 'damon_for_each_region'
|
||||||
|
- 'damon_for_each_region_from'
|
||||||
|
- 'damon_for_each_region_safe'
|
||||||
|
- 'damon_for_each_scheme'
|
||||||
|
- 'damon_for_each_scheme_safe'
|
||||||
|
- 'damon_for_each_target'
|
||||||
|
- 'damon_for_each_target_safe'
|
||||||
|
- 'damos_for_each_filter'
|
||||||
|
- 'damos_for_each_filter_safe'
|
||||||
|
- 'damos_for_each_ops_filter'
|
||||||
|
- 'damos_for_each_ops_filter_safe'
|
||||||
|
- 'damos_for_each_quota_goal'
|
||||||
|
- 'damos_for_each_quota_goal_safe'
|
||||||
|
- 'data__for_each_file'
|
||||||
|
- 'data__for_each_file_new'
|
||||||
|
- 'data__for_each_file_start'
|
||||||
|
- 'def_for_each_cpu'
|
||||||
- 'device_for_each_child_node'
|
- 'device_for_each_child_node'
|
||||||
|
- 'device_for_each_child_node_scoped'
|
||||||
|
- 'dma_fence_array_for_each'
|
||||||
- 'dma_fence_chain_for_each'
|
- 'dma_fence_chain_for_each'
|
||||||
|
- 'dma_fence_unwrap_for_each'
|
||||||
|
- 'dma_resv_for_each_fence'
|
||||||
|
- 'dma_resv_for_each_fence_unlocked'
|
||||||
- 'do_for_each_ftrace_op'
|
- 'do_for_each_ftrace_op'
|
||||||
- 'drm_atomic_crtc_for_each_plane'
|
- 'drm_atomic_crtc_for_each_plane'
|
||||||
- 'drm_atomic_crtc_state_for_each_plane'
|
- 'drm_atomic_crtc_state_for_each_plane'
|
||||||
@@ -119,9 +165,12 @@ ForEachMacros:
|
|||||||
- 'drm_client_for_each_connector_iter'
|
- 'drm_client_for_each_connector_iter'
|
||||||
- 'drm_client_for_each_modeset'
|
- 'drm_client_for_each_modeset'
|
||||||
- 'drm_connector_for_each_possible_encoder'
|
- 'drm_connector_for_each_possible_encoder'
|
||||||
|
- 'drm_exec_for_each_locked_object'
|
||||||
|
- 'drm_exec_for_each_locked_object_reverse'
|
||||||
- 'drm_for_each_bridge_in_chain'
|
- 'drm_for_each_bridge_in_chain'
|
||||||
- 'drm_for_each_connector_iter'
|
- 'drm_for_each_connector_iter'
|
||||||
- 'drm_for_each_crtc'
|
- 'drm_for_each_crtc'
|
||||||
|
- 'drm_for_each_crtc_reverse'
|
||||||
- 'drm_for_each_encoder'
|
- 'drm_for_each_encoder'
|
||||||
- 'drm_for_each_encoder_mask'
|
- 'drm_for_each_encoder_mask'
|
||||||
- 'drm_for_each_fb'
|
- 'drm_for_each_fb'
|
||||||
@@ -129,19 +178,64 @@ ForEachMacros:
|
|||||||
- 'drm_for_each_plane'
|
- 'drm_for_each_plane'
|
||||||
- 'drm_for_each_plane_mask'
|
- 'drm_for_each_plane_mask'
|
||||||
- 'drm_for_each_privobj'
|
- 'drm_for_each_privobj'
|
||||||
|
- 'drm_gem_for_each_gpuvm_bo'
|
||||||
|
- 'drm_gem_for_each_gpuvm_bo_safe'
|
||||||
|
- 'drm_gpusvm_for_each_range'
|
||||||
|
- 'drm_gpuva_for_each_op'
|
||||||
|
- 'drm_gpuva_for_each_op_from_reverse'
|
||||||
|
- 'drm_gpuva_for_each_op_reverse'
|
||||||
|
- 'drm_gpuva_for_each_op_safe'
|
||||||
|
- 'drm_gpuvm_bo_for_each_va'
|
||||||
|
- 'drm_gpuvm_bo_for_each_va_safe'
|
||||||
|
- 'drm_gpuvm_for_each_va'
|
||||||
|
- 'drm_gpuvm_for_each_va_range'
|
||||||
|
- 'drm_gpuvm_for_each_va_range_safe'
|
||||||
|
- 'drm_gpuvm_for_each_va_safe'
|
||||||
- 'drm_mm_for_each_hole'
|
- 'drm_mm_for_each_hole'
|
||||||
- 'drm_mm_for_each_node'
|
- 'drm_mm_for_each_node'
|
||||||
- 'drm_mm_for_each_node_in_range'
|
- 'drm_mm_for_each_node_in_range'
|
||||||
- 'drm_mm_for_each_node_safe'
|
- 'drm_mm_for_each_node_safe'
|
||||||
|
- 'dsa_switch_for_each_available_port'
|
||||||
|
- 'dsa_switch_for_each_cpu_port'
|
||||||
|
- 'dsa_switch_for_each_cpu_port_continue_reverse'
|
||||||
|
- 'dsa_switch_for_each_port'
|
||||||
|
- 'dsa_switch_for_each_port_continue_reverse'
|
||||||
|
- 'dsa_switch_for_each_port_safe'
|
||||||
|
- 'dsa_switch_for_each_user_port'
|
||||||
|
- 'dsa_switch_for_each_user_port_continue_reverse'
|
||||||
|
- 'dsa_tree_for_each_cpu_port'
|
||||||
|
- 'dsa_tree_for_each_user_port'
|
||||||
|
- 'dsa_tree_for_each_user_port_continue_reverse'
|
||||||
|
- 'dso__for_each_symbol'
|
||||||
|
- 'elf_hash_for_each_possible'
|
||||||
|
- 'elf_symtab__for_each_symbol'
|
||||||
|
- 'evlist__for_each_cpu'
|
||||||
|
- 'evlist__for_each_entry'
|
||||||
|
- 'evlist__for_each_entry_continue'
|
||||||
|
- 'evlist__for_each_entry_from'
|
||||||
|
- 'evlist__for_each_entry_reverse'
|
||||||
|
- 'evlist__for_each_entry_safe'
|
||||||
- 'flow_action_for_each'
|
- 'flow_action_for_each'
|
||||||
|
- 'for_each_acpi_consumer_dev'
|
||||||
|
- 'for_each_acpi_dev_match'
|
||||||
- 'for_each_active_dev_scope'
|
- 'for_each_active_dev_scope'
|
||||||
- 'for_each_active_drhd_unit'
|
- 'for_each_active_drhd_unit'
|
||||||
- 'for_each_active_iommu'
|
- 'for_each_active_iommu'
|
||||||
|
- 'for_each_active_irq'
|
||||||
|
- 'for_each_active_route'
|
||||||
- 'for_each_aggr_pgid'
|
- 'for_each_aggr_pgid'
|
||||||
|
- 'for_each_alloc_capable_rdt_resource'
|
||||||
|
- 'for_each_and_bit'
|
||||||
|
- 'for_each_andnot_bit'
|
||||||
- 'for_each_available_child_of_node'
|
- 'for_each_available_child_of_node'
|
||||||
|
- 'for_each_available_child_of_node_scoped'
|
||||||
|
- 'for_each_bench'
|
||||||
- 'for_each_bio'
|
- 'for_each_bio'
|
||||||
- 'for_each_board_func_rsrc'
|
- 'for_each_board_func_rsrc'
|
||||||
|
- 'for_each_btf_ext_rec'
|
||||||
|
- 'for_each_btf_ext_sec'
|
||||||
- 'for_each_bvec'
|
- 'for_each_bvec'
|
||||||
|
- 'for_each_capable_rdt_resource'
|
||||||
- 'for_each_card_auxs'
|
- 'for_each_card_auxs'
|
||||||
- 'for_each_card_auxs_safe'
|
- 'for_each_card_auxs_safe'
|
||||||
- 'for_each_card_components'
|
- 'for_each_card_components'
|
||||||
@@ -154,22 +248,32 @@ ForEachMacros:
|
|||||||
- 'for_each_card_widgets_safe'
|
- 'for_each_card_widgets_safe'
|
||||||
- 'for_each_cgroup_storage_type'
|
- 'for_each_cgroup_storage_type'
|
||||||
- 'for_each_child_of_node'
|
- 'for_each_child_of_node'
|
||||||
|
- 'for_each_child_of_node_scoped'
|
||||||
|
- 'for_each_child_of_node_with_prefix'
|
||||||
- 'for_each_clear_bit'
|
- 'for_each_clear_bit'
|
||||||
- 'for_each_clear_bit_from'
|
- 'for_each_clear_bit_from'
|
||||||
|
- 'for_each_clear_bitrange'
|
||||||
|
- 'for_each_clear_bitrange_from'
|
||||||
|
- 'for_each_cmd'
|
||||||
- 'for_each_cmsghdr'
|
- 'for_each_cmsghdr'
|
||||||
|
- 'for_each_collection'
|
||||||
|
- 'for_each_comp_order'
|
||||||
- 'for_each_compatible_node'
|
- 'for_each_compatible_node'
|
||||||
- 'for_each_component_dais'
|
- 'for_each_component_dais'
|
||||||
- 'for_each_component_dais_safe'
|
- 'for_each_component_dais_safe'
|
||||||
- 'for_each_comp_order'
|
- 'for_each_conduit'
|
||||||
- 'for_each_console'
|
- 'for_each_console'
|
||||||
|
- 'for_each_console_srcu'
|
||||||
- 'for_each_cpu'
|
- 'for_each_cpu'
|
||||||
- 'for_each_cpu_and'
|
- 'for_each_cpu_and'
|
||||||
- 'for_each_cpu_not'
|
- 'for_each_cpu_andnot'
|
||||||
|
- 'for_each_cpu_from'
|
||||||
|
- 'for_each_cpu_or'
|
||||||
- 'for_each_cpu_wrap'
|
- 'for_each_cpu_wrap'
|
||||||
- 'for_each_dapm_widgets'
|
- 'for_each_dapm_widgets'
|
||||||
|
- 'for_each_dedup_cand'
|
||||||
- 'for_each_dev_addr'
|
- 'for_each_dev_addr'
|
||||||
- 'for_each_dev_scope'
|
- 'for_each_dev_scope'
|
||||||
- 'for_each_displayid_db'
|
|
||||||
- 'for_each_dma_cap_mask'
|
- 'for_each_dma_cap_mask'
|
||||||
- 'for_each_dpcm_be'
|
- 'for_each_dpcm_be'
|
||||||
- 'for_each_dpcm_be_rollback'
|
- 'for_each_dpcm_be_rollback'
|
||||||
@@ -182,107 +286,160 @@ ForEachMacros:
|
|||||||
- 'for_each_element'
|
- 'for_each_element'
|
||||||
- 'for_each_element_extid'
|
- 'for_each_element_extid'
|
||||||
- 'for_each_element_id'
|
- 'for_each_element_id'
|
||||||
|
- 'for_each_enabled_cpu'
|
||||||
- 'for_each_endpoint_of_node'
|
- 'for_each_endpoint_of_node'
|
||||||
|
- 'for_each_event'
|
||||||
|
- 'for_each_event_tps'
|
||||||
- 'for_each_evictable_lru'
|
- 'for_each_evictable_lru'
|
||||||
- 'for_each_fib6_node_rt_rcu'
|
- 'for_each_fib6_node_rt_rcu'
|
||||||
- 'for_each_fib6_walker_rt'
|
- 'for_each_fib6_walker_rt'
|
||||||
- 'for_each_free_mem_pfn_range_in_zone'
|
- 'for_each_file_lock'
|
||||||
- 'for_each_free_mem_pfn_range_in_zone_from'
|
- 'for_each_free_mem_pfn_range_in_zone_from'
|
||||||
- 'for_each_free_mem_range'
|
- 'for_each_free_mem_range'
|
||||||
- 'for_each_free_mem_range_reverse'
|
- 'for_each_free_mem_range_reverse'
|
||||||
- 'for_each_func_rsrc'
|
- 'for_each_func_rsrc'
|
||||||
|
- 'for_each_gpiochip_node'
|
||||||
|
- 'for_each_group_evsel'
|
||||||
|
- 'for_each_group_evsel_head'
|
||||||
|
- 'for_each_group_member'
|
||||||
|
- 'for_each_group_member_head'
|
||||||
- 'for_each_hstate'
|
- 'for_each_hstate'
|
||||||
|
- 'for_each_hwgpio'
|
||||||
|
- 'for_each_hwgpio_in_range'
|
||||||
- 'for_each_if'
|
- 'for_each_if'
|
||||||
|
- 'for_each_inject_fn'
|
||||||
|
- 'for_each_insn'
|
||||||
|
- 'for_each_insn_op_loc'
|
||||||
|
- 'for_each_insn_prefix'
|
||||||
|
- 'for_each_intid'
|
||||||
- 'for_each_iommu'
|
- 'for_each_iommu'
|
||||||
- 'for_each_ip_tunnel_rcu'
|
- 'for_each_ip_tunnel_rcu'
|
||||||
|
- 'for_each_irq_desc'
|
||||||
- 'for_each_irq_nr'
|
- 'for_each_irq_nr'
|
||||||
|
- 'for_each_lang'
|
||||||
|
- 'for_each_link_ch_maps'
|
||||||
- 'for_each_link_codecs'
|
- 'for_each_link_codecs'
|
||||||
- 'for_each_link_cpus'
|
- 'for_each_link_cpus'
|
||||||
- 'for_each_link_platforms'
|
- 'for_each_link_platforms'
|
||||||
- 'for_each_lru'
|
- 'for_each_lru'
|
||||||
- 'for_each_matching_node'
|
- 'for_each_matching_node'
|
||||||
- 'for_each_matching_node_and_match'
|
- 'for_each_matching_node_and_match'
|
||||||
- 'for_each_member'
|
- 'for_each_media_entity_data_link'
|
||||||
- 'for_each_mem_region'
|
|
||||||
- 'for_each_memblock_type'
|
|
||||||
- 'for_each_memcg_cache_index'
|
|
||||||
- 'for_each_mem_pfn_range'
|
- 'for_each_mem_pfn_range'
|
||||||
- '__for_each_mem_range'
|
|
||||||
- 'for_each_mem_range'
|
- 'for_each_mem_range'
|
||||||
- '__for_each_mem_range_rev'
|
|
||||||
- 'for_each_mem_range_rev'
|
- 'for_each_mem_range_rev'
|
||||||
|
- 'for_each_mem_region'
|
||||||
|
- 'for_each_member'
|
||||||
|
- 'for_each_memory'
|
||||||
- 'for_each_migratetype_order'
|
- 'for_each_migratetype_order'
|
||||||
- 'for_each_msi_entry'
|
- 'for_each_missing_reg'
|
||||||
- 'for_each_msi_entry_safe'
|
- 'for_each_mle_subelement'
|
||||||
|
- 'for_each_mod_mem_type'
|
||||||
|
- 'for_each_mon_capable_rdt_resource'
|
||||||
|
- 'for_each_mp_bvec'
|
||||||
- 'for_each_net'
|
- 'for_each_net'
|
||||||
- 'for_each_net_continue_reverse'
|
- 'for_each_net_continue_reverse'
|
||||||
|
- 'for_each_net_rcu'
|
||||||
- 'for_each_netdev'
|
- 'for_each_netdev'
|
||||||
- 'for_each_netdev_continue'
|
- 'for_each_netdev_continue'
|
||||||
- 'for_each_netdev_continue_rcu'
|
- 'for_each_netdev_continue_rcu'
|
||||||
- 'for_each_netdev_continue_reverse'
|
- 'for_each_netdev_continue_reverse'
|
||||||
|
- 'for_each_netdev_dump'
|
||||||
- 'for_each_netdev_feature'
|
- 'for_each_netdev_feature'
|
||||||
- 'for_each_netdev_in_bond_rcu'
|
- 'for_each_netdev_in_bond_rcu'
|
||||||
- 'for_each_netdev_rcu'
|
- 'for_each_netdev_rcu'
|
||||||
- 'for_each_netdev_reverse'
|
- 'for_each_netdev_reverse'
|
||||||
- 'for_each_netdev_safe'
|
- 'for_each_netdev_safe'
|
||||||
- 'for_each_net_rcu'
|
|
||||||
- 'for_each_new_connector_in_state'
|
- 'for_each_new_connector_in_state'
|
||||||
- 'for_each_new_crtc_in_state'
|
- 'for_each_new_crtc_in_state'
|
||||||
- 'for_each_new_mst_mgr_in_state'
|
- 'for_each_new_mst_mgr_in_state'
|
||||||
- 'for_each_new_plane_in_state'
|
- 'for_each_new_plane_in_state'
|
||||||
|
- 'for_each_new_plane_in_state_reverse'
|
||||||
- 'for_each_new_private_obj_in_state'
|
- 'for_each_new_private_obj_in_state'
|
||||||
|
- 'for_each_new_reg'
|
||||||
|
- 'for_each_nhlt_endpoint'
|
||||||
|
- 'for_each_nhlt_endpoint_fmtcfg'
|
||||||
|
- 'for_each_nhlt_fmtcfg'
|
||||||
- 'for_each_node'
|
- 'for_each_node'
|
||||||
- 'for_each_node_by_name'
|
- 'for_each_node_by_name'
|
||||||
- 'for_each_node_by_type'
|
- 'for_each_node_by_type'
|
||||||
- 'for_each_node_mask'
|
- 'for_each_node_mask'
|
||||||
|
- 'for_each_node_numadist'
|
||||||
- 'for_each_node_state'
|
- 'for_each_node_state'
|
||||||
- 'for_each_node_with_cpus'
|
- 'for_each_node_with_cpus'
|
||||||
- 'for_each_node_with_property'
|
- 'for_each_node_with_property'
|
||||||
- 'for_each_nonreserved_multicast_dest_pgid'
|
- 'for_each_nonreserved_multicast_dest_pgid'
|
||||||
|
- 'for_each_numa_hop_mask'
|
||||||
- 'for_each_of_allnodes'
|
- 'for_each_of_allnodes'
|
||||||
- 'for_each_of_allnodes_from'
|
- 'for_each_of_allnodes_from'
|
||||||
- 'for_each_of_cpu_node'
|
- 'for_each_of_cpu_node'
|
||||||
|
- 'for_each_of_graph_port'
|
||||||
|
- 'for_each_of_graph_port_endpoint'
|
||||||
- 'for_each_of_pci_range'
|
- 'for_each_of_pci_range'
|
||||||
- 'for_each_old_connector_in_state'
|
- 'for_each_old_connector_in_state'
|
||||||
- 'for_each_old_crtc_in_state'
|
- 'for_each_old_crtc_in_state'
|
||||||
- 'for_each_old_mst_mgr_in_state'
|
- 'for_each_old_mst_mgr_in_state'
|
||||||
|
- 'for_each_old_plane_in_state'
|
||||||
|
- 'for_each_old_private_obj_in_state'
|
||||||
- 'for_each_oldnew_connector_in_state'
|
- 'for_each_oldnew_connector_in_state'
|
||||||
- 'for_each_oldnew_crtc_in_state'
|
- 'for_each_oldnew_crtc_in_state'
|
||||||
- 'for_each_oldnew_mst_mgr_in_state'
|
- 'for_each_oldnew_mst_mgr_in_state'
|
||||||
- 'for_each_oldnew_plane_in_state'
|
- 'for_each_oldnew_plane_in_state'
|
||||||
- 'for_each_oldnew_plane_in_state_reverse'
|
- 'for_each_oldnew_plane_in_state_reverse'
|
||||||
- 'for_each_oldnew_private_obj_in_state'
|
- 'for_each_oldnew_private_obj_in_state'
|
||||||
- 'for_each_old_plane_in_state'
|
|
||||||
- 'for_each_old_private_obj_in_state'
|
|
||||||
- 'for_each_online_cpu'
|
- 'for_each_online_cpu'
|
||||||
|
- 'for_each_online_cpu_wrap'
|
||||||
- 'for_each_online_node'
|
- 'for_each_online_node'
|
||||||
- 'for_each_online_pgdat'
|
- 'for_each_online_pgdat'
|
||||||
|
- 'for_each_or_bit'
|
||||||
|
- 'for_each_page_ext'
|
||||||
|
- 'for_each_path'
|
||||||
- 'for_each_pci_bridge'
|
- 'for_each_pci_bridge'
|
||||||
- 'for_each_pci_dev'
|
- 'for_each_pci_dev'
|
||||||
- 'for_each_pci_msi_entry'
|
|
||||||
- 'for_each_pcm_streams'
|
- 'for_each_pcm_streams'
|
||||||
- 'for_each_physmem_range'
|
- 'for_each_physmem_range'
|
||||||
- 'for_each_populated_zone'
|
- 'for_each_populated_zone'
|
||||||
- 'for_each_possible_cpu'
|
- 'for_each_possible_cpu'
|
||||||
|
- 'for_each_possible_cpu_wrap'
|
||||||
|
- 'for_each_present_blessed_reg'
|
||||||
- 'for_each_present_cpu'
|
- 'for_each_present_cpu'
|
||||||
|
- 'for_each_present_section_nr'
|
||||||
- 'for_each_prime_number'
|
- 'for_each_prime_number'
|
||||||
- 'for_each_prime_number_from'
|
- 'for_each_prime_number_from'
|
||||||
|
- 'for_each_probe_cache_entry'
|
||||||
- 'for_each_process'
|
- 'for_each_process'
|
||||||
- 'for_each_process_thread'
|
- 'for_each_process_thread'
|
||||||
|
- 'for_each_prop_codec_conf'
|
||||||
|
- 'for_each_prop_dai_codec'
|
||||||
|
- 'for_each_prop_dai_cpu'
|
||||||
|
- 'for_each_prop_dlc_codecs'
|
||||||
|
- 'for_each_prop_dlc_cpus'
|
||||||
|
- 'for_each_prop_dlc_platforms'
|
||||||
- 'for_each_property_of_node'
|
- 'for_each_property_of_node'
|
||||||
- 'for_each_registered_fb'
|
- 'for_each_rdt_resource'
|
||||||
|
- 'for_each_reg'
|
||||||
|
- 'for_each_reg_filtered'
|
||||||
|
- 'for_each_reloc'
|
||||||
|
- 'for_each_reloc_from'
|
||||||
- 'for_each_requested_gpio'
|
- 'for_each_requested_gpio'
|
||||||
- 'for_each_requested_gpio_in_range'
|
- 'for_each_requested_gpio_in_range'
|
||||||
|
- 'for_each_reserved_child_of_node'
|
||||||
- 'for_each_reserved_mem_range'
|
- 'for_each_reserved_mem_range'
|
||||||
- 'for_each_reserved_mem_region'
|
- 'for_each_reserved_mem_region'
|
||||||
|
- 'for_each_rtd_ch_maps'
|
||||||
- 'for_each_rtd_codec_dais'
|
- 'for_each_rtd_codec_dais'
|
||||||
- 'for_each_rtd_codec_dais_rollback'
|
|
||||||
- 'for_each_rtd_components'
|
- 'for_each_rtd_components'
|
||||||
- 'for_each_rtd_cpu_dais'
|
- 'for_each_rtd_cpu_dais'
|
||||||
- 'for_each_rtd_cpu_dais_rollback'
|
|
||||||
- 'for_each_rtd_dais'
|
- 'for_each_rtd_dais'
|
||||||
|
- 'for_each_rtd_dais_reverse'
|
||||||
|
- 'for_each_sband_iftype_data'
|
||||||
|
- 'for_each_script'
|
||||||
|
- 'for_each_sec'
|
||||||
- 'for_each_set_bit'
|
- 'for_each_set_bit'
|
||||||
- 'for_each_set_bit_from'
|
- 'for_each_set_bit_from'
|
||||||
|
- 'for_each_set_bit_wrap'
|
||||||
|
- 'for_each_set_bitrange'
|
||||||
|
- 'for_each_set_bitrange_from'
|
||||||
- 'for_each_set_clump8'
|
- 'for_each_set_clump8'
|
||||||
- 'for_each_sg'
|
- 'for_each_sg'
|
||||||
- 'for_each_sg_dma_page'
|
- 'for_each_sg_dma_page'
|
||||||
@@ -292,22 +449,37 @@ ForEachMacros:
|
|||||||
- 'for_each_sgtable_page'
|
- 'for_each_sgtable_page'
|
||||||
- 'for_each_sgtable_sg'
|
- 'for_each_sgtable_sg'
|
||||||
- 'for_each_sibling_event'
|
- 'for_each_sibling_event'
|
||||||
|
- 'for_each_sta_active_link'
|
||||||
- 'for_each_subelement'
|
- 'for_each_subelement'
|
||||||
- 'for_each_subelement_extid'
|
- 'for_each_subelement_extid'
|
||||||
- 'for_each_subelement_id'
|
- 'for_each_subelement_id'
|
||||||
- '__for_each_thread'
|
- 'for_each_sublist'
|
||||||
|
- 'for_each_subsystem'
|
||||||
|
- 'for_each_suite'
|
||||||
|
- 'for_each_supported_activate_fn'
|
||||||
|
- 'for_each_supported_inject_fn'
|
||||||
|
- 'for_each_sym'
|
||||||
- 'for_each_thread'
|
- 'for_each_thread'
|
||||||
|
- 'for_each_token'
|
||||||
- 'for_each_unicast_dest_pgid'
|
- 'for_each_unicast_dest_pgid'
|
||||||
|
- 'for_each_valid_link'
|
||||||
|
- 'for_each_vif_active_link'
|
||||||
|
- 'for_each_vma'
|
||||||
|
- 'for_each_vma_range'
|
||||||
|
- 'for_each_vsi'
|
||||||
- 'for_each_wakeup_source'
|
- 'for_each_wakeup_source'
|
||||||
- 'for_each_zone'
|
- 'for_each_zone'
|
||||||
- 'for_each_zone_zonelist'
|
- 'for_each_zone_zonelist'
|
||||||
- 'for_each_zone_zonelist_nodemask'
|
- 'for_each_zone_zonelist_nodemask'
|
||||||
|
- 'func_for_each_insn'
|
||||||
- 'fwnode_for_each_available_child_node'
|
- 'fwnode_for_each_available_child_node'
|
||||||
- 'fwnode_for_each_child_node'
|
- 'fwnode_for_each_child_node'
|
||||||
|
- 'fwnode_for_each_parent_node'
|
||||||
- 'fwnode_graph_for_each_endpoint'
|
- 'fwnode_graph_for_each_endpoint'
|
||||||
- 'gadget_for_each_ep'
|
- 'gadget_for_each_ep'
|
||||||
- 'genradix_for_each'
|
- 'genradix_for_each'
|
||||||
- 'genradix_for_each_from'
|
- 'genradix_for_each_from'
|
||||||
|
- 'genradix_for_each_reverse'
|
||||||
- 'hash_for_each'
|
- 'hash_for_each'
|
||||||
- 'hash_for_each_possible'
|
- 'hash_for_each_possible'
|
||||||
- 'hash_for_each_possible_rcu'
|
- 'hash_for_each_possible_rcu'
|
||||||
@@ -315,7 +487,13 @@ ForEachMacros:
|
|||||||
- 'hash_for_each_possible_safe'
|
- 'hash_for_each_possible_safe'
|
||||||
- 'hash_for_each_rcu'
|
- 'hash_for_each_rcu'
|
||||||
- 'hash_for_each_safe'
|
- 'hash_for_each_safe'
|
||||||
|
- 'hashmap__for_each_entry'
|
||||||
|
- 'hashmap__for_each_entry_safe'
|
||||||
|
- 'hashmap__for_each_key_entry'
|
||||||
|
- 'hashmap__for_each_key_entry_safe'
|
||||||
- 'hctx_for_each_ctx'
|
- 'hctx_for_each_ctx'
|
||||||
|
- 'hists__for_each_format'
|
||||||
|
- 'hists__for_each_sort_list'
|
||||||
- 'hlist_bl_for_each_entry'
|
- 'hlist_bl_for_each_entry'
|
||||||
- 'hlist_bl_for_each_entry_rcu'
|
- 'hlist_bl_for_each_entry_rcu'
|
||||||
- 'hlist_bl_for_each_entry_safe'
|
- 'hlist_bl_for_each_entry_safe'
|
||||||
@@ -330,7 +508,7 @@ ForEachMacros:
|
|||||||
- 'hlist_for_each_entry_rcu_bh'
|
- 'hlist_for_each_entry_rcu_bh'
|
||||||
- 'hlist_for_each_entry_rcu_notrace'
|
- 'hlist_for_each_entry_rcu_notrace'
|
||||||
- 'hlist_for_each_entry_safe'
|
- 'hlist_for_each_entry_safe'
|
||||||
- '__hlist_for_each_rcu'
|
- 'hlist_for_each_entry_srcu'
|
||||||
- 'hlist_for_each_safe'
|
- 'hlist_for_each_safe'
|
||||||
- 'hlist_nulls_for_each_entry'
|
- 'hlist_nulls_for_each_entry'
|
||||||
- 'hlist_nulls_for_each_entry_from'
|
- 'hlist_nulls_for_each_entry_from'
|
||||||
@@ -338,17 +516,19 @@ ForEachMacros:
|
|||||||
- 'hlist_nulls_for_each_entry_safe'
|
- 'hlist_nulls_for_each_entry_safe'
|
||||||
- 'i3c_bus_for_each_i2cdev'
|
- 'i3c_bus_for_each_i2cdev'
|
||||||
- 'i3c_bus_for_each_i3cdev'
|
- 'i3c_bus_for_each_i3cdev'
|
||||||
- 'ide_host_for_each_port'
|
|
||||||
- 'ide_port_for_each_dev'
|
|
||||||
- 'ide_port_for_each_present_dev'
|
|
||||||
- 'idr_for_each_entry'
|
- 'idr_for_each_entry'
|
||||||
- 'idr_for_each_entry_continue'
|
- 'idr_for_each_entry_continue'
|
||||||
- 'idr_for_each_entry_continue_ul'
|
- 'idr_for_each_entry_continue_ul'
|
||||||
- 'idr_for_each_entry_ul'
|
- 'idr_for_each_entry_ul'
|
||||||
|
- 'iio_for_each_active_channel'
|
||||||
- 'in_dev_for_each_ifa_rcu'
|
- 'in_dev_for_each_ifa_rcu'
|
||||||
- 'in_dev_for_each_ifa_rtnl'
|
- 'in_dev_for_each_ifa_rtnl'
|
||||||
|
- 'in_dev_for_each_ifa_rtnl_net'
|
||||||
- 'inet_bind_bucket_for_each'
|
- 'inet_bind_bucket_for_each'
|
||||||
- 'inet_lhash2_for_each_icsk_rcu'
|
- 'interval_tree_for_each_span'
|
||||||
|
- 'intlist__for_each_entry'
|
||||||
|
- 'intlist__for_each_entry_safe'
|
||||||
|
- 'kcore_copy__for_each_phdr'
|
||||||
- 'key_for_each'
|
- 'key_for_each'
|
||||||
- 'key_for_each_safe'
|
- 'key_for_each_safe'
|
||||||
- 'klp_for_each_func'
|
- 'klp_for_each_func'
|
||||||
@@ -359,7 +539,9 @@ ForEachMacros:
|
|||||||
- 'klp_for_each_object_static'
|
- 'klp_for_each_object_static'
|
||||||
- 'kunit_suite_for_each_test_case'
|
- 'kunit_suite_for_each_test_case'
|
||||||
- 'kvm_for_each_memslot'
|
- 'kvm_for_each_memslot'
|
||||||
|
- 'kvm_for_each_memslot_in_gfn_range'
|
||||||
- 'kvm_for_each_vcpu'
|
- 'kvm_for_each_vcpu'
|
||||||
|
- 'libbpf_nla_for_each_attr'
|
||||||
- 'list_for_each'
|
- 'list_for_each'
|
||||||
- 'list_for_each_codec'
|
- 'list_for_each_codec'
|
||||||
- 'list_for_each_codec_safe'
|
- 'list_for_each_codec_safe'
|
||||||
@@ -378,29 +560,53 @@ ForEachMacros:
|
|||||||
- 'list_for_each_entry_safe_continue'
|
- 'list_for_each_entry_safe_continue'
|
||||||
- 'list_for_each_entry_safe_from'
|
- 'list_for_each_entry_safe_from'
|
||||||
- 'list_for_each_entry_safe_reverse'
|
- 'list_for_each_entry_safe_reverse'
|
||||||
|
- 'list_for_each_entry_srcu'
|
||||||
|
- 'list_for_each_from'
|
||||||
- 'list_for_each_prev'
|
- 'list_for_each_prev'
|
||||||
- 'list_for_each_prev_safe'
|
- 'list_for_each_prev_safe'
|
||||||
|
- 'list_for_each_rcu'
|
||||||
- 'list_for_each_safe'
|
- 'list_for_each_safe'
|
||||||
- 'llist_for_each'
|
- 'llist_for_each'
|
||||||
- 'llist_for_each_entry'
|
- 'llist_for_each_entry'
|
||||||
- 'llist_for_each_entry_safe'
|
- 'llist_for_each_entry_safe'
|
||||||
- 'llist_for_each_safe'
|
- 'llist_for_each_safe'
|
||||||
|
- 'lwq_for_each_safe'
|
||||||
|
- 'map__for_each_symbol'
|
||||||
|
- 'map__for_each_symbol_by_name'
|
||||||
|
- 'mas_for_each'
|
||||||
|
- 'mas_for_each_rev'
|
||||||
- 'mci_for_each_dimm'
|
- 'mci_for_each_dimm'
|
||||||
- 'media_device_for_each_entity'
|
- 'media_device_for_each_entity'
|
||||||
- 'media_device_for_each_intf'
|
- 'media_device_for_each_intf'
|
||||||
- 'media_device_for_each_link'
|
- 'media_device_for_each_link'
|
||||||
- 'media_device_for_each_pad'
|
- 'media_device_for_each_pad'
|
||||||
|
- 'media_entity_for_each_pad'
|
||||||
|
- 'media_pipeline_for_each_entity'
|
||||||
|
- 'media_pipeline_for_each_pad'
|
||||||
|
- 'mlx5_lag_for_each_peer_mdev'
|
||||||
|
- 'mptcp_for_each_subflow'
|
||||||
|
- 'msi_domain_for_each_desc'
|
||||||
|
- 'msi_for_each_desc'
|
||||||
|
- 'mt_for_each'
|
||||||
|
- 'nanddev_io_for_each_block'
|
||||||
- 'nanddev_io_for_each_page'
|
- 'nanddev_io_for_each_page'
|
||||||
|
- 'neigh_for_each_in_bucket'
|
||||||
|
- 'neigh_for_each_in_bucket_rcu'
|
||||||
|
- 'neigh_for_each_in_bucket_safe'
|
||||||
- 'netdev_for_each_lower_dev'
|
- 'netdev_for_each_lower_dev'
|
||||||
- 'netdev_for_each_lower_private'
|
- 'netdev_for_each_lower_private'
|
||||||
- 'netdev_for_each_lower_private_rcu'
|
- 'netdev_for_each_lower_private_rcu'
|
||||||
- 'netdev_for_each_mc_addr'
|
- 'netdev_for_each_mc_addr'
|
||||||
|
- 'netdev_for_each_synced_mc_addr'
|
||||||
|
- 'netdev_for_each_synced_uc_addr'
|
||||||
- 'netdev_for_each_uc_addr'
|
- 'netdev_for_each_uc_addr'
|
||||||
- 'netdev_for_each_upper_dev_rcu'
|
- 'netdev_for_each_upper_dev_rcu'
|
||||||
- 'netdev_hw_addr_list_for_each'
|
- 'netdev_hw_addr_list_for_each'
|
||||||
- 'nft_rule_for_each_expr'
|
- 'nft_rule_for_each_expr'
|
||||||
- 'nla_for_each_attr'
|
- 'nla_for_each_attr'
|
||||||
|
- 'nla_for_each_attr_type'
|
||||||
- 'nla_for_each_nested'
|
- 'nla_for_each_nested'
|
||||||
|
- 'nla_for_each_nested_type'
|
||||||
- 'nlmsg_for_each_attr'
|
- 'nlmsg_for_each_attr'
|
||||||
- 'nlmsg_for_each_msg'
|
- 'nlmsg_for_each_msg'
|
||||||
- 'nr_neigh_for_each'
|
- 'nr_neigh_for_each'
|
||||||
@@ -411,8 +617,26 @@ ForEachMacros:
|
|||||||
- 'of_property_for_each_string'
|
- 'of_property_for_each_string'
|
||||||
- 'of_property_for_each_u32'
|
- 'of_property_for_each_u32'
|
||||||
- 'pci_bus_for_each_resource'
|
- 'pci_bus_for_each_resource'
|
||||||
|
- 'pci_dev_for_each_resource'
|
||||||
|
- 'pcl_for_each_chunk'
|
||||||
|
- 'pcl_for_each_segment'
|
||||||
- 'pcm_for_each_format'
|
- 'pcm_for_each_format'
|
||||||
- 'ping_portaddr_for_each_entry'
|
- 'perf_config_items__for_each_entry'
|
||||||
|
- 'perf_config_sections__for_each_entry'
|
||||||
|
- 'perf_config_set__for_each_entry'
|
||||||
|
- 'perf_cpu_map__for_each_cpu'
|
||||||
|
- 'perf_cpu_map__for_each_cpu_skip_any'
|
||||||
|
- 'perf_cpu_map__for_each_idx'
|
||||||
|
- 'perf_evlist__for_each_entry'
|
||||||
|
- 'perf_evlist__for_each_entry_reverse'
|
||||||
|
- 'perf_evlist__for_each_entry_safe'
|
||||||
|
- 'perf_evlist__for_each_evsel'
|
||||||
|
- 'perf_evlist__for_each_mmap'
|
||||||
|
- 'perf_evsel_for_each_per_thread_period_safe'
|
||||||
|
- 'perf_hpp_list__for_each_format'
|
||||||
|
- 'perf_hpp_list__for_each_format_safe'
|
||||||
|
- 'perf_hpp_list__for_each_sort_list'
|
||||||
|
- 'perf_hpp_list__for_each_sort_list_safe'
|
||||||
- 'plist_for_each'
|
- 'plist_for_each'
|
||||||
- 'plist_for_each_continue'
|
- 'plist_for_each_continue'
|
||||||
- 'plist_for_each_entry'
|
- 'plist_for_each_entry'
|
||||||
@@ -426,6 +650,7 @@ ForEachMacros:
|
|||||||
- 'queue_for_each_hw_ctx'
|
- 'queue_for_each_hw_ctx'
|
||||||
- 'radix_tree_for_each_slot'
|
- 'radix_tree_for_each_slot'
|
||||||
- 'radix_tree_for_each_tagged'
|
- 'radix_tree_for_each_tagged'
|
||||||
|
- 'rb_for_each'
|
||||||
- 'rbtree_postorder_for_each_entry_safe'
|
- 'rbtree_postorder_for_each_entry_safe'
|
||||||
- 'rdma_for_each_block'
|
- 'rdma_for_each_block'
|
||||||
- 'rdma_for_each_port'
|
- 'rdma_for_each_port'
|
||||||
@@ -443,18 +668,24 @@ ForEachMacros:
|
|||||||
- 'rht_for_each_from'
|
- 'rht_for_each_from'
|
||||||
- 'rht_for_each_rcu'
|
- 'rht_for_each_rcu'
|
||||||
- 'rht_for_each_rcu_from'
|
- 'rht_for_each_rcu_from'
|
||||||
- '__rq_for_each_bio'
|
|
||||||
- 'rq_for_each_bvec'
|
- 'rq_for_each_bvec'
|
||||||
- 'rq_for_each_segment'
|
- 'rq_for_each_segment'
|
||||||
|
- 'rq_list_for_each'
|
||||||
|
- 'rq_list_for_each_safe'
|
||||||
|
- 'sample_read_group__for_each'
|
||||||
- 'scsi_for_each_prot_sg'
|
- 'scsi_for_each_prot_sg'
|
||||||
- 'scsi_for_each_sg'
|
- 'scsi_for_each_sg'
|
||||||
- 'sctp_for_each_hentry'
|
- 'sctp_for_each_hentry'
|
||||||
- 'sctp_skb_for_each'
|
- 'sctp_skb_for_each'
|
||||||
|
- 'sec_for_each_insn'
|
||||||
|
- 'sec_for_each_insn_continue'
|
||||||
|
- 'sec_for_each_insn_from'
|
||||||
|
- 'sec_for_each_sym'
|
||||||
- 'shdma_for_each_chan'
|
- 'shdma_for_each_chan'
|
||||||
- '__shost_for_each_device'
|
|
||||||
- 'shost_for_each_device'
|
- 'shost_for_each_device'
|
||||||
- 'sk_for_each'
|
- 'sk_for_each'
|
||||||
- 'sk_for_each_bound'
|
- 'sk_for_each_bound'
|
||||||
|
- 'sk_for_each_bound_safe'
|
||||||
- 'sk_for_each_entry_offset_rcu'
|
- 'sk_for_each_entry_offset_rcu'
|
||||||
- 'sk_for_each_from'
|
- 'sk_for_each_from'
|
||||||
- 'sk_for_each_rcu'
|
- 'sk_for_each_rcu'
|
||||||
@@ -468,8 +699,20 @@ ForEachMacros:
|
|||||||
- 'snd_soc_dapm_widget_for_each_path_safe'
|
- 'snd_soc_dapm_widget_for_each_path_safe'
|
||||||
- 'snd_soc_dapm_widget_for_each_sink_path'
|
- 'snd_soc_dapm_widget_for_each_sink_path'
|
||||||
- 'snd_soc_dapm_widget_for_each_source_path'
|
- 'snd_soc_dapm_widget_for_each_source_path'
|
||||||
|
- 'sparsebit_for_each_set_range'
|
||||||
|
- 'strlist__for_each_entry'
|
||||||
|
- 'strlist__for_each_entry_safe'
|
||||||
|
- 'sym_for_each_insn'
|
||||||
|
- 'sym_for_each_insn_continue_reverse'
|
||||||
|
- 'symbols__for_each_entry'
|
||||||
- 'tb_property_for_each'
|
- 'tb_property_for_each'
|
||||||
|
- 'tcf_act_for_each_action'
|
||||||
- 'tcf_exts_for_each_action'
|
- 'tcf_exts_for_each_action'
|
||||||
|
- 'test_suite__for_each_test_case'
|
||||||
|
- 'tool_pmu__for_each_event'
|
||||||
|
- 'ttm_bo_lru_for_each_reserved_guarded'
|
||||||
|
- 'ttm_resource_manager_for_each_res'
|
||||||
|
- 'udp_lrpa_for_each_entry_rcu'
|
||||||
- 'udp_portaddr_for_each_entry'
|
- 'udp_portaddr_for_each_entry'
|
||||||
- 'udp_portaddr_for_each_entry_rcu'
|
- 'udp_portaddr_for_each_entry_rcu'
|
||||||
- 'usb_hub_for_each_child'
|
- 'usb_hub_for_each_child'
|
||||||
@@ -479,7 +722,15 @@ ForEachMacros:
|
|||||||
- 'v4l2_m2m_for_each_src_buf'
|
- 'v4l2_m2m_for_each_src_buf'
|
||||||
- 'v4l2_m2m_for_each_src_buf_safe'
|
- 'v4l2_m2m_for_each_src_buf_safe'
|
||||||
- 'virtio_device_for_each_vq'
|
- 'virtio_device_for_each_vq'
|
||||||
|
- 'vkms_config_for_each_connector'
|
||||||
|
- 'vkms_config_for_each_crtc'
|
||||||
|
- 'vkms_config_for_each_encoder'
|
||||||
|
- 'vkms_config_for_each_plane'
|
||||||
|
- 'vkms_config_connector_for_each_possible_encoder'
|
||||||
|
- 'vkms_config_encoder_for_each_possible_crtc'
|
||||||
|
- 'vkms_config_plane_for_each_possible_crtc'
|
||||||
- 'while_for_each_ftrace_op'
|
- 'while_for_each_ftrace_op'
|
||||||
|
- 'workloads__for_each'
|
||||||
- 'xa_for_each'
|
- 'xa_for_each'
|
||||||
- 'xa_for_each_marked'
|
- 'xa_for_each_marked'
|
||||||
- 'xa_for_each_range'
|
- 'xa_for_each_range'
|
||||||
@@ -492,15 +743,20 @@ ForEachMacros:
|
|||||||
- 'xbc_node_for_each_array_value'
|
- 'xbc_node_for_each_array_value'
|
||||||
- 'xbc_node_for_each_child'
|
- 'xbc_node_for_each_child'
|
||||||
- 'xbc_node_for_each_key_value'
|
- 'xbc_node_for_each_key_value'
|
||||||
|
- 'xbc_node_for_each_subkey'
|
||||||
|
- 'ynl_attr_for_each'
|
||||||
|
- 'ynl_attr_for_each_nested'
|
||||||
|
- 'ynl_attr_for_each_payload'
|
||||||
- 'zorro_for_each_dev'
|
- 'zorro_for_each_dev'
|
||||||
|
|
||||||
#IncludeBlocks: Preserve # Unknown to clang-format-5.0
|
IncludeBlocks: Preserve
|
||||||
IncludeCategories:
|
IncludeCategories:
|
||||||
- Regex: '.*'
|
- Regex: '.*'
|
||||||
Priority: 1
|
Priority: 1
|
||||||
IncludeIsMainRegex: '(Test)?$'
|
IncludeIsMainRegex: '(Test)?$'
|
||||||
IndentCaseLabels: false
|
IndentCaseLabels: false
|
||||||
#IndentPPDirectives: None # Unknown to clang-format-5.0
|
IndentGotoLabels: false
|
||||||
|
IndentPPDirectives: None
|
||||||
IndentWidth: 8
|
IndentWidth: 8
|
||||||
IndentWrappedFunctionNames: false
|
IndentWrappedFunctionNames: false
|
||||||
JavaScriptQuotes: Leave
|
JavaScriptQuotes: Leave
|
||||||
@@ -510,13 +766,13 @@ MacroBlockBegin: ''
|
|||||||
MacroBlockEnd: ''
|
MacroBlockEnd: ''
|
||||||
MaxEmptyLinesToKeep: 1
|
MaxEmptyLinesToKeep: 1
|
||||||
NamespaceIndentation: None
|
NamespaceIndentation: None
|
||||||
#ObjCBinPackProtocolList: Auto # Unknown to clang-format-5.0
|
ObjCBinPackProtocolList: Auto
|
||||||
ObjCBlockIndentWidth: 8
|
ObjCBlockIndentWidth: 8
|
||||||
ObjCSpaceAfterProperty: true
|
ObjCSpaceAfterProperty: true
|
||||||
ObjCSpaceBeforeProtocolList: true
|
ObjCSpaceBeforeProtocolList: true
|
||||||
|
|
||||||
# Taken from git's rules
|
# Taken from git's rules
|
||||||
#PenaltyBreakAssignment: 10 # Unknown to clang-format-4.0
|
PenaltyBreakAssignment: 10
|
||||||
PenaltyBreakBeforeFirstCallParameter: 30
|
PenaltyBreakBeforeFirstCallParameter: 30
|
||||||
PenaltyBreakComment: 10
|
PenaltyBreakComment: 10
|
||||||
PenaltyBreakFirstLessLess: 0
|
PenaltyBreakFirstLessLess: 0
|
||||||
@@ -527,14 +783,14 @@ PenaltyReturnTypeOnItsOwnLine: 60
|
|||||||
PointerAlignment: Right
|
PointerAlignment: Right
|
||||||
ReflowComments: false
|
ReflowComments: false
|
||||||
SortIncludes: false
|
SortIncludes: false
|
||||||
#SortUsingDeclarations: false # Unknown to clang-format-4.0
|
SortUsingDeclarations: false
|
||||||
SpaceAfterCStyleCast: false
|
SpaceAfterCStyleCast: false
|
||||||
SpaceAfterTemplateKeyword: true
|
SpaceAfterTemplateKeyword: true
|
||||||
SpaceBeforeAssignmentOperators: true
|
SpaceBeforeAssignmentOperators: true
|
||||||
#SpaceBeforeCtorInitializerColon: true # Unknown to clang-format-5.0
|
SpaceBeforeCtorInitializerColon: true
|
||||||
#SpaceBeforeInheritanceColon: true # Unknown to clang-format-5.0
|
SpaceBeforeInheritanceColon: true
|
||||||
SpaceBeforeParens: ControlStatements
|
SpaceBeforeParens: ControlStatementsExceptForEachMacros
|
||||||
#SpaceBeforeRangeBasedForLoopColon: true # Unknown to clang-format-5.0
|
SpaceBeforeRangeBasedForLoopColon: true
|
||||||
SpaceInEmptyParentheses: false
|
SpaceInEmptyParentheses: false
|
||||||
SpacesBeforeTrailingComments: 1
|
SpacesBeforeTrailingComments: 1
|
||||||
SpacesInAngles: false
|
SpacesInAngles: false
|
||||||
|
|||||||
@@ -31,7 +31,8 @@ static DEFINE_MUTEX(allowlist_mutex);
|
|||||||
static struct root_profile default_root_profile;
|
static struct root_profile default_root_profile;
|
||||||
static struct non_root_profile default_non_root_profile;
|
static struct non_root_profile default_non_root_profile;
|
||||||
|
|
||||||
static int allow_list_arr[PAGE_SIZE / sizeof(int)] __read_mostly __aligned(PAGE_SIZE);
|
static int allow_list_arr[PAGE_SIZE / sizeof(int)] __read_mostly
|
||||||
|
__aligned(PAGE_SIZE);
|
||||||
static int allow_list_pointer __read_mostly = 0;
|
static int allow_list_pointer __read_mostly = 0;
|
||||||
|
|
||||||
static void remove_uid_from_arr(uid_t uid)
|
static void remove_uid_from_arr(uid_t uid)
|
||||||
@@ -72,7 +73,7 @@ static void init_default_profiles()
|
|||||||
default_root_profile.groups_count = 1;
|
default_root_profile.groups_count = 1;
|
||||||
default_root_profile.groups[0] = 0;
|
default_root_profile.groups[0] = 0;
|
||||||
memcpy(&default_root_profile.capabilities.effective, &full_cap,
|
memcpy(&default_root_profile.capabilities.effective, &full_cap,
|
||||||
sizeof(default_root_profile.capabilities.effective));
|
sizeof(default_root_profile.capabilities.effective));
|
||||||
default_root_profile.namespaces = 0;
|
default_root_profile.namespaces = 0;
|
||||||
strcpy(default_root_profile.selinux_domain, KSU_DEFAULT_SELINUX_DOMAIN);
|
strcpy(default_root_profile.selinux_domain, KSU_DEFAULT_SELINUX_DOMAIN);
|
||||||
|
|
||||||
@@ -102,7 +103,7 @@ void ksu_show_allow_list(void)
|
|||||||
struct perm_data *p = NULL;
|
struct perm_data *p = NULL;
|
||||||
struct list_head *pos = NULL;
|
struct list_head *pos = NULL;
|
||||||
pr_info("ksu_show_allow_list\n");
|
pr_info("ksu_show_allow_list\n");
|
||||||
list_for_each (pos, &allow_list) {
|
list_for_each(pos, &allow_list) {
|
||||||
p = list_entry(pos, struct perm_data, list);
|
p = list_entry(pos, struct perm_data, list);
|
||||||
pr_info("uid :%d, allow: %d\n", p->profile.current_uid,
|
pr_info("uid :%d, allow: %d\n", p->profile.current_uid,
|
||||||
p->profile.allow_su);
|
p->profile.allow_su);
|
||||||
@@ -118,7 +119,8 @@ static void ksu_grant_root_to_shell()
|
|||||||
.current_uid = 2000,
|
.current_uid = 2000,
|
||||||
};
|
};
|
||||||
strcpy(profile.key, "com.android.shell");
|
strcpy(profile.key, "com.android.shell");
|
||||||
strcpy(profile.rp_config.profile.selinux_domain, KSU_DEFAULT_SELINUX_DOMAIN);
|
strcpy(profile.rp_config.profile.selinux_domain,
|
||||||
|
KSU_DEFAULT_SELINUX_DOMAIN);
|
||||||
ksu_set_app_profile(&profile, false);
|
ksu_set_app_profile(&profile, false);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -129,7 +131,7 @@ bool ksu_get_app_profile(struct app_profile *profile)
|
|||||||
struct list_head *pos = NULL;
|
struct list_head *pos = NULL;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
list_for_each (pos, &allow_list) {
|
list_for_each(pos, &allow_list) {
|
||||||
p = list_entry(pos, struct perm_data, list);
|
p = list_entry(pos, struct perm_data, list);
|
||||||
bool uid_match = profile->current_uid == p->profile.current_uid;
|
bool uid_match = profile->current_uid == p->profile.current_uid;
|
||||||
if (uid_match) {
|
if (uid_match) {
|
||||||
@@ -144,9 +146,10 @@ exit:
|
|||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool forbid_system_uid(uid_t uid) {
|
static inline bool forbid_system_uid(uid_t uid)
|
||||||
#define SHELL_UID 2000
|
{
|
||||||
#define SYSTEM_UID 1000
|
#define SHELL_UID 2000
|
||||||
|
#define SYSTEM_UID 1000
|
||||||
return uid < SHELL_UID && uid != SYSTEM_UID;
|
return uid < SHELL_UID && uid != SYSTEM_UID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,7 +188,7 @@ bool ksu_set_app_profile(struct app_profile *profile, bool persist)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_for_each (pos, &allow_list) {
|
list_for_each(pos, &allow_list) {
|
||||||
p = list_entry(pos, struct perm_data, list);
|
p = list_entry(pos, struct perm_data, list);
|
||||||
// both uid and package must match, otherwise it will break multiple package with different user id
|
// both uid and package must match, otherwise it will break multiple package with different user id
|
||||||
if (profile->current_uid == p->profile.current_uid &&
|
if (profile->current_uid == p->profile.current_uid &&
|
||||||
@@ -220,9 +223,11 @@ bool ksu_set_app_profile(struct app_profile *profile, bool persist)
|
|||||||
out:
|
out:
|
||||||
if (profile->current_uid <= BITMAP_UID_MAX) {
|
if (profile->current_uid <= BITMAP_UID_MAX) {
|
||||||
if (profile->allow_su)
|
if (profile->allow_su)
|
||||||
allow_list_bitmap[profile->current_uid / BITS_PER_BYTE] |= 1 << (profile->current_uid % BITS_PER_BYTE);
|
allow_list_bitmap[profile->current_uid / BITS_PER_BYTE] |=
|
||||||
|
1 << (profile->current_uid % BITS_PER_BYTE);
|
||||||
else
|
else
|
||||||
allow_list_bitmap[profile->current_uid / BITS_PER_BYTE] &= ~(1 << (profile->current_uid % BITS_PER_BYTE));
|
allow_list_bitmap[profile->current_uid / BITS_PER_BYTE] &=
|
||||||
|
~(1 << (profile->current_uid % BITS_PER_BYTE));
|
||||||
} else {
|
} else {
|
||||||
if (profile->allow_su) {
|
if (profile->allow_su) {
|
||||||
/*
|
/*
|
||||||
@@ -234,7 +239,8 @@ out:
|
|||||||
WARN_ON(1);
|
WARN_ON(1);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
allow_list_arr[allow_list_pointer++] = profile->current_uid;
|
allow_list_arr[allow_list_pointer++] =
|
||||||
|
profile->current_uid;
|
||||||
} else {
|
} else {
|
||||||
remove_uid_from_arr(profile->current_uid);
|
remove_uid_from_arr(profile->current_uid);
|
||||||
}
|
}
|
||||||
@@ -274,13 +280,15 @@ bool __ksu_is_allow_uid(uid_t uid)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (likely(ksu_is_manager_uid_valid()) && unlikely(ksu_get_manager_uid() == uid)) {
|
if (likely(ksu_is_manager_uid_valid()) &&
|
||||||
|
unlikely(ksu_get_manager_uid() == uid)) {
|
||||||
// manager is always allowed!
|
// manager is always allowed!
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (likely(uid <= BITMAP_UID_MAX)) {
|
if (likely(uid <= BITMAP_UID_MAX)) {
|
||||||
return !!(allow_list_bitmap[uid / BITS_PER_BYTE] & (1 << (uid % BITS_PER_BYTE)));
|
return !!(allow_list_bitmap[uid / BITS_PER_BYTE] &
|
||||||
|
(1 << (uid % BITS_PER_BYTE)));
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; i < allow_list_pointer; i++) {
|
for (i = 0; i < allow_list_pointer; i++) {
|
||||||
if (allow_list_arr[i] == uid)
|
if (allow_list_arr[i] == uid)
|
||||||
@@ -294,7 +302,8 @@ bool __ksu_is_allow_uid(uid_t uid)
|
|||||||
bool ksu_uid_should_umount(uid_t uid)
|
bool ksu_uid_should_umount(uid_t uid)
|
||||||
{
|
{
|
||||||
struct app_profile profile = { .current_uid = uid };
|
struct app_profile profile = { .current_uid = uid };
|
||||||
if (likely(ksu_is_manager_uid_valid()) && unlikely(ksu_get_manager_uid() == uid)) {
|
if (likely(ksu_is_manager_uid_valid()) &&
|
||||||
|
unlikely(ksu_get_manager_uid() == uid)) {
|
||||||
// we should not umount on manager!
|
// we should not umount on manager!
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -321,7 +330,7 @@ struct root_profile *ksu_get_root_profile(uid_t uid)
|
|||||||
struct perm_data *p = NULL;
|
struct perm_data *p = NULL;
|
||||||
struct list_head *pos = NULL;
|
struct list_head *pos = NULL;
|
||||||
|
|
||||||
list_for_each (pos, &allow_list) {
|
list_for_each(pos, &allow_list) {
|
||||||
p = list_entry(pos, struct perm_data, list);
|
p = list_entry(pos, struct perm_data, list);
|
||||||
if (uid == p->profile.current_uid && p->profile.allow_su) {
|
if (uid == p->profile.current_uid && p->profile.allow_su) {
|
||||||
if (!p->profile.rp_config.use_default) {
|
if (!p->profile.rp_config.use_default) {
|
||||||
@@ -339,7 +348,7 @@ bool ksu_get_allow_list(int *array, int *length, bool allow)
|
|||||||
struct perm_data *p = NULL;
|
struct perm_data *p = NULL;
|
||||||
struct list_head *pos = NULL;
|
struct list_head *pos = NULL;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
list_for_each (pos, &allow_list) {
|
list_for_each(pos, &allow_list) {
|
||||||
p = list_entry(pos, struct perm_data, list);
|
p = list_entry(pos, struct perm_data, list);
|
||||||
// pr_info("get_allow_list uid: %d allow: %d\n", p->uid, p->allow);
|
// pr_info("get_allow_list uid: %d allow: %d\n", p->uid, p->allow);
|
||||||
if (p->profile.allow_su == allow) {
|
if (p->profile.allow_su == allow) {
|
||||||
@@ -359,10 +368,11 @@ void do_save_allow_list(struct work_struct *work)
|
|||||||
struct list_head *pos = NULL;
|
struct list_head *pos = NULL;
|
||||||
loff_t off = 0;
|
loff_t off = 0;
|
||||||
|
|
||||||
struct file *fp =
|
struct file *fp = ksu_filp_open_compat(
|
||||||
ksu_filp_open_compat(KERNEL_SU_ALLOWLIST, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
KERNEL_SU_ALLOWLIST, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||||
if (IS_ERR(fp)) {
|
if (IS_ERR(fp)) {
|
||||||
pr_err("save_allow_list create file failed: %ld\n", PTR_ERR(fp));
|
pr_err("save_allow_list create file failed: %ld\n",
|
||||||
|
PTR_ERR(fp));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -379,7 +389,7 @@ void do_save_allow_list(struct work_struct *work)
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_for_each (pos, &allow_list) {
|
list_for_each(pos, &allow_list) {
|
||||||
p = list_entry(pos, struct perm_data, list);
|
p = list_entry(pos, struct perm_data, list);
|
||||||
pr_info("save allow list, name: %s uid: %d, allow: %d\n",
|
pr_info("save allow list, name: %s uid: %d, allow: %d\n",
|
||||||
p->profile.key, p->profile.current_uid,
|
p->profile.key, p->profile.current_uid,
|
||||||
@@ -450,7 +460,8 @@ exit:
|
|||||||
filp_close(fp, 0);
|
filp_close(fp, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ksu_prune_allowlist(bool (*is_uid_valid)(uid_t, char *, void *), void *data)
|
void ksu_prune_allowlist(bool (*is_uid_valid)(uid_t, char *, void *),
|
||||||
|
void *data)
|
||||||
{
|
{
|
||||||
struct perm_data *np = NULL;
|
struct perm_data *np = NULL;
|
||||||
struct perm_data *n = NULL;
|
struct perm_data *n = NULL;
|
||||||
@@ -458,7 +469,7 @@ void ksu_prune_allowlist(bool (*is_uid_valid)(uid_t, char *, void *), void *data
|
|||||||
bool modified = false;
|
bool modified = false;
|
||||||
// TODO: use RCU!
|
// TODO: use RCU!
|
||||||
mutex_lock(&allowlist_mutex);
|
mutex_lock(&allowlist_mutex);
|
||||||
list_for_each_entry_safe (np, n, &allow_list, list) {
|
list_for_each_entry_safe(np, n, &allow_list, list) {
|
||||||
uid_t uid = np->profile.current_uid;
|
uid_t uid = np->profile.current_uid;
|
||||||
char *package = np->profile.key;
|
char *package = np->profile.key;
|
||||||
// we use this uid for special cases, don't prune it!
|
// we use this uid for special cases, don't prune it!
|
||||||
@@ -468,7 +479,8 @@ void ksu_prune_allowlist(bool (*is_uid_valid)(uid_t, char *, void *), void *data
|
|||||||
pr_info("prune uid: %d, package: %s\n", uid, package);
|
pr_info("prune uid: %d, package: %s\n", uid, package);
|
||||||
list_del(&np->list);
|
list_del(&np->list);
|
||||||
if (likely(uid <= BITMAP_UID_MAX)) {
|
if (likely(uid <= BITMAP_UID_MAX)) {
|
||||||
allow_list_bitmap[uid / BITS_PER_BYTE] &= ~(1 << (uid % BITS_PER_BYTE));
|
allow_list_bitmap[uid / BITS_PER_BYTE] &=
|
||||||
|
~(1 << (uid % BITS_PER_BYTE));
|
||||||
}
|
}
|
||||||
remove_uid_from_arr(uid);
|
remove_uid_from_arr(uid);
|
||||||
smp_mb();
|
smp_mb();
|
||||||
@@ -520,7 +532,7 @@ void ksu_allowlist_exit(void)
|
|||||||
|
|
||||||
// free allowlist
|
// free allowlist
|
||||||
mutex_lock(&allowlist_mutex);
|
mutex_lock(&allowlist_mutex);
|
||||||
list_for_each_entry_safe (np, n, &allow_list, list) {
|
list_for_each_entry_safe(np, n, &allow_list, list) {
|
||||||
list_del(&np->list);
|
list_del(&np->list);
|
||||||
kfree(np);
|
kfree(np);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,8 @@ bool __ksu_is_allow_uid(uid_t uid);
|
|||||||
|
|
||||||
bool ksu_get_allow_list(int *array, int *length, bool allow);
|
bool ksu_get_allow_list(int *array, int *length, bool allow);
|
||||||
|
|
||||||
void ksu_prune_allowlist(bool (*is_uid_exist)(uid_t, char *, void *), void *data);
|
void ksu_prune_allowlist(bool (*is_uid_exist)(uid_t, char *, void *),
|
||||||
|
void *data);
|
||||||
|
|
||||||
bool ksu_get_app_profile(struct app_profile *);
|
bool ksu_get_app_profile(struct app_profile *);
|
||||||
bool ksu_set_app_profile(struct app_profile *, bool persist);
|
bool ksu_set_app_profile(struct app_profile *, bool persist);
|
||||||
|
|||||||
@@ -29,10 +29,10 @@ static struct apk_sign_key {
|
|||||||
unsigned size;
|
unsigned size;
|
||||||
const char *sha256;
|
const char *sha256;
|
||||||
} apk_sign_keys[] = {
|
} apk_sign_keys[] = {
|
||||||
{EXPECTED_SIZE_SHIRKNEKO, EXPECTED_HASH_SHIRKNEKO}, // SukiSU
|
{ EXPECTED_SIZE_SHIRKNEKO, EXPECTED_HASH_SHIRKNEKO }, // SukiSU
|
||||||
{EXPECTED_SIZE_OTHER, EXPECTED_HASH_OTHER}, // Dynamic Sign
|
{ EXPECTED_SIZE_OTHER, EXPECTED_HASH_OTHER }, // Dynamic Sign
|
||||||
#ifdef EXPECTED_SIZE
|
#ifdef EXPECTED_SIZE
|
||||||
{EXPECTED_SIZE, EXPECTED_HASH}, // Custom
|
{ EXPECTED_SIZE, EXPECTED_HASH }, // Custom
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -82,7 +82,8 @@ static int ksu_sha256(const unsigned char *data, unsigned int datalen,
|
|||||||
crypto_free_shash(alg);
|
crypto_free_shash(alg);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
static bool check_block(struct file *fp, u32 *size4, loff_t *pos, u32 *offset, int *matched_index)
|
static bool check_block(struct file *fp, u32 *size4, loff_t *pos, u32 *offset,
|
||||||
|
int *matched_index)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct apk_sign_key sign_key;
|
struct apk_sign_key sign_key;
|
||||||
@@ -127,7 +128,7 @@ static bool check_block(struct file *fp, u32 *size4, loff_t *pos, u32 *offset, i
|
|||||||
}
|
}
|
||||||
ksu_kernel_read_compat(fp, cert, *size4, pos);
|
ksu_kernel_read_compat(fp, cert, *size4, pos);
|
||||||
unsigned char digest[SHA256_DIGEST_SIZE];
|
unsigned char digest[SHA256_DIGEST_SIZE];
|
||||||
if (ksu_sha256(cert, *size4, digest) < 0 ) {
|
if (ksu_sha256(cert, *size4, digest) < 0) {
|
||||||
pr_info("sha256 error\n");
|
pr_info("sha256 error\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -136,8 +137,9 @@ static bool check_block(struct file *fp, u32 *size4, loff_t *pos, u32 *offset, i
|
|||||||
hash_str[SHA256_DIGEST_SIZE * 2] = '\0';
|
hash_str[SHA256_DIGEST_SIZE * 2] = '\0';
|
||||||
|
|
||||||
bin2hex(hash_str, digest, SHA256_DIGEST_SIZE);
|
bin2hex(hash_str, digest, SHA256_DIGEST_SIZE);
|
||||||
pr_info("sha256: %s, expected: %s, index: %d\n", hash_str, sign_key.sha256, i);
|
pr_info("sha256: %s, expected: %s, index: %d\n", hash_str,
|
||||||
|
sign_key.sha256, i);
|
||||||
|
|
||||||
if (strcmp(sign_key.sha256, hash_str) == 0) {
|
if (strcmp(sign_key.sha256, hash_str) == 0) {
|
||||||
signature_valid = true;
|
signature_valid = true;
|
||||||
if (matched_index) {
|
if (matched_index) {
|
||||||
@@ -202,7 +204,8 @@ static bool has_v1_signature_file(struct file *fp)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __always_inline bool check_v2_signature(char *path, bool check_multi_manager, int *signature_index)
|
static __always_inline bool
|
||||||
|
check_v2_signature(char *path, bool check_multi_manager, int *signature_index)
|
||||||
{
|
{
|
||||||
unsigned char buffer[0x11] = { 0 };
|
unsigned char buffer[0x11] = { 0 };
|
||||||
u32 size4;
|
u32 size4;
|
||||||
@@ -279,7 +282,8 @@ static __always_inline bool check_v2_signature(char *path, bool check_multi_mana
|
|||||||
offset = 4;
|
offset = 4;
|
||||||
if (id == 0x7109871au) {
|
if (id == 0x7109871au) {
|
||||||
v2_signing_blocks++;
|
v2_signing_blocks++;
|
||||||
bool result = check_block(fp, &size4, &pos, &offset, &matched_index);
|
bool result = check_block(fp, &size4, &pos, &offset,
|
||||||
|
&matched_index);
|
||||||
if (result) {
|
if (result) {
|
||||||
v2_signing_valid = true;
|
v2_signing_valid = true;
|
||||||
}
|
}
|
||||||
@@ -327,11 +331,12 @@ clean:
|
|||||||
if (signature_index) {
|
if (signature_index) {
|
||||||
*signature_index = matched_index;
|
*signature_index = matched_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_multi_manager) {
|
if (check_multi_manager) {
|
||||||
// 0: ShirkNeko/SukiSU, 1: Dynamic Sign
|
// 0: ShirkNeko/SukiSU, 1: Dynamic Sign
|
||||||
if (matched_index == 0 || matched_index == 1) {
|
if (matched_index == 0 || matched_index == 1) {
|
||||||
pr_info("Multi-manager APK detected (dynamic_sign enabled): signature_index=%d\n", matched_index);
|
pr_info("Multi-manager APK detected (dynamic_sign enabled): signature_index=%d\n",
|
||||||
|
matched_index);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -369,10 +374,10 @@ module_param_cb(ksu_debug_manager_uid, &expected_size_ops,
|
|||||||
|
|
||||||
bool is_manager_apk(char *path)
|
bool is_manager_apk(char *path)
|
||||||
{
|
{
|
||||||
return check_v2_signature(path, false, NULL);
|
return check_v2_signature(path, false, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ksu_is_multi_manager_apk(char *path, int *signature_index)
|
bool ksu_is_multi_manager_apk(char *path, int *signature_index)
|
||||||
{
|
{
|
||||||
return check_v2_signature(path, true, signature_index);
|
return check_v2_signature(path, true, signature_index);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ static void disable_seccomp(struct task_struct *tsk)
|
|||||||
assert_spin_locked(&tsk->sighand->siglock);
|
assert_spin_locked(&tsk->sighand->siglock);
|
||||||
|
|
||||||
// disable seccomp
|
// disable seccomp
|
||||||
#if defined(CONFIG_GENERIC_ENTRY) && \
|
#if defined(CONFIG_GENERIC_ENTRY) && \
|
||||||
LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0)
|
LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0)
|
||||||
current_thread_info()->syscall_work &= ~SYSCALL_WORK_SECCOMP;
|
current_thread_info()->syscall_work &= ~SYSCALL_WORK_SECCOMP;
|
||||||
#else
|
#else
|
||||||
@@ -137,8 +137,8 @@ static void disable_seccomp(struct task_struct *tsk)
|
|||||||
#ifdef CONFIG_SECCOMP
|
#ifdef CONFIG_SECCOMP
|
||||||
tsk->seccomp.mode = 0;
|
tsk->seccomp.mode = 0;
|
||||||
if (tsk->seccomp.filter) {
|
if (tsk->seccomp.filter) {
|
||||||
// TODO: Add kernel 6.11+ support
|
// TODO: Add kernel 6.11+ support
|
||||||
// 5.9+ have filter_count and use seccomp_filter_release
|
// 5.9+ have filter_count and use seccomp_filter_release
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)
|
||||||
seccomp_filter_release(tsk);
|
seccomp_filter_release(tsk);
|
||||||
atomic_set(&tsk->seccomp.filter_count, 0);
|
atomic_set(&tsk->seccomp.filter_count, 0);
|
||||||
@@ -186,8 +186,8 @@ void escape_to_root(void)
|
|||||||
// setup capabilities
|
// setup capabilities
|
||||||
// we need CAP_DAC_READ_SEARCH becuase `/data/adb/ksud` is not accessible for non root process
|
// we need CAP_DAC_READ_SEARCH becuase `/data/adb/ksud` is not accessible for non root process
|
||||||
// we add it here but don't add it to cap_inhertiable, it would be dropped automaticly after exec!
|
// we add it here but don't add it to cap_inhertiable, it would be dropped automaticly after exec!
|
||||||
u64 cap_for_ksud =
|
u64 cap_for_ksud = profile->capabilities.effective |
|
||||||
profile->capabilities.effective | CAP_DAC_READ_SEARCH;
|
CAP_DAC_READ_SEARCH;
|
||||||
memcpy(&newcreds->cap_effective, &cap_for_ksud,
|
memcpy(&newcreds->cap_effective, &cap_for_ksud,
|
||||||
sizeof(newcreds->cap_effective));
|
sizeof(newcreds->cap_effective));
|
||||||
memcpy(&newcreds->cap_permitted, &profile->capabilities.effective,
|
memcpy(&newcreds->cap_permitted, &profile->capabilities.effective,
|
||||||
@@ -244,7 +244,8 @@ int ksu_handle_rename(struct dentry *old_dentry, struct dentry *new_dentry)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_EXT4_FS
|
#ifdef CONFIG_EXT4_FS
|
||||||
static void nuke_ext4_sysfs() {
|
static void nuke_ext4_sysfs()
|
||||||
|
{
|
||||||
struct path path;
|
struct path path;
|
||||||
int err = kern_path("/data/adb/modules", 0, &path);
|
int err = kern_path("/data/adb/modules", 0, &path);
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -252,8 +253,8 @@ static void nuke_ext4_sysfs() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct super_block* sb = path.dentry->d_inode->i_sb;
|
struct super_block *sb = path.dentry->d_inode->i_sb;
|
||||||
const char* name = sb->s_type->name;
|
const char *name = sb->s_type->name;
|
||||||
if (strcmp(name, "ext4") != 0) {
|
if (strcmp(name, "ext4") != 0) {
|
||||||
pr_info("nuke but module aren't mounted\n");
|
pr_info("nuke but module aren't mounted\n");
|
||||||
path_put(&path);
|
path_put(&path);
|
||||||
@@ -264,7 +265,9 @@ static void nuke_ext4_sysfs() {
|
|||||||
path_put(&path);
|
path_put(&path);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static inline void nuke_ext4_sysfs() { }
|
static inline void nuke_ext4_sysfs()
|
||||||
|
{
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
|
int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
|
||||||
@@ -338,13 +341,16 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
|
|||||||
|
|
||||||
// Allow root manager to get full version strings
|
// Allow root manager to get full version strings
|
||||||
if (arg2 == CMD_GET_FULL_VERSION) {
|
if (arg2 == CMD_GET_FULL_VERSION) {
|
||||||
char ksu_version_full[KSU_FULL_VERSION_STRING] = {0};
|
char ksu_version_full[KSU_FULL_VERSION_STRING] = { 0 };
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
|
||||||
strscpy(ksu_version_full, KSU_VERSION_FULL, KSU_FULL_VERSION_STRING);
|
strscpy(ksu_version_full, KSU_VERSION_FULL,
|
||||||
|
KSU_FULL_VERSION_STRING);
|
||||||
#else
|
#else
|
||||||
strlcpy(ksu_version_full, KSU_VERSION_FULL, KSU_FULL_VERSION_STRING);
|
strlcpy(ksu_version_full, KSU_VERSION_FULL,
|
||||||
|
KSU_FULL_VERSION_STRING);
|
||||||
#endif
|
#endif
|
||||||
if (copy_to_user((void __user *)arg3, ksu_version_full, KSU_FULL_VERSION_STRING)) {
|
if (copy_to_user((void __user *)arg3, ksu_version_full,
|
||||||
|
KSU_FULL_VERSION_STRING)) {
|
||||||
pr_err("prctl reply error, cmd: %lu\n", arg2);
|
pr_err("prctl reply error, cmd: %lu\n", arg2);
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
@@ -353,32 +359,34 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
|
|||||||
|
|
||||||
// Allow the root manager to configure dynamic signatures
|
// Allow the root manager to configure dynamic signatures
|
||||||
if (arg2 == CMD_DYNAMIC_SIGN) {
|
if (arg2 == CMD_DYNAMIC_SIGN) {
|
||||||
if (!from_root && !from_manager) {
|
if (!from_root && !from_manager) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dynamic_sign_user_config config;
|
struct dynamic_sign_user_config config;
|
||||||
|
|
||||||
if (copy_from_user(&config, (void __user *)arg3, sizeof(config))) {
|
if (copy_from_user(&config, (void __user *)arg3,
|
||||||
pr_err("copy dynamic sign config failed\n");
|
sizeof(config))) {
|
||||||
return 0;
|
pr_err("copy dynamic sign config failed\n");
|
||||||
}
|
return 0;
|
||||||
|
}
|
||||||
int ret = ksu_handle_dynamic_sign(&config);
|
|
||||||
|
int ret = ksu_handle_dynamic_sign(&config);
|
||||||
if (ret == 0 && config.operation == DYNAMIC_SIGN_OP_GET) {
|
|
||||||
if (copy_to_user((void __user *)arg3, &config, sizeof(config))) {
|
if (ret == 0 && config.operation == DYNAMIC_SIGN_OP_GET) {
|
||||||
pr_err("copy dynamic sign config back failed\n");
|
if (copy_to_user((void __user *)arg3, &config,
|
||||||
return 0;
|
sizeof(config))) {
|
||||||
}
|
pr_err("copy dynamic sign config back failed\n");
|
||||||
}
|
return 0;
|
||||||
|
}
|
||||||
if (ret == 0) {
|
}
|
||||||
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
|
|
||||||
pr_err("dynamic_sign: prctl reply error\n");
|
if (ret == 0) {
|
||||||
}
|
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
|
||||||
}
|
pr_err("dynamic_sign: prctl reply error\n");
|
||||||
return 0;
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allow root manager to get active managers
|
// Allow root manager to get active managers
|
||||||
@@ -386,12 +394,13 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
|
|||||||
if (!from_root && !from_manager) {
|
if (!from_root && !from_manager) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct manager_list_info manager_info;
|
struct manager_list_info manager_info;
|
||||||
int ret = ksu_get_active_managers(&manager_info);
|
int ret = ksu_get_active_managers(&manager_info);
|
||||||
|
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
if (copy_to_user((void __user *)arg3, &manager_info, sizeof(manager_info))) {
|
if (copy_to_user((void __user *)arg3, &manager_info,
|
||||||
|
sizeof(manager_info))) {
|
||||||
pr_err("copy manager list failed\n");
|
pr_err("copy manager list failed\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -414,8 +423,8 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
|
|||||||
pr_info("post-fs-data triggered\n");
|
pr_info("post-fs-data triggered\n");
|
||||||
on_post_fs_data();
|
on_post_fs_data();
|
||||||
// Initializing Dynamic Signatures
|
// Initializing Dynamic Signatures
|
||||||
ksu_dynamic_sign_init();
|
ksu_dynamic_sign_init();
|
||||||
pr_info("Dynamic sign config loaded during post-fs-data\n");
|
pr_info("Dynamic sign config loaded during post-fs-data\n");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -530,23 +539,24 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_KPM
|
#ifdef CONFIG_KPM
|
||||||
// ADD: 添加KPM模块控制
|
// ADD: 添加KPM模块控制
|
||||||
if(sukisu_is_kpm_control_code(arg2)) {
|
if (sukisu_is_kpm_control_code(arg2)) {
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
pr_info("KPM: calling before arg2=%d\n", (int) arg2);
|
pr_info("KPM: calling before arg2=%d\n", (int)arg2);
|
||||||
|
|
||||||
res = sukisu_handle_kpm(arg2, arg3, arg4, arg5);
|
res = sukisu_handle_kpm(arg2, arg3, arg4, arg5);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (arg2 == CMD_ENABLE_KPM) {
|
if (arg2 == CMD_ENABLE_KPM) {
|
||||||
bool KPM_Enabled = IS_ENABLED(CONFIG_KPM);
|
bool KPM_Enabled = IS_ENABLED(CONFIG_KPM);
|
||||||
if (copy_to_user((void __user *)arg3, &KPM_Enabled, sizeof(KPM_Enabled)))
|
if (copy_to_user((void __user *)arg3, &KPM_Enabled,
|
||||||
pr_info("KPM: copy_to_user() failed\n");
|
sizeof(KPM_Enabled)))
|
||||||
return 0;
|
pr_info("KPM: copy_to_user() failed\n");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// all other cmds are for 'root manager'
|
// all other cmds are for 'root manager'
|
||||||
@@ -654,7 +664,8 @@ static bool should_umount(struct path *path)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0) || defined(KSU_HAS_PATH_UMOUNT)
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0) || \
|
||||||
|
defined(KSU_HAS_PATH_UMOUNT)
|
||||||
static void ksu_path_umount(const char *mnt, struct path *path, int flags)
|
static void ksu_path_umount(const char *mnt, struct path *path, int flags)
|
||||||
{
|
{
|
||||||
int ret = path_umount(path, flags);
|
int ret = path_umount(path, flags);
|
||||||
@@ -662,7 +673,7 @@ static void ksu_path_umount(const char *mnt, struct path *path, int flags)
|
|||||||
pr_info("%s: path: %s ret: %d\n", __func__, mnt, ret);
|
pr_info("%s: path: %s ret: %d\n", __func__, mnt, ret);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#define ksu_umount_mnt(mnt, path, flags) (ksu_path_umount(mnt, path, flags))
|
#define ksu_umount_mnt(mnt, path, flags) (ksu_path_umount(mnt, path, flags))
|
||||||
#else
|
#else
|
||||||
static void ksu_sys_umount(const char *mnt, int flags)
|
static void ksu_sys_umount(const char *mnt, int flags)
|
||||||
{
|
{
|
||||||
@@ -681,10 +692,10 @@ static void ksu_sys_umount(const char *mnt, int flags)
|
|||||||
pr_info("%s: path: %s ret: %d\n", __func__, usermnt, ret);
|
pr_info("%s: path: %s ret: %d\n", __func__, usermnt, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ksu_umount_mnt(mnt, __unused, flags) \
|
#define ksu_umount_mnt(mnt, __unused, flags) \
|
||||||
({ \
|
({ \
|
||||||
path_put(__unused); \
|
path_put(__unused); \
|
||||||
ksu_sys_umount(mnt, flags); \
|
ksu_sys_umount(mnt, flags); \
|
||||||
})
|
})
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -781,13 +792,11 @@ int ksu_handle_setuid(struct cred *new, const struct cred *old)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// kernel 4.4 and 4.9
|
// kernel 4.4 and 4.9
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || \
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || \
|
||||||
defined(CONFIG_IS_HW_HISI) || \
|
defined(CONFIG_IS_HW_HISI) || defined(CONFIG_KSU_ALLOWLIST_WORKAROUND)
|
||||||
defined(CONFIG_KSU_ALLOWLIST_WORKAROUND)
|
|
||||||
int ksu_key_permission(key_ref_t key_ref, const struct cred *cred,
|
int ksu_key_permission(key_ref_t key_ref, const struct cred *cred,
|
||||||
unsigned perm)
|
unsigned perm)
|
||||||
{
|
{
|
||||||
if (init_session_keyring != NULL) {
|
if (init_session_keyring != NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -826,9 +835,11 @@ static int ksu_task_fix_setuid(struct cred *new, const struct cred *old,
|
|||||||
extern int __ksu_handle_devpts(struct inode *inode);
|
extern int __ksu_handle_devpts(struct inode *inode);
|
||||||
static int ksu_inode_permission(struct inode *inode, int mask)
|
static int ksu_inode_permission(struct inode *inode, int mask)
|
||||||
{
|
{
|
||||||
if (unlikely(inode->i_sb && inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC)) {
|
if (unlikely(inode->i_sb &&
|
||||||
|
inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC)) {
|
||||||
#ifdef CONFIG_KSU_DEBUG
|
#ifdef CONFIG_KSU_DEBUG
|
||||||
pr_info("%s: devpts inode accessed with mask: %x\n", __func__, mask);
|
pr_info("%s: devpts inode accessed with mask: %x\n", __func__,
|
||||||
|
mask);
|
||||||
#endif
|
#endif
|
||||||
__ksu_handle_devpts(inode);
|
__ksu_handle_devpts(inode);
|
||||||
}
|
}
|
||||||
@@ -840,9 +851,8 @@ static struct security_hook_list ksu_hooks[] = {
|
|||||||
LSM_HOOK_INIT(inode_rename, ksu_inode_rename),
|
LSM_HOOK_INIT(inode_rename, ksu_inode_rename),
|
||||||
LSM_HOOK_INIT(task_fix_setuid, ksu_task_fix_setuid),
|
LSM_HOOK_INIT(task_fix_setuid, ksu_task_fix_setuid),
|
||||||
LSM_HOOK_INIT(inode_permission, ksu_inode_permission),
|
LSM_HOOK_INIT(inode_permission, ksu_inode_permission),
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || \
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || \
|
||||||
defined(CONFIG_IS_HW_HISI) || \
|
defined(CONFIG_IS_HW_HISI) || defined(CONFIG_KSU_ALLOWLIST_WORKAROUND)
|
||||||
defined(CONFIG_KSU_ALLOWLIST_WORKAROUND)
|
|
||||||
LSM_HOOK_INIT(key_permission, ksu_key_permission)
|
LSM_HOOK_INIT(key_permission, ksu_key_permission)
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
@@ -911,7 +921,7 @@ static void free_security_hook_list(struct hlist_head *head)
|
|||||||
if (!head)
|
if (!head)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
hlist_for_each_entry_safe (entry, temp, head, list) {
|
hlist_for_each_entry_safe(entry, temp, head, list) {
|
||||||
hlist_del(&entry->list);
|
hlist_del(&entry->list);
|
||||||
kfree(entry);
|
kfree(entry);
|
||||||
}
|
}
|
||||||
@@ -930,7 +940,7 @@ struct hlist_head *copy_security_hlist(struct hlist_head *orig)
|
|||||||
struct security_hook_list *entry;
|
struct security_hook_list *entry;
|
||||||
struct security_hook_list *new_entry;
|
struct security_hook_list *new_entry;
|
||||||
|
|
||||||
hlist_for_each_entry (entry, orig, list) {
|
hlist_for_each_entry(entry, orig, list) {
|
||||||
new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL);
|
new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL);
|
||||||
if (!new_entry) {
|
if (!new_entry) {
|
||||||
free_security_hook_list(new_head);
|
free_security_hook_list(new_head);
|
||||||
@@ -957,7 +967,7 @@ static void *find_head_addr(void *security_ptr, int *index)
|
|||||||
for (int i = 0; i < LSM_SEARCH_MAX; i++) {
|
for (int i = 0; i < LSM_SEARCH_MAX; i++) {
|
||||||
struct hlist_head *head = head_start + i;
|
struct hlist_head *head = head_start + i;
|
||||||
struct security_hook_list *pos;
|
struct security_hook_list *pos;
|
||||||
hlist_for_each_entry (pos, head, list) {
|
hlist_for_each_entry(pos, head, list) {
|
||||||
if (pos->hook.capget == security_ptr) {
|
if (pos->hook.capget == security_ptr) {
|
||||||
if (index) {
|
if (index) {
|
||||||
*index = i;
|
*index = i;
|
||||||
@@ -970,33 +980,33 @@ static void *find_head_addr(void *security_ptr, int *index)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define GET_SYMBOL_ADDR(sym) \
|
#define GET_SYMBOL_ADDR(sym) \
|
||||||
({ \
|
({ \
|
||||||
void *addr = kallsyms_lookup_name(#sym ".cfi_jt"); \
|
void *addr = kallsyms_lookup_name(#sym ".cfi_jt"); \
|
||||||
if (!addr) { \
|
if (!addr) { \
|
||||||
addr = kallsyms_lookup_name(#sym); \
|
addr = kallsyms_lookup_name(#sym); \
|
||||||
} \
|
} \
|
||||||
addr; \
|
addr; \
|
||||||
})
|
})
|
||||||
|
|
||||||
#define KSU_LSM_HOOK_HACK_INIT(head_ptr, name, func) \
|
#define KSU_LSM_HOOK_HACK_INIT(head_ptr, name, func) \
|
||||||
do { \
|
do { \
|
||||||
static struct security_hook_list hook = { \
|
static struct security_hook_list hook = { \
|
||||||
.hook = { .name = func } \
|
.hook = { .name = func } \
|
||||||
}; \
|
}; \
|
||||||
hook.head = head_ptr; \
|
hook.head = head_ptr; \
|
||||||
hook.lsm = "ksu"; \
|
hook.lsm = "ksu"; \
|
||||||
struct hlist_head *new_head = copy_security_hlist(hook.head); \
|
struct hlist_head *new_head = copy_security_hlist(hook.head); \
|
||||||
if (!new_head) { \
|
if (!new_head) { \
|
||||||
pr_err("Failed to copy security list: %s\n", #name); \
|
pr_err("Failed to copy security list: %s\n", #name); \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
hlist_add_tail_rcu(&hook.list, new_head); \
|
hlist_add_tail_rcu(&hook.list, new_head); \
|
||||||
if (override_security_head(hook.head, new_head, \
|
if (override_security_head(hook.head, new_head, \
|
||||||
sizeof(*new_head))) { \
|
sizeof(*new_head))) { \
|
||||||
free_security_hook_list(new_head); \
|
free_security_hook_list(new_head); \
|
||||||
pr_err("Failed to hack lsm for: %s\n", #name); \
|
pr_err("Failed to hack lsm for: %s\n", #name); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
void __init ksu_lsm_hook_init(void)
|
void __init ksu_lsm_hook_init(void)
|
||||||
|
|||||||
@@ -24,9 +24,9 @@
|
|||||||
|
|
||||||
// Dynamic sign configuration
|
// Dynamic sign configuration
|
||||||
static struct dynamic_sign_config dynamic_sign = {
|
static struct dynamic_sign_config dynamic_sign = {
|
||||||
.size = 0x300,
|
.size = 0x300,
|
||||||
.hash = "0000000000000000000000000000000000000000000000000000000000000000",
|
.hash = "0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
.is_set = 0
|
.is_set = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
// Multi-manager state
|
// Multi-manager state
|
||||||
@@ -41,465 +41,500 @@ static struct work_struct ksu_clear_dynamic_sign_work;
|
|||||||
|
|
||||||
bool ksu_is_dynamic_sign_enabled(void)
|
bool ksu_is_dynamic_sign_enabled(void)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
bool enabled;
|
bool enabled;
|
||||||
|
|
||||||
spin_lock_irqsave(&dynamic_sign_lock, flags);
|
spin_lock_irqsave(&dynamic_sign_lock, flags);
|
||||||
enabled = dynamic_sign.is_set;
|
enabled = dynamic_sign.is_set;
|
||||||
spin_unlock_irqrestore(&dynamic_sign_lock, flags);
|
spin_unlock_irqrestore(&dynamic_sign_lock, flags);
|
||||||
|
|
||||||
return enabled;
|
return enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ksu_add_manager(uid_t uid, int signature_index)
|
void ksu_add_manager(uid_t uid, int signature_index)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!ksu_is_dynamic_sign_enabled()) {
|
if (!ksu_is_dynamic_sign_enabled()) {
|
||||||
pr_info("Dynamic sign not enabled, skipping multi-manager add\n");
|
pr_info("Dynamic sign not enabled, skipping multi-manager add\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(&managers_lock, flags);
|
spin_lock_irqsave(&managers_lock, flags);
|
||||||
|
|
||||||
// Check if manager already exists and update
|
// Check if manager already exists and update
|
||||||
for (i = 0; i < MAX_MANAGERS; i++) {
|
for (i = 0; i < MAX_MANAGERS; i++) {
|
||||||
if (active_managers[i].is_active && active_managers[i].uid == uid) {
|
if (active_managers[i].is_active &&
|
||||||
active_managers[i].signature_index = signature_index;
|
active_managers[i].uid == uid) {
|
||||||
spin_unlock_irqrestore(&managers_lock, flags);
|
active_managers[i].signature_index = signature_index;
|
||||||
pr_info("Updated manager uid=%d, signature_index=%d\n", uid, signature_index);
|
spin_unlock_irqrestore(&managers_lock, flags);
|
||||||
return;
|
pr_info("Updated manager uid=%d, signature_index=%d\n",
|
||||||
}
|
uid, signature_index);
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
// Find free slot for new manager
|
}
|
||||||
for (i = 0; i < MAX_MANAGERS; i++) {
|
|
||||||
if (!active_managers[i].is_active) {
|
// Find free slot for new manager
|
||||||
active_managers[i].uid = uid;
|
for (i = 0; i < MAX_MANAGERS; i++) {
|
||||||
active_managers[i].signature_index = signature_index;
|
if (!active_managers[i].is_active) {
|
||||||
active_managers[i].is_active = true;
|
active_managers[i].uid = uid;
|
||||||
spin_unlock_irqrestore(&managers_lock, flags);
|
active_managers[i].signature_index = signature_index;
|
||||||
pr_info("Added manager uid=%d, signature_index=%d\n", uid, signature_index);
|
active_managers[i].is_active = true;
|
||||||
return;
|
spin_unlock_irqrestore(&managers_lock, flags);
|
||||||
}
|
pr_info("Added manager uid=%d, signature_index=%d\n",
|
||||||
}
|
uid, signature_index);
|
||||||
|
return;
|
||||||
spin_unlock_irqrestore(&managers_lock, flags);
|
}
|
||||||
pr_warn("Failed to add manager, no free slots\n");
|
}
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&managers_lock, flags);
|
||||||
|
pr_warn("Failed to add manager, no free slots\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ksu_remove_manager(uid_t uid)
|
void ksu_remove_manager(uid_t uid)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!ksu_is_dynamic_sign_enabled()) {
|
if (!ksu_is_dynamic_sign_enabled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(&managers_lock, flags);
|
spin_lock_irqsave(&managers_lock, flags);
|
||||||
|
|
||||||
for (i = 0; i < MAX_MANAGERS; i++) {
|
for (i = 0; i < MAX_MANAGERS; i++) {
|
||||||
if (active_managers[i].is_active && active_managers[i].uid == uid) {
|
if (active_managers[i].is_active &&
|
||||||
active_managers[i].is_active = false;
|
active_managers[i].uid == uid) {
|
||||||
pr_info("Removed manager uid=%d\n", uid);
|
active_managers[i].is_active = false;
|
||||||
break;
|
pr_info("Removed manager uid=%d\n", uid);
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
spin_unlock_irqrestore(&managers_lock, flags);
|
|
||||||
|
spin_unlock_irqrestore(&managers_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ksu_is_any_manager(uid_t uid)
|
bool ksu_is_any_manager(uid_t uid)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
bool is_manager = false;
|
bool is_manager = false;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!ksu_is_dynamic_sign_enabled()) {
|
if (!ksu_is_dynamic_sign_enabled()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(&managers_lock, flags);
|
spin_lock_irqsave(&managers_lock, flags);
|
||||||
|
|
||||||
for (i = 0; i < MAX_MANAGERS; i++) {
|
for (i = 0; i < MAX_MANAGERS; i++) {
|
||||||
if (active_managers[i].is_active && active_managers[i].uid == uid) {
|
if (active_managers[i].is_active &&
|
||||||
is_manager = true;
|
active_managers[i].uid == uid) {
|
||||||
break;
|
is_manager = true;
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
spin_unlock_irqrestore(&managers_lock, flags);
|
|
||||||
return is_manager;
|
spin_unlock_irqrestore(&managers_lock, flags);
|
||||||
|
return is_manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ksu_get_manager_signature_index(uid_t uid)
|
int ksu_get_manager_signature_index(uid_t uid)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int signature_index = -1;
|
int signature_index = -1;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
// Check traditional manager first
|
// Check traditional manager first
|
||||||
if (ksu_manager_uid != KSU_INVALID_UID && uid == ksu_manager_uid) {
|
if (ksu_manager_uid != KSU_INVALID_UID && uid == ksu_manager_uid) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ksu_is_dynamic_sign_enabled()) {
|
if (!ksu_is_dynamic_sign_enabled()) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(&managers_lock, flags);
|
spin_lock_irqsave(&managers_lock, flags);
|
||||||
|
|
||||||
for (i = 0; i < MAX_MANAGERS; i++) {
|
for (i = 0; i < MAX_MANAGERS; i++) {
|
||||||
if (active_managers[i].is_active && active_managers[i].uid == uid) {
|
if (active_managers[i].is_active &&
|
||||||
signature_index = active_managers[i].signature_index;
|
active_managers[i].uid == uid) {
|
||||||
break;
|
signature_index = active_managers[i].signature_index;
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
spin_unlock_irqrestore(&managers_lock, flags);
|
|
||||||
return signature_index;
|
spin_unlock_irqrestore(&managers_lock, flags);
|
||||||
|
return signature_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clear_dynamic_manager(void)
|
static void clear_dynamic_manager(void)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
spin_lock_irqsave(&managers_lock, flags);
|
spin_lock_irqsave(&managers_lock, flags);
|
||||||
|
|
||||||
for (i = 0; i < MAX_MANAGERS; i++) {
|
for (i = 0; i < MAX_MANAGERS; i++) {
|
||||||
if (active_managers[i].is_active) {
|
if (active_managers[i].is_active) {
|
||||||
pr_info("Clearing dynamic manager uid=%d (signature_index=%d) for rescan\n",
|
pr_info("Clearing dynamic manager uid=%d (signature_index=%d) for rescan\n",
|
||||||
active_managers[i].uid, active_managers[i].signature_index);
|
active_managers[i].uid,
|
||||||
active_managers[i].is_active = false;
|
active_managers[i].signature_index);
|
||||||
}
|
active_managers[i].is_active = false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
spin_unlock_irqrestore(&managers_lock, flags);
|
|
||||||
|
spin_unlock_irqrestore(&managers_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ksu_get_active_managers(struct manager_list_info *info)
|
int ksu_get_active_managers(struct manager_list_info *info)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int i, count = 0;
|
int i, count = 0;
|
||||||
|
|
||||||
if (!info) {
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add traditional manager first
|
if (!info) {
|
||||||
if (ksu_manager_uid != KSU_INVALID_UID && count < 2) {
|
return -EINVAL;
|
||||||
info->managers[count].uid = ksu_manager_uid;
|
}
|
||||||
info->managers[count].signature_index = 0;
|
|
||||||
count++;
|
// Add traditional manager first
|
||||||
}
|
if (ksu_manager_uid != KSU_INVALID_UID && count < 2) {
|
||||||
|
info->managers[count].uid = ksu_manager_uid;
|
||||||
// Add dynamic managers
|
info->managers[count].signature_index = 0;
|
||||||
if (ksu_is_dynamic_sign_enabled()) {
|
count++;
|
||||||
spin_lock_irqsave(&managers_lock, flags);
|
}
|
||||||
|
|
||||||
for (i = 0; i < MAX_MANAGERS && count < 2; i++) {
|
// Add dynamic managers
|
||||||
if (active_managers[i].is_active) {
|
if (ksu_is_dynamic_sign_enabled()) {
|
||||||
info->managers[count].uid = active_managers[i].uid;
|
spin_lock_irqsave(&managers_lock, flags);
|
||||||
info->managers[count].signature_index = active_managers[i].signature_index;
|
|
||||||
count++;
|
for (i = 0; i < MAX_MANAGERS && count < 2; i++) {
|
||||||
}
|
if (active_managers[i].is_active) {
|
||||||
}
|
info->managers[count].uid =
|
||||||
|
active_managers[i].uid;
|
||||||
spin_unlock_irqrestore(&managers_lock, flags);
|
info->managers[count].signature_index =
|
||||||
}
|
active_managers[i].signature_index;
|
||||||
|
count++;
|
||||||
info->count = count;
|
}
|
||||||
return 0;
|
}
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&managers_lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
info->count = count;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_save_dynamic_sign(struct work_struct *work)
|
static void do_save_dynamic_sign(struct work_struct *work)
|
||||||
{
|
{
|
||||||
u32 magic = DYNAMIC_SIGN_FILE_MAGIC;
|
u32 magic = DYNAMIC_SIGN_FILE_MAGIC;
|
||||||
u32 version = DYNAMIC_SIGN_FILE_VERSION;
|
u32 version = DYNAMIC_SIGN_FILE_VERSION;
|
||||||
struct dynamic_sign_config config_to_save;
|
struct dynamic_sign_config config_to_save;
|
||||||
loff_t off = 0;
|
loff_t off = 0;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct file *fp;
|
struct file *fp;
|
||||||
|
|
||||||
spin_lock_irqsave(&dynamic_sign_lock, flags);
|
spin_lock_irqsave(&dynamic_sign_lock, flags);
|
||||||
config_to_save = dynamic_sign;
|
config_to_save = dynamic_sign;
|
||||||
spin_unlock_irqrestore(&dynamic_sign_lock, flags);
|
spin_unlock_irqrestore(&dynamic_sign_lock, flags);
|
||||||
|
|
||||||
if (!config_to_save.is_set) {
|
if (!config_to_save.is_set) {
|
||||||
pr_info("Dynamic sign config not set, skipping save\n");
|
pr_info("Dynamic sign config not set, skipping save\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fp = ksu_filp_open_compat(KERNEL_SU_DYNAMIC_SIGN, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
fp = ksu_filp_open_compat(KERNEL_SU_DYNAMIC_SIGN,
|
||||||
if (IS_ERR(fp)) {
|
O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||||
pr_err("save_dynamic_sign create file failed: %ld\n", PTR_ERR(fp));
|
if (IS_ERR(fp)) {
|
||||||
return;
|
pr_err("save_dynamic_sign create file failed: %ld\n",
|
||||||
}
|
PTR_ERR(fp));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (ksu_kernel_write_compat(fp, &magic, sizeof(magic), &off) != sizeof(magic)) {
|
if (ksu_kernel_write_compat(fp, &magic, sizeof(magic), &off) !=
|
||||||
pr_err("save_dynamic_sign write magic failed.\n");
|
sizeof(magic)) {
|
||||||
goto exit;
|
pr_err("save_dynamic_sign write magic failed.\n");
|
||||||
}
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
if (ksu_kernel_write_compat(fp, &version, sizeof(version), &off) != sizeof(version)) {
|
if (ksu_kernel_write_compat(fp, &version, sizeof(version), &off) !=
|
||||||
pr_err("save_dynamic_sign write version failed.\n");
|
sizeof(version)) {
|
||||||
goto exit;
|
pr_err("save_dynamic_sign write version failed.\n");
|
||||||
}
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
if (ksu_kernel_write_compat(fp, &config_to_save, sizeof(config_to_save), &off) != sizeof(config_to_save)) {
|
if (ksu_kernel_write_compat(fp, &config_to_save, sizeof(config_to_save),
|
||||||
pr_err("save_dynamic_sign write config failed.\n");
|
&off) != sizeof(config_to_save)) {
|
||||||
goto exit;
|
pr_err("save_dynamic_sign write config failed.\n");
|
||||||
}
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
pr_info("Dynamic sign config saved successfully\n");
|
pr_info("Dynamic sign config saved successfully\n");
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
filp_close(fp, 0);
|
filp_close(fp, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_load_dynamic_sign(struct work_struct *work)
|
static void do_load_dynamic_sign(struct work_struct *work)
|
||||||
{
|
{
|
||||||
loff_t off = 0;
|
loff_t off = 0;
|
||||||
ssize_t ret = 0;
|
ssize_t ret = 0;
|
||||||
struct file *fp = NULL;
|
struct file *fp = NULL;
|
||||||
u32 magic;
|
u32 magic;
|
||||||
u32 version;
|
u32 version;
|
||||||
struct dynamic_sign_config loaded_config;
|
struct dynamic_sign_config loaded_config;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
fp = ksu_filp_open_compat(KERNEL_SU_DYNAMIC_SIGN, O_RDONLY, 0);
|
fp = ksu_filp_open_compat(KERNEL_SU_DYNAMIC_SIGN, O_RDONLY, 0);
|
||||||
if (IS_ERR(fp)) {
|
if (IS_ERR(fp)) {
|
||||||
if (PTR_ERR(fp) == -ENOENT) {
|
if (PTR_ERR(fp) == -ENOENT) {
|
||||||
pr_info("No saved dynamic sign config found\n");
|
pr_info("No saved dynamic sign config found\n");
|
||||||
} else {
|
} else {
|
||||||
pr_err("load_dynamic_sign open file failed: %ld\n", PTR_ERR(fp));
|
pr_err("load_dynamic_sign open file failed: %ld\n",
|
||||||
}
|
PTR_ERR(fp));
|
||||||
return;
|
}
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (ksu_kernel_read_compat(fp, &magic, sizeof(magic), &off) != sizeof(magic) ||
|
if (ksu_kernel_read_compat(fp, &magic, sizeof(magic), &off) !=
|
||||||
magic != DYNAMIC_SIGN_FILE_MAGIC) {
|
sizeof(magic) ||
|
||||||
pr_err("dynamic sign file invalid magic: %x!\n", magic);
|
magic != DYNAMIC_SIGN_FILE_MAGIC) {
|
||||||
goto exit;
|
pr_err("dynamic sign file invalid magic: %x!\n", magic);
|
||||||
}
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
if (ksu_kernel_read_compat(fp, &version, sizeof(version), &off) != sizeof(version)) {
|
if (ksu_kernel_read_compat(fp, &version, sizeof(version), &off) !=
|
||||||
pr_err("dynamic sign read version failed\n");
|
sizeof(version)) {
|
||||||
goto exit;
|
pr_err("dynamic sign read version failed\n");
|
||||||
}
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
pr_info("dynamic sign file version: %d\n", version);
|
pr_info("dynamic sign file version: %d\n", version);
|
||||||
|
|
||||||
ret = ksu_kernel_read_compat(fp, &loaded_config, sizeof(loaded_config), &off);
|
ret = ksu_kernel_read_compat(fp, &loaded_config, sizeof(loaded_config),
|
||||||
if (ret <= 0) {
|
&off);
|
||||||
pr_info("load_dynamic_sign read err: %zd\n", ret);
|
if (ret <= 0) {
|
||||||
goto exit;
|
pr_info("load_dynamic_sign read err: %zd\n", ret);
|
||||||
}
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
if (ret != sizeof(loaded_config)) {
|
if (ret != sizeof(loaded_config)) {
|
||||||
pr_err("load_dynamic_sign read incomplete config: %zd/%zu\n", ret, sizeof(loaded_config));
|
pr_err("load_dynamic_sign read incomplete config: %zd/%zu\n",
|
||||||
goto exit;
|
ret, sizeof(loaded_config));
|
||||||
}
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
if (loaded_config.size < 0x100 || loaded_config.size > 0x1000) {
|
if (loaded_config.size < 0x100 || loaded_config.size > 0x1000) {
|
||||||
pr_err("Invalid saved config size: 0x%x\n", loaded_config.size);
|
pr_err("Invalid saved config size: 0x%x\n", loaded_config.size);
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen(loaded_config.hash) != 64) {
|
if (strlen(loaded_config.hash) != 64) {
|
||||||
pr_err("Invalid saved config hash length: %zu\n", strlen(loaded_config.hash));
|
pr_err("Invalid saved config hash length: %zu\n",
|
||||||
goto exit;
|
strlen(loaded_config.hash));
|
||||||
}
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
// Validate hash format
|
// Validate hash format
|
||||||
for (i = 0; i < 64; i++) {
|
for (i = 0; i < 64; i++) {
|
||||||
char c = loaded_config.hash[i];
|
char c = loaded_config.hash[i];
|
||||||
if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f'))) {
|
if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f'))) {
|
||||||
pr_err("Invalid saved config hash character at position %d: %c\n", i, c);
|
pr_err("Invalid saved config hash character at position %d: %c\n",
|
||||||
goto exit;
|
i, c);
|
||||||
}
|
goto exit;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(&dynamic_sign_lock, flags);
|
spin_lock_irqsave(&dynamic_sign_lock, flags);
|
||||||
dynamic_sign = loaded_config;
|
dynamic_sign = loaded_config;
|
||||||
spin_unlock_irqrestore(&dynamic_sign_lock, flags);
|
spin_unlock_irqrestore(&dynamic_sign_lock, flags);
|
||||||
|
|
||||||
pr_info("Dynamic sign config loaded: size=0x%x, hash=%.16s...\n",
|
pr_info("Dynamic sign config loaded: size=0x%x, hash=%.16s...\n",
|
||||||
loaded_config.size, loaded_config.hash);
|
loaded_config.size, loaded_config.hash);
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
filp_close(fp, 0);
|
filp_close(fp, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool persistent_dynamic_sign(void)
|
static bool persistent_dynamic_sign(void)
|
||||||
{
|
{
|
||||||
return ksu_queue_work(&ksu_save_dynamic_sign_work);
|
return ksu_queue_work(&ksu_save_dynamic_sign_work);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_clear_dynamic_sign(struct work_struct *work)
|
static void do_clear_dynamic_sign(struct work_struct *work)
|
||||||
{
|
{
|
||||||
loff_t off = 0;
|
loff_t off = 0;
|
||||||
struct file *fp;
|
struct file *fp;
|
||||||
char zero_buffer[512];
|
char zero_buffer[512];
|
||||||
|
|
||||||
memset(zero_buffer, 0, sizeof(zero_buffer));
|
memset(zero_buffer, 0, sizeof(zero_buffer));
|
||||||
|
|
||||||
fp = ksu_filp_open_compat(KERNEL_SU_DYNAMIC_SIGN, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
fp = ksu_filp_open_compat(KERNEL_SU_DYNAMIC_SIGN,
|
||||||
if (IS_ERR(fp)) {
|
O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||||
pr_err("clear_dynamic_sign create file failed: %ld\n", PTR_ERR(fp));
|
if (IS_ERR(fp)) {
|
||||||
return;
|
pr_err("clear_dynamic_sign create file failed: %ld\n",
|
||||||
}
|
PTR_ERR(fp));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Write null bytes to overwrite the file content
|
// Write null bytes to overwrite the file content
|
||||||
if (ksu_kernel_write_compat(fp, zero_buffer, sizeof(zero_buffer), &off) != sizeof(zero_buffer)) {
|
if (ksu_kernel_write_compat(fp, zero_buffer, sizeof(zero_buffer),
|
||||||
pr_err("clear_dynamic_sign write null bytes failed.\n");
|
&off) != sizeof(zero_buffer)) {
|
||||||
} else {
|
pr_err("clear_dynamic_sign write null bytes failed.\n");
|
||||||
pr_info("Dynamic sign config file cleared successfully\n");
|
} else {
|
||||||
}
|
pr_info("Dynamic sign config file cleared successfully\n");
|
||||||
|
}
|
||||||
|
|
||||||
filp_close(fp, 0);
|
filp_close(fp, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool clear_dynamic_sign_file(void)
|
static bool clear_dynamic_sign_file(void)
|
||||||
{
|
{
|
||||||
return ksu_queue_work(&ksu_clear_dynamic_sign_work);
|
return ksu_queue_work(&ksu_clear_dynamic_sign_work);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ksu_handle_dynamic_sign(struct dynamic_sign_user_config *config)
|
int ksu_handle_dynamic_sign(struct dynamic_sign_user_config *config)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!config) {
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (config->operation) {
|
|
||||||
case DYNAMIC_SIGN_OP_SET:
|
|
||||||
if (config->size < 0x100 || config->size > 0x1000) {
|
|
||||||
pr_err("invalid size: 0x%x\n", config->size);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strlen(config->hash) != 64) {
|
|
||||||
pr_err("invalid hash length: %zu\n", strlen(config->hash));
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate hash format
|
|
||||||
for (i = 0; i < 64; i++) {
|
|
||||||
char c = config->hash[i];
|
|
||||||
if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f'))) {
|
|
||||||
pr_err("invalid hash character at position %d: %c\n", i, c);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
spin_lock_irqsave(&dynamic_sign_lock, flags);
|
|
||||||
dynamic_sign.size = config->size;
|
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
|
|
||||||
strscpy(dynamic_sign.hash, config->hash, sizeof(dynamic_sign.hash));
|
|
||||||
#else
|
|
||||||
strlcpy(dynamic_sign.hash, config->hash, sizeof(dynamic_sign.hash));
|
|
||||||
#endif
|
|
||||||
dynamic_sign.is_set = 1;
|
|
||||||
spin_unlock_irqrestore(&dynamic_sign_lock, flags);
|
|
||||||
|
|
||||||
persistent_dynamic_sign();
|
|
||||||
pr_info("dynamic sign updated: size=0x%x, hash=%.16s... (multi-manager enabled)\n",
|
|
||||||
config->size, config->hash);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DYNAMIC_SIGN_OP_GET:
|
|
||||||
spin_lock_irqsave(&dynamic_sign_lock, flags);
|
|
||||||
if (dynamic_sign.is_set) {
|
|
||||||
config->size = dynamic_sign.size;
|
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
|
|
||||||
strscpy(config->hash, dynamic_sign.hash, sizeof(config->hash));
|
|
||||||
#else
|
|
||||||
strlcpy(config->hash, dynamic_sign.hash, sizeof(config->hash));
|
|
||||||
#endif
|
|
||||||
ret = 0;
|
|
||||||
} else {
|
|
||||||
ret = -ENODATA;
|
|
||||||
}
|
|
||||||
spin_unlock_irqrestore(&dynamic_sign_lock, flags);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DYNAMIC_SIGN_OP_CLEAR:
|
|
||||||
spin_lock_irqsave(&dynamic_sign_lock, flags);
|
|
||||||
dynamic_sign.size = 0x300;
|
|
||||||
strcpy(dynamic_sign.hash, "0000000000000000000000000000000000000000000000000000000000000000");
|
|
||||||
dynamic_sign.is_set = 0;
|
|
||||||
spin_unlock_irqrestore(&dynamic_sign_lock, flags);
|
|
||||||
|
|
||||||
// Clear only dynamic managers, preserve default manager
|
|
||||||
clear_dynamic_manager();
|
|
||||||
|
|
||||||
// Clear file using the same method as save
|
|
||||||
clear_dynamic_sign_file();
|
|
||||||
|
|
||||||
pr_info("Dynamic sign config cleared (multi-manager disabled)\n");
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
pr_err("Invalid dynamic sign operation: %d\n", config->operation);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
if (!config) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (config->operation) {
|
||||||
|
case DYNAMIC_SIGN_OP_SET:
|
||||||
|
if (config->size < 0x100 || config->size > 0x1000) {
|
||||||
|
pr_err("invalid size: 0x%x\n", config->size);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen(config->hash) != 64) {
|
||||||
|
pr_err("invalid hash length: %zu\n",
|
||||||
|
strlen(config->hash));
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate hash format
|
||||||
|
for (i = 0; i < 64; i++) {
|
||||||
|
char c = config->hash[i];
|
||||||
|
if (!((c >= '0' && c <= '9') ||
|
||||||
|
(c >= 'a' && c <= 'f'))) {
|
||||||
|
pr_err("invalid hash character at position %d: %c\n",
|
||||||
|
i, c);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_lock_irqsave(&dynamic_sign_lock, flags);
|
||||||
|
dynamic_sign.size = config->size;
|
||||||
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
|
||||||
|
strscpy(dynamic_sign.hash, config->hash,
|
||||||
|
sizeof(dynamic_sign.hash));
|
||||||
|
#else
|
||||||
|
strlcpy(dynamic_sign.hash, config->hash,
|
||||||
|
sizeof(dynamic_sign.hash));
|
||||||
|
#endif
|
||||||
|
dynamic_sign.is_set = 1;
|
||||||
|
spin_unlock_irqrestore(&dynamic_sign_lock, flags);
|
||||||
|
|
||||||
|
persistent_dynamic_sign();
|
||||||
|
pr_info("dynamic sign updated: size=0x%x, hash=%.16s... (multi-manager enabled)\n",
|
||||||
|
config->size, config->hash);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DYNAMIC_SIGN_OP_GET:
|
||||||
|
spin_lock_irqsave(&dynamic_sign_lock, flags);
|
||||||
|
if (dynamic_sign.is_set) {
|
||||||
|
config->size = dynamic_sign.size;
|
||||||
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
|
||||||
|
strscpy(config->hash, dynamic_sign.hash,
|
||||||
|
sizeof(config->hash));
|
||||||
|
#else
|
||||||
|
strlcpy(config->hash, dynamic_sign.hash,
|
||||||
|
sizeof(config->hash));
|
||||||
|
#endif
|
||||||
|
ret = 0;
|
||||||
|
} else {
|
||||||
|
ret = -ENODATA;
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&dynamic_sign_lock, flags);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DYNAMIC_SIGN_OP_CLEAR:
|
||||||
|
spin_lock_irqsave(&dynamic_sign_lock, flags);
|
||||||
|
dynamic_sign.size = 0x300;
|
||||||
|
strcpy(dynamic_sign.hash,
|
||||||
|
"0000000000000000000000000000000000000000000000000000000000000000");
|
||||||
|
dynamic_sign.is_set = 0;
|
||||||
|
spin_unlock_irqrestore(&dynamic_sign_lock, flags);
|
||||||
|
|
||||||
|
// Clear only dynamic managers, preserve default manager
|
||||||
|
clear_dynamic_manager();
|
||||||
|
|
||||||
|
// Clear file using the same method as save
|
||||||
|
clear_dynamic_sign_file();
|
||||||
|
|
||||||
|
pr_info("Dynamic sign config cleared (multi-manager disabled)\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
pr_err("Invalid dynamic sign operation: %d\n",
|
||||||
|
config->operation);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ksu_load_dynamic_sign(void)
|
bool ksu_load_dynamic_sign(void)
|
||||||
{
|
{
|
||||||
return ksu_queue_work(&ksu_load_dynamic_sign_work);
|
return ksu_queue_work(&ksu_load_dynamic_sign_work);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ksu_dynamic_sign_init(void)
|
void ksu_dynamic_sign_init(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
INIT_WORK(&ksu_save_dynamic_sign_work, do_save_dynamic_sign);
|
|
||||||
INIT_WORK(&ksu_load_dynamic_sign_work, do_load_dynamic_sign);
|
|
||||||
INIT_WORK(&ksu_clear_dynamic_sign_work, do_clear_dynamic_sign);
|
|
||||||
|
|
||||||
// Initialize manager slots
|
|
||||||
for (i = 0; i < MAX_MANAGERS; i++) {
|
|
||||||
active_managers[i].is_active = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ksu_load_dynamic_sign();
|
INIT_WORK(&ksu_save_dynamic_sign_work, do_save_dynamic_sign);
|
||||||
|
INIT_WORK(&ksu_load_dynamic_sign_work, do_load_dynamic_sign);
|
||||||
pr_info("Dynamic sign initialized with conditional multi-manager support\n");
|
INIT_WORK(&ksu_clear_dynamic_sign_work, do_clear_dynamic_sign);
|
||||||
|
|
||||||
|
// Initialize manager slots
|
||||||
|
for (i = 0; i < MAX_MANAGERS; i++) {
|
||||||
|
active_managers[i].is_active = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ksu_load_dynamic_sign();
|
||||||
|
|
||||||
|
pr_info("Dynamic sign initialized with conditional multi-manager support\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ksu_dynamic_sign_exit(void)
|
void ksu_dynamic_sign_exit(void)
|
||||||
{
|
{
|
||||||
clear_dynamic_manager();
|
clear_dynamic_manager();
|
||||||
|
|
||||||
// Save current config before exit
|
// Save current config before exit
|
||||||
do_save_dynamic_sign(NULL);
|
do_save_dynamic_sign(NULL);
|
||||||
pr_info("Dynamic sign exited with persistent storage\n");
|
pr_info("Dynamic sign exited with persistent storage\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get dynamic sign configuration for signature verification
|
// Get dynamic sign configuration for signature verification
|
||||||
bool ksu_get_dynamic_sign_config(unsigned int *size, const char **hash)
|
bool ksu_get_dynamic_sign_config(unsigned int *size, const char **hash)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
bool valid = false;
|
bool valid = false;
|
||||||
|
|
||||||
spin_lock_irqsave(&dynamic_sign_lock, flags);
|
spin_lock_irqsave(&dynamic_sign_lock, flags);
|
||||||
if (dynamic_sign.is_set) {
|
if (dynamic_sign.is_set) {
|
||||||
if (size) *size = dynamic_sign.size;
|
if (size)
|
||||||
if (hash) *hash = dynamic_sign.hash;
|
*size = dynamic_sign.size;
|
||||||
valid = true;
|
if (hash)
|
||||||
}
|
*hash = dynamic_sign.hash;
|
||||||
spin_unlock_irqrestore(&dynamic_sign_lock, flags);
|
valid = true;
|
||||||
|
}
|
||||||
return valid;
|
spin_unlock_irqrestore(&dynamic_sign_lock, flags);
|
||||||
|
|
||||||
|
return valid;
|
||||||
}
|
}
|
||||||
@@ -9,15 +9,15 @@
|
|||||||
#define KERNEL_SU_DYNAMIC_SIGN "/data/adb/ksu/.dynamic_sign"
|
#define KERNEL_SU_DYNAMIC_SIGN "/data/adb/ksu/.dynamic_sign"
|
||||||
|
|
||||||
struct dynamic_sign_config {
|
struct dynamic_sign_config {
|
||||||
unsigned int size;
|
unsigned int size;
|
||||||
char hash[65];
|
char hash[65];
|
||||||
int is_set;
|
int is_set;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct manager_info {
|
struct manager_info {
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
int signature_index;
|
int signature_index;
|
||||||
bool is_active;
|
bool is_active;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Dynamic sign operations
|
// Dynamic sign operations
|
||||||
|
|||||||
@@ -12,28 +12,28 @@
|
|||||||
#include <linux/cred.h>
|
#include <linux/cred.h>
|
||||||
#include <linux/version.h>
|
#include <linux/version.h>
|
||||||
|
|
||||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) && \
|
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) && \
|
||||||
defined(CONFIG_UIDGID_STRICT_TYPE_CHECKS)) || \
|
defined(CONFIG_UIDGID_STRICT_TYPE_CHECKS)) || \
|
||||||
LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
|
LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
|
||||||
#define ksu_cred_uid(x) ((x)->uid.val)
|
#define ksu_cred_uid(x) ((x)->uid.val)
|
||||||
#define ksu_cred_suid(x) ((x)->suid.val)
|
#define ksu_cred_suid(x) ((x)->suid.val)
|
||||||
#define ksu_cred_euid(x) ((x)->euid.val)
|
#define ksu_cred_euid(x) ((x)->euid.val)
|
||||||
#define ksu_cred_fsuid(x) ((x)->fsuid.val)
|
#define ksu_cred_fsuid(x) ((x)->fsuid.val)
|
||||||
#define ksu_cred_gid(x) ((x)->gid.val)
|
#define ksu_cred_gid(x) ((x)->gid.val)
|
||||||
#define ksu_cred_fsgid(x) ((x)->fsgid.val)
|
#define ksu_cred_fsgid(x) ((x)->fsgid.val)
|
||||||
#define ksu_cred_sgid(x) ((x)->sgid.val)
|
#define ksu_cred_sgid(x) ((x)->sgid.val)
|
||||||
#define ksu_cred_egid(x) ((x)->egid.val)
|
#define ksu_cred_egid(x) ((x)->egid.val)
|
||||||
#define ksu_current_uid() (current_uid().val)
|
#define ksu_current_uid() (current_uid().val)
|
||||||
#else
|
#else
|
||||||
#define ksu_cred_uid(x) ((x)->uid)
|
#define ksu_cred_uid(x) ((x)->uid)
|
||||||
#define ksu_cred_suid(x) ((x)->suid)
|
#define ksu_cred_suid(x) ((x)->suid)
|
||||||
#define ksu_cred_euid(x) ((x)->euid)
|
#define ksu_cred_euid(x) ((x)->euid)
|
||||||
#define ksu_cred_fsuid(x) ((x)->fsuid)
|
#define ksu_cred_fsuid(x) ((x)->fsuid)
|
||||||
#define ksu_cred_gid(x) ((x)->gid)
|
#define ksu_cred_gid(x) ((x)->gid)
|
||||||
#define ksu_cred_fsgid(x) ((x)->fsgid)
|
#define ksu_cred_fsgid(x) ((x)->fsgid)
|
||||||
#define ksu_cred_sgid(x) ((x)->sgid)
|
#define ksu_cred_sgid(x) ((x)->sgid)
|
||||||
#define ksu_cred_egid(x) ((x)->egid)
|
#define ksu_cred_egid(x) ((x)->egid)
|
||||||
#define ksu_current_uid() (current_uid())
|
#define ksu_current_uid() (current_uid())
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ int ksu_handle_execveat(int *fd, struct filename **filename_ptr, void *argv,
|
|||||||
void *envp, int *flags);
|
void *envp, int *flags);
|
||||||
|
|
||||||
// For volume button
|
// For volume button
|
||||||
int ksu_handle_input_handle_event(unsigned int *type, unsigned int *code,
|
int ksu_handle_input_handle_event(unsigned int *type, unsigned int *code,
|
||||||
int *value);
|
int *value);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -10,9 +10,8 @@
|
|||||||
#include "klog.h" // IWYU pragma: keep
|
#include "klog.h" // IWYU pragma: keep
|
||||||
#include "kernel_compat.h" // Add check Huawei Device
|
#include "kernel_compat.h" // Add check Huawei Device
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || \
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || \
|
||||||
defined(CONFIG_IS_HW_HISI) || \
|
defined(CONFIG_IS_HW_HISI) || defined(CONFIG_KSU_ALLOWLIST_WORKAROUND)
|
||||||
defined(CONFIG_KSU_ALLOWLIST_WORKAROUND)
|
|
||||||
#include <linux/key.h>
|
#include <linux/key.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/cred.h>
|
#include <linux/cred.h>
|
||||||
@@ -81,9 +80,8 @@ void ksu_android_ns_fs_check()
|
|||||||
|
|
||||||
struct file *ksu_filp_open_compat(const char *filename, int flags, umode_t mode)
|
struct file *ksu_filp_open_compat(const char *filename, int flags, umode_t mode)
|
||||||
{
|
{
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || \
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || \
|
||||||
defined(CONFIG_IS_HW_HISI) || \
|
defined(CONFIG_IS_HW_HISI) || defined(CONFIG_KSU_ALLOWLIST_WORKAROUND)
|
||||||
defined(CONFIG_KSU_ALLOWLIST_WORKAROUND)
|
|
||||||
if (init_session_keyring != NULL && !current_cred()->session_keyring &&
|
if (init_session_keyring != NULL && !current_cred()->session_keyring &&
|
||||||
(current->flags & PF_WQ_WORKER)) {
|
(current->flags & PF_WQ_WORKER)) {
|
||||||
pr_info("installing init session keyring for older kernel\n");
|
pr_info("installing init session keyring for older kernel\n");
|
||||||
@@ -112,7 +110,8 @@ struct file *ksu_filp_open_compat(const char *filename, int flags, umode_t mode)
|
|||||||
ssize_t ksu_kernel_read_compat(struct file *p, void *buf, size_t count,
|
ssize_t ksu_kernel_read_compat(struct file *p, void *buf, size_t count,
|
||||||
loff_t *pos)
|
loff_t *pos)
|
||||||
{
|
{
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) || defined(KSU_OPTIONAL_KERNEL_READ)
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) || \
|
||||||
|
defined(KSU_OPTIONAL_KERNEL_READ)
|
||||||
return kernel_read(p, buf, count, pos);
|
return kernel_read(p, buf, count, pos);
|
||||||
#else
|
#else
|
||||||
loff_t offset = pos ? *pos : 0;
|
loff_t offset = pos ? *pos : 0;
|
||||||
@@ -127,7 +126,8 @@ ssize_t ksu_kernel_read_compat(struct file *p, void *buf, size_t count,
|
|||||||
ssize_t ksu_kernel_write_compat(struct file *p, const void *buf, size_t count,
|
ssize_t ksu_kernel_write_compat(struct file *p, const void *buf, size_t count,
|
||||||
loff_t *pos)
|
loff_t *pos)
|
||||||
{
|
{
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) || defined(KSU_OPTIONAL_KERNEL_WRITE)
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) || \
|
||||||
|
defined(KSU_OPTIONAL_KERNEL_WRITE)
|
||||||
return kernel_write(p, buf, count, pos);
|
return kernel_write(p, buf, count, pos);
|
||||||
#else
|
#else
|
||||||
loff_t offset = pos ? *pos : 0;
|
loff_t offset = pos ? *pos : 0;
|
||||||
@@ -139,7 +139,8 @@ ssize_t ksu_kernel_write_compat(struct file *p, const void *buf, size_t count,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) || defined(KSU_OPTIONAL_STRNCPY)
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) || \
|
||||||
|
defined(KSU_OPTIONAL_STRNCPY)
|
||||||
long ksu_strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr,
|
long ksu_strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr,
|
||||||
long count)
|
long count)
|
||||||
{
|
{
|
||||||
@@ -180,7 +181,7 @@ long ksu_strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
long ksu_strncpy_from_user_retry(char *dst, const void __user *unsafe_addr,
|
long ksu_strncpy_from_user_retry(char *dst, const void __user *unsafe_addr,
|
||||||
long count)
|
long count)
|
||||||
{
|
{
|
||||||
long ret;
|
long ret;
|
||||||
|
|
||||||
|
|||||||
@@ -12,9 +12,9 @@
|
|||||||
* Huawei Hisi Kernel EBITMAP Enable or Disable Flag ,
|
* Huawei Hisi Kernel EBITMAP Enable or Disable Flag ,
|
||||||
* From ss/ebitmap.h
|
* From ss/ebitmap.h
|
||||||
*/
|
*/
|
||||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) && \
|
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) && \
|
||||||
(LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) || \
|
(LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) || \
|
||||||
(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) && \
|
(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) && \
|
||||||
(LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0))
|
(LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0))
|
||||||
#ifdef HISI_SELINUX_EBITMAP_RO
|
#ifdef HISI_SELINUX_EBITMAP_RO
|
||||||
#define CONFIG_IS_HW_HISI
|
#define CONFIG_IS_HW_HISI
|
||||||
@@ -32,12 +32,11 @@ extern long ksu_strncpy_from_user_nofault(char *dst,
|
|||||||
const void __user *unsafe_addr,
|
const void __user *unsafe_addr,
|
||||||
long count);
|
long count);
|
||||||
extern long ksu_strncpy_from_user_retry(char *dst,
|
extern long ksu_strncpy_from_user_retry(char *dst,
|
||||||
const void __user *unsafe_addr,
|
const void __user *unsafe_addr,
|
||||||
long count);
|
long count);
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || \
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || \
|
||||||
defined(CONFIG_IS_HW_HISI) || \
|
defined(CONFIG_IS_HW_HISI) || defined(CONFIG_KSU_ALLOWLIST_WORKAROUND)
|
||||||
defined(CONFIG_KSU_ALLOWLIST_WORKAROUND)
|
|
||||||
extern struct key *init_session_keyring;
|
extern struct key *init_session_keyring;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -50,9 +49,9 @@ extern ssize_t ksu_kernel_write_compat(struct file *p, const void *buf,
|
|||||||
size_t count, loff_t *pos);
|
size_t count, loff_t *pos);
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
|
||||||
#define ksu_access_ok(addr, size) access_ok(addr, size)
|
#define ksu_access_ok(addr, size) access_ok(addr, size)
|
||||||
#else
|
#else
|
||||||
#define ksu_access_ok(addr, size) access_ok(VERIFY_READ, addr, size)
|
#define ksu_access_ok(addr, size) access_ok(VERIFY_READ, addr, size)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/rcupdate.h>
|
#include <linux/rcupdate.h>
|
||||||
#include <asm/elf.h> /* 包含 ARM64 重定位类型定义 */
|
#include <asm/elf.h> /* 包含 ARM64 重定位类型定义 */
|
||||||
#include <linux/vmalloc.h>
|
#include <linux/vmalloc.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
@@ -29,74 +29,77 @@
|
|||||||
#include "../allowlist.h"
|
#include "../allowlist.h"
|
||||||
#include "../manager.h"
|
#include "../manager.h"
|
||||||
|
|
||||||
unsigned long sukisu_compact_find_symbol(const char* name);
|
unsigned long sukisu_compact_find_symbol(const char *name);
|
||||||
|
|
||||||
// ======================================================================
|
// ======================================================================
|
||||||
// 兼容函数 for KPM
|
// 兼容函数 for KPM
|
||||||
|
|
||||||
static
|
static int sukisu_is_su_allow_uid(uid_t uid)
|
||||||
int sukisu_is_su_allow_uid(uid_t uid) {
|
{
|
||||||
return ksu_is_allow_uid(uid) ? 1 : 0;
|
return ksu_is_allow_uid(uid) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static int sukisu_get_ap_mod_exclude(uid_t uid)
|
||||||
int sukisu_get_ap_mod_exclude(uid_t uid) {
|
{
|
||||||
// Not supported
|
// Not supported
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static int sukisu_is_uid_should_umount(uid_t uid)
|
||||||
int sukisu_is_uid_should_umount(uid_t uid) {
|
{
|
||||||
return ksu_uid_should_umount(uid) ? 1 : 0;
|
return ksu_uid_should_umount(uid) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static int sukisu_is_current_uid_manager()
|
||||||
int sukisu_is_current_uid_manager() {
|
{
|
||||||
return is_manager();
|
return is_manager();
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static uid_t sukisu_get_manager_uid()
|
||||||
uid_t sukisu_get_manager_uid() {
|
{
|
||||||
return ksu_manager_uid;
|
return ksu_manager_uid;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ======================================================================
|
// ======================================================================
|
||||||
|
|
||||||
struct CompactAddressSymbol {
|
struct CompactAddressSymbol {
|
||||||
const char* symbol_name;
|
const char *symbol_name;
|
||||||
void* addr;
|
void *addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct CompactAddressSymbol address_symbol [] = {
|
static struct CompactAddressSymbol address_symbol[] = {
|
||||||
{ "kallsyms_lookup_name", &kallsyms_lookup_name },
|
{ "kallsyms_lookup_name", &kallsyms_lookup_name },
|
||||||
{ "compact_find_symbol", &sukisu_compact_find_symbol },
|
{ "compact_find_symbol", &sukisu_compact_find_symbol },
|
||||||
{ "is_run_in_sukisu_ultra", (void*)1 },
|
{ "is_run_in_sukisu_ultra", (void *)1 },
|
||||||
{ "is_su_allow_uid", &sukisu_is_su_allow_uid },
|
{ "is_su_allow_uid", &sukisu_is_su_allow_uid },
|
||||||
{ "get_ap_mod_exclude", &sukisu_get_ap_mod_exclude },
|
{ "get_ap_mod_exclude", &sukisu_get_ap_mod_exclude },
|
||||||
{ "is_uid_should_umount", &sukisu_is_uid_should_umount },
|
{ "is_uid_should_umount", &sukisu_is_uid_should_umount },
|
||||||
{ "is_current_uid_manager", &sukisu_is_current_uid_manager },
|
{ "is_current_uid_manager", &sukisu_is_current_uid_manager },
|
||||||
{ "get_manager_uid", &sukisu_get_manager_uid }
|
{ "get_manager_uid", &sukisu_get_manager_uid }
|
||||||
};
|
};
|
||||||
|
|
||||||
unsigned long sukisu_compact_find_symbol(const char* name) {
|
unsigned long sukisu_compact_find_symbol(const char *name)
|
||||||
int i;
|
{
|
||||||
unsigned long addr;
|
int i;
|
||||||
|
unsigned long addr;
|
||||||
|
|
||||||
// 先自己在地址表部分查出来
|
// 先自己在地址表部分查出来
|
||||||
for(i = 0; i < (sizeof(address_symbol) / sizeof(struct CompactAddressSymbol)); i++) {
|
for (i = 0;
|
||||||
struct CompactAddressSymbol* symbol = &address_symbol[i];
|
i < (sizeof(address_symbol) / sizeof(struct CompactAddressSymbol));
|
||||||
if(strcmp(name, symbol->symbol_name) == 0) {
|
i++) {
|
||||||
return (unsigned long) symbol->addr;
|
struct CompactAddressSymbol *symbol = &address_symbol[i];
|
||||||
}
|
if (strcmp(name, symbol->symbol_name) == 0) {
|
||||||
}
|
return (unsigned long)symbol->addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 通过内核来查
|
// 通过内核来查
|
||||||
addr = kallsyms_lookup_name(name);
|
addr = kallsyms_lookup_name(name);
|
||||||
if(addr) {
|
if (addr) {
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(sukisu_compact_find_symbol);
|
EXPORT_SYMBOL(sukisu_compact_find_symbol);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#ifndef ___SUKISU_KPM_COMPACT_H
|
#ifndef ___SUKISU_KPM_COMPACT_H
|
||||||
#define ___SUKISU_KPM_COMPACT_H
|
#define ___SUKISU_KPM_COMPACT_H
|
||||||
|
|
||||||
unsigned long sukisu_compact_find_symbol(const char* name);
|
unsigned long sukisu_compact_find_symbol(const char *name);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
227
kernel/kpm/kpm.c
227
kernel/kpm/kpm.c
@@ -23,7 +23,7 @@
|
|||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/rcupdate.h>
|
#include <linux/rcupdate.h>
|
||||||
#include <asm/elf.h> /* 包含 ARM64 重定位类型定义 */
|
#include <asm/elf.h> /* 包含 ARM64 重定位类型定义 */
|
||||||
#include <linux/vmalloc.h>
|
#include <linux/vmalloc.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
#include <linux/kprobes.h>
|
#include <linux/kprobes.h>
|
||||||
#include <linux/stacktrace.h>
|
#include <linux/stacktrace.h>
|
||||||
#include <linux/kallsyms.h>
|
#include <linux/kallsyms.h>
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0) && defined(CONFIG_MODULES)
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) && defined(CONFIG_MODULES)
|
||||||
#include <linux/moduleloader.h> // 需要启用 CONFIG_MODULES
|
#include <linux/moduleloader.h> // 需要启用 CONFIG_MODULES
|
||||||
#endif
|
#endif
|
||||||
#include "kpm.h"
|
#include "kpm.h"
|
||||||
@@ -46,81 +46,96 @@
|
|||||||
|
|
||||||
#ifndef NO_OPTIMIZE
|
#ifndef NO_OPTIMIZE
|
||||||
#if defined(__GNUC__) && !defined(__clang__)
|
#if defined(__GNUC__) && !defined(__clang__)
|
||||||
#define NO_OPTIMIZE __attribute__((optimize("O0")))
|
#define NO_OPTIMIZE __attribute__((optimize("O0")))
|
||||||
#elif defined(__clang__)
|
#elif defined(__clang__)
|
||||||
#define NO_OPTIMIZE __attribute__((optnone))
|
#define NO_OPTIMIZE __attribute__((optnone))
|
||||||
#else
|
#else
|
||||||
#define NO_OPTIMIZE
|
#define NO_OPTIMIZE
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// ============================================================================================
|
// ============================================================================================
|
||||||
|
|
||||||
noinline
|
noinline NO_OPTIMIZE void sukisu_kpm_load_module_path(const char *path,
|
||||||
NO_OPTIMIZE
|
const char *args,
|
||||||
void sukisu_kpm_load_module_path(const char* path, const char* args, void* ptr, void __user* result) {
|
void *ptr,
|
||||||
// This is a KPM module stub.
|
void __user *result)
|
||||||
int res = -1;
|
{
|
||||||
printk("KPM: Stub function called (sukisu_kpm_load_module_path). path=%s args=%s ptr=%p\n", path, args, ptr);
|
// This is a KPM module stub.
|
||||||
__asm__ volatile("nop"); // 精确控制循环不被优化
|
int res = -1;
|
||||||
if(copy_to_user(result, &res, sizeof(res)) < 1) printk("KPM: Copy to user failed.");
|
printk("KPM: Stub function called (sukisu_kpm_load_module_path). path=%s args=%s ptr=%p\n",
|
||||||
|
path, args, ptr);
|
||||||
|
__asm__ volatile("nop"); // 精确控制循环不被优化
|
||||||
|
if (copy_to_user(result, &res, sizeof(res)) < 1)
|
||||||
|
printk("KPM: Copy to user failed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
noinline
|
noinline NO_OPTIMIZE void sukisu_kpm_unload_module(const char *name, void *ptr,
|
||||||
NO_OPTIMIZE
|
void __user *result)
|
||||||
void sukisu_kpm_unload_module(const char* name, void* ptr, void __user* result) {
|
{
|
||||||
// This is a KPM module stub.
|
// This is a KPM module stub.
|
||||||
int res = -1;
|
int res = -1;
|
||||||
printk("KPM: Stub function called (sukisu_kpm_unload_module). name=%s ptr=%p\n", name, ptr);
|
printk("KPM: Stub function called (sukisu_kpm_unload_module). name=%s ptr=%p\n",
|
||||||
__asm__ volatile("nop"); // 精确控制循环不被优化
|
name, ptr);
|
||||||
if(copy_to_user(result, &res, sizeof(res)) < 1) printk("KPM: Copy to user failed.");
|
__asm__ volatile("nop"); // 精确控制循环不被优化
|
||||||
|
if (copy_to_user(result, &res, sizeof(res)) < 1)
|
||||||
|
printk("KPM: Copy to user failed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
noinline
|
noinline NO_OPTIMIZE void sukisu_kpm_num(void __user *result)
|
||||||
NO_OPTIMIZE
|
{
|
||||||
void sukisu_kpm_num(void __user* result) {
|
// This is a KPM module stub.
|
||||||
// This is a KPM module stub.
|
int res = 0;
|
||||||
int res = 0;
|
printk("KPM: Stub function called (sukisu_kpm_num).\n");
|
||||||
printk("KPM: Stub function called (sukisu_kpm_num).\n");
|
__asm__ volatile("nop"); // 精确控制循环不被优化
|
||||||
__asm__ volatile("nop"); // 精确控制循环不被优化
|
if (copy_to_user(result, &res, sizeof(res)) < 1)
|
||||||
if(copy_to_user(result, &res, sizeof(res)) < 1) printk("KPM: Copy to user failed.");
|
printk("KPM: Copy to user failed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
noinline
|
noinline NO_OPTIMIZE void sukisu_kpm_info(const char *name, void __user *out,
|
||||||
NO_OPTIMIZE
|
void __user *result)
|
||||||
void sukisu_kpm_info(const char* name, void __user* out, void __user* result) {
|
{
|
||||||
// This is a KPM module stub.
|
// This is a KPM module stub.
|
||||||
int res = -1;
|
int res = -1;
|
||||||
printk("KPM: Stub function called (sukisu_kpm_info). name=%s buffer=%p\n", name, out);
|
printk("KPM: Stub function called (sukisu_kpm_info). name=%s buffer=%p\n",
|
||||||
__asm__ volatile("nop"); // 精确控制循环不被优化
|
name, out);
|
||||||
if(copy_to_user(result, &res, sizeof(res)) < 1) printk("KPM: Copy to user failed.");
|
__asm__ volatile("nop"); // 精确控制循环不被优化
|
||||||
|
if (copy_to_user(result, &res, sizeof(res)) < 1)
|
||||||
|
printk("KPM: Copy to user failed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
noinline
|
noinline NO_OPTIMIZE void
|
||||||
NO_OPTIMIZE
|
sukisu_kpm_list(void __user *out, unsigned int bufferSize, void __user *result)
|
||||||
void sukisu_kpm_list(void __user* out, unsigned int bufferSize, void __user* result) {
|
{
|
||||||
// This is a KPM module stub.
|
// This is a KPM module stub.
|
||||||
int res = -1;
|
int res = -1;
|
||||||
printk("KPM: Stub function called (sukisu_kpm_list). buffer=%p size=%d\n", out, bufferSize);
|
printk("KPM: Stub function called (sukisu_kpm_list). buffer=%p size=%d\n",
|
||||||
if(copy_to_user(result, &res, sizeof(res)) < 1) printk("KPM: Copy to user failed.");
|
out, bufferSize);
|
||||||
|
if (copy_to_user(result, &res, sizeof(res)) < 1)
|
||||||
|
printk("KPM: Copy to user failed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
noinline
|
noinline NO_OPTIMIZE void
|
||||||
NO_OPTIMIZE
|
sukisu_kpm_control(void __user *name, void __user *args, void __user *result)
|
||||||
void sukisu_kpm_control(void __user* name, void __user* args, void __user* result) {
|
{
|
||||||
// This is a KPM module stub.
|
// This is a KPM module stub.
|
||||||
int res = -1;
|
int res = -1;
|
||||||
printk("KPM: Stub function called (sukisu_kpm_control). name=%p args=%p\n", name, args);
|
printk("KPM: Stub function called (sukisu_kpm_control). name=%p args=%p\n",
|
||||||
__asm__ volatile("nop"); // 精确控制循环不被优化
|
name, args);
|
||||||
if(copy_to_user(result, &res, sizeof(res)) < 1) printk("KPM: Copy to user failed.");
|
__asm__ volatile("nop"); // 精确控制循环不被优化
|
||||||
|
if (copy_to_user(result, &res, sizeof(res)) < 1)
|
||||||
|
printk("KPM: Copy to user failed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
noinline
|
noinline NO_OPTIMIZE void sukisu_kpm_version(void __user *out,
|
||||||
NO_OPTIMIZE
|
unsigned int bufferSize,
|
||||||
void sukisu_kpm_version(void __user* out, unsigned int bufferSize, void __user* result) {
|
void __user *result)
|
||||||
int res = -1;
|
{
|
||||||
printk("KPM: Stub function called (sukisu_kpm_version). buffer=%p size=%d\n", out, bufferSize);
|
int res = -1;
|
||||||
if(copy_to_user(result, &res, sizeof(res)) < 1) printk("KPM: Copy to user failed.");
|
printk("KPM: Stub function called (sukisu_kpm_version). buffer=%p size=%d\n",
|
||||||
|
out, bufferSize);
|
||||||
|
if (copy_to_user(result, &res, sizeof(res)) < 1)
|
||||||
|
printk("KPM: Copy to user failed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(sukisu_kpm_load_module_path);
|
EXPORT_SYMBOL(sukisu_kpm_load_module_path);
|
||||||
@@ -131,54 +146,66 @@ EXPORT_SYMBOL(sukisu_kpm_list);
|
|||||||
EXPORT_SYMBOL(sukisu_kpm_version);
|
EXPORT_SYMBOL(sukisu_kpm_version);
|
||||||
EXPORT_SYMBOL(sukisu_kpm_control);
|
EXPORT_SYMBOL(sukisu_kpm_control);
|
||||||
|
|
||||||
noinline
|
noinline int sukisu_handle_kpm(unsigned long arg2, unsigned long arg3,
|
||||||
int sukisu_handle_kpm(unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5)
|
unsigned long arg4, unsigned long arg5)
|
||||||
{
|
{
|
||||||
if(arg2 == SUKISU_KPM_LOAD) {
|
if (arg2 == SUKISU_KPM_LOAD) {
|
||||||
char kernel_load_path[256] = { 0 };
|
char kernel_load_path[256] = { 0 };
|
||||||
char kernel_args_buffer[256] = { 0 };
|
char kernel_args_buffer[256] = { 0 };
|
||||||
|
|
||||||
if(arg3 == 0) {
|
if (arg3 == 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
strncpy_from_user((char*)&kernel_load_path, (const char __user *)arg3, 255);
|
|
||||||
if(arg4 != 0) {
|
|
||||||
strncpy_from_user((char*)&kernel_args_buffer, (const char __user *)arg4, 255);
|
|
||||||
}
|
|
||||||
sukisu_kpm_load_module_path((const char*)&kernel_load_path, (const char*) &kernel_args_buffer, NULL, (void __user*) arg5);
|
|
||||||
} else if(arg2 == SUKISU_KPM_UNLOAD) {
|
|
||||||
char kernel_name_buffer[256] = { 0 };
|
|
||||||
|
|
||||||
if(arg3 == 0) {
|
strncpy_from_user((char *)&kernel_load_path,
|
||||||
return -1;
|
(const char __user *)arg3, 255);
|
||||||
}
|
if (arg4 != 0) {
|
||||||
|
strncpy_from_user((char *)&kernel_args_buffer,
|
||||||
strncpy_from_user((char*)&kernel_name_buffer, (const char __user *)arg3, 255);
|
(const char __user *)arg4, 255);
|
||||||
sukisu_kpm_unload_module((const char*) &kernel_name_buffer, NULL, (void __user*) arg5);
|
}
|
||||||
} else if(arg2 == SUKISU_KPM_NUM) {
|
sukisu_kpm_load_module_path((const char *)&kernel_load_path,
|
||||||
sukisu_kpm_num((void __user*) arg5);
|
(const char *)&kernel_args_buffer,
|
||||||
} else if(arg2 == SUKISU_KPM_INFO) {
|
NULL, (void __user *)arg5);
|
||||||
char kernel_name_buffer[256] = { 0 };
|
} else if (arg2 == SUKISU_KPM_UNLOAD) {
|
||||||
|
char kernel_name_buffer[256] = { 0 };
|
||||||
|
|
||||||
if(arg3 == 0 || arg4 == 0) {
|
if (arg3 == 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
strncpy_from_user((char*)&kernel_name_buffer, (const char __user *)arg3, 255);
|
strncpy_from_user((char *)&kernel_name_buffer,
|
||||||
sukisu_kpm_info((const char*) &kernel_name_buffer, (char __user*) arg4, (void __user*) arg5);
|
(const char __user *)arg3, 255);
|
||||||
} else if(arg2 == SUKISU_KPM_LIST) {
|
sukisu_kpm_unload_module((const char *)&kernel_name_buffer,
|
||||||
sukisu_kpm_list((char __user*) arg3, (unsigned int) arg4, (void __user*) arg5);
|
NULL, (void __user *)arg5);
|
||||||
} else if(arg2 == SUKISU_KPM_VERSION) {
|
} else if (arg2 == SUKISU_KPM_NUM) {
|
||||||
sukisu_kpm_version((char __user*) arg3, (unsigned int) arg4, (void __user*) arg5);
|
sukisu_kpm_num((void __user *)arg5);
|
||||||
} else if(arg2 == SUKISU_KPM_CONTROL) {
|
} else if (arg2 == SUKISU_KPM_INFO) {
|
||||||
sukisu_kpm_control((char __user*) arg3, (char __user*) arg4, (void __user*) arg5);
|
char kernel_name_buffer[256] = { 0 };
|
||||||
}
|
|
||||||
return 0;
|
if (arg3 == 0 || arg4 == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy_from_user((char *)&kernel_name_buffer,
|
||||||
|
(const char __user *)arg3, 255);
|
||||||
|
sukisu_kpm_info((const char *)&kernel_name_buffer,
|
||||||
|
(char __user *)arg4, (void __user *)arg5);
|
||||||
|
} else if (arg2 == SUKISU_KPM_LIST) {
|
||||||
|
sukisu_kpm_list((char __user *)arg3, (unsigned int)arg4,
|
||||||
|
(void __user *)arg5);
|
||||||
|
} else if (arg2 == SUKISU_KPM_VERSION) {
|
||||||
|
sukisu_kpm_version((char __user *)arg3, (unsigned int)arg4,
|
||||||
|
(void __user *)arg5);
|
||||||
|
} else if (arg2 == SUKISU_KPM_CONTROL) {
|
||||||
|
sukisu_kpm_control((char __user *)arg3, (char __user *)arg4,
|
||||||
|
(void __user *)arg5);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sukisu_is_kpm_control_code(unsigned long arg2) {
|
int sukisu_is_kpm_control_code(unsigned long arg2)
|
||||||
return (arg2 >= CMD_KPM_CONTROL && arg2 <= CMD_KPM_CONTROL_MAX) ? 1 : 0;
|
{
|
||||||
|
return (arg2 >= CMD_KPM_CONTROL && arg2 <= CMD_KPM_CONTROL_MAX) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(sukisu_handle_kpm);
|
EXPORT_SYMBOL(sukisu_handle_kpm);
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
#ifndef ___SUKISU_KPM_H
|
#ifndef ___SUKISU_KPM_H
|
||||||
#define ___SUKISU_KPM_H
|
#define ___SUKISU_KPM_H
|
||||||
|
|
||||||
int sukisu_handle_kpm(unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5);
|
int sukisu_handle_kpm(unsigned long arg2, unsigned long arg3,
|
||||||
|
unsigned long arg4, unsigned long arg5);
|
||||||
int sukisu_is_kpm_control_code(unsigned long arg2);
|
int sukisu_is_kpm_control_code(unsigned long arg2);
|
||||||
|
|
||||||
// KPM控制代码
|
// KPM控制代码
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/rcupdate.h>
|
#include <linux/rcupdate.h>
|
||||||
#include <asm/elf.h> /* 包含 ARM64 重定位类型定义 */
|
#include <asm/elf.h> /* 包含 ARM64 重定位类型定义 */
|
||||||
#include <linux/vmalloc.h>
|
#include <linux/vmalloc.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
@@ -31,38 +31,37 @@
|
|||||||
|
|
||||||
// 结构体成员元数据
|
// 结构体成员元数据
|
||||||
struct DynamicStructMember {
|
struct DynamicStructMember {
|
||||||
const char* name;
|
const char *name;
|
||||||
size_t size;
|
size_t size;
|
||||||
size_t offset;
|
size_t offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 结构体元数据(包含总大小)
|
// 结构体元数据(包含总大小)
|
||||||
struct DynamicStructInfo {
|
struct DynamicStructInfo {
|
||||||
const char* name;
|
const char *name;
|
||||||
size_t count;
|
size_t count;
|
||||||
size_t total_size;
|
size_t total_size;
|
||||||
struct DynamicStructMember* members;
|
struct DynamicStructMember *members;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 定义结构体元数据的宏(直接使用 struct 名称)
|
// 定义结构体元数据的宏(直接使用 struct 名称)
|
||||||
#define DYNAMIC_STRUCT_BEGIN(struct_name) \
|
#define DYNAMIC_STRUCT_BEGIN(struct_name) \
|
||||||
static struct DynamicStructMember struct_name##_members[] = {
|
static struct DynamicStructMember struct_name##_members[] = {
|
||||||
|
#define DEFINE_MEMBER(struct_name, member) \
|
||||||
|
{ .name = #member, \
|
||||||
|
.size = sizeof(((struct struct_name *)0)->member), \
|
||||||
|
.offset = offsetof(struct struct_name, member) },
|
||||||
|
|
||||||
#define DEFINE_MEMBER(struct_name, member) \
|
#define DYNAMIC_STRUCT_END(struct_name) \
|
||||||
{ \
|
} \
|
||||||
.name = #member, \
|
; \
|
||||||
.size = sizeof(((struct struct_name*)0)->member), \
|
static struct DynamicStructInfo struct_name##_info = { \
|
||||||
.offset = offsetof(struct struct_name, member) \
|
.name = #struct_name, \
|
||||||
},
|
.count = sizeof(struct_name##_members) / \
|
||||||
|
sizeof(struct DynamicStructMember), \
|
||||||
#define DYNAMIC_STRUCT_END(struct_name) \
|
.total_size = sizeof(struct struct_name), \
|
||||||
}; \
|
.members = struct_name##_members \
|
||||||
static struct DynamicStructInfo struct_name##_info = { \
|
};
|
||||||
.name = #struct_name, \
|
|
||||||
.count = sizeof(struct_name##_members) / sizeof(struct DynamicStructMember), \
|
|
||||||
.total_size = sizeof(struct struct_name), \
|
|
||||||
.members = struct_name##_members \
|
|
||||||
};
|
|
||||||
|
|
||||||
// ==================================================================================
|
// ==================================================================================
|
||||||
|
|
||||||
@@ -76,28 +75,28 @@ struct DynamicStructInfo {
|
|||||||
|
|
||||||
// 定义元数据
|
// 定义元数据
|
||||||
DYNAMIC_STRUCT_BEGIN(mount)
|
DYNAMIC_STRUCT_BEGIN(mount)
|
||||||
DEFINE_MEMBER(mount, mnt_parent)
|
DEFINE_MEMBER(mount, mnt_parent)
|
||||||
DEFINE_MEMBER(mount, mnt)
|
DEFINE_MEMBER(mount, mnt)
|
||||||
DEFINE_MEMBER(mount, mnt_id)
|
DEFINE_MEMBER(mount, mnt_id)
|
||||||
DEFINE_MEMBER(mount, mnt_group_id)
|
DEFINE_MEMBER(mount, mnt_group_id)
|
||||||
DEFINE_MEMBER(mount, mnt_expiry_mark)
|
DEFINE_MEMBER(mount, mnt_expiry_mark)
|
||||||
DEFINE_MEMBER(mount, mnt_master)
|
DEFINE_MEMBER(mount, mnt_master)
|
||||||
DEFINE_MEMBER(mount, mnt_devname)
|
DEFINE_MEMBER(mount, mnt_devname)
|
||||||
DYNAMIC_STRUCT_END(mount)
|
DYNAMIC_STRUCT_END(mount)
|
||||||
|
|
||||||
DYNAMIC_STRUCT_BEGIN(vfsmount)
|
DYNAMIC_STRUCT_BEGIN(vfsmount)
|
||||||
DEFINE_MEMBER(vfsmount, mnt_root)
|
DEFINE_MEMBER(vfsmount, mnt_root)
|
||||||
DEFINE_MEMBER(vfsmount, mnt_sb)
|
DEFINE_MEMBER(vfsmount, mnt_sb)
|
||||||
DEFINE_MEMBER(vfsmount, mnt_flags)
|
DEFINE_MEMBER(vfsmount, mnt_flags)
|
||||||
DYNAMIC_STRUCT_END(vfsmount)
|
DYNAMIC_STRUCT_END(vfsmount)
|
||||||
|
|
||||||
DYNAMIC_STRUCT_BEGIN(mnt_namespace)
|
DYNAMIC_STRUCT_BEGIN(mnt_namespace)
|
||||||
DEFINE_MEMBER(mnt_namespace, ns)
|
DEFINE_MEMBER(mnt_namespace, ns)
|
||||||
DEFINE_MEMBER(mnt_namespace, root)
|
DEFINE_MEMBER(mnt_namespace, root)
|
||||||
DEFINE_MEMBER(mnt_namespace, seq)
|
DEFINE_MEMBER(mnt_namespace, seq)
|
||||||
DEFINE_MEMBER(mnt_namespace, mounts)
|
DEFINE_MEMBER(mnt_namespace, mounts)
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION_5_15
|
#if LINUX_VERSION_CODE < KERNEL_VERSION_5_15
|
||||||
DEFINE_MEMBER(mnt_namespace, count)
|
DEFINE_MEMBER(mnt_namespace, count)
|
||||||
#endif
|
#endif
|
||||||
DYNAMIC_STRUCT_END(mnt_namespace)
|
DYNAMIC_STRUCT_END(mnt_namespace)
|
||||||
|
|
||||||
@@ -105,15 +104,15 @@ DYNAMIC_STRUCT_END(mnt_namespace)
|
|||||||
|
|
||||||
#ifdef CONFIG_KPROBES
|
#ifdef CONFIG_KPROBES
|
||||||
DYNAMIC_STRUCT_BEGIN(kprobe)
|
DYNAMIC_STRUCT_BEGIN(kprobe)
|
||||||
DEFINE_MEMBER(kprobe, addr)
|
DEFINE_MEMBER(kprobe, addr)
|
||||||
DEFINE_MEMBER(kprobe, symbol_name)
|
DEFINE_MEMBER(kprobe, symbol_name)
|
||||||
DEFINE_MEMBER(kprobe, offset)
|
DEFINE_MEMBER(kprobe, offset)
|
||||||
DEFINE_MEMBER(kprobe, pre_handler)
|
DEFINE_MEMBER(kprobe, pre_handler)
|
||||||
DEFINE_MEMBER(kprobe, post_handler)
|
DEFINE_MEMBER(kprobe, post_handler)
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION_5_15
|
#if LINUX_VERSION_CODE < KERNEL_VERSION_5_15
|
||||||
DEFINE_MEMBER(kprobe, fault_handler)
|
DEFINE_MEMBER(kprobe, fault_handler)
|
||||||
#endif
|
#endif
|
||||||
DEFINE_MEMBER(kprobe, flags)
|
DEFINE_MEMBER(kprobe, flags)
|
||||||
DYNAMIC_STRUCT_END(kprobe)
|
DYNAMIC_STRUCT_END(kprobe)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -121,76 +120,75 @@ DYNAMIC_STRUCT_END(kprobe)
|
|||||||
#include <linux/mm_types.h>
|
#include <linux/mm_types.h>
|
||||||
|
|
||||||
DYNAMIC_STRUCT_BEGIN(vm_area_struct)
|
DYNAMIC_STRUCT_BEGIN(vm_area_struct)
|
||||||
DEFINE_MEMBER(vm_area_struct,vm_start)
|
DEFINE_MEMBER(vm_area_struct, vm_start)
|
||||||
DEFINE_MEMBER(vm_area_struct,vm_end)
|
DEFINE_MEMBER(vm_area_struct, vm_end)
|
||||||
DEFINE_MEMBER(vm_area_struct,vm_flags)
|
DEFINE_MEMBER(vm_area_struct, vm_flags)
|
||||||
DEFINE_MEMBER(vm_area_struct,anon_vma)
|
DEFINE_MEMBER(vm_area_struct, anon_vma)
|
||||||
DEFINE_MEMBER(vm_area_struct,vm_pgoff)
|
DEFINE_MEMBER(vm_area_struct, vm_pgoff)
|
||||||
DEFINE_MEMBER(vm_area_struct,vm_file)
|
DEFINE_MEMBER(vm_area_struct, vm_file)
|
||||||
DEFINE_MEMBER(vm_area_struct,vm_private_data)
|
DEFINE_MEMBER(vm_area_struct, vm_private_data)
|
||||||
#ifdef CONFIG_ANON_VMA_NAME
|
#ifdef CONFIG_ANON_VMA_NAME
|
||||||
DEFINE_MEMBER(vm_area_struct, anon_name)
|
DEFINE_MEMBER(vm_area_struct, anon_name)
|
||||||
#endif
|
#endif
|
||||||
DEFINE_MEMBER(vm_area_struct, vm_ops)
|
DEFINE_MEMBER(vm_area_struct, vm_ops)
|
||||||
DYNAMIC_STRUCT_END(vm_area_struct)
|
DYNAMIC_STRUCT_END(vm_area_struct)
|
||||||
|
|
||||||
DYNAMIC_STRUCT_BEGIN(vm_operations_struct)
|
DYNAMIC_STRUCT_BEGIN(vm_operations_struct)
|
||||||
DEFINE_MEMBER(vm_operations_struct, open)
|
DEFINE_MEMBER(vm_operations_struct, open)
|
||||||
DEFINE_MEMBER(vm_operations_struct, close)
|
DEFINE_MEMBER(vm_operations_struct, close)
|
||||||
DEFINE_MEMBER(vm_operations_struct, name)
|
DEFINE_MEMBER(vm_operations_struct, name)
|
||||||
DEFINE_MEMBER(vm_operations_struct, access)
|
DEFINE_MEMBER(vm_operations_struct, access)
|
||||||
DYNAMIC_STRUCT_END(vm_operations_struct)
|
DYNAMIC_STRUCT_END(vm_operations_struct)
|
||||||
|
|
||||||
#include <linux/netlink.h>
|
#include <linux/netlink.h>
|
||||||
|
|
||||||
DYNAMIC_STRUCT_BEGIN(netlink_kernel_cfg)
|
DYNAMIC_STRUCT_BEGIN(netlink_kernel_cfg)
|
||||||
DEFINE_MEMBER(netlink_kernel_cfg, groups)
|
DEFINE_MEMBER(netlink_kernel_cfg, groups)
|
||||||
DEFINE_MEMBER(netlink_kernel_cfg, flags)
|
DEFINE_MEMBER(netlink_kernel_cfg, flags)
|
||||||
DEFINE_MEMBER(netlink_kernel_cfg, input)
|
DEFINE_MEMBER(netlink_kernel_cfg, input)
|
||||||
DEFINE_MEMBER(netlink_kernel_cfg, cb_mutex)
|
DEFINE_MEMBER(netlink_kernel_cfg, cb_mutex)
|
||||||
DEFINE_MEMBER(netlink_kernel_cfg, bind)
|
DEFINE_MEMBER(netlink_kernel_cfg, bind)
|
||||||
DEFINE_MEMBER(netlink_kernel_cfg, unbind)
|
DEFINE_MEMBER(netlink_kernel_cfg, unbind)
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION_6_1
|
#if LINUX_VERSION_CODE < KERNEL_VERSION_6_1
|
||||||
DEFINE_MEMBER(netlink_kernel_cfg, compare)
|
DEFINE_MEMBER(netlink_kernel_cfg, compare)
|
||||||
#endif
|
#endif
|
||||||
DYNAMIC_STRUCT_END(netlink_kernel_cfg)
|
DYNAMIC_STRUCT_END(netlink_kernel_cfg)
|
||||||
|
|
||||||
|
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
DYNAMIC_STRUCT_BEGIN(task_struct)
|
DYNAMIC_STRUCT_BEGIN(task_struct)
|
||||||
DEFINE_MEMBER(task_struct, pid)
|
DEFINE_MEMBER(task_struct, pid)
|
||||||
DEFINE_MEMBER(task_struct, tgid)
|
DEFINE_MEMBER(task_struct, tgid)
|
||||||
DEFINE_MEMBER(task_struct, cred)
|
DEFINE_MEMBER(task_struct, cred)
|
||||||
DEFINE_MEMBER(task_struct, real_cred)
|
DEFINE_MEMBER(task_struct, real_cred)
|
||||||
DEFINE_MEMBER(task_struct, comm)
|
DEFINE_MEMBER(task_struct, comm)
|
||||||
DEFINE_MEMBER(task_struct, parent)
|
DEFINE_MEMBER(task_struct, parent)
|
||||||
DEFINE_MEMBER(task_struct, group_leader)
|
DEFINE_MEMBER(task_struct, group_leader)
|
||||||
DEFINE_MEMBER(task_struct, mm)
|
DEFINE_MEMBER(task_struct, mm)
|
||||||
DEFINE_MEMBER(task_struct, active_mm)
|
DEFINE_MEMBER(task_struct, active_mm)
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)
|
||||||
DEFINE_MEMBER(task_struct, pids[PIDTYPE_PID].pid)
|
DEFINE_MEMBER(task_struct, pids[PIDTYPE_PID].pid)
|
||||||
#else
|
#else
|
||||||
DEFINE_MEMBER(task_struct, thread_pid)
|
DEFINE_MEMBER(task_struct, thread_pid)
|
||||||
#endif
|
#endif
|
||||||
DEFINE_MEMBER(task_struct, files)
|
DEFINE_MEMBER(task_struct, files)
|
||||||
DEFINE_MEMBER(task_struct, seccomp)
|
DEFINE_MEMBER(task_struct, seccomp)
|
||||||
#ifdef CONFIG_THREAD_INFO_IN_TASK
|
#ifdef CONFIG_THREAD_INFO_IN_TASK
|
||||||
DEFINE_MEMBER(task_struct, thread_info)
|
DEFINE_MEMBER(task_struct, thread_info)
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_CGROUPS
|
#ifdef CONFIG_CGROUPS
|
||||||
DEFINE_MEMBER(task_struct, cgroups)
|
DEFINE_MEMBER(task_struct, cgroups)
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_SECURITY
|
#ifdef CONFIG_SECURITY
|
||||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
|
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
|
||||||
DEFINE_MEMBER(task_struct, security)
|
DEFINE_MEMBER(task_struct, security)
|
||||||
#else
|
#else
|
||||||
DEFINE_MEMBER(task_struct, cred)
|
DEFINE_MEMBER(task_struct, cred)
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
|
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
|
||||||
DEFINE_MEMBER(task_struct, thread)
|
DEFINE_MEMBER(task_struct, thread)
|
||||||
#else
|
#else
|
||||||
DEFINE_MEMBER(task_struct, thread_info)
|
DEFINE_MEMBER(task_struct, thread_info)
|
||||||
#endif
|
#endif
|
||||||
DYNAMIC_STRUCT_END(task_struct)
|
DYNAMIC_STRUCT_END(task_struct)
|
||||||
|
|
||||||
@@ -198,38 +196,37 @@ DYNAMIC_STRUCT_END(task_struct)
|
|||||||
|
|
||||||
#define STRUCT_INFO(name) &(name##_info)
|
#define STRUCT_INFO(name) &(name##_info)
|
||||||
|
|
||||||
static
|
static struct DynamicStructInfo *dynamic_struct_infos[] = {
|
||||||
struct DynamicStructInfo* dynamic_struct_infos[] = {
|
STRUCT_INFO(mount),
|
||||||
STRUCT_INFO(mount),
|
STRUCT_INFO(vfsmount),
|
||||||
STRUCT_INFO(vfsmount),
|
STRUCT_INFO(mnt_namespace),
|
||||||
STRUCT_INFO(mnt_namespace),
|
#ifdef CONFIG_KPROBES
|
||||||
#ifdef CONFIG_KPROBES
|
STRUCT_INFO(kprobe),
|
||||||
STRUCT_INFO(kprobe),
|
#endif
|
||||||
#endif
|
STRUCT_INFO(vm_area_struct),
|
||||||
STRUCT_INFO(vm_area_struct),
|
STRUCT_INFO(vm_operations_struct),
|
||||||
STRUCT_INFO(vm_operations_struct),
|
STRUCT_INFO(netlink_kernel_cfg),
|
||||||
STRUCT_INFO(netlink_kernel_cfg),
|
STRUCT_INFO(task_struct)
|
||||||
STRUCT_INFO(task_struct)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// return 0 if successful
|
// return 0 if successful
|
||||||
// return -1 if struct not defined
|
// return -1 if struct not defined
|
||||||
int sukisu_super_find_struct(
|
int sukisu_super_find_struct(const char *struct_name, size_t *out_size,
|
||||||
const char* struct_name,
|
int *out_members)
|
||||||
size_t* out_size,
|
{
|
||||||
int* out_members
|
for (size_t i = 0; i < (sizeof(dynamic_struct_infos) /
|
||||||
) {
|
sizeof(dynamic_struct_infos[0]));
|
||||||
for(size_t i = 0; i < (sizeof(dynamic_struct_infos) / sizeof(dynamic_struct_infos[0])); i++) {
|
i++) {
|
||||||
struct DynamicStructInfo* info = dynamic_struct_infos[i];
|
struct DynamicStructInfo *info = dynamic_struct_infos[i];
|
||||||
if(strcmp(struct_name, info->name) == 0) {
|
if (strcmp(struct_name, info->name) == 0) {
|
||||||
if(out_size)
|
if (out_size)
|
||||||
*out_size = info->total_size;
|
*out_size = info->total_size;
|
||||||
if(out_members)
|
if (out_members)
|
||||||
*out_members = info->count;
|
*out_members = info->count;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(sukisu_super_find_struct);
|
EXPORT_SYMBOL(sukisu_super_find_struct);
|
||||||
|
|
||||||
@@ -237,61 +234,67 @@ EXPORT_SYMBOL(sukisu_super_find_struct);
|
|||||||
// return 0 if successful
|
// return 0 if successful
|
||||||
// return -1 if struct not defined
|
// return -1 if struct not defined
|
||||||
// return -2 if member not defined
|
// return -2 if member not defined
|
||||||
int sukisu_super_access (
|
int sukisu_super_access(const char *struct_name, const char *member_name,
|
||||||
const char* struct_name,
|
size_t *out_offset, size_t *out_size)
|
||||||
const char* member_name,
|
{
|
||||||
size_t* out_offset,
|
for (size_t i = 0; i < (sizeof(dynamic_struct_infos) /
|
||||||
size_t* out_size
|
sizeof(dynamic_struct_infos[0]));
|
||||||
) {
|
i++) {
|
||||||
for(size_t i = 0; i < (sizeof(dynamic_struct_infos) / sizeof(dynamic_struct_infos[0])); i++) {
|
struct DynamicStructInfo *info = dynamic_struct_infos[i];
|
||||||
struct DynamicStructInfo* info = dynamic_struct_infos[i];
|
if (strcmp(struct_name, info->name) == 0) {
|
||||||
if(strcmp(struct_name, info->name) == 0) {
|
for (size_t i1 = 0; i1 < info->count; i1++) {
|
||||||
for (size_t i1 = 0; i1 < info->count; i1++) {
|
if (strcmp(info->members[i1].name,
|
||||||
if (strcmp(info->members[i1].name, member_name) == 0) {
|
member_name) == 0) {
|
||||||
if(out_offset)
|
if (out_offset)
|
||||||
*out_offset = info->members[i].offset;
|
*out_offset =
|
||||||
if(out_size)
|
info->members[i].offset;
|
||||||
*out_size = info->members[i].size;
|
if (out_size)
|
||||||
return 0;
|
*out_size =
|
||||||
}
|
info->members[i].size;
|
||||||
}
|
return 0;
|
||||||
return -2;
|
}
|
||||||
}
|
}
|
||||||
}
|
return -2;
|
||||||
return -1;
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(sukisu_super_access);
|
EXPORT_SYMBOL(sukisu_super_access);
|
||||||
|
|
||||||
// 动态 container_of 宏
|
// 动态 container_of 宏
|
||||||
#define DYNAMIC_CONTAINER_OF(offset, member_ptr) ({ \
|
#define DYNAMIC_CONTAINER_OF(offset, member_ptr) \
|
||||||
(offset != (size_t)-1) ? (void*)((char*)(member_ptr) - offset) : NULL; \
|
({ \
|
||||||
})
|
(offset != (size_t)-1) ? \
|
||||||
|
(void *)((char *)(member_ptr) - offset) : \
|
||||||
|
NULL; \
|
||||||
|
})
|
||||||
|
|
||||||
// Dynamic container_of
|
// Dynamic container_of
|
||||||
// return 0 if success
|
// return 0 if success
|
||||||
// return -1 if current struct not defined
|
// return -1 if current struct not defined
|
||||||
// return -2 if target member not defined
|
// return -2 if target member not defined
|
||||||
int sukisu_super_container_of(
|
int sukisu_super_container_of(const char *struct_name, const char *member_name,
|
||||||
const char* struct_name,
|
void *ptr, void **out_ptr)
|
||||||
const char* member_name,
|
{
|
||||||
void* ptr,
|
if (ptr == NULL) {
|
||||||
void** out_ptr
|
return -3;
|
||||||
) {
|
}
|
||||||
if(ptr == NULL) {
|
for (size_t i = 0; i < (sizeof(dynamic_struct_infos) /
|
||||||
return -3;
|
sizeof(dynamic_struct_infos[0]));
|
||||||
}
|
i++) {
|
||||||
for(size_t i = 0; i < (sizeof(dynamic_struct_infos) / sizeof(dynamic_struct_infos[0])); i++) {
|
struct DynamicStructInfo *info = dynamic_struct_infos[i];
|
||||||
struct DynamicStructInfo* info = dynamic_struct_infos[i];
|
if (strcmp(struct_name, info->name) == 0) {
|
||||||
if(strcmp(struct_name, info->name) == 0) {
|
for (size_t i1 = 0; i1 < info->count; i1++) {
|
||||||
for (size_t i1 = 0; i1 < info->count; i1++) {
|
if (strcmp(info->members[i1].name,
|
||||||
if (strcmp(info->members[i1].name, member_name) == 0) {
|
member_name) == 0) {
|
||||||
*out_ptr = (void*) DYNAMIC_CONTAINER_OF(info->members[i1].offset, ptr);
|
*out_ptr = (void *)DYNAMIC_CONTAINER_OF(
|
||||||
return 0;
|
info->members[i1].offset, ptr);
|
||||||
}
|
return 0;
|
||||||
}
|
}
|
||||||
return -2;
|
}
|
||||||
}
|
return -2;
|
||||||
}
|
}
|
||||||
return -1;
|
}
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(sukisu_super_container_of);
|
EXPORT_SYMBOL(sukisu_super_container_of);
|
||||||
@@ -8,32 +8,21 @@
|
|||||||
|
|
||||||
// return 0 if successful
|
// return 0 if successful
|
||||||
// return -1 if struct not defined
|
// return -1 if struct not defined
|
||||||
int sukisu_super_find_struct(
|
int sukisu_super_find_struct(const char *struct_name, size_t *out_size,
|
||||||
const char* struct_name,
|
int *out_members);
|
||||||
size_t* out_size,
|
|
||||||
int* out_members
|
|
||||||
);
|
|
||||||
|
|
||||||
// Dynamic access struct
|
// Dynamic access struct
|
||||||
// return 0 if successful
|
// return 0 if successful
|
||||||
// return -1 if struct not defined
|
// return -1 if struct not defined
|
||||||
// return -2 if member not defined
|
// return -2 if member not defined
|
||||||
int sukisu_super_access (
|
int sukisu_super_access(const char *struct_name, const char *member_name,
|
||||||
const char* struct_name,
|
size_t *out_offset, size_t *out_size);
|
||||||
const char* member_name,
|
|
||||||
size_t* out_offset,
|
|
||||||
size_t* out_size
|
|
||||||
);
|
|
||||||
|
|
||||||
// Dynamic container_of
|
// Dynamic container_of
|
||||||
// return 0 if success
|
// return 0 if success
|
||||||
// return -1 if current struct not defined
|
// return -1 if current struct not defined
|
||||||
// return -2 if target member not defined
|
// return -2 if target member not defined
|
||||||
int sukisu_super_container_of(
|
int sukisu_super_container_of(const char *struct_name, const char *member_name,
|
||||||
const char* struct_name,
|
void *ptr, void **out_ptr);
|
||||||
const char* member_name,
|
|
||||||
void* ptr,
|
|
||||||
void** out_ptr
|
|
||||||
);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
38
kernel/ksu.c
38
kernel/ksu.c
@@ -24,9 +24,15 @@ static int __init read_kernelsu_state(char *s)
|
|||||||
}
|
}
|
||||||
__setup("kernelsu.enabled=", read_kernelsu_state);
|
__setup("kernelsu.enabled=", read_kernelsu_state);
|
||||||
|
|
||||||
bool get_ksu_state(void) { return enable_kernelsu >= 1; }
|
bool get_ksu_state(void)
|
||||||
|
{
|
||||||
|
return enable_kernelsu >= 1;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
bool get_ksu_state(void) { return true; }
|
bool get_ksu_state(void)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
#endif /* CONFIG_KSU_CMDLINE */
|
#endif /* CONFIG_KSU_CMDLINE */
|
||||||
|
|
||||||
static struct workqueue_struct *ksu_workqueue;
|
static struct workqueue_struct *ksu_workqueue;
|
||||||
@@ -61,8 +67,7 @@ extern void ksu_trace_unregister();
|
|||||||
|
|
||||||
int __init kernelsu_init(void)
|
int __init kernelsu_init(void)
|
||||||
{
|
{
|
||||||
pr_info("kernelsu.enabled=%d\n",
|
pr_info("kernelsu.enabled=%d\n", (int)get_ksu_state());
|
||||||
(int)get_ksu_state());
|
|
||||||
|
|
||||||
#ifdef CONFIG_KSU_CMDLINE
|
#ifdef CONFIG_KSU_CMDLINE
|
||||||
if (!get_ksu_state()) {
|
if (!get_ksu_state()) {
|
||||||
@@ -72,13 +77,20 @@ int __init kernelsu_init(void)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_KSU_DEBUG
|
#ifdef CONFIG_KSU_DEBUG
|
||||||
pr_alert("*************************************************************");
|
pr_alert(
|
||||||
pr_alert("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **");
|
"*************************************************************");
|
||||||
pr_alert("** **");
|
pr_alert(
|
||||||
pr_alert("** You are running KernelSU in DEBUG mode **");
|
"** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **");
|
||||||
pr_alert("** **");
|
pr_alert(
|
||||||
pr_alert("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **");
|
"** **");
|
||||||
pr_alert("*************************************************************");
|
pr_alert(
|
||||||
|
"** You are running KernelSU in DEBUG mode **");
|
||||||
|
pr_alert(
|
||||||
|
"** **");
|
||||||
|
pr_alert(
|
||||||
|
"** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **");
|
||||||
|
pr_alert(
|
||||||
|
"*************************************************************");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ksu_core_init();
|
ksu_core_init();
|
||||||
@@ -98,7 +110,7 @@ int __init kernelsu_init(void)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_KSU_TRACEPOINT_HOOK
|
#ifdef CONFIG_KSU_TRACEPOINT_HOOK
|
||||||
ksu_trace_register();
|
ksu_trace_register();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MODULE
|
#ifdef MODULE
|
||||||
@@ -127,7 +139,7 @@ void kernelsu_exit(void)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_KSU_TRACEPOINT_HOOK
|
#ifdef CONFIG_KSU_TRACEPOINT_HOOK
|
||||||
ksu_trace_unregister();
|
ksu_trace_unregister();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ksu_sucompat_exit();
|
ksu_sucompat_exit();
|
||||||
|
|||||||
18
kernel/ksu.h
18
kernel/ksu.h
@@ -42,7 +42,7 @@
|
|||||||
#define KSU_SELINUX_DOMAIN 64
|
#define KSU_SELINUX_DOMAIN 64
|
||||||
|
|
||||||
// SukiSU Ultra kernel su version full strings
|
// SukiSU Ultra kernel su version full strings
|
||||||
#ifndef KSU_VERSION_FULL
|
#ifndef KSU_VERSION_FULL
|
||||||
#define KSU_VERSION_FULL "v3.x-00000000@unknown"
|
#define KSU_VERSION_FULL "v3.x-00000000@unknown"
|
||||||
#endif
|
#endif
|
||||||
#define KSU_FULL_VERSION_STRING 255
|
#define KSU_FULL_VERSION_STRING 255
|
||||||
@@ -52,17 +52,17 @@
|
|||||||
#define DYNAMIC_SIGN_OP_CLEAR 2
|
#define DYNAMIC_SIGN_OP_CLEAR 2
|
||||||
|
|
||||||
struct dynamic_sign_user_config {
|
struct dynamic_sign_user_config {
|
||||||
unsigned int operation;
|
unsigned int operation;
|
||||||
unsigned int size;
|
unsigned int size;
|
||||||
char hash[65];
|
char hash[65];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct manager_list_info {
|
struct manager_list_info {
|
||||||
int count;
|
int count;
|
||||||
struct {
|
struct {
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
int signature_index;
|
int signature_index;
|
||||||
} managers[2];
|
} managers[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct root_profile {
|
struct root_profile {
|
||||||
|
|||||||
@@ -1,58 +1,68 @@
|
|||||||
#include "ksu_trace.h"
|
#include "ksu_trace.h"
|
||||||
|
|
||||||
|
|
||||||
// extern kernelsu functions
|
// extern kernelsu functions
|
||||||
extern bool ksu_execveat_hook __read_mostly;
|
extern bool ksu_execveat_hook __read_mostly;
|
||||||
extern int ksu_handle_execveat(int *fd, struct filename **filename_ptr, void *argv, void *envp, int *flags);
|
extern int ksu_handle_execveat(int *fd, struct filename **filename_ptr,
|
||||||
extern int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr, void *argv, void *envp, int *flags);
|
void *argv, void *envp, int *flags);
|
||||||
extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode, int *flags);
|
extern int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr,
|
||||||
|
void *argv, void *envp, int *flags);
|
||||||
|
extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user,
|
||||||
|
int *mode, int *flags);
|
||||||
extern bool ksu_vfs_read_hook __read_mostly;
|
extern bool ksu_vfs_read_hook __read_mostly;
|
||||||
extern int ksu_handle_sys_read(unsigned int fd, char __user **buf_ptr, size_t *count_ptr);
|
extern int ksu_handle_sys_read(unsigned int fd, char __user **buf_ptr,
|
||||||
extern int ksu_handle_stat(int *dfd, const char __user **filename_user, int *flags);
|
size_t *count_ptr);
|
||||||
|
extern int ksu_handle_stat(int *dfd, const char __user **filename_user,
|
||||||
|
int *flags);
|
||||||
extern bool ksu_input_hook __read_mostly;
|
extern bool ksu_input_hook __read_mostly;
|
||||||
extern int ksu_handle_input_handle_event(unsigned int *type, unsigned int *code, int *value);
|
extern int ksu_handle_input_handle_event(unsigned int *type, unsigned int *code,
|
||||||
extern int ksu_handle_devpts(struct inode*);
|
int *value);
|
||||||
|
extern int ksu_handle_devpts(struct inode *);
|
||||||
// end kernelsu functions
|
// end kernelsu functions
|
||||||
|
|
||||||
|
|
||||||
// tracepoint callback functions
|
// tracepoint callback functions
|
||||||
void ksu_trace_execveat_hook_callback(void *data, int *fd, struct filename **filename_ptr,
|
void ksu_trace_execveat_hook_callback(void *data, int *fd,
|
||||||
void *argv, void *envp, int *flags)
|
struct filename **filename_ptr,
|
||||||
|
void *argv, void *envp, int *flags)
|
||||||
{
|
{
|
||||||
if (unlikely(ksu_execveat_hook))
|
if (unlikely(ksu_execveat_hook))
|
||||||
ksu_handle_execveat(fd, filename_ptr, argv, envp, flags);
|
ksu_handle_execveat(fd, filename_ptr, argv, envp, flags);
|
||||||
else
|
else
|
||||||
ksu_handle_execveat_sucompat(fd, filename_ptr, NULL, NULL, NULL);
|
ksu_handle_execveat_sucompat(fd, filename_ptr, NULL, NULL,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ksu_trace_execveat_sucompat_hook_callback(void *data, int *fd, struct filename **filename_ptr,
|
void ksu_trace_execveat_sucompat_hook_callback(void *data, int *fd,
|
||||||
void *argv, void *envp, int *flags)
|
struct filename **filename_ptr,
|
||||||
|
void *argv, void *envp,
|
||||||
|
int *flags)
|
||||||
{
|
{
|
||||||
if (!ksu_execveat_hook)
|
if (!ksu_execveat_hook)
|
||||||
ksu_handle_execveat_sucompat(fd, filename_ptr, argv, envp, flags);
|
ksu_handle_execveat_sucompat(fd, filename_ptr, argv, envp,
|
||||||
|
flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ksu_trace_faccessat_hook_callback(void *data, int *dfd, const char __user **filename_user,
|
void ksu_trace_faccessat_hook_callback(void *data, int *dfd,
|
||||||
int *mode, int *flags)
|
const char __user **filename_user,
|
||||||
|
int *mode, int *flags)
|
||||||
{
|
{
|
||||||
ksu_handle_faccessat(dfd, filename_user, mode, flags);
|
ksu_handle_faccessat(dfd, filename_user, mode, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ksu_trace_sys_read_hook_callback(void *data, unsigned int fd, char __user **buf_ptr,
|
void ksu_trace_sys_read_hook_callback(void *data, unsigned int fd,
|
||||||
size_t *count_ptr)
|
char __user **buf_ptr, size_t *count_ptr)
|
||||||
{
|
{
|
||||||
if (unlikely(ksu_vfs_read_hook))
|
if (unlikely(ksu_vfs_read_hook))
|
||||||
ksu_handle_sys_read(fd, buf_ptr, count_ptr);
|
ksu_handle_sys_read(fd, buf_ptr, count_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ksu_trace_stat_hook_callback(void *data, int *dfd, const char __user **filename_user,
|
void ksu_trace_stat_hook_callback(void *data, int *dfd,
|
||||||
int *flags)
|
const char __user **filename_user, int *flags)
|
||||||
{
|
{
|
||||||
ksu_handle_stat(dfd, filename_user, flags);
|
ksu_handle_stat(dfd, filename_user, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ksu_trace_input_hook_callback(void *data, unsigned int *type, unsigned int *code,
|
void ksu_trace_input_hook_callback(void *data, unsigned int *type,
|
||||||
int *value)
|
unsigned int *code, int *value)
|
||||||
{
|
{
|
||||||
if (unlikely(ksu_input_hook))
|
if (unlikely(ksu_input_hook))
|
||||||
ksu_handle_input_handle_event(type, code, value);
|
ksu_handle_input_handle_event(type, code, value);
|
||||||
@@ -60,31 +70,43 @@ void ksu_trace_input_hook_callback(void *data, unsigned int *type, unsigned int
|
|||||||
|
|
||||||
void ksu_trace_devpts_hook_callback(void *data, struct inode *inode)
|
void ksu_trace_devpts_hook_callback(void *data, struct inode *inode)
|
||||||
{
|
{
|
||||||
ksu_handle_devpts(inode);
|
ksu_handle_devpts(inode);
|
||||||
}
|
}
|
||||||
// end tracepoint callback functions
|
// end tracepoint callback functions
|
||||||
|
|
||||||
|
|
||||||
// register tracepoint callback functions
|
// register tracepoint callback functions
|
||||||
void ksu_trace_register(void)
|
void ksu_trace_register(void)
|
||||||
{
|
{
|
||||||
register_trace_ksu_trace_execveat_hook(ksu_trace_execveat_hook_callback, NULL);
|
register_trace_ksu_trace_execveat_hook(ksu_trace_execveat_hook_callback,
|
||||||
register_trace_ksu_trace_execveat_sucompat_hook(ksu_trace_execveat_sucompat_hook_callback, NULL);
|
NULL);
|
||||||
register_trace_ksu_trace_faccessat_hook(ksu_trace_faccessat_hook_callback, NULL);
|
register_trace_ksu_trace_execveat_sucompat_hook(
|
||||||
register_trace_ksu_trace_sys_read_hook(ksu_trace_sys_read_hook_callback, NULL);
|
ksu_trace_execveat_sucompat_hook_callback, NULL);
|
||||||
register_trace_ksu_trace_stat_hook(ksu_trace_stat_hook_callback, NULL);
|
register_trace_ksu_trace_faccessat_hook(
|
||||||
register_trace_ksu_trace_input_hook(ksu_trace_input_hook_callback, NULL);
|
ksu_trace_faccessat_hook_callback, NULL);
|
||||||
register_trace_ksu_trace_devpts_hook(ksu_trace_devpts_hook_callback, NULL);
|
register_trace_ksu_trace_sys_read_hook(ksu_trace_sys_read_hook_callback,
|
||||||
|
NULL);
|
||||||
|
register_trace_ksu_trace_stat_hook(ksu_trace_stat_hook_callback, NULL);
|
||||||
|
register_trace_ksu_trace_input_hook(ksu_trace_input_hook_callback,
|
||||||
|
NULL);
|
||||||
|
register_trace_ksu_trace_devpts_hook(ksu_trace_devpts_hook_callback,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// unregister tracepoint callback functions
|
// unregister tracepoint callback functions
|
||||||
void ksu_trace_unregister(void)
|
void ksu_trace_unregister(void)
|
||||||
{
|
{
|
||||||
unregister_trace_ksu_trace_execveat_hook(ksu_trace_execveat_hook_callback, NULL);
|
unregister_trace_ksu_trace_execveat_hook(
|
||||||
unregister_trace_ksu_trace_execveat_sucompat_hook(ksu_trace_execveat_sucompat_hook_callback, NULL);
|
ksu_trace_execveat_hook_callback, NULL);
|
||||||
unregister_trace_ksu_trace_faccessat_hook(ksu_trace_faccessat_hook_callback, NULL);
|
unregister_trace_ksu_trace_execveat_sucompat_hook(
|
||||||
unregister_trace_ksu_trace_sys_read_hook(ksu_trace_sys_read_hook_callback, NULL);
|
ksu_trace_execveat_sucompat_hook_callback, NULL);
|
||||||
unregister_trace_ksu_trace_stat_hook(ksu_trace_stat_hook_callback, NULL);
|
unregister_trace_ksu_trace_faccessat_hook(
|
||||||
unregister_trace_ksu_trace_input_hook(ksu_trace_input_hook_callback, NULL);
|
ksu_trace_faccessat_hook_callback, NULL);
|
||||||
unregister_trace_ksu_trace_devpts_hook(ksu_trace_devpts_hook_callback, NULL);
|
unregister_trace_ksu_trace_sys_read_hook(
|
||||||
|
ksu_trace_sys_read_hook_callback, NULL);
|
||||||
|
unregister_trace_ksu_trace_stat_hook(ksu_trace_stat_hook_callback,
|
||||||
|
NULL);
|
||||||
|
unregister_trace_ksu_trace_input_hook(ksu_trace_input_hook_callback,
|
||||||
|
NULL);
|
||||||
|
unregister_trace_ksu_trace_devpts_hook(ksu_trace_devpts_hook_callback,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,32 +8,35 @@
|
|||||||
#include <linux/tracepoint.h>
|
#include <linux/tracepoint.h>
|
||||||
|
|
||||||
DECLARE_TRACE(ksu_trace_execveat_hook,
|
DECLARE_TRACE(ksu_trace_execveat_hook,
|
||||||
TP_PROTO(int *fd, struct filename **filename_ptr, void *argv, void *envp, int *flags),
|
TP_PROTO(int *fd, struct filename **filename_ptr, void *argv,
|
||||||
TP_ARGS(fd, filename_ptr, argv, envp, flags));
|
void *envp, int *flags),
|
||||||
|
TP_ARGS(fd, filename_ptr, argv, envp, flags));
|
||||||
|
|
||||||
DECLARE_TRACE(ksu_trace_execveat_sucompat_hook,
|
DECLARE_TRACE(ksu_trace_execveat_sucompat_hook,
|
||||||
TP_PROTO(int *fd, struct filename **filename_ptr, void *argv, void *envp, int *flags),
|
TP_PROTO(int *fd, struct filename **filename_ptr, void *argv,
|
||||||
TP_ARGS(fd, filename_ptr, argv, envp, flags));
|
void *envp, int *flags),
|
||||||
|
TP_ARGS(fd, filename_ptr, argv, envp, flags));
|
||||||
|
|
||||||
DECLARE_TRACE(ksu_trace_faccessat_hook,
|
DECLARE_TRACE(ksu_trace_faccessat_hook,
|
||||||
TP_PROTO(int *dfd, const char __user **filename_user, int *mode, int *flags),
|
TP_PROTO(int *dfd, const char __user **filename_user, int *mode,
|
||||||
TP_ARGS(dfd, filename_user, mode, flags));
|
int *flags),
|
||||||
|
TP_ARGS(dfd, filename_user, mode, flags));
|
||||||
|
|
||||||
DECLARE_TRACE(ksu_trace_sys_read_hook,
|
DECLARE_TRACE(ksu_trace_sys_read_hook,
|
||||||
TP_PROTO(unsigned int fd, char __user **buf_ptr, size_t *count_ptr),
|
TP_PROTO(unsigned int fd, char __user **buf_ptr,
|
||||||
TP_ARGS(fd, buf_ptr, count_ptr));
|
size_t *count_ptr),
|
||||||
|
TP_ARGS(fd, buf_ptr, count_ptr));
|
||||||
|
|
||||||
DECLARE_TRACE(ksu_trace_stat_hook,
|
DECLARE_TRACE(ksu_trace_stat_hook,
|
||||||
TP_PROTO(int *dfd, const char __user **filename_user, int *flags),
|
TP_PROTO(int *dfd, const char __user **filename_user, int *flags),
|
||||||
TP_ARGS(dfd, filename_user, flags));
|
TP_ARGS(dfd, filename_user, flags));
|
||||||
|
|
||||||
DECLARE_TRACE(ksu_trace_input_hook,
|
DECLARE_TRACE(ksu_trace_input_hook,
|
||||||
TP_PROTO(unsigned int *type, unsigned int *code, int *value),
|
TP_PROTO(unsigned int *type, unsigned int *code, int *value),
|
||||||
TP_ARGS(type, code, value));
|
TP_ARGS(type, code, value));
|
||||||
|
|
||||||
DECLARE_TRACE(ksu_trace_devpts_hook,
|
DECLARE_TRACE(ksu_trace_devpts_hook, TP_PROTO(struct inode *inode),
|
||||||
TP_PROTO(struct inode *inode),
|
TP_ARGS(inode));
|
||||||
TP_ARGS(inode));
|
|
||||||
|
|
||||||
#endif /* _KSU_TRACE_H */
|
#endif /* _KSU_TRACE_H */
|
||||||
|
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ void on_post_fs_data(void)
|
|||||||
pr_info("devpts sid: %d\n", ksu_devpts_sid);
|
pr_info("devpts sid: %d\n", ksu_devpts_sid);
|
||||||
|
|
||||||
// End of boot state
|
// End of boot state
|
||||||
is_boot_phase = false;
|
is_boot_phase = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAX_ARG_STRINGS 0x7FFFFFFF
|
#define MAX_ARG_STRINGS 0x7FFFFFFF
|
||||||
@@ -200,8 +200,8 @@ int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
|
|||||||
const char __user *p = get_user_arg_ptr(*argv, 1);
|
const char __user *p = get_user_arg_ptr(*argv, 1);
|
||||||
if (p && !IS_ERR(p)) {
|
if (p && !IS_ERR(p)) {
|
||||||
char first_arg[16];
|
char first_arg[16];
|
||||||
ksu_strncpy_from_user_retry(
|
ksu_strncpy_from_user_retry(first_arg, p,
|
||||||
first_arg, p, sizeof(first_arg));
|
sizeof(first_arg));
|
||||||
pr_info("/system/bin/init first arg: %s\n",
|
pr_info("/system/bin/init first arg: %s\n",
|
||||||
first_arg);
|
first_arg);
|
||||||
if (!strcmp(first_arg, "second_stage")) {
|
if (!strcmp(first_arg, "second_stage")) {
|
||||||
@@ -225,8 +225,8 @@ int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
|
|||||||
const char __user *p = get_user_arg_ptr(*argv, 1);
|
const char __user *p = get_user_arg_ptr(*argv, 1);
|
||||||
if (p && !IS_ERR(p)) {
|
if (p && !IS_ERR(p)) {
|
||||||
char first_arg[16];
|
char first_arg[16];
|
||||||
ksu_strncpy_from_user_retry(
|
ksu_strncpy_from_user_retry(first_arg, p,
|
||||||
first_arg, p, sizeof(first_arg));
|
sizeof(first_arg));
|
||||||
pr_info("/init first arg: %s\n", first_arg);
|
pr_info("/init first arg: %s\n", first_arg);
|
||||||
if (!strcmp(first_arg, "--second-stage")) {
|
if (!strcmp(first_arg, "--second-stage")) {
|
||||||
pr_info("/init second_stage executed\n");
|
pr_info("/init second_stage executed\n");
|
||||||
@@ -573,12 +573,12 @@ static void do_stop_input_hook(struct work_struct *work)
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static int ksu_execve_ksud_common(const char __user *filename_user,
|
static int ksu_execve_ksud_common(const char __user *filename_user,
|
||||||
struct user_arg_ptr *argv)
|
struct user_arg_ptr *argv)
|
||||||
{
|
{
|
||||||
struct filename filename_in, *filename_p;
|
struct filename filename_in, *filename_p;
|
||||||
char path[32];
|
char path[32];
|
||||||
long len;
|
long len;
|
||||||
|
|
||||||
// return early if disabled.
|
// return early if disabled.
|
||||||
if (!ksu_execveat_hook) {
|
if (!ksu_execveat_hook) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -597,19 +597,21 @@ static int ksu_execve_ksud_common(const char __user *filename_user,
|
|||||||
filename_in.name = path;
|
filename_in.name = path;
|
||||||
filename_p = &filename_in;
|
filename_p = &filename_in;
|
||||||
|
|
||||||
return ksu_handle_execveat_ksud(AT_FDCWD, &filename_p, argv, NULL, NULL);
|
return ksu_handle_execveat_ksud(AT_FDCWD, &filename_p, argv, NULL,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int __maybe_unused ksu_handle_execve_ksud(const char __user *filename_user,
|
int __maybe_unused
|
||||||
const char __user *const __user *__argv)
|
ksu_handle_execve_ksud(const char __user *filename_user,
|
||||||
|
const char __user *const __user *__argv)
|
||||||
{
|
{
|
||||||
struct user_arg_ptr argv = { .ptr.native = __argv };
|
struct user_arg_ptr argv = { .ptr.native = __argv };
|
||||||
return ksu_execve_ksud_common(filename_user, &argv);
|
return ksu_execve_ksud_common(filename_user, &argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_COMPAT) && defined(CONFIG_64BIT)
|
#if defined(CONFIG_COMPAT) && defined(CONFIG_64BIT)
|
||||||
int __maybe_unused ksu_handle_compat_execve_ksud(const char __user *filename_user,
|
int __maybe_unused ksu_handle_compat_execve_ksud(
|
||||||
const compat_uptr_t __user *__argv)
|
const char __user *filename_user, const compat_uptr_t __user *__argv)
|
||||||
{
|
{
|
||||||
struct user_arg_ptr argv = { .ptr.compat = __argv };
|
struct user_arg_ptr argv = { .ptr.compat = __argv };
|
||||||
return ksu_execve_ksud_common(filename_user, &argv);
|
return ksu_execve_ksud_common(filename_user, &argv);
|
||||||
@@ -651,7 +653,9 @@ static void stop_input_hook()
|
|||||||
bool ret = schedule_work(&stop_input_hook_work);
|
bool ret = schedule_work(&stop_input_hook_work);
|
||||||
pr_info("unregister input kprobe: %d!\n", ret);
|
pr_info("unregister input kprobe: %d!\n", ret);
|
||||||
#else
|
#else
|
||||||
if (!ksu_input_hook) { return; }
|
if (!ksu_input_hook) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
ksu_input_hook = false;
|
ksu_input_hook = false;
|
||||||
pr_info("stop input_hook\n");
|
pr_info("stop input_hook\n");
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ static inline bool ksu_is_manager_uid_valid()
|
|||||||
|
|
||||||
static inline bool is_manager()
|
static inline bool is_manager()
|
||||||
{
|
{
|
||||||
return unlikely(ksu_is_any_manager(ksu_current_uid()) || ksu_manager_uid == ksu_current_uid());
|
return unlikely(ksu_is_any_manager(ksu_current_uid()) ||
|
||||||
|
ksu_manager_uid == ksu_current_uid());
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uid_t ksu_get_manager_uid()
|
static inline uid_t ksu_get_manager_uid()
|
||||||
|
|||||||
@@ -2,11 +2,13 @@
|
|||||||
#define MANAGER_SIGN_H
|
#define MANAGER_SIGN_H
|
||||||
|
|
||||||
// ShirkNeko/KernelSU
|
// ShirkNeko/KernelSU
|
||||||
#define EXPECTED_SIZE_SHIRKNEKO 0x35c
|
#define EXPECTED_SIZE_SHIRKNEKO 0x35c
|
||||||
#define EXPECTED_HASH_SHIRKNEKO "947ae944f3de4ed4c21a7e4f7953ecf351bfa2b36239da37a34111ad29993eef"
|
#define EXPECTED_HASH_SHIRKNEKO \
|
||||||
|
"947ae944f3de4ed4c21a7e4f7953ecf351bfa2b36239da37a34111ad29993eef"
|
||||||
|
|
||||||
// Dynamic Sign
|
// Dynamic Sign
|
||||||
#define EXPECTED_SIZE_OTHER 0x300
|
#define EXPECTED_SIZE_OTHER 0x300
|
||||||
#define EXPECTED_HASH_OTHER "0000000000000000000000000000000000000000000000000000000000000000"
|
#define EXPECTED_HASH_OTHER \
|
||||||
|
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||||
|
|
||||||
#endif /* MANAGER_SIGN_H */
|
#endif /* MANAGER_SIGN_H */
|
||||||
|
|||||||
@@ -162,9 +162,9 @@ extern bool ksu_is_compat __read_mostly;
|
|||||||
|
|
||||||
// armv7l kernel compat
|
// armv7l kernel compat
|
||||||
#ifdef CONFIG_64BIT
|
#ifdef CONFIG_64BIT
|
||||||
#define usize u64
|
#define usize u64
|
||||||
#else
|
#else
|
||||||
#define usize u32
|
#define usize u32
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct sepol_data {
|
struct sepol_data {
|
||||||
@@ -212,7 +212,7 @@ static int get_object(char *buf, char __user *user_object, size_t buf_sz,
|
|||||||
// reset avc cache table, otherwise the new rules will not take effect if already denied
|
// reset avc cache table, otherwise the new rules will not take effect if already denied
|
||||||
static void reset_avc_cache()
|
static void reset_avc_cache()
|
||||||
{
|
{
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0) || \
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0) || \
|
||||||
!defined(KSU_COMPAT_USE_SELINUX_STATE)
|
!defined(KSU_COMPAT_USE_SELINUX_STATE)
|
||||||
avc_ss_reset(0);
|
avc_ss_reset(0);
|
||||||
selnl_notify_policyload(0);
|
selnl_notify_policyload(0);
|
||||||
@@ -239,11 +239,13 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
|
|||||||
}
|
}
|
||||||
|
|
||||||
u32 cmd, subcmd;
|
u32 cmd, subcmd;
|
||||||
char __user *sepol1, *sepol2, *sepol3, *sepol4, *sepol5, *sepol6, *sepol7;
|
char __user *sepol1, *sepol2, *sepol3, *sepol4, *sepol5, *sepol6,
|
||||||
|
*sepol7;
|
||||||
|
|
||||||
if (unlikely(ksu_is_compat)) {
|
if (unlikely(ksu_is_compat)) {
|
||||||
struct sepol_data_compat data_compat;
|
struct sepol_data_compat data_compat;
|
||||||
if (copy_from_user(&data_compat, arg4, sizeof(struct sepol_data_compat))) {
|
if (copy_from_user(&data_compat, arg4,
|
||||||
|
sizeof(struct sepol_data_compat))) {
|
||||||
pr_err("sepol: copy sepol_data failed.\n");
|
pr_err("sepol: copy sepol_data failed.\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -301,8 +303,7 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_object(perm_buf, sepol4, sizeof(perm_buf), &p) <
|
if (get_object(perm_buf, sepol4, sizeof(perm_buf), &p) < 0) {
|
||||||
0) {
|
|
||||||
pr_err("sepol: copy perm failed.\n");
|
pr_err("sepol: copy perm failed.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
@@ -343,13 +344,12 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
|
|||||||
pr_err("sepol: copy cls failed.\n");
|
pr_err("sepol: copy cls failed.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
if (strncpy_from_user(operation, sepol4,
|
if (strncpy_from_user(operation, sepol4, sizeof(operation)) <
|
||||||
sizeof(operation)) < 0) {
|
0) {
|
||||||
pr_err("sepol: copy operation failed.\n");
|
pr_err("sepol: copy operation failed.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
if (strncpy_from_user(perm_set, sepol5, sizeof(perm_set)) <
|
if (strncpy_from_user(perm_set, sepol5, sizeof(perm_set)) < 0) {
|
||||||
0) {
|
|
||||||
pr_err("sepol: copy perm_set failed.\n");
|
pr_err("sepol: copy perm_set failed.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
@@ -450,8 +450,8 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
|
|||||||
if (sepol5 == NULL) {
|
if (sepol5 == NULL) {
|
||||||
real_object = NULL;
|
real_object = NULL;
|
||||||
} else {
|
} else {
|
||||||
if (strncpy_from_user(object, sepol5,
|
if (strncpy_from_user(object, sepol5, sizeof(object)) <
|
||||||
sizeof(object)) < 0) {
|
0) {
|
||||||
pr_err("sepol: copy object failed.\n");
|
pr_err("sepol: copy object failed.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
@@ -510,8 +510,7 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
|
|||||||
pr_err("sepol: copy path failed.\n");
|
pr_err("sepol: copy path failed.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
if (strncpy_from_user(context, sepol3, sizeof(context)) <
|
if (strncpy_from_user(context, sepol3, sizeof(context)) < 0) {
|
||||||
0) {
|
|
||||||
pr_err("sepol: copy context failed.\n");
|
pr_err("sepol: copy context failed.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,8 +36,9 @@ static int transive_to_domain(const char *domain)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(4, 19, 0)
|
#if LINUX_VERSION_CODE <= KERNEL_VERSION(4, 19, 0)
|
||||||
bool __maybe_unused is_ksu_transition(const struct task_security_struct *old_tsec,
|
bool __maybe_unused
|
||||||
const struct task_security_struct *new_tsec)
|
is_ksu_transition(const struct task_security_struct *old_tsec,
|
||||||
|
const struct task_security_struct *new_tsec)
|
||||||
{
|
{
|
||||||
static u32 ksu_sid;
|
static u32 ksu_sid;
|
||||||
char *secdata;
|
char *secdata;
|
||||||
@@ -45,7 +46,8 @@ bool __maybe_unused is_ksu_transition(const struct task_security_struct *old_tse
|
|||||||
bool allowed = false;
|
bool allowed = false;
|
||||||
|
|
||||||
if (!ksu_sid)
|
if (!ksu_sid)
|
||||||
security_secctx_to_secid(KERNEL_SU_DOMAIN, strlen(KERNEL_SU_DOMAIN), &ksu_sid);
|
security_secctx_to_secid(KERNEL_SU_DOMAIN,
|
||||||
|
strlen(KERNEL_SU_DOMAIN), &ksu_sid);
|
||||||
|
|
||||||
if (security_secid_to_secctx(old_tsec->sid, &secdata, &seclen))
|
if (security_secid_to_secctx(old_tsec->sid, &secdata, &seclen))
|
||||||
return false;
|
return false;
|
||||||
@@ -74,11 +76,11 @@ bool getenforce(void)
|
|||||||
if (is_selinux_disabled()) {
|
if (is_selinux_disabled()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return __is_selinux_enforcing();
|
return __is_selinux_enforcing();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0)) && \
|
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0)) && \
|
||||||
!defined(KSU_COMPAT_HAS_CURRENT_SID)
|
!defined(KSU_COMPAT_HAS_CURRENT_SID)
|
||||||
/*
|
/*
|
||||||
* get the subjective security ID of the current task
|
* get the subjective security ID of the current task
|
||||||
|
|||||||
@@ -4,7 +4,8 @@
|
|||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/version.h>
|
#include <linux/version.h>
|
||||||
|
|
||||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) || defined(KSU_COMPAT_HAS_SELINUX_STATE)
|
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) || \
|
||||||
|
defined(KSU_COMPAT_HAS_SELINUX_STATE)
|
||||||
#define KSU_COMPAT_USE_SELINUX_STATE
|
#define KSU_COMPAT_USE_SELINUX_STATE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -12,24 +12,24 @@
|
|||||||
|
|
||||||
#ifdef CONFIG_SECURITY_SELINUX_DISABLE
|
#ifdef CONFIG_SECURITY_SELINUX_DISABLE
|
||||||
#ifdef KSU_COMPAT_USE_SELINUX_STATE
|
#ifdef KSU_COMPAT_USE_SELINUX_STATE
|
||||||
#define is_selinux_disabled() (selinux_state.disabled)
|
#define is_selinux_disabled() (selinux_state.disabled)
|
||||||
#else
|
#else
|
||||||
#define is_selinux_disabled() (selinux_disabled)
|
#define is_selinux_disabled() (selinux_disabled)
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#define is_selinux_disabled() (0)
|
#define is_selinux_disabled() (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
|
#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
|
||||||
#ifdef KSU_COMPAT_USE_SELINUX_STATE
|
#ifdef KSU_COMPAT_USE_SELINUX_STATE
|
||||||
#define __is_selinux_enforcing() (selinux_state.enforcing)
|
#define __is_selinux_enforcing() (selinux_state.enforcing)
|
||||||
#define __setenforce(val) selinux_state.enforcing = val
|
#define __setenforce(val) selinux_state.enforcing = val
|
||||||
#elif defined(SAMSUNG_SELINUX_PORTING) || !defined(KSU_COMPAT_USE_SELINUX_STATE)
|
#elif defined(SAMSUNG_SELINUX_PORTING) || !defined(KSU_COMPAT_USE_SELINUX_STATE)
|
||||||
#define __is_selinux_enforcing() (selinux_enforcing)
|
#define __is_selinux_enforcing() (selinux_enforcing)
|
||||||
#define __setenforce(val) selinux_enforcing = val
|
#define __setenforce(val) selinux_enforcing = val
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#define __is_selinux_enforcing() (1)
|
#define __is_selinux_enforcing() (1)
|
||||||
#define __setenforce(val)
|
#define __setenforce(val)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -62,18 +62,18 @@ static bool add_typeattribute(struct policydb *db, const char *type,
|
|||||||
// rules
|
// rules
|
||||||
#define strip_av(effect, invert) ((effect == AVTAB_AUDITDENY) == !invert)
|
#define strip_av(effect, invert) ((effect == AVTAB_AUDITDENY) == !invert)
|
||||||
|
|
||||||
#define ksu_hash_for_each(node_ptr, n_slot, cur) \
|
#define ksu_hash_for_each(node_ptr, n_slot, cur) \
|
||||||
int i; \
|
int i; \
|
||||||
for (i = 0; i < n_slot; ++i) \
|
for (i = 0; i < n_slot; ++i) \
|
||||||
for (cur = node_ptr[i]; cur; cur = cur->next)
|
for (cur = node_ptr[i]; cur; cur = cur->next)
|
||||||
|
|
||||||
// htable is a struct instead of pointer above 5.8.0:
|
// htable is a struct instead of pointer above 5.8.0:
|
||||||
// https://elixir.bootlin.com/linux/v5.8-rc1/source/security/selinux/ss/symtab.h
|
// https://elixir.bootlin.com/linux/v5.8-rc1/source/security/selinux/ss/symtab.h
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
|
||||||
#define ksu_hashtab_for_each(htab, cur) \
|
#define ksu_hashtab_for_each(htab, cur) \
|
||||||
ksu_hash_for_each(htab.htable, htab.size, cur)
|
ksu_hash_for_each(htab.htable, htab.size, cur)
|
||||||
#else
|
#else
|
||||||
#define ksu_hashtab_for_each(htab, cur) \
|
#define ksu_hashtab_for_each(htab, cur) \
|
||||||
ksu_hash_for_each(htab->htable, htab->size, cur)
|
ksu_hash_for_each(htab->htable, htab->size, cur)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -84,7 +84,7 @@ static bool add_typeattribute(struct policydb *db, const char *type,
|
|||||||
#define symtab_insert(s, name, datum) hashtab_insert((s)->table, name, datum)
|
#define symtab_insert(s, name, datum) hashtab_insert((s)->table, name, datum)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define avtab_for_each(avtab, cur) \
|
#define avtab_for_each(avtab, cur) \
|
||||||
ksu_hash_for_each(avtab.htable, avtab.nslot, cur);
|
ksu_hash_for_each(avtab.htable, avtab.nslot, cur);
|
||||||
|
|
||||||
static struct avtab_node *get_avtab_node(struct policydb *db,
|
static struct avtab_node *get_avtab_node(struct policydb *db,
|
||||||
@@ -657,30 +657,27 @@ static bool add_type(struct policydb *db, const char *type_name, bool attr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0)
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0)
|
||||||
struct ebitmap *new_type_attr_map_array =
|
struct ebitmap *new_type_attr_map_array = ksu_realloc(
|
||||||
ksu_realloc(db->type_attr_map_array,
|
db->type_attr_map_array, value * sizeof(struct ebitmap),
|
||||||
value * sizeof(struct ebitmap),
|
(value - 1) * sizeof(struct ebitmap));
|
||||||
(value - 1) * sizeof(struct ebitmap));
|
|
||||||
|
|
||||||
if (!new_type_attr_map_array) {
|
if (!new_type_attr_map_array) {
|
||||||
pr_err("add_type: alloc type_attr_map_array failed\n");
|
pr_err("add_type: alloc type_attr_map_array failed\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct type_datum **new_type_val_to_struct =
|
struct type_datum **new_type_val_to_struct = ksu_realloc(
|
||||||
ksu_realloc(db->type_val_to_struct,
|
db->type_val_to_struct, sizeof(*db->type_val_to_struct) * value,
|
||||||
sizeof(*db->type_val_to_struct) * value,
|
sizeof(*db->type_val_to_struct) * (value - 1));
|
||||||
sizeof(*db->type_val_to_struct) * (value - 1));
|
|
||||||
|
|
||||||
if (!new_type_val_to_struct) {
|
if (!new_type_val_to_struct) {
|
||||||
pr_err("add_type: alloc type_val_to_struct failed\n");
|
pr_err("add_type: alloc type_val_to_struct failed\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
char **new_val_to_name_types =
|
char **new_val_to_name_types = ksu_realloc(
|
||||||
ksu_realloc(db->sym_val_to_name[SYM_TYPES],
|
db->sym_val_to_name[SYM_TYPES], sizeof(char *) * value,
|
||||||
sizeof(char *) * value,
|
sizeof(char *) * (value - 1));
|
||||||
sizeof(char *) * (value - 1));
|
|
||||||
if (!new_val_to_name_types) {
|
if (!new_val_to_name_types) {
|
||||||
pr_err("add_type: alloc val_to_name failed\n");
|
pr_err("add_type: alloc val_to_name failed\n");
|
||||||
return false;
|
return false;
|
||||||
@@ -727,10 +724,9 @@ static bool add_type(struct policydb *db, const char *type_name, bool attr)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
char **new_val_to_name_types =
|
char **new_val_to_name_types = krealloc(
|
||||||
krealloc(db->sym_val_to_name[SYM_TYPES],
|
db->sym_val_to_name[SYM_TYPES],
|
||||||
sizeof(char *) * db->symtab[SYM_TYPES].nprim,
|
sizeof(char *) * db->symtab[SYM_TYPES].nprim, GFP_KERNEL);
|
||||||
GFP_KERNEL);
|
|
||||||
if (!new_val_to_name_types) {
|
if (!new_val_to_name_types) {
|
||||||
pr_err("add_type: alloc val_to_name failed\n");
|
pr_err("add_type: alloc val_to_name failed\n");
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -67,11 +67,11 @@ static inline bool __is_su_allowed(const void *ptr_to_check)
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#define is_su_allowed(ptr) __is_su_allowed((const void *)ptr)
|
#define is_su_allowed(ptr) __is_su_allowed((const void *)ptr)
|
||||||
|
|
||||||
static int ksu_sucompat_user_common(const char __user **filename_user,
|
static int ksu_sucompat_user_common(const char __user **filename_user,
|
||||||
const char *syscall_name,
|
const char *syscall_name,
|
||||||
const bool escalate)
|
const bool escalate)
|
||||||
{
|
{
|
||||||
char path[sizeof(su)]; // sizeof includes nullterm already!
|
char path[sizeof(su)]; // sizeof includes nullterm already!
|
||||||
memset(path, 0, sizeof(path));
|
memset(path, 0, sizeof(path));
|
||||||
|
|||||||
@@ -63,7 +63,8 @@ static int get_pkg_from_apk_path(char *pkg, const char *path)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void crown_manager(const char *apk, struct list_head *uid_data, int signature_index)
|
static void crown_manager(const char *apk, struct list_head *uid_data,
|
||||||
|
int signature_index)
|
||||||
{
|
{
|
||||||
char pkg[KSU_MAX_PACKAGE_NAME];
|
char pkg[KSU_MAX_PACKAGE_NAME];
|
||||||
if (get_pkg_from_apk_path(pkg, apk) < 0) {
|
if (get_pkg_from_apk_path(pkg, apk) < 0) {
|
||||||
@@ -84,13 +85,14 @@ static void crown_manager(const char *apk, struct list_head *uid_data, int signa
|
|||||||
struct list_head *list = (struct list_head *)uid_data;
|
struct list_head *list = (struct list_head *)uid_data;
|
||||||
struct uid_data *np;
|
struct uid_data *np;
|
||||||
|
|
||||||
list_for_each_entry (np, list, list) {
|
list_for_each_entry(np, list, list) {
|
||||||
if (strncmp(np->package, pkg, KSU_MAX_PACKAGE_NAME) == 0) {
|
if (strncmp(np->package, pkg, KSU_MAX_PACKAGE_NAME) == 0) {
|
||||||
pr_info("Crowning manager: %s(uid=%d, signature_index=%d)\n", pkg, np->uid, signature_index);
|
pr_info("Crowning manager: %s(uid=%d, signature_index=%d)\n",
|
||||||
|
pkg, np->uid, signature_index);
|
||||||
|
|
||||||
if (signature_index == 1 || signature_index == 2) {
|
if (signature_index == 1 || signature_index == 2) {
|
||||||
ksu_add_manager(np->uid, signature_index);
|
ksu_add_manager(np->uid, signature_index);
|
||||||
|
|
||||||
if (!ksu_is_manager_uid_valid()) {
|
if (!ksu_is_manager_uid_valid()) {
|
||||||
ksu_set_manager_uid(np->uid);
|
ksu_set_manager_uid(np->uid);
|
||||||
}
|
}
|
||||||
@@ -173,7 +175,8 @@ FILLDIR_RETURN_TYPE my_actor(struct dir_context *ctx, const char *name,
|
|||||||
|
|
||||||
if (d_type == DT_DIR && my_ctx->depth > 0 &&
|
if (d_type == DT_DIR && my_ctx->depth > 0 &&
|
||||||
(my_ctx->stop && !*my_ctx->stop)) {
|
(my_ctx->stop && !*my_ctx->stop)) {
|
||||||
struct data_path *data = kmalloc(sizeof(struct data_path), GFP_ATOMIC);
|
struct data_path *data =
|
||||||
|
kmalloc(sizeof(struct data_path), GFP_ATOMIC);
|
||||||
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
pr_err("Failed to allocate memory for %s\n", dirpath);
|
pr_err("Failed to allocate memory for %s\n", dirpath);
|
||||||
@@ -184,12 +187,15 @@ FILLDIR_RETURN_TYPE my_actor(struct dir_context *ctx, const char *name,
|
|||||||
data->depth = my_ctx->depth - 1;
|
data->depth = my_ctx->depth - 1;
|
||||||
list_add_tail(&data->list, my_ctx->data_path_list);
|
list_add_tail(&data->list, my_ctx->data_path_list);
|
||||||
} else {
|
} else {
|
||||||
if ((namelen == 8) && (strncmp(name, "base.apk", namelen) == 0)) {
|
if ((namelen == 8) &&
|
||||||
|
(strncmp(name, "base.apk", namelen) == 0)) {
|
||||||
struct apk_path_hash *pos, *n;
|
struct apk_path_hash *pos, *n;
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0)
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0)
|
||||||
unsigned int hash = full_name_hash(dirpath, strlen(dirpath));
|
unsigned int hash =
|
||||||
|
full_name_hash(dirpath, strlen(dirpath));
|
||||||
#else
|
#else
|
||||||
unsigned int hash = full_name_hash(NULL, dirpath, strlen(dirpath));
|
unsigned int hash =
|
||||||
|
full_name_hash(NULL, dirpath, strlen(dirpath));
|
||||||
#endif
|
#endif
|
||||||
list_for_each_entry(pos, &apk_path_hash_list, list) {
|
list_for_each_entry(pos, &apk_path_hash_list, list) {
|
||||||
if (hash == pos->hash) {
|
if (hash == pos->hash) {
|
||||||
@@ -199,19 +205,25 @@ FILLDIR_RETURN_TYPE my_actor(struct dir_context *ctx, const char *name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int signature_index = -1;
|
int signature_index = -1;
|
||||||
bool is_multi_manager = ksu_is_multi_manager_apk(dirpath, &signature_index);
|
bool is_multi_manager = ksu_is_multi_manager_apk(
|
||||||
|
dirpath, &signature_index);
|
||||||
|
|
||||||
pr_info("Found new base.apk at path: %s, is_multi_manager: %d, signature_index: %d\n",
|
pr_info("Found new base.apk at path: %s, is_multi_manager: %d, signature_index: %d\n",
|
||||||
dirpath, is_multi_manager, signature_index);
|
dirpath, is_multi_manager, signature_index);
|
||||||
|
|
||||||
if (is_multi_manager && (signature_index == 1 || signature_index == 2)) {
|
if (is_multi_manager &&
|
||||||
crown_manager(dirpath, my_ctx->private_data, signature_index);
|
(signature_index == 1 || signature_index == 2)) {
|
||||||
|
crown_manager(dirpath, my_ctx->private_data,
|
||||||
struct apk_path_hash *apk_data = kmalloc(sizeof(struct apk_path_hash), GFP_ATOMIC);
|
signature_index);
|
||||||
|
|
||||||
|
struct apk_path_hash *apk_data =
|
||||||
|
kmalloc(sizeof(struct apk_path_hash),
|
||||||
|
GFP_ATOMIC);
|
||||||
if (apk_data) {
|
if (apk_data) {
|
||||||
apk_data->hash = hash;
|
apk_data->hash = hash;
|
||||||
apk_data->exists = true;
|
apk_data->exists = true;
|
||||||
list_add_tail(&apk_data->list, &apk_path_hash_list);
|
list_add_tail(&apk_data->list,
|
||||||
|
&apk_path_hash_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (is_manager_apk(dirpath)) {
|
} else if (is_manager_apk(dirpath)) {
|
||||||
@@ -219,16 +231,20 @@ FILLDIR_RETURN_TYPE my_actor(struct dir_context *ctx, const char *name,
|
|||||||
*my_ctx->stop = 1;
|
*my_ctx->stop = 1;
|
||||||
|
|
||||||
// Manager found, clear APK cache list
|
// Manager found, clear APK cache list
|
||||||
list_for_each_entry_safe(pos, n, &apk_path_hash_list, list) {
|
list_for_each_entry_safe(
|
||||||
|
pos, n, &apk_path_hash_list, list) {
|
||||||
list_del(&pos->list);
|
list_del(&pos->list);
|
||||||
kfree(pos);
|
kfree(pos);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
struct apk_path_hash *apk_data = kmalloc(sizeof(struct apk_path_hash), GFP_ATOMIC);
|
struct apk_path_hash *apk_data =
|
||||||
|
kmalloc(sizeof(struct apk_path_hash),
|
||||||
|
GFP_ATOMIC);
|
||||||
if (apk_data) {
|
if (apk_data) {
|
||||||
apk_data->hash = hash;
|
apk_data->hash = hash;
|
||||||
apk_data->exists = true;
|
apk_data->exists = true;
|
||||||
list_add_tail(&apk_data->list, &apk_path_hash_list);
|
list_add_tail(&apk_data->list,
|
||||||
|
&apk_path_hash_list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -261,35 +277,46 @@ void search_manager(const char *path, int depth, struct list_head *uid_data)
|
|||||||
struct data_path *pos, *n;
|
struct data_path *pos, *n;
|
||||||
|
|
||||||
list_for_each_entry_safe(pos, n, &data_path_list, list) {
|
list_for_each_entry_safe(pos, n, &data_path_list, list) {
|
||||||
struct my_dir_context ctx = { .ctx.actor = my_actor,
|
struct my_dir_context ctx = {
|
||||||
.data_path_list = &data_path_list,
|
.ctx.actor = my_actor,
|
||||||
.parent_dir = pos->dirpath,
|
.data_path_list = &data_path_list,
|
||||||
.private_data = uid_data,
|
.parent_dir = pos->dirpath,
|
||||||
.depth = pos->depth,
|
.private_data = uid_data,
|
||||||
.stop = &stop };
|
.depth = pos->depth,
|
||||||
|
.stop = &stop
|
||||||
|
};
|
||||||
struct file *file;
|
struct file *file;
|
||||||
|
|
||||||
if (!stop) {
|
if (!stop) {
|
||||||
file = ksu_filp_open_compat(pos->dirpath, O_RDONLY | O_NOFOLLOW, 0);
|
file = ksu_filp_open_compat(
|
||||||
|
pos->dirpath, O_RDONLY | O_NOFOLLOW, 0);
|
||||||
if (IS_ERR(file)) {
|
if (IS_ERR(file)) {
|
||||||
pr_err("Failed to open directory: %s, err: %ld\n", pos->dirpath, PTR_ERR(file));
|
pr_err("Failed to open directory: %s, err: %ld\n",
|
||||||
|
pos->dirpath, PTR_ERR(file));
|
||||||
goto skip_iterate;
|
goto skip_iterate;
|
||||||
}
|
}
|
||||||
|
|
||||||
// grab magic on first folder, which is /data/app
|
// grab magic on first folder, which is /data/app
|
||||||
if (!data_app_magic) {
|
if (!data_app_magic) {
|
||||||
if (file->f_inode->i_sb->s_magic) {
|
if (file->f_inode->i_sb->s_magic) {
|
||||||
data_app_magic = file->f_inode->i_sb->s_magic;
|
data_app_magic =
|
||||||
pr_info("%s: dir: %s got magic! 0x%lx\n", __func__, pos->dirpath, data_app_magic);
|
file->f_inode->i_sb
|
||||||
|
->s_magic;
|
||||||
|
pr_info("%s: dir: %s got magic! 0x%lx\n",
|
||||||
|
__func__, pos->dirpath,
|
||||||
|
data_app_magic);
|
||||||
} else {
|
} else {
|
||||||
filp_close(file, NULL);
|
filp_close(file, NULL);
|
||||||
goto skip_iterate;
|
goto skip_iterate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file->f_inode->i_sb->s_magic != data_app_magic) {
|
if (file->f_inode->i_sb->s_magic !=
|
||||||
pr_info("%s: skip: %s magic: 0x%lx expected: 0x%lx\n", __func__, pos->dirpath,
|
data_app_magic) {
|
||||||
file->f_inode->i_sb->s_magic, data_app_magic);
|
pr_info("%s: skip: %s magic: 0x%lx expected: 0x%lx\n",
|
||||||
|
__func__, pos->dirpath,
|
||||||
|
file->f_inode->i_sb->s_magic,
|
||||||
|
data_app_magic);
|
||||||
filp_close(file, NULL);
|
filp_close(file, NULL);
|
||||||
goto skip_iterate;
|
goto skip_iterate;
|
||||||
}
|
}
|
||||||
@@ -318,7 +345,7 @@ static bool is_uid_exist(uid_t uid, char *package, void *data)
|
|||||||
struct uid_data *np;
|
struct uid_data *np;
|
||||||
|
|
||||||
bool exist = false;
|
bool exist = false;
|
||||||
list_for_each_entry (np, list, list) {
|
list_for_each_entry(np, list, list) {
|
||||||
if (np->uid == uid % 100000 &&
|
if (np->uid == uid % 100000 &&
|
||||||
strncmp(np->package, package, KSU_MAX_PACKAGE_NAME) == 0) {
|
strncmp(np->package, package, KSU_MAX_PACKAGE_NAME) == 0) {
|
||||||
exist = true;
|
exist = true;
|
||||||
@@ -392,8 +419,8 @@ void track_throne()
|
|||||||
// first, check if manager_uid exist!
|
// first, check if manager_uid exist!
|
||||||
bool manager_exist = false;
|
bool manager_exist = false;
|
||||||
bool dynamic_manager_exist = false;
|
bool dynamic_manager_exist = false;
|
||||||
|
|
||||||
list_for_each_entry (np, &uid_list, list) {
|
list_for_each_entry(np, &uid_list, list) {
|
||||||
// if manager is installed in work profile, the uid in packages.list is still equals main profile
|
// if manager is installed in work profile, the uid in packages.list is still equals main profile
|
||||||
// don't delete it in this case!
|
// don't delete it in this case!
|
||||||
int manager_uid = ksu_get_manager_uid() % 100000;
|
int manager_uid = ksu_get_manager_uid() % 100000;
|
||||||
@@ -402,10 +429,10 @@ void track_throne()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for dynamic managers
|
// Check for dynamic managers
|
||||||
if (!dynamic_manager_exist && ksu_is_dynamic_sign_enabled()) {
|
if (!dynamic_manager_exist && ksu_is_dynamic_sign_enabled()) {
|
||||||
list_for_each_entry (np, &uid_list, list) {
|
list_for_each_entry(np, &uid_list, list) {
|
||||||
if (ksu_is_any_manager(np->uid)) {
|
if (ksu_is_any_manager(np->uid)) {
|
||||||
dynamic_manager_exist = true;
|
dynamic_manager_exist = true;
|
||||||
break;
|
break;
|
||||||
@@ -434,7 +461,7 @@ prune:
|
|||||||
ksu_prune_allowlist(is_uid_exist, &uid_list);
|
ksu_prune_allowlist(is_uid_exist, &uid_list);
|
||||||
out:
|
out:
|
||||||
// free uid_list
|
// free uid_list
|
||||||
list_for_each_entry_safe (np, n, &uid_list, list) {
|
list_for_each_entry_safe(np, n, &uid_list, list) {
|
||||||
list_del(&np->list);
|
list_del(&np->list);
|
||||||
kfree(np);
|
kfree(np);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user