Home | History | Annotate | Download | only in trunks
      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 
     39 namespace {
     40 
     41 const uid_t kRootUID = 0;
     42 #if defined(__ANDROID__)
     43 const char kTrunksUser[] = "system";
     44 const char kTrunksGroup[] = "system";
     45 const char kTrunksSeccompPath[] =
     46     "/system/usr/share/policy/trunksd-seccomp.policy";
     47 #else
     48 const char kTrunksUser[] = "trunks";
     49 const char kTrunksGroup[] = "trunks";
     50 const char kTrunksSeccompPath[] = "/usr/share/policy/trunksd-seccomp.policy";
     51 #endif
     52 const char kBackgroundThreadName[] = "trunksd_background_thread";
     53 
     54 void InitMinijailSandbox() {
     55   uid_t trunks_uid;
     56   gid_t trunks_gid;
     57   CHECK(brillo::userdb::GetUserInfo(kTrunksUser, &trunks_uid, &trunks_gid))
     58       << "Error getting trunks uid and gid.";
     59   CHECK_EQ(getuid(), kRootUID) << "trunksd not initialized as root.";
     60   brillo::Minijail* minijail = brillo::Minijail::GetInstance();
     61   struct minijail* jail = minijail->New();
     62   minijail->DropRoot(jail, kTrunksUser, kTrunksGroup);
     63   minijail->UseSeccompFilter(jail, kTrunksSeccompPath);
     64   minijail->Enter(jail);
     65   minijail->Destroy(jail);
     66   CHECK_EQ(getuid(), trunks_uid)
     67       << "trunksd was not able to drop user privilege.";
     68   CHECK_EQ(getgid(), trunks_gid)
     69       << "trunksd was not able to drop group privilege.";
     70 }
     71 
     72 }  // namespace
     73 
     74 int main(int argc, char **argv) {
     75   base::CommandLine::Init(argc, argv);
     76   base::CommandLine *cl = base::CommandLine::ForCurrentProcess();
     77   int flags = brillo::kLogToSyslog;
     78   if (cl->HasSwitch("log_to_stderr")) {
     79     flags |= brillo::kLogToStderr;
     80   }
     81   brillo::InitLog(flags);
     82 
     83   // Create a service instance before anything else so objects like
     84   // AtExitManager exist.
     85 #if defined(USE_BINDER_IPC)
     86   trunks::TrunksBinderService service;
     87 #else
     88   trunks::TrunksDBusService service;
     89 #endif
     90 
     91   // Chain together command transceivers:
     92   //   [IPC] --> BackgroundCommandTransceiver
     93   //         --> ResourceManager
     94   //         --> TpmHandle
     95   //         --> [TPM]
     96   trunks::CommandTransceiver *low_level_transceiver;
     97   if (cl->HasSwitch("ftdi")) {
     98     LOG(INFO) << "Sending commands to FTDI SPI.";
     99     low_level_transceiver = new trunks::TrunksFtdiSpi();
    100   } else if (cl->HasSwitch("simulator")) {
    101     LOG(INFO) << "Sending commands to simulator.";
    102     low_level_transceiver = new trunks::TpmSimulatorHandle();
    103   } else {
    104     low_level_transceiver = new trunks::TpmHandle();
    105   }
    106   CHECK(low_level_transceiver->Init())
    107       << "Error initializing TPM communication.";
    108   // This needs to be *after* opening the TPM handle and *before* starting the
    109   // background thread.
    110   InitMinijailSandbox();
    111   base::Thread background_thread(kBackgroundThreadName);
    112   CHECK(background_thread.Start()) << "Failed to start background thread.";
    113   trunks::TrunksFactoryImpl factory(low_level_transceiver);
    114   trunks::ResourceManager resource_manager(factory, low_level_transceiver);
    115   background_thread.task_runner()->PostNonNestableTask(
    116       FROM_HERE, base::Bind(&trunks::ResourceManager::Initialize,
    117                             base::Unretained(&resource_manager)));
    118   trunks::BackgroundCommandTransceiver background_transceiver(
    119       &resource_manager, background_thread.task_runner());
    120   service.set_transceiver(&background_transceiver);
    121   LOG(INFO) << "Trunks service started.";
    122   return service.Run();
    123 }
    124