1f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross/*
2f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross * Copyright (C) 2010 The Android Open Source Project
3f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross *
4f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross * Licensed under the Apache License, Version 2.0 (the "License");
5f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross * you may not use this file except in compliance with the License.
6f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross * You may obtain a copy of the License at
7f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross *
8f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross *      http://www.apache.org/licenses/LICENSE-2.0
9f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross *
10f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross * Unless required by applicable law or agreed to in writing, software
11f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross * distributed under the License is distributed on an "AS IS" BASIS,
12f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross * See the License for the specific language governing permissions and
14f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross * limitations under the License.
15f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross */
16f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross
1744b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross#include <ctype.h>
18da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes#include <fcntl.h>
19da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes#include <poll.h>
208d48c8e45724c7103f0ace7885d339e49399908bBrian Swetland#include <signal.h>
21da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes#include <stdio.h>
22da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes#include <stdlib.h>
23da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes#include <string.h>
248d48c8e45724c7103f0ace7885d339e49399908bBrian Swetland
254f71319df011d796a60a43fc1bc68e16fbf7d321Elliott Hughes#include <android-base/stringprintf.h>
2644b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross#include <private/android_filesystem_config.h>
27da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes#include <selinux/selinux.h>
28f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross
29f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross#include "ueventd.h"
30f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross#include "log.h"
31f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross#include "util.h"
32f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross#include "devices.h"
3344b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross#include "ueventd_parser.h"
3474b34f3cb79aa8f2c5ba6a9dcc46d0dd84cdac86Rom Lemarchand#include "property_service.h"
352b99543cef1b8b0aa8cca39544939910035117b0Vladimir Chtchetkine
36f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Crossint ueventd_main(int argc, char **argv)
37f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross{
386ebf12fe1bc2de7af4522349973e8bfcc71d6126Nick Kralevich    /*
396ebf12fe1bc2de7af4522349973e8bfcc71d6126Nick Kralevich     * init sets the umask to 077 for forked processes. We need to
406ebf12fe1bc2de7af4522349973e8bfcc71d6126Nick Kralevich     * create files with exact permissions, without modification by
416ebf12fe1bc2de7af4522349973e8bfcc71d6126Nick Kralevich     * the umask.
426ebf12fe1bc2de7af4522349973e8bfcc71d6126Nick Kralevich     */
436ebf12fe1bc2de7af4522349973e8bfcc71d6126Nick Kralevich    umask(000);
446ebf12fe1bc2de7af4522349973e8bfcc71d6126Nick Kralevich
456ebf12fe1bc2de7af4522349973e8bfcc71d6126Nick Kralevich    /* Prevent fire-and-forget children from becoming zombies.
466ebf12fe1bc2de7af4522349973e8bfcc71d6126Nick Kralevich     * If we should need to wait() for some children in the future
476ebf12fe1bc2de7af4522349973e8bfcc71d6126Nick Kralevich     * (as opposed to none right now), double-forking here instead
486ebf12fe1bc2de7af4522349973e8bfcc71d6126Nick Kralevich     * of ignoring SIGCHLD may be the better solution.
496ebf12fe1bc2de7af4522349973e8bfcc71d6126Nick Kralevich     */
508d48c8e45724c7103f0ace7885d339e49399908bBrian Swetland    signal(SIGCHLD, SIG_IGN);
518d48c8e45724c7103f0ace7885d339e49399908bBrian Swetland
52f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross    open_devnull_stdio();
538f91282ebe1963b9d27f8779ad1342302b293bd2Dima Zavin    klog_init();
54da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes    klog_set_level(KLOG_NOTICE_LEVEL);
55f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross
56da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes    NOTICE("ueventd started!\n");
57439224e27530353351c7df504fb29fad9ac776a0Stephen Smalley
58da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes    selinux_callback cb;
59da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes    cb.func_log = selinux_klog_callback;
60da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes    selinux_set_callback(SELINUX_CB_LOG, cb);
61f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross
6274edcea90e31a3795e58aa1b2bbe96032f0bcd61Yabin Cui    std::string hardware = property_get("ro.hardware");
6344b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross
6444b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    ueventd_parse_config_file("/ueventd.rc");
6574edcea90e31a3795e58aa1b2bbe96032f0bcd61Yabin Cui    ueventd_parse_config_file(android::base::StringPrintf("/ueventd.%s.rc", hardware.c_str()).c_str());
6644b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross
67f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross    device_init();
68f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross
69da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes    pollfd ufd;
70f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross    ufd.events = POLLIN;
71f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross    ufd.fd = get_device_fd();
72f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross
73da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes    while (true) {
74f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross        ufd.revents = 0;
75da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes        int nr = poll(&ufd, 1, -1);
76da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes        if (nr <= 0) {
77f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross            continue;
78da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes        }
79da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes        if (ufd.revents & POLLIN) {
80da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes            handle_device_fd();
81da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes        }
82f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross    }
832145779c871d4a9f632a8afbfc2adc5bea185a45Elliott Hughes
842145779c871d4a9f632a8afbfc2adc5bea185a45Elliott Hughes    return 0;
85f83d0b9af5cbe4440cc41ceaa8a7806a13c86282Colin Cross}
8644b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross
8744b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Crossstatic int get_android_id(const char *id)
8844b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross{
8944b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    unsigned int i;
9044b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    for (i = 0; i < ARRAY_SIZE(android_ids); i++)
9144b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross        if (!strcmp(id, android_ids[i].name))
9244b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross            return android_ids[i].aid;
934f97fd91e361c8fc2f5fbcab0fa34e2bd68d3218Veeren Mandalia    return -1;
9444b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross}
9544b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross
9644b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Crossvoid set_device_permission(int nargs, char **args)
9744b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross{
9844b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    char *name;
99bc57d4ce925a62f14c28c55e0ff28af1114f12beBrian Swetland    char *attr = 0;
10044b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    mode_t perm;
10144b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    uid_t uid;
10244b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    gid_t gid;
10344b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    int prefix = 0;
104c0c1ffea588c7d3c565b79d4f8bf3d4a8f75abc9Daniel Leung    int wildcard = 0;
10544b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    char *endptr;
10644b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    int ret;
10744b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    char *tmp = 0;
10844b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross
10944b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    if (nargs == 0)
11044b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross        return;
11144b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross
11244b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    if (args[0][0] == '#')
11344b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross        return;
11444b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross
115bc57d4ce925a62f14c28c55e0ff28af1114f12beBrian Swetland    name = args[0];
116bc57d4ce925a62f14c28c55e0ff28af1114f12beBrian Swetland
117bc57d4ce925a62f14c28c55e0ff28af1114f12beBrian Swetland    if (!strncmp(name,"/sys/", 5) && (nargs == 5)) {
118bc57d4ce925a62f14c28c55e0ff28af1114f12beBrian Swetland        INFO("/sys/ rule %s %s\n",args[0],args[1]);
119bc57d4ce925a62f14c28c55e0ff28af1114f12beBrian Swetland        attr = args[1];
120bc57d4ce925a62f14c28c55e0ff28af1114f12beBrian Swetland        args++;
121bc57d4ce925a62f14c28c55e0ff28af1114f12beBrian Swetland        nargs--;
122bc57d4ce925a62f14c28c55e0ff28af1114f12beBrian Swetland    }
123bc57d4ce925a62f14c28c55e0ff28af1114f12beBrian Swetland
12444b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    if (nargs != 4) {
12544b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross        ERROR("invalid line ueventd.rc line for '%s'\n", args[0]);
12644b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross        return;
12744b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    }
12844b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross
12944b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    /* If path starts with mtd@ lookup the mount number. */
13044b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    if (!strncmp(name, "mtd@", 4)) {
13144b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross        int n = mtd_name_to_number(name + 4);
13244b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross        if (n >= 0)
13344b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross            asprintf(&tmp, "/dev/mtd/mtd%d", n);
13444b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross        name = tmp;
13544b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    } else {
13644b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross        int len = strlen(name);
137c0c1ffea588c7d3c565b79d4f8bf3d4a8f75abc9Daniel Leung        char *wildcard_chr = strchr(name, '*');
138c0c1ffea588c7d3c565b79d4f8bf3d4a8f75abc9Daniel Leung        if ((name[len - 1] == '*') &&
139c0c1ffea588c7d3c565b79d4f8bf3d4a8f75abc9Daniel Leung            (wildcard_chr == (name + len - 1))) {
14044b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross            prefix = 1;
14144b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross            name[len - 1] = '\0';
142c0c1ffea588c7d3c565b79d4f8bf3d4a8f75abc9Daniel Leung        } else if (wildcard_chr) {
143c0c1ffea588c7d3c565b79d4f8bf3d4a8f75abc9Daniel Leung            wildcard = 1;
14444b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross        }
14544b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    }
14644b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross
14744b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    perm = strtol(args[1], &endptr, 8);
14844b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    if (!endptr || *endptr != '\0') {
14944b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross        ERROR("invalid mode '%s'\n", args[1]);
15044b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross        free(tmp);
15144b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross        return;
15244b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    }
15344b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross
15444b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    ret = get_android_id(args[2]);
15544b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    if (ret < 0) {
15644b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross        ERROR("invalid uid '%s'\n", args[2]);
15744b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross        free(tmp);
15844b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross        return;
15944b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    }
16044b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    uid = ret;
16144b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross
16244b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    ret = get_android_id(args[3]);
16344b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    if (ret < 0) {
16444b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross        ERROR("invalid gid '%s'\n", args[3]);
16544b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross        free(tmp);
16644b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross        return;
16744b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    }
16844b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    gid = ret;
16944b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross
170c0c1ffea588c7d3c565b79d4f8bf3d4a8f75abc9Daniel Leung    add_dev_perms(name, attr, perm, uid, gid, prefix, wildcard);
17144b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    free(tmp);
17244b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross}
173