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) {
return stats.pidToName(pid);
}
uid_t pidToUid(pid_t pid) {
virtual uid_t pidToUid(pid_t pid) override {
return stats.pidToUid(pid);
}
virtual pid_t tidToPid(pid_t tid) override {
return stats.tidToPid(tid);
}
const char* uidToName(uid_t uid) {
return stats.uidToName(uid);
}

View File

@ -15,8 +15,15 @@
*/
#include "LogBufferInterface.h"
#include "LogUtils.h"
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,
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:
DISALLOW_COPY_AND_ASSIGN(LogBufferInterface);
};

View File

@ -14,7 +14,9 @@
* limitations under the License.
*/
#include <ctype.h>
#include <limits.h>
#include <stdio.h>
#include <sys/cdefs.h>
#include <sys/prctl.h>
#include <sys/socket.h>
@ -72,8 +74,11 @@ bool LogListener::onDataAvailable(SocketClient* cli) {
cmsg = CMSG_NXTHDR(&hdr, cmsg);
}
struct ucred fake_cred;
if (cred == NULL) {
return false;
cred = &fake_cred;
cred->pid = 0;
cred->uid = DEFAULT_OVERFLOWUID;
}
if (cred->uid == AID_LOGD) {
@ -96,6 +101,27 @@ bool LogListener::onDataAvailable(SocketClient* cli) {
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);
n -= sizeof(android_log_header_t);

View File

@ -20,6 +20,16 @@
#include <sysutils/SocketListener.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 {
LogBufferInterface* logbuf;
LogReader* reader;

View File

@ -14,6 +14,7 @@
* limitations under the License.
*/
#include <ctype.h>
#include <fcntl.h>
#include <inttypes.h>
#include <pwd.h>
@ -824,8 +825,10 @@ uid_t pidToUid(pid_t pid) {
FILE* fp = fopen(buffer, "r");
if (fp) {
while (fgets(buffer, sizeof(buffer), fp)) {
int uid;
if (sscanf(buffer, "Uid: %d", &uid) == 1) {
int uid = AID_LOGD;
char space = 0;
if ((sscanf(buffer, "Uid: %d%c", &uid, &space) == 2) &&
isspace(space)) {
fclose(fp);
return uid;
}
@ -834,12 +837,35 @@ uid_t pidToUid(pid_t pid) {
}
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) {
return pidTable.add(pid)->second.getUid();
}
pid_t LogStatistics::tidToPid(pid_t tid) {
return tidTable.add(tid)->second.getPid();
}
// caller must free character string
const char* LogStatistics::pidToName(pid_t pid) const {
// 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;
};
namespace android {
uid_t pidToUid(pid_t pid);
}
struct PidEntry : public EntryBaseDropped {
const pid_t pid;
uid_t uid;
@ -389,6 +385,13 @@ struct TidEntry : public EntryBaseDropped {
uid(android::pidToUid(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)
: EntryBaseDropped(element),
tid(element->getTid()),
@ -785,6 +788,7 @@ class LogStatistics {
// helper (must be locked directly or implicitly by mLogElementsLock)
const char* pidToName(pid_t pid) const;
uid_t pidToUid(pid_t pid);
pid_t tidToPid(pid_t tid);
const char* uidToName(uid_t uid) const;
};

View File

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