18b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn/*
28b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn * Copyright (C) 2007 The Android Open Source Project
38b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn *
48b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn * Licensed under the Apache License, Version 2.0 (the "License");
58b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn * you may not use this file except in compliance with the License.
68b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn * You may obtain a copy of the License at
78b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn *
88b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn *      http://www.apache.org/licenses/LICENSE-2.0
98b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn *
108b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn * Unless required by applicable law or agreed to in writing, software
118b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn * distributed under the License is distributed on an "AS IS" BASIS,
128b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn * See the License for the specific language governing permissions and
148b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn * limitations under the License.
158b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn */
168b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn
178b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn/* This file is used to define the properties of the filesystem
188b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn** images generated by build tools (mkbootfs and mkyaffs2image) and
198b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn** by the device side of adb.
208b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn*/
218b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn
2268651148dd06da576068749d33a82b5105d67091Mark Salyzyn#define LOG_TAG "fs_config"
2368651148dd06da576068749d33a82b5105d67091Mark Salyzyn
2468651148dd06da576068749d33a82b5105d67091Mark Salyzyn#define _GNU_SOURCE
2568651148dd06da576068749d33a82b5105d67091Mark Salyzyn
2668651148dd06da576068749d33a82b5105d67091Mark Salyzyn#include <errno.h>
2768651148dd06da576068749d33a82b5105d67091Mark Salyzyn#include <fcntl.h>
2868651148dd06da576068749d33a82b5105d67091Mark Salyzyn#include <stdbool.h>
298b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn#include <stdint.h>
3068651148dd06da576068749d33a82b5105d67091Mark Salyzyn#include <stdio.h>
3168651148dd06da576068749d33a82b5105d67091Mark Salyzyn#include <stdlib.h>
328b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn#include <string.h>
338b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn#include <sys/stat.h>
3468651148dd06da576068749d33a82b5105d67091Mark Salyzyn#include <sys/types.h>
358b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn
3668651148dd06da576068749d33a82b5105d67091Mark Salyzyn#include <log/log.h>
378b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn#include <private/android_filesystem_config.h>
38fd5b425b6eeef94987f7540bc2522fc05750857cMark Salyzyn#include <utils/Compat.h>
398b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn
404232b378e79f4254abc16a4254e2ba1b91851f11Mark Salyzyn#ifndef O_BINARY
414232b378e79f4254abc16a4254e2ba1b91851f11Mark Salyzyn#define O_BINARY 0
424232b378e79f4254abc16a4254e2ba1b91851f11Mark Salyzyn#endif
434232b378e79f4254abc16a4254e2ba1b91851f11Mark Salyzyn
4468651148dd06da576068749d33a82b5105d67091Mark Salyzyn/* The following structure is stored little endian */
4568651148dd06da576068749d33a82b5105d67091Mark Salyzynstruct fs_path_config_from_file {
4668651148dd06da576068749d33a82b5105d67091Mark Salyzyn    uint16_t len;
4768651148dd06da576068749d33a82b5105d67091Mark Salyzyn    uint16_t mode;
4868651148dd06da576068749d33a82b5105d67091Mark Salyzyn    uint16_t uid;
4968651148dd06da576068749d33a82b5105d67091Mark Salyzyn    uint16_t gid;
5068651148dd06da576068749d33a82b5105d67091Mark Salyzyn    uint64_t capabilities;
5168651148dd06da576068749d33a82b5105d67091Mark Salyzyn    char prefix[];
5268651148dd06da576068749d33a82b5105d67091Mark Salyzyn} __attribute__((__aligned__(sizeof(uint64_t))));
5368651148dd06da576068749d33a82b5105d67091Mark Salyzyn
5468651148dd06da576068749d33a82b5105d67091Mark Salyzyn/* My kingdom for <endian.h> */
5568651148dd06da576068749d33a82b5105d67091Mark Salyzynstatic inline uint16_t get2LE(const uint8_t* src)
5668651148dd06da576068749d33a82b5105d67091Mark Salyzyn{
5768651148dd06da576068749d33a82b5105d67091Mark Salyzyn    return src[0] | (src[1] << 8);
5868651148dd06da576068749d33a82b5105d67091Mark Salyzyn}
5968651148dd06da576068749d33a82b5105d67091Mark Salyzyn
6068651148dd06da576068749d33a82b5105d67091Mark Salyzynstatic inline uint64_t get8LE(const uint8_t* src)
6168651148dd06da576068749d33a82b5105d67091Mark Salyzyn{
6268651148dd06da576068749d33a82b5105d67091Mark Salyzyn    uint32_t low, high;
6368651148dd06da576068749d33a82b5105d67091Mark Salyzyn
6468651148dd06da576068749d33a82b5105d67091Mark Salyzyn    low = src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
6568651148dd06da576068749d33a82b5105d67091Mark Salyzyn    high = src[4] | (src[5] << 8) | (src[6] << 16) | (src[7] << 24);
6668651148dd06da576068749d33a82b5105d67091Mark Salyzyn    return ((uint64_t) high << 32) | (uint64_t) low;
6768651148dd06da576068749d33a82b5105d67091Mark Salyzyn}
6868651148dd06da576068749d33a82b5105d67091Mark Salyzyn
695d9e5efbcdab4a5442e332944765f67eb7005be5Mark Salyzyn#define ALIGN(x, alignment) ( ((x) + ((alignment) - 1)) & ~((alignment) - 1) )
705d9e5efbcdab4a5442e332944765f67eb7005be5Mark Salyzyn
718b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn/* Rules for directories.
728b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn** These rules are applied based on "first match", so they
738b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn** should start with the most specific path and work their
748b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn** way up to the root.
758b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn*/
768b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn
778b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzynstatic const struct fs_path_config android_dirs[] = {
788b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00770, AID_SYSTEM, AID_CACHE,  0, "cache" },
798b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/app" },
808b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/app-private" },
818b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00771, AID_ROOT,   AID_ROOT,   0, "data/dalvik-cache" },
828b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/data" },
838b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00771, AID_SHELL,  AID_SHELL,  0, "data/local/tmp" },
848b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00771, AID_SHELL,  AID_SHELL,  0, "data/local" },
858b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 01771, AID_SYSTEM, AID_MISC,   0, "data/misc" },
868b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00770, AID_DHCP,   AID_DHCP,   0, "data/misc/dhcp" },
878b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00771, AID_SHARED_RELRO, AID_SHARED_RELRO, 0, "data/misc/shared_relro" },
888b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00775, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media" },
898b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00775, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media/Music" },
908b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data" },
918b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00750, AID_ROOT,   AID_SHELL,  0, "sbin" },
928b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00755, AID_ROOT,   AID_SHELL,  0, "system/bin" },
938b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00755, AID_ROOT,   AID_SHELL,  0, "system/vendor" },
948b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00755, AID_ROOT,   AID_SHELL,  0, "system/xbin" },
958b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00755, AID_ROOT,   AID_ROOT,   0, "system/etc/ppp" },
968b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00755, AID_ROOT,   AID_SHELL,  0, "vendor" },
978b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00777, AID_ROOT,   AID_ROOT,   0, "sdcard" },
988b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00755, AID_ROOT,   AID_ROOT,   0, 0 },
998b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn};
1008b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn
1018b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn/* Rules for files.
1028b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn** These rules are applied based on "first match", so they
1038b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn** should start with the most specific path and work their
1048b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn** way up to the root. Prefixes ending in * denotes wildcard
1058b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn** and will allow partial matches.
1068b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn*/
10768651148dd06da576068749d33a82b5105d67091Mark Salyzynstatic const char conf_dir[] = "/system/etc/fs_config_dirs";
10868651148dd06da576068749d33a82b5105d67091Mark Salyzynstatic const char conf_file[] = "/system/etc/fs_config_files";
10968651148dd06da576068749d33a82b5105d67091Mark Salyzyn
1108b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzynstatic const struct fs_path_config android_files[] = {
1118b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00440, AID_ROOT,      AID_SHELL,     0, "system/etc/init.goldfish.rc" },
1128b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00550, AID_ROOT,      AID_SHELL,     0, "system/etc/init.goldfish.sh" },
1138b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00550, AID_ROOT,      AID_SHELL,     0, "system/etc/init.ril" },
1148b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00550, AID_DHCP,      AID_SHELL,     0, "system/etc/dhcpcd/dhcpcd-run-hooks" },
1158b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00555, AID_ROOT,      AID_ROOT,      0, "system/etc/ppp/*" },
1168b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00555, AID_ROOT,      AID_ROOT,      0, "system/etc/rc.*" },
11768651148dd06da576068749d33a82b5105d67091Mark Salyzyn    { 00444, AID_ROOT,      AID_ROOT,      0, conf_dir + 1 },
11868651148dd06da576068749d33a82b5105d67091Mark Salyzyn    { 00444, AID_ROOT,      AID_ROOT,      0, conf_file + 1 },
1198b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00644, AID_SYSTEM,    AID_SYSTEM,    0, "data/app/*" },
1208b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00644, AID_MEDIA_RW,  AID_MEDIA_RW,  0, "data/media/*" },
1218b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00644, AID_SYSTEM,    AID_SYSTEM,    0, "data/app-private/*" },
1228b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00644, AID_APP,       AID_APP,       0, "data/data/*" },
1238b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn
1248b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    /* the following five files are INTENTIONALLY set-uid, but they
1258b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn     * are NOT included on user builds. */
1268b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 04750, AID_ROOT,      AID_SHELL,     0, "system/xbin/su" },
1278b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 06755, AID_ROOT,      AID_ROOT,      0, "system/xbin/librank" },
1288b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 06755, AID_ROOT,      AID_ROOT,      0, "system/xbin/procrank" },
1298b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 06755, AID_ROOT,      AID_ROOT,      0, "system/xbin/procmem" },
1308b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 04770, AID_ROOT,      AID_RADIO,     0, "system/bin/pppd-ril" },
1318b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn
1328b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    /* the following files have enhanced capabilities and ARE included in user builds. */
1338b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00750, AID_ROOT,      AID_SHELL,     (1ULL << CAP_SETUID) | (1ULL << CAP_SETGID), "system/bin/run-as" },
1348b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00700, AID_SYSTEM,    AID_SHELL,     (1ULL << CAP_BLOCK_SUSPEND), "system/bin/inputflinger" },
1358b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn
1368b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00750, AID_ROOT,      AID_ROOT,      0, "system/bin/uncrypt" },
1378b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00750, AID_ROOT,      AID_ROOT,      0, "system/bin/install-recovery.sh" },
1388b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00755, AID_ROOT,      AID_SHELL,     0, "system/bin/*" },
1398b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00755, AID_ROOT,      AID_ROOT,      0, "system/lib/valgrind/*" },
1408b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00755, AID_ROOT,      AID_ROOT,      0, "system/lib64/valgrind/*" },
1418b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00755, AID_ROOT,      AID_SHELL,     0, "system/xbin/*" },
1428b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00755, AID_ROOT,      AID_SHELL,     0, "system/vendor/bin/*" },
1438b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00755, AID_ROOT,      AID_SHELL,     0, "vendor/bin/*" },
1448b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00750, AID_ROOT,      AID_SHELL,     0, "sbin/*" },
1458b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00755, AID_ROOT,      AID_ROOT,      0, "bin/*" },
1468b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00750, AID_ROOT,      AID_SHELL,     0, "init*" },
1478b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00750, AID_ROOT,      AID_SHELL,     0, "sbin/fs_mgr" },
1488b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00640, AID_ROOT,      AID_SHELL,     0, "fstab.*" },
1498b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    { 00644, AID_ROOT,      AID_ROOT,      0, 0 },
1508b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn};
1518b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn
152df33ffadd29ed02d87e87515626b673eac67f735Thierry Strudelstatic int fs_config_open(int dir, const char *target_out_path)
15368651148dd06da576068749d33a82b5105d67091Mark Salyzyn{
15468651148dd06da576068749d33a82b5105d67091Mark Salyzyn    int fd = -1;
15568651148dd06da576068749d33a82b5105d67091Mark Salyzyn
156df33ffadd29ed02d87e87515626b673eac67f735Thierry Strudel    if (target_out_path && *target_out_path) {
157df33ffadd29ed02d87e87515626b673eac67f735Thierry Strudel        /* target_out_path is the path to the directory holding content of system partition
158df33ffadd29ed02d87e87515626b673eac67f735Thierry Strudel           but as we cannot guaranty it ends with '/system' we need this below skip_len logic */
15968651148dd06da576068749d33a82b5105d67091Mark Salyzyn        char *name = NULL;
160df33ffadd29ed02d87e87515626b673eac67f735Thierry Strudel        int target_out_path_len = strlen(target_out_path);
161df33ffadd29ed02d87e87515626b673eac67f735Thierry Strudel        int skip_len = strlen("/system");
162df33ffadd29ed02d87e87515626b673eac67f735Thierry Strudel
163df33ffadd29ed02d87e87515626b673eac67f735Thierry Strudel        if (target_out_path[target_out_path_len] == '/') {
164df33ffadd29ed02d87e87515626b673eac67f735Thierry Strudel            skip_len++;
165df33ffadd29ed02d87e87515626b673eac67f735Thierry Strudel        }
166df33ffadd29ed02d87e87515626b673eac67f735Thierry Strudel        asprintf(&name, "%s%s", target_out_path, (dir ? conf_dir : conf_file) + skip_len);
16768651148dd06da576068749d33a82b5105d67091Mark Salyzyn        if (name) {
1684232b378e79f4254abc16a4254e2ba1b91851f11Mark Salyzyn            fd = TEMP_FAILURE_RETRY(open(name, O_RDONLY | O_BINARY));
16968651148dd06da576068749d33a82b5105d67091Mark Salyzyn            free(name);
17068651148dd06da576068749d33a82b5105d67091Mark Salyzyn        }
17168651148dd06da576068749d33a82b5105d67091Mark Salyzyn    }
17268651148dd06da576068749d33a82b5105d67091Mark Salyzyn    if (fd < 0) {
1734232b378e79f4254abc16a4254e2ba1b91851f11Mark Salyzyn        fd = TEMP_FAILURE_RETRY(open(dir ? conf_dir : conf_file, O_RDONLY | O_BINARY));
17468651148dd06da576068749d33a82b5105d67091Mark Salyzyn    }
17568651148dd06da576068749d33a82b5105d67091Mark Salyzyn    return fd;
17668651148dd06da576068749d33a82b5105d67091Mark Salyzyn}
17768651148dd06da576068749d33a82b5105d67091Mark Salyzyn
17868651148dd06da576068749d33a82b5105d67091Mark Salyzynstatic bool fs_config_cmp(bool dir, const char *prefix, size_t len,
17968651148dd06da576068749d33a82b5105d67091Mark Salyzyn                                    const char *path, size_t plen)
18068651148dd06da576068749d33a82b5105d67091Mark Salyzyn{
18168651148dd06da576068749d33a82b5105d67091Mark Salyzyn    if (dir) {
18268651148dd06da576068749d33a82b5105d67091Mark Salyzyn        if (plen < len) {
18368651148dd06da576068749d33a82b5105d67091Mark Salyzyn            return false;
18468651148dd06da576068749d33a82b5105d67091Mark Salyzyn        }
18568651148dd06da576068749d33a82b5105d67091Mark Salyzyn    } else {
18668651148dd06da576068749d33a82b5105d67091Mark Salyzyn        /* If name ends in * then allow partial matches. */
18768651148dd06da576068749d33a82b5105d67091Mark Salyzyn        if (prefix[len - 1] == '*') {
18868651148dd06da576068749d33a82b5105d67091Mark Salyzyn            return !strncmp(prefix, path, len - 1);
18968651148dd06da576068749d33a82b5105d67091Mark Salyzyn        }
19068651148dd06da576068749d33a82b5105d67091Mark Salyzyn        if (plen != len) {
19168651148dd06da576068749d33a82b5105d67091Mark Salyzyn            return false;
19268651148dd06da576068749d33a82b5105d67091Mark Salyzyn        }
19368651148dd06da576068749d33a82b5105d67091Mark Salyzyn    }
19468651148dd06da576068749d33a82b5105d67091Mark Salyzyn    return !strncmp(prefix, path, len);
19568651148dd06da576068749d33a82b5105d67091Mark Salyzyn}
19668651148dd06da576068749d33a82b5105d67091Mark Salyzyn
197df33ffadd29ed02d87e87515626b673eac67f735Thierry Strudelvoid fs_config(const char *path, int dir, const char *target_out_path,
1988b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn               unsigned *uid, unsigned *gid, unsigned *mode, uint64_t *capabilities)
1998b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn{
2008b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    const struct fs_path_config *pc;
2017977cc63b1c287158f1b02fe6f437d89f510bb47Mark Salyzyn    int fd, plen;
2028b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn
2038b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    if (path[0] == '/') {
2048b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn        path++;
2058b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    }
2068b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn
2077e82633106361d628338bcac12d2d269e56a9a71Mark Salyzyn    plen = strlen(path);
20868651148dd06da576068749d33a82b5105d67091Mark Salyzyn
209df33ffadd29ed02d87e87515626b673eac67f735Thierry Strudel    fd = fs_config_open(dir, target_out_path);
2107977cc63b1c287158f1b02fe6f437d89f510bb47Mark Salyzyn    if (fd >= 0) {
2117977cc63b1c287158f1b02fe6f437d89f510bb47Mark Salyzyn        struct fs_path_config_from_file header;
2127977cc63b1c287158f1b02fe6f437d89f510bb47Mark Salyzyn
2137977cc63b1c287158f1b02fe6f437d89f510bb47Mark Salyzyn        while (TEMP_FAILURE_RETRY(read(fd, &header, sizeof(header))) == sizeof(header)) {
2147977cc63b1c287158f1b02fe6f437d89f510bb47Mark Salyzyn            char *prefix;
2157977cc63b1c287158f1b02fe6f437d89f510bb47Mark Salyzyn            uint16_t host_len = get2LE((const uint8_t *)&header.len);
2167977cc63b1c287158f1b02fe6f437d89f510bb47Mark Salyzyn            ssize_t len, remainder = host_len - sizeof(header);
21768651148dd06da576068749d33a82b5105d67091Mark Salyzyn            if (remainder <= 0) {
2187977cc63b1c287158f1b02fe6f437d89f510bb47Mark Salyzyn                ALOGE("%s len is corrupted", dir ? conf_dir : conf_file);
2197977cc63b1c287158f1b02fe6f437d89f510bb47Mark Salyzyn                break;
2207977cc63b1c287158f1b02fe6f437d89f510bb47Mark Salyzyn            }
2217977cc63b1c287158f1b02fe6f437d89f510bb47Mark Salyzyn            prefix = calloc(1, remainder);
2227977cc63b1c287158f1b02fe6f437d89f510bb47Mark Salyzyn            if (!prefix) {
2237977cc63b1c287158f1b02fe6f437d89f510bb47Mark Salyzyn                ALOGE("%s out of memory", dir ? conf_dir : conf_file);
22468651148dd06da576068749d33a82b5105d67091Mark Salyzyn                break;
22568651148dd06da576068749d33a82b5105d67091Mark Salyzyn            }
2267977cc63b1c287158f1b02fe6f437d89f510bb47Mark Salyzyn            if (TEMP_FAILURE_RETRY(read(fd, prefix, remainder)) != remainder) {
2277977cc63b1c287158f1b02fe6f437d89f510bb47Mark Salyzyn                free(prefix);
2287977cc63b1c287158f1b02fe6f437d89f510bb47Mark Salyzyn                ALOGE("%s prefix is truncated", dir ? conf_dir : conf_file);
2297977cc63b1c287158f1b02fe6f437d89f510bb47Mark Salyzyn                break;
23068651148dd06da576068749d33a82b5105d67091Mark Salyzyn            }
2317977cc63b1c287158f1b02fe6f437d89f510bb47Mark Salyzyn            len = strnlen(prefix, remainder);
23268651148dd06da576068749d33a82b5105d67091Mark Salyzyn            if (len >= remainder) { /* missing a terminating null */
2337977cc63b1c287158f1b02fe6f437d89f510bb47Mark Salyzyn                free(prefix);
23468651148dd06da576068749d33a82b5105d67091Mark Salyzyn                ALOGE("%s is corrupted", dir ? conf_dir : conf_file);
23568651148dd06da576068749d33a82b5105d67091Mark Salyzyn                break;
23668651148dd06da576068749d33a82b5105d67091Mark Salyzyn            }
2377977cc63b1c287158f1b02fe6f437d89f510bb47Mark Salyzyn            if (fs_config_cmp(dir, prefix, len, path, plen)) {
2387977cc63b1c287158f1b02fe6f437d89f510bb47Mark Salyzyn                free(prefix);
2397977cc63b1c287158f1b02fe6f437d89f510bb47Mark Salyzyn                close(fd);
2407977cc63b1c287158f1b02fe6f437d89f510bb47Mark Salyzyn                *uid = get2LE((const uint8_t *)&(header.uid));
2417977cc63b1c287158f1b02fe6f437d89f510bb47Mark Salyzyn                *gid = get2LE((const uint8_t *)&(header.gid));
2427977cc63b1c287158f1b02fe6f437d89f510bb47Mark Salyzyn                *mode = (*mode & (~07777)) | get2LE((const uint8_t *)&(header.mode));
2437977cc63b1c287158f1b02fe6f437d89f510bb47Mark Salyzyn                *capabilities = get8LE((const uint8_t *)&(header.capabilities));
2447977cc63b1c287158f1b02fe6f437d89f510bb47Mark Salyzyn                return;
24568651148dd06da576068749d33a82b5105d67091Mark Salyzyn            }
2467977cc63b1c287158f1b02fe6f437d89f510bb47Mark Salyzyn            free(prefix);
2477e82633106361d628338bcac12d2d269e56a9a71Mark Salyzyn        }
24868651148dd06da576068749d33a82b5105d67091Mark Salyzyn        close(fd);
24968651148dd06da576068749d33a82b5105d67091Mark Salyzyn    }
25068651148dd06da576068749d33a82b5105d67091Mark Salyzyn
25168651148dd06da576068749d33a82b5105d67091Mark Salyzyn    pc = dir ? android_dirs : android_files;
25268651148dd06da576068749d33a82b5105d67091Mark Salyzyn    for(; pc->prefix; pc++){
25368651148dd06da576068749d33a82b5105d67091Mark Salyzyn        if (fs_config_cmp(dir, pc->prefix, strlen(pc->prefix), path, plen)) {
25468651148dd06da576068749d33a82b5105d67091Mark Salyzyn            break;
2558b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn        }
2568b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    }
2578b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    *uid = pc->uid;
2588b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    *gid = pc->gid;
2598b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    *mode = (*mode & (~07777)) | pc->mode;
2608b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn    *capabilities = pc->capabilities;
2618b2c7dee59f0ca89e6a0866537054a0d41dbae97Mark Salyzyn}
2625d9e5efbcdab4a5442e332944765f67eb7005be5Mark Salyzyn
2635d9e5efbcdab4a5442e332944765f67eb7005be5Mark Salyzynssize_t fs_config_generate(char *buffer, size_t length, const struct fs_path_config *pc)
2645d9e5efbcdab4a5442e332944765f67eb7005be5Mark Salyzyn{
2655d9e5efbcdab4a5442e332944765f67eb7005be5Mark Salyzyn    struct fs_path_config_from_file *p = (struct fs_path_config_from_file *)buffer;
2665d9e5efbcdab4a5442e332944765f67eb7005be5Mark Salyzyn    size_t len = ALIGN(sizeof(*p) + strlen(pc->prefix) + 1, sizeof(uint64_t));
2675d9e5efbcdab4a5442e332944765f67eb7005be5Mark Salyzyn
2685d9e5efbcdab4a5442e332944765f67eb7005be5Mark Salyzyn    if ((length < len) || (len > UINT16_MAX)) {
2695d9e5efbcdab4a5442e332944765f67eb7005be5Mark Salyzyn        return -ENOSPC;
2705d9e5efbcdab4a5442e332944765f67eb7005be5Mark Salyzyn    }
2715d9e5efbcdab4a5442e332944765f67eb7005be5Mark Salyzyn    memset(p, 0, len);
2725d9e5efbcdab4a5442e332944765f67eb7005be5Mark Salyzyn    uint16_t host_len = len;
2735d9e5efbcdab4a5442e332944765f67eb7005be5Mark Salyzyn    p->len = get2LE((const uint8_t *)&host_len);
2745d9e5efbcdab4a5442e332944765f67eb7005be5Mark Salyzyn    p->mode = get2LE((const uint8_t *)&(pc->mode));
2755d9e5efbcdab4a5442e332944765f67eb7005be5Mark Salyzyn    p->uid = get2LE((const uint8_t *)&(pc->uid));
2765d9e5efbcdab4a5442e332944765f67eb7005be5Mark Salyzyn    p->gid = get2LE((const uint8_t *)&(pc->gid));
2775d9e5efbcdab4a5442e332944765f67eb7005be5Mark Salyzyn    p->capabilities = get8LE((const uint8_t *)&(pc->capabilities));
2785d9e5efbcdab4a5442e332944765f67eb7005be5Mark Salyzyn    strcpy(p->prefix, pc->prefix);
2795d9e5efbcdab4a5442e332944765f67eb7005be5Mark Salyzyn    return len;
2805d9e5efbcdab4a5442e332944765f67eb7005be5Mark Salyzyn}
281