1e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project/*
2e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
3e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project *
4e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * you may not use this file except in compliance with the License.
6e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * You may obtain a copy of the License at
7e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project *
8e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project *
10e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * See the License for the specific language governing permissions and
14e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * limitations under the License.
15e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project */
16e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
17e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project// A simple file permissions checker. See associated README.
18e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
19e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#define _GNU_SOURCE
20e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
21e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <stdio.h>
22e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <stdlib.h>
23e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <stdarg.h>
24e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <string.h>
25e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <ctype.h>
26e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <sys/types.h>
27e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <dirent.h>
28e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <errno.h>
29e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
30e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <sys/stat.h>
31e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <unistd.h>
32e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <time.h>
33e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
34e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <pwd.h>
35e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <grp.h>
36e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
37e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <linux/kdev_t.h>
38e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
3918d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish#define DEFAULT_CONFIG_FILE "/data/local/perm_checker.conf"
4018d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish
41e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#define PERMS(M) (M & ~S_IFMT)
42e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#define MAX_NAME_LEN 4096
43e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#define MAX_UID_LEN 256
44e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#define MAX_GID_LEN MAX_UID_LEN
45e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
4618d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfishstatic char *config_file;
4718d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfishstatic char *executable_file;
4818d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish
49e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectenum perm_rule_type {EXACT_FILE = 0, EXACT_DIR, WILDCARD, RECURSIVE,
50e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    NUM_PR_TYPES};
51e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
52e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstruct perm_rule {
53e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    char *rule_text;
54e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    int rule_line;
55e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    char *spec;
56e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    mode_t min_mode;
57e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    mode_t max_mode;
58e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    uid_t min_uid;
59e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    uid_t max_uid;
60e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    gid_t min_gid;
61e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    gid_t max_gid;
62e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    enum perm_rule_type type;
63e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    struct perm_rule *next;
64e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project};
65e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
66e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projecttypedef struct perm_rule perm_rule_t;
67e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
68e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic perm_rule_t *rules[NUM_PR_TYPES];
69e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
70e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic uid_t str2uid(char *str, int line_num)
71e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project{
72e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    struct passwd *pw;
73e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
74e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (isdigit(str[0]))
75e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return (uid_t) atol(str);
76e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
77e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (!(pw = getpwnam(str))) {
78e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        printf("# ERROR # Invalid uid '%s' reading line %d\n", str, line_num);
79e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        exit(255);
80e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
81e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    return pw->pw_uid;
82e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}
83e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
84e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic gid_t str2gid(char *str, int line_num)
85e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project{
86e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    struct group *gr;
87e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
88e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (isdigit(str[0]))
89e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return (uid_t) atol(str);
90e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
91e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (!(gr = getgrnam(str))) {
92e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        printf("# ERROR # Invalid gid '%s' reading line %d\n", str, line_num);
93e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        exit(255);
94e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
95e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    return gr->gr_gid;
96e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}
97e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
9818d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfishstatic void add_rule(int line_num, char *spec,
9918d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish                     unsigned long min_mode, unsigned long max_mode,
10018d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish                     char *min_uid_buf, char *max_uid_buf,
10118d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish                     char *min_gid_buf, char *max_gid_buf) {
10218d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish
10318d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish    char rule_text_buf[MAX_NAME_LEN + 2*MAX_UID_LEN + 2*MAX_GID_LEN + 9];
10418d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish    perm_rule_t *pr = malloc(sizeof(perm_rule_t));
10518d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish    if (!pr) {
10618d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish        printf("Out of memory.\n");
10718d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish        exit(255);
10818d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish    }
10918d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish    if (snprintf(rule_text_buf, sizeof(rule_text_buf),
11018d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish                 "%s %lo %lo %s %s %s %s", spec, min_mode, max_mode,
11118d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish                 min_uid_buf, max_uid_buf, min_gid_buf, max_gid_buf)
11218d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish                 >= (long int) sizeof(rule_text_buf)) {
11318d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish        // This should never happen, but just in case...
11418d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish        printf("# ERROR # Maximum length limits exceeded on line %d\n",
11518d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish               line_num);
11618d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish        exit(255);
11718d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish    }
11818d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish    pr->rule_text = strndup(rule_text_buf, sizeof(rule_text_buf));
11918d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish    pr->rule_line = line_num;
12018d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish    if (strstr(spec, "/...")) {
12118d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish        pr->spec = strndup(spec, strlen(spec) - 3);
12218d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish        pr->type = RECURSIVE;
12318d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish    } else if (spec[strlen(spec) - 1] == '*') {
12418d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish        pr->spec = strndup(spec, strlen(spec) - 1);
12518d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish        pr->type = WILDCARD;
12618d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish    } else if (spec[strlen(spec) - 1] == '/') {
12718d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish        pr->spec = strdup(spec);
12818d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish        pr->type = EXACT_DIR;
12918d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish    } else {
13018d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish        pr->spec = strdup(spec);
13118d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish        pr->type = EXACT_FILE;
13218d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish    }
13318d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish    if ((pr->spec == NULL) || (pr->rule_text == NULL)) {
13418d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish        printf("Out of memory.\n");
13518d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish        exit(255);
13618d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish    }
13718d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish    pr->min_mode = min_mode;
13818d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish    pr->max_mode = max_mode;
13918d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish    pr->min_uid = str2uid(min_uid_buf, line_num);
14018d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish    pr->max_uid = str2uid(max_uid_buf, line_num);
14118d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish    pr->min_gid = str2gid(min_gid_buf, line_num);
14218d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish    pr->max_gid = str2gid(max_gid_buf, line_num);
14318d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish
14418d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish    // Add the rule to the appropriate set
14518d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish    pr->next = rules[pr->type];
14618d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish    rules[pr->type] = pr;
14718d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish#if 0  // Useful for debugging
14818d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish    printf("rule #%d: type = %d spec = %s min_mode = %o max_mode = %o "
14918d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish           "min_uid = %d max_uid = %d min_gid = %d max_gid = %d\n",
15018d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish           num_rules, pr->type, pr->spec, pr->min_mode, pr->max_mode,
15118d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish           pr->min_uid, pr->max_uid, pr->min_gid, pr->max_gid);
15218d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish#endif
15318d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish}
15418d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish
155e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic int read_rules(FILE *fp)
156e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project{
157e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    char spec[MAX_NAME_LEN + 5];  // Allows for "/..." suffix + terminator
158e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    char min_uid_buf[MAX_UID_LEN + 1], max_uid_buf[MAX_UID_LEN + 1];
159e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    char min_gid_buf[MAX_GID_LEN + 1], max_gid_buf[MAX_GID_LEN + 1];
160e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned long min_mode, max_mode;
161e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    int res;
162e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    int num_rules = 0, num_lines = 0;
163e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
164e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    // Note: Use of an unsafe C function here is OK, since this is a test
165e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    while ((res = fscanf(fp, "%s %lo %lo %s %s %s %s\n", spec,
166e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                         &min_mode, &max_mode, min_uid_buf, max_uid_buf,
167e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                         min_gid_buf, max_gid_buf)) != EOF) {
168e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        num_lines++;
169e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        if (res < 7) {
170e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            printf("# WARNING # Invalid rule on line number %d\n", num_lines);
171e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            continue;
172e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        }
17318d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish        add_rule(num_lines, spec,
17418d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish                 min_mode, max_mode,
17518d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish                 min_uid_buf, max_uid_buf,
17618d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish                 min_gid_buf, max_gid_buf);
177e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        num_rules++;
178e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
17918d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish
18018d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish    // Automatically add a rule to match this executable itself
18118d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish    add_rule(-1, executable_file,
18218d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish             000, 0777,
18318d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish             "root", "shell",
18418d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish             "root", "shell");
18518d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish
18618d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish    // Automatically add a rule to match the configuration file
18718d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish    add_rule(-1, config_file,
18818d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish             000, 0777,
18918d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish             "root", "shell",
19018d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish             "root", "shell");
19118d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish
192e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    return num_lines - num_rules;
193e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}
194e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
195e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic void print_failed_rule(const perm_rule_t *pr)
196e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project{
197e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    printf("# INFO # Failed rule #%d: %s\n", pr->rule_line, pr->rule_text);
198e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}
199e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
200e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic void print_new_rule(const char *name, mode_t mode, uid_t uid, gid_t gid)
201e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project{
202e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    struct passwd *pw;
203e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    struct group *gr;
204e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    gr = getgrgid(gid);
205e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    pw = getpwuid(uid);
206e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    printf("%s %4o %4o %s %d %s %d\n", name, mode, mode, pw->pw_name, uid,
207e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project           gr->gr_name, gid);
208e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}
209e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
210e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project// Returns 1 if the rule passes, prints the failure and returns 0 if not
211e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic int pass_rule(const perm_rule_t *pr, mode_t mode, uid_t uid, gid_t gid)
212e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project{
213e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (((pr->min_mode & mode) == pr->min_mode) &&
214e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            ((pr->max_mode | mode) == pr->max_mode) &&
215e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            (pr->min_gid <= gid) && (pr->max_gid >= gid) &&
216e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            (pr->min_uid <= uid) && (pr->max_uid >= uid))
217e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return 1;
218e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    print_failed_rule(pr);
219e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    return 0;
220e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}
221e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
222e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project// Returns 0 on success
223e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic int validate_file(const char *name, mode_t mode, uid_t uid, gid_t gid)
224e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project{
225e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    perm_rule_t *pr;
226e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    int rules_matched = 0;
227e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    int retval = 0;
228e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
229e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    pr = rules[EXACT_FILE];
230e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    while (pr != NULL) {
231e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        if (strcmp(name, pr->spec) == 0) {
232e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            if (!pass_rule(pr, mode, uid, gid))
233e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                retval++;
234e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            else
235e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                rules_matched++;  // Exact match found
236e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        }
237e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        pr = pr->next;
238e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
239e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
240e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if ((retval + rules_matched) > 1)
241e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        printf("# WARNING # Multiple exact rules for file: %s\n", name);
242e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
243e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    // If any exact rule matched or failed, we are done with this file
244e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (retval)
245e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        print_new_rule(name, mode, uid, gid);
246e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (rules_matched || retval)
247e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return retval;
248e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
249e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    pr = rules[WILDCARD];
250e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    while (pr != NULL) {
251e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        // Check if the spec is a prefix of the filename, and that the file
252e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        // is actually in the same directory as the wildcard.
253e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        if ((strstr(name, pr->spec) == name) &&
254e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                (!strchr(name + strlen(pr->spec), '/'))) {
255e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            if (!pass_rule(pr, mode, uid, gid))
256e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                retval++;
257e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            else
258e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                rules_matched++;
259e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        }
260e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        pr = pr->next;
261e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
262e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
263e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    pr = rules[RECURSIVE];
264e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    while (pr != NULL) {
265e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        if (strstr(name, pr->spec) == name) {
266e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            if (!pass_rule(pr, mode, uid, gid))
267e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                retval++;
268e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            else
269e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                rules_matched++;
270e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        }
271e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        pr = pr->next;
272e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
273e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
274e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (!rules_matched)
275e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        retval++;  // In case no rules either matched or failed, be sure to fail
276e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
277e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (retval)
278e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        print_new_rule(name, mode, uid, gid);
279e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
280e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    return retval;
281e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}
282e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
283e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project// Returns 0 on success
284e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic int validate_link(const char *name, mode_t mode, uid_t uid, gid_t gid)
285e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project{
286e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    perm_rule_t *pr;
287e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    int rules_matched = 0;
288e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    int retval = 0;
289e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
290e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    // For now, we match links against "exact" file rules only
291e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    pr = rules[EXACT_FILE];
292e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    while (pr != NULL) {
293e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        if (strcmp(name, pr->spec) == 0) {
294e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            if (!pass_rule(pr, mode, uid, gid))
295e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                retval++;
296e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            else
297e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                rules_matched++;  // Exact match found
298e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        }
299e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        pr = pr->next;
300e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
301e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
302e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if ((retval + rules_matched) > 1)
303e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        printf("# WARNING # Multiple exact rules for link: %s\n", name);
304e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (retval)
305e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        print_new_rule(name, mode, uid, gid);
30618d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish
307e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    // Note: Unlike files, if no rules matches for links, retval = 0 (success).
308e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    return retval;
309e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}
310e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
311e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project// Returns 0 on success
312e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic int validate_dir(const char *name, mode_t mode, uid_t uid, gid_t gid)
313e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project{
314e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    perm_rule_t *pr;
315e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    int rules_matched = 0;
316e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    int retval = 0;
317e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
318e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    pr = rules[EXACT_DIR];
319e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    while (pr != NULL) {
320e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        if (strcmp(name, pr->spec) == 0) {
321e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            if (!pass_rule(pr, mode, uid, gid))
322e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                retval++;
323e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            else
324e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                rules_matched++;  // Exact match found
325e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        }
326e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        pr = pr->next;
327e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
328e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
329e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if ((retval + rules_matched) > 1)
330e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        printf("# WARNING # Multiple exact rules for directory: %s\n", name);
331e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
332e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    // If any exact rule matched or failed, we are done with this directory
333e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (retval)
334e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        print_new_rule(name, mode, uid, gid);
335e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (rules_matched || retval)
336e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return retval;
337e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
338e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    pr = rules[RECURSIVE];
339e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    while (pr != NULL) {
340e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        if (strstr(name, pr->spec) == name) {
341e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            if (!pass_rule(pr, mode, uid, gid))
342e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                retval++;
343e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            else
344e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                rules_matched++;
345e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        }
346e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        pr = pr->next;
347e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
348e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
349e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (!rules_matched)
350e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        retval++;  // In case no rules either matched or failed, be sure to fail
351e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
352e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (retval)
353e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        print_new_rule(name, mode, uid, gid);
354e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
355e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    return retval;
356e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}
357e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
358e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project// Returns 0 on success
359e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic int check_path(const char *name)
360e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project{
361e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    char namebuf[MAX_NAME_LEN + 1];
362e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    char tmp[MAX_NAME_LEN + 1];
363e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    DIR *d;
364e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    struct dirent *de;
365e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    struct stat s;
366e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    int err;
367e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    int retval = 0;
368e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
369e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    err = lstat(name, &s);
370e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (err < 0) {
371e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        if (errno != ENOENT)
372e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        {
373e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            perror(name);
374e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            return 1;
375e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        }
376e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return 0;  // File doesn't exist anymore
377e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
378e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
379e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (S_ISDIR(s.st_mode)) {
380e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        if (name[strlen(name) - 1] != '/')
381e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            snprintf(namebuf, sizeof(namebuf), "%s/", name);
382e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        else
383e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            snprintf(namebuf, sizeof(namebuf), "%s", name);
384e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
385e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        retval |= validate_dir(namebuf, PERMS(s.st_mode), s.st_uid, s.st_gid);
386e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        d = opendir(namebuf);
387e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        if(d == 0) {
388e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            printf("%s : opendir failed: %s\n", namebuf, strerror(errno));
389e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            return 1;
390e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        }
391e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
392e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        while ((de = readdir(d)) != 0) {
393e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
394e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                continue;
395e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            snprintf(tmp, sizeof(tmp), "%s%s", namebuf, de->d_name);
396e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            retval |= check_path(tmp);
397e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        }
398e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        closedir(d);
399e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return retval;
400e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    } else if (S_ISLNK(s.st_mode)) {
401e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return validate_link(name, PERMS(s.st_mode), s.st_uid, s.st_gid);
402e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    } else {
403e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return validate_file(name, PERMS(s.st_mode), s.st_uid, s.st_gid);
404e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
405e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}
406e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
407e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectint main(int argc, char **argv)
408e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project{
409e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    FILE *fp;
410e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    int i;
411e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
41218d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish    if (argc > 2) {
41318d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish      printf("\nSyntax: %s [configfilename]\n", argv[0]);
41418d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish    }
41518d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish    config_file = (argc == 2) ? argv[1] : DEFAULT_CONFIG_FILE;
41618d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish    executable_file = argv[0];
41718d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish
418e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    // Initialize ruleset pointers
419e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    for (i = 0; i < NUM_PR_TYPES; i++)
420e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        rules[i] = NULL;
421e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
42218d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish    if (!(fp = fopen(config_file, "r"))) {
42318d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish        printf("Error opening %s\n", config_file);
424e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        exit(255);
425e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
426e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    read_rules(fp);
427e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    fclose(fp);
428e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
429e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (check_path("/"))
430e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return 255;
43118d9c5da994b8741877e999653f93fc6df1d6310Shabsi Walfish
432e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    printf("Passed.\n");
433e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    return 0;
434e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}
435