mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 976398 - Check camera permissions directly instead of using Unix groups. r=mwu r=bent
Loosely based on the code used to check PRemoteOpenFile.
This commit is contained in:
parent
5c75b92a92
commit
b756489606
@ -587,34 +587,6 @@ ContentParent::GetNewOrUsed(bool aForBrowserElement)
|
|||||||
return p.forget();
|
return p.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
|
||||||
struct SpecialPermission {
|
|
||||||
const char* perm; // an app permission
|
|
||||||
ChildPrivileges privs; // the OS privilege it requires
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static ChildPrivileges
|
|
||||||
PrivilegesForApp(mozIApplication* aApp)
|
|
||||||
{
|
|
||||||
const SpecialPermission specialPermissions[] = {
|
|
||||||
// FIXME/bug 785592: implement a CameraBridge so we don't have
|
|
||||||
// to hack around with OS permissions
|
|
||||||
{ "camera", base::PRIVILEGES_CAMERA }
|
|
||||||
};
|
|
||||||
for (size_t i = 0; i < ArrayLength(specialPermissions); ++i) {
|
|
||||||
const char* const permission = specialPermissions[i].perm;
|
|
||||||
bool hasPermission = false;
|
|
||||||
if (NS_FAILED(aApp->HasPermission(permission, &hasPermission))) {
|
|
||||||
NS_WARNING("Unable to check permissions. Breakage may follow.");
|
|
||||||
break;
|
|
||||||
} else if (hasPermission) {
|
|
||||||
return specialPermissions[i].privs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return base::PRIVILEGES_DEFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*static*/ ProcessPriority
|
/*static*/ ProcessPriority
|
||||||
ContentParent::GetInitialProcessPriority(Element* aFrameElement)
|
ContentParent::GetInitialProcessPriority(Element* aFrameElement)
|
||||||
{
|
{
|
||||||
@ -733,7 +705,7 @@ ContentParent::CreateBrowserOrApp(const TabContext& aContext,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!p) {
|
if (!p) {
|
||||||
ChildPrivileges privs = PrivilegesForApp(ownApp);
|
ChildPrivileges privs = base::PRIVILEGES_DEFAULT;
|
||||||
p = MaybeTakePreallocatedAppProcess(manifestURL, privs,
|
p = MaybeTakePreallocatedAppProcess(manifestURL, privs,
|
||||||
initialPriority);
|
initialPriority);
|
||||||
if (!p) {
|
if (!p) {
|
||||||
|
@ -129,7 +129,6 @@ void CloseSuperfluousFds(const base::InjectiveMultimap& saved_map);
|
|||||||
enum ChildPrivileges {
|
enum ChildPrivileges {
|
||||||
PRIVILEGES_DEFAULT,
|
PRIVILEGES_DEFAULT,
|
||||||
PRIVILEGES_UNPRIVILEGED,
|
PRIVILEGES_UNPRIVILEGED,
|
||||||
PRIVILEGES_CAMERA,
|
|
||||||
PRIVILEGES_INHERIT,
|
PRIVILEGES_INHERIT,
|
||||||
PRIVILEGES_LAST
|
PRIVILEGES_LAST
|
||||||
};
|
};
|
||||||
|
@ -302,17 +302,6 @@ void SetCurrentProcessPrivileges(ChildPrivileges privs) {
|
|||||||
gid += getpid();
|
gid += getpid();
|
||||||
uid += getpid();
|
uid += getpid();
|
||||||
}
|
}
|
||||||
if (privs == PRIVILEGES_CAMERA) {
|
|
||||||
#if ANDROID_VERSION < 17
|
|
||||||
gid_t groups[] = { AID_SDCARD_RW };
|
|
||||||
#else
|
|
||||||
gid_t groups[] = { AID_SDCARD_R, AID_SDCARD_RW, AID_MEDIA_RW };
|
|
||||||
#endif
|
|
||||||
if (setgroups(sizeof(groups) / sizeof(groups[0]), groups) != 0) {
|
|
||||||
DLOG(ERROR) << "FAILED TO setgroups() CHILD PROCESS";
|
|
||||||
_exit(127);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
if (setgid(gid) != 0) {
|
if (setgid(gid) != 0) {
|
||||||
DLOG(ERROR) << "FAILED TO setgid() CHILD PROCESS";
|
DLOG(ERROR) << "FAILED TO setgid() CHILD PROCESS";
|
||||||
|
@ -21,6 +21,13 @@
|
|||||||
#include <private/android_filesystem_config.h>
|
#include <private/android_filesystem_config.h>
|
||||||
#include "GonkPermission.h"
|
#include "GonkPermission.h"
|
||||||
|
|
||||||
|
#include "mozilla/dom/ContentParent.h"
|
||||||
|
#include "mozilla/dom/TabParent.h"
|
||||||
|
#include "mozilla/SyncRunnable.h"
|
||||||
|
#include "nsIAppsService.h"
|
||||||
|
#include "mozIApplication.h"
|
||||||
|
#include "nsThreadUtils.h"
|
||||||
|
|
||||||
#undef LOG
|
#undef LOG
|
||||||
#include <android/log.h>
|
#include <android/log.h>
|
||||||
#define ALOGE(args...) __android_log_print(ANDROID_LOG_ERROR, "gonkperm" , ## args)
|
#define ALOGE(args...) __android_log_print(ANDROID_LOG_ERROR, "gonkperm" , ## args)
|
||||||
@ -28,31 +35,104 @@
|
|||||||
using namespace android;
|
using namespace android;
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
|
|
||||||
|
// Checking permissions needs to happen on the main thread, but the
|
||||||
|
// binder callback is called on a special binder thread, so we use
|
||||||
|
// this runnable for that.
|
||||||
|
class GonkPermissionChecker : public nsRunnable {
|
||||||
|
int32_t mPid;
|
||||||
|
bool mCanUseCamera;
|
||||||
|
|
||||||
|
explicit GonkPermissionChecker(int32_t pid)
|
||||||
|
: mPid(pid)
|
||||||
|
, mCanUseCamera(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
static already_AddRefed<GonkPermissionChecker> Inspect(int32_t pid)
|
||||||
|
{
|
||||||
|
nsRefPtr<GonkPermissionChecker> that = new GonkPermissionChecker(pid);
|
||||||
|
nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
|
||||||
|
MOZ_ASSERT(mainThread);
|
||||||
|
SyncRunnable::DispatchToThread(mainThread, that);
|
||||||
|
return that.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CanUseCamera()
|
||||||
|
{
|
||||||
|
return mCanUseCamera;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHOD Run();
|
||||||
|
};
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
GonkPermissionChecker::Run()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
// Find our ContentParent.
|
||||||
|
dom::ContentParent *contentParent = nullptr;
|
||||||
|
{
|
||||||
|
nsTArray<dom::ContentParent*> parents;
|
||||||
|
dom::ContentParent::GetAll(parents);
|
||||||
|
for (uint32_t i = 0; i < parents.Length(); ++i) {
|
||||||
|
if (parents[i]->Pid() == mPid) {
|
||||||
|
contentParent = parents[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!contentParent) {
|
||||||
|
ALOGE("pid=%d denied: can't find ContentParent", mPid);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now iterate its apps...
|
||||||
|
for (uint32_t i = 0; i < contentParent->ManagedPBrowserParent().Length(); i++) {
|
||||||
|
dom::TabParent *tabParent =
|
||||||
|
static_cast<dom::TabParent*>(contentParent->ManagedPBrowserParent()[i]);
|
||||||
|
nsCOMPtr<mozIApplication> mozApp = tabParent->GetOwnOrContainingApp();
|
||||||
|
if (!mozApp) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...and check if any of them has camera access.
|
||||||
|
bool appCanUseCamera;
|
||||||
|
nsresult rv = mozApp->HasPermission("camera", &appCanUseCamera);
|
||||||
|
if (NS_SUCCEEDED(rv) && appCanUseCamera) {
|
||||||
|
mCanUseCamera = true;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
GonkPermissionService::checkPermission(const String16& permission, int32_t pid,
|
GonkPermissionService::checkPermission(const String16& permission, int32_t pid,
|
||||||
int32_t uid)
|
int32_t uid)
|
||||||
{
|
{
|
||||||
if (0 == uid)
|
// root can do anything.
|
||||||
|
if (0 == uid) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
String8 perm8(permission);
|
String8 perm8(permission);
|
||||||
|
|
||||||
|
|
||||||
// Some ril implementations need android.permission.MODIFY_AUDIO_SETTINGS
|
// Some ril implementations need android.permission.MODIFY_AUDIO_SETTINGS
|
||||||
if (uid == AID_RADIO &&
|
if (uid == AID_RADIO &&
|
||||||
perm8 == "android.permission.MODIFY_AUDIO_SETTINGS")
|
perm8 == "android.permission.MODIFY_AUDIO_SETTINGS") {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Camera/audio record permissions are only for apps with the
|
// No other permissions apply to non-app processes.
|
||||||
// "camera" permission. These apps are also the only apps granted
|
|
||||||
// the AID_SDCARD_RW supplemental group (bug 785592)
|
|
||||||
|
|
||||||
if (uid < AID_APP) {
|
if (uid < AID_APP) {
|
||||||
ALOGE("%s for pid=%d,uid=%d denied: not an app",
|
ALOGE("%s for pid=%d,uid=%d denied: not an app",
|
||||||
String8(permission).string(), pid, uid);
|
String8(permission).string(), pid, uid);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only these permissions can be granted to apps through this service.
|
||||||
if (perm8 != "android.permission.CAMERA" &&
|
if (perm8 != "android.permission.CAMERA" &&
|
||||||
perm8 != "android.permission.RECORD_AUDIO") {
|
perm8 != "android.permission.RECORD_AUDIO") {
|
||||||
ALOGE("%s for pid=%d,uid=%d denied: unsupported permission",
|
ALOGE("%s for pid=%d,uid=%d denied: unsupported permission",
|
||||||
@ -69,40 +149,16 @@ GonkPermissionService::checkPermission(const String16& permission, int32_t pid,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
char filename[32];
|
// Camera/audio record permissions are allowed for apps with the
|
||||||
snprintf(filename, sizeof(filename), "/proc/%d/status", pid);
|
// "camera" permission.
|
||||||
FILE *f = fopen(filename, "r");
|
nsRefPtr<GonkPermissionChecker> checker =
|
||||||
if (!f) {
|
GonkPermissionChecker::Inspect(pid);
|
||||||
ALOGE("%s for pid=%d,uid=%d denied: unable to open %s",
|
bool canUseCamera = checker->CanUseCamera();
|
||||||
String8(permission).string(), pid, uid, filename);
|
if (!canUseCamera) {
|
||||||
return false;
|
ALOGE("%s for pid=%d,uid=%d denied: not granted by user or app manifest",
|
||||||
|
String8(permission).string(), pid, uid);
|
||||||
}
|
}
|
||||||
|
return canUseCamera;
|
||||||
char line[80];
|
|
||||||
while (fgets(line, sizeof(line), f)) {
|
|
||||||
char *save;
|
|
||||||
char *name = strtok_r(line, "\t", &save);
|
|
||||||
if (!name)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (strcmp(name, "Groups:"))
|
|
||||||
continue;
|
|
||||||
char *group;
|
|
||||||
while ((group = strtok_r(NULL, " \n", &save))) {
|
|
||||||
#define _STR(x) #x
|
|
||||||
#define STR(x) _STR(x)
|
|
||||||
if (!strcmp(group, STR(AID_SDCARD_RW))) {
|
|
||||||
fclose(f);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
fclose(f);
|
|
||||||
|
|
||||||
ALOGE("%s for pid=%d,uid=%d denied: missing group",
|
|
||||||
String8(permission).string(), pid, uid);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static GonkPermissionService* gGonkPermissionService = NULL;
|
static GonkPermissionService* gGonkPermissionService = NULL;
|
||||||
|
Loading…
Reference in New Issue
Block a user