Home | History | Annotate | Download | only in adb
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 // Functionality for launching and managing shell subprocesses.
     18 //
     19 // There are two types of subprocesses, PTY or raw. PTY is typically used for
     20 // an interactive session, raw for non-interactive. There are also two methods
     21 // of communication with the subprocess, passing raw data or using a simple
     22 // protocol to wrap packets. The protocol allows separating stdout/stderr and
     23 // passing the exit code back, but is not backwards compatible.
     24 //   ----------------+--------------------------------------
     25 //   Type  Protocol  |   Exit code?  Separate stdout/stderr?
     26 //   ----------------+--------------------------------------
     27 //   PTY   No        |   No          No
     28 //   Raw   No        |   No          No
     29 //   PTY   Yes       |   Yes         No
     30 //   Raw   Yes       |   Yes         Yes
     31 //   ----------------+--------------------------------------
     32 //
     33 // Non-protocol subprocesses work by passing subprocess stdin/out/err through
     34 // a single pipe which is registered with a local socket in adbd. The local
     35 // socket uses the fdevent loop to pass raw data between this pipe and the
     36 // transport, which then passes data back to the adb client. Cleanup is done by
     37 // waiting in a separate thread for the subprocesses to exit and then signaling
     38 // a separate fdevent to close out the local socket from the main loop.
     39 //
     40 // ------------------+-------------------------+------------------------------
     41 //   Subprocess      |  adbd subprocess thread |   adbd main fdevent loop
     42 // ------------------+-------------------------+------------------------------
     43 //                   |                         |
     44 //   stdin/out/err <----------------------------->       LocalSocket
     45 //      |            |                         |
     46 //      |            |      Block on exit      |
     47 //      |            |           *             |
     48 //      v            |           *             |
     49 //     Exit         --->      Unblock          |
     50 //                   |           |             |
     51 //                   |           v             |
     52 //                   |   Notify shell exit FD --->    Close LocalSocket
     53 // ------------------+-------------------------+------------------------------
     54 //
     55 // The protocol requires the thread to intercept stdin/out/err in order to
     56 // wrap/unwrap data with shell protocol packets.
     57 //
     58 // ------------------+-------------------------+------------------------------
     59 //   Subprocess      |  adbd subprocess thread |   adbd main fdevent loop
     60 // ------------------+-------------------------+------------------------------
     61 //                   |                         |
     62 //     stdin/out   <--->      Protocol       <--->       LocalSocket
     63 //     stderr       --->      Protocol        --->       LocalSocket
     64 //       |           |                         |
     65 //       v           |                         |
     66 //      Exit        --->  Exit code protocol  --->       LocalSocket
     67 //                   |           |             |
     68 //                   |           v             |
     69 //                   |   Notify shell exit FD --->    Close LocalSocket
     70 // ------------------+-------------------------+------------------------------
     71 //
     72 // An alternate approach is to put the protocol wrapping/unwrapping in the main
     73 // fdevent loop, which has the advantage of being able to re-use the existing
     74 // select() code for handling data streams. However, implementation turned out
     75 // to be more complex due to partial reads and non-blocking I/O so this model
     76 // was chosen instead.
     77 
     78 #define TRACE_TAG SHELL
     79 
     80 #include "sysdeps.h"
     81 
     82 #include "shell_service.h"
     83 
     84 #include <errno.h>
     85 #include <pty.h>
     86 #include <pwd.h>
     87 #include <sys/select.h>
     88 #include <termios.h>
     89 
     90 #include <memory>
     91 #include <string>
     92 #include <unordered_map>
     93 #include <vector>
     94 
     95 #include <android-base/logging.h>
     96 #include <android-base/stringprintf.h>
     97 #include <paths.h>
     98 #include <log/log.h>
     99 
    100 #include "adb.h"
    101 #include "adb_io.h"
    102 #include "adb_trace.h"
    103 #include "adb_utils.h"
    104 #include "security_log_tags.h"
    105 
    106 namespace {
    107 
    108 void init_subproc_child()
    109 {
    110     setsid();
    111 
    112     // Set OOM score adjustment to prevent killing
    113     int fd = adb_open("/proc/self/oom_score_adj", O_WRONLY | O_CLOEXEC);
    114     if (fd >= 0) {
    115         adb_write(fd, "0", 1);
    116         adb_close(fd);
    117     } else {
    118        D("adb: unable to update oom_score_adj");
    119     }
    120 }
    121 
    122 // Reads from |fd| until close or failure.
    123 std::string ReadAll(int fd) {
    124     char buffer[512];
    125     std::string received;
    126 
    127     while (1) {
    128         int bytes = adb_read(fd, buffer, sizeof(buffer));
    129         if (bytes <= 0) {
    130             break;
    131         }
    132         received.append(buffer, bytes);
    133     }
    134 
    135     return received;
    136 }
    137 
    138 // Creates a socketpair and saves the endpoints to |fd1| and |fd2|.
    139 bool CreateSocketpair(ScopedFd* fd1, ScopedFd* fd2) {
    140     int sockets[2];
    141     if (adb_socketpair(sockets) < 0) {
    142         PLOG(ERROR) << "cannot create socket pair";
    143         return false;
    144     }
    145     fd1->Reset(sockets[0]);
    146     fd2->Reset(sockets[1]);
    147     return true;
    148 }
    149 
    150 class Subprocess {
    151   public:
    152     Subprocess(const std::string& command, const char* terminal_type,
    153                SubprocessType type, SubprocessProtocol protocol);
    154     ~Subprocess();
    155 
    156     const std::string& command() const { return command_; }
    157 
    158     int ReleaseLocalSocket() { return local_socket_sfd_.Release(); }
    159 
    160     pid_t pid() const { return pid_; }
    161 
    162     // Sets up FDs, forks a subprocess, starts the subprocess manager thread,
    163     // and exec's the child. Returns false and sets error on failure.
    164     bool ForkAndExec(std::string* _Nonnull error);
    165 
    166     // Start the subprocess manager thread. Consumes the subprocess, regardless of success.
    167     // Returns false and sets error on failure.
    168     static bool StartThread(std::unique_ptr<Subprocess> subprocess,
    169                             std::string* _Nonnull error);
    170 
    171   private:
    172     // Opens the file at |pts_name|.
    173     int OpenPtyChildFd(const char* pts_name, ScopedFd* error_sfd);
    174 
    175     static void ThreadHandler(void* userdata);
    176     void PassDataStreams();
    177     void WaitForExit();
    178 
    179     ScopedFd* SelectLoop(fd_set* master_read_set_ptr,
    180                          fd_set* master_write_set_ptr);
    181 
    182     // Input/output stream handlers. Success returns nullptr, failure returns
    183     // a pointer to the failed FD.
    184     ScopedFd* PassInput();
    185     ScopedFd* PassOutput(ScopedFd* sfd, ShellProtocol::Id id);
    186 
    187     const std::string command_;
    188     const std::string terminal_type_;
    189     bool make_pty_raw_ = false;
    190     SubprocessType type_;
    191     SubprocessProtocol protocol_;
    192     pid_t pid_ = -1;
    193     ScopedFd local_socket_sfd_;
    194 
    195     // Shell protocol variables.
    196     ScopedFd stdinout_sfd_, stderr_sfd_, protocol_sfd_;
    197     std::unique_ptr<ShellProtocol> input_, output_;
    198     size_t input_bytes_left_ = 0;
    199 
    200     DISALLOW_COPY_AND_ASSIGN(Subprocess);
    201 };
    202 
    203 Subprocess::Subprocess(const std::string& command, const char* terminal_type,
    204                        SubprocessType type, SubprocessProtocol protocol)
    205     : command_(command),
    206       terminal_type_(terminal_type ? terminal_type : ""),
    207       type_(type),
    208       protocol_(protocol) {
    209     // If we aren't using the shell protocol we must allocate a PTY to properly close the
    210     // subprocess. PTYs automatically send SIGHUP to the slave-side process when the master side
    211     // of the PTY closes, which we rely on. If we use a raw pipe, processes that don't read/write,
    212     // e.g. screenrecord, will never notice the broken pipe and terminate.
    213     // The shell protocol doesn't require a PTY because it's always monitoring the local socket FD
    214     // with select() and will send SIGHUP manually to the child process.
    215     if (protocol_ == SubprocessProtocol::kNone && type_ == SubprocessType::kRaw) {
    216         // Disable PTY input/output processing since the client is expecting raw data.
    217         D("Can't create raw subprocess without shell protocol, using PTY in raw mode instead");
    218         type_ = SubprocessType::kPty;
    219         make_pty_raw_ = true;
    220     }
    221 }
    222 
    223 Subprocess::~Subprocess() {
    224     WaitForExit();
    225 }
    226 
    227 bool Subprocess::ForkAndExec(std::string* error) {
    228     ScopedFd child_stdinout_sfd, child_stderr_sfd;
    229     ScopedFd parent_error_sfd, child_error_sfd;
    230     char pts_name[PATH_MAX];
    231 
    232     if (command_.empty()) {
    233         __android_log_security_bswrite(SEC_TAG_ADB_SHELL_INTERACTIVE, "");
    234     } else {
    235         __android_log_security_bswrite(SEC_TAG_ADB_SHELL_CMD, command_.c_str());
    236     }
    237 
    238     // Create a socketpair for the fork() child to report any errors back to the parent. Since we
    239     // use threads, logging directly from the child might deadlock due to locks held in another
    240     // thread during the fork.
    241     if (!CreateSocketpair(&parent_error_sfd, &child_error_sfd)) {
    242         *error = android::base::StringPrintf(
    243             "failed to create pipe for subprocess error reporting: %s", strerror(errno));
    244         return false;
    245     }
    246 
    247     // Construct the environment for the child before we fork.
    248     passwd* pw = getpwuid(getuid());
    249     std::unordered_map<std::string, std::string> env;
    250     if (environ) {
    251         char** current = environ;
    252         while (char* env_cstr = *current++) {
    253             std::string env_string = env_cstr;
    254             char* delimiter = strchr(env_string.c_str(), '=');
    255 
    256             // Drop any values that don't contain '='.
    257             if (delimiter) {
    258                 *delimiter++ = '\0';
    259                 env[env_string.c_str()] = delimiter;
    260             }
    261         }
    262     }
    263 
    264     if (pw != nullptr) {
    265         // TODO: $HOSTNAME? Normally bash automatically sets that, but mksh doesn't.
    266         env["HOME"] = pw->pw_dir;
    267         env["LOGNAME"] = pw->pw_name;
    268         env["USER"] = pw->pw_name;
    269         env["SHELL"] = pw->pw_shell;
    270     }
    271 
    272     if (!terminal_type_.empty()) {
    273         env["TERM"] = terminal_type_;
    274     }
    275 
    276     std::vector<std::string> joined_env;
    277     for (auto it : env) {
    278         const char* key = it.first.c_str();
    279         const char* value = it.second.c_str();
    280         joined_env.push_back(android::base::StringPrintf("%s=%s", key, value));
    281     }
    282 
    283     std::vector<const char*> cenv;
    284     for (const std::string& str : joined_env) {
    285         cenv.push_back(str.c_str());
    286     }
    287     cenv.push_back(nullptr);
    288 
    289     if (type_ == SubprocessType::kPty) {
    290         int fd;
    291         pid_ = forkpty(&fd, pts_name, nullptr, nullptr);
    292         if (pid_ > 0) {
    293           stdinout_sfd_.Reset(fd);
    294         }
    295     } else {
    296         if (!CreateSocketpair(&stdinout_sfd_, &child_stdinout_sfd)) {
    297             *error = android::base::StringPrintf("failed to create socketpair for stdin/out: %s",
    298                                                  strerror(errno));
    299             return false;
    300         }
    301         // Raw subprocess + shell protocol allows for splitting stderr.
    302         if (protocol_ == SubprocessProtocol::kShell &&
    303                 !CreateSocketpair(&stderr_sfd_, &child_stderr_sfd)) {
    304             *error = android::base::StringPrintf("failed to create socketpair for stderr: %s",
    305                                                  strerror(errno));
    306             return false;
    307         }
    308         pid_ = fork();
    309     }
    310 
    311     if (pid_ == -1) {
    312         *error = android::base::StringPrintf("fork failed: %s", strerror(errno));
    313         return false;
    314     }
    315 
    316     if (pid_ == 0) {
    317         // Subprocess child.
    318         init_subproc_child();
    319 
    320         if (type_ == SubprocessType::kPty) {
    321             child_stdinout_sfd.Reset(OpenPtyChildFd(pts_name, &child_error_sfd));
    322         }
    323 
    324         dup2(child_stdinout_sfd.fd(), STDIN_FILENO);
    325         dup2(child_stdinout_sfd.fd(), STDOUT_FILENO);
    326         dup2(child_stderr_sfd.valid() ? child_stderr_sfd.fd() : child_stdinout_sfd.fd(),
    327              STDERR_FILENO);
    328 
    329         // exec doesn't trigger destructors, close the FDs manually.
    330         stdinout_sfd_.Reset();
    331         stderr_sfd_.Reset();
    332         child_stdinout_sfd.Reset();
    333         child_stderr_sfd.Reset();
    334         parent_error_sfd.Reset();
    335         close_on_exec(child_error_sfd.fd());
    336 
    337         if (command_.empty()) {
    338             execle(_PATH_BSHELL, _PATH_BSHELL, "-", nullptr, cenv.data());
    339         } else {
    340             execle(_PATH_BSHELL, _PATH_BSHELL, "-c", command_.c_str(), nullptr, cenv.data());
    341         }
    342         WriteFdExactly(child_error_sfd.fd(), "exec '" _PATH_BSHELL "' failed: ");
    343         WriteFdExactly(child_error_sfd.fd(), strerror(errno));
    344         child_error_sfd.Reset();
    345         _Exit(1);
    346     }
    347 
    348     // Subprocess parent.
    349     D("subprocess parent: stdin/stdout FD = %d, stderr FD = %d",
    350       stdinout_sfd_.fd(), stderr_sfd_.fd());
    351 
    352     // Wait to make sure the subprocess exec'd without error.
    353     child_error_sfd.Reset();
    354     std::string error_message = ReadAll(parent_error_sfd.fd());
    355     if (!error_message.empty()) {
    356         *error = error_message;
    357         return false;
    358     }
    359 
    360     D("subprocess parent: exec completed");
    361     if (protocol_ == SubprocessProtocol::kNone) {
    362         // No protocol: all streams pass through the stdinout FD and hook
    363         // directly into the local socket for raw data transfer.
    364         local_socket_sfd_.Reset(stdinout_sfd_.Release());
    365     } else {
    366         // Shell protocol: create another socketpair to intercept data.
    367         if (!CreateSocketpair(&protocol_sfd_, &local_socket_sfd_)) {
    368             *error = android::base::StringPrintf(
    369                 "failed to create socketpair to intercept data: %s", strerror(errno));
    370             kill(pid_, SIGKILL);
    371             return false;
    372         }
    373         D("protocol FD = %d", protocol_sfd_.fd());
    374 
    375         input_.reset(new ShellProtocol(protocol_sfd_.fd()));
    376         output_.reset(new ShellProtocol(protocol_sfd_.fd()));
    377         if (!input_ || !output_) {
    378             *error = "failed to allocate shell protocol objects";
    379             kill(pid_, SIGKILL);
    380             return false;
    381         }
    382 
    383         // Don't let reads/writes to the subprocess block our thread. This isn't
    384         // likely but could happen under unusual circumstances, such as if we
    385         // write a ton of data to stdin but the subprocess never reads it and
    386         // the pipe fills up.
    387         for (int fd : {stdinout_sfd_.fd(), stderr_sfd_.fd()}) {
    388             if (fd >= 0) {
    389                 if (!set_file_block_mode(fd, false)) {
    390                     *error = android::base::StringPrintf(
    391                         "failed to set non-blocking mode for fd %d", fd);
    392                     kill(pid_, SIGKILL);
    393                     return false;
    394                 }
    395             }
    396         }
    397     }
    398 
    399     D("subprocess parent: completed");
    400     return true;
    401 }
    402 
    403 bool Subprocess::StartThread(std::unique_ptr<Subprocess> subprocess, std::string* error) {
    404     Subprocess* raw = subprocess.release();
    405     if (!adb_thread_create(ThreadHandler, raw)) {
    406         *error =
    407             android::base::StringPrintf("failed to create subprocess thread: %s", strerror(errno));
    408         kill(raw->pid_, SIGKILL);
    409         return false;
    410     }
    411 
    412     return true;
    413 }
    414 
    415 int Subprocess::OpenPtyChildFd(const char* pts_name, ScopedFd* error_sfd) {
    416     int child_fd = adb_open(pts_name, O_RDWR | O_CLOEXEC);
    417     if (child_fd == -1) {
    418         // Don't use WriteFdFmt; since we're in the fork() child we don't want
    419         // to allocate any heap memory to avoid race conditions.
    420         const char* messages[] = {"child failed to open pseudo-term slave ",
    421                                   pts_name, ": ", strerror(errno)};
    422         for (const char* message : messages) {
    423             WriteFdExactly(error_sfd->fd(), message);
    424         }
    425         exit(-1);
    426     }
    427 
    428     if (make_pty_raw_) {
    429         termios tattr;
    430         if (tcgetattr(child_fd, &tattr) == -1) {
    431             int saved_errno = errno;
    432             WriteFdExactly(error_sfd->fd(), "tcgetattr failed: ");
    433             WriteFdExactly(error_sfd->fd(), strerror(saved_errno));
    434             exit(-1);
    435         }
    436 
    437         cfmakeraw(&tattr);
    438         if (tcsetattr(child_fd, TCSADRAIN, &tattr) == -1) {
    439             int saved_errno = errno;
    440             WriteFdExactly(error_sfd->fd(), "tcsetattr failed: ");
    441             WriteFdExactly(error_sfd->fd(), strerror(saved_errno));
    442             exit(-1);
    443         }
    444     }
    445 
    446     return child_fd;
    447 }
    448 
    449 void Subprocess::ThreadHandler(void* userdata) {
    450     Subprocess* subprocess = reinterpret_cast<Subprocess*>(userdata);
    451 
    452     adb_thread_setname(android::base::StringPrintf(
    453             "shell srvc %d", subprocess->pid()));
    454 
    455     D("passing data streams for PID %d", subprocess->pid());
    456     subprocess->PassDataStreams();
    457 
    458     D("deleting Subprocess for PID %d", subprocess->pid());
    459     delete subprocess;
    460 }
    461 
    462 void Subprocess::PassDataStreams() {
    463     if (!protocol_sfd_.valid()) {
    464         return;
    465     }
    466 
    467     // Start by trying to read from the protocol FD, stdout, and stderr.
    468     fd_set master_read_set, master_write_set;
    469     FD_ZERO(&master_read_set);
    470     FD_ZERO(&master_write_set);
    471     for (ScopedFd* sfd : {&protocol_sfd_, &stdinout_sfd_, &stderr_sfd_}) {
    472         if (sfd->valid()) {
    473             FD_SET(sfd->fd(), &master_read_set);
    474         }
    475     }
    476 
    477     // Pass data until the protocol FD or both the subprocess pipes die, at
    478     // which point we can't pass any more data.
    479     while (protocol_sfd_.valid() &&
    480             (stdinout_sfd_.valid() || stderr_sfd_.valid())) {
    481         ScopedFd* dead_sfd = SelectLoop(&master_read_set, &master_write_set);
    482         if (dead_sfd) {
    483             D("closing FD %d", dead_sfd->fd());
    484             FD_CLR(dead_sfd->fd(), &master_read_set);
    485             FD_CLR(dead_sfd->fd(), &master_write_set);
    486             if (dead_sfd == &protocol_sfd_) {
    487                 // Using SIGHUP is a decent general way to indicate that the
    488                 // controlling process is going away. If specific signals are
    489                 // needed (e.g. SIGINT), pass those through the shell protocol
    490                 // and only fall back on this for unexpected closures.
    491                 D("protocol FD died, sending SIGHUP to pid %d", pid_);
    492                 kill(pid_, SIGHUP);
    493 
    494                 // We also need to close the pipes connected to the child process
    495                 // so that if it ignores SIGHUP and continues to write data it
    496                 // won't fill up the pipe and block.
    497                 stdinout_sfd_.Reset();
    498                 stderr_sfd_.Reset();
    499             }
    500             dead_sfd->Reset();
    501         }
    502     }
    503 }
    504 
    505 namespace {
    506 
    507 inline bool ValidAndInSet(const ScopedFd& sfd, fd_set* set) {
    508     return sfd.valid() && FD_ISSET(sfd.fd(), set);
    509 }
    510 
    511 }   // namespace
    512 
    513 ScopedFd* Subprocess::SelectLoop(fd_set* master_read_set_ptr,
    514                                  fd_set* master_write_set_ptr) {
    515     fd_set read_set, write_set;
    516     int select_n = std::max(std::max(protocol_sfd_.fd(), stdinout_sfd_.fd()),
    517                             stderr_sfd_.fd()) + 1;
    518     ScopedFd* dead_sfd = nullptr;
    519 
    520     // Keep calling select() and passing data until an FD closes/errors.
    521     while (!dead_sfd) {
    522         memcpy(&read_set, master_read_set_ptr, sizeof(read_set));
    523         memcpy(&write_set, master_write_set_ptr, sizeof(write_set));
    524         if (select(select_n, &read_set, &write_set, nullptr, nullptr) < 0) {
    525             if (errno == EINTR) {
    526                 continue;
    527             } else {
    528                 PLOG(ERROR) << "select failed, closing subprocess pipes";
    529                 stdinout_sfd_.Reset();
    530                 stderr_sfd_.Reset();
    531                 return nullptr;
    532             }
    533         }
    534 
    535         // Read stdout, write to protocol FD.
    536         if (ValidAndInSet(stdinout_sfd_, &read_set)) {
    537             dead_sfd = PassOutput(&stdinout_sfd_, ShellProtocol::kIdStdout);
    538         }
    539 
    540         // Read stderr, write to protocol FD.
    541         if (!dead_sfd && ValidAndInSet(stderr_sfd_, &read_set)) {
    542             dead_sfd = PassOutput(&stderr_sfd_, ShellProtocol::kIdStderr);
    543         }
    544 
    545         // Read protocol FD, write to stdin.
    546         if (!dead_sfd && ValidAndInSet(protocol_sfd_, &read_set)) {
    547             dead_sfd = PassInput();
    548             // If we didn't finish writing, block on stdin write.
    549             if (input_bytes_left_) {
    550                 FD_CLR(protocol_sfd_.fd(), master_read_set_ptr);
    551                 FD_SET(stdinout_sfd_.fd(), master_write_set_ptr);
    552             }
    553         }
    554 
    555         // Continue writing to stdin; only happens if a previous write blocked.
    556         if (!dead_sfd && ValidAndInSet(stdinout_sfd_, &write_set)) {
    557             dead_sfd = PassInput();
    558             // If we finished writing, go back to blocking on protocol read.
    559             if (!input_bytes_left_) {
    560                 FD_SET(protocol_sfd_.fd(), master_read_set_ptr);
    561                 FD_CLR(stdinout_sfd_.fd(), master_write_set_ptr);
    562             }
    563         }
    564     }  // while (!dead_sfd)
    565 
    566     return dead_sfd;
    567 }
    568 
    569 ScopedFd* Subprocess::PassInput() {
    570     // Only read a new packet if we've finished writing the last one.
    571     if (!input_bytes_left_) {
    572         if (!input_->Read()) {
    573             // Read() uses ReadFdExactly() which sets errno to 0 on EOF.
    574             if (errno != 0) {
    575                 PLOG(ERROR) << "error reading protocol FD "
    576                             << protocol_sfd_.fd();
    577             }
    578             return &protocol_sfd_;
    579         }
    580 
    581         if (stdinout_sfd_.valid()) {
    582             switch (input_->id()) {
    583                 case ShellProtocol::kIdWindowSizeChange:
    584                     int rows, cols, x_pixels, y_pixels;
    585                     if (sscanf(input_->data(), "%dx%d,%dx%d",
    586                                &rows, &cols, &x_pixels, &y_pixels) == 4) {
    587                         winsize ws;
    588                         ws.ws_row = rows;
    589                         ws.ws_col = cols;
    590                         ws.ws_xpixel = x_pixels;
    591                         ws.ws_ypixel = y_pixels;
    592                         ioctl(stdinout_sfd_.fd(), TIOCSWINSZ, &ws);
    593                     }
    594                     break;
    595                 case ShellProtocol::kIdStdin:
    596                     input_bytes_left_ = input_->data_length();
    597                     break;
    598                 case ShellProtocol::kIdCloseStdin:
    599                     if (type_ == SubprocessType::kRaw) {
    600                         if (adb_shutdown(stdinout_sfd_.fd(), SHUT_WR) == 0) {
    601                             return nullptr;
    602                         }
    603                         PLOG(ERROR) << "failed to shutdown writes to FD "
    604                                     << stdinout_sfd_.fd();
    605                         return &stdinout_sfd_;
    606                     } else {
    607                         // PTYs can't close just input, so rather than close the
    608                         // FD and risk losing subprocess output, leave it open.
    609                         // This only happens if the client starts a PTY shell
    610                         // non-interactively which is rare and unsupported.
    611                         // If necessary, the client can manually close the shell
    612                         // with `exit` or by killing the adb client process.
    613                         D("can't close input for PTY FD %d", stdinout_sfd_.fd());
    614                     }
    615                     break;
    616             }
    617         }
    618     }
    619 
    620     if (input_bytes_left_ > 0) {
    621         int index = input_->data_length() - input_bytes_left_;
    622         int bytes = adb_write(stdinout_sfd_.fd(), input_->data() + index,
    623                               input_bytes_left_);
    624         if (bytes == 0 || (bytes < 0 && errno != EAGAIN)) {
    625             if (bytes < 0) {
    626                 PLOG(ERROR) << "error reading stdin FD " << stdinout_sfd_.fd();
    627             }
    628             // stdin is done, mark this packet as finished and we'll just start
    629             // dumping any further data received from the protocol FD.
    630             input_bytes_left_ = 0;
    631             return &stdinout_sfd_;
    632         } else if (bytes > 0) {
    633             input_bytes_left_ -= bytes;
    634         }
    635     }
    636 
    637     return nullptr;
    638 }
    639 
    640 ScopedFd* Subprocess::PassOutput(ScopedFd* sfd, ShellProtocol::Id id) {
    641     int bytes = adb_read(sfd->fd(), output_->data(), output_->data_capacity());
    642     if (bytes == 0 || (bytes < 0 && errno != EAGAIN)) {
    643         // read() returns EIO if a PTY closes; don't report this as an error,
    644         // it just means the subprocess completed.
    645         if (bytes < 0 && !(type_ == SubprocessType::kPty && errno == EIO)) {
    646             PLOG(ERROR) << "error reading output FD " << sfd->fd();
    647         }
    648         return sfd;
    649     }
    650 
    651     if (bytes > 0 && !output_->Write(id, bytes)) {
    652         if (errno != 0) {
    653             PLOG(ERROR) << "error reading protocol FD " << protocol_sfd_.fd();
    654         }
    655         return &protocol_sfd_;
    656     }
    657 
    658     return nullptr;
    659 }
    660 
    661 void Subprocess::WaitForExit() {
    662     int exit_code = 1;
    663 
    664     D("waiting for pid %d", pid_);
    665     while (true) {
    666         int status;
    667         if (pid_ == waitpid(pid_, &status, 0)) {
    668             D("post waitpid (pid=%d) status=%04x", pid_, status);
    669             if (WIFSIGNALED(status)) {
    670                 exit_code = 0x80 | WTERMSIG(status);
    671                 D("subprocess killed by signal %d", WTERMSIG(status));
    672                 break;
    673             } else if (!WIFEXITED(status)) {
    674                 D("subprocess didn't exit");
    675                 break;
    676             } else if (WEXITSTATUS(status) >= 0) {
    677                 exit_code = WEXITSTATUS(status);
    678                 D("subprocess exit code = %d", WEXITSTATUS(status));
    679                 break;
    680             }
    681         }
    682     }
    683 
    684     // If we have an open protocol FD send an exit packet.
    685     if (protocol_sfd_.valid()) {
    686         output_->data()[0] = exit_code;
    687         if (output_->Write(ShellProtocol::kIdExit, 1)) {
    688             D("wrote the exit code packet: %d", exit_code);
    689         } else {
    690             PLOG(ERROR) << "failed to write the exit code packet";
    691         }
    692         protocol_sfd_.Reset();
    693     }
    694 
    695     // Pass the local socket FD to the shell cleanup fdevent.
    696     if (SHELL_EXIT_NOTIFY_FD >= 0) {
    697         int fd = local_socket_sfd_.fd();
    698         if (WriteFdExactly(SHELL_EXIT_NOTIFY_FD, &fd, sizeof(fd))) {
    699             D("passed fd %d to SHELL_EXIT_NOTIFY_FD (%d) for pid %d",
    700               fd, SHELL_EXIT_NOTIFY_FD, pid_);
    701             // The shell exit fdevent now owns the FD and will close it once
    702             // the last bit of data flushes through.
    703             local_socket_sfd_.Release();
    704         } else {
    705             PLOG(ERROR) << "failed to write fd " << fd
    706                         << " to SHELL_EXIT_NOTIFY_FD (" << SHELL_EXIT_NOTIFY_FD
    707                         << ") for pid " << pid_;
    708         }
    709     }
    710 }
    711 
    712 }  // namespace
    713 
    714 // Create a pipe containing the error.
    715 static int ReportError(SubprocessProtocol protocol, const std::string& message) {
    716     int pipefd[2];
    717     if (pipe(pipefd) != 0) {
    718         LOG(ERROR) << "failed to create pipe to report error";
    719         return -1;
    720     }
    721 
    722     std::string buf = android::base::StringPrintf("error: %s\n", message.c_str());
    723     if (protocol == SubprocessProtocol::kShell) {
    724         ShellProtocol::Id id = ShellProtocol::kIdStderr;
    725         uint32_t length = buf.length();
    726         WriteFdExactly(pipefd[1], &id, sizeof(id));
    727         WriteFdExactly(pipefd[1], &length, sizeof(length));
    728     }
    729 
    730     WriteFdExactly(pipefd[1], buf.data(), buf.length());
    731 
    732     if (protocol == SubprocessProtocol::kShell) {
    733         ShellProtocol::Id id = ShellProtocol::kIdExit;
    734         uint32_t length = 1;
    735         char exit_code = 126;
    736         WriteFdExactly(pipefd[1], &id, sizeof(id));
    737         WriteFdExactly(pipefd[1], &length, sizeof(length));
    738         WriteFdExactly(pipefd[1], &exit_code, sizeof(exit_code));
    739     }
    740 
    741     adb_close(pipefd[1]);
    742     return pipefd[0];
    743 }
    744 
    745 int StartSubprocess(const char* name, const char* terminal_type,
    746                     SubprocessType type, SubprocessProtocol protocol) {
    747     D("starting %s subprocess (protocol=%s, TERM=%s): '%s'",
    748       type == SubprocessType::kRaw ? "raw" : "PTY",
    749       protocol == SubprocessProtocol::kNone ? "none" : "shell",
    750       terminal_type, name);
    751 
    752     auto subprocess = std::make_unique<Subprocess>(name, terminal_type, type, protocol);
    753     if (!subprocess) {
    754         LOG(ERROR) << "failed to allocate new subprocess";
    755         return ReportError(protocol, "failed to allocate new subprocess");
    756     }
    757 
    758     std::string error;
    759     if (!subprocess->ForkAndExec(&error)) {
    760         LOG(ERROR) << "failed to start subprocess: " << error;
    761         return ReportError(protocol, error);
    762     }
    763 
    764     int local_socket = subprocess->ReleaseLocalSocket();
    765     D("subprocess creation successful: local_socket_fd=%d, pid=%d", local_socket, subprocess->pid());
    766 
    767     if (!Subprocess::StartThread(std::move(subprocess), &error)) {
    768         LOG(ERROR) << "failed to start subprocess management thread: " << error;
    769         return ReportError(protocol, error);
    770     }
    771 
    772     return local_socket;
    773 }
    774