16d528ed9Sopenharmony_ci// Copyright (c) 2011 The Chromium Authors. All rights reserved. 26d528ed9Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 36d528ed9Sopenharmony_ci// found in the LICENSE file. 46d528ed9Sopenharmony_ci 56d528ed9Sopenharmony_ci#include "base/posix/file_descriptor_shuffle.h" 66d528ed9Sopenharmony_ci 76d528ed9Sopenharmony_ci#include <stddef.h> 86d528ed9Sopenharmony_ci#include <unistd.h> 96d528ed9Sopenharmony_ci#include <ostream> 106d528ed9Sopenharmony_ci 116d528ed9Sopenharmony_ci#include "base/logging.h" 126d528ed9Sopenharmony_ci#include "base/posix/eintr_wrapper.h" 136d528ed9Sopenharmony_ci 146d528ed9Sopenharmony_cinamespace base { 156d528ed9Sopenharmony_ci 166d528ed9Sopenharmony_cibool PerformInjectiveMultimapDestructive(InjectiveMultimap* m, 176d528ed9Sopenharmony_ci InjectionDelegate* delegate) { 186d528ed9Sopenharmony_ci static const size_t kMaxExtraFDs = 16; 196d528ed9Sopenharmony_ci int extra_fds[kMaxExtraFDs]; 206d528ed9Sopenharmony_ci unsigned next_extra_fd = 0; 216d528ed9Sopenharmony_ci 226d528ed9Sopenharmony_ci // DANGER: this function must not allocate or lock. 236d528ed9Sopenharmony_ci // Cannot use STL iterators here, since debug iterators use locks. 246d528ed9Sopenharmony_ci 256d528ed9Sopenharmony_ci for (size_t i_index = 0; i_index < m->size(); ++i_index) { 266d528ed9Sopenharmony_ci InjectiveMultimap::value_type* i = &(*m)[i_index]; 276d528ed9Sopenharmony_ci int temp_fd = -1; 286d528ed9Sopenharmony_ci 296d528ed9Sopenharmony_ci // We DCHECK the injectiveness of the mapping. 306d528ed9Sopenharmony_ci for (size_t j_index = i_index + 1; j_index < m->size(); ++j_index) { 316d528ed9Sopenharmony_ci InjectiveMultimap::value_type* j = &(*m)[j_index]; 326d528ed9Sopenharmony_ci DCHECK(i->dest != j->dest) << "Both fd " << i->source << " and " 336d528ed9Sopenharmony_ci << j->source << " map to " << i->dest; 346d528ed9Sopenharmony_ci } 356d528ed9Sopenharmony_ci 366d528ed9Sopenharmony_ci const bool is_identity = i->source == i->dest; 376d528ed9Sopenharmony_ci 386d528ed9Sopenharmony_ci for (size_t j_index = i_index + 1; j_index < m->size(); ++j_index) { 396d528ed9Sopenharmony_ci InjectiveMultimap::value_type* j = &(*m)[j_index]; 406d528ed9Sopenharmony_ci if (!is_identity && i->dest == j->source) { 416d528ed9Sopenharmony_ci if (temp_fd == -1) { 426d528ed9Sopenharmony_ci if (!delegate->Duplicate(&temp_fd, i->dest)) 436d528ed9Sopenharmony_ci return false; 446d528ed9Sopenharmony_ci if (next_extra_fd < kMaxExtraFDs) { 456d528ed9Sopenharmony_ci extra_fds[next_extra_fd++] = temp_fd; 466d528ed9Sopenharmony_ci } else { 476d528ed9Sopenharmony_ci RAW_LOG(ERROR, 486d528ed9Sopenharmony_ci "PerformInjectiveMultimapDestructive overflowed " 496d528ed9Sopenharmony_ci "extra_fds. Leaking file descriptors!"); 506d528ed9Sopenharmony_ci } 516d528ed9Sopenharmony_ci } 526d528ed9Sopenharmony_ci 536d528ed9Sopenharmony_ci j->source = temp_fd; 546d528ed9Sopenharmony_ci j->close = false; 556d528ed9Sopenharmony_ci } 566d528ed9Sopenharmony_ci 576d528ed9Sopenharmony_ci if (i->close && i->source == j->dest) 586d528ed9Sopenharmony_ci i->close = false; 596d528ed9Sopenharmony_ci 606d528ed9Sopenharmony_ci if (i->close && i->source == j->source) { 616d528ed9Sopenharmony_ci i->close = false; 626d528ed9Sopenharmony_ci j->close = true; 636d528ed9Sopenharmony_ci } 646d528ed9Sopenharmony_ci } 656d528ed9Sopenharmony_ci 666d528ed9Sopenharmony_ci if (!is_identity) { 676d528ed9Sopenharmony_ci if (!delegate->Move(i->source, i->dest)) 686d528ed9Sopenharmony_ci return false; 696d528ed9Sopenharmony_ci } 706d528ed9Sopenharmony_ci 716d528ed9Sopenharmony_ci if (!is_identity && i->close) 726d528ed9Sopenharmony_ci delegate->Close(i->source); 736d528ed9Sopenharmony_ci } 746d528ed9Sopenharmony_ci 756d528ed9Sopenharmony_ci for (unsigned i = 0; i < next_extra_fd; i++) 766d528ed9Sopenharmony_ci delegate->Close(extra_fds[i]); 776d528ed9Sopenharmony_ci 786d528ed9Sopenharmony_ci return true; 796d528ed9Sopenharmony_ci} 806d528ed9Sopenharmony_ci 816d528ed9Sopenharmony_cibool PerformInjectiveMultimap(const InjectiveMultimap& m_in, 826d528ed9Sopenharmony_ci InjectionDelegate* delegate) { 836d528ed9Sopenharmony_ci InjectiveMultimap m(m_in); 846d528ed9Sopenharmony_ci return PerformInjectiveMultimapDestructive(&m, delegate); 856d528ed9Sopenharmony_ci} 866d528ed9Sopenharmony_ci 876d528ed9Sopenharmony_cibool FileDescriptorTableInjection::Duplicate(int* result, int fd) { 886d528ed9Sopenharmony_ci *result = HANDLE_EINTR(dup(fd)); 896d528ed9Sopenharmony_ci return *result >= 0; 906d528ed9Sopenharmony_ci} 916d528ed9Sopenharmony_ci 926d528ed9Sopenharmony_cibool FileDescriptorTableInjection::Move(int src, int dest) { 936d528ed9Sopenharmony_ci return HANDLE_EINTR(dup2(src, dest)) != -1; 946d528ed9Sopenharmony_ci} 956d528ed9Sopenharmony_ci 966d528ed9Sopenharmony_civoid FileDescriptorTableInjection::Close(int fd) { 976d528ed9Sopenharmony_ci int ret = IGNORE_EINTR(close(fd)); 986d528ed9Sopenharmony_ci DPCHECK(ret == 0); 996d528ed9Sopenharmony_ci} 1006d528ed9Sopenharmony_ci 1016d528ed9Sopenharmony_ci} // namespace base 102