- client/manager/API: code cleanup to disentangle sandbox code from lib/.

- move client sandbox-specific code to a new file, sandbox.C
    - remove g_use_sandbox from util.C; move to MainDocument.cpp (manager)
        and sandbox.C (client)
    - don't declare check_security() in util.h; it's not in util.C
    - don't call remove_project_owned_file_or_dir() in
        boinc_delete_file_aux() or boinc_rmdir();
        rather, at the points in the client that delete
        dirs that are usually owned by boinc_projects,
        call remove_project_owned_file_or_dir() first,
        then clean_out_dir().
    - rename boinc_exec() to switcher_exec() and move it to sandbox.C

Note: this change was sparked by needing to remove a call to getgrnam()
from boinclib, to avoid requiring the same version of glibc
on both compile and target hosts

svn path=/trunk/boinc/; revision=13784
This commit is contained in:
David Anderson 2007-10-05 16:47:07 +00:00
parent 28073fd644
commit d302a5e107
27 changed files with 247 additions and 150 deletions

View File

@ -9193,3 +9193,43 @@ Charlie 5 Oct 2007
mac_build/
boinc.xcodeproj/
project.pbxproj
David 5 Oct 2007
- client/manager/API: code cleanup to disentangle sandbox code from lib/.
- move client sandbox-specific code to a new file, sandbox.C
- remove g_use_sandbox from util.C; move to MainDocument.cpp (manager)
and sandbox.C (client)
- don't declare check_security() in util.h; it's not in util.C
- don't call remove_project_owned_file_or_dir() in
boinc_delete_file_aux() or boinc_rmdir();
rather, at the points in the client that delete
dirs that are usually owned by boinc_projects,
call remove_project_owned_file_or_dir() first,
then clean_out_dir().
- rename boinc_exec() to switcher_exec() and move it to sandbox.C
Note: this change was sparked by needing to remove a call to getgrnam()
from boinclib, to avoid requiring the same version of glibc
on both compile and target hosts
client/
Makefile.am
app.C
app_control.C
app_start.C
client_state.C,h
client_types.C
cs_cmdline.C
file_names.C,h
gui_rpc_server.C
main.C
sandbox.C,h (new)
clientgui/
MainDocument.cpp,h
lib/
boinc_cmd.C
common_defs.h
error_numbers.h
filesys.C,h
str_util.C
util.C,h

View File

@ -54,6 +54,7 @@ boinc_client_SOURCES = \
main.C \
net_stats.C \
pers_file_xfer.C \
sandbox.C \
scheduler_op.C \
time_stats.C \
whetstone.C \

View File

@ -409,6 +409,9 @@ int ACTIVE_TASK_SET::get_free_slot() {
get_slot_dir(j, path, sizeof(path));
if (boinc_file_exists(path)) {
if (is_dir(path)) {
#ifdef SANDBOX
remove_project_owned_file_or_dirs(path);
#endif
retval = clean_out_dir(path);
if (!retval) return j;
}

View File

@ -62,6 +62,7 @@ using std::vector;
#include "client_state.h"
#include "file_names.h"
#include "procinfo.h"
#include "sandbox.h"
#include "app.h"
@ -122,16 +123,9 @@ int ACTIVE_TASK::kill_task(bool restart) {
TerminateProcessById(pid);
#else
#ifdef SANDBOX
char cmd[1024];
if (g_use_sandbox) {
// if project application is running as user boinc_project and
// core client is running as user boinc_master, we cannot send
// a signal directly, so use switcher.
sprintf(cmd, "/bin/kill kill -s KILL %d", pid);
boinc_exec(SWITCHER_FILE_NAME, cmd);
}
// Always try to kill project app directly, just to be safe:
kill_via_switcher(pid);
// Also kill app directly, just to be safe
//
#endif
kill(pid, SIGKILL);
#endif
@ -336,6 +330,9 @@ void ACTIVE_TASK::handle_exited_app(int stat) {
if (!will_restart) {
copy_output_files();
read_stderr_file();
#ifdef SANDBOX
remove_project_owned_file_or_dirs(slot_dir);
#endif
clean_out_dir(slot_dir);
}
gstate.request_schedule_cpus("application exited");

View File

@ -66,6 +66,7 @@ using std::vector;
#include "client_msgs.h"
#include "client_state.h"
#include "file_names.h"
#include "sandbox.h"
#include "app.h"
@ -94,11 +95,10 @@ static int make_link(const char *existing, const char *new_link) {
if (!fp) return ERR_FOPEN;
fprintf(fp, "<soft_link>%s</soft_link>\n", existing);
fclose(fp);
if (g_use_sandbox) {
return set_to_project_group(new_link);
} else {
return 0;
}
#ifdef SANDBOX
return set_to_project_group(new_link);
#endif
return 0;
}
int ACTIVE_TASK::link_user_files() {
@ -593,7 +593,9 @@ int ACTIVE_TASK::start(bool first_time) {
int fd = open(buf, O_RDWR | O_CREAT, 0660);
if (fd >= 0) {
close (fd);
#ifdef SANDBOX
set_to_project_group(buf);
#endif
}
}
}

View File

@ -47,6 +47,7 @@
#include "http_curl.h"
#include "client_msgs.h"
#include "shmem.h"
#include "sandbox.h"
#include "client_state.h"
using std::max;
@ -350,17 +351,8 @@ int CLIENT_STATE::init() {
);
}
#if (defined(SANDBOX) && ! defined(_WIN32))
if (g_use_sandbox) {
#ifdef _DEBUG
boinc_project_gid = getegid();
#else
retval = lookup_group(BOINC_PROJECT_GROUP_NAME, boinc_project_gid);
if (retval) return retval;
#endif // _DEBUG
} else {
boinc_project_gid = 0;
}
#ifdef SANDBOX
get_project_gid();
#endif
check_file_existence();

View File

@ -471,10 +471,6 @@ public:
extern CLIENT_STATE gstate;
#ifdef SANDBOX
#define BOINC_PROJECT_GROUP_NAME "boinc_project"
#endif
// return a random double in the range [MIN,min(e^n,MAX))
//
extern double calculate_exponential_backoff(

View File

@ -39,6 +39,7 @@
#include "str_util.h"
#include "client_state.h"
#include "pers_file_xfer.h"
#include "sandbox.h"
#include "client_types.h"

View File

@ -32,6 +32,7 @@
#include "util.h"
#include "client_msgs.h"
#include "client_state.h"
#include "sandbox.h"
static void print_options(char* prog) {
printf(

View File

@ -40,6 +40,7 @@
#include "util.h"
#include "client_msgs.h"
#include "client_state.h"
#include "sandbox.h"
#include "file_names.h"
@ -140,6 +141,9 @@ int remove_project_dir(PROJECT& p) {
int retval;
get_project_dir(&p, buf, sizeof(buf));
#ifdef SANDBOX
remove_project_owned_file_or_dir(buf);
#endif
retval = clean_out_dir(buf);
if (retval) {
msg_printf(&p, MSG_INTERNAL_ERROR, "Can't delete file %s", boinc_failed_file);
@ -212,6 +216,9 @@ void delete_old_slot_dirs() {
}
#endif
if (!gstate.active_tasks.is_slot_dir_in_use(path)) {
#ifdef SANDBOX
remove_project_owned_files_or_dirs(path);
#endif
clean_out_dir(path);
boinc_rmdir(path);
}
@ -291,18 +298,6 @@ bool is_image_file(const char* filename) {
return false;
}
#ifdef SANDBOX
int set_to_project_group(const char* path) {
if (g_use_sandbox) {
if (boinc_exec(SETPROJECTGRP_FILE_NAME, (char*)path))
return ERR_CHOWN;
}
#else
int set_to_project_group(const char*) {
#endif
return 0;
}
void boinc_version_dir(PROJECT& p, VERSION_INFO& vi, char* buf) {
char projdir[1024];
get_project_dir(&p, projdir, sizeof(projdir));

View File

@ -48,7 +48,6 @@ extern void get_sched_request_filename(PROJECT&, char*, int len);
extern void get_sched_reply_filename(PROJECT&, char*, int len);
extern void get_master_filename(PROJECT&, char*, int len);
extern void job_log_filename(PROJECT&, char*, int);
extern int set_to_project_group(const char* path);
extern void boinc_version_dir(PROJECT&, VERSION_INFO&, char*);
extern bool is_version_dir(char*, VERSION_INFO&);
extern void send_log_after(const char* filename, double t, MIOFILE& mf);

View File

@ -52,6 +52,7 @@
#include "file_names.h"
#include "client_msgs.h"
#include "client_state.h"
#include "sandbox.h"
using std::string;
using std::vector;

View File

@ -73,6 +73,7 @@ typedef void (CALLBACK* ClientLibraryShutdown)();
#include "log_flags.h"
#include "client_msgs.h"
#include "http_curl.h"
#include "sandbox.h"
#include "main.h"
@ -718,7 +719,7 @@ int main(int argc, char** argv) {
// for the current setting of g_use_sandbox
//
#if defined(_DEBUG) && defined(__APPLE__)
// GDB can't attach to applications which are running as a diferent user
// GDB can't attach to applications which are running as a different user
// or group, so fix up data with current user and group during debugging
//
if (check_security(g_use_sandbox, false)) {

119
client/sandbox.C Normal file
View File

@ -0,0 +1,119 @@
// Berkeley Open Infrastructure for Network Computing
// http://boinc.berkeley.edu
// Copyright (C) 2007 University of California
//
// This is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any later version.
//
// This software is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// To view the GNU Lesser General Public License visit
// http://www.gnu.org/copyleft/lesser.html
// or write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include <sys/types.h>
#include <sys/wait.h>
#include <grp.h>
#include "error_numbers.h"
#include "file_names.h"
#include "util.h"
#include "str_util.h"
#include "client_state.h"
#include "sandbox.h"
bool g_use_sandbox;
#ifndef _WIN32
static int lookup_group(char* name, gid_t& gid) {
struct group* gp = getgrnam(name);
if (!gp) return ERR_GETGRNAM;
gid = gp->gr_gid;
return 0;
}
#endif
void kill_via_switcher(int pid) {
char cmd[1024];
if (!g_use_sandbox) return;
// if project application is running as user boinc_project and
// core client is running as user boinc_master, we cannot send
// a signal directly, so use switcher.
sprintf(cmd, "/bin/kill kill -s KILL %d", pid);
switcher_exec(SWITCHER_FILE_NAME, cmd);
}
int get_project_gid() {
if (g_use_sandbox) {
#ifdef _DEBUG
gstate.boinc_project_gid = getegid();
#else
return lookup_group(BOINC_PROJECT_GROUP_NAME, gstate.boinc_project_gid);
#endif // _DEBUG
} else {
gstate.boinc_project_gid = 0;
}
return 0;
}
int set_to_project_group(const char* path) {
if (g_use_sandbox) {
if (switcher_exec(SETPROJECTGRP_FILE_NAME, (char*)path)) {
return ERR_CHOWN;
}
}
return 0;
}
// POSIX requires that shells run from an application will use the
// real UID and GID if different from the effective UID and GID.
// Mac OS 10.4 did not enforce this, but OS 10.5 does. Since
// system() invokes a shell, we can't use it to run the switcher
// or setprojectgrp utilities, so we must do a fork() and execv().
//
int switcher_exec(char *util_filename, char* cmdline) {
char* argv[100];
char util_path[1024];
sprintf(util_path, "%s/%s", SWITCHER_DIR, util_filename);
argv[0] = util_filename;
parse_command_line(cmdline, argv+1);
int pid = fork();
if (pid == -1) {
perror("fork() failed in switcher_exec");
return ERR_FORK;
}
if (pid == 0) {
// This is the new (forked) process
execv(util_path, argv);
perror("execv failed in switcher_exec");
return ERR_EXEC;
}
// Wait for command to complete, like system() does.
waitpid(pid, 0, 0);
return BOINC_SUCCESS;
}
int remove_project_owned_file_or_dir(const char* path) {
char cmd[1024];
if (g_use_sandbox) {
sprintf(cmd, "/bin/rm rm -fR \"%s\"", path);
if (switcher_exec(SWITCHER_FILE_NAME, cmd)) {
return ERR_UNLINK;
} else {
return 0;
}
}
return ERR_UNLINK;
}

27
client/sandbox.h Normal file
View File

@ -0,0 +1,27 @@
// Berkeley Open Infrastructure for Network Computing
// http://boinc.berkeley.edu
// Copyright (C) 2007 University of California
//
// This is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any later version.
//
// This software is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// To view the GNU Lesser General Public License visit
// http://www.gnu.org/copyleft/lesser.html
// or write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
extern void kill_via_switcher(int pid);
extern int get_project_gid();
extern int set_to_project_group(const char* path);
extern int switcher_exec(char* util_filename, char* cmdline);
#define BOINC_PROJECT_GROUP_NAME "boinc_project"
extern bool g_use_sandbox;

View File

@ -33,10 +33,8 @@
#else
#include <sys/wait.h>
#endif
#ifdef SANDBOX
#include <grp.h>
#include "util.h" // For g_use_sandbox
#endif
bool g_use_sandbox;
using std::string;

View File

@ -40,6 +40,8 @@ typedef struct {
} RUNNING_GFX_APP;
extern bool g_use_sandbox;
class CMainDocument;
class CNetworkConnection : public wxObject {

View File

@ -2,6 +2,11 @@
$project_news = array(
array("October 4, 2007",
"The National Science Foundation has awarded a three-year grant,
NSF award #OCI-0721124, to the BOINC project.
This will support our development efforts through August 2010."
),
array("September 26, 2007",
"The Third Pan-Galactic BOINC Workshop took place 5-6 Sept. in Geneva.
The proceedings, including talk slides and notes from

View File

@ -89,6 +89,7 @@ function show_create() {
<li> <b>Companies</b>:
use BOINC for <a href=dg.php>desktop Grid computing</a>.
</ul>
Current projects: check for <a href=trac/wiki/ServerUpdates>server software updates</a>.
</td></tr>
";
}
@ -119,12 +120,13 @@ function show_nsf() {
<img align=left src=nsf.gif>
BOINC is supported by the
<a href=http://nsf.gov>National Science Foundation</a>
through awards SCI/0221529, SCI/0438443 and SCI/0506411.
<font size=-2>
through awards SCI-0221529, SCI-0438443, SCI-0506411,
PHY/0555655, and OCI-0721124.
<span class=note>
Any opinions, findings, and conclusions or recommendations expressed in
this material are those of the author(s)
and do not necessarily reflect the views of the National Science Foundation.
</font>
</span>
</td></tr>
";
}

View File

@ -161,8 +161,6 @@ int main(int argc, char** argv) {
char passwd_buf[256], hostname_buf[256], *hostname=0;
char* passwd = passwd_buf, *p;
g_use_sandbox = false;
strcpy(passwd_buf, "");
read_password_from_file(passwd_buf);

View File

@ -190,6 +190,6 @@ struct VERSION_INFO {
#define LOCK_FILE_NAME "lockfile"
#endif
#define GRAPHICS_APP_FILENAME "v6graphics"
#define GRAPHICS_APP_FILENAME "graphics_app"
#endif

View File

@ -183,6 +183,7 @@
// represents HTTP 404 error
#define ERR_BAD_FILENAME -225
#define ERR_TOO_MANY_EXITS -226
#define ERR_RMDIR -227
// PLEASE: add a text description of your error to
// the text description function boincerror() in str_util.C.

View File

@ -64,10 +64,6 @@ typedef BOOL (CALLBACK* FreeFn)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULAR
#include "str_util.h"
#include "error_numbers.h"
#include "filesys.h"
#ifdef SANDBOX
#include "file_names.h"
#include <sys/wait.h>
#endif
#ifdef _USING_FCGI_
#include "fcgi_stdio.h"
@ -248,16 +244,14 @@ DirScanner::~DirScanner() {
static int boinc_delete_file_aux(const char* path) {
#ifdef _WIN32
if (DeleteFile(path)) return 0;
return GetLastError();
if (!DeleteFile(path)) {
return ERR_UNLINK;
}
#else
int retval = unlink(path);
if (retval && g_use_sandbox && (errno == EACCES)) {
// We may not have permission to read subdirectories created by projects
return remove_project_owned_file_or_dir(path);
}
return retval;
if (retval) return ERR_UNLINK;
#endif
return 0;
}
// Delete the file located at path
@ -326,10 +320,6 @@ int clean_out_dir(const char* dirpath) {
dirp = dir_open(dirpath);
if (!dirp) {
if (g_use_sandbox && (errno == EACCES)) {
// dir may be owned by boinc_apps
return remove_project_owned_file_or_dir(dirpath);
}
return 0; // if dir doesn't exist, it's empty
}
@ -544,68 +534,15 @@ int boinc_mkdir(const char* path) {
int boinc_rmdir(const char* name) {
#ifdef _WIN32
if (!RemoveDirectory(name)) {
return GetLastError();
return ERR_RMDIR;
}
#else
int retval = rmdir(name);
if (retval) return ERR_RMDIR;
#endif
return 0;
#else
int retval;
retval = rmdir(name);
// We may not have permission to read subdirectories created by projects
if (retval && g_use_sandbox && (errno == EACCES)) {
retval = remove_project_owned_file_or_dir(name);
}
return retval;
#endif
}
#ifdef SANDBOX
// POSIX requires that shells run from an application will use the
// real UID and GID if different from the effective UID and GID.
// Mac OS 10.4 did not enforce this, but OS 10.5 does. Since
// system() invokes a shell, we can't use it to run the switcher
// or setprojectgrp utilities, so we must do a fork() and execv().
int boinc_exec(char *util_filename, char* cmdline) {
char* argv[100];
char util_path[MAXPATHLEN];
sprintf(util_path, "%s/%s", SWITCHER_DIR, util_filename);
argv[0] = util_filename;
parse_command_line(cmdline, argv+1);
int pid = fork();
if (pid == -1) {
perror("fork() failed in boinc_exec");
return ERR_FORK;
}
if (pid == 0) {
// This is the new (forked) process
execv(util_path, argv);
perror("execv failed in boinc_exec");
return ERR_EXEC;
}
// Wait for command to complete, like system() does.
waitpid(pid, 0, 0);
return BOINC_SUCCESS;
}
int remove_project_owned_file_or_dir(const char* path) {
char cmd[1024];
if (g_use_sandbox) {
sprintf(cmd, "/bin/rm rm -fR \"%s\"", path);
if (boinc_exec(SWITCHER_FILE_NAME, cmd)) {
return ERR_UNLINK;
} else {
return 0;
}
}
return ERR_UNLINK;
}
#else
int remove_project_owned_file_or_dir(const char*) {
return ERR_UNLINK;
}
#endif
#ifndef _WIN32
int boinc_chown(const char* path, gid_t gid) {
if (gid) {

View File

@ -46,9 +46,6 @@ extern "C" {
extern int boinc_chown(const char*, gid_t);
#endif
extern int boinc_rmdir(const char*);
#ifdef SANDBOX
extern int boinc_exec(char* util_filename, char* cmdline);
#endif
extern int remove_project_owned_file_or_dir(const char* path);
extern void boinc_getcwd(char*);
extern void relative_to_absolute(const char* relname, char* path);

View File

@ -677,6 +677,7 @@ const char* boincerror(int which_error) {
case ERR_FILE_NOT_FOUND: return "file not found";
case ERR_BAD_FILENAME: return "file name is empty or has '..'";
case ERR_TOO_MANY_EXITS: return "application exited too many times";
case ERR_RMDIR: return "rmdir() failed";
case 404: return "HTTP file not found";
case 407: return "HTTP proxy authentication failure";
case 416: return "HTTP range request error";

View File

@ -66,8 +66,6 @@ using std::min;
using std::string;
using std::vector;
int g_use_sandbox = 0;
#define EPOCHFILETIME_SEC (11644473600.)
#define TEN_MILLION 10000000.
@ -285,15 +283,6 @@ void update_average(
avg_time = now;
}
#ifndef _WIN32
int lookup_group(char* name, gid_t& gid) {
struct group* gp = getgrnam(name);
if (!gp) return ERR_GETGRNAM;
gid = gp->gr_gid;
return 0;
}
#endif
// chdir into the given directory, and run a program there.
// If nsecs is nonzero, make sure it's still running after that many seconds.
//

View File

@ -33,12 +33,6 @@
#include <pthread.h>
#endif
// Ideally, we would access this using wxGetApp().m_use_sandbox in the Manager
// and gstate.m_use_sandbox in the Client, but it is used by some source files
// (filesys.C, check_security.C) that are linked with both Manager and Client
// so the most practical solution is to use a global.
extern int g_use_sandbox;
extern double dtime();
extern double dday();
extern void boinc_sleep(double);
@ -62,11 +56,9 @@ extern char* windows_format_error_string(
extern int boinc_thread_cpu_time(HANDLE thread_handle, double& cpu);
extern int boinc_process_cpu_time(double& cpu);
#else
extern int lookup_group(char*, gid_t& gid);
extern int check_security(int use_sandbox, int isManager);
// setpriority(2) arg to run in background
// (don't use 20 because
//
static const int PROCESS_IDLE_PRIORITY = 19;
extern double linux_cpu_time(int pid);
#endif