From b066fccc5c977f3e464676d58a7fa550d368f426 Mon Sep 17 00:00:00 2001 From: Mark Salyzyn Date: Fri, 5 May 2017 14:44:35 -0700 Subject: [PATCH] init: add "+passcred" for socket to set SO_PASSCRED In the init scripts for socket, the type can have a suffix of "+passcred" to request that the socket be bound to report SO_PASSCRED credentials as part of socket transactions. Test: gTest logd-unit-tests --gtest_filter=logd.statistics right after boot (fails without logd.rc change) Bug: 37985222 Change-Id: Ie5b50e99fb92fa9bec9a32463a0e6df26a968bfd --- init/descriptors.cpp | 11 +++++++---- init/property_service.cpp | 4 ++-- init/service.cpp | 4 +++- init/util.cpp | 14 +++++++++++--- init/util.h | 4 ++-- 5 files changed, 25 insertions(+), 12 deletions(-) diff --git a/init/descriptors.cpp b/init/descriptors.cpp index b2142ca99..6f729a372 100644 --- a/init/descriptors.cpp +++ b/init/descriptors.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -77,10 +78,12 @@ void SocketInfo::Clean() const { } int SocketInfo::Create(const std::string& context) const { - int flags = ((type() == "stream" ? SOCK_STREAM : - (type() == "dgram" ? SOCK_DGRAM : - SOCK_SEQPACKET))); - return create_socket(name().c_str(), flags, perm(), uid(), gid(), context.c_str(), sehandle); + auto types = android::base::Split(type(), "+"); + int flags = + ((types[0] == "stream" ? SOCK_STREAM : (types[0] == "dgram" ? SOCK_DGRAM : SOCK_SEQPACKET))); + bool passcred = types.size() > 1 && types[1] == "passcred"; + return CreateSocket(name().c_str(), flags, passcred, perm(), uid(), gid(), context.c_str(), + sehandle); } const std::string SocketInfo::key() const { diff --git a/init/property_service.cpp b/init/property_service.cpp index e01cd0b4b..77227505b 100644 --- a/init/property_service.cpp +++ b/init/property_service.cpp @@ -659,8 +659,8 @@ void load_system_props() { void start_property_service() { property_set("ro.property_service.version", "2"); - property_set_fd = create_socket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, - 0666, 0, 0, nullptr, sehandle); + property_set_fd = CreateSocket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, + false, 0666, 0, 0, nullptr, sehandle); if (property_set_fd == -1) { PLOG(ERROR) << "start_property_service socket creation failed"; exit(1); diff --git a/init/service.cpp b/init/service.cpp index 4d9edc445..296c04c71 100644 --- a/init/service.cpp +++ b/init/service.cpp @@ -525,7 +525,9 @@ bool Service::AddDescriptor(const std::vector& args, std::string* e // name type perm [ uid gid context ] bool Service::ParseSocket(const std::vector& args, std::string* err) { - if (args[2] != "dgram" && args[2] != "stream" && args[2] != "seqpacket") { + if (!android::base::StartsWith(args[2], "dgram") && + !android::base::StartsWith(args[2], "stream") && + !android::base::StartsWith(args[2], "seqpacket")) { *err = "socket type must be 'dgram', 'stream' or 'seqpacket'"; return false; } diff --git a/init/util.cpp b/init/util.cpp index e7f724b8f..5afe28554 100644 --- a/init/util.cpp +++ b/init/util.cpp @@ -78,13 +78,13 @@ bool DecodeUid(const std::string& name, uid_t* uid, std::string* err) { } /* - * create_socket - creates a Unix domain socket in ANDROID_SOCKET_DIR + * CreateSocket - creates a Unix domain socket in ANDROID_SOCKET_DIR * ("/dev/socket") as dictated in init.rc. This socket is inherited by the * daemon. We communicate the file descriptor's value via the environment * variable ANDROID_SOCKET_ENV_PREFIX ("ANDROID_SOCKET_foo"). */ -int create_socket(const char* name, int type, mode_t perm, uid_t uid, gid_t gid, - const char* socketcon, selabel_handle* sehandle) { +int CreateSocket(const char* name, int type, bool passcred, mode_t perm, uid_t uid, gid_t gid, + const char* socketcon, selabel_handle* sehandle) { if (socketcon) { if (setsockcreatecon(socketcon) == -1) { PLOG(ERROR) << "setsockcreatecon(\"" << socketcon << "\") failed"; @@ -118,6 +118,14 @@ int create_socket(const char* name, int type, mode_t perm, uid_t uid, gid_t gid, } } + if (passcred) { + int on = 1; + if (setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on))) { + PLOG(ERROR) << "Failed to set SO_PASSCRED '" << name << "'"; + return -1; + } + } + int ret = bind(fd, (struct sockaddr *) &addr, sizeof (addr)); int savederrno = errno; diff --git a/init/util.h b/init/util.h index 4c33909f0..f3252c294 100644 --- a/init/util.h +++ b/init/util.h @@ -35,8 +35,8 @@ const std::string kAndroidDtDir("/proc/device-tree/firmware/android/"); using android::base::boot_clock; using namespace std::chrono_literals; -int create_socket(const char* name, int type, mode_t perm, uid_t uid, gid_t gid, - const char* socketcon, selabel_handle* sehandle); +int CreateSocket(const char* name, int type, bool passcred, mode_t perm, uid_t uid, gid_t gid, + const char* socketcon, selabel_handle* sehandle); bool ReadFile(const std::string& path, std::string* content, std::string* err); bool WriteFile(const std::string& path, const std::string& content, std::string* err);