Skip to content
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

Mac: Fixes for MacOS 13 and Xcode 14 #5002

Merged
merged 6 commits into from
Nov 8, 2022
Merged
Show file tree
Hide file tree
Changes from all 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: 2 additions & 2 deletions client/check_security.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -433,10 +433,10 @@ int use_sandbox, int isManager, char* path_to_error, int len
if (sbuf.st_gid != boinc_project_gid)
return -1042;

if (sbuf.st_uid != boinc_master_uid)
if (sbuf.st_uid != 0) // root
return -1043;

if ((sbuf.st_mode & 07777) != 02500)
if ((sbuf.st_mode & 07777) != 04050)
return -1044;

#ifdef __APPLE__
Expand Down
33 changes: 27 additions & 6 deletions client/gui_rpc_server_ops.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1378,11 +1378,21 @@ static void stop_graphics_app(pid_t thePID,
argv[3] = (char *)pidString;
argc = 4;
#endif
if (!theScreensaverLoginUser.empty()) {
argv[argc++] = "--ScreensaverLoginUser";
safe_strcpy(screensaverLoginUser, theScreensaverLoginUser.c_str());
argv[argc++] = screensaverLoginUser;
// Graphics apps run by Manager write files in slot directory
// as logged in user, not boinc_master. This ugly hack uses
// setprojectgrp to fix all ownerships in this slot directory.
// To fix all ownerships in the slot directory, invoke the
// run_graphics_app RPC with operation "stop", slot number
// for the operand and empty string for screensaverLoginUser
// after the graphics app stops.
if (theScreensaverLoginUser.empty()) {
fix_slot_owners(thePID); // Manager passes slot # instead of PID
return;
}

argv[argc++] = "--ScreensaverLoginUser";
safe_strcpy(screensaverLoginUser, theScreensaverLoginUser.c_str());
argv[argc++] = screensaverLoginUser;
argv[argc] = 0;

retval = run_program(
Expand All @@ -1391,6 +1401,7 @@ static void stop_graphics_app(pid_t thePID,
);
} else {
retval = kill_program(thePID);

}
if (retval) {
grc.mfout.printf("<error>attempt to kill graphics app failed</error>\n");
Expand Down Expand Up @@ -1448,7 +1459,17 @@ static void handle_run_graphics_app(GUI_RPC_CONN& grc) {
if (grc.xp.parse_string("ScreensaverLoginUser", theScreensaverLoginUser)) continue;
}

if (stop || test) {
if (stop) {
if (theScreensaverLoginUser.empty() ){
if (thePID < 0) {
grc.mfout.printf("<error>missing or invalid slot number</error>\n");
}
} else {
if (thePID < 1) {
grc.mfout.printf("<error>missing or invalid process id</error>\n");
}
}
} else if (test) {
if (thePID < 1) {
grc.mfout.printf("<error>missing or invalid process id</error>\n");
return;
Expand Down Expand Up @@ -1864,7 +1885,7 @@ GUI_RPC gui_rpcs[] = {
GUI_RPC("project_reset", handle_project_reset, true, true, false),
GUI_RPC("project_update", handle_project_update, true, true, false),
GUI_RPC("retry_file_transfer", handle_retry_file_transfer, true, true, false),
GUI_RPC("run_graphics_app", handle_run_graphics_app, true, true, false),
GUI_RPC("run_graphics_app", handle_run_graphics_app, false, false, false),
};

// return nonzero only if we need to close the connection
Expand Down
22 changes: 22 additions & 0 deletions client/sandbox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,28 @@ int get_project_gid() {
return 0;
}

// Graphics apps run by Manager write files in slot directory
// as logged in user, not boinc_master. This ugly hack uses
// setprojectgrp to fix all ownerships in this slot directory.
int fix_slot_owners(const int slot){
char path[MAXPATHLEN];
DIR* dirp;

snprintf(path, sizeof(path), "slots/%d", slot);
dirp = opendir(path);
if (!dirp) return ERR_READDIR;
while (1) {
dirent* dp = readdir(dirp);
if (!dp) break;
if (dp->d_name[0] == '.') continue;
snprintf(path, sizeof(path), "\"/Library/Application Support/BOINC Data/slots/%d/%s\"", slot, dp->d_name);
set_to_project_group(path);
}
closedir(dirp);

return 0;
}

int set_to_project_group(const char* path) {
if (g_use_sandbox) {
if (switcher_exec(SETPROJECTGRP_FILE_NAME, path)) {
Expand Down
1 change: 1 addition & 0 deletions client/sandbox.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

extern int kill_via_switcher(int pid);
extern int get_project_gid();
extern int fix_slot_owners(const int slot);
extern int set_to_project_group(const char* path);
extern int switcher_exec(const char* util_filename, const char* cmdline);
extern int client_clean_out_dir(
Expand Down
95 changes: 86 additions & 9 deletions client/setprojectgrp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,28 +19,54 @@
//
// When run as
// setprojectgrp Path
// sets group of file at Path to boinc_project
// sets file at Path to user boinc_master and group boinc_project
//
// setprojectgrp runs setuid boinc_master and setgid boinc_project

#include <unistd.h>
#include <grp.h>
#include <pwd.h> // getpwuid
#include <cstdio>
#include <cerrno>
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif

#define VERBOSE 0

#if VERBOSE
#include <cstring>
#include <time.h>
#include <stdlib.h>
#include <stdarg.h>

#ifdef __cplusplus
extern "C" {
#endif
static void print_to_log_file(const char *format, ...);
#ifdef __cplusplus
}
static void strip_cr(char *buf);
#endif
#endif

int main(int argc, char** argv) {
gid_t project_gid;
passwd *pw;
group *grp;
uid_t master_uid = 0;
gid_t project_gid = 0;
int retval = 0;
struct stat sbuf;

project_gid = getegid();

#if 0 // For debugging
fprintf(stderr, "setprojectgrp argc=%d, arg[1]= %s, boinc_project gid = %d\n", argc, argv[1], project_gid);
fflush(stderr);
pw = getpwnam("boinc_master");
if (pw) master_uid = pw->pw_uid;

grp = getgrnam("boinc_project");
if (grp) project_gid = grp->gr_gid;

#if VERBOSE
print_to_log_file("setprojectgrp: current uid=%d, current euid=%d, current gid=%d, current egid=%d\n", getuid(), geteuid(), getgid(), getegid());
print_to_log_file("setprojectgrp: argc=%d, arg[1]= %s, boinc_project gid = %d\n", argc, argv[1], project_gid);
#endif

// chown() doesn't change ownership of symbolic links; it follows the link and
Expand All @@ -54,10 +80,61 @@ int main(int argc, char** argv) {
//
if (lstat(argv[1], &sbuf) == 0) {
if (!S_ISLNK(sbuf.st_mode)) {
retval = chown(argv[1], (uid_t)-1, project_gid);
retval = chown(argv[1], master_uid, project_gid);
// retval = chown(argv[1], -1, project_gid);
#if VERBOSE
if (retval)
fprintf(stderr, "chown(%s, -1, %d) failed: errno=%d\n", argv[1], project_gid, errno);
print_to_log_file("setprojectgrp: chown(%s, %d, %d) failed: errno=%d %s\n", argv[1], master_uid, project_gid, errno, strerror(errno));
else
print_to_log_file("setprojectgrp: chown(%s, %d, %d) succeeded: errno=%d\n", argv[1], master_uid, project_gid, errno);
#endif
}
}
return retval;
}


#if VERBOSE

static void print_to_log_file(const char *format, ...) {
FILE *f;
va_list args;
char buf[256];
time_t t;

f = fopen("/Users/Shared/test_log_gfx_switcher.txt", "a");
if (!f) return;

// freopen(buf, "a", stdout);
// freopen(buf, "a", stderr);

time(&t);
strlcpy(buf, asctime(localtime(&t)), sizeof(buf));
strip_cr(buf);

fputs(buf, f);
fputs(" ", f);

va_start(args, format);
vfprintf(f, format, args);
va_end(args);

fputs("\n", f);
fflush(f);
fclose(f);
chmod("/Users/Shared/test_log_gfx_switcher.txt", 0666);
}

static void strip_cr(char *buf)
{
char *theCR;

theCR = strrchr(buf, '\n');
if (theCR)
*theCR = '\0';
theCR = strrchr(buf, '\r');
if (theCR)
*theCR = '\0';
}
#endif

83 changes: 75 additions & 8 deletions client/switcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,24 @@
#include "mac_spawn.h"
#endif

#define VERBOSE 0

#if VERBOSE
#include <cstring>
#include <time.h>
#include <stdlib.h>
#include <stdarg.h>

#ifdef __cplusplus
extern "C" {
#endif
static void print_to_log_file(const char *format, ...);
#ifdef __cplusplus
}
static void strip_cr(char *buf);
#endif
#endif

using std::strcpy;

int main(int /*argc*/, char** argv) {
Expand All @@ -62,21 +80,21 @@ int main(int /*argc*/, char** argv) {
strcpy(boinc_project_group_name, "boinc_project");
strcpy(boinc_master_user_name, "boinc_master");

#if 0 // For debugging only
fprintf(stderr, "\n\nEntered switcher with euid %d, egid %d, uid %d and gid %d\n", geteuid(), getegid(), getuid(), getgid());
#if VERBOSE // For debugging only
print_to_log_file("\n\nEntered switcher with euid %d, egid %d, uid %d and gid %d\n", geteuid(), getegid(), getuid(), getgid());
getcwd( current_dir, sizeof(current_dir));
fprintf(stderr, "current directory = %s\n", current_dir);
print_to_log_file("current directory = %s\n", current_dir);
fflush(stderr);

i = 0;
while(argv[i]) {
fprintf(stderr, "switcher arg %d: %s\n", i, argv[i]);
print_to_log_file("switcher arg %d: %s\n", i, argv[i]);
fflush(stderr);
++i;
}
#endif

#if 0 // For debugging only
#if VERBOSE // For debugging only
// Allow debugging without running as user or group boinc_project
pw = getpwuid(getuid());
if (pw) {
Expand All @@ -85,7 +103,7 @@ int main(int /*argc*/, char** argv) {
}
grp = getgrgid(getgid());
if (grp) {
strcpy(boinc_project_group_name, grp->gr_gid);
strcpy(boinc_project_group_name, grp->gr_name);
}

#endif
Expand Down Expand Up @@ -226,8 +244,8 @@ int main(int /*argc*/, char** argv) {
}
}
safe_strcat(cmd, "\'");
#if 0 // For debugging only
fprintf(stderr, "About to call Posix Spawn (%s)\n", cmd);
#if VERBOSE // For debugging only
print_to_log_file("About to call Posix Spawn (%s)\n", cmd);
fflush(stderr);
#endif
if (launching_gfx) {
Expand All @@ -243,7 +261,56 @@ int main(int /*argc*/, char** argv) {
if (retval == -1) {
// If we got here execv failed
fprintf(stderr, "Process creation (%s) failed: %s (errno = %d)\n", argv[1], strerror(errno), retval);
#if VERBOSE
print_to_log_file("Process creation (%s) failed: %s (errno = %d)\n", argv[1], strerror(errno), retval);
#endif
}

return retval;
}


#if VERBOSE

static void print_to_log_file(const char *format, ...) {
FILE *f;
va_list args;
char buf[256];
time_t t;

f = fopen("/Users/Shared/test_log_gfx_switcher.txt", "a");
if (!f) return;

// freopen(buf, "a", stdout);
// freopen(buf, "a", stderr);

time(&t);
strlcpy(buf, asctime(localtime(&t)), sizeof(buf));
strip_cr(buf);

fputs(buf, f);
fputs(" ", f);

va_start(args, format);
vfprintf(f, format, args);
va_end(args);

fputs("\n", f);
fflush(f);
fclose(f);
chmod("/Users/Shared/test_log_gfx_switcher.txt", 0666);
}

static void strip_cr(char *buf)
{
char *theCR;

theCR = strrchr(buf, '\n');
if (theCR)
*theCR = '\0';
theCR = strrchr(buf, '\r');
if (theCR)
*theCR = '\0';
}
#endif

Loading