Merge "logd: validate and fill in socket credentials" am: 17254f59a2

am: 1423041905

Change-Id: I80c1ec043d288ae037a208702c639acf0042fc27
This commit is contained in:
Mark Salyzyn 2017-05-11 23:40:19 +00:00 committed by android-build-merger
commit b3b67adafd
8 changed files with 90 additions and 9 deletions

View file

@ -159,9 +159,12 @@ class LogBuffer : public LogBufferInterface {
const char* pidToName(pid_t pid) { const char* pidToName(pid_t pid) {
return stats.pidToName(pid); return stats.pidToName(pid);
} }
uid_t pidToUid(pid_t pid) { virtual uid_t pidToUid(pid_t pid) override {
return stats.pidToUid(pid); return stats.pidToUid(pid);
} }
virtual pid_t tidToPid(pid_t tid) override {
return stats.tidToPid(tid);
}
const char* uidToName(uid_t uid) { const char* uidToName(uid_t uid) {
return stats.uidToName(uid); return stats.uidToName(uid);
} }

View file

@ -15,8 +15,15 @@
*/ */
#include "LogBufferInterface.h" #include "LogBufferInterface.h"
#include "LogUtils.h"
LogBufferInterface::LogBufferInterface() { LogBufferInterface::LogBufferInterface() {
} }
LogBufferInterface::~LogBufferInterface() { LogBufferInterface::~LogBufferInterface() {
} }
uid_t LogBufferInterface::pidToUid(pid_t pid) {
return android::pidToUid(pid);
}
pid_t LogBufferInterface::tidToPid(pid_t tid) {
return android::tidToPid(tid);
}

View file

@ -33,6 +33,9 @@ class LogBufferInterface {
virtual int log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid, virtual int log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid,
pid_t tid, const char* msg, unsigned short len) = 0; pid_t tid, const char* msg, unsigned short len) = 0;
virtual uid_t pidToUid(pid_t pid);
virtual pid_t tidToPid(pid_t tid);
private: private:
DISALLOW_COPY_AND_ASSIGN(LogBufferInterface); DISALLOW_COPY_AND_ASSIGN(LogBufferInterface);
}; };

View file

@ -14,7 +14,9 @@
* limitations under the License. * limitations under the License.
*/ */
#include <ctype.h>
#include <limits.h> #include <limits.h>
#include <stdio.h>
#include <sys/cdefs.h> #include <sys/cdefs.h>
#include <sys/prctl.h> #include <sys/prctl.h>
#include <sys/socket.h> #include <sys/socket.h>
@ -72,8 +74,11 @@ bool LogListener::onDataAvailable(SocketClient* cli) {
cmsg = CMSG_NXTHDR(&hdr, cmsg); cmsg = CMSG_NXTHDR(&hdr, cmsg);
} }
struct ucred fake_cred;
if (cred == NULL) { if (cred == NULL) {
return false; cred = &fake_cred;
cred->pid = 0;
cred->uid = DEFAULT_OVERFLOWUID;
} }
if (cred->uid == AID_LOGD) { if (cred->uid == AID_LOGD) {
@ -96,6 +101,27 @@ bool LogListener::onDataAvailable(SocketClient* cli) {
return false; return false;
} }
// Check credential validity, acquire corrected details if not supplied.
if (cred->pid == 0) {
cred->pid = logbuf ? logbuf->tidToPid(header->tid)
: android::tidToPid(header->tid);
if (cred->pid == getpid()) {
// We expect that /proc/<tid>/ is accessible to self even without
// readproc group, so that we will always drop messages that come
// from any of our logd threads and their library calls.
return false; // ignore self
}
}
if (cred->uid == DEFAULT_OVERFLOWUID) {
uid_t uid =
logbuf ? logbuf->pidToUid(cred->pid) : android::pidToUid(cred->pid);
if (uid == AID_LOGD) {
uid = logbuf ? logbuf->pidToUid(header->tid)
: android::pidToUid(cred->pid);
}
if (uid != AID_LOGD) cred->uid = uid;
}
char* msg = ((char*)buffer) + sizeof(android_log_header_t); char* msg = ((char*)buffer) + sizeof(android_log_header_t);
n -= sizeof(android_log_header_t); n -= sizeof(android_log_header_t);

View file

@ -20,6 +20,16 @@
#include <sysutils/SocketListener.h> #include <sysutils/SocketListener.h>
#include "LogReader.h" #include "LogReader.h"
// DEFAULT_OVERFLOWUID is defined in linux/highuid.h, which is not part of
// the uapi headers for userspace to use. This value is filled in on the
// out-of-band socket credentials if the OS fails to find one available.
// One of the causes of this is if SO_PASSCRED is set, all the packets before
// that point will have this value. We also use it in a fake credential if
// no socket credentials are supplied.
#ifndef DEFAULT_OVERFLOWUID
#define DEFAULT_OVERFLOWUID 65534
#endif
class LogListener : public SocketListener { class LogListener : public SocketListener {
LogBufferInterface* logbuf; LogBufferInterface* logbuf;
LogReader* reader; LogReader* reader;

View file

@ -14,6 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
#include <ctype.h>
#include <fcntl.h> #include <fcntl.h>
#include <inttypes.h> #include <inttypes.h>
#include <pwd.h> #include <pwd.h>
@ -824,8 +825,10 @@ uid_t pidToUid(pid_t pid) {
FILE* fp = fopen(buffer, "r"); FILE* fp = fopen(buffer, "r");
if (fp) { if (fp) {
while (fgets(buffer, sizeof(buffer), fp)) { while (fgets(buffer, sizeof(buffer), fp)) {
int uid; int uid = AID_LOGD;
if (sscanf(buffer, "Uid: %d", &uid) == 1) { char space = 0;
if ((sscanf(buffer, "Uid: %d%c", &uid, &space) == 2) &&
isspace(space)) {
fclose(fp); fclose(fp);
return uid; return uid;
} }
@ -834,12 +837,35 @@ uid_t pidToUid(pid_t pid) {
} }
return AID_LOGD; // associate this with the logger return AID_LOGD; // associate this with the logger
} }
pid_t tidToPid(pid_t tid) {
char buffer[512];
snprintf(buffer, sizeof(buffer), "/proc/%u/status", tid);
FILE* fp = fopen(buffer, "r");
if (fp) {
while (fgets(buffer, sizeof(buffer), fp)) {
int pid = tid;
char space = 0;
if ((sscanf(buffer, "Tgid: %d%c", &pid, &space) == 2) &&
isspace(space)) {
fclose(fp);
return pid;
}
}
fclose(fp);
}
return tid;
}
} }
uid_t LogStatistics::pidToUid(pid_t pid) { uid_t LogStatistics::pidToUid(pid_t pid) {
return pidTable.add(pid)->second.getUid(); return pidTable.add(pid)->second.getUid();
} }
pid_t LogStatistics::tidToPid(pid_t tid) {
return tidTable.add(tid)->second.getPid();
}
// caller must free character string // caller must free character string
const char* LogStatistics::pidToName(pid_t pid) const { const char* LogStatistics::pidToName(pid_t pid) const {
// An inconvenient truth ... getName() can alter the object // An inconvenient truth ... getName() can alter the object

View file

@ -306,10 +306,6 @@ struct UidEntry : public EntryBaseDropped {
std::string format(const LogStatistics& stat, log_id_t id) const; std::string format(const LogStatistics& stat, log_id_t id) const;
}; };
namespace android {
uid_t pidToUid(pid_t pid);
}
struct PidEntry : public EntryBaseDropped { struct PidEntry : public EntryBaseDropped {
const pid_t pid; const pid_t pid;
uid_t uid; uid_t uid;
@ -389,6 +385,13 @@ struct TidEntry : public EntryBaseDropped {
uid(android::pidToUid(tid)), uid(android::pidToUid(tid)),
name(android::tidToName(tid)) { name(android::tidToName(tid)) {
} }
TidEntry(pid_t tid)
: EntryBaseDropped(),
tid(tid),
pid(android::tidToPid(tid)),
uid(android::pidToUid(tid)),
name(android::tidToName(tid)) {
}
explicit TidEntry(const LogBufferElement* element) explicit TidEntry(const LogBufferElement* element)
: EntryBaseDropped(element), : EntryBaseDropped(element),
tid(element->getTid()), tid(element->getTid()),
@ -785,6 +788,7 @@ class LogStatistics {
// helper (must be locked directly or implicitly by mLogElementsLock) // helper (must be locked directly or implicitly by mLogElementsLock)
const char* pidToName(pid_t pid) const; const char* pidToName(pid_t pid) const;
uid_t pidToUid(pid_t pid); uid_t pidToUid(pid_t pid);
pid_t tidToPid(pid_t tid);
const char* uidToName(uid_t uid) const; const char* uidToName(uid_t uid) const;
}; };

View file

@ -38,6 +38,8 @@ size_t sizesTotal();
// Caller must own and free returned value // Caller must own and free returned value
char* pidToName(pid_t pid); char* pidToName(pid_t pid);
char* tidToName(pid_t tid); char* tidToName(pid_t tid);
uid_t pidToUid(pid_t pid);
pid_t tidToPid(pid_t tid);
// Furnished in LogTags.cpp. Thread safe. // Furnished in LogTags.cpp. Thread safe.
const char* tagToName(uint32_t tag); const char* tagToName(uint32_t tag);