Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: sw=4 ts=4 et :
3 : * This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #include "GMPLoader.h"
8 : #include <stdio.h>
9 : #include "mozilla/Attributes.h"
10 : #include "gmp-entrypoints.h"
11 : #include "prlink.h"
12 : #include "prenv.h"
13 : #if defined(XP_WIN) && defined(MOZ_SANDBOX)
14 : #include "mozilla/sandboxTarget.h"
15 : #include "mozilla/sandboxing/SandboxInitialization.h"
16 : #include "mozilla/sandboxing/sandboxLogging.h"
17 : #endif
18 : #if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
19 : #include "mozilla/Sandbox.h"
20 : #include "mozilla/SandboxInfo.h"
21 : #endif
22 :
23 : #include <string>
24 :
25 : #ifdef XP_WIN
26 : #include "windows.h"
27 : #endif
28 :
29 : namespace mozilla {
30 : namespace gmp {
31 0 : class PassThroughGMPAdapter : public GMPAdapter {
32 : public:
33 0 : ~PassThroughGMPAdapter() override {
34 : // Ensure we're always shutdown, even if caller forgets to call GMPShutdown().
35 0 : GMPShutdown();
36 0 : }
37 :
38 0 : void SetAdaptee(PRLibrary* aLib) override
39 : {
40 0 : mLib = aLib;
41 0 : }
42 :
43 0 : GMPErr GMPInit(const GMPPlatformAPI* aPlatformAPI) override
44 : {
45 0 : if (!mLib) {
46 0 : return GMPGenericErr;
47 : }
48 0 : GMPInitFunc initFunc = reinterpret_cast<GMPInitFunc>(PR_FindFunctionSymbol(mLib, "GMPInit"));
49 0 : if (!initFunc) {
50 0 : return GMPNotImplementedErr;
51 : }
52 0 : return initFunc(aPlatformAPI);
53 : }
54 :
55 0 : GMPErr GMPGetAPI(const char* aAPIName,
56 : void* aHostAPI,
57 : void** aPluginAPI,
58 : uint32_t aDecryptorId) override
59 : {
60 0 : if (!mLib) {
61 0 : return GMPGenericErr;
62 : }
63 0 : GMPGetAPIFunc getapiFunc = reinterpret_cast<GMPGetAPIFunc>(PR_FindFunctionSymbol(mLib, "GMPGetAPI"));
64 0 : if (!getapiFunc) {
65 0 : return GMPNotImplementedErr;
66 : }
67 0 : return getapiFunc(aAPIName, aHostAPI, aPluginAPI);
68 : }
69 :
70 0 : void GMPShutdown() override
71 : {
72 0 : if (mLib) {
73 0 : GMPShutdownFunc shutdownFunc = reinterpret_cast<GMPShutdownFunc>(PR_FindFunctionSymbol(mLib, "GMPShutdown"));
74 0 : if (shutdownFunc) {
75 0 : shutdownFunc();
76 : }
77 0 : PR_UnloadLibrary(mLib);
78 0 : mLib = nullptr;
79 : }
80 0 : }
81 :
82 : private:
83 : PRLibrary* mLib = nullptr;
84 : };
85 :
86 : bool
87 0 : GMPLoader::Load(const char* aUTF8LibPath,
88 : uint32_t aUTF8LibPathLen,
89 : const GMPPlatformAPI* aPlatformAPI,
90 : GMPAdapter* aAdapter)
91 : {
92 0 : if (mSandboxStarter && !mSandboxStarter->Start(aUTF8LibPath)) {
93 0 : return false;
94 : }
95 :
96 : // Load the GMP.
97 : PRLibSpec libSpec;
98 : #ifdef XP_WIN
99 : int pathLen = MultiByteToWideChar(CP_UTF8, 0, aUTF8LibPath, -1, nullptr, 0);
100 : if (pathLen == 0) {
101 : return false;
102 : }
103 :
104 : auto widePath = MakeUnique<wchar_t[]>(pathLen);
105 : if (MultiByteToWideChar(CP_UTF8, 0, aUTF8LibPath, -1, widePath.get(), pathLen) == 0) {
106 : return false;
107 : }
108 :
109 : libSpec.value.pathname_u = widePath.get();
110 : libSpec.type = PR_LibSpec_PathnameU;
111 : #else
112 0 : libSpec.value.pathname = aUTF8LibPath;
113 0 : libSpec.type = PR_LibSpec_Pathname;
114 : #endif
115 0 : PRLibrary* lib = PR_LoadLibraryWithFlags(libSpec, 0);
116 0 : if (!lib) {
117 0 : return false;
118 : }
119 :
120 0 : mAdapter.reset((!aAdapter) ? new PassThroughGMPAdapter() : aAdapter);
121 0 : mAdapter->SetAdaptee(lib);
122 :
123 0 : if (mAdapter->GMPInit(aPlatformAPI) != GMPNoErr) {
124 0 : return false;
125 : }
126 :
127 0 : return true;
128 : }
129 :
130 : GMPErr
131 0 : GMPLoader::GetAPI(const char* aAPIName,
132 : void* aHostAPI,
133 : void** aPluginAPI,
134 : uint32_t aDecryptorId)
135 : {
136 0 : return mAdapter->GMPGetAPI(aAPIName, aHostAPI, aPluginAPI, aDecryptorId);
137 : }
138 :
139 : void
140 0 : GMPLoader::Shutdown()
141 : {
142 0 : if (mAdapter) {
143 0 : mAdapter->GMPShutdown();
144 : }
145 0 : }
146 :
147 : #if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
148 : void
149 : GMPLoader::SetSandboxInfo(MacSandboxInfo* aSandboxInfo)
150 : {
151 : if (mSandboxStarter) {
152 : mSandboxStarter->SetSandboxInfo(aSandboxInfo);
153 : }
154 : }
155 : #endif
156 :
157 : #if defined(XP_WIN) && defined(MOZ_SANDBOX)
158 : class WinSandboxStarter : public mozilla::gmp::SandboxStarter
159 : {
160 : public:
161 : bool Start(const char *aLibPath) override
162 : {
163 : // Cause advapi32 to load before the sandbox is turned on, as
164 : // Widevine version 970 and later require it and the sandbox
165 : // blocks it on Win7.
166 : unsigned int dummy_rand;
167 : rand_s(&dummy_rand);
168 :
169 : mozilla::SandboxTarget::Instance()->StartSandbox();
170 : return true;
171 : }
172 : };
173 : #endif
174 :
175 : #if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
176 : class MacSandboxStarter : public mozilla::gmp::SandboxStarter
177 : {
178 : public:
179 : bool Start(const char *aLibPath) override
180 : {
181 : std::string err;
182 : bool rv = mozilla::StartMacSandbox(mInfo, err);
183 : if (!rv) {
184 : fprintf(stderr, "sandbox_init() failed! Error \"%s\"\n", err.c_str());
185 : }
186 : return rv;
187 : }
188 : void SetSandboxInfo(MacSandboxInfo* aSandboxInfo) override
189 : {
190 : mInfo = *aSandboxInfo;
191 : }
192 : private:
193 : MacSandboxInfo mInfo;
194 : };
195 : #endif
196 :
197 : #if defined (XP_LINUX) && defined(MOZ_GMP_SANDBOX)
198 : namespace {
199 : class LinuxSandboxStarter : public mozilla::gmp::SandboxStarter
200 : {
201 : private:
202 : LinuxSandboxStarter() { }
203 : friend mozilla::detail::UniqueSelector<LinuxSandboxStarter>::SingleObject mozilla::MakeUnique<LinuxSandboxStarter>();
204 :
205 : public:
206 : static UniquePtr<SandboxStarter> Make()
207 : {
208 : if (mozilla::SandboxInfo::Get().CanSandboxMedia()) {
209 : return MakeUnique<LinuxSandboxStarter>();
210 : }
211 : // Sandboxing isn't possible, but the parent has already
212 : // checked that this plugin doesn't require it. (Bug 1074561)
213 : return nullptr;
214 : }
215 : bool Start(const char *aLibPath) override
216 : {
217 : mozilla::SetMediaPluginSandbox(aLibPath);
218 : return true;
219 : }
220 : };
221 : } // anonymous namespace
222 : #endif // XP_LINUX && MOZ_GMP_SANDBOX
223 :
224 : static UniquePtr<SandboxStarter>
225 0 : MakeSandboxStarter()
226 : {
227 : #if defined(XP_WIN) && defined(MOZ_SANDBOX)
228 : return mozilla::MakeUnique<WinSandboxStarter>();
229 : #elif defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
230 : return mozilla::MakeUnique<MacSandboxStarter>();
231 : #elif defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
232 : return LinuxSandboxStarter::Make();
233 : #else
234 0 : return nullptr;
235 : #endif
236 : }
237 :
238 0 : GMPLoader::GMPLoader()
239 0 : : mSandboxStarter(MakeSandboxStarter())
240 : {
241 0 : }
242 :
243 : bool
244 0 : GMPLoader::CanSandbox() const
245 : {
246 0 : return !!mSandboxStarter;
247 : }
248 :
249 : } // namespace gmp
250 : } // namespace mozilla
|