1// Copyright (c) 2012 The Chromium 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 "content/common/child_process_sandbox_support_impl_linux.h" 6 7#include <sys/stat.h> 8 9#include <limits> 10 11#include "base/basictypes.h" 12#include "base/debug/trace_event.h" 13#include "base/memory/scoped_ptr.h" 14#include "base/numerics/safe_conversions.h" 15#include "base/pickle.h" 16#include "base/posix/eintr_wrapper.h" 17#include "base/posix/unix_domain_socket_linux.h" 18#include "base/sys_byteorder.h" 19#include "content/common/sandbox_linux/sandbox_linux.h" 20#include "content/common/zygote_commands_linux.h" 21#include "third_party/WebKit/public/platform/linux/WebFallbackFont.h" 22#include "third_party/WebKit/public/platform/linux/WebFontRenderStyle.h" 23 24namespace content { 25 26void GetFallbackFontForCharacter(int32_t character, 27 const char* preferred_locale, 28 blink::WebFallbackFont* fallbackFont) { 29 TRACE_EVENT0("sandbox_ipc", "GetFontFamilyForCharacter"); 30 31 Pickle request; 32 request.WriteInt(LinuxSandbox::METHOD_GET_FALLBACK_FONT_FOR_CHAR); 33 request.WriteInt(character); 34 request.WriteString(preferred_locale); 35 36 uint8_t buf[512]; 37 const ssize_t n = UnixDomainSocket::SendRecvMsg(GetSandboxFD(), buf, 38 sizeof(buf), NULL, request); 39 40 std::string family_name; 41 std::string filename; 42 int fontconfigInterfaceId = 0; 43 int ttcIndex = 0; 44 bool isBold = false; 45 bool isItalic = false; 46 if (n != -1) { 47 Pickle reply(reinterpret_cast<char*>(buf), n); 48 PickleIterator pickle_iter(reply); 49 if (reply.ReadString(&pickle_iter, &family_name) && 50 reply.ReadString(&pickle_iter, &filename) && 51 reply.ReadInt(&pickle_iter, &fontconfigInterfaceId) && 52 reply.ReadInt(&pickle_iter, &ttcIndex) && 53 reply.ReadBool(&pickle_iter, &isBold) && 54 reply.ReadBool(&pickle_iter, &isItalic)) { 55 fallbackFont->name = family_name; 56 fallbackFont->filename = filename; 57 fallbackFont->fontconfigInterfaceId = fontconfigInterfaceId; 58 fallbackFont->ttcIndex = ttcIndex; 59 fallbackFont->isBold = isBold; 60 fallbackFont->isItalic = isItalic; 61 } 62 } 63} 64 65void GetRenderStyleForStrike(const char* family, 66 int size_and_style, 67 blink::WebFontRenderStyle* out) { 68 TRACE_EVENT0("sandbox_ipc", "GetRenderStyleForStrike"); 69 70 out->setDefaults(); 71 72 if (size_and_style < 0) 73 return; 74 75 const bool bold = size_and_style & 1; 76 const bool italic = size_and_style & 2; 77 const int pixel_size = size_and_style >> 2; 78 if (pixel_size > std::numeric_limits<uint16>::max()) 79 return; 80 81 Pickle request; 82 request.WriteInt(LinuxSandbox::METHOD_GET_STYLE_FOR_STRIKE); 83 request.WriteString(family); 84 request.WriteBool(bold); 85 request.WriteBool(italic); 86 request.WriteUInt16(pixel_size); 87 88 uint8_t buf[512]; 89 const ssize_t n = UnixDomainSocket::SendRecvMsg(GetSandboxFD(), buf, 90 sizeof(buf), NULL, request); 91 if (n == -1) 92 return; 93 94 Pickle reply(reinterpret_cast<char*>(buf), n); 95 PickleIterator pickle_iter(reply); 96 int use_bitmaps, use_autohint, use_hinting, hint_style, use_antialias; 97 int use_subpixel_rendering, use_subpixel_positioning; 98 if (reply.ReadInt(&pickle_iter, &use_bitmaps) && 99 reply.ReadInt(&pickle_iter, &use_autohint) && 100 reply.ReadInt(&pickle_iter, &use_hinting) && 101 reply.ReadInt(&pickle_iter, &hint_style) && 102 reply.ReadInt(&pickle_iter, &use_antialias) && 103 reply.ReadInt(&pickle_iter, &use_subpixel_rendering) && 104 reply.ReadInt(&pickle_iter, &use_subpixel_positioning)) { 105 out->useBitmaps = use_bitmaps; 106 out->useAutoHint = use_autohint; 107 out->useHinting = use_hinting; 108 out->hintStyle = hint_style; 109 out->useAntiAlias = use_antialias; 110 out->useSubpixelRendering = use_subpixel_rendering; 111 out->useSubpixelPositioning = use_subpixel_positioning; 112 } 113} 114 115int MatchFontWithFallback(const std::string& face, 116 bool bold, 117 bool italic, 118 int charset, 119 PP_BrowserFont_Trusted_Family fallback_family) { 120 TRACE_EVENT0("sandbox_ipc", "MatchFontWithFallback"); 121 122 Pickle request; 123 request.WriteInt(LinuxSandbox::METHOD_MATCH_WITH_FALLBACK); 124 request.WriteString(face); 125 request.WriteBool(bold); 126 request.WriteBool(italic); 127 request.WriteUInt32(charset); 128 request.WriteUInt32(fallback_family); 129 uint8_t reply_buf[64]; 130 int fd = -1; 131 UnixDomainSocket::SendRecvMsg(GetSandboxFD(), reply_buf, sizeof(reply_buf), 132 &fd, request); 133 return fd; 134} 135 136bool GetFontTable(int fd, uint32_t table_tag, off_t offset, 137 uint8_t* output, size_t* output_length) { 138 if (offset < 0) 139 return false; 140 141 size_t data_length = 0; // the length of the file data. 142 off_t data_offset = 0; // the offset of the data in the file. 143 if (table_tag == 0) { 144 // Get the entire font file. 145 struct stat st; 146 if (fstat(fd, &st) < 0) 147 return false; 148 data_length = base::checked_cast<size_t>(st.st_size); 149 } else { 150 // Get a font table. Read the header to find its offset in the file. 151 uint16_t num_tables; 152 ssize_t n = HANDLE_EINTR(pread(fd, &num_tables, sizeof(num_tables), 153 4 /* skip the font type */)); 154 if (n != sizeof(num_tables)) 155 return false; 156 // Font data is stored in net (big-endian) order. 157 num_tables = base::NetToHost16(num_tables); 158 159 // Read the table directory. 160 static const size_t kTableEntrySize = 16; 161 const size_t directory_size = num_tables * kTableEntrySize; 162 scoped_ptr<uint8_t[]> table_entries(new uint8_t[directory_size]); 163 n = HANDLE_EINTR(pread(fd, table_entries.get(), directory_size, 164 12 /* skip the SFNT header */)); 165 if (n != base::checked_cast<ssize_t>(directory_size)) 166 return false; 167 168 for (uint16_t i = 0; i < num_tables; ++i) { 169 uint8_t* entry = table_entries.get() + i * kTableEntrySize; 170 uint32_t tag = *reinterpret_cast<uint32_t*>(entry); 171 if (tag == table_tag) { 172 // Font data is stored in net (big-endian) order. 173 data_offset = 174 base::NetToHost32(*reinterpret_cast<uint32_t*>(entry + 8)); 175 data_length = 176 base::NetToHost32(*reinterpret_cast<uint32_t*>(entry + 12)); 177 break; 178 } 179 } 180 } 181 182 if (!data_length) 183 return false; 184 // Clamp |offset| inside the allowable range. This allows the read to succeed 185 // but return 0 bytes. 186 offset = std::min(offset, base::checked_cast<off_t>(data_length)); 187 // Make sure it's safe to add the data offset and the caller's logical offset. 188 // Define the maximum positive offset on 32 bit systems. 189 static const off_t kMaxPositiveOffset32 = 0x7FFFFFFF; // 2 GB - 1. 190 if ((offset > kMaxPositiveOffset32 / 2) || 191 (data_offset > kMaxPositiveOffset32 / 2)) 192 return false; 193 data_offset += offset; 194 data_length -= offset; 195 196 if (output) { 197 // 'output_length' holds the maximum amount of data the caller can accept. 198 data_length = std::min(data_length, *output_length); 199 ssize_t n = HANDLE_EINTR(pread(fd, output, data_length, data_offset)); 200 if (n != base::checked_cast<ssize_t>(data_length)) 201 return false; 202 } 203 *output_length = data_length; 204 205 return true; 206} 207 208bool SendZygoteChildPing(int fd) { 209 return UnixDomainSocket::SendMsg(fd, 210 kZygoteChildPingMessage, 211 sizeof(kZygoteChildPingMessage), 212 std::vector<int>()); 213} 214 215} // namespace content 216