• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/bin/bash
2
3# This script uses some heuristics to suggest potential ways to clean up SELinux policy.
4# As these are heuristics, not everything it outputs is an error.
5# It is better to run this on device-specific policy rather than core policy.
6# It requires a device connected to adb.
7# Usage:
8#   ./sepolicy_cleanup_check.sh <sepolicy source path> [serial]
9
10if [[ $# -lt 1 ]]; then
11  echo "Usage: $0 <sepolicy source path> [serial]"
12  exit
13fi
14
15sedir=$1
16shift
17
18adb_cmd="adb"
19if [[ $# -eq 1 ]]; then
20  adb_cmd="$adb_cmd -s $1"
21  shift
22fi
23
24$adb_cmd shell id &>/dev/null
25if [[ $? -ne 0 ]]; then
26  echo "Please plug in a device and/or specify a serial"
27  adb devices
28  exit
29fi
30
31echo "Warning: this file uses heuristics, so all of its outputs are not necessarily errors."
32echo "For example, when run on core policy, it will likely find many things that do not exist on a given device but might exist on others."
33
34echo
35echo "Scanning for labels that are not assigned to any files."
36# Find all types.
37grep -r "^type " --exclude=\*.go $sedir --exclude=\*_macros | sed 's/^.*:.*type \([^,]*\)*.*$/\1/' | sort | uniq | while read -r type; do
38  # Find types that are not referenced in *_contexts.
39  if [[ `find $sedir -name "*_contexts" -not -path "*prebuilts*" -exec grep $type '{}' \; |wc -l` -eq 0 ]]; then
40    echo "None for $type"
41    grep -r $type --exclude-dir=prebuilts --exclude=\*.cil $sedir
42  fi
43done
44
45echo
46echo "Scanning for executables that don't exist."
47# Find executable types.
48grep -r "^type .*exec_type" --exclude=\*.go $sedir | sed 's/^.*:.*type \([^,]*\)*.*$/\1/' | sort | uniq | while read -r type; do
49  path_line=`grep -r $type --include=\*_contexts $sedir`
50  # Note that this only examines one entry, even if multiple executables have the same label.
51  # But the file_contexts scan below covers that case.
52  path=`echo $path_line | sed 's/^.*:[^\/]*\([^ ]*\) .*$/\1/'`
53  # Replace character classes and + with *.
54  path=`echo $path | sed 's/\[[^]]*\]/*/' | sed 's/+/*/'`
55  # Check whether the file exists.
56  if [ -n "`$adb_cmd shell ls -lZ $path < /dev/null |& grep "No such file or directory"`" ]; then
57    echo "$path does not exist"
58  fi
59done
60
61echo
62echo "Scanning genfs_contexts for files that don't exist."
63# Find files in genfs_contexts.
64find $sedir -name genfs_contexts -exec grep "^genfscon " '{}' \; | cut -d' ' -f2,3 | sort | uniq | while read -r file_line; do
65  # Extract the full path.
66  path=`echo $file_line | sed 's/rootfs //' | sed 's/sysfs /\/sys/' | sed 's/proc /\/proc/' | sed 's/debugfs /\/sys\/kernel\/debug/' | sed 's/tracefs /\/sys\/kernel\/debug\/tracing/'`
67  # Skip things whose prefix we don't recognize.
68  if [[ $path = *" "* ]]; then
69    continue
70  fi
71  # Check whether the file exists.
72  if [ -n "`$adb_cmd shell ls -lZ $path < /dev/null |& grep "No such file or directory"`" ]; then
73    echo "$path does not exist"
74  fi
75done
76
77echo
78echo "Scanning file_contexts for files that don't exist."
79# Find files in file_contexts.
80find $sedir -name file_contexts -not -path "*prebuilts*" -exec grep "^/" '{}' \; | cut -d' ' -f1 | cut -f1 | sort | uniq | while read -r path; do
81  # Replace (/.*)? with *
82  # Replace (64)? with ??
83  # Replace (vendor|system/vendor) with /vendor
84  # Replace character classes and + with *.
85  # Replace captures.
86  # Replace \. with .
87  # Replace .* with *
88  # Replace ** with *
89  path=`echo "$path" | sed 's/(\/\.\*)?$//' | sed 's/(64)?/??/' | sed 's/\(vendor|system\/vendor\)/vendor/' | sed 's/\[[^]]*\]/*/' | sed 's/+/*/' | sed 's/(\([^)]*\))/\1/' | sed 's/\\\././g' | sed 's/\.\*/\*/g' | sed 's/\*\*/\*/g'`
90  # Check whether the file exists.
91  if [ -n "`$adb_cmd shell ls -lZ "$path" < /dev/null |& grep "No such file or directory"`" ]; then
92    echo "$path does not exist"
93  fi
94done
95
96echo
97echo "Scanning for rules that are defined in the wrong file."
98echo "That is, rules that do not contain the name of the file."
99# Find .te files.
100find $sedir -name "*.te" -not -path "*prebuilts*" | while read -r file; do
101  filename=`basename $file`
102  filename="${filename%.*}"
103  # Look for lines that don't have the filename in them.
104  lines=$(grep "^[^# }']" $file | grep -v $filename | grep -v "^userdebug_or_eng(\`$" | grep -v "^type " | grep "[,)]" | grep -v "^define(")
105  if [[ -n "$lines" ]]; then
106    echo "$file:"
107    echo "$lines"
108  fi
109done
110
111echo
112echo "Scanning for labels in file_contexts that do not escape '.' properly."
113find $sedir -name file_contexts -not -path "*prebuilts*" -exec grep -H "^[^#].*[^\\]\.[^*]" '{}' \;
114
115echo
116echo "Scanning for rules that use the wrong file/dir macros."
117grep -r ":file.*_dir_perms" --exclude=\*_macros $sedir
118grep -r ":dir.*_file_perms" --exclude=\*_macros $sedir
119