1*ec63e07aSXin Li // Copyright 2019 Google LLC
2*ec63e07aSXin Li //
3*ec63e07aSXin Li // Licensed under the Apache License, Version 2.0 (the "License");
4*ec63e07aSXin Li // you may not use this file except in compliance with the License.
5*ec63e07aSXin Li // You may obtain a copy of the License at
6*ec63e07aSXin Li //
7*ec63e07aSXin Li // https://www.apache.org/licenses/LICENSE-2.0
8*ec63e07aSXin Li //
9*ec63e07aSXin Li // Unless required by applicable law or agreed to in writing, software
10*ec63e07aSXin Li // distributed under the License is distributed on an "AS IS" BASIS,
11*ec63e07aSXin Li // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*ec63e07aSXin Li // See the License for the specific language governing permissions and
13*ec63e07aSXin Li // limitations under the License.
14*ec63e07aSXin Li
15*ec63e07aSXin Li #include "sandboxed_api/var_int.h"
16*ec63e07aSXin Li
17*ec63e07aSXin Li #include <unistd.h>
18*ec63e07aSXin Li
19*ec63e07aSXin Li #include "absl/log/log.h"
20*ec63e07aSXin Li #include "absl/status/status.h"
21*ec63e07aSXin Li #include "sandboxed_api/rpcchannel.h"
22*ec63e07aSXin Li #include "sandboxed_api/util/status_macros.h"
23*ec63e07aSXin Li
24*ec63e07aSXin Li namespace sapi::v {
25*ec63e07aSXin Li
~Fd()26*ec63e07aSXin Li Fd::~Fd() {
27*ec63e07aSXin Li if (GetFreeRPCChannel() && GetRemoteFd() >= 0 && own_remote_) {
28*ec63e07aSXin Li this->CloseRemoteFd(GetFreeRPCChannel()).IgnoreError();
29*ec63e07aSXin Li }
30*ec63e07aSXin Li if (GetValue() >= 0 && own_local_) {
31*ec63e07aSXin Li CloseLocalFd();
32*ec63e07aSXin Li }
33*ec63e07aSXin Li }
34*ec63e07aSXin Li
CloseRemoteFd(RPCChannel * rpc_channel)35*ec63e07aSXin Li absl::Status Fd::CloseRemoteFd(RPCChannel* rpc_channel) {
36*ec63e07aSXin Li SAPI_RETURN_IF_ERROR(rpc_channel->Close(GetRemoteFd()));
37*ec63e07aSXin Li
38*ec63e07aSXin Li SetRemoteFd(-1);
39*ec63e07aSXin Li return absl::OkStatus();
40*ec63e07aSXin Li }
41*ec63e07aSXin Li
CloseLocalFd()42*ec63e07aSXin Li void Fd::CloseLocalFd() {
43*ec63e07aSXin Li if (GetValue() < 0) {
44*ec63e07aSXin Li return;
45*ec63e07aSXin Li }
46*ec63e07aSXin Li if (close(GetValue()) != 0) {
47*ec63e07aSXin Li PLOG(WARNING) << "close(" << GetValue() << ") failed";
48*ec63e07aSXin Li }
49*ec63e07aSXin Li
50*ec63e07aSXin Li SetValue(-1);
51*ec63e07aSXin Li }
52*ec63e07aSXin Li
TransferToSandboxee(RPCChannel * rpc_channel,pid_t)53*ec63e07aSXin Li absl::Status Fd::TransferToSandboxee(RPCChannel* rpc_channel, pid_t /* pid */) {
54*ec63e07aSXin Li int remote_fd;
55*ec63e07aSXin Li
56*ec63e07aSXin Li SetFreeRPCChannel(rpc_channel);
57*ec63e07aSXin Li OwnRemoteFd(true);
58*ec63e07aSXin Li
59*ec63e07aSXin Li if (GetValue() < 0) {
60*ec63e07aSXin Li return absl::FailedPreconditionError(
61*ec63e07aSXin Li "Cannot transfer FD: Local FD not valid");
62*ec63e07aSXin Li }
63*ec63e07aSXin Li
64*ec63e07aSXin Li if (GetRemoteFd() >= 0) {
65*ec63e07aSXin Li return absl::FailedPreconditionError(
66*ec63e07aSXin Li "Cannot transfer FD: Sandboxee already has a valid FD");
67*ec63e07aSXin Li }
68*ec63e07aSXin Li
69*ec63e07aSXin Li SAPI_RETURN_IF_ERROR(rpc_channel->SendFD(GetValue(), &remote_fd));
70*ec63e07aSXin Li SetRemoteFd(remote_fd);
71*ec63e07aSXin Li
72*ec63e07aSXin Li return absl::OkStatus();
73*ec63e07aSXin Li }
74*ec63e07aSXin Li
TransferFromSandboxee(RPCChannel * rpc_channel,pid_t)75*ec63e07aSXin Li absl::Status Fd::TransferFromSandboxee(RPCChannel* rpc_channel,
76*ec63e07aSXin Li pid_t /* pid */) {
77*ec63e07aSXin Li int local_fd;
78*ec63e07aSXin Li
79*ec63e07aSXin Li SetFreeRPCChannel(rpc_channel);
80*ec63e07aSXin Li OwnRemoteFd(false);
81*ec63e07aSXin Li
82*ec63e07aSXin Li if (GetValue()) {
83*ec63e07aSXin Li return absl::FailedPreconditionError(
84*ec63e07aSXin Li "Cannot transfer FD back: Our FD is already valid");
85*ec63e07aSXin Li }
86*ec63e07aSXin Li
87*ec63e07aSXin Li if (GetRemoteFd() < 0) {
88*ec63e07aSXin Li return absl::FailedPreconditionError(
89*ec63e07aSXin Li "Cannot transfer FD back: Sandboxee has no valid FD");
90*ec63e07aSXin Li }
91*ec63e07aSXin Li
92*ec63e07aSXin Li SAPI_RETURN_IF_ERROR(rpc_channel->RecvFD(GetRemoteFd(), &local_fd));
93*ec63e07aSXin Li SetValue(local_fd);
94*ec63e07aSXin Li
95*ec63e07aSXin Li return absl::OkStatus();
96*ec63e07aSXin Li }
97*ec63e07aSXin Li
98*ec63e07aSXin Li } // namespace sapi::v
99