summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cache.cxx24
-rw-r--r--runtime/staprun/common.c1
-rw-r--r--runtime/staprun/modverify.c43
-rw-r--r--runtime/staprun/modverify.h7
-rw-r--r--runtime/staprun/staprun.c18
-rw-r--r--runtime/staprun/staprun.h1
-rw-r--r--runtime/staprun/staprun_funcs.c27
-rw-r--r--runtime/transport/transport.c4
-rwxr-xr-xstap-authorize-server-cert2
-rwxr-xr-xstap-authorize-signing-cert2
-rwxr-xr-xstap-client2
-rwxr-xr-xstap-find-or-start-server2
-rwxr-xr-xstap-find-servers2
-rwxr-xr-xstap-gen-cert2
-rwxr-xr-xstap-server2
-rwxr-xr-xstap-serverd2
-rwxr-xr-xstap-start-server2
-rw-r--r--testsuite/lib/systemtap.exp2
-rw-r--r--translate.cxx19
19 files changed, 108 insertions, 56 deletions
diff --git a/cache.cxx b/cache.cxx
index 76e9faf8..1e4d7f18 100644
--- a/cache.cxx
+++ b/cache.cxx
@@ -69,7 +69,7 @@ add_to_cache(systemtap_session& s)
}
#if HAVE_NSS
- // This is the name of the cached module signatire.
+ // This is the name of the cached module signature.
string module_signature_dest_path = s.hash_path;
module_signature_dest_path += ".sgn";
@@ -133,6 +133,10 @@ get_from_cache(systemtap_session& s)
string module_dest_path = s.tmpdir + "/" + s.module_name + ".ko";
string c_src_path = s.hash_path;
int fd_stapconf, fd_module, fd_c;
+#if HAVE_NSS
+ string hash_signature_path = s.hash_path + ".sgn";
+ int fd_signature;
+#endif
if (c_src_path.rfind(".ko") == (c_src_path.size() - 3))
c_src_path.resize(c_src_path.size() - 3);
@@ -202,6 +206,24 @@ get_from_cache(systemtap_session& s)
close(fd_c);
return false;
}
+#if HAVE_NSS
+ // See if module signature exists. It's not an error if it doesn't. It just
+ // means that the module is unsigned.
+ fd_signature = open(hash_signature_path.c_str(), O_RDONLY);
+ if (fd_signature != -1) {
+ string signature_dest_path = module_dest_path + ".sgn";
+ close(fd_signature);
+ if (copy_file(hash_signature_path.c_str(), signature_dest_path.c_str()) != 0)
+ {
+ cerr << "Copy failed (\"" << hash_signature_path << "\" to \""
+ << signature_dest_path << "\"): " << strerror(errno) << endl;
+ unlink(c_src_path.c_str());
+ close(fd_module);
+ close(fd_c);
+ return false;
+ }
+ }
+#endif
}
// We're done with these file handles.
diff --git a/runtime/staprun/common.c b/runtime/staprun/common.c
index 26b166c2..6c199616 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 688734c0..d9ccc094 100644
--- a/runtime/staprun/modverify.c
+++ b/runtime/staprun/modverify.c
@@ -29,6 +29,7 @@
#include <certt.h>
#include "nsscommon.h"
+#include "modverify.h"
static int
verify_it (const char *inputName, const char *signatureName, SECKEYPublicKey *pubKey)
@@ -48,7 +49,7 @@ verify_it (const char *inputName, const char *signatureName, SECKEYPublicKey *pu
{
fprintf (stderr, "Unable to obtain information on the signature file %s.\n", signatureName);
nssError ();
- return -1;
+ return MODULE_UNTRUSTED; /* Not signed */
}
/* Open the signature file. */
@@ -57,7 +58,7 @@ verify_it (const char *inputName, const char *signatureName, SECKEYPublicKey *pu
{
fprintf (stderr, "Could not open the signature file %s\n.", signatureName);
nssError ();
- return -1;
+ return MODULE_CHECK_ERROR;
}
/* Allocate space to read the signature file. */
@@ -66,7 +67,7 @@ verify_it (const char *inputName, const char *signatureName, SECKEYPublicKey *pu
{
fprintf (stderr, "Unable to allocate memory for the signature in %s.\n", signatureName);
nssError ();
- return -1;
+ return MODULE_CHECK_ERROR;
}
/* Read the signature. */
@@ -74,18 +75,18 @@ verify_it (const char *inputName, const char *signatureName, SECKEYPublicKey *pu
if (numBytes == 0) /* EOF */
{
fprintf (stderr, "EOF reading signature file %s.\n", signatureName);
- return -1;
+ return MODULE_CHECK_ERROR;
}
if (numBytes < 0)
{
fprintf (stderr, "Error reading signature file %s.\n", signatureName);
nssError ();
- return -1;
+ return MODULE_CHECK_ERROR;
}
if (numBytes != info.size)
{
fprintf (stderr, "Incomplete data while reading signature file %s.\n", signatureName);
- return -1;
+ return MODULE_CHECK_ERROR;
}
signature.len = info.size;
@@ -97,10 +98,10 @@ verify_it (const char *inputName, const char *signatureName, SECKEYPublicKey *pu
SEC_OID_UNKNOWN, NULL, NULL);
if (! vfy)
{
- fprintf (stderr, "Unable to create verification context while verifying %s using the signature in %s.\n",
- inputName, signatureName);
- nssError ();
- return -1;
+ /* The key does not match the signature. This is not an error. It just means
+ we are currently trying the wrong certificate/key. i.e. the module
+ remains untrusted for now. */
+ return MODULE_UNTRUSTED;
}
/* Begin the verification process. */
@@ -110,7 +111,7 @@ verify_it (const char *inputName, const char *signatureName, SECKEYPublicKey *pu
fprintf (stderr, "Unable to initialize verification context while verifying %s using the signature in %s.\n",
inputName, signatureName);
nssError ();
- return -1;
+ return MODULE_CHECK_ERROR;
}
/* Now read the data and add it to the signature. */
@@ -119,7 +120,7 @@ verify_it (const char *inputName, const char *signatureName, SECKEYPublicKey *pu
{
fprintf (stderr, "Could not open module file %s.\n", inputName);
nssError ();
- return -1;
+ return MODULE_CHECK_ERROR;
}
for (;;)
@@ -132,7 +133,7 @@ verify_it (const char *inputName, const char *signatureName, SECKEYPublicKey *pu
{
fprintf (stderr, "Error reading module file %s.\n", inputName);
nssError ();
- return -1;
+ return MODULE_CHECK_ERROR;
}
/* Add the data to the signature. */
@@ -141,7 +142,7 @@ verify_it (const char *inputName, const char *signatureName, SECKEYPublicKey *pu
{
fprintf (stderr, "Error while verifying module file %s.\n", inputName);
nssError ();
- return -1;
+ return MODULE_CHECK_ERROR;
}
}
@@ -152,10 +153,10 @@ verify_it (const char *inputName, const char *signatureName, SECKEYPublicKey *pu
if (secStatus != SECSuccess) {
fprintf (stderr, "Unable to verify signed module %s. It may have been altered since it was created.\n", inputName);
nssError ();
- return 0;
+ return MODULE_ALTERED;
}
- return 1;
+ return MODULE_OK;
}
int verify_module (const char *module_name, const char *signature_name)
@@ -178,7 +179,7 @@ int verify_module (const char *module_name, const char *signature_name)
fprintf (stderr, "Unable to initialize nss library using the database in %s.\n",
dbdir);
nssError ();
- return -1;
+ return MODULE_CHECK_ERROR;
}
certList = PK11_ListCerts (PK11CertListAll, NULL);
@@ -187,7 +188,7 @@ int verify_module (const char *module_name, const char *signature_name)
fprintf (stderr, "Unable to find certificates in the certificate database in %s.\n",
dbdir);
nssError ();
- return -1;
+ return MODULE_UNTRUSTED;
}
/* We need to look at each certificate in the database. */
@@ -203,13 +204,13 @@ int verify_module (const char *module_name, const char *signature_name)
fprintf (stderr, "Unable to extract public key from the certificate with nickname %s from the certificate database in %s.\n",
cert->nickname, dbdir);
nssError ();
- return -1;
+ return MODULE_CHECK_ERROR;
}
/* Verify the file. */
rc = verify_it (module_name, signature_name, pubKey);
- if (rc == 1)
- break; /* Verified! */
+ if (rc == MODULE_OK || rc == MODULE_ALTERED || rc == MODULE_CHECK_ERROR)
+ break; /* resolved or error */
}
/* Shutdown NSS and exit NSPR gracefully. */
diff --git a/runtime/staprun/modverify.h b/runtime/staprun/modverify.h
index ad212e2b..9abf62d4 100644
--- a/runtime/staprun/modverify.h
+++ b/runtime/staprun/modverify.h
@@ -1 +1,8 @@
int verify_module (const char *module_name, const char *signature_name);
+
+/* return codes for verify_module. */
+#define MODULE_OK 1
+#define MODULE_UNTRUSTED 0
+#define MODULE_CHECK_ERROR -1
+#define MODULE_ALTERED -2
+
diff --git a/runtime/staprun/staprun.c b/runtime/staprun/staprun.c
index 42b72ff1..917990dc 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 acc533b2..5159f1bd 100644
--- a/runtime/staprun/staprun.h
+++ b/runtime/staprun/staprun.h
@@ -166,6 +166,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 020bb312..6e72fd72 100644
--- a/runtime/staprun/staprun_funcs.c
+++ b/runtime/staprun/staprun_funcs.c
@@ -20,6 +20,7 @@
#include <sys/utsname.h>
#include <grp.h>
#include <pwd.h>
+#include <assert.h>
extern long init_module(void *, unsigned long, const char *);
@@ -225,18 +226,18 @@ check_signature(void)
/* Use realpath() to canonicalize the module path. */
if (realpath(modpath, module_realpath) == NULL) {
perr("Unable to canonicalize signature path \"%s\"", modpath);
- return -1;
+ return MODULE_CHECK_ERROR;
}
/* Now add the .sgn suffix to get the signature file name. */
if (strlen (module_realpath) > PATH_MAX - 4) {
err("Path \"%s\" is too long.", modpath);
- return -1;
+ return MODULE_CHECK_ERROR;
}
sprintf (signature_realpath, "%s.sgn", module_realpath);
- dbug(2, "verify_module (%s, %s)\n", module_realpath, signature_realpath);
rc = verify_module (module_realpath, signature_realpath);
+
dbug(2, "verify_module returns %d\n", rc);
return rc;
@@ -419,8 +420,10 @@ check_groups (void)
gid = stapusr_gid;
}
- if (gid != stapusr_gid)
+ if (gid != stapusr_gid) {
+ unprivileged_user = 1;
return 0;
+ }
}
/* At this point the user is only a member of the 'stapusr'
@@ -450,6 +453,14 @@ int check_permissions(void)
int check_groups_rc;
int check_signature_rc = 0;
+#if HAVE_NSS
+ /* Attempt to verify the module against its signature. Return failure
+ if the module has been tampered with (altered). */
+ check_signature_rc = check_signature ();
+ if (check_signature_rc == MODULE_ALTERED)
+ return 0;
+#endif
+
/* If we're root, we can do anything. */
if (getuid() == 0)
return 1;
@@ -459,15 +470,17 @@ int check_permissions(void)
if (check_groups_rc == 1)
return 1;
-#if HAVE_NSS
/* 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. */
- check_signature_rc = check_signature ();
- if (check_signature_rc == 1)
+#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");
diff --git a/runtime/transport/transport.c b/runtime/transport/transport.c
index 762c0a92..1ab49ae2 100644
--- a/runtime/transport/transport.c
+++ b/runtime/transport/transport.c
@@ -41,6 +41,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/stap-authorize-server-cert b/stap-authorize-server-cert
index 058e7ebb..d5f9c2e6 100755
--- a/stap-authorize-server-cert
+++ b/stap-authorize-server-cert
@@ -11,7 +11,7 @@
# later version.
# Initialize the environment
-. stap-env
+. `dirname $0`/stap-env
certfile=$1
certdb=$2
diff --git a/stap-authorize-signing-cert b/stap-authorize-signing-cert
index dfcf1a94..429d7fa5 100755
--- a/stap-authorize-signing-cert
+++ b/stap-authorize-signing-cert
@@ -11,7 +11,7 @@
# later version.
# Initialize the environment
-. stap-env
+. `dirname $0`/stap-env
certfile=$1
certdb=$2
diff --git a/stap-client b/stap-client
index c8664852..c3afab89 100755
--- a/stap-client
+++ b/stap-client
@@ -22,7 +22,7 @@ trap 'interrupt' SIGINT
trap 'ignore_signal' SIGHUP SIGPIPE
# Initialize the environment
-. stap-env
+. `dirname $0`/stap-env
#-----------------------------------------------------------------------------
# Helper functions.
diff --git a/stap-find-or-start-server b/stap-find-or-start-server
index 28fcfa8c..131133ef 100755
--- a/stap-find-or-start-server
+++ b/stap-find-or-start-server
@@ -18,7 +18,7 @@
# Otherwise, it echoes -1
# Initialize the environment
-. stap-env
+. `dirname $0`/stap-env
# Is there a server available?
${stap_exec_prefix}stap-find-servers >/dev/null 2>&1 && echo 0 && exit 0
diff --git a/stap-find-servers b/stap-find-servers
index e0838708..77cd267a 100755
--- a/stap-find-servers
+++ b/stap-find-servers
@@ -13,7 +13,7 @@
# network. Information about each server found is printed to stdout.
# Initialize the environment
-. stap-env
+. `dirname $0`/stap-env
#-----------------------------------------------------------------------------
# Helper functions.
diff --git a/stap-gen-cert b/stap-gen-cert
index bf87b572..940779eb 100755
--- a/stap-gen-cert
+++ b/stap-gen-cert
@@ -11,7 +11,7 @@
# later version.
# Initialize the environment
-. stap-env
+. `dirname $0`/stap-env
# Obtain a password from stdin and echo it.
function user_enter_password
diff --git a/stap-server b/stap-server
index 76130bb1..316cc954 100755
--- a/stap-server
+++ b/stap-server
@@ -17,7 +17,7 @@
trap 'terminate' SIGTERM SIGINT
# Initialize the environment
-. stap-env
+. `dirname $0`/stap-env
#-----------------------------------------------------------------------------
# Helper functions.
diff --git a/stap-serverd b/stap-serverd
index 04ef54c3..16869e89 100755
--- a/stap-serverd
+++ b/stap-serverd
@@ -17,7 +17,7 @@
trap 'terminate' SIGTERM SIGINT
# Initialize the environment
-. stap-env
+. `dirname $0`/stap-env
#-----------------------------------------------------------------------------
# Helper functions.
diff --git a/stap-start-server b/stap-start-server
index bc441545..6471db96 100755
--- a/stap-start-server
+++ b/stap-start-server
@@ -13,7 +13,7 @@
# process id, if successful.
# Initialize the environment
-. stap-env
+. `dirname $0`/stap-env
# start the server
${stap_exec_prefix}stap-serverd "$@" </dev/null >/dev/null 2>&1 &
diff --git a/testsuite/lib/systemtap.exp b/testsuite/lib/systemtap.exp
index 5311be7b..43116a85 100644
--- a/testsuite/lib/systemtap.exp
+++ b/testsuite/lib/systemtap.exp
@@ -128,8 +128,10 @@ proc setup_server {} {
# The server does not call this instance of 'stap'
if {[installtest_p]} then {
exec /bin/cp -p [exec which stap-client] $net_path/stap
+ exec /bin/cp -p [exec which stap-env] $net_path/stap-env
} else {
exec /bin/cp -p $srcdir/../stap-client $net_path/stap
+ exec /bin/cp -p $srcdir/../stap-env $net_path/stap-env
}
set env(PATH) "$net_path:$env(PATH)"
diff --git a/translate.cxx b/translate.cxx
index 1a86dcd2..95986924 100644
--- a/translate.cxx
+++ b/translate.cxx
@@ -1097,26 +1097,17 @@ c_unparser::emit_unprivileged_user_check ()
if (session->unprivileged)
return;
- // Otherwise, generate code to check the user or group. If the user is not
- // root or a member of stapdev or stapusr, then generate an error and
- // unload the module.
+ // Otherwise, generate code to check whether the user is unprivileged.
+ // If so, then generate an error and indicate that the check has failed.
o->newline();
o->newline() << "static int systemtap_unprivileged_user_check (void) {";
-#if 0
- o->newline(1) << "if (_stp_uid == 0)";
- o->newline(1) << "return 0;";
- o->newline(-1) << "stgr = getgrnam(\"stapdev\");";
- o->newline() << "if (stgr != NULL && _stp_gid == stgr->gr_gid)";
- o->newline(1) << "return 0;";
- o->newline(-1) << "stgr = getgrnam(\"stapusr\");";
- o->newline() << "if (stgr != NULL && _stp_gid == stgr->gr_gid)";
+ o->newline(1) << "if (! _stp_unprivileged_user)";
o->newline(1) << "return 0;";
+
o->newline(-1) << "_stp_error (\"You are attempting to run stap as an ordinary user.\");";
o->newline() << "_stp_error (\"Your module must be compiled using the --unprivileged option.\");";
o->newline() << "return 1;";
-#else
- o->newline(1) << "return 0;";
-#endif
+
o->newline(-1) << "}\n";
}