summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Brolley <brolley@redhat.com>2009-06-25 11:50:47 -0400
committerDave Brolley <brolley@redhat.com>2009-06-25 11:50:47 -0400
commit313db8e6d1e62f372d168b7368f220cb432d07d6 (patch)
tree54fdfdbc16b25dfab4e7b3b025971e4adf420e7d
parentf75b6811dee35832309e55a9e3455c40d4c13437 (diff)
downloadsystemtap-steved-313db8e6d1e62f372d168b7368f220cb432d07d6.tar.gz
systemtap-steved-313db8e6d1e62f372d168b7368f220cb432d07d6.tar.xz
systemtap-steved-313db8e6d1e62f372d168b7368f220cb432d07d6.zip
Disallow embedded C in tapset functions ifor unprivileged users unless tagged by /* unprivileged */.
-rw-r--r--elaborate.cxx18
-rw-r--r--staptree.cxx10
-rw-r--r--staptree.h6
-rw-r--r--tapset/logging.stp8
-rw-r--r--tapset/timestamp.stp2
-rw-r--r--tapsets.cxx3
-rw-r--r--testsuite/systemtap.base/optim_arridx.exp2
-rw-r--r--translate.cxx5
8 files changed, 35 insertions, 19 deletions
diff --git a/elaborate.cxx b/elaborate.cxx
index f0c6c5a9..e7ea7b23 100644
--- a/elaborate.cxx
+++ b/elaborate.cxx
@@ -1044,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())
@@ -1199,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);
@@ -1986,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++)
{
@@ -2183,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
{
@@ -2216,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
@@ -2320,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 ())
{
@@ -2384,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);
@@ -2421,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))
@@ -2761,7 +2761,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/staptree.cxx b/staptree.cxx
index 8d251731..df075f44 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>
@@ -1684,6 +1685,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
@@ -1694,7 +1703,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 7e9506bb..7cf482c1 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;
@@ -752,12 +754,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/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 3017e203..0a07e7a8 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -2662,6 +2662,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);
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 5336dc66..172c1287 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 ();
@@ -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);