예제 #1
0
        public static string ExtractWorkingDirectory(string commandOutput, string packageName)
        {
            IEnumerable <string> allLines = commandOutput.GetLines();

            // Linux will allow just about anything in a directory name as long as it is excaped. Android is much
            // more picky about package names. Let's reject characters which are invalid in a package name, highly
            // unlikely that any Android distribution would decide to use in the base directory, and likely to show
            // up in any debug spew we should ignore.
            char[] invalidPackageNameChars = { ' ', '\t', '*', '[', ']', '(', ')', '{', '}', ':' };

            // run-as is giving debug spew on a Galaxy S6, so we need to look at all the lines, and find the one that could be the working directory
            IEnumerable <string> workingDirectoryLines = allLines.Where(
                line => line.Length > 0 &&
                line[0] == '/' &&
                line.IndexOfAny(invalidPackageNameChars) < 0
                );

            if (workingDirectoryLines.Count() == 1)
            {
                return(workingDirectoryLines.Single());
            }

            RunAsOutputParser.ThrowIfRunAsErrors(commandOutput, packageName);
            throw new LauncherException(Telemetry.LaunchFailureCode.BadPwdOutput, string.Format(CultureInfo.CurrentCulture, LauncherResources.Error_ShellCommandBadResults, "pwd"));
        }
예제 #2
0
        private string GetGdbServerPath(string workingDirectory, Device device)
        {
            // On Android, the files of an application are extracted to the system owned directory /data/app/<appname>-<int>/lib
            // For 32-bit shared libraries, Android will create a symlink from the app owned directory /data/data/<appname>/lib
            // to maintain backwards compatibility with previous API versions.

            // There is no such symlink for 64-bit libraries, since Android only supports 64-bit since API 21, at which point
            // the app owned directory was no longer used for libs.

            // check the legacy location for 32-bit libs
            string gdbServerPath = workingDirectory + "/lib/gdbserver";

            string lsCommand = string.Format(CultureInfo.InvariantCulture, "ls {0}", gdbServerPath);
            string output    = ExecCommand(lsCommand);

            if (string.Compare(output, gdbServerPath, StringComparison.Ordinal) != 0)
            {
                // <app data>/lib is not symlinked to system's app data directory (/data/app/<app package>/lib).
                // We copy gdbserver ourselves because of 2 reasons:
                // 1. the app user doesn't have permissions on /data/app/<app package>-<suffix>/lib (it's owned by system)
                // 2. we can't deterministically figure out the location where gdbserver is in /data/app because of the suffix,
                //    which is used by Android to have multiple copies of the APK extracted in the system.
                string tmpGDBServer = string.Format(CultureInfo.InvariantCulture, "/data/local/tmp/gdbserver");

                device.FileSystem.Upload(_installPaths.GDBServerPath, tmpGDBServer, true);

                // Files can't be executed from /data/local/tmp
                string dest = string.Format(CultureInfo.InvariantCulture, "{0}/gdbserver", workingDirectory);

                // Can't use cp since shell doesn't have permissions to /data/data/<app>
                // and the app uid doesn't have permissions to /data/local/tmp
                string copyGDBServerCommand = string.Format(CultureInfo.InvariantCulture,
                                                            "cat {0} | run-as {1} /system/bin/sh -c \"cat > {2}\"", tmpGDBServer, _launchOptions.Package, dest);
                int rc = ExecCommand(copyGDBServerCommand, out output);
                RunAsOutputParser.ThrowIfRunAsErrors(output, _launchOptions.Package);
                if (rc != 0)
                {
                    throw new LauncherException(
                              Telemetry.LaunchFailureCode.NoGdbServer,
                              string.Format(CultureInfo.InvariantCulture, LauncherResources.Error_ShellCommandFailed, copyGDBServerCommand, output));
                }

                string chmodGDBServerCommand = string.Format(CultureInfo.InvariantCulture,
                                                             "run-as {0} chmod 700 {1}", _launchOptions.Package, dest);
                rc = ExecCommand(chmodGDBServerCommand, out output);
                RunAsOutputParser.ThrowIfRunAsErrors(output, _launchOptions.Package);
                if (rc != 0)
                {
                    throw new LauncherException(
                              Telemetry.LaunchFailureCode.NoGdbServer,
                              string.Format(CultureInfo.InvariantCulture, LauncherResources.Error_ShellCommandFailed, chmodGDBServerCommand, output));
                }

                gdbServerPath = dest;
            }

            return(gdbServerPath);
        }