You've already forked macports-base
mirror of
https://github.com/macports/macports-base.git
synced 2026-07-12 18:18:43 -07:00
add rudimentary sandboxing support for commands run via system proc
git-svn-id: https://svn.macports.org/repository/macports/trunk/base@98156 d073be05-634f-4543-b044-5fe20cf6d1d6
This commit is contained in:
@@ -710,6 +710,7 @@ TAR
|
||||
SWIG
|
||||
SVN
|
||||
SED
|
||||
SANDBOX_EXEC
|
||||
RSYNC
|
||||
RMDIR
|
||||
PAX
|
||||
@@ -5544,6 +5545,46 @@ $as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
# Extract the first word of "sandbox-exec", so it can be a program name with args.
|
||||
set dummy sandbox-exec; ac_word=$2
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
$as_echo_n "checking for $ac_word... " >&6; }
|
||||
if ${ac_cv_path_SANDBOX_EXEC+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
case $SANDBOX_EXEC in
|
||||
[\\/]* | ?:[\\/]*)
|
||||
ac_cv_path_SANDBOX_EXEC="$SANDBOX_EXEC" # Let the user override the test with a path.
|
||||
;;
|
||||
*)
|
||||
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
for as_dir in /usr/bin
|
||||
do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_path_SANDBOX_EXEC="$as_dir/$ac_word$ac_exec_ext"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
IFS=$as_save_IFS
|
||||
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
SANDBOX_EXEC=$ac_cv_path_SANDBOX_EXEC
|
||||
if test -n "$SANDBOX_EXEC"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $SANDBOX_EXEC" >&5
|
||||
$as_echo "$SANDBOX_EXEC" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
# Extract the first word of "sed", so it can be a program name with args.
|
||||
set dummy sed; ac_word=$2
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
|
||||
@@ -133,6 +133,7 @@ AC_PATH_PROG(PATCH, [patch], [])
|
||||
AC_PATH_PROG(PAX, [pax], [])
|
||||
AC_PATH_PROG(RMDIR, [rmdir], [])
|
||||
AC_PATH_PROG(RSYNC, [rsync], [])
|
||||
AC_PATH_PROG(SANDBOX_EXEC, [sandbox-exec], [], [/usr/bin])
|
||||
AC_PATH_PROG(SED, [sed])
|
||||
AC_PATH_PROG(SVN, [svn], [])
|
||||
AC_PATH_PROG(SWIG, [swig], [], [$PATH:/usr/local/bin])
|
||||
|
||||
+50
-6
@@ -77,14 +77,42 @@ struct linebuf {
|
||||
char *line;
|
||||
};
|
||||
|
||||
static int check_sandboxing(Tcl_Interp *interp, char **sandbox_exec_path, char **profilestr)
|
||||
{
|
||||
Tcl_Obj *tcl_result;
|
||||
int supported;
|
||||
int len;
|
||||
|
||||
tcl_result = Tcl_GetVar2Ex(interp, "portsandbox_supported", NULL, TCL_GLOBAL_ONLY);
|
||||
if (!tcl_result || Tcl_GetBooleanFromObj(interp, tcl_result, &supported) != TCL_OK || !supported) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
tcl_result = Tcl_GetVar2Ex(interp, "portutil::autoconf::sandbox_exec_path", NULL, TCL_GLOBAL_ONLY);
|
||||
if (!tcl_result || !(*sandbox_exec_path = Tcl_GetString(tcl_result))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
tcl_result = Tcl_GetVar2Ex(interp, "portsandbox_profile", NULL, TCL_GLOBAL_ONLY);
|
||||
if (!tcl_result || !(*profilestr = Tcl_GetStringFromObj(tcl_result, &len))
|
||||
|| len == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* usage: system ?-notty? ?-nice value? ?-W path? command */
|
||||
int SystemCmd(ClientData clientData UNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
{
|
||||
char *buf;
|
||||
struct linebuf circbuf[CBUFSIZ];
|
||||
size_t linelen;
|
||||
char *args[4];
|
||||
char *args[7];
|
||||
char *cmdstring;
|
||||
int sandbox = 0;
|
||||
char *sandbox_exec_path;
|
||||
char *profilestr;
|
||||
FILE *pdes;
|
||||
int fdset[2], nullfd;
|
||||
int fline, pos, ret;
|
||||
@@ -128,6 +156,11 @@ int SystemCmd(ClientData clientData UNUSED, Tcl_Interp *interp, int objc, Tcl_Ob
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* check if and how we should use sandbox-exec */
|
||||
sandbox = check_sandboxing(interp, &sandbox_exec_path, &profilestr);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Fork a child to run the command, in a popen() like fashion -
|
||||
* popen() itself is not used because stderr is also desired.
|
||||
@@ -178,11 +211,22 @@ int SystemCmd(ClientData clientData UNUSED, Tcl_Interp *interp, int objc, Tcl_Ob
|
||||
}
|
||||
|
||||
/* XXX ugly string constants */
|
||||
args[0] = "sh";
|
||||
args[1] = "-c";
|
||||
args[2] = cmdstring;
|
||||
args[3] = NULL;
|
||||
execve("/bin/sh", args, environ);
|
||||
if (sandbox) {
|
||||
args[0] = "sandbox-exec";
|
||||
args[1] = "-p";
|
||||
args[2] = profilestr;
|
||||
args[3] = "sh";
|
||||
args[4] = "-c";
|
||||
args[5] = cmdstring;
|
||||
args[6] = NULL;
|
||||
execve(sandbox_exec_path, args, environ);
|
||||
} else {
|
||||
args[0] = "sh";
|
||||
args[1] = "-c";
|
||||
args[2] = cmdstring;
|
||||
args[3] = NULL;
|
||||
execve("/bin/sh", args, environ);
|
||||
}
|
||||
_exit(1);
|
||||
break;
|
||||
default: /* parent */
|
||||
|
||||
@@ -6,7 +6,8 @@ SRCS= port.tcl portchecksum.tcl portconfigure.tcl portextract.tcl \
|
||||
portlint.tcl portclean.tcl porttest.tcl portactivate.tcl \
|
||||
portdeactivate.tcl portsubmit.tcl port_autoconf.tcl portstartupitem.tcl \
|
||||
porttrace.tcl portlivecheck.tcl portdistcheck.tcl portmirror.tcl \
|
||||
portload.tcl portunload.tcl portdistfiles.tcl fetch_common.tcl
|
||||
portload.tcl portunload.tcl portdistfiles.tcl fetch_common.tcl \
|
||||
portsandbox.tcl
|
||||
|
||||
include ../../Mk/macports.subdir.mk
|
||||
include ../../Mk/macports.autoconf.mk
|
||||
|
||||
@@ -58,3 +58,4 @@ package require portload 1.0
|
||||
package require portunload 1.0
|
||||
|
||||
package require portdistfiles 1.0
|
||||
package require portsandbox 1.0
|
||||
|
||||
@@ -65,6 +65,7 @@ namespace eval portutil::autoconf {
|
||||
variable xcode_select_path "@XCODE_SELECT@"
|
||||
variable xcodebuild_path "@XCODEBUILD@"
|
||||
variable xcrun_path "@XCRUN@"
|
||||
variable sandbox_exec_path "@SANDBOX_EXEC@"
|
||||
variable sed_command "@SED@"
|
||||
variable sed_ext_flag "@SED_EXT@"
|
||||
variable tar_command "@TAR_CMD@"
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4
|
||||
# $Id$
|
||||
#
|
||||
# Copyright (c) 2012 The MacPorts Project
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of The MacPorts Project nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package provide portsandbox 1.0
|
||||
|
||||
namespace eval portsandbox {
|
||||
}
|
||||
|
||||
options portsandbox_supported portsandbox_profile
|
||||
default portsandbox_supported {[file executable $portutil::autoconf::sandbox_exec_path]}
|
||||
default portsandbox_profile {[portsandbox::get_default_profile]}
|
||||
|
||||
# produce a suitable profile to pass to sandbox-exec
|
||||
# command line usage would be:
|
||||
# sandbox-exec -p '(version 1) (allow default) (deny file* (subpath "/usr/local") (subpath "/Library/Frameworks"))' some-command
|
||||
proc portsandbox::get_default_profile {} {
|
||||
global os.major prefix frameworks_dir
|
||||
set prefix_conflict [expr {$prefix == "/usr/local" || [string match $prefix "/usr/local/*"]}]
|
||||
set frameworks_conflict [expr {$frameworks_dir == "/Library/Frameworks" || [string match $frameworks_dir "/Library/Frameworks/*"]}]
|
||||
if {$prefix_conflict && $frameworks_conflict} {
|
||||
return ""
|
||||
}
|
||||
set profile "(version 1) (allow default) (deny "
|
||||
if {${os.major} > 9} {
|
||||
append profile "file* "
|
||||
if {!$prefix_conflict} {
|
||||
append profile {(subpath "/usr/local")}
|
||||
}
|
||||
if {!$frameworks_conflict} {
|
||||
append profile { (subpath "/Library/Frameworks")}
|
||||
}
|
||||
} else {
|
||||
append profile "file-read* file-write* (regex "
|
||||
if {!$prefix_conflict} {
|
||||
append profile {#"^/usr/local/"}
|
||||
}
|
||||
if {!$frameworks_conflict} {
|
||||
append profile { #"^/Library/Frameworks/"}
|
||||
}
|
||||
append profile ")"
|
||||
}
|
||||
append profile ")"
|
||||
return $profile
|
||||
}
|
||||
Reference in New Issue
Block a user