diff options
author | Nick Kralevich <nnk@google.com> | 2016-02-24 15:50:52 -0800 |
---|---|---|
committer | Nick Kralevich <nnk@google.com> | 2016-02-25 12:38:51 -0800 |
commit | 9bcfd64b59f71641567464632b393dcd8aca6512 (patch) | |
tree | 7e45d9290d094cd0bb2a07c2441e98479b2fd765 /init/util.cpp | |
parent | 26815151008e863b754506da4a2ac7da471672c9 (diff) | |
download | core-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.cpp | 24 |
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); |