summaryrefslogtreecommitdiffstats
path: root/init/util.cpp
diff options
context:
space:
mode:
authorNick Kralevich <nnk@google.com>2016-02-24 15:50:52 -0800
committerNick Kralevich <nnk@google.com>2016-02-25 12:38:51 -0800
commit9bcfd64b59f71641567464632b393dcd8aca6512 (patch)
tree7e45d9290d094cd0bb2a07c2441e98479b2fd765 /init/util.cpp
parent26815151008e863b754506da4a2ac7da471672c9 (diff)
downloadcore-9bcfd64b59f71641567464632b393dcd8aca6512.tar.gz
core-9bcfd64b59f71641567464632b393dcd8aca6512.tar.bz2
core-9bcfd64b59f71641567464632b393dcd8aca6512.zip
init: harden socket creation against symlinks
Instead of using chown, use the symlink safe lchown. Instead of using chmod, use the symlink safe fchmodat with AT_SYMLINK_NOFOLLOW. Fix a bug where the SELinux filesystem creation context may not be restored, and some memory not freed, if bind() fails. Check the return values from the chown/chmod calls and unlink the files if it ever fails. (cherrypicked from commit ab5629c197ae278992039a9685df047fe34232b8) Bug: 27337831 Change-Id: I28c5f4dee55aa706437eb51ad403c1fbf56138de
Diffstat (limited to 'init/util.cpp')
-rw-r--r--init/util.cpp24
1 files changed, 17 insertions, 7 deletions
diff --git a/init/util.cpp b/init/util.cpp
index aefdf8fee..84b415552 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -102,7 +102,7 @@ int create_socket(const char *name, int type, mode_t perm, uid_t uid,
gid_t gid, const char *socketcon)
{
struct sockaddr_un addr;
- int fd, ret;
+ int fd, ret, savederrno;
char *filecon;
if (socketcon) {
@@ -140,16 +140,26 @@ int create_socket(const char *name, int type, mode_t perm, uid_t uid,
}
ret = bind(fd, (struct sockaddr *) &addr, sizeof (addr));
- if (ret) {
- ERROR("Failed to bind socket '%s': %s\n", name, strerror(errno));
- goto out_unlink;
- }
+ savederrno = errno;
setfscreatecon(NULL);
freecon(filecon);
- chown(addr.sun_path, uid, gid);
- chmod(addr.sun_path, perm);
+ if (ret) {
+ ERROR("Failed to bind socket '%s': %s\n", name, strerror(savederrno));
+ goto out_unlink;
+ }
+
+ ret = lchown(addr.sun_path, uid, gid);
+ if (ret) {
+ ERROR("Failed to lchown socket '%s': %s\n", addr.sun_path, strerror(errno));
+ goto out_unlink;
+ }
+ ret = fchmodat(AT_FDCWD, addr.sun_path, perm, AT_SYMLINK_NOFOLLOW);
+ if (ret) {
+ ERROR("Failed to fchmodat socket '%s': %s\n", addr.sun_path, strerror(errno));
+ goto out_unlink;
+ }
INFO("Created socket '%s' with mode '%o', user '%d', group '%d'\n",
addr.sun_path, perm, uid, gid);