aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Schlemmer <azarah@gentoo.org>2006-07-06 16:37:20 +0000
committerMartin Schlemmer <azarah@gentoo.org>2006-07-06 16:37:20 +0000
commit27feeab6e5eb6e2ff389943899691b18c970b08c (patch)
treeb300e0395e2b6b673900292f7d27dbef9a4c5ad8
parentOnly print info if we have a controlling terminal. (diff)
downloadsandbox-27feeab6e5eb6e2ff389943899691b18c970b08c.tar.gz
sandbox-27feeab6e5eb6e2ff389943899691b18c970b08c.tar.bz2
sandbox-27feeab6e5eb6e2ff389943899691b18c970b08c.zip
Set default values via a config file. Also support sandbox.d
config directory for package specific configuration files. Signed-off-by: Martin Schlemmer <azarah@gentoo.org>
-rw-r--r--Makefile.am2
-rw-r--r--configure.ac1
-rw-r--r--etc/00default29
-rw-r--r--etc/Makefile.am6
-rw-r--r--etc/sandbox.conf80
-rw-r--r--src/Makefile.am3
-rw-r--r--src/sandbox.c264
-rw-r--r--src/sandbox.h4
8 files changed, 314 insertions, 75 deletions
diff --git a/Makefile.am b/Makefile.am
index 941e5ea..2cf257b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,6 +1,6 @@
AUTOMAKE_OPTIONS = dist-bzip2 no-dist-gzip
-SUBDIRS = scripts data librcutil src
+SUBDIRS = scripts etc data librcutil src
src: librcutil
diff --git a/configure.ac b/configure.ac
index a15ab9d..d63f995 100644
--- a/configure.ac
+++ b/configure.ac
@@ -196,6 +196,7 @@ fi
AC_OUTPUT([
Makefile
scripts/Makefile
+ etc/Makefile
data/Makefile
librcutil/Makefile
src/Makefile
diff --git a/etc/00default b/etc/00default
new file mode 100644
index 0000000..6bae212
--- /dev/null
+++ b/etc/00default
@@ -0,0 +1,29 @@
+# Default configuration for non-set values
+#
+# As stated in sandbox.conf, any value in here do not get used if the variable
+# is already present in the environment. All rules of the ACCESS Section
+# applies here.
+
+# Normally the whole filesystem should be readable
+SANDBOX_READ="/"
+
+# Finally add current directory if interactive
+SANDBOX_WRITE="${SANDBOX_WORKDIR}"
+# Needed for configure tests
+SANDBOX_WRITE="/usr/tmp/conftest:/usr/lib/conftest:/usr/lib32/conftest:/usr/lib64/conftest:/usr/tmp/cf:/usr/lib/cf:/usr/lib32/cf:/usr/lib64/cf"
+
+
+#
+# The following should be moved to respective packages
+#
+
+# This should be handled by gnome-base/gconf
+SANDBOX_WRITE="${HOME}/.gconfd/lock"
+# This should be handled by app-text/scrollkeeper
+SANDBOX_WRITE="/var/log/scrollkeeper.log"
+
+# These should be handled by dev-lang/python or sys-apps/portage
+SANDBOX_PREDICT="/usr/lib/python2.0/:/usr/lib/python2.1/:/usr/lib/python2.2/:/usr/lib/python2.3/:/usr/lib/python2.4/:/usr/lib/python2.5/:/usr/lib/python3.0/"
+# These should be handled by sys-libs/nss-db
+SANDBOX_PREDICT="/var/db/aliases.db:/var/db/netgroup.db:/var/db/netmasks.db:/var/db/ethers.db:/var/db/rpc.db:/var/db/protocols.db:/var/db/services.db:/var/db/networks.db:/var/db/hosts.db:/var/db/group.db:/var/db/passwd.db"
+
diff --git a/etc/Makefile.am b/etc/Makefile.am
new file mode 100644
index 0000000..3425f1b
--- /dev/null
+++ b/etc/Makefile.am
@@ -0,0 +1,6 @@
+confdir = $(sysconfdir)
+dist_conf_DATA = sandbox.conf
+
+confddir = $(sysconfdir)/sandbox.d
+dist_confd_DATA = 00default
+
diff --git a/etc/sandbox.conf b/etc/sandbox.conf
new file mode 100644
index 0000000..d6ae4bf
--- /dev/null
+++ b/etc/sandbox.conf
@@ -0,0 +1,80 @@
+# Sandbox main configuration file
+
+# Note that configuration parser is fairly basic, so try to keep things simple.
+
+#
+# BASIC Section
+#
+
+# Basic sandbox configuration. Sandbox will use values here if not already set
+# in the environment. Assignment works like bash variable assignment (ie, last
+# value assigned to the variable is used).
+
+# SANDBOX_VERBOSE
+#
+# Determine if sandbox print access violations, or if debugging is enabled,
+# it will also print allowed operations. Default is "yes"
+#SANDBOX_VERBOSE="yes"
+
+# SANDBOX_DEBUG
+#
+# In addition to the normal log, a debug log is also written containing all
+# operations caught by sandbox. Default is "no"
+#SANDBOX_DEBUG="no"
+
+# SANDBOX_BEEP
+#
+# The amount of beeps sandbox will issue when it exits with access violations
+# after printing the normal log. Default is "3"
+#SANDBOX_BEEP=3
+
+# NOCOLOR
+#
+# Determine the use of color in the output. Default is "false" (ie, use color)
+#NOCOLOR="false"
+
+
+#
+# ACCESS Section
+#
+
+# The next section contain rules for access. It works a bit different from the
+# previous section in that values assigned to variables stack. Also since these
+# do NOT get overridded by values already set in the environment, but rather
+# those get added.
+#
+# If you want values that only get set if one of the variables are not already
+# present in the environment, place a file in /etc/sandbox.d/ (replace /etc
+# with what sysconfdir was configured to).
+#
+# Another difference from above, is that these support simple variable name
+# substitution. Variable names must be in the form of '${variable}' (without
+# the ''). It is very basic, so no command substitution, etc is supported.
+#
+# The values consists of the respective paths seperated by a colon (:)
+#
+# SANDBOX_DENY - all access to respective paths are denied
+#
+# SANDBOX_READ - can read respective paths
+#
+# SANDBOX_WRITE - can write to respective paths
+#
+# SANDBOX_PREDICT - respective paths are not writable, but no access violation
+# will be issued in the case of a write
+#
+
+# Needed for stdout, stdin and stderr
+SANDBOX_WRITE="/dev/fd:/proc/self/fd"
+# Common device nodes
+SANDBOX_WRITE="/dev/zero:/dev/null:/dev/full"
+# Console device nodes
+SANDBOX_WRITE="/dev/console:/dev/tty:/dev/vc/:/dev/pty:/dev/tts"
+# Device filesystems
+SANDBOX_WRITE="/dev/pts/:/dev/shm"
+# Tempory storage
+SANDBOX_WRITE="/tmp/:/var/tmp/"
+# Needed for shells
+SANDBOX_WRITE="${HOME}/.bash_history"
+
+# Usually writes in /home should not cause violations
+SANDBOX_PREDICT="${HOME}"
diff --git a/src/Makefile.am b/src/Makefile.am
index 0eb7bd3..20b8ef0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -4,7 +4,8 @@ lib_LTLIBRARIES = libsandbox.la
bin_PROGRAMS = sandbox
AM_CPPFLAGS = \
- -DPIC -fPIC -D_REENTRANT \
+ -DPIC -fPIC -D_REENTRANT \
+ -DETCDIR=\"$(sysconfdir)\" \
-DLIBSANDBOX_PATH=\"$(libdir)\" \
-DSANDBOX_BASHRC_PATH=\"$(pkgdatadir)\" \
-I$(top_srcdir) -Wall
diff --git a/src/sandbox.c b/src/sandbox.c
index 019d9b1..027301e 100644
--- a/src/sandbox.c
+++ b/src/sandbox.c
@@ -50,7 +50,7 @@ static char log_domain[] = "sandbox";
extern char **environ;
-int sandbox_setup(struct sandbox_info_t *sandbox_info)
+int sandbox_setup(struct sandbox_info_t *sandbox_info, bool interactive)
{
if (NULL != getenv(ENV_PORTAGE_TMPDIR)) {
/* Portage handle setting SANDBOX_WRITE itself. */
@@ -60,6 +60,8 @@ int sandbox_setup(struct sandbox_info_t *sandbox_info)
perror("sandbox: Failed to get current directory");
return -1;
}
+ if (interactive)
+ setenv(ENV_SANDBOX_WORKDIR, sandbox_info->work_dir, 1);
}
/* Do not resolve symlinks, etc .. libsandbox will handle that. */
@@ -194,68 +196,198 @@ void usr1_handler(int signum, siginfo_t *siginfo, void *ucontext)
}
}
-int get_sandbox_write_envvar(char *buf, struct sandbox_info_t *sandbox_info)
+char *sandbox_subst_env_vars(dyn_buf_t *env_data)
{
- int retval = 0;
-
- /* bzero out entire buffer then append trailing 0 */
- memset(buf, 0, SB_BUF_LEN);
-
- /* these could go into make.globals later on */
- retval = snprintf(buf, SB_BUF_LEN,
- "%s:%s/.gconfd/lock:%s/.bash_history:%s:%s:%s:%s",
- "/dev/zero:/dev/null:/dev/full:/dev/fd:/proc/self/fd:/dev/pts/:"
- "/dev/vc/:/dev/pty:/dev/tty:/dev/tts:/dev/console:"
- "/dev/shm:/dev/shm/ngpt:/var/log/scrollkeeper.log:"
- "/usr/tmp/conftest:/usr/lib/conftest:"
- "/usr/lib32/conftest:/usr/lib64/conftest:"
- "/usr/tmp/cf:/usr/lib/cf:/usr/lib32/cf:/usr/lib64/cf",
- sandbox_info->home_dir, sandbox_info->home_dir,
- sandbox_info->work_dir[0] != '\0' ? sandbox_info->work_dir
- : "",
- sandbox_info->tmp_dir, sandbox_info->var_tmp_dir,
- "/tmp/:/var/tmp/");
- if (SB_BUF_LEN <= retval) {
- errno = EMSGSIZE;
- perror("sandbox: Failed to generate SANDBOX_WRITE");
+ dyn_buf_t *new_data = NULL;
+ char *tmp_ptr, *tmp_data = NULL;
+ char *var_start, *var_stop;
+
+ new_data = new_dyn_buf();
+ if (NULL == new_data)
+ return NULL;
+
+ tmp_data = read_line_dyn_buf(env_data);
+ if (NULL == tmp_data)
+ goto error;
+ tmp_ptr = tmp_data;
+
+ while (NULL != (var_start = strchr(tmp_ptr, '$'))) {
+ char *env = NULL;
+
+ var_stop = strchr(var_start, '}');
+
+ /* We only support ${} style env var names, so just skip any
+ * '$' that do not follow this syntax */
+ if (('{' != var_start[1]) || (NULL == var_stop)) {
+ tmp_ptr = var_start + 1;
+ continue;
+ }
+
+ /* Terminate part before env string so that we can copy it */
+ var_start[0] = '\0';
+ /* Move var_start past '${' */
+ var_start += 2;
+ /* Terminate the name of the env var */
+ var_stop[0] = '\0';
+
+ if (strlen(var_start) > 0)
+ env = getenv(var_start);
+ if (-1 == sprintf_dyn_buf(new_data, "%s%s",
+ tmp_ptr ? tmp_ptr : "",
+ env ? env : ""))
+ goto error;
+
+ /* Move tmp_ptr past the '}' of the env var */
+ tmp_ptr = var_stop + 1;
+ }
+
+ if (0 != strlen(tmp_ptr))
+ if (-1 == write_dyn_buf(new_data, tmp_ptr, strlen(tmp_ptr)))
+ goto error;
+
+ free(tmp_data);
+
+ tmp_data = read_line_dyn_buf(new_data);
+ if (NULL == tmp_data)
+ goto error;
+
+ free_dyn_buf(new_data);
+
+ return tmp_data;
+
+error:
+ if (NULL != new_data)
+ free_dyn_buf(new_data);
+ if (NULL != tmp_data)
+ free(tmp_data);
+
+ return NULL;
+}
+
+void sandbox_set_env_var(const char *env_var)
+{
+ char *config;
+
+ /* We check if the variable is set in the environment, and if not, we
+ * get it from sandbox.conf, and if they exist, we just add them to the
+ * environment if not already present. */
+ if (NULL == getenv(env_var)) {
+ config = rc_get_cnf_entry(SANDBOX_CONF_FILE, env_var, NULL);
+ if (NULL != config) {
+ setenv(ENV_SANDBOX_VERBOSE, config, 0);
+ free(config);
+ }
+ }
+}
+
+int sandbox_set_env_access_var(const char *access_var)
+{
+ dyn_buf_t *env_data = NULL;
+ int count = 0;
+ char *config = NULL;
+ char **confd_files = NULL;
+ bool use_confd = TRUE;
+
+ env_data = new_dyn_buf();
+ if (NULL == env_data)
return -1;
+
+ /* Now get the defaults for the access variable from sandbox.conf.
+ * These do not get overridden via the environment. */
+ config = rc_get_cnf_entry(SANDBOX_CONF_FILE, access_var, ":");
+ if (NULL != config) {
+ if (-1 == write_dyn_buf(env_data, config, strlen(config)))
+ goto error;
+ free(config);
+ config = NULL;
+ }
+ /* Append whatever might be already set. If anything is set, we do
+ * not process the sandbox.d/ files for this variable. */
+ if (NULL != getenv(access_var)) {
+ use_confd = FALSE;
+ if (-1 == sprintf_dyn_buf(env_data, env_data->wr_index ? ":%s" : "%s",
+ getenv(access_var)))
+ goto error;
}
+ if (!use_confd)
+ goto done;
+
+ /* Now scan the files in sandbox.d/ if the access variable was not
+ * alreay set. */
+ confd_files = rc_ls_dir(SANDBOX_CONFD_DIR, FALSE, TRUE);
+ if (NULL != confd_files) {
+ while (NULL != confd_files[count]) {
+ config = rc_get_cnf_entry(confd_files[count], access_var, ":");
+ if (NULL != config) {
+ if (-1 == sprintf_dyn_buf(env_data,
+ env_data->wr_index ? ":%s" : "%s",
+ config))
+ goto error;
+ free(config);
+ config = NULL;
+ }
+ count++;
+ }
+
+ str_list_free(confd_files);
+ }
+
+done:
+ if (env_data->wr_index > 0) {
+ char *subst;
+
+ subst = sandbox_subst_env_vars(env_data);
+ if (NULL == subst)
+ goto error;
+
+ setenv(access_var, subst, 1);
+ free(subst);
+ }
+
+ free_dyn_buf(env_data);
+
return 0;
+
+error:
+ if (NULL != env_data)
+ free_dyn_buf(env_data);
+ if (NULL != config)
+ free(config);
+ if (NULL != confd_files)
+ str_list_free(confd_files);
+
+ return -1;
}
-int get_sandbox_predict_envvar(char *buf, struct sandbox_info_t *sandbox_info)
+int sandbox_setup_env_config(struct sandbox_info_t *sandbox_info)
{
- int retval = 0;
- /* bzero out entire buffer then append trailing 0 */
- memset(buf, 0, SB_BUF_LEN);
-
- /* these should go into make.globals later on */
- retval = snprintf(buf, SB_BUF_LEN, "%s/.:"
- "/usr/lib/python2.0/:"
- "/usr/lib/python2.1/:"
- "/usr/lib/python2.2/:"
- "/usr/lib/python2.3/:"
- "/usr/lib/python2.4/:"
- "/usr/lib/python2.5/:"
- "/usr/lib/python3.0/:"
- "/var/db/aliases.db:"
- "/var/db/netgroup.db:"
- "/var/db/netmasks.db:"
- "/var/db/ethers.db:"
- "/var/db/rpc.db:"
- "/var/db/protocols.db:"
- "/var/db/services.db:"
- "/var/db/networks.db:"
- "/var/db/hosts.db:"
- "/var/db/group.db:"
- "/var/db/passwd.db",
- sandbox_info->home_dir);
- if (SB_BUF_LEN <= retval) {
- errno = EMSGSIZE;
- perror("sandbox: Failed to generate SANDBOX_PREDICT");
+ sandbox_set_env_var(ENV_SANDBOX_VERBOSE);
+ sandbox_set_env_var(ENV_SANDBOX_DEBUG);
+ sandbox_set_env_var(ENV_SANDBOX_BEEP);
+ sandbox_set_env_var(ENV_NOCOLOR);
+
+ if (-1 == sandbox_set_env_access_var(ENV_SANDBOX_DENY))
return -1;
- }
+ if (NULL == getenv(ENV_SANDBOX_DENY))
+ setenv(ENV_SANDBOX_DENY, LD_PRELOAD_FILE, 1);
+
+ if (-1 == sandbox_set_env_access_var(ENV_SANDBOX_READ))
+ return -1;
+ if (NULL == getenv(ENV_SANDBOX_READ))
+ setenv(ENV_SANDBOX_READ, "/", 1);
+
+ if (-1 == sandbox_set_env_access_var(ENV_SANDBOX_WRITE))
+ return -1;
+ if ((NULL == getenv(ENV_SANDBOX_WRITE)) &&
+ (NULL != sandbox_info->work_dir))
+ setenv(ENV_SANDBOX_WRITE, sandbox_info->work_dir, 1);
+
+ if (-1 == sandbox_set_env_access_var(ENV_SANDBOX_PREDICT))
+ return -1;
+ if ((NULL == getenv(ENV_SANDBOX_PREDICT)) &&
+ (NULL != sandbox_info->home_dir))
+ setenv(ENV_SANDBOX_PREDICT, sandbox_info->home_dir, 1);
return 0;
}
@@ -295,12 +427,13 @@ char **sandbox_setup_environ(struct sandbox_info_t *sandbox_info, bool interacti
char **new_environ;
char **env_ptr = environ;
- char sandbox_write_envvar[SB_BUF_LEN];
- char sandbox_predict_envvar[SB_BUF_LEN];
char *ld_preload_envvar = NULL;
char *orig_ld_preload_envvar = NULL;
char sb_pid[64];
+ if (-1 == sandbox_setup_env_config(sandbox_info))
+ return NULL;
+
/* Unset these, as its easier than replacing when setting up our
* new environment below */
unsetenv(ENV_SANDBOX_ON);
@@ -309,6 +442,7 @@ char **sandbox_setup_environ(struct sandbox_info_t *sandbox_info, bool interacti
unsetenv(ENV_SANDBOX_BASHRC);
unsetenv(ENV_SANDBOX_LOG);
unsetenv(ENV_SANDBOX_DEBUG_LOG);
+ unsetenv(ENV_SANDBOX_WORKDIR);
unsetenv(ENV_SANDBOX_ACTIVE);
if (NULL != getenv(ENV_LD_PRELOAD)) {
@@ -372,22 +506,6 @@ char **sandbox_setup_environ(struct sandbox_info_t *sandbox_info, bool interacti
if (1 != have_ld_preload)
sandbox_setenv(new_environ, ENV_LD_PRELOAD, ld_preload_envvar);
- if (!getenv(ENV_SANDBOX_DENY))
- sandbox_setenv(new_environ, ENV_SANDBOX_DENY, LD_PRELOAD_FILE);
-
- if (!getenv(ENV_SANDBOX_READ))
- sandbox_setenv(new_environ, ENV_SANDBOX_READ, "/");
-
- if (-1 == get_sandbox_write_envvar(sandbox_write_envvar, sandbox_info))
- return NULL;
- if (!getenv(ENV_SANDBOX_WRITE))
- sandbox_setenv(new_environ, ENV_SANDBOX_WRITE, sandbox_write_envvar);
-
- if (-1 == get_sandbox_predict_envvar(sandbox_predict_envvar, sandbox_info))
- return NULL;
- if (!getenv(ENV_SANDBOX_PREDICT))
- sandbox_setenv(new_environ, ENV_SANDBOX_PREDICT, sandbox_predict_envvar);
-
/* Make sure our bashrc gets preference */
sandbox_setenv(new_environ, ENV_BASH_ENV, sandbox_info->sandbox_rc);
@@ -484,7 +602,7 @@ int main(int argc, char **argv)
if (print_debug)
printf("Detection of the support files.\n");
- if (-1 == sandbox_setup(&sandbox_info)) {
+ if (-1 == sandbox_setup(&sandbox_info, print_debug)) {
fprintf(stderr, "sandbox: Failed to setup sandbox.");
exit(EXIT_FAILURE);
}
diff --git a/src/sandbox.h b/src/sandbox.h
index cc1845a..a9cd3b4 100644
--- a/src/sandbox.h
+++ b/src/sandbox.h
@@ -14,6 +14,9 @@
#include "config.h"
#include "rcscripts/rctypes.h"
+#define SANDBOX_CONF_FILE ETCDIR "/sandbox.conf"
+#define SANDBOX_CONFD_DIR ETCDIR "/sandbox.d"
+
#define LD_PRELOAD_EQ "LD_PRELOAD="
#define LD_PRELOAD_FILE "/etc/ld.so.preload"
#define LIB_NAME "libsandbox.so"
@@ -43,6 +46,7 @@
#define ENV_SANDBOX_BASHRC "SANDBOX_BASHRC"
#define ENV_SANDBOX_LOG "SANDBOX_LOG"
#define ENV_SANDBOX_DEBUG_LOG "SANDBOX_DEBUG_LOG"
+#define ENV_SANDBOX_WORKDIR "SANDBOX_WORKDIR"
#define ENV_SANDBOX_DENY "SANDBOX_DENY"
#define ENV_SANDBOX_READ "SANDBOX_READ"