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:
Helium_Studio
2025-08-22 14:02:20 +08:00
committed by GitHub
parent fe472057b1
commit ce58519e66
31 changed files with 1542 additions and 1131 deletions

View File

@@ -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

View File

@@ -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);
} }

View File

@@ -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);

View File

@@ -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,7 +137,8 @@ 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;
@@ -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;
} }
@@ -331,7 +335,8 @@ clean:
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);
} }

View File

@@ -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 (ret == 0 && config.operation == DYNAMIC_SIGN_OP_GET) {
if (copy_to_user((void __user *)arg3, &config, sizeof(config))) { if (copy_to_user((void __user *)arg3, &config,
pr_err("copy dynamic sign config back failed\n"); sizeof(config))) {
return 0; pr_err("copy dynamic sign config back failed\n");
} return 0;
} }
}
if (ret == 0) { if (ret == 0) {
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) { if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
pr_err("dynamic_sign: prctl reply error\n"); 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
@@ -391,7 +399,8 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
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)

View File

@@ -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 // Find free slot for new manager
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) {
active_managers[i].uid = uid; active_managers[i].uid = uid;
active_managers[i].signature_index = signature_index; active_managers[i].signature_index = signature_index;
active_managers[i].is_active = true; active_managers[i].is_active = true;
spin_unlock_irqrestore(&managers_lock, flags); spin_unlock_irqrestore(&managers_lock, flags);
pr_info("Added manager uid=%d, signature_index=%d\n", uid, signature_index); pr_info("Added manager uid=%d, signature_index=%d\n",
return; uid, signature_index);
} return;
} }
}
spin_unlock_irqrestore(&managers_lock, flags); spin_unlock_irqrestore(&managers_lock, flags);
pr_warn("Failed to add manager, no free slots\n"); 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); spin_unlock_irqrestore(&managers_lock, flags);
return is_manager; 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); spin_unlock_irqrestore(&managers_lock, flags);
return signature_index; 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) { if (!info) {
return -EINVAL; return -EINVAL;
} }
// Add traditional manager first // Add traditional manager first
if (ksu_manager_uid != KSU_INVALID_UID && count < 2) { if (ksu_manager_uid != KSU_INVALID_UID && count < 2) {
info->managers[count].uid = ksu_manager_uid; info->managers[count].uid = ksu_manager_uid;
info->managers[count].signature_index = 0; info->managers[count].signature_index = 0;
count++; count++;
} }
// Add dynamic managers // Add dynamic managers
if (ksu_is_dynamic_sign_enabled()) { if (ksu_is_dynamic_sign_enabled()) {
spin_lock_irqsave(&managers_lock, flags); spin_lock_irqsave(&managers_lock, flags);
for (i = 0; i < MAX_MANAGERS && count < 2; i++) { for (i = 0; i < MAX_MANAGERS && count < 2; i++) {
if (active_managers[i].is_active) { if (active_managers[i].is_active) {
info->managers[count].uid = active_managers[i].uid; info->managers[count].uid =
info->managers[count].signature_index = active_managers[i].signature_index; active_managers[i].uid;
count++; info->managers[count].signature_index =
} active_managers[i].signature_index;
} count++;
}
}
spin_unlock_irqrestore(&managers_lock, flags); spin_unlock_irqrestore(&managers_lock, flags);
} }
info->count = count; info->count = count;
return 0; 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) { if (!config) {
return -EINVAL; return -EINVAL;
} }
switch (config->operation) { switch (config->operation) {
case DYNAMIC_SIGN_OP_SET: case DYNAMIC_SIGN_OP_SET:
if (config->size < 0x100 || config->size > 0x1000) { if (config->size < 0x100 || config->size > 0x1000) {
pr_err("invalid size: 0x%x\n", config->size); pr_err("invalid size: 0x%x\n", config->size);
return -EINVAL; return -EINVAL;
} }
if (strlen(config->hash) != 64) { if (strlen(config->hash) != 64) {
pr_err("invalid hash length: %zu\n", strlen(config->hash)); pr_err("invalid hash length: %zu\n",
return -EINVAL; strlen(config->hash));
} return -EINVAL;
}
// Validate hash format // Validate hash format
for (i = 0; i < 64; i++) { for (i = 0; i < 64; i++) {
char c = config->hash[i]; char c = config->hash[i];
if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f'))) { if (!((c >= '0' && c <= '9') ||
pr_err("invalid hash character at position %d: %c\n", i, c); (c >= 'a' && c <= 'f'))) {
return -EINVAL; pr_err("invalid hash character at position %d: %c\n",
} i, c);
} return -EINVAL;
}
}
spin_lock_irqsave(&dynamic_sign_lock, flags); spin_lock_irqsave(&dynamic_sign_lock, flags);
dynamic_sign.size = config->size; dynamic_sign.size = config->size;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
strscpy(dynamic_sign.hash, config->hash, sizeof(dynamic_sign.hash)); strscpy(dynamic_sign.hash, config->hash,
sizeof(dynamic_sign.hash));
#else #else
strlcpy(dynamic_sign.hash, config->hash, sizeof(dynamic_sign.hash)); strlcpy(dynamic_sign.hash, config->hash,
sizeof(dynamic_sign.hash));
#endif #endif
dynamic_sign.is_set = 1; dynamic_sign.is_set = 1;
spin_unlock_irqrestore(&dynamic_sign_lock, flags); spin_unlock_irqrestore(&dynamic_sign_lock, flags);
persistent_dynamic_sign(); persistent_dynamic_sign();
pr_info("dynamic sign updated: size=0x%x, hash=%.16s... (multi-manager enabled)\n", pr_info("dynamic sign updated: size=0x%x, hash=%.16s... (multi-manager enabled)\n",
config->size, config->hash); config->size, config->hash);
break; break;
case DYNAMIC_SIGN_OP_GET: case DYNAMIC_SIGN_OP_GET:
spin_lock_irqsave(&dynamic_sign_lock, flags); spin_lock_irqsave(&dynamic_sign_lock, flags);
if (dynamic_sign.is_set) { if (dynamic_sign.is_set) {
config->size = dynamic_sign.size; config->size = dynamic_sign.size;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
strscpy(config->hash, dynamic_sign.hash, sizeof(config->hash)); strscpy(config->hash, dynamic_sign.hash,
sizeof(config->hash));
#else #else
strlcpy(config->hash, dynamic_sign.hash, sizeof(config->hash)); strlcpy(config->hash, dynamic_sign.hash,
sizeof(config->hash));
#endif #endif
ret = 0; ret = 0;
} else { } else {
ret = -ENODATA; ret = -ENODATA;
} }
spin_unlock_irqrestore(&dynamic_sign_lock, flags); spin_unlock_irqrestore(&dynamic_sign_lock, flags);
break; break;
case DYNAMIC_SIGN_OP_CLEAR: case DYNAMIC_SIGN_OP_CLEAR:
spin_lock_irqsave(&dynamic_sign_lock, flags); spin_lock_irqsave(&dynamic_sign_lock, flags);
dynamic_sign.size = 0x300; dynamic_sign.size = 0x300;
strcpy(dynamic_sign.hash, "0000000000000000000000000000000000000000000000000000000000000000"); strcpy(dynamic_sign.hash,
dynamic_sign.is_set = 0; "0000000000000000000000000000000000000000000000000000000000000000");
spin_unlock_irqrestore(&dynamic_sign_lock, flags); dynamic_sign.is_set = 0;
spin_unlock_irqrestore(&dynamic_sign_lock, flags);
// Clear only dynamic managers, preserve default manager // Clear only dynamic managers, preserve default manager
clear_dynamic_manager(); clear_dynamic_manager();
// Clear file using the same method as save // Clear file using the same method as save
clear_dynamic_sign_file(); clear_dynamic_sign_file();
pr_info("Dynamic sign config cleared (multi-manager disabled)\n"); pr_info("Dynamic sign config cleared (multi-manager disabled)\n");
break; break;
default: default:
pr_err("Invalid dynamic sign operation: %d\n", config->operation); pr_err("Invalid dynamic sign operation: %d\n",
return -EINVAL; config->operation);
} return -EINVAL;
}
return ret; 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_save_dynamic_sign_work, do_save_dynamic_sign);
INIT_WORK(&ksu_load_dynamic_sign_work, do_load_dynamic_sign); INIT_WORK(&ksu_load_dynamic_sign_work, do_load_dynamic_sign);
INIT_WORK(&ksu_clear_dynamic_sign_work, do_clear_dynamic_sign); INIT_WORK(&ksu_clear_dynamic_sign_work, do_clear_dynamic_sign);
// Initialize manager slots // Initialize manager slots
for (i = 0; i < MAX_MANAGERS; i++) { for (i = 0; i < MAX_MANAGERS; i++) {
active_managers[i].is_active = false; active_managers[i].is_active = false;
} }
ksu_load_dynamic_sign(); ksu_load_dynamic_sign();
pr_info("Dynamic sign initialized with conditional multi-manager support\n"); 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;
}
spin_unlock_irqrestore(&dynamic_sign_lock, flags);
return valid; return valid;
} }

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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);

View File

@@ -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

View File

@@ -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); strncpy_from_user((char *)&kernel_load_path,
if(arg4 != 0) { (const char __user *)arg3, 255);
strncpy_from_user((char*)&kernel_args_buffer, (const char __user *)arg4, 255); if (arg4 != 0) {
} strncpy_from_user((char *)&kernel_args_buffer,
sukisu_kpm_load_module_path((const char*)&kernel_load_path, (const char*) &kernel_args_buffer, NULL, (void __user*) arg5); (const char __user *)arg4, 255);
} else if(arg2 == SUKISU_KPM_UNLOAD) { }
char kernel_name_buffer[256] = { 0 }; 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) { 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_unload_module((const char*) &kernel_name_buffer, NULL, (void __user*) arg5); (const char __user *)arg3, 255);
} else if(arg2 == SUKISU_KPM_NUM) { sukisu_kpm_unload_module((const char *)&kernel_name_buffer,
sukisu_kpm_num((void __user*) arg5); NULL, (void __user *)arg5);
} else if(arg2 == SUKISU_KPM_INFO) { } else if (arg2 == SUKISU_KPM_NUM) {
char kernel_name_buffer[256] = { 0 }; sukisu_kpm_num((void __user *)arg5);
} else if (arg2 == SUKISU_KPM_INFO) {
char kernel_name_buffer[256] = { 0 };
if(arg3 == 0 || arg4 == 0) { if (arg3 == 0 || arg4 == 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_info((const char *)&kernel_name_buffer,
sukisu_kpm_list((char __user*) arg3, (unsigned int) arg4, (void __user*) arg5); (char __user *)arg4, (void __user *)arg5);
} else if(arg2 == SUKISU_KPM_VERSION) { } else if (arg2 == SUKISU_KPM_LIST) {
sukisu_kpm_version((char __user*) arg3, (unsigned int) arg4, (void __user*) arg5); sukisu_kpm_list((char __user *)arg3, (unsigned int)arg4,
} else if(arg2 == SUKISU_KPM_CONTROL) { (void __user *)arg5);
sukisu_kpm_control((char __user*) arg3, (char __user*) arg4, (void __user*) arg5); } else if (arg2 == SUKISU_KPM_VERSION) {
} sukisu_kpm_version((char __user *)arg3, (unsigned int)arg4,
return 0; (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);

View File

@@ -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控制代码

View File

@@ -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);

View File

@@ -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

View File

@@ -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();

View File

@@ -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 {

View File

@@ -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);
} }

View File

@@ -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 */

View File

@@ -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,7 +573,7 @@ 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];
@@ -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

View File

@@ -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()

View File

@@ -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 */

View File

@@ -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;
} }

View File

@@ -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;
@@ -78,7 +80,7 @@ bool getenforce(void)
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

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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));

View File

@@ -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,9 +85,10 @@ 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);
@@ -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,
signature_index);
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);
} }
} 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;
@@ -393,7 +420,7 @@ void track_throne()
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;
@@ -405,7 +432,7 @@ void track_throne()
// 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);
} }