10b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn/*
20b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn * Copyright (C) 2016 The Android Open Source Project
30b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn * All rights reserved.
40b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn *
50b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn * Redistribution and use in source and binary forms, with or without
60b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn * modification, are permitted provided that the following conditions
70b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn * are met:
80b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn *  * Redistributions of source code must retain the above copyright
90b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn *    notice, this list of conditions and the following disclaimer.
100b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn *  * Redistributions in binary form must reproduce the above copyright
110b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn *    notice, this list of conditions and the following disclaimer in
120b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn *    the documentation and/or other materials provided with the
130b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn *    distribution.
140b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn *
150b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
160b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
170b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
180b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
190b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
200b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
210b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
220b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
230b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
240b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
250b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
260b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn * SUCH DAMAGE.
270b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn */
280b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn#include <ctype.h>
290b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn#include <errno.h>
300b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn#include <fcntl.h>
310b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn#include <limits.h>
320b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn#include <stdio.h>
330b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn#include <stdlib.h>
340b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn#include <string.h>
350b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn#include <sys/stat.h>
360b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn#include <sys/types.h>
370b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn#include <unistd.h>
380b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn
3952bd37e63373b410c009e8611508191dfbf31d30Mark Salyzyn#include <cutils/android_get_control_file.h>
400b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn
4152bd37e63373b410c009e8611508191dfbf31d30Mark Salyzyn#include "android_get_control_env.h"
420b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn
436b652160d1f33ecb31663224813c57288f7008e1Mark Salyzyn#ifndef TEMP_FAILURE_RETRY
446b652160d1f33ecb31663224813c57288f7008e1Mark Salyzyn#define TEMP_FAILURE_RETRY(exp) (exp) // KISS implementation
456b652160d1f33ecb31663224813c57288f7008e1Mark Salyzyn#endif
466b652160d1f33ecb31663224813c57288f7008e1Mark Salyzyn
4752bd37e63373b410c009e8611508191dfbf31d30Mark SalyzynLIBCUTILS_HIDDEN int __android_get_control_from_env(const char* prefix,
4852bd37e63373b410c009e8611508191dfbf31d30Mark Salyzyn                                                    const char* name) {
4952bd37e63373b410c009e8611508191dfbf31d30Mark Salyzyn    if (!prefix || !name) return -1;
500b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn
510b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn    char *key = NULL;
5252bd37e63373b410c009e8611508191dfbf31d30Mark Salyzyn    if (asprintf(&key, "%s%s", prefix, name) < 0) return -1;
530b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn    if (!key) return -1;
540b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn
550b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn    char *cp = key;
560b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn    while (*cp) {
570b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn        if (!isalnum(*cp)) *cp = '_';
580b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn        ++cp;
590b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn    }
600b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn
610b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn    const char* val = getenv(key);
620b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn    free(key);
630b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn    if (!val) return -1;
640b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn
650b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn    errno = 0;
660b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn    long fd = strtol(val, NULL, 10);
670b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn    if (errno) return -1;
680b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn
690b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn    // validity checking
700b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn    if ((fd < 0) || (fd > INT_MAX)) return -1;
710b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn
7252bd37e63373b410c009e8611508191dfbf31d30Mark Salyzyn    // Since we are inheriting an fd, it could legitimately exceed _SC_OPEN_MAX
7352bd37e63373b410c009e8611508191dfbf31d30Mark Salyzyn
7452bd37e63373b410c009e8611508191dfbf31d30Mark Salyzyn    // Still open?
756b652160d1f33ecb31663224813c57288f7008e1Mark Salyzyn#if defined(F_GETFD) // Lowest overhead
760b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn    if (TEMP_FAILURE_RETRY(fcntl(fd, F_GETFD)) < 0) return -1;
776b652160d1f33ecb31663224813c57288f7008e1Mark Salyzyn#elif defined(F_GETFL) // Alternate lowest overhead
786b652160d1f33ecb31663224813c57288f7008e1Mark Salyzyn    if (TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL)) < 0) return -1;
7952bd37e63373b410c009e8611508191dfbf31d30Mark Salyzyn#else // Hail Mary pass
800b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn    struct stat s;
816b652160d1f33ecb31663224813c57288f7008e1Mark Salyzyn    if (TEMP_FAILURE_RETRY(fstat(fd, &s)) < 0) return -1;
820b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn#endif
830b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn
8452bd37e63373b410c009e8611508191dfbf31d30Mark Salyzyn    return static_cast<int>(fd);
8552bd37e63373b410c009e8611508191dfbf31d30Mark Salyzyn}
8652bd37e63373b410c009e8611508191dfbf31d30Mark Salyzyn
8752bd37e63373b410c009e8611508191dfbf31d30Mark Salyzynint android_get_control_file(const char* path) {
8852bd37e63373b410c009e8611508191dfbf31d30Mark Salyzyn    int fd = __android_get_control_from_env(ANDROID_FILE_ENV_PREFIX, path);
8952bd37e63373b410c009e8611508191dfbf31d30Mark Salyzyn
900b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn#if defined(__linux__)
9152bd37e63373b410c009e8611508191dfbf31d30Mark Salyzyn    // Find file path from /proc and make sure it is correct
920b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn    char *proc = NULL;
9352bd37e63373b410c009e8611508191dfbf31d30Mark Salyzyn    if (asprintf(&proc, "/proc/self/fd/%d", fd) < 0) return -1;
940b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn    if (!proc) return -1;
950b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn
960b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn    size_t len = strlen(path);
9752bd37e63373b410c009e8611508191dfbf31d30Mark Salyzyn    // readlink() does not guarantee a nul byte, len+2 so we catch truncation.
980b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn    char *buf = static_cast<char *>(calloc(1, len + 2));
990b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn    if (!buf) {
1000b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn        free(proc);
1010b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn        return -1;
1020b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn    }
1030b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn    ssize_t ret = TEMP_FAILURE_RETRY(readlink(proc, buf, len + 1));
1040b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn    free(proc);
1050b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn    int cmp = (len != static_cast<size_t>(ret)) || strcmp(buf, path);
1060b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn    free(buf);
1070b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn    if (ret < 0) return -1;
1080b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn    if (cmp != 0) return -1;
10952bd37e63373b410c009e8611508191dfbf31d30Mark Salyzyn    // It is what we think it is
1100b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn#endif
1110b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn
11252bd37e63373b410c009e8611508191dfbf31d30Mark Salyzyn    return fd;
1130b034d9d7b1af4e2f608ddf2dc2a0e08773e69acMark Salyzyn}
114