Skip to content

[macOS sandbox mode] Application group name mangling for semaphores #1167

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 19 commits into from
Dec 21, 2022
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion app/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ set(app_android_SRCS
src/uuid.cc)
set(app_ios_SRCS
src/app_ios.mm
src/util_apple.mm
src/util_ios.mm
src/invites/ios/invites_receiver_internal_ios.mm
src/invites/ios/invites_ios_startup.mm
Expand Down Expand Up @@ -220,7 +221,8 @@ else()
src/secure/user_secure_darwin_internal.mm
src/filesystem_apple.mm
src/locale_apple.mm
src/uuid_ios_darwin.mm)
src/uuid_ios_darwin.mm
src/util_apple.mm)
else()
# Linux requires libsecret.
pkg_check_modules(LIBSECRET libsecret-1)
Expand Down
34 changes: 26 additions & 8 deletions app/src/semaphore.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#if FIREBASE_PLATFORM_OSX || FIREBASE_PLATFORM_IOS || FIREBASE_PLATFORM_TVOS
#include "app/src/include/firebase/internal/mutex.h"
#include "app/src/pthread_condvar.h"
#include "app/src/util_apple.h"
#endif // FIREBASE_PLATFORM_OSX || FIREBASE_PLATFORM_IOS ||
// FIREBASE_PLATFORM_TVOS

Expand All @@ -50,44 +51,61 @@ class Semaphore {
#if FIREBASE_PLATFORM_OSX || FIREBASE_PLATFORM_IOS || FIREBASE_PLATFORM_TVOS
// MacOS requires named semaphores, and does not support unnamed.
// Generate a unique string for the semaphore name:
static const char kPrefix[] = "/firebase-";
// String length of the name prefix.
static const int kPprefixLen = sizeof(kPrefix);

// String length of the pointer, when printed to a string.
static const int kPointerStringLength = 16;
// Buffer size. the +1 is for the null terminator.
static const int kBufferSize = kPprefixLen + kPointerStringLength + 1;
static const int kBufferSize = kPointerStringLength + 1;

char buffer[kBufferSize];
snprintf(buffer, kBufferSize, "%s%016llx", kPrefix,
snprintf(buffer, kBufferSize, "%016llx",
static_cast<unsigned long long>( // NOLINT
reinterpret_cast<intptr_t>(this)));

semaphore_ = sem_open(buffer,
#if FIREBASE_PLATFORM_OSX
// Sandbox mode is currently only available for macOS.
std::string semaphore_name = util::GetSandboxModeSemaphorePrefix();
if (semaphore_name.empty()) {
semaphore_name = "/firebase-";
}
#else
std::string semaphore_name = "/firebase-";
#endif // FIREBASE_PLATFORM_OSX

semaphore_name.append(buffer);
printf("semaphore name: %s\n", semaphore_name.c_str());

semaphore_ = sem_open(semaphore_name.c_str(),
O_CREAT | O_EXCL, // Create if it doesn't exist.
S_IRUSR | S_IWUSR, // Only the owner can read/write.
initial_count);
printf("Semaphore: %p\n", semaphore_);

assert(semaphore_ != SEM_FAILED);

// Remove the semaphore from the system registry, so other processes can't
// grab it. (These are designed to just be passed around internally by
// pointer, like unnamed semaphores. Mac OSX targets don't support unnamed
// semaphores though, so we have to use named, and just treat them like
// unnamed.
bool success = (sem_unlink(buffer) == 0);
bool success = (sem_unlink(semaphore_name.c_str()) == 0);
assert(success);
(void)success;

#elif !FIREBASE_PLATFORM_WINDOWS
// Android requires unnamed semaphores, and does not support sem_open
semaphore_ = &semaphore_value_;
bool success = sem_init(semaphore_, 0, initial_count) == 0;
assert(success);
(void)success;
assert(semaphore_ != nullptr);
#else
semaphore_ = CreateSemaphore(nullptr, // default security attributes
initial_count, // initial count
LONG_MAX, // maximum count
nullptr); // unnamed semaphore
#endif
assert(semaphore_ != nullptr);
#endif
}

~Semaphore() {
Expand Down
33 changes: 33 additions & 0 deletions app/src/util_apple.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef FIREBASE_APP_SRC_UTIL_APPLE_H_
#define FIREBASE_APP_SRC_UTIL_APPLE_H_

#include <string>

namespace firebase {
namespace util {

// Attempts to query the custom semaphore prefix from the application's
// Info.plist file. Returns an empty string if a custom semahpore prefix
// wasn't conifgured.
std::string GetSandboxModeSemaphorePrefix();

} // namespace util
} // namespace firebase

#endif // FIREBASE_APP_SRC_UTIL_APPLE_H_
39 changes: 39 additions & 0 deletions app/src/util_apple.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "app/src/util_apple.h"

#import <Foundation/Foundation.h>

namespace firebase {
namespace util {

std::string GetSandboxModeSemaphorePrefix() {
NSBundle* mainBundle = [NSBundle mainBundle];
if (mainBundle != nil) {
NSDictionary<NSString*, id>* dictionary = [mainBundle infoDictionary];
if (dictionary != nil) {
NSString* customPrefix = [dictionary valueForKey:@"FBAppGroupEntitlementName"];
if (customPrefix != nil) {
return std::string(customPrefix.UTF8String).append("/");
}
}
}
return std::string();
}

} // namespace util
} // namespace firebase
9 changes: 9 additions & 0 deletions release_build_files/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,15 @@ workflow use only during the development of your app, not for publicly shipping
code.

## Release Notes
### Upcoming
- Changes
- General (macOS): In order to support sandbox mode, apps can define a
key/value pair for FBAppGroupEntitlementName in Info.plist. The value
associated with this key will be used to prefix semaphore names
created internally by the Firebase C++ SDK so that they conform with
[macOS sandbox
requirements](https://developer.apple.com/library/archive/documentation/Security/Conceptual/AppSandboxDesignGuide/AppSandboxInDepth/AppSandboxInDepth.html#//apple_ref/doc/uid/TP40011183-CH3-SW24).

### 10.2.0
- Changes
- General (Android): Update to Firebase Android BoM version 31.1.0.
Expand Down