summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--buildrun.cxx5
-rw-r--r--cache.cxx36
-rw-r--r--elaborate.cxx43
-rw-r--r--elaborate.h4
-rw-r--r--main.cxx154
-rw-r--r--runtime/staprun/common.c1
-rw-r--r--runtime/staprun/modverify.c6
-rw-r--r--runtime/staprun/staprun.c18
-rw-r--r--runtime/staprun/staprun.h1
-rw-r--r--runtime/staprun/staprun_funcs.c29
-rw-r--r--runtime/transport/transport.c4
-rw-r--r--session.h1
-rwxr-xr-x[-rw-r--r--]stap-env6
-rw-r--r--staptree.cxx10
-rw-r--r--staptree.h6
-rw-r--r--systemtap.spec2
-rw-r--r--tapset-been.cxx32
-rw-r--r--tapset-timers.cxx91
-rw-r--r--tapset/logging.stp8
-rw-r--r--tapset/timestamp.stp2
-rw-r--r--tapsets.cxx47
-rw-r--r--testsuite/systemtap.base/optim_arridx.exp2
-rw-r--r--translate.cxx7
-rw-r--r--translate.h2
-rw-r--r--util.cxx24
-rw-r--r--util.h2
26 files changed, 386 insertions, 157 deletions
diff --git a/buildrun.cxx b/buildrun.cxx
index e4b4b7bf..a93b2909 100644
--- a/buildrun.cxx
+++ b/buildrun.cxx
@@ -231,11 +231,12 @@ compile_pass (systemtap_session& s)
rc = run_make_cmd(s, make_cmd);
#if HAVE_NSS
- // If a certificate database was specified, then try to sign the module.
+ // If a certificate database was specified, and we're in unprivileged
+ // mode, then try to sign the module.
// Failure to do so is not a fatal error. If the signature is actually needed,
// staprun will complain at that time.
assert (! s.cert_db_path.empty());
- if (!rc)
+ if (s.unprivileged && ! rc)
sign_module (s);
#endif
diff --git a/cache.cxx b/cache.cxx
index 99b88000..ee6d0bf6 100644
--- a/cache.cxx
+++ b/cache.cxx
@@ -81,18 +81,20 @@ add_to_cache(systemtap_session& s)
string module_signature_src_path = module_src_path;
module_signature_src_path += ".sgn";
- STAP_PROBE2(stap, cache__add__nss, module_signature_src_path.c_str(), module_signature_dest_path.c_str());
-
- if (s.verbose > 1)
- clog << "Copying " << module_signature_src_path << " to " << module_signature_dest_path << endl;
- if (copy_file(module_signature_src_path.c_str(), module_signature_dest_path.c_str()) != 0)
+ if (file_exists (module_signature_src_path))
{
- cerr << "Copy failed (\"" << module_signature_src_path << "\" to \""
- << module_signature_dest_path << "\"): " << strerror(errno) << endl;
- // NB: this is not so severe as to prevent reuse of the .ko
- // already copied.
- //
- // s.use_cache = false;
+ STAP_PROBE2(stap, cache__add__nss, module_signature_src_path.c_str(), module_signature_dest_path.c_str());
+ if (s.verbose > 1)
+ clog << "Copying " << module_signature_src_path << " to " << module_signature_dest_path << endl;
+ if (copy_file(module_signature_src_path.c_str(), module_signature_dest_path.c_str()) != 0)
+ {
+ cerr << "Copy failed (\"" << module_signature_src_path << "\" to \""
+ << module_signature_dest_path << "\"): " << strerror(errno) << endl;
+ // NB: this is not so severe as to prevent reuse of the .ko
+ // already copied.
+ //
+ // s.use_cache = false;
+ }
}
#endif /* HAVE_NSS */
@@ -372,18 +374,6 @@ clean_cache(systemtap_session& s)
}
}
-// Get the size of a file in bytes
-static size_t
-get_file_size(const string &path)
-{
- struct stat file_info;
-
- if (stat(path.c_str(), &file_info) == 0)
- return file_info.st_size;
- else
- return 0;
-}
-
//Assign a weight for a particular file. A lower weight
// will be removed before a higher weight.
//TODO: for now use system mtime... later base a
diff --git a/elaborate.cxx b/elaborate.cxx
index 9271e847..93500239 100644
--- a/elaborate.cxx
+++ b/elaborate.cxx
@@ -261,8 +261,9 @@ match_key::globmatch(match_key const & other) const
// ------------------------------------------------------------------------
match_node::match_node()
- : end(NULL)
-{}
+ : end(NULL), unprivileged_ok (false)
+{
+}
match_node *
match_node::bind(match_key const & k)
@@ -304,6 +305,18 @@ match_node::bind_num(string const & k)
return bind(match_key(k).with_number());
}
+match_node*
+match_node::allow_unprivileged (bool b)
+{
+ unprivileged_ok = b;
+ return this;
+}
+
+bool
+match_node::unprivileged_allowed () const
+{
+ return unprivileged_ok;
+}
void
match_node::find_and_build (systemtap_session& s,
@@ -331,6 +344,14 @@ match_node::find_and_build (systemtap_session& s,
param_map[loc->components[i]->functor] = loc->components[i]->arg;
// maybe 0
+ // Are we compiling for unprivileged users? */
+ if (s.unprivileged)
+ {
+ // Is this probe point ok for unprivileged users?
+ if (! unprivileged_allowed ())
+ throw semantic_error (string("probe point is not allowed for unprivileged users"));
+ }
+
b->build (s, p, loc, param_map, results);
}
else if (isglob(loc->components[pos]->functor)) // wildcard?
@@ -1023,7 +1044,7 @@ semantic_pass_conditions (systemtap_session & sess)
expression* e = p->sole_location()->condition;
if (e)
{
- varuse_collecting_visitor vut;
+ varuse_collecting_visitor vut(sess);
e->visit (& vut);
if (! vut.written.empty())
@@ -1178,7 +1199,7 @@ void add_global_var_display (systemtap_session& s)
// it would clutter up the list of probe points with "end ...".
if (s.listing_mode) return;
- varuse_collecting_visitor vut;
+ varuse_collecting_visitor vut(s);
for (unsigned i=0; i<s.probes.size(); i++)
{
s.probes[i]->body->visit (& vut);
@@ -1965,7 +1986,7 @@ void semantic_pass_opt1 (systemtap_session& s, bool& relaxed_p)
// written nor read.
void semantic_pass_opt2 (systemtap_session& s, bool& relaxed_p, unsigned iterations)
{
- varuse_collecting_visitor vut;
+ varuse_collecting_visitor vut(s);
for (unsigned i=0; i<s.probes.size(); i++)
{
@@ -2162,7 +2183,7 @@ dead_assignment_remover::visit_assignment (assignment* e)
break;
}
- varuse_collecting_visitor lvut;
+ varuse_collecting_visitor lvut(session);
e->left->visit (& lvut);
if (lvut.side_effect_free () && !is_global) // XXX: use _wrt() once we track focal_vars
{
@@ -2195,7 +2216,7 @@ void semantic_pass_opt3 (systemtap_session& s, bool& relaxed_p)
// Recompute the varuse data, which will probably match the opt2
// copy of the computation, except for those totally unused
// variables that opt2 removed.
- varuse_collecting_visitor vut;
+ varuse_collecting_visitor vut(s);
for (unsigned i=0; i<s.probes.size(); i++)
s.probes[i]->body->visit (& vut); // includes reachable functions too
@@ -2299,7 +2320,7 @@ dead_stmtexpr_remover::visit_if_statement (if_statement *s)
{
// We may be able to elide this statement, if the condition
// expression is side-effect-free.
- varuse_collecting_visitor vct;
+ varuse_collecting_visitor vct(session);
s->condition->visit(& vct);
if (vct.side_effect_free ())
{
@@ -2363,7 +2384,7 @@ dead_stmtexpr_remover::visit_for_loop (for_loop *s)
{
// We may be able to elide this statement, if the condition
// expression is side-effect-free.
- varuse_collecting_visitor vct;
+ varuse_collecting_visitor vct(session);
if (s->init) s->init->visit(& vct);
s->cond->visit(& vct);
if (s->incr) s->incr->visit(& vct);
@@ -2400,7 +2421,7 @@ dead_stmtexpr_remover::visit_expr_statement (expr_statement *s)
// NB. While we don't share nodes in the parse tree, let's not
// deallocate *s anyway, just in case...
- varuse_collecting_visitor vut;
+ varuse_collecting_visitor vut(session);
s->value->visit (& vut);
if (vut.side_effect_free_wrt (focal_vars))
@@ -2741,7 +2762,7 @@ void_statement_reducer::visit_functioncall (functioncall* e)
return;
}
- varuse_collecting_visitor vut;
+ varuse_collecting_visitor vut(session);
vut.traversed.insert (e->referent);
vut.current_function = e->referent;
e->referent->body->visit (& vut);
diff --git a/elaborate.h b/elaborate.h
index d927177b..36439c4f 100644
--- a/elaborate.h
+++ b/elaborate.h
@@ -236,6 +236,7 @@ match_node
typedef std::map<match_key, match_node*>::iterator sub_map_iterator_t;
sub_map_t sub;
derived_probe_builder* end;
+ bool unprivileged_ok;
public:
match_node();
@@ -250,6 +251,9 @@ match_node
match_node* bind_str(std::string const & k);
match_node* bind_num(std::string const & k);
void bind(derived_probe_builder* e);
+
+ match_node* allow_unprivileged (bool b = true);
+ bool unprivileged_allowed () const;
};
// ------------------------------------------------------------------------
diff --git a/main.cxx b/main.cxx
index 2c1b1c68..daf64561 100644
--- a/main.cxx
+++ b/main.cxx
@@ -45,6 +45,7 @@ extern "C" {
using namespace std;
+#define PATH_TBD string("__TBD__")
void
version ()
@@ -132,6 +133,8 @@ usage (systemtap_session& s, int exitcode)
#ifdef HAVE_LIBSQLITE3
<< " -q generate information on tapset coverage" << endl
#endif /* HAVE_LIBSQLITE3 */
+ << " --unprivileged" << endl
+ << " restrict usage to features available to unprivileged users" << endl
#if 0 /* PR6864: disable temporarily; should merge with -d somehow */
<< " --kelf make do with symbol table from vmlinux" << endl
<< " --kmap[=FILE]" << endl
@@ -356,6 +359,90 @@ setup_kernel_release (systemtap_session &s, const char* kstr) {
}
}
+static void
+checkOptions (systemtap_session &s)
+{
+ bool optionsConflict = false;
+
+ if(!s.bulk_mode && !s.merge)
+ {
+ cerr << "-M option is valid only for bulk (relayfs) mode." <<endl;
+ optionsConflict = true;
+ }
+
+ if(!s.output_file.empty() && s.bulk_mode && !s.merge)
+ {
+ cerr << "You can't specify -M, -b and -o options together." <<endl;
+ optionsConflict = true;
+ }
+
+ if((s.cmd != "") && (s.target_pid))
+ {
+ cerr << "You can't specify -c and -x options together." <<endl;
+ optionsConflict = true;
+ }
+
+ if (s.unprivileged)
+ {
+ if (s.guru_mode)
+ {
+ cerr << "You can't specify -g and --unprivileged together." << endl;
+ optionsConflict = true;
+ }
+ if (s.include_path.size () > 1)
+ {
+ cerr << "You can't specify -I and --unprivileged together." << endl;
+ optionsConflict = true;
+ }
+ if (s.runtime_path != string(PKGDATADIR) + "/runtime")
+ {
+ cerr << "You can't use -R to specify an alternate runtime path when --unprivileged is specified." << endl;
+ optionsConflict = true;
+ }
+ if (s.kernel_build_tree.substr(0, 13) != "/lib/modules/")
+ {
+ cerr << "You can't use -r to specify a kernel release which is not installed when --unprivileged is specified." << endl;
+ optionsConflict = true;
+ }
+ if (! s.macros.empty ())
+ {
+ cerr << "You can't specify -D and --unprivileged together." << endl;
+ optionsConflict = true;
+ }
+
+ if (getenv ("SYSTEMTAP_TAPSET"))
+ {
+ cerr << "The environment variable SYSTEMTAP_TAPSET can not be defined when --unprivileged is specified." << endl;
+ optionsConflict = true;
+ }
+ if (getenv ("SYSTEMTAP_RUNTIME"))
+ {
+ cerr << "The environment variable SYSTEMTAP_RUNTIME can not be defined when --unprivileged is specified." << endl;
+ optionsConflict = true;
+ }
+ if (getenv ("SYSTEMTAP_DEBUGINFO_PATH"))
+ {
+ cerr << "The environment variable SYSTEMTAP_DEBUGINFO_PATH can not be defined when --unprivileged is specified." << endl;
+ optionsConflict = true;
+ }
+ }
+
+ if (!s.kernel_symtab_path.empty())
+ {
+ if (s.consult_symtab)
+ {
+ cerr << "You can't specify --kelf and --kmap together." << endl;
+ optionsConflict = true;
+ }
+ s.consult_symtab = true;
+ if (s.kernel_symtab_path == PATH_TBD)
+ s.kernel_symtab_path = string("/boot/System.map-") + s.kernel_release;
+ }
+
+ if (optionsConflict)
+ usage (s, 1);
+}
+
int
main (int argc, char * const argv [])
{
@@ -406,11 +493,12 @@ main (int argc, char * const argv [])
s.ignore_dwarf = false;
s.load_only = false;
s.skip_badvars = false;
+ s.unprivileged = false;
// Location of our signing certificate.
// If we're root, use the database in SYSCONFDIR, otherwise
// use the one in our $HOME directory. */
- if (geteuid() == 0)
+ if (getuid() == 0)
s.cert_db_path = SYSCONFDIR "/systemtap/ssl/server";
else
s.cert_db_path = getenv("HOME") + string ("/.systemtap/ssl/server");
@@ -460,6 +548,14 @@ main (int argc, char * const argv [])
}
}
+ // Location of our signing certificate.
+ // If we're root, use the database in SYSCONFDIR, otherwise
+ // use the one in s.data_path. */
+ if (geteuid() == 0)
+ s.cert_db_path = SYSCONFDIR "/systemtap/ssl/server";
+ else
+ s.cert_db_path = s.data_path + "/ssl/server";
+
const char* s_tc = getenv ("SYSTEMTAP_COVERAGE");
if (s_tc != NULL)
s.tapset_compile_coverage = true;
@@ -480,6 +576,7 @@ main (int argc, char * const argv [])
#define LONG_OPT_IGNORE_DWARF 4
#define LONG_OPT_VERBOSE_PASS 5
#define LONG_OPT_SKIP_BADVARS 6
+#define LONG_OPT_UNPRIVILEGED 7
// NB: also see find_hash(), usage(), switch stmt below, stap.1 man page
static struct option long_options[] = {
{ "kelf", 0, &long_opt, LONG_OPT_KELF },
@@ -488,6 +585,7 @@ main (int argc, char * const argv [])
{ "ignore-dwarf", 0, &long_opt, LONG_OPT_IGNORE_DWARF },
{ "skip-badvars", 0, &long_opt, LONG_OPT_SKIP_BADVARS },
{ "vp", 1, &long_opt, LONG_OPT_VERBOSE_PASS },
+ { "unprivileged", 0, &long_opt, LONG_OPT_UNPRIVILEGED },
{ NULL, 0, NULL, 0 }
};
int grc = getopt_long (argc, argv, "hVMvtp:I:e:o:R:r:m:kgPc:x:D:bs:uqwl:d:L:FS:",
@@ -705,7 +803,6 @@ main (int argc, char * const argv [])
if (optarg)
s.kernel_symtab_path = optarg;
else
-#define PATH_TBD string("__TBD__")
s.kernel_symtab_path = PATH_TBD;
break;
case LONG_OPT_IGNORE_VMLINUX:
@@ -737,6 +834,9 @@ main (int argc, char * const argv [])
case LONG_OPT_SKIP_BADVARS:
s.skip_badvars = true;
break;
+ case LONG_OPT_UNPRIVILEGED:
+ s.unprivileged = true;
+ break;
default:
cerr << "Internal error parsing command arguments." << endl;
usage(s, 1);
@@ -749,35 +849,8 @@ main (int argc, char * const argv [])
}
}
- if(!s.bulk_mode && !s.merge)
- {
- cerr << "-M option is valid only for bulk (relayfs) mode." <<endl;
- usage (s, 1);
- }
-
- if(!s.output_file.empty() && s.bulk_mode && !s.merge)
- {
- cerr << "You can't specify -M, -b and -o options together." <<endl;
- usage (s, 1);
- }
-
- if((s.cmd != "") && (s.target_pid))
- {
- cerr << "You can't specify -c and -x options together." <<endl;
- usage (s, 1);
- }
-
- if (!s.kernel_symtab_path.empty())
- {
- if (s.consult_symtab)
- {
- cerr << "You can't specify --kelf and --kmap together." << endl;
- usage (s, 1);
- }
- s.consult_symtab = true;
- if (s.kernel_symtab_path == PATH_TBD)
- s.kernel_symtab_path = string("/boot/System.map-") + s.kernel_release;
- }
+ // Check for options conflicts.
+ checkOptions (s);
// Warn in case the target kernel release doesn't match the running one.
if (s.last_pass > 4 &&
@@ -1177,14 +1250,17 @@ main (int argc, char * const argv [])
// Save the signature as well.
assert (! s.cert_db_path.empty());
module_src_path += ".sgn";
- module_dest_path += ".sgn";
-
- if (s.verbose > 1)
- clog << "Copying " << module_src_path << " to "
- << module_dest_path << endl;
- if (copy_file(module_src_path.c_str(), module_dest_path.c_str()) != 0)
- cerr << "Copy failed (\"" << module_src_path << "\" to \""
- << module_dest_path << "\"): " << strerror(errno) << endl;
+ if (file_exists (module_src_path))
+ {
+ module_dest_path += ".sgn";
+
+ if (s.verbose > 1)
+ clog << "Copying " << module_src_path << " to "
+ << module_dest_path << endl;
+ if (copy_file(module_src_path.c_str(), module_dest_path.c_str()) != 0)
+ cerr << "Copy failed (\"" << module_src_path << "\" to \""
+ << module_dest_path << "\"): " << strerror(errno) << endl;
+ }
#endif
}
}
diff --git a/runtime/staprun/common.c b/runtime/staprun/common.c
index afe96606..6a2ac77e 100644
--- a/runtime/staprun/common.c
+++ b/runtime/staprun/common.c
@@ -30,6 +30,7 @@ int need_uprobes;
int daemon_mode;
off_t fsize_max;
int fnum_max;
+int unprivileged_user = 0;
/* module variables */
char *modname = NULL;
diff --git a/runtime/staprun/modverify.c b/runtime/staprun/modverify.c
index b50a69f4..f4b15ac3 100644
--- a/runtime/staprun/modverify.c
+++ b/runtime/staprun/modverify.c
@@ -203,11 +203,7 @@ verify_it (const char *inputName, const char *signatureName, SECKEYPublicKey *pu
/* Get the size of the signature file. */
prStatus = PR_GetFileInfo (signatureName, &info);
if (prStatus != PR_SUCCESS || info.type != PR_FILE_FILE || info.size < 0)
- {
- fprintf (stderr, "Unable to obtain information on the signature file %s.\n", signatureName);
- nssError ();
- return MODULE_UNTRUSTED; /* Not signed */
- }
+ return MODULE_UNTRUSTED; /* Not signed */
/* Open the signature file. */
local_file_fd = PR_Open (signatureName, PR_RDONLY, 0);
diff --git a/runtime/staprun/staprun.c b/runtime/staprun/staprun.c
index 7069cab3..554eecc8 100644
--- a/runtime/staprun/staprun.c
+++ b/runtime/staprun/staprun.c
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
- * Copyright (C) 2005-2008 Red Hat, Inc.
+ * Copyright (C) 2005-2009 Red Hat, Inc.
*
*/
@@ -139,11 +139,21 @@ static int enable_uprobes(void)
static int insert_stap_module(void)
{
- char bufsize_option[128];
+ char special_options[128];
+ char *bufptr = special_options;
- if (snprintf_chk(bufsize_option, 128, "_stp_bufsize=%d", buffer_size))
+ /* Add the _stp_bufsize option. */
+ if (snprintf_chk(bufptr, sizeof (special_options), "_stp_bufsize=%d", buffer_size))
return -1;
- return insert_module(modpath, bufsize_option, modoptions);
+
+ /* Add the _stp_unprivileged_user option. */
+ bufptr += strlen (bufptr);
+ if (snprintf_chk(bufptr,
+ sizeof (special_options) - (bufptr - special_options),
+ " _stp_unprivileged_user=%d", unprivileged_user))
+ return -1;
+
+ return insert_module(modpath, special_options, modoptions);
}
static int remove_module(const char *name, int verb);
diff --git a/runtime/staprun/staprun.h b/runtime/staprun/staprun.h
index 1c9aece8..0a1ca885 100644
--- a/runtime/staprun/staprun.h
+++ b/runtime/staprun/staprun.h
@@ -171,6 +171,7 @@ extern int need_uprobes;
extern int daemon_mode;
extern off_t fsize_max;
extern int fnum_max;
+extern int unprivileged_user;
/* getopt variables */
extern char *optarg;
diff --git a/runtime/staprun/staprun_funcs.c b/runtime/staprun/staprun_funcs.c
index c19dc3ba..ed7f4fc3 100644
--- a/runtime/staprun/staprun_funcs.c
+++ b/runtime/staprun/staprun_funcs.c
@@ -404,7 +404,6 @@ check_groups (void)
perr("Unable to retrieve group list");
return -1;
}
-
for (i = 0; i < ngids; i++) {
/* If the user is a member of 'stapdev', then we're
* done, since he can use staprun without any
@@ -420,9 +419,10 @@ check_groups (void)
if (gidlist[i] == stapusr_gid)
gid = stapusr_gid;
}
- /* Not a member of stapusr? */
- if (gid != stapusr_gid)
- return 0;
+ if (gid != stapusr_gid) {
+ unprivileged_user = 1;
+ return 0;
+ }
}
/* At this point the user is only a member of the 'stapusr'
@@ -441,8 +441,9 @@ check_groups (void)
* 1) root can do anything
* 2) members of stapdev can do anything
* 3) members of stapusr can load modules from /lib/modules/KVER/systemtap
+ * 4) anyone can load a module which has been signed by a trusted signer
*
- * It is only an error if all 3 levels of checking fail
+ * It is only an error if all 4 levels of checking fail
*
* Returns: -1 on errors, 0 on failure, 1 on success.
*/
@@ -481,6 +482,17 @@ int check_permissions(void)
if (check_groups_rc == 1)
return 1;
+ /* The user is an ordinary user. If the module has been signed with
+ * a "blessed" certificate and private key, then we will load it for
+ * anyone. */
+#if HAVE_NSS
+ if (check_signature_rc == MODULE_OK)
+ return 1;
+ assert (check_signature_rc == MODULE_UNTRUSTED || check_signature_rc == MODULE_CHECK_ERROR);
+#endif
+
+ /* We are an ordinary user and the module was not signed by a trusted
+ signer. */
err("ERROR: You are trying to run stap as a normal user.\n"
"You should either be root, or be part of either "
"group \"stapdev\" or group \"stapusr\".\n");
@@ -488,6 +500,11 @@ int check_permissions(void)
err("Your system doesn't seem to have either group.\n");
check_groups_rc = -1;
}
+#if HAVE_NSS
+ err("Alternatively, your module must be compiled using the --unprivileged option and signed by a trusted signer.\n"
+ "For more information, please consult the \"SAFETY AND SECURITY\" section of the \"stap(1)\" manpage\n");
+#endif
- return check_groups_rc;
+ /* Combine the return codes. They are either 0 or -1. */
+ return check_groups_rc | check_signature_rc;
}
diff --git a/runtime/transport/transport.c b/runtime/transport/transport.c
index 1d029e53..ec73f05f 100644
--- a/runtime/transport/transport.c
+++ b/runtime/transport/transport.c
@@ -59,6 +59,10 @@ static int _stp_bufsize;
module_param(_stp_bufsize, int, 0);
MODULE_PARM_DESC(_stp_bufsize, "buffer size");
+static int _stp_unprivileged_user;
+module_param(_stp_unprivileged_user, int, 1);
+MODULE_PARM_DESC(_stp_unprivileged_user, "user is unprivileged");
+
/* forward declarations */
static void probe_exit(void);
static int probe_start(void);
diff --git a/session.h b/session.h
index cd12f495..ea914425 100644
--- a/session.h
+++ b/session.h
@@ -115,6 +115,7 @@ struct systemtap_session
bool tapset_compile_coverage;
bool need_uprobes;
bool load_only; // flight recorder mode
+ bool unprivileged;
// NB: It is very important for all of the above (and below) fields
// to be cleared in the systemtap_session ctor (elaborate.cxx)
diff --git a/stap-env b/stap-env
index 8d765ae6..ceeca465 100644..100755
--- a/stap-env
+++ b/stap-env
@@ -25,7 +25,11 @@ stap_avahi_service_tag=_stap._tcp
# NSS certificate databases
stap_root_ssl_db=$stap_sysconfdir/systemtap/ssl
-stap_user_ssl_db=$HOME/.systemtap/ssl
+if test "X$SYSTEMTAP_DIR" = "X"; then
+ stap_user_ssl_db=$HOME/.systemtap/ssl
+else
+ stap_user_ssl_db=$SYSTEMTAP_DIR/ssl
+fi
if test $EUID = 0; then
stap_ssl_db=$stap_root_ssl_db
diff --git a/staptree.cxx b/staptree.cxx
index 8a589167..aa37b754 100644
--- a/staptree.cxx
+++ b/staptree.cxx
@@ -10,6 +10,7 @@
#include "staptree.h"
#include "parse.h"
#include "util.h"
+#include "session.h"
#include <iostream>
#include <typeinfo>
@@ -1735,6 +1736,14 @@ functioncall_traversing_visitor::visit_functioncall (functioncall* e)
void
varuse_collecting_visitor::visit_embeddedcode (embeddedcode *s)
{
+ assert (current_function); // only they get embedded code
+
+ // Don't allow embedded C functions in unprivileged mode unless
+ // they are tagged with /* unprivileged */
+ if (session.unprivileged && s->code.find ("/* unprivileged */") == string::npos)
+ throw semantic_error ("function may not be used when --unprivileged is specified",
+ current_function->tok);
+
// We want to elide embedded-C functions when possible. For
// example, each $target variable access is expanded to an
// embedded-C function call. Yet, for safety reasons, we should
@@ -1745,7 +1754,6 @@ varuse_collecting_visitor::visit_embeddedcode (embeddedcode *s)
// $target variables as rvalues will have this; lvalues won't.
// Also, explicit side-effect-free tapset functions will have this.
- assert (current_function); // only they get embedded code
if (s->code.find ("/* pure */") != string::npos)
return;
diff --git a/staptree.h b/staptree.h
index c9b2bdce..f1d43403 100644
--- a/staptree.h
+++ b/staptree.h
@@ -23,6 +23,8 @@ extern "C" {
}
struct token; // parse.h
+struct systemtap_session; // session.h
+
struct semantic_error: public std::runtime_error
{
const token* tok1;
@@ -778,12 +780,14 @@ struct functioncall_traversing_visitor: public traversing_visitor
// the elaboration-time optimizer pass.
struct varuse_collecting_visitor: public functioncall_traversing_visitor
{
+ systemtap_session& session;
std::set<vardecl*> read;
std::set<vardecl*> written;
bool embedded_seen;
expression* current_lvalue;
expression* current_lrvalue;
- varuse_collecting_visitor():
+ varuse_collecting_visitor(systemtap_session& s):
+ session (s),
embedded_seen (false),
current_lvalue(0),
current_lrvalue(0) {}
diff --git a/systemtap.spec b/systemtap.spec
index a8e0d9da..eae8a2a2 100644
--- a/systemtap.spec
+++ b/systemtap.spec
@@ -322,6 +322,8 @@ exit 0
%{_bindir}/stap-client
%{_bindir}/stap-env
%{_bindir}/stap-find-servers
+%{_bindir}/stap-authorize-cert
+%{_bindir}/stap-authorize-server-cert
%{_bindir}/stap-client-connect
%{_mandir}/man8/stap-server.8*
diff --git a/tapset-been.cxx b/tapset-been.cxx
index d695bdf3..99b59574 100644
--- a/tapset-been.cxx
+++ b/tapset-been.cxx
@@ -215,14 +215,30 @@ register_tapset_been(systemtap_session& s)
{
match_node* root = s.pattern_root;
- root->bind(TOK_BEGIN)->bind(new be_builder(BEGIN));
- root->bind_num(TOK_BEGIN)->bind(new be_builder(BEGIN));
- root->bind(TOK_END)->bind(new be_builder(END));
- root->bind_num(TOK_END)->bind(new be_builder(END));
- root->bind(TOK_ERROR)->bind(new be_builder(ERROR));
- root->bind_num(TOK_ERROR)->bind(new be_builder(ERROR));
-
- root->bind(TOK_NEVER)->bind(new never_builder());
+ root->bind(TOK_BEGIN)
+ ->allow_unprivileged()
+ ->bind(new be_builder(BEGIN));
+ root->bind_num(TOK_BEGIN)
+ ->allow_unprivileged()
+ ->bind(new be_builder(BEGIN));
+
+ root->bind(TOK_END)
+ ->allow_unprivileged()
+ ->bind(new be_builder(END));
+ root->bind_num(TOK_END)
+ ->allow_unprivileged()
+ ->bind(new be_builder(END));
+
+ root->bind(TOK_ERROR)
+ ->allow_unprivileged()
+ ->bind(new be_builder(ERROR));
+ root->bind_num(TOK_ERROR)
+ ->allow_unprivileged()
+ ->bind(new be_builder(ERROR));
+
+ root->bind(TOK_NEVER)
+ ->allow_unprivileged()
+ ->bind(new never_builder());
}
/* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
diff --git a/tapset-timers.cxx b/tapset-timers.cxx
index 1dc0acac..565a54e8 100644
--- a/tapset-timers.cxx
+++ b/tapset-timers.cxx
@@ -593,32 +593,71 @@ register_tapset_timers(systemtap_session& s)
root = root->bind(TOK_TIMER);
- root->bind_num("s")->bind(builder);
- root->bind_num("s")->bind_num("randomize")->bind(builder);
- root->bind_num("sec")->bind(builder);
- root->bind_num("sec")->bind_num("randomize")->bind(builder);
-
- root->bind_num("ms")->bind(builder);
- root->bind_num("ms")->bind_num("randomize")->bind(builder);
- root->bind_num("msec")->bind(builder);
- root->bind_num("msec")->bind_num("randomize")->bind(builder);
-
- root->bind_num("us")->bind(builder);
- root->bind_num("us")->bind_num("randomize")->bind(builder);
- root->bind_num("usec")->bind(builder);
- root->bind_num("usec")->bind_num("randomize")->bind(builder);
-
- root->bind_num("ns")->bind(builder);
- root->bind_num("ns")->bind_num("randomize")->bind(builder);
- root->bind_num("nsec")->bind(builder);
- root->bind_num("nsec")->bind_num("randomize")->bind(builder);
-
- root->bind_num("jiffies")->bind(builder);
- root->bind_num("jiffies")->bind_num("randomize")->bind(builder);
-
- root->bind_num("hz")->bind(builder);
-
- root->bind("profile")->bind(builder);
+ root->bind_num("s")
+ ->allow_unprivileged()
+ ->bind(builder);
+ root->bind_num("s")->bind_num("randomize")
+ ->allow_unprivileged()
+ ->bind(builder);
+ root->bind_num("sec")
+ ->allow_unprivileged()
+ ->bind(builder);
+ root->bind_num("sec")->bind_num("randomize")
+ ->allow_unprivileged()
+ ->bind(builder);
+
+ root->bind_num("ms")
+ ->allow_unprivileged()
+ ->bind(builder);
+ root->bind_num("ms")->bind_num("randomize")
+ ->allow_unprivileged()
+ ->bind(builder);
+ root->bind_num("msec")
+ ->allow_unprivileged()
+ ->bind(builder);
+ root->bind_num("msec")->bind_num("randomize")
+ ->allow_unprivileged()
+ ->bind(builder);
+
+ root->bind_num("us")
+ ->allow_unprivileged()
+ ->bind(builder);
+ root->bind_num("us")->bind_num("randomize")
+ ->allow_unprivileged()
+ ->bind(builder);
+ root->bind_num("usec")
+ ->allow_unprivileged()
+ ->bind(builder);
+ root->bind_num("usec")->bind_num("randomize")
+ ->allow_unprivileged()
+ ->bind(builder);
+
+ root->bind_num("ns")
+ ->allow_unprivileged()
+ ->bind(builder);
+ root->bind_num("ns")->bind_num("randomize")
+ ->allow_unprivileged()
+ ->bind(builder);
+ root->bind_num("nsec")
+ ->allow_unprivileged()
+ ->bind(builder);
+ root->bind_num("nsec")->bind_num("randomize")
+ ->allow_unprivileged()
+ ->bind(builder);
+
+ root->bind_num("jiffies")
+ ->allow_unprivileged()
+ ->bind(builder);
+ root->bind_num("jiffies")->bind_num("randomize")
+ ->allow_unprivileged()
+ ->bind(builder);
+
+ root->bind_num("hz")
+ ->allow_unprivileged()
+ ->bind(builder);
+
+ root->bind("profile")
+ ->bind(builder);
}
diff --git a/tapset/logging.stp b/tapset/logging.stp
index d2cca612..91f9672b 100644
--- a/tapset/logging.stp
+++ b/tapset/logging.stp
@@ -8,21 +8,21 @@
// send a string out with a newline
// Deprecated. print* functions are much more efficient.
-function log (msg:string) %{
+function log (msg:string) %{ /* unprivileged */
_stp_printf ("%s\n", THIS->msg);
%}
-function warn (msg:string) %{
+function warn (msg:string) %{ /* unprivileged */
_stp_warn ("%s", THIS->msg);
%}
// NB: exit() does *not* cause immediate return from current function/probe
-function exit () %{
+function exit () %{ /* unprivileged */
atomic_set (&session_state, STAP_SESSION_STOPPING);
_stp_exit ();
%}
-function error (msg:string) %{
+function error (msg:string) %{ /* unprivileged */
/* This is an assignment of a local char[] to a global char*.
It would normally be just as unsafe as returning a pointer to
a local variable from a function. However, the translated
diff --git a/tapset/timestamp.stp b/tapset/timestamp.stp
index 0b9d350a..1980932a 100644
--- a/tapset/timestamp.stp
+++ b/tapset/timestamp.stp
@@ -16,7 +16,7 @@
*
* Return the processor cycle counter value, or 0 if unavailable.
*/
-function get_cycles:long () %{ /* pure */
+function get_cycles:long () %{ /* pure */ /* unprivileged */
cycles_t c = get_cycles();
THIS->__retvalue = (int64_t) c;
%}
diff --git a/tapsets.cxx b/tapsets.cxx
index a105526c..b1ca2998 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -359,11 +359,14 @@ struct dwarf_derived_probe: public derived_probe
// Pattern registration helpers.
static void register_statement_variants(match_node * root,
- dwarf_builder * dw);
+ dwarf_builder * dw,
+ bool unprivileged_ok_p = false);
static void register_function_variants(match_node * root,
- dwarf_builder * dw);
+ dwarf_builder * dw,
+ bool unprivileged_ok_p = false);
static void register_function_and_statement_variants(match_node * root,
- dwarf_builder * dw);
+ dwarf_builder * dw,
+ bool unprivileged_ok_p = false);
static void register_patterns(systemtap_session& s);
};
@@ -2463,6 +2466,9 @@ void dwarf_cast_expanding_visitor::filter_special_modules(string& module)
void dwarf_cast_expanding_visitor::visit_cast_op (cast_op* e)
{
+ if (s.unprivileged)
+ throw semantic_error("typecasting may not be used when --unprivileged is specified", e->tok);
+
bool lvalue = is_active_lvalue(e);
if (lvalue && !s.guru_mode)
throw semantic_error("write to typecast value not permitted", e->tok);
@@ -2812,25 +2818,28 @@ dwarf_derived_probe::printargs(std::ostream &o) const
void
dwarf_derived_probe::register_statement_variants(match_node * root,
- dwarf_builder * dw)
+ dwarf_builder * dw,
+ bool unprivileged_ok_p)
{
- root->bind(dw);
+ root->allow_unprivileged(unprivileged_ok_p)->bind(dw);
}
void
dwarf_derived_probe::register_function_variants(match_node * root,
- dwarf_builder * dw)
-{
- root->bind(dw);
- root->bind(TOK_INLINE)->bind(dw);
- root->bind(TOK_CALL)->bind(dw);
- root->bind(TOK_RETURN)->bind(dw);
- root->bind(TOK_RETURN)->bind_num(TOK_MAXACTIVE)->bind(dw);
+ dwarf_builder * dw,
+ bool unprivileged_ok_p)
+{
+ root->allow_unprivileged(unprivileged_ok_p)->bind(dw);
+ root->bind(TOK_INLINE)->allow_unprivileged(unprivileged_ok_p)->bind(dw);
+ root->bind(TOK_CALL)->allow_unprivileged(unprivileged_ok_p)->bind(dw);
+ root->bind(TOK_RETURN)->allow_unprivileged(unprivileged_ok_p)->bind(dw);
+ root->bind(TOK_RETURN)->bind_num(TOK_MAXACTIVE)->allow_unprivileged(unprivileged_ok_p)->bind(dw);
}
void
dwarf_derived_probe::register_function_and_statement_variants(match_node * root,
- dwarf_builder * dw)
+ dwarf_builder * dw,
+ bool unprivileged_ok_p)
{
// Here we match 4 forms:
//
@@ -2839,10 +2848,10 @@ dwarf_derived_probe::register_function_and_statement_variants(match_node * root,
// .statement("foo")
// .statement(0xdeadbeef)
- register_function_variants(root->bind_str(TOK_FUNCTION), dw);
- register_function_variants(root->bind_num(TOK_FUNCTION), dw);
- register_statement_variants(root->bind_str(TOK_STATEMENT), dw);
- register_statement_variants(root->bind_num(TOK_STATEMENT), dw);
+ register_function_variants(root->bind_str(TOK_FUNCTION), dw, unprivileged_ok_p);
+ register_function_variants(root->bind_num(TOK_FUNCTION), dw, unprivileged_ok_p);
+ register_statement_variants(root->bind_str(TOK_STATEMENT), dw, unprivileged_ok_p);
+ register_statement_variants(root->bind_num(TOK_STATEMENT), dw, unprivileged_ok_p);
}
void
@@ -2859,8 +2868,7 @@ dwarf_derived_probe::register_patterns(systemtap_session& s)
root->bind(TOK_KERNEL)->bind_num(TOK_STATEMENT)->bind(TOK_ABSOLUTE)->bind(dw);
root->bind(TOK_KERNEL)->bind_str(TOK_FUNCTION)->bind_str(TOK_LABEL)->bind(dw);
root->bind_str(TOK_PROCESS)->bind_str(TOK_FUNCTION)->bind_str(TOK_LABEL)->bind(dw);
-
- register_function_and_statement_variants(root->bind_str(TOK_PROCESS), dw);
+ register_function_and_statement_variants(root->bind_str(TOK_PROCESS), dw, false/*!unprivileged_ok_p*/);
root->bind_str(TOK_PROCESS)->bind_str(TOK_MARK)->bind(dw);
root->bind_str(TOK_PROCESS)->bind_num(TOK_MARK)->bind(dw);
}
@@ -6093,7 +6101,6 @@ register_standard_tapsets(systemtap_session & s)
register_tapset_timers(s);
register_tapset_utrace(s);
-
// dwarf-based kprobe/uprobe parts
dwarf_derived_probe::register_patterns(s);
diff --git a/testsuite/systemtap.base/optim_arridx.exp b/testsuite/systemtap.base/optim_arridx.exp
index 1f3f4371..c33952a6 100644
--- a/testsuite/systemtap.base/optim_arridx.exp
+++ b/testsuite/systemtap.base/optim_arridx.exp
@@ -10,7 +10,7 @@ elide_global_a:long
elide_global_b:long
# functions
exit:unknown ()
-%{
+%{ /* unprivileged */
atomic_set (&session_state, STAP_SESSION_STOPPING);
_stp_exit ();
%}
diff --git a/translate.cxx b/translate.cxx
index a26e4085..4a6a10b5 100644
--- a/translate.cxx
+++ b/translate.cxx
@@ -57,7 +57,8 @@ struct c_unparser: public unparser, public visitor
c_unparser (systemtap_session* ss):
session (ss), o (ss->op), current_probe(0), current_function (0),
- tmpvar_counter (0), label_counter (0) {}
+ tmpvar_counter (0), label_counter (0),
+ vcv_needs_global_locks (*ss) {}
~c_unparser () {}
void emit_map_type_instantiations ();
@@ -1087,7 +1088,6 @@ c_unparser::emit_functionsig (functiondecl* v)
}
-
void
c_unparser::emit_module_init ()
{
@@ -1131,6 +1131,7 @@ c_unparser::emit_module_init ()
o->newline() << "if (_stp_module_check()) rc = -EINVAL;";
o->newline(-1) << "}";
+
o->newline() << "if (rc) goto out;";
// initialize gettimeofday (if needed)
@@ -1600,7 +1601,7 @@ c_unparser::emit_probe (derived_probe* v)
v->emit_probe_local_init(o);
// emit all read/write locks for global variables
- varuse_collecting_visitor vut;
+ varuse_collecting_visitor vut(*session);
if (v->needs_global_locks ())
{
v->body->visit (& vut);
diff --git a/translate.h b/translate.h
index fdff9521..d1bff678 100644
--- a/translate.h
+++ b/translate.h
@@ -1,5 +1,5 @@
// -*- C++ -*-
-// Copyright (C) 2005 Red Hat Inc.
+// Copyright (C) 2005, 2009 Red Hat Inc.
//
// This file is part of systemtap, and is free software. You can
// redistribute it and/or modify it under the terms of the GNU General
diff --git a/util.cxx b/util.cxx
index 23deb37b..495d2f5a 100644
--- a/util.cxx
+++ b/util.cxx
@@ -52,6 +52,30 @@ get_home_directory(void)
}
+// Get the size of a file in bytes
+size_t
+get_file_size(const string &path)
+{
+ struct stat file_info;
+
+ if (stat(path.c_str(), &file_info) == 0)
+ return file_info.st_size;
+ else
+ return 0;
+}
+
+// Get the size of a file in bytes
+bool
+file_exists (const string &path)
+{
+ struct stat file_info;
+
+ if (stat(path.c_str(), &file_info) == 0)
+ return true;
+
+ return false;
+}
+
// Copy a file. The copy is done via a temporary file and atomic
// rename.
int
diff --git a/util.h b/util.h
index 63e41f9a..4921cef7 100644
--- a/util.h
+++ b/util.h
@@ -6,6 +6,8 @@
#include <cctype>
const char *get_home_directory(void);
+size_t get_file_size(const std::string &path);
+bool file_exists (const std::string &path);
int copy_file(const char *src, const char *dest);
int create_dir(const char *dir);
int remove_file_or_dir(const char *dir);