Merge "sdcard: Fix compilation with FUSE_TRACE == 1."
diff --git a/include/utils/LruCache.h b/include/utils/LruCache.h
index ed96fe4..f4e225a 100644
--- a/include/utils/LruCache.h
+++ b/include/utils/LruCache.h
@@ -56,36 +56,55 @@
private:
LruCache(const LruCache& that); // disallow copy constructor
- struct Entry {
+ // Super class so that we can have entries having only a key reference, for searches.
+ class KeyedEntry {
+ public:
+ virtual const TKey& getKey() const = 0;
+ // Make sure the right destructor is executed so that keys and values are deleted.
+ virtual ~KeyedEntry() {}
+ };
+
+ class Entry final : public KeyedEntry {
+ public:
TKey key;
TValue value;
Entry* parent;
Entry* child;
- Entry(TKey key_, TValue value_) : key(key_), value(value_), parent(NULL), child(NULL) {
+ Entry(TKey _key, TValue _value) : key(_key), value(_value), parent(NULL), child(NULL) {
}
- const TKey& getKey() const { return key; }
+ const TKey& getKey() const final { return key; }
};
- struct HashForEntry : public std::unary_function<Entry*, hash_t> {
- size_t operator() (const Entry* entry) const {
- return hash_type(entry->key);
+ class EntryForSearch : public KeyedEntry {
+ public:
+ const TKey& key;
+ EntryForSearch(const TKey& key_) : key(key_) {
+ }
+ const TKey& getKey() const final { return key; }
+ };
+
+ struct HashForEntry : public std::unary_function<KeyedEntry*, hash_t> {
+ size_t operator() (const KeyedEntry* entry) const {
+ return hash_type(entry->getKey());
};
};
- struct EqualityForHashedEntries : public std::unary_function<Entry*, hash_t> {
- bool operator() (const Entry* lhs, const Entry* rhs) const {
- return lhs->key == rhs->key;
+ struct EqualityForHashedEntries : public std::unary_function<KeyedEntry*, hash_t> {
+ bool operator() (const KeyedEntry* lhs, const KeyedEntry* rhs) const {
+ return lhs->getKey() == rhs->getKey();
};
};
- typedef std::unordered_set<Entry*, HashForEntry, EqualityForHashedEntries> LruCacheSet;
+ // All entries in the set will be Entry*. Using the weaker KeyedEntry as to allow entries
+ // that have only a key reference, for searching.
+ typedef std::unordered_set<KeyedEntry*, HashForEntry, EqualityForHashedEntries> LruCacheSet;
void attachToCache(Entry& entry);
void detachFromCache(Entry& entry);
typename LruCacheSet::iterator findByKey(const TKey& key) {
- Entry entryForSearch(key, mNullValue);
+ EntryForSearch entryForSearch(key);
typename LruCacheSet::iterator result = mSet->find(&entryForSearch);
return result;
}
@@ -124,11 +143,13 @@
}
const TValue& value() const {
- return (*mIterator)->value;
+ // All the elements in the set are of type Entry. See comment in the definition
+ // of LruCacheSet above.
+ return reinterpret_cast<Entry *>(*mIterator)->value;
}
const TKey& key() const {
- return (*mIterator)->key;
+ return (*mIterator)->getKey();
}
private:
const LruCache<TKey, TValue>& mCache;
@@ -171,7 +192,9 @@
if (find_result == mSet->end()) {
return mNullValue;
}
- Entry *entry = *find_result;
+ // All the elements in the set are of type Entry. See comment in the definition
+ // of LruCacheSet above.
+ Entry *entry = reinterpret_cast<Entry*>(*find_result);
detachFromCache(*entry);
attachToCache(*entry);
return entry->value;
@@ -199,7 +222,9 @@
if (find_result == mSet->end()) {
return false;
}
- Entry* entry = *find_result;
+ // All the elements in the set are of type Entry. See comment in the definition
+ // of LruCacheSet above.
+ Entry* entry = reinterpret_cast<Entry*>(*find_result);
mSet->erase(entry);
if (mListener) {
(*mListener)(entry->key, entry->value);
diff --git a/libcutils/iosched_policy.c b/libcutils/iosched_policy.c
index 71bc94b..13c2ceb 100644
--- a/libcutils/iosched_policy.c
+++ b/libcutils/iosched_policy.c
@@ -24,7 +24,8 @@
#include <cutils/iosched_policy.h>
#if defined(__ANDROID__)
-#include <linux/ioprio.h>
+#define IOPRIO_WHO_PROCESS (1)
+#define IOPRIO_CLASS_SHIFT (13)
#include <sys/syscall.h>
#define __android_unused
#else
diff --git a/libpackagelistparser/Android.bp b/libpackagelistparser/Android.bp
new file mode 100644
index 0000000..70ff528
--- /dev/null
+++ b/libpackagelistparser/Android.bp
@@ -0,0 +1,13 @@
+cc_library {
+
+ name: "libpackagelistparser",
+ srcs: ["packagelistparser.c"],
+ shared_libs: ["liblog"],
+ local_include_dirs: ["include"],
+ export_include_dirs: ["include"],
+
+ clang: true,
+ sanitize: {
+ misc_undefined: ["integer"],
+ },
+}
diff --git a/libpackagelistparser/Android.mk b/libpackagelistparser/Android.mk
deleted file mode 100644
index c8be050..0000000
--- a/libpackagelistparser/Android.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-#########################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libpackagelistparser
-LOCAL_MODULE_TAGS := optional
-LOCAL_SRC_FILES := packagelistparser.c
-LOCAL_SHARED_LIBRARIES := liblog
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-
-LOCAL_CLANG := true
-LOCAL_SANITIZE := integer
-
-include $(BUILD_SHARED_LIBRARY)
-
-#########################
-include $(CLEAR_VARS)
-
-
-LOCAL_MODULE := libpackagelistparser
-LOCAL_MODULE_TAGS := optional
-LOCAL_SRC_FILES := packagelistparser.c
-LOCAL_STATIC_LIBRARIES := liblog
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-
-LOCAL_CLANG := true
-LOCAL_SANITIZE := integer
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/libutils/tests/LruCache_test.cpp b/libutils/tests/LruCache_test.cpp
index dd95c57..de440fd 100644
--- a/libutils/tests/LruCache_test.cpp
+++ b/libutils/tests/LruCache_test.cpp
@@ -80,6 +80,14 @@
}
};
+struct KeyFailsOnCopy : public ComplexKey {
+ public:
+ KeyFailsOnCopy(const KeyFailsOnCopy& key) : ComplexKey(key) {
+ ADD_FAILURE();
+ }
+ KeyFailsOnCopy(int key) : ComplexKey(key) { }
+};
+
} // namespace
@@ -95,6 +103,10 @@
return hash_type(*value.ptr);
}
+template<> inline android::hash_t hash_type(const KeyFailsOnCopy& value) {
+ return hash_type<ComplexKey>(value);
+}
+
class EntryRemovedCallback : public OnEntryRemoved<SimpleKey, StringValue> {
public:
EntryRemovedCallback() : callbackCount(0), lastKey(-1), lastValue(NULL) { }
@@ -437,4 +449,10 @@
EXPECT_EQ(std::unordered_set<int>({ 4, 5, 6 }), returnedValues);
}
+TEST_F(LruCacheTest, DontCopyKeyInGet) {
+ LruCache<KeyFailsOnCopy, KeyFailsOnCopy> cache(1);
+ // Check that get doesn't copy the key
+ cache.get(KeyFailsOnCopy(0));
+}
+
}
diff --git a/logcat/logpersist b/logcat/logpersist
index e9982e2..f0e7d42 100755
--- a/logcat/logpersist
+++ b/logcat/logpersist
@@ -17,6 +17,7 @@
;;
esac
+log_tag_property=persist.log.tag
data=/data/misc/logd
service=logcatd
size_default=256
@@ -65,6 +66,9 @@
exit 1
fi
+log_tag="`getprop ${log_tag_property}`"
+logd_logpersistd="`getprop ${property}`"
+
case ${progname} in
*.cat)
if [ -n "${size}${buffer}" -o "true" = "${clear}" ]; then
@@ -123,6 +127,12 @@
while [ "clear" = "`getprop ${property#persist.}`" ]; do
continue
done
+ # Tell Settings that we are back on again if we turned logging off
+ tag="${log_tag#Settings}"
+ if [ X"${log_tag}" != X"${tag}" ]; then
+ echo "WARNING: enabling logd service" >&2
+ setprop ${log_tag_property} "${tag#,}"
+ fi
# ${service}.rc does the heavy lifting with the following trigger
setprop ${property} ${service}
# 20ms done, to permit process feedback check
@@ -158,3 +168,9 @@
echo "ERROR: Unexpected command ${0##*/} ${args}" >&2
exit 1
esac
+
+if [ X"${log_tag}" != X"`getprop ${log_tag_property}`" ] ||
+ [ X"${logd_logpersistd}" != X"`getprop ${property}`" ]; then
+ echo "WARNING: killing Settings" >&2
+ am force-stop com.android.settings
+fi
diff --git a/logd/Android.mk b/logd/Android.mk
index 84ea7a2..3348890 100644
--- a/logd/Android.mk
+++ b/logd/Android.mk
@@ -28,7 +28,8 @@
liblog \
libcutils \
libbase \
- libpackagelistparser
+ libpackagelistparser \
+ libminijail
# This is what we want to do:
# event_logtags = $(shell \
diff --git a/logd/LogAudit.cpp b/logd/LogAudit.cpp
index 4eb5e83..8859d55 100644
--- a/logd/LogAudit.cpp
+++ b/logd/LogAudit.cpp
@@ -181,16 +181,72 @@
struct iovec iov[3];
static const char log_info[] = { KMSG_PRIORITY(LOG_INFO) };
static const char log_warning[] = { KMSG_PRIORITY(LOG_WARNING) };
+ static const char newline[] = "\n";
- iov[0].iov_base = info ? const_cast<char *>(log_info)
- : const_cast<char *>(log_warning);
- iov[0].iov_len = info ? sizeof(log_info) : sizeof(log_warning);
- iov[1].iov_base = str;
- iov[1].iov_len = strlen(str);
- iov[2].iov_base = const_cast<char *>("\n");
- iov[2].iov_len = 1;
+ // Dedupe messages, checking for identical messages starting with avc:
+ static unsigned count;
+ static char *last_str;
+ static bool last_info;
- writev(fdDmesg, iov, sizeof(iov) / sizeof(iov[0]));
+ if (last_str != NULL) {
+ static const char avc[] = "): avc: ";
+ char *avcl = strstr(last_str, avc);
+ bool skip = false;
+
+ if (avcl) {
+ char *avcr = strstr(str, avc);
+
+ skip = avcr && !strcmp(avcl + strlen(avc), avcr + strlen(avc));
+ if (skip) {
+ ++count;
+ free(last_str);
+ last_str = strdup(str);
+ last_info = info;
+ }
+ }
+ if (!skip) {
+ static const char resume[] = " duplicate messages suppressed\n";
+
+ iov[0].iov_base = last_info ?
+ const_cast<char *>(log_info) :
+ const_cast<char *>(log_warning);
+ iov[0].iov_len = last_info ?
+ sizeof(log_info) :
+ sizeof(log_warning);
+ iov[1].iov_base = last_str;
+ iov[1].iov_len = strlen(last_str);
+ if (count > 1) {
+ iov[2].iov_base = const_cast<char *>(resume);
+ iov[2].iov_len = strlen(resume);
+ } else {
+ iov[2].iov_base = const_cast<char *>(newline);
+ iov[2].iov_len = strlen(newline);
+ }
+
+ writev(fdDmesg, iov, sizeof(iov) / sizeof(iov[0]));
+ free(last_str);
+ last_str = NULL;
+ }
+ }
+ if (last_str == NULL) {
+ count = 0;
+ last_str = strdup(str);
+ last_info = info;
+ }
+ if (count == 0) {
+ iov[0].iov_base = info ?
+ const_cast<char *>(log_info) :
+ const_cast<char *>(log_warning);
+ iov[0].iov_len = info ?
+ sizeof(log_info) :
+ sizeof(log_warning);
+ iov[1].iov_base = str;
+ iov[1].iov_len = strlen(str);
+ iov[2].iov_base = const_cast<char *>(newline);
+ iov[2].iov_len = strlen(newline);
+
+ writev(fdDmesg, iov, sizeof(iov) / sizeof(iov[0]));
+ }
}
pid_t pid = getpid();
diff --git a/logd/main.cpp b/logd/main.cpp
index 69ba896..b69927d 100644
--- a/logd/main.cpp
+++ b/logd/main.cpp
@@ -36,12 +36,15 @@
#include <cstdbool>
#include <memory>
+#include <android-base/macros.h>
#include <cutils/properties.h>
#include <cutils/sched_policy.h>
#include <cutils/sockets.h>
+#include <libminijail.h>
#include <log/event_tag_map.h>
#include <packagelistparser/packagelistparser.h>
#include <private/android_filesystem_config.h>
+#include <scoped_minijail.h>
#include <utils/threads.h>
#include "CommandListener.h"
@@ -58,14 +61,14 @@
'>'
//
-// The service is designed to be run by init, it does not respond well
+// The service is designed to be run by init, it does not respond well
// to starting up manually. When starting up manually the sockets will
// fail to open typically for one of the following reasons:
// EADDRINUSE if logger is running.
// EACCESS if started without precautions (below)
//
// Here is a cookbook procedure for starting up logd manually assuming
-// init is out of the way, pedantically all permissions and selinux
+// init is out of the way, pedantically all permissions and SELinux
// security is put back in place:
//
// setenforce 0
@@ -102,43 +105,13 @@
return -1;
}
- if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
- return -1;
- }
-
gid_t groups[] = { AID_READPROC };
-
- if (setgroups(sizeof(groups) / sizeof(groups[0]), groups) == -1) {
- return -1;
- }
-
- if (setgid(AID_LOGD) != 0) {
- return -1;
- }
-
- if (setuid(AID_LOGD) != 0) {
- return -1;
- }
-
- struct __user_cap_header_struct capheader;
- struct __user_cap_data_struct capdata[2];
- memset(&capheader, 0, sizeof(capheader));
- memset(&capdata, 0, sizeof(capdata));
- capheader.version = _LINUX_CAPABILITY_VERSION_3;
- capheader.pid = 0;
-
- capdata[CAP_TO_INDEX(CAP_SYSLOG)].permitted = CAP_TO_MASK(CAP_SYSLOG);
- capdata[CAP_TO_INDEX(CAP_AUDIT_CONTROL)].permitted |= CAP_TO_MASK(CAP_AUDIT_CONTROL);
-
- capdata[0].effective = capdata[0].permitted;
- capdata[1].effective = capdata[1].permitted;
- capdata[0].inheritable = 0;
- capdata[1].inheritable = 0;
-
- if (capset(&capheader, &capdata[0]) < 0) {
- return -1;
- }
-
+ ScopedMinijail j(minijail_new());
+ minijail_set_supplementary_gids(j.get(), arraysize(groups), groups);
+ minijail_change_uid(j.get(), AID_LOGD);
+ minijail_change_gid(j.get(), AID_LOGD);
+ minijail_use_caps(j.get(), CAP_TO_MASK(CAP_SYSLOG) | CAP_TO_MASK(CAP_AUDIT_CONTROL));
+ minijail_enter(j.get());
return 0;
}