blob: 56ac56e09f23b0521cb767b691e966be7facff6c [file] [log] [blame]
Rajat Jain8e567e22020-11-03 14:59:28 -08001// Copyright 2020 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "pciguard/authorizer.h"
Rajat Jain8e567e22020-11-03 14:59:28 -08006
7#include <sysexits.h>
8
9namespace pciguard {
10
11void* Authorizer::AuthorizerThread(void* ptr) {
12 if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) ||
13 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
14 PLOG(ERROR) << __func__ << ": Can't set thread cancel state or type.";
15 exit(EX_OSERR);
16 }
17
18 Authorizer* authorizer = static_cast<Authorizer*>(ptr);
19 Job job;
20 while (authorizer->GetNextJob(&job)) {
21 if (job.type_ == AUTHORIZE_ALL_DEVICES)
Rajat Jain5bf732b2021-01-22 14:57:59 -080022 authorizer->utils_->AuthorizeAllDevices();
Rajat Jain8e567e22020-11-03 14:59:28 -080023 else
Rajat Jain5bf732b2021-01-22 14:57:59 -080024 authorizer->utils_->AuthorizeThunderboltDev(job.syspath_);
Rajat Jain28cd9ad2021-03-22 12:39:53 -070025
26 pthread_mutex_lock(&authorizer->mutex_);
27 authorizer->authorization_in_flight_ = false;
28 pthread_mutex_unlock(&authorizer->mutex_);
Rajat Jain8e567e22020-11-03 14:59:28 -080029 }
30 return NULL;
31}
32
Rajat Jain5bf732b2021-01-22 14:57:59 -080033Authorizer::Authorizer(SysfsUtils* utils)
Rajat Jain8e567e22020-11-03 14:59:28 -080034 : mutex_(PTHREAD_MUTEX_INITIALIZER),
Rajat Jain5bf732b2021-01-22 14:57:59 -080035 job_available_(PTHREAD_COND_INITIALIZER),
Rajat Jain28cd9ad2021-03-22 12:39:53 -070036 authorization_in_flight_(false),
Rajat Jain5bf732b2021-01-22 14:57:59 -080037 utils_(utils) {
Rajat Jain8e567e22020-11-03 14:59:28 -080038 if (pthread_create(&authorizer_thread_, NULL, &Authorizer::AuthorizerThread,
39 this)) {
40 PLOG(ERROR) << __func__ << ": Problem creating thread. Exiting now";
41 exit(EX_OSERR);
42 }
43 LOG(INFO) << "Created new authorizer object";
44}
45
46Authorizer::~Authorizer() {
47 pthread_cancel(authorizer_thread_);
48 pthread_join(authorizer_thread_, NULL);
49 LOG(INFO) << "Destroyed authorizer object";
50}
51
52void Authorizer::SubmitJob(JobType type, base::FilePath path) {
53 Job job = {type, path};
54
55 if (pthread_mutex_lock(&mutex_)) {
56 PLOG(ERROR) << "Mutex lock issue while submitting job";
57 return;
58 }
59 queue_.push(job);
60 LOG(INFO) << "Inserted authorization job (" << queue_.back().type_ << ","
61 << queue_.back().syspath_ << ")";
62 pthread_cond_signal(&job_available_);
63
64 if (pthread_mutex_unlock(&mutex_)) {
65 PLOG(ERROR) << "Mutex unlock issue while submitting job";
66 return;
67 }
68}
69
Rajat Jain5bf732b2021-01-22 14:57:59 -080070bool Authorizer::IsJobQueueEmpty() {
71 if (pthread_mutex_lock(&mutex_)) {
72 PLOG(ERROR) << "Mutex lock issue while checking job queue status";
73 exit(EXIT_FAILURE);
74 }
Rajat Jain28cd9ad2021-03-22 12:39:53 -070075 auto ret = queue_.empty() && !authorization_in_flight_;
Rajat Jain5bf732b2021-01-22 14:57:59 -080076 if (pthread_mutex_unlock(&mutex_)) {
77 PLOG(ERROR) << "Mutex unlock issue while checking job queue status";
78 exit(EXIT_FAILURE);
79 }
80 return ret;
81}
82
Rajat Jain8e567e22020-11-03 14:59:28 -080083// Pops and returns next authorization job. If no job, then blocks until
84// next job is available
85bool Authorizer::GetNextJob(Job* job) {
86 if (pthread_mutex_lock(&mutex_)) {
87 PLOG(ERROR) << "Mutex lock issue while retrieving job";
88 return false;
89 }
90
91 do {
92 if (!queue_.empty()) {
93 *job = queue_.front();
94 queue_.pop();
95 LOG(INFO) << "Fetched authorization job (" << job->type_ << ","
96 << job->syspath_ << ")";
97
Rajat Jain28cd9ad2021-03-22 12:39:53 -070098 authorization_in_flight_ = true;
99
Rajat Jain8e567e22020-11-03 14:59:28 -0800100 if (pthread_mutex_unlock(&mutex_))
101 PLOG(ERROR) << "Mutex unlock issue while retrieving job";
102 return true;
103 }
104 } while (!pthread_cond_wait(&job_available_, &mutex_));
105
106 if (pthread_mutex_unlock(&mutex_))
107 PLOG(ERROR) << "Mutex unlock issue while retrieving job";
108 return false;
109}
110
111} // namespace pciguard