trunksd.cc revision 4dc4629c415e7ca90ff146d7bb75b5646ecd8b17
1//
2// Copyright (C) 2014 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//      http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
17#include <sysexits.h>
18
19#include <base/at_exit.h>
20#include <base/bind.h>
21#include <base/command_line.h>
22#include <base/threading/thread.h>
23#include <brillo/minijail/minijail.h>
24#include <brillo/syslog_logging.h>
25#include <brillo/userdb_utils.h>
26
27#include "trunks/background_command_transceiver.h"
28#include "trunks/resource_manager.h"
29#include "trunks/tpm_handle.h"
30#include "trunks/tpm_simulator_handle.h"
31#if defined(USE_BINDER_IPC)
32#include "trunks/trunks_binder_service.h"
33#else
34#include "trunks/trunks_dbus_service.h"
35#endif
36#include "trunks/trunks_factory_impl.h"
37#include "trunks/trunks_ftdi_spi.h"
38
39namespace {
40
41const uid_t kRootUID = 0;
42const char kTrunksUser[] = "trunks";
43const char kTrunksGroup[] = "trunks";
44#if defined(__ANDROID__)
45const char kTrunksSeccompPath[] =
46    "/system/usr/share/policy/trunksd-seccomp.policy";
47#else
48const char kTrunksSeccompPath[] = "/usr/share/policy/trunksd-seccomp.policy";
49#endif
50const char kBackgroundThreadName[] = "trunksd_background_thread";
51
52void InitMinijailSandbox() {
53  uid_t trunks_uid;
54  gid_t trunks_gid;
55  CHECK(brillo::userdb::GetUserInfo(kTrunksUser, &trunks_uid, &trunks_gid))
56      << "Error getting trunks uid and gid.";
57  CHECK_EQ(getuid(), kRootUID) << "trunksd not initialized as root.";
58  brillo::Minijail* minijail = brillo::Minijail::GetInstance();
59  struct minijail* jail = minijail->New();
60  minijail->DropRoot(jail, kTrunksUser, kTrunksGroup);
61  minijail->UseSeccompFilter(jail, kTrunksSeccompPath);
62  minijail->Enter(jail);
63  minijail->Destroy(jail);
64  CHECK_EQ(getuid(), trunks_uid)
65      << "trunksd was not able to drop user privilege.";
66  CHECK_EQ(getgid(), trunks_gid)
67      << "trunksd was not able to drop group privilege.";
68}
69
70}  // namespace
71
72int main(int argc, char** argv) {
73  base::CommandLine::Init(argc, argv);
74  base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
75  int flags = brillo::kLogToSyslog;
76  if (cl->HasSwitch("log_to_stderr")) {
77    flags |= brillo::kLogToStderr;
78  }
79  brillo::InitLog(flags);
80
81// Create a service instance before anything else so objects like
82// AtExitManager exist.
83#if defined(USE_BINDER_IPC)
84  trunks::TrunksBinderService service;
85#else
86  trunks::TrunksDBusService service;
87#endif
88
89  // Chain together command transceivers:
90  //   [IPC] --> BackgroundCommandTransceiver
91  //         --> ResourceManager
92  //         --> TpmHandle
93  //         --> [TPM]
94  trunks::CommandTransceiver* low_level_transceiver;
95  if (cl->HasSwitch("ftdi")) {
96    LOG(INFO) << "Sending commands to FTDI SPI.";
97    low_level_transceiver = new trunks::TrunksFtdiSpi();
98  } else if (cl->HasSwitch("simulator")) {
99    LOG(INFO) << "Sending commands to simulator.";
100    low_level_transceiver = new trunks::TpmSimulatorHandle();
101  } else {
102    low_level_transceiver = new trunks::TpmHandle();
103  }
104  CHECK(low_level_transceiver->Init())
105      << "Error initializing TPM communication.";
106  // This needs to be *after* opening the TPM handle and *before* starting the
107  // background thread.
108  InitMinijailSandbox();
109  base::Thread background_thread(kBackgroundThreadName);
110  CHECK(background_thread.Start()) << "Failed to start background thread.";
111  trunks::TrunksFactoryImpl factory(low_level_transceiver);
112  trunks::ResourceManager resource_manager(factory, low_level_transceiver);
113  background_thread.task_runner()->PostNonNestableTask(
114      FROM_HERE, base::Bind(&trunks::ResourceManager::Initialize,
115                            base::Unretained(&resource_manager)));
116  trunks::BackgroundCommandTransceiver background_transceiver(
117      &resource_manager, background_thread.task_runner());
118  service.set_transceiver(&background_transceiver);
119  LOG(INFO) << "Trunks service started.";
120  return service.Run();
121}
122