1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* 2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * you may not use this file except in compliance with the License. 6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * You may obtain a copy of the License at 7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * See the License for the specific language governing permissions and 14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * limitations under the License. 15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdarg.h> 18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h> 19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h> 20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h> 21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <fcntl.h> 22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <ctype.h> 23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h> 24504bc5175a8fe5a2f2552903afee761a86283cf4Colin Cross#include <time.h> 25ae76f6dbcf3dfd6eda223911f91f4a1316433771Nick Kralevich#include <ftw.h> 26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 27e46f9d510db9351682cf17c49115110870147335Stephen Smalley#include <selinux/label.h> 28dbd37f2e1da5b27ef1ad6d0cc9580e6893560f5fStephen Smalley#include <selinux/android.h> 29e46f9d510db9351682cf17c49115110870147335Stephen Smalley 30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/stat.h> 31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/types.h> 32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/socket.h> 33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/un.h> 34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 354f71319df011d796a60a43fc1bc68e16fbf7d321Elliott Hughes#include <android-base/file.h> 364f71319df011d796a60a43fc1bc68e16fbf7d321Elliott Hughes#include <android-base/strings.h> 37c007bc3856a4cf86b8f610eb045f26a9dedc2894Dan Albert 38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* for ANDROID_SOCKET_* */ 39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <cutils/sockets.h> 404f71319df011d796a60a43fc1bc68e16fbf7d321Elliott Hughes#include <android-base/stringprintf.h> 41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <private/android_filesystem_config.h> 43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 44e46f9d510db9351682cf17c49115110870147335Stephen Smalley#include "init.h" 45ed8a7d84428ec945c48b6b53dc5a3a18fabaf683Colin Cross#include "log.h" 46b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry#include "property_service.h" 47f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross#include "util.h" 48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* 50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * android_name_to_id - returns the integer uid/gid associated with the given 51d2104df69b464721a17c21b4cd27931dc3bca612Nick Kralevich * name, or UINT_MAX on error. 52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic unsigned int android_name_to_id(const char *name) 54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 55de7f1ad86f532e79ea2a9f77b0147406a9ad971bEdwin Vane const struct android_id_info *info = android_ids; 56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned int n; 57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project for (n = 0; n < android_id_count; n++) { 59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (!strcmp(info[n].name, name)) 60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return info[n].aid; 61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 63d2104df69b464721a17c21b4cd27931dc3bca612Nick Kralevich return UINT_MAX; 64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 66d2104df69b464721a17c21b4cd27931dc3bca612Nick Kralevichstatic unsigned int do_decode_uid(const char *s) 67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned int v; 69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (!s || *s == '\0') 71d2104df69b464721a17c21b4cd27931dc3bca612Nick Kralevich return UINT_MAX; 72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (isalpha(s[0])) 73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return android_name_to_id(s); 74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project errno = 0; 76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project v = (unsigned int) strtoul(s, 0, 0); 77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (errno) 78d2104df69b464721a17c21b4cd27931dc3bca612Nick Kralevich return UINT_MAX; 79d2104df69b464721a17c21b4cd27931dc3bca612Nick Kralevich return v; 80d2104df69b464721a17c21b4cd27931dc3bca612Nick Kralevich} 81d2104df69b464721a17c21b4cd27931dc3bca612Nick Kralevich 82d2104df69b464721a17c21b4cd27931dc3bca612Nick Kralevich/* 83d2104df69b464721a17c21b4cd27931dc3bca612Nick Kralevich * decode_uid - decodes and returns the given string, which can be either the 84d2104df69b464721a17c21b4cd27931dc3bca612Nick Kralevich * numeric or name representation, into the integer uid or gid. Returns 85d2104df69b464721a17c21b4cd27931dc3bca612Nick Kralevich * UINT_MAX on error. 86d2104df69b464721a17c21b4cd27931dc3bca612Nick Kralevich */ 87d2104df69b464721a17c21b4cd27931dc3bca612Nick Kralevichunsigned int decode_uid(const char *s) { 88d2104df69b464721a17c21b4cd27931dc3bca612Nick Kralevich unsigned int v = do_decode_uid(s); 89d2104df69b464721a17c21b4cd27931dc3bca612Nick Kralevich if (v == UINT_MAX) { 90d2104df69b464721a17c21b4cd27931dc3bca612Nick Kralevich ERROR("decode_uid: Unable to find UID for '%s'. Returning UINT_MAX\n", s); 91d2104df69b464721a17c21b4cd27931dc3bca612Nick Kralevich } 92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return v; 93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* 96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * create_socket - creates a Unix domain socket in ANDROID_SOCKET_DIR 97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * ("/dev/socket") as dictated in init.rc. This socket is inherited by the 98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * daemon. We communicate the file descriptor's value via the environment 99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * variable ANDROID_SOCKET_ENV_PREFIX<name> ("ANDROID_SOCKET_foo"). 100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 1018348d279c7ce1a2453965ba7f05a7b818d58886cStephen Smalleyint create_socket(const char *name, int type, mode_t perm, uid_t uid, 1028348d279c7ce1a2453965ba7f05a7b818d58886cStephen Smalley gid_t gid, const char *socketcon) 103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct sockaddr_un addr; 105ab5629c197ae278992039a9685df047fe34232b8Nick Kralevich int fd, ret, savederrno; 1068348d279c7ce1a2453965ba7f05a7b818d58886cStephen Smalley char *filecon; 1078348d279c7ce1a2453965ba7f05a7b818d58886cStephen Smalley 10883ccb1c76b2b88f62bfba2c58e2edd419b089756Nick Kralevich if (socketcon) { 10983ccb1c76b2b88f62bfba2c58e2edd419b089756Nick Kralevich if (setsockcreatecon(socketcon) == -1) { 11083ccb1c76b2b88f62bfba2c58e2edd419b089756Nick Kralevich ERROR("setsockcreatecon(\"%s\") failed: %s\n", socketcon, strerror(errno)); 11183ccb1c76b2b88f62bfba2c58e2edd419b089756Nick Kralevich return -1; 11283ccb1c76b2b88f62bfba2c58e2edd419b089756Nick Kralevich } 11383ccb1c76b2b88f62bfba2c58e2edd419b089756Nick Kralevich } 114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fd = socket(PF_UNIX, type, 0); 116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (fd < 0) { 117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ERROR("Failed to open socket '%s': %s\n", name, strerror(errno)); 118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1218348d279c7ce1a2453965ba7f05a7b818d58886cStephen Smalley if (socketcon) 1228348d279c7ce1a2453965ba7f05a7b818d58886cStephen Smalley setsockcreatecon(NULL); 1238348d279c7ce1a2453965ba7f05a7b818d58886cStephen Smalley 124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memset(&addr, 0 , sizeof(addr)); 125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project addr.sun_family = AF_UNIX; 126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project snprintf(addr.sun_path, sizeof(addr.sun_path), ANDROID_SOCKET_DIR"/%s", 127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project name); 128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ret = unlink(addr.sun_path); 130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (ret != 0 && errno != ENOENT) { 131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ERROR("Failed to unlink old socket '%s': %s\n", name, strerror(errno)); 132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project goto out_close; 133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1358348d279c7ce1a2453965ba7f05a7b818d58886cStephen Smalley filecon = NULL; 136e46f9d510db9351682cf17c49115110870147335Stephen Smalley if (sehandle) { 1378348d279c7ce1a2453965ba7f05a7b818d58886cStephen Smalley ret = selabel_lookup(sehandle, &filecon, addr.sun_path, S_IFSOCK); 138e46f9d510db9351682cf17c49115110870147335Stephen Smalley if (ret == 0) 1398348d279c7ce1a2453965ba7f05a7b818d58886cStephen Smalley setfscreatecon(filecon); 140e46f9d510db9351682cf17c49115110870147335Stephen Smalley } 141e46f9d510db9351682cf17c49115110870147335Stephen Smalley 142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ret = bind(fd, (struct sockaddr *) &addr, sizeof (addr)); 143ab5629c197ae278992039a9685df047fe34232b8Nick Kralevich savederrno = errno; 144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 145e46f9d510db9351682cf17c49115110870147335Stephen Smalley setfscreatecon(NULL); 1468348d279c7ce1a2453965ba7f05a7b818d58886cStephen Smalley freecon(filecon); 147e46f9d510db9351682cf17c49115110870147335Stephen Smalley 148ab5629c197ae278992039a9685df047fe34232b8Nick Kralevich if (ret) { 149ab5629c197ae278992039a9685df047fe34232b8Nick Kralevich ERROR("Failed to bind socket '%s': %s\n", name, strerror(savederrno)); 150ab5629c197ae278992039a9685df047fe34232b8Nick Kralevich goto out_unlink; 151ab5629c197ae278992039a9685df047fe34232b8Nick Kralevich } 152ab5629c197ae278992039a9685df047fe34232b8Nick Kralevich 153ab5629c197ae278992039a9685df047fe34232b8Nick Kralevich ret = lchown(addr.sun_path, uid, gid); 154ab5629c197ae278992039a9685df047fe34232b8Nick Kralevich if (ret) { 155ab5629c197ae278992039a9685df047fe34232b8Nick Kralevich ERROR("Failed to lchown socket '%s': %s\n", addr.sun_path, strerror(errno)); 156ab5629c197ae278992039a9685df047fe34232b8Nick Kralevich goto out_unlink; 157ab5629c197ae278992039a9685df047fe34232b8Nick Kralevich } 158ab5629c197ae278992039a9685df047fe34232b8Nick Kralevich ret = fchmodat(AT_FDCWD, addr.sun_path, perm, AT_SYMLINK_NOFOLLOW); 159ab5629c197ae278992039a9685df047fe34232b8Nick Kralevich if (ret) { 160ab5629c197ae278992039a9685df047fe34232b8Nick Kralevich ERROR("Failed to fchmodat socket '%s': %s\n", addr.sun_path, strerror(errno)); 161ab5629c197ae278992039a9685df047fe34232b8Nick Kralevich goto out_unlink; 162ab5629c197ae278992039a9685df047fe34232b8Nick Kralevich } 163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project INFO("Created socket '%s' with mode '%o', user '%d', group '%d'\n", 165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project addr.sun_path, perm, uid, gid); 166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return fd; 168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectout_unlink: 170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unlink(addr.sun_path); 171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectout_close: 172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project close(fd); 173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 176f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughesbool read_file(const char* path, std::string* content) { 177f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughes content->clear(); 178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 179f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughes int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY|O_NOFOLLOW|O_CLOEXEC)); 180f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughes if (fd == -1) { 181f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughes return false; 182f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughes } 183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 184f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughes // For security reasons, disallow world-writable 185f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughes // or group-writable files. 186f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughes struct stat sb; 187f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughes if (fstat(fd, &sb) == -1) { 188f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughes ERROR("fstat failed for '%s': %s\n", path, strerror(errno)); 189f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughes return false; 19038f368c1b3bac76d342189b6412691a217421178Nick Kralevich } 19138f368c1b3bac76d342189b6412691a217421178Nick Kralevich if ((sb.st_mode & (S_IWGRP | S_IWOTH)) != 0) { 192f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughes ERROR("skipping insecure file '%s'\n", path); 193f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughes return false; 19438f368c1b3bac76d342189b6412691a217421178Nick Kralevich } 19538f368c1b3bac76d342189b6412691a217421178Nick Kralevich 196c007bc3856a4cf86b8f610eb045f26a9dedc2894Dan Albert bool okay = android::base::ReadFdToString(fd, content); 1979fc834377297cb2dcc418e4ce7e38e89dd09812bElliott Hughes close(fd); 198f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughes return okay; 199f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughes} 200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 201f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughesint write_file(const char* path, const char* content) { 202f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughes int fd = TEMP_FAILURE_RETRY(open(path, O_WRONLY|O_CREAT|O_NOFOLLOW|O_CLOEXEC, 0600)); 203f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughes if (fd == -1) { 204eedbe81f753fd19e5eb2238187c5618e9153bf55Nick Kralevich NOTICE("write_file: Unable to open '%s': %s\n", path, strerror(errno)); 205eedbe81f753fd19e5eb2238187c5618e9153bf55Nick Kralevich return -1; 206eedbe81f753fd19e5eb2238187c5618e9153bf55Nick Kralevich } 207eedbe81f753fd19e5eb2238187c5618e9153bf55Nick Kralevich int result = android::base::WriteStringToFd(content, fd) ? 0 : -1; 208eedbe81f753fd19e5eb2238187c5618e9153bf55Nick Kralevich if (result == -1) { 209eedbe81f753fd19e5eb2238187c5618e9153bf55Nick Kralevich NOTICE("write_file: Unable to write to '%s': %s\n", path, strerror(errno)); 210f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughes } 2119fc834377297cb2dcc418e4ce7e38e89dd09812bElliott Hughes close(fd); 212f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughes return result; 213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 215f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross#define MAX_MTD_PARTITIONS 16 216f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross 217f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Crossstatic struct { 218f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross char name[16]; 219f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross int number; 220f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross} mtd_part_map[MAX_MTD_PARTITIONS]; 221f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross 222f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Crossstatic int mtd_part_count = -1; 223f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross 224f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Crossstatic void find_mtd_partitions(void) 225f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross{ 226f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross int fd; 227f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross char buf[1024]; 228f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross char *pmtdbufp; 229f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross ssize_t pmtdsize; 230f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross int r; 231f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross 23245a884f85f8eae602fe6e7c9718c90db65675e07Nick Kralevich fd = open("/proc/mtd", O_RDONLY|O_CLOEXEC); 233f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross if (fd < 0) 234f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross return; 235f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross 236f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross buf[sizeof(buf) - 1] = '\0'; 237f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross pmtdsize = read(fd, buf, sizeof(buf) - 1); 238f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross pmtdbufp = buf; 239f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross while (pmtdsize > 0) { 240f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross int mtdnum, mtdsize, mtderasesize; 241f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross char mtdname[16]; 242f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross mtdname[0] = '\0'; 243f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross mtdnum = -1; 244f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross r = sscanf(pmtdbufp, "mtd%d: %x %x %15s", 245f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross &mtdnum, &mtdsize, &mtderasesize, mtdname); 246f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross if ((r == 4) && (mtdname[0] == '"')) { 247f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross char *x = strchr(mtdname + 1, '"'); 248f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross if (x) { 249f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross *x = 0; 250f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross } 251f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross INFO("mtd partition %d, %s\n", mtdnum, mtdname + 1); 252f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross if (mtd_part_count < MAX_MTD_PARTITIONS) { 253f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross strcpy(mtd_part_map[mtd_part_count].name, mtdname + 1); 254f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross mtd_part_map[mtd_part_count].number = mtdnum; 255f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross mtd_part_count++; 256f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross } else { 257f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross ERROR("too many mtd partitions\n"); 258f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross } 259f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross } 260f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross while (pmtdsize > 0 && *pmtdbufp != '\n') { 261f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross pmtdbufp++; 262f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross pmtdsize--; 263f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross } 264f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross if (pmtdsize > 0) { 265f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross pmtdbufp++; 266f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross pmtdsize--; 267f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross } 268f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross } 269f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross close(fd); 270f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross} 271f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross 272f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Crossint mtd_name_to_number(const char *name) 273f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross{ 274f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross int n; 275f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross if (mtd_part_count < 0) { 276f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross mtd_part_count = 0; 277f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross find_mtd_partitions(); 278f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross } 279f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross for (n = 0; n < mtd_part_count; n++) { 280f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross if (!strcmp(name, mtd_part_map[n].name)) { 281f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross return mtd_part_map[n].number; 282f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross } 283f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross } 284f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross return -1; 285f24ed8ca0a13f1b97bd55d10f75a289bf9ccd98dColin Cross} 286504bc5175a8fe5a2f2552903afee761a86283cf4Colin Cross 287da40c00137f75543a69972f1be506e2d14a41845Elliott Hughestime_t gettime() { 288da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes timespec now; 289da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes clock_gettime(CLOCK_MONOTONIC, &now); 290da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes return now.tv_sec; 291da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes} 292504bc5175a8fe5a2f2552903afee761a86283cf4Colin Cross 293da40c00137f75543a69972f1be506e2d14a41845Elliott Hughesuint64_t gettime_ns() { 294da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes timespec now; 295da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes clock_gettime(CLOCK_MONOTONIC, &now); 296da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000000000) + now.tv_nsec; 297504bc5175a8fe5a2f2552903afee761a86283cf4Colin Cross} 298b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross 299b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Crossint mkdir_recursive(const char *pathname, mode_t mode) 300b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross{ 301b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross char buf[128]; 302b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross const char *slash; 303b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross const char *p = pathname; 304b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross int width; 305b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross int ret; 306b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross struct stat info; 307b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross 308b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross while ((slash = strchr(p, '/')) != NULL) { 309b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross width = slash - pathname; 310b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross p = slash + 1; 311b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross if (width < 0) 312b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross break; 313b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross if (width == 0) 314b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross continue; 315b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross if ((unsigned int)width > sizeof(buf) - 1) { 316b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross ERROR("path too long for mkdir_recursive\n"); 317b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross return -1; 318b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross } 319b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross memcpy(buf, pathname, width); 320b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross buf[width] = 0; 321b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross if (stat(buf, &info) != 0) { 322e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley ret = make_dir(buf, mode); 323b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross if (ret && errno != EEXIST) 324b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross return ret; 325b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross } 326b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross } 327e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley ret = make_dir(pathname, mode); 328b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross if (ret && errno != EEXIST) 329b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross return ret; 330b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross return 0; 331b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross} 332b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross 33393ca79b44535ee24ece08001e1948070db6ab6edJohan Redestig/* 33493ca79b44535ee24ece08001e1948070db6ab6edJohan Redestig * replaces any unacceptable characters with '_', the 33593ca79b44535ee24ece08001e1948070db6ab6edJohan Redestig * length of the resulting string is equal to the input string 33693ca79b44535ee24ece08001e1948070db6ab6edJohan Redestig */ 337b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Crossvoid sanitize(char *s) 338b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross{ 33993ca79b44535ee24ece08001e1948070db6ab6edJohan Redestig const char* accept = 34093ca79b44535ee24ece08001e1948070db6ab6edJohan Redestig "abcdefghijklmnopqrstuvwxyz" 34193ca79b44535ee24ece08001e1948070db6ab6edJohan Redestig "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 34293ca79b44535ee24ece08001e1948070db6ab6edJohan Redestig "0123456789" 34393ca79b44535ee24ece08001e1948070db6ab6edJohan Redestig "_-."; 34493ca79b44535ee24ece08001e1948070db6ab6edJohan Redestig 345b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross if (!s) 346b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross return; 34793ca79b44535ee24ece08001e1948070db6ab6edJohan Redestig 34807f3fee164bd7ba14ce9b2dd3818006f07162845Christopher R. Palmer while (*s) { 34993ca79b44535ee24ece08001e1948070db6ab6edJohan Redestig s += strspn(s, accept); 35007f3fee164bd7ba14ce9b2dd3818006f07162845Christopher R. Palmer if (*s) *s++ = '_'; 35193ca79b44535ee24ece08001e1948070db6ab6edJohan Redestig } 352b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross} 35393ca79b44535ee24ece08001e1948070db6ab6edJohan Redestig 35479f338465213885900cea5a39f3aeeea083bbe51Chris Friesvoid make_link_init(const char *oldpath, const char *newpath) 355b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross{ 356b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross int ret; 357b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross char buf[256]; 358b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross char *slash; 359b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross int width; 360b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross 361b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross slash = strrchr(newpath, '/'); 362b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross if (!slash) 363b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross return; 364b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross width = slash - newpath; 365b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross if (width <= 0 || width > (int)sizeof(buf) - 1) 366b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross return; 367b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross memcpy(buf, newpath, width); 368b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross buf[width] = 0; 369b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross ret = mkdir_recursive(buf, 0755); 370b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross if (ret) 371b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross ERROR("Failed to create directory %s: %s (%d)\n", buf, strerror(errno), errno); 372b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross 373b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross ret = symlink(oldpath, newpath); 374b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross if (ret && errno != EEXIST) 375b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross ERROR("Failed to symlink %s to %s: %s (%d)\n", oldpath, newpath, strerror(errno), errno); 376b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross} 377b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross 378b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Crossvoid remove_link(const char *oldpath, const char *newpath) 379b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross{ 380b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross char path[256]; 381b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross ssize_t ret; 382b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross ret = readlink(newpath, path, sizeof(path) - 1); 383b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross if (ret <= 0) 384b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross return; 385b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross path[ret] = 0; 386b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross if (!strcmp(path, oldpath)) 387b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross unlink(newpath); 388b0ab94b7d5a888f0b6920b156e5c6a075fa0741aColin Cross} 389cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross 390cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Crossint wait_for_file(const char *filename, int timeout) 391cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross{ 392cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross struct stat info; 39391cf41cf43847930a8e55b3789d4943a8e22f73aThierry Strudel uint64_t timeout_time_ns = gettime_ns() + timeout * UINT64_C(1000000000); 394cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross int ret = -1; 395cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross 39691cf41cf43847930a8e55b3789d4943a8e22f73aThierry Strudel while (gettime_ns() < timeout_time_ns && ((ret = stat(filename, &info)) < 0)) 397cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross usleep(10000); 398cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross 399cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross return ret; 400cd0f173e2790ee068fd2a20bcfc6c20468e97e51Colin Cross} 401f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross 402f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Crossvoid open_devnull_stdio(void) 403f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross{ 404e34577ce1bd4a8de53ff3d9178b4f78c86086dc8Nick Kralevich // Try to avoid the mknod() call if we can. Since SELinux makes 405e34577ce1bd4a8de53ff3d9178b4f78c86086dc8Nick Kralevich // a /dev/null replacement available for free, let's use it. 406e34577ce1bd4a8de53ff3d9178b4f78c86086dc8Nick Kralevich int fd = open("/sys/fs/selinux/null", O_RDWR); 407e34577ce1bd4a8de53ff3d9178b4f78c86086dc8Nick Kralevich if (fd == -1) { 408e34577ce1bd4a8de53ff3d9178b4f78c86086dc8Nick Kralevich // OOPS, /sys/fs/selinux/null isn't available, likely because 409e34577ce1bd4a8de53ff3d9178b4f78c86086dc8Nick Kralevich // /sys/fs/selinux isn't mounted. Fall back to mknod. 410e34577ce1bd4a8de53ff3d9178b4f78c86086dc8Nick Kralevich static const char *name = "/dev/__null__"; 411e34577ce1bd4a8de53ff3d9178b4f78c86086dc8Nick Kralevich if (mknod(name, S_IFCHR | 0600, (1 << 8) | 3) == 0) { 412e34577ce1bd4a8de53ff3d9178b4f78c86086dc8Nick Kralevich fd = open(name, O_RDWR); 413e34577ce1bd4a8de53ff3d9178b4f78c86086dc8Nick Kralevich unlink(name); 414e34577ce1bd4a8de53ff3d9178b4f78c86086dc8Nick Kralevich } 415e34577ce1bd4a8de53ff3d9178b4f78c86086dc8Nick Kralevich if (fd == -1) { 416e34577ce1bd4a8de53ff3d9178b4f78c86086dc8Nick Kralevich exit(1); 417f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross } 418f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross } 419f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross 420e34577ce1bd4a8de53ff3d9178b4f78c86086dc8Nick Kralevich dup2(fd, 0); 421e34577ce1bd4a8de53ff3d9178b4f78c86086dc8Nick Kralevich dup2(fd, 1); 422e34577ce1bd4a8de53ff3d9178b4f78c86086dc8Nick Kralevich dup2(fd, 2); 423e34577ce1bd4a8de53ff3d9178b4f78c86086dc8Nick Kralevich if (fd > 2) { 424e34577ce1bd4a8de53ff3d9178b4f78c86086dc8Nick Kralevich close(fd); 425e34577ce1bd4a8de53ff3d9178b4f78c86086dc8Nick Kralevich } 426f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross} 427f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross 428e5ce30fed81d1918a259be092dcd8bfffc3c2649Elliott Hughesvoid import_kernel_cmdline(bool in_qemu, 429e5ce30fed81d1918a259be092dcd8bfffc3c2649Elliott Hughes std::function<void(const std::string&, const std::string&, bool)> fn) { 430e5ce30fed81d1918a259be092dcd8bfffc3c2649Elliott Hughes std::string cmdline; 431e5ce30fed81d1918a259be092dcd8bfffc3c2649Elliott Hughes android::base::ReadFileToString("/proc/cmdline", &cmdline); 4322b99543cef1b8b0aa8cca39544939910035117b0Vladimir Chtchetkine 433e5ce30fed81d1918a259be092dcd8bfffc3c2649Elliott Hughes for (const auto& entry : android::base::Split(android::base::Trim(cmdline), " ")) { 434e5ce30fed81d1918a259be092dcd8bfffc3c2649Elliott Hughes std::vector<std::string> pieces = android::base::Split(entry, "="); 435e5ce30fed81d1918a259be092dcd8bfffc3c2649Elliott Hughes if (pieces.size() == 2) { 436e5ce30fed81d1918a259be092dcd8bfffc3c2649Elliott Hughes fn(pieces[0], pieces[1], in_qemu); 437e5ce30fed81d1918a259be092dcd8bfffc3c2649Elliott Hughes } 4382b99543cef1b8b0aa8cca39544939910035117b0Vladimir Chtchetkine } 4392b99543cef1b8b0aa8cca39544939910035117b0Vladimir Chtchetkine} 440e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley 441e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalleyint make_dir(const char *path, mode_t mode) 442e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley{ 443e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley int rc; 444e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley 445e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley char *secontext = NULL; 446e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley 447e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley if (sehandle) { 448e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley selabel_lookup(sehandle, &secontext, path, mode); 449e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley setfscreatecon(secontext); 450e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley } 451e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley 452e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley rc = mkdir(path, mode); 453e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley 454e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley if (secontext) { 455e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley int save_errno = errno; 456e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley freecon(secontext); 457e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley setfscreatecon(NULL); 458e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley errno = save_errno; 459e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley } 460b5982bf7c65b30be981ecfe1847437b05e32b2bbKenny Root 461e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley return rc; 462e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley} 463e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley 464dbd37f2e1da5b27ef1ad6d0cc9580e6893560f5fStephen Smalleyint restorecon(const char* pathname) 465e096e36e50b4b66638ebc4d3c09c2ee35f538dfaStephen Smalley{ 46627a93650c0df02e4cd3c48bbec8acee8b817a012Stephen Smalley return selinux_android_restorecon(pathname, 0); 467ae76f6dbcf3dfd6eda223911f91f4a1316433771Nick Kralevich} 468ae76f6dbcf3dfd6eda223911f91f4a1316433771Nick Kralevich 469ae76f6dbcf3dfd6eda223911f91f4a1316433771Nick Kralevichint restorecon_recursive(const char* pathname) 470ae76f6dbcf3dfd6eda223911f91f4a1316433771Nick Kralevich{ 47127a93650c0df02e4cd3c48bbec8acee8b817a012Stephen Smalley return selinux_android_restorecon(pathname, SELINUX_ANDROID_RESTORECON_RECURSE); 472ae76f6dbcf3dfd6eda223911f91f4a1316433771Nick Kralevich} 473db5f5d43679546ecde2b85151c0a8b8ccd605b07Andres Morales 4741635afe83d1ebd6b5f1fac1e9c6c6b5cd1c93204Jeff Sharkeyint restorecon_recursive_skipce(const char* pathname) 4751635afe83d1ebd6b5f1fac1e9c6c6b5cd1c93204Jeff Sharkey{ 4761635afe83d1ebd6b5f1fac1e9c6c6b5cd1c93204Jeff Sharkey return selinux_android_restorecon(pathname, 4771635afe83d1ebd6b5f1fac1e9c6c6b5cd1c93204Jeff Sharkey SELINUX_ANDROID_RESTORECON_RECURSE | SELINUX_ANDROID_RESTORECON_SKIPCE); 4781635afe83d1ebd6b5f1fac1e9c6c6b5cd1c93204Jeff Sharkey} 4791635afe83d1ebd6b5f1fac1e9c6c6b5cd1c93204Jeff Sharkey 480db5f5d43679546ecde2b85151c0a8b8ccd605b07Andres Morales/* 481db5f5d43679546ecde2b85151c0a8b8ccd605b07Andres Morales * Writes hex_len hex characters (1/2 byte) to hex from bytes. 482db5f5d43679546ecde2b85151c0a8b8ccd605b07Andres Morales */ 483db5f5d43679546ecde2b85151c0a8b8ccd605b07Andres Moralesstd::string bytes_to_hex(const uint8_t* bytes, size_t bytes_len) { 484db5f5d43679546ecde2b85151c0a8b8ccd605b07Andres Morales std::string hex("0x"); 485db5f5d43679546ecde2b85151c0a8b8ccd605b07Andres Morales for (size_t i = 0; i < bytes_len; i++) 486db5f5d43679546ecde2b85151c0a8b8ccd605b07Andres Morales android::base::StringAppendF(&hex, "%02x", bytes[i]); 487db5f5d43679546ecde2b85151c0a8b8ccd605b07Andres Morales return hex; 488db5f5d43679546ecde2b85151c0a8b8ccd605b07Andres Morales} 489f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell 490f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell/* 491f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell * Returns true is pathname is a directory 492f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell */ 493f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbellbool is_dir(const char* pathname) { 494f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell struct stat info; 495f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell if (stat(pathname, &info) == -1) { 496f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell return false; 497f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell } 498f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell return S_ISDIR(info.st_mode); 499f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell} 500b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 501b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool expand_props(const std::string& src, std::string* dst) { 502b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry const char* src_ptr = src.c_str(); 503b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 504b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry if (!dst) { 505b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return false; 506b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } 507b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 508b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry /* - variables can either be $x.y or ${x.y}, in case they are only part 509b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry * of the string. 510b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry * - will accept $$ as a literal $. 511b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry * - no nested property expansion, i.e. ${foo.${bar}} is not supported, 512b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry * bad things will happen 513109d7d23c57dd740af188109ee84ef5fae14617aMark Salyzyn * - ${x.y:-default} will return default value if property empty. 514b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry */ 515b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry while (*src_ptr) { 516b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry const char* c; 517b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 518b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry c = strchr(src_ptr, '$'); 519b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry if (!c) { 520b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry dst->append(src_ptr); 521b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return true; 522b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } 523b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 524b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry dst->append(src_ptr, c); 525b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry c++; 526b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 527b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry if (*c == '$') { 528b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry dst->push_back(*(c++)); 529b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry src_ptr = c; 530b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry continue; 531b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } else if (*c == '\0') { 532b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return true; 533b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } 534b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 535b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry std::string prop_name; 536109d7d23c57dd740af188109ee84ef5fae14617aMark Salyzyn std::string def_val; 537b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry if (*c == '{') { 538b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry c++; 539b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry const char* end = strchr(c, '}'); 540b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry if (!end) { 541b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry // failed to find closing brace, abort. 542b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry ERROR("unexpected end of string in '%s', looking for }\n", src.c_str()); 543b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return false; 544b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } 545b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry prop_name = std::string(c, end); 546b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry c = end + 1; 547109d7d23c57dd740af188109ee84ef5fae14617aMark Salyzyn size_t def = prop_name.find(":-"); 548109d7d23c57dd740af188109ee84ef5fae14617aMark Salyzyn if (def < prop_name.size()) { 549109d7d23c57dd740af188109ee84ef5fae14617aMark Salyzyn def_val = prop_name.substr(def + 2); 550109d7d23c57dd740af188109ee84ef5fae14617aMark Salyzyn prop_name = prop_name.substr(0, def); 551109d7d23c57dd740af188109ee84ef5fae14617aMark Salyzyn } 552b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } else { 553b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry prop_name = c; 554b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry ERROR("using deprecated syntax for specifying property '%s', use ${name} instead\n", 555b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry c); 556b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry c += prop_name.size(); 557b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } 558b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 559b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry if (prop_name.empty()) { 560b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry ERROR("invalid zero-length prop name in '%s'\n", src.c_str()); 561b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return false; 562b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } 563b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 564b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry std::string prop_val = property_get(prop_name.c_str()); 565b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry if (prop_val.empty()) { 566109d7d23c57dd740af188109ee84ef5fae14617aMark Salyzyn if (def_val.empty()) { 567109d7d23c57dd740af188109ee84ef5fae14617aMark Salyzyn ERROR("property '%s' doesn't exist while expanding '%s'\n", 568109d7d23c57dd740af188109ee84ef5fae14617aMark Salyzyn prop_name.c_str(), src.c_str()); 569109d7d23c57dd740af188109ee84ef5fae14617aMark Salyzyn return false; 570109d7d23c57dd740af188109ee84ef5fae14617aMark Salyzyn } 571109d7d23c57dd740af188109ee84ef5fae14617aMark Salyzyn prop_val = def_val; 572b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } 573b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 574b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry dst->append(prop_val); 575b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry src_ptr = c; 576b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } 577b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 578b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return true; 579b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry} 580