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