Chromium Code Reviews| Index: build/android/pylib/android_commands.py |
| diff --git a/build/android/pylib/android_commands.py b/build/android/pylib/android_commands.py |
| index b734d17597838541dbda1a12527f05949a2d9eac..1b315a454e257a34cfea187509e5ce427eff91ca 100644 |
| --- a/build/android/pylib/android_commands.py |
| +++ b/build/android/pylib/android_commands.py |
| @@ -297,6 +297,7 @@ class AndroidCommands(object): |
| 'command': None, |
| 'cached': False, |
| } |
| + self._protected_file_access_method = None |
| @property |
| def system_properties(self): |
| @@ -1103,29 +1104,72 @@ class AndroidCommands(object): |
| def RunShellCommandWithSU(self, command, timeout_time=20, log_result=False): |
| return self.RunShellCommand('su -c %s' % command, timeout_time, log_result) |
| + ACCESS_METHOD_NO_ACCESS = "no access" |
|
Sami
2014/04/28 12:55:49
nit: Start with underscore since these probably do
jbudorick
2014/04/28 14:22:52
+1 for using numeric constants.
pasko
2014/04/29 09:42:32
Renaming: Done. Most votes are for numeric constan
pasko
2014/04/29 09:42:32
Done.
|
| + ACCESS_METHOD_AS_ROOT = "as root" |
| + ACCESS_METHOD_WITH_SU = "with su" |
|
bulach
2014/04/28 12:21:48
nit: use single quotes
pasko
2014/04/29 09:42:32
thanks, changed to numeric constants
|
| + |
| def CanAccessProtectedFileContents(self): |
| - """Returns True if Get/SetProtectedFileContents would work via "su". |
| + """Returns True if Get/SetProtectedFileContents would work via "su" or adb |
| + shell running as root. |
| Devices running user builds don't have adb root, but may provide "su" which |
| can be used for accessing protected files. |
| """ |
| - r = self.RunShellCommandWithSU('cat /dev/null') |
| - return r == [] or r[0].strip() == '' |
| + return (self._ProtectedFileAccessMethod() != |
| + AndroidCommands.ACCESS_METHOD_NO_ACCESS) |
| + |
| + def _ProtectedFileAccessMethod(self): |
| + """Tests for the best method to access protected files on the device. |
| + |
| + Returns: |
| + ACCESS_METHOD_NO_ACCESS: if protected files cannot be accessed |
| + ACCESS_METHOD_AS_ROOT: if the adb shell has root privileges |
| + ACCESS_METHOD_WITH_SU: if the 'su' command properly works on the device |
| + """ |
| + if self._protected_file_access_method is not None: |
|
bulach
2014/04/28 12:21:48
nit: s/is not None//
pasko
2014/04/29 09:42:32
I changed this to numeric constants, so to disting
|
| + return self._protected_file_access_method |
| + |
| + def AuxContentsLookReal(contents): |
|
bulach
2014/04/28 12:21:48
nit: how about "_IsValidContents" ?
jbudorick
2014/04/28 14:22:52
Why check the output rather than the return code?
pasko
2014/04/29 09:42:32
I changed this to IsValidAuxContents(). Since the
pasko
2014/04/29 09:42:32
This is mainly because RunShellCommand() and RunSh
|
| + # The leading 4 or 8-bytes of auxv vector is a_type. There are not many |
| + # reserved a_type values, hence byte 2 must always be '\0' for a realistic |
| + # auxv. See /usr/include/elf.h. |
| + return len(contents) > 0 and (contents[0][2] == '\0') |
| + |
| + self._protected_file_access_method = AndroidCommands.ACCESS_METHOD_NO_ACCESS |
| + |
| + # Get contents of the auxv vector for the init(8) process from a small |
| + # binary file that always exists on a linux and is always read-protected. |
| + contents = self.RunShellCommand('cat /proc/1/auxv') |
|
Sami
2014/04/28 12:55:49
Neat trick :)
pasko
2014/04/29 09:42:32
thnx)
|
| + if AuxContentsLookReal(contents): |
| + # Protected data is available without SU, hence adb is running as root. |
| + self._protected_file_access_method = AndroidCommands.ACCESS_METHOD_AS_ROOT |
|
jbudorick
2014/04/28 14:22:52
FWIW, I've been toying with doing the as_root chec
pasko
2014/04/29 09:42:32
I did not know about this property :)
|
| + else: |
| + contents = self.RunShellCommandWithSU('cat /proc/1/auxv') |
| + if AuxContentsLookReal(contents): |
| + # Protected data is available when asked with SU. |
| + self._protected_file_access_method = ( |
| + AndroidCommands.ACCESS_METHOD_WITH_SU) |
| + return self._protected_file_access_method |
|
Sami
2014/04/28 12:55:49
Set access method to ACCESS_METHOD_NO_ACCESS here?
pasko
2014/04/29 09:42:32
I've set it above. If I wanted to move it here fro
|
| def GetProtectedFileContents(self, filename): |
| """Gets contents from the protected file specified by |filename|. |
| - This is less efficient than GetFileContents, but will work for protected |
| - files and device files. |
| + This is potentially less efficient than GetFileContents. |
| """ |
| - # Run the script as root |
| - return self.RunShellCommandWithSU('cat "%s" 2> /dev/null' % filename) |
| + command = 'cat "%s" 2> /dev/null' % filename |
| + access_method = self._ProtectedFileAccessMethod() |
| + if access_method == AndroidCommands.ACCESS_METHOD_WITH_SU: |
| + return self.RunShellCommandWithSU(command) |
| + elif access_method == AndroidCommands.ACCESS_METHOD_AS_ROOT: |
| + return self.RunShellCommand(command) |
| + else: |
| + logging.warning('Could not access protected file: %s' % filename) |
| + return [] |
|
bulach
2014/04/28 12:21:48
now, if we're going to fix this once and for all :
jbudorick
2014/04/28 14:22:52
I'm ok with this idea in general. I think implemen
pasko
2014/04/29 09:42:32
I'm +1 to jbudorick@ here: it will likely break in
|
| def SetProtectedFileContents(self, filename, contents): |
| """Writes |contents| to the protected file specified by |filename|. |
| - This is less efficient than SetFileContents, but will work for protected |
| - files and device files. |
| + This is less efficient than SetFileContents. |
| """ |
| temp_file = self._GetDeviceTempFileName(AndroidCommands._TEMP_FILE_BASE_FMT) |
| temp_script = self._GetDeviceTempFileName( |
| @@ -1135,8 +1179,16 @@ class AndroidCommands(object): |
| self.SetFileContents(temp_file, contents) |
| # Create a script to copy the file contents to its final destination |
| self.SetFileContents(temp_script, 'cat %s > %s' % (temp_file, filename)) |
| - # Run the script as root |
| - self.RunShellCommandWithSU('sh %s' % temp_script) |
| + |
| + command = 'sh %s' % temp_script |
| + access_method = self._ProtectedFileAccessMethod() |
|
Sami
2014/04/28 12:55:49
This could be a little cleaner if access_method wa
pasko
2014/04/29 09:42:32
Do you suggest to check for None and call otherwis
|
| + if access_method == AndroidCommands.ACCESS_METHOD_WITH_SU: |
| + return self.RunShellCommandWithSU(command) |
| + elif access_method == AndroidCommands.ACCESS_METHOD_AS_ROOT: |
| + return self.RunShellCommand(command) |
| + else: |
| + logging.warning('Could not set contents of protected file: %s' % filename) |
|
bulach
2014/04/28 12:21:48
ditto.
|
| + |
| # And remove the temporary files |
| self.RunShellCommand('rm ' + temp_file) |
| self.RunShellCommand('rm ' + temp_script) |