mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1214812 - [mozdevice] - adb.py, adb_android.py - if possible always run adbd as root, set SELinux to Permissive, r=gbrown.
This commit is contained in:
parent
c665dbc82b
commit
1a98f76852
@ -2,7 +2,6 @@
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
# You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
from abc import ABCMeta, abstractmethod
|
||||
import os
|
||||
import posixpath
|
||||
import re
|
||||
@ -11,6 +10,8 @@ import tempfile
|
||||
import time
|
||||
import traceback
|
||||
|
||||
from abc import ABCMeta, abstractmethod
|
||||
|
||||
|
||||
class ADBProcess(object):
|
||||
"""ADBProcess encapsulates the data related to executing the adb process."""
|
||||
@ -535,49 +536,58 @@ class ADBDevice(ADBCommand):
|
||||
self._have_su = False
|
||||
self._have_android_su = False
|
||||
|
||||
uid = 'uid=0'
|
||||
# Is shell already running as root?
|
||||
# Catch exceptions due to the potential for segfaults
|
||||
# calling su when using an improperly rooted device.
|
||||
try:
|
||||
if self.shell_output("id").find(uid) != -1:
|
||||
self._have_root_shell = True
|
||||
except ADBError:
|
||||
self._logger.debug("Check for root shell failed")
|
||||
|
||||
# Note this check to see if adbd is running is performed on
|
||||
# the device in the state it exists in when the ADBDevice is
|
||||
# initialized. It may be the case that it has been manipulated
|
||||
# since its last boot and that its current state does not
|
||||
# match the state the device will have immediately after a
|
||||
# reboot. For example, if adb root was called manually prior
|
||||
# to ADBDevice being initialized, then self._have_root_shell
|
||||
# will not reflect the state of the device after it has been
|
||||
# rebooted again. Therefore this check will need to be
|
||||
# performed again after a reboot.
|
||||
|
||||
self._check_adb_root(timeout=timeout)
|
||||
|
||||
uid = 'uid=0'
|
||||
# Do we have a 'Superuser' sh like su?
|
||||
try:
|
||||
if self.shell_output("su -c id").find(uid) != -1:
|
||||
if self.shell_output("su -c id", timeout=timeout).find(uid) != -1:
|
||||
self._have_su = True
|
||||
self._logger.info("su -c supported")
|
||||
except ADBError:
|
||||
self._logger.debug("Check for su failed")
|
||||
self._logger.debug("Check for su -c failed")
|
||||
|
||||
# Do we have Android's su?
|
||||
try:
|
||||
if self.shell_output("su 0 id").find(uid) != -1:
|
||||
if self.shell_output("su 0 id", timeout=timeout).find(uid) != -1:
|
||||
self._have_android_su = True
|
||||
self._logger.info("su 0 supported")
|
||||
except ADBError:
|
||||
self._logger.debug("Check for Android su failed")
|
||||
self._logger.debug("Check for su 0 failed")
|
||||
|
||||
self._mkdir_p = None
|
||||
# Force the use of /system/bin/ls or /system/xbin/ls in case
|
||||
# there is /sbin/ls which embeds ansi escape codes to colorize
|
||||
# the output. Detect if we are using busybox ls. We want each
|
||||
# entry on a single line and we don't want . or ..
|
||||
if self.shell_bool("/system/bin/ls /"):
|
||||
if self.shell_bool("/system/bin/ls /", timeout=timeout):
|
||||
self._ls = "/system/bin/ls"
|
||||
elif self.shell_bool("/system/xbin/ls /"):
|
||||
elif self.shell_bool("/system/xbin/ls /", timeout=timeout):
|
||||
self._ls = "/system/xbin/ls"
|
||||
else:
|
||||
raise ADBError("ADBDevice.__init__: ls not found")
|
||||
try:
|
||||
self.shell_output("%s -1A /" % self._ls)
|
||||
self.shell_output("%s -1A /" % self._ls, timeout=timeout)
|
||||
self._ls += " -1A"
|
||||
except ADBError:
|
||||
self._ls += " -a"
|
||||
|
||||
# Do we have cp?
|
||||
self._have_cp = self.shell_bool("type cp")
|
||||
self._have_cp = self.shell_bool("type cp", timeout=timeout)
|
||||
|
||||
self._logger.debug("ADBDevice: %s" % self.__dict__)
|
||||
|
||||
@ -614,6 +624,28 @@ class ADBDevice(ADBCommand):
|
||||
|
||||
raise ValueError("Unable to get device serial")
|
||||
|
||||
def _check_adb_root(self, timeout=None):
|
||||
self._have_root_shell = False
|
||||
uid = 'uid=0'
|
||||
# Is shell already running as root?
|
||||
try:
|
||||
if self.shell_output("id", timeout=timeout).find(uid) != -1:
|
||||
self._have_root_shell = True
|
||||
self._logger.info("adbd running as root")
|
||||
except ADBError:
|
||||
self._logger.debug("Check for root shell failed")
|
||||
|
||||
# Do we need to run adb root to get a root shell?
|
||||
try:
|
||||
if (not self._have_root_shell and
|
||||
self.command_output(
|
||||
["root"],
|
||||
timeout=timeout).find("cannot run as root") == -1):
|
||||
self._have_root_shell = True
|
||||
self._logger.info("adbd restarted as root")
|
||||
except ADBError:
|
||||
self._logger.debug("Check for root adbd failed")
|
||||
|
||||
|
||||
@staticmethod
|
||||
def _escape_command_line(cmd):
|
||||
@ -1859,6 +1891,7 @@ class ADBDevice(ADBCommand):
|
||||
# 'wait-for-device' arguments which is an error in newer
|
||||
# versions of adb.
|
||||
self.command_output([], timeout=timeout)
|
||||
self._check_adb_root(timeout=timeout)
|
||||
return self.is_device_ready(timeout=timeout)
|
||||
|
||||
@abstractmethod
|
||||
|
@ -6,6 +6,8 @@ import os
|
||||
import re
|
||||
import time
|
||||
|
||||
from abc import ABCMeta
|
||||
|
||||
import version_codes
|
||||
|
||||
from adb import ADBDevice, ADBError
|
||||
@ -24,6 +26,99 @@ class ADBAndroid(ADBDevice):
|
||||
if adbdevice.process_exist("org.mozilla.fennec"):
|
||||
print "Fennec is running"
|
||||
"""
|
||||
__metaclass__ = ABCMeta
|
||||
|
||||
def __init__(self,
|
||||
device=None,
|
||||
adb='adb',
|
||||
adb_host=None,
|
||||
adb_port=None,
|
||||
test_root='',
|
||||
logger_name='adb',
|
||||
timeout=300,
|
||||
verbose=False,
|
||||
device_ready_retry_wait=20,
|
||||
device_ready_retry_attempts=3):
|
||||
"""Initializes the ADBAndroid object.
|
||||
|
||||
:param device: When a string is passed, it is interpreted as the
|
||||
device serial number. This form is not compatible with
|
||||
devices containing a ":" in the serial; in this case
|
||||
ValueError will be raised.
|
||||
When a dictionary is passed it must have one or both of
|
||||
the keys "device_serial" and "usb". This is compatible
|
||||
with the dictionaries in the list returned by
|
||||
ADBHost.devices(). If the value of device_serial is a
|
||||
valid serial not containing a ":" it will be used to
|
||||
identify the device, otherwise the value of the usb key,
|
||||
prefixed with "usb:" is used.
|
||||
If None is passed and there is exactly one device attached
|
||||
to the host, that device is used. If there is more than one
|
||||
device attached, ValueError is raised. If no device is
|
||||
attached the constructor will block until a device is
|
||||
attached or the timeout is reached.
|
||||
:type device: dict, str or None
|
||||
:param adb_host: host of the adb server to connect to.
|
||||
:type adb_host: str or None
|
||||
:param adb_port: port of the adb server to connect to.
|
||||
:type adb_port: integer or None
|
||||
:param str logger_name: logging logger name. Defaults to 'adb'.
|
||||
:param integer device_ready_retry_wait: number of seconds to wait
|
||||
between attempts to check if the device is ready after a
|
||||
reboot.
|
||||
:param integer device_ready_retry_attempts: number of attempts when
|
||||
checking if a device is ready.
|
||||
|
||||
:raises: * ADBError
|
||||
* ADBTimeoutError
|
||||
* ValueError
|
||||
"""
|
||||
ADBDevice.__init__(self, device=device, adb=adb,
|
||||
adb_host=adb_host, adb_port=adb_port,
|
||||
logger_name=logger_name, timeout=timeout,
|
||||
verbose=verbose,
|
||||
device_ready_retry_wait=device_ready_retry_wait,
|
||||
device_ready_retry_attempts=device_ready_retry_attempts)
|
||||
# https://source.android.com/devices/tech/security/selinux/index.html
|
||||
# setenforce
|
||||
# usage: setenforce [ Enforcing | Permissive | 1 | 0 ]
|
||||
# getenforce returns either Enforcing or Permissive
|
||||
|
||||
try:
|
||||
self.selinux = True
|
||||
if self.shell_output('getenforce', timeout=timeout) != 'Permissive':
|
||||
self._logger.info('Setting SELinux Permissive Mode')
|
||||
self.shell_output("setenforce Permissive", timeout=timeout, root=True)
|
||||
except ADBError:
|
||||
self.selinux = False
|
||||
|
||||
def reboot(self, timeout=None):
|
||||
"""Reboots the device.
|
||||
|
||||
:param timeout: optional integer specifying the maximum time in
|
||||
seconds for any spawned adb process to complete before
|
||||
throwing an ADBTimeoutError.
|
||||
This timeout is per adb call. The total time spent
|
||||
may exceed this value. If it is not specified, the value
|
||||
set in the ADB constructor is used.
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBError
|
||||
|
||||
reboot() reboots the device, issues an adb wait-for-device in order to
|
||||
wait for the device to complete rebooting, then calls is_device_ready()
|
||||
to determine if the device has completed booting.
|
||||
|
||||
If the device supports running adbd as root, adbd will be
|
||||
restarted running as root. Then, if the device supports
|
||||
SELinux, setenforce Permissive will be called to change
|
||||
SELinux to permissive. This must be done after adbd is
|
||||
restarted in order for the SELinux Permissive setting to
|
||||
persist.
|
||||
|
||||
"""
|
||||
ready = ADBDevice.reboot(self, timeout=timeout)
|
||||
self._check_adb_root(timeout=timeout)
|
||||
return ready
|
||||
|
||||
# Informational methods
|
||||
|
||||
@ -99,10 +194,15 @@ class ADBAndroid(ADBDevice):
|
||||
failure = "Device state: %s" % state
|
||||
success = False
|
||||
else:
|
||||
if self.is_dir(ready_path, timeout=timeout):
|
||||
self.rmdir(ready_path, timeout=timeout)
|
||||
self.mkdir(ready_path, timeout=timeout)
|
||||
self.rmdir(ready_path, timeout=timeout)
|
||||
if (self.selinux and
|
||||
self.shell_output('getenforce',
|
||||
timeout=timeout) != 'Permissive'):
|
||||
self._logger.info('Setting SELinux Permissive Mode')
|
||||
self.shell_output("setenforce Permissive", timeout=timeout, root=True)
|
||||
if self.is_dir(ready_path, timeout=timeout, root=True):
|
||||
self.rmdir(ready_path, timeout=timeout, root=True)
|
||||
self.mkdir(ready_path, timeout=timeout, root=True)
|
||||
self.rmdir(ready_path, timeout=timeout, root=True)
|
||||
# Invoke the pm list commands to see if it is up and
|
||||
# running.
|
||||
for pm_list_cmd in pm_list_commands:
|
||||
|
Loading…
Reference in New Issue
Block a user