Loading logd/CommandListener.cpp +7 −9 Original line number Diff line number Diff line /* * Copyright (C) 2012-2013 The Android Open Source Project * Copyright (C) 2012-2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. Loading @@ -24,10 +24,11 @@ #include <sys/socket.h> #include <sys/types.h> #include <sysutils/SocketClient.h> #include <private/android_filesystem_config.h> #include <sysutils/SocketClient.h> #include "CommandListener.h" #include "LogCommand.h" CommandListener::CommandListener(LogBuffer *buf, LogReader * /*reader*/, LogListener * /*swl*/) Loading Loading @@ -62,9 +63,7 @@ CommandListener::ClearCmd::ClearCmd(LogBuffer *buf) int CommandListener::ClearCmd::runCommand(SocketClient *cli, int argc, char **argv) { if ((cli->getUid() != AID_ROOT) && (cli->getGid() != AID_ROOT) && (cli->getGid() != AID_LOG)) { if (!clientHasLogCredentials(cli)) { cli->sendMsg("Permission Denied"); return 0; } Loading @@ -75,7 +74,7 @@ int CommandListener::ClearCmd::runCommand(SocketClient *cli, } int id = atoi(argv[1]); if ((id < LOG_ID_MIN) || (id >= LOG_ID_MAX)) { if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) { cli->sendMsg("Range Error"); return 0; } Loading @@ -85,7 +84,6 @@ int CommandListener::ClearCmd::runCommand(SocketClient *cli, return 0; } CommandListener::GetBufSizeCmd::GetBufSizeCmd(LogBuffer *buf) : LogCommand("getLogSize") , mBuf(*buf) Loading @@ -99,7 +97,7 @@ int CommandListener::GetBufSizeCmd::runCommand(SocketClient *cli, } int id = atoi(argv[1]); if ((id < LOG_ID_MIN) || (id >= LOG_ID_MAX)) { if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) { cli->sendMsg("Range Error"); return 0; } Loading @@ -124,7 +122,7 @@ int CommandListener::GetBufSizeUsedCmd::runCommand(SocketClient *cli, } int id = atoi(argv[1]); if ((id < LOG_ID_MIN) || (id >= LOG_ID_MAX)) { if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) { cli->sendMsg("Range Error"); return 0; } Loading logd/FlushCommand.cpp +5 −6 Original line number Diff line number Diff line /* * Copyright (C) 2012-2013 The Android Open Source Project * Copyright (C) 2012-2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. Loading @@ -15,11 +15,12 @@ */ #include <stdlib.h> #include <private/android_filesystem_config.h> #include "FlushCommand.h" #include "LogBufferElement.h" #include "LogTimes.h" #include "LogCommand.h" #include "LogReader.h" #include "LogTimes.h" FlushCommand::FlushCommand(LogReader &reader, bool nonBlock, Loading Loading @@ -80,7 +81,5 @@ void FlushCommand::runSocketCommand(SocketClient *client) { } bool FlushCommand::hasReadLogs(SocketClient *client) { return (client->getUid() == AID_ROOT) || (client->getGid() == AID_ROOT) || (client->getGid() == AID_LOG); return clientHasLogCredentials(client); } logd/LogCommand.cpp +110 −1 Original line number Diff line number Diff line /* * Copyright (C) 2012-2013 The Android Open Source Project * Copyright (C) 2012-2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. Loading @@ -14,8 +14,117 @@ * limitations under the License. */ #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <private/android_filesystem_config.h> #include "LogCommand.h" LogCommand::LogCommand(const char *cmd) : FrameworkCommand(cmd) { } // gets a list of supplementary group IDs associated with // the socket peer. This is implemented by opening // /proc/PID/status and look for the "Group:" line. // // This function introduces races especially since status // can change 'shape' while reading, the net result is err // on lack of permission. // // Race-free alternative is to introduce pairs of sockets // and threads for each command and reading, one each that // has open permissions, and one that has restricted // permissions. static bool groupIsLog(char *buf) { char *ptr; static const char ws[] = " \n"; bool ret = false; for (buf = strtok_r(buf, ws, &ptr); buf; buf = strtok_r(NULL, ws, &ptr)) { errno = 0; gid_t Gid = strtol(buf, NULL, 10); if (errno != 0) { return false; } if (Gid == AID_LOG) { ret = true; } } return ret; } bool clientHasLogCredentials(SocketClient * cli) { uid_t uid = cli->getUid(); if (uid == AID_ROOT) { return true; } gid_t gid = cli->getGid(); if ((gid == AID_ROOT) || (gid == AID_LOG)) { return true; } // FYI We will typically be here for 'adb logcat' bool ret = false; char filename[1024]; snprintf(filename, sizeof(filename), "/proc/%d/status", cli->getPid()); FILE *file = fopen(filename, "r"); if (!file) { return ret; } bool foundGid = false; bool foundUid = false; char line[1024]; while (fgets(line, sizeof(line), file)) { static const char groups_string[] = "Groups:\t"; static const char uid_string[] = "Uid:\t"; static const char gid_string[] = "Gid:\t"; if (strncmp(groups_string, line, strlen(groups_string)) == 0) { ret = groupIsLog(line + strlen(groups_string)); if (!ret) { break; } } else if (strncmp(uid_string, line, strlen(uid_string)) == 0) { uid_t u[4] = { (uid_t) -1, (uid_t) -1, (uid_t) -1, (uid_t) -1}; sscanf(line + strlen(uid_string), "%u\t%u\t%u\t%u", &u[0], &u[1], &u[2], &u[3]); // Protect against PID reuse by checking that the UID is the same if ((uid != u[0]) || (uid != u[1]) || (uid != u[2]) || (uid != u[3])) { ret = false; break; } foundUid = true; } else if (strncmp(gid_string, line, strlen(gid_string)) == 0) { gid_t g[4] = { (gid_t) -1, (gid_t) -1, (gid_t) -1, (gid_t) -1}; sscanf(line + strlen(gid_string), "%u\t%u\t%u\t%u", &g[0], &g[1], &g[2], &g[3]); // Protect against PID reuse by checking that the GID is the same if ((gid != g[0]) || (gid != g[1]) || (gid != g[2]) || (gid != g[3])) { ret = false; break; } foundGid = true; } } fclose(file); if (!foundGid || !foundUid) { ret = false; } return ret; } logd/LogCommand.h +4 −1 Original line number Diff line number Diff line /* * Copyright (C) 2012-2013 The Android Open Source Project * Copyright (C) 2012-2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. Loading @@ -17,6 +17,7 @@ #ifndef _LOGD_COMMAND_H #define _LOGD_COMMAND_H #include <sysutils/SocketClient.h> #include <sysutils/FrameworkCommand.h> class LogCommand : public FrameworkCommand { Loading @@ -25,4 +26,6 @@ public: virtual ~LogCommand() {} }; bool clientHasLogCredentials(SocketClient * cli); #endif Loading
logd/CommandListener.cpp +7 −9 Original line number Diff line number Diff line /* * Copyright (C) 2012-2013 The Android Open Source Project * Copyright (C) 2012-2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. Loading @@ -24,10 +24,11 @@ #include <sys/socket.h> #include <sys/types.h> #include <sysutils/SocketClient.h> #include <private/android_filesystem_config.h> #include <sysutils/SocketClient.h> #include "CommandListener.h" #include "LogCommand.h" CommandListener::CommandListener(LogBuffer *buf, LogReader * /*reader*/, LogListener * /*swl*/) Loading Loading @@ -62,9 +63,7 @@ CommandListener::ClearCmd::ClearCmd(LogBuffer *buf) int CommandListener::ClearCmd::runCommand(SocketClient *cli, int argc, char **argv) { if ((cli->getUid() != AID_ROOT) && (cli->getGid() != AID_ROOT) && (cli->getGid() != AID_LOG)) { if (!clientHasLogCredentials(cli)) { cli->sendMsg("Permission Denied"); return 0; } Loading @@ -75,7 +74,7 @@ int CommandListener::ClearCmd::runCommand(SocketClient *cli, } int id = atoi(argv[1]); if ((id < LOG_ID_MIN) || (id >= LOG_ID_MAX)) { if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) { cli->sendMsg("Range Error"); return 0; } Loading @@ -85,7 +84,6 @@ int CommandListener::ClearCmd::runCommand(SocketClient *cli, return 0; } CommandListener::GetBufSizeCmd::GetBufSizeCmd(LogBuffer *buf) : LogCommand("getLogSize") , mBuf(*buf) Loading @@ -99,7 +97,7 @@ int CommandListener::GetBufSizeCmd::runCommand(SocketClient *cli, } int id = atoi(argv[1]); if ((id < LOG_ID_MIN) || (id >= LOG_ID_MAX)) { if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) { cli->sendMsg("Range Error"); return 0; } Loading @@ -124,7 +122,7 @@ int CommandListener::GetBufSizeUsedCmd::runCommand(SocketClient *cli, } int id = atoi(argv[1]); if ((id < LOG_ID_MIN) || (id >= LOG_ID_MAX)) { if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) { cli->sendMsg("Range Error"); return 0; } Loading
logd/FlushCommand.cpp +5 −6 Original line number Diff line number Diff line /* * Copyright (C) 2012-2013 The Android Open Source Project * Copyright (C) 2012-2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. Loading @@ -15,11 +15,12 @@ */ #include <stdlib.h> #include <private/android_filesystem_config.h> #include "FlushCommand.h" #include "LogBufferElement.h" #include "LogTimes.h" #include "LogCommand.h" #include "LogReader.h" #include "LogTimes.h" FlushCommand::FlushCommand(LogReader &reader, bool nonBlock, Loading Loading @@ -80,7 +81,5 @@ void FlushCommand::runSocketCommand(SocketClient *client) { } bool FlushCommand::hasReadLogs(SocketClient *client) { return (client->getUid() == AID_ROOT) || (client->getGid() == AID_ROOT) || (client->getGid() == AID_LOG); return clientHasLogCredentials(client); }
logd/LogCommand.cpp +110 −1 Original line number Diff line number Diff line /* * Copyright (C) 2012-2013 The Android Open Source Project * Copyright (C) 2012-2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. Loading @@ -14,8 +14,117 @@ * limitations under the License. */ #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <private/android_filesystem_config.h> #include "LogCommand.h" LogCommand::LogCommand(const char *cmd) : FrameworkCommand(cmd) { } // gets a list of supplementary group IDs associated with // the socket peer. This is implemented by opening // /proc/PID/status and look for the "Group:" line. // // This function introduces races especially since status // can change 'shape' while reading, the net result is err // on lack of permission. // // Race-free alternative is to introduce pairs of sockets // and threads for each command and reading, one each that // has open permissions, and one that has restricted // permissions. static bool groupIsLog(char *buf) { char *ptr; static const char ws[] = " \n"; bool ret = false; for (buf = strtok_r(buf, ws, &ptr); buf; buf = strtok_r(NULL, ws, &ptr)) { errno = 0; gid_t Gid = strtol(buf, NULL, 10); if (errno != 0) { return false; } if (Gid == AID_LOG) { ret = true; } } return ret; } bool clientHasLogCredentials(SocketClient * cli) { uid_t uid = cli->getUid(); if (uid == AID_ROOT) { return true; } gid_t gid = cli->getGid(); if ((gid == AID_ROOT) || (gid == AID_LOG)) { return true; } // FYI We will typically be here for 'adb logcat' bool ret = false; char filename[1024]; snprintf(filename, sizeof(filename), "/proc/%d/status", cli->getPid()); FILE *file = fopen(filename, "r"); if (!file) { return ret; } bool foundGid = false; bool foundUid = false; char line[1024]; while (fgets(line, sizeof(line), file)) { static const char groups_string[] = "Groups:\t"; static const char uid_string[] = "Uid:\t"; static const char gid_string[] = "Gid:\t"; if (strncmp(groups_string, line, strlen(groups_string)) == 0) { ret = groupIsLog(line + strlen(groups_string)); if (!ret) { break; } } else if (strncmp(uid_string, line, strlen(uid_string)) == 0) { uid_t u[4] = { (uid_t) -1, (uid_t) -1, (uid_t) -1, (uid_t) -1}; sscanf(line + strlen(uid_string), "%u\t%u\t%u\t%u", &u[0], &u[1], &u[2], &u[3]); // Protect against PID reuse by checking that the UID is the same if ((uid != u[0]) || (uid != u[1]) || (uid != u[2]) || (uid != u[3])) { ret = false; break; } foundUid = true; } else if (strncmp(gid_string, line, strlen(gid_string)) == 0) { gid_t g[4] = { (gid_t) -1, (gid_t) -1, (gid_t) -1, (gid_t) -1}; sscanf(line + strlen(gid_string), "%u\t%u\t%u\t%u", &g[0], &g[1], &g[2], &g[3]); // Protect against PID reuse by checking that the GID is the same if ((gid != g[0]) || (gid != g[1]) || (gid != g[2]) || (gid != g[3])) { ret = false; break; } foundGid = true; } } fclose(file); if (!foundGid || !foundUid) { ret = false; } return ret; }
logd/LogCommand.h +4 −1 Original line number Diff line number Diff line /* * Copyright (C) 2012-2013 The Android Open Source Project * Copyright (C) 2012-2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. Loading @@ -17,6 +17,7 @@ #ifndef _LOGD_COMMAND_H #define _LOGD_COMMAND_H #include <sysutils/SocketClient.h> #include <sysutils/FrameworkCommand.h> class LogCommand : public FrameworkCommand { Loading @@ -25,4 +26,6 @@ public: virtual ~LogCommand() {} }; bool clientHasLogCredentials(SocketClient * cli); #endif