summaryrefslogtreecommitdiffstats
path: root/runtime/staprun
diff options
context:
space:
mode:
authorDave Brolley <brolley@redhat.com>2009-11-09 14:50:52 -0500
committerDave Brolley <brolley@redhat.com>2009-11-09 14:50:52 -0500
commit64211010978d0e35c80ec7c119f1986a48f97543 (patch)
tree4a9d67ed8f7682cf8eb61686709fd69341394e63 /runtime/staprun
parent5e90af3e298ae39838acedf85f1301806143e920 (diff)
downloadsystemtap-steved-64211010978d0e35c80ec7c119f1986a48f97543.tar.gz
systemtap-steved-64211010978d0e35c80ec7c119f1986a48f97543.tar.xz
systemtap-steved-64211010978d0e35c80ec7c119f1986a48f97543.zip
Don't reference global variable modpath in insert_module and its helpers.
This allows insert_module to to be used for loading the signed uprobes.ko module. Allow the use of $$parms and $$return in uprobes based probes for unprivileged users. Re-add management of module signatures in the cache. Don't know why it was removed.
Diffstat (limited to 'runtime/staprun')
-rw-r--r--runtime/staprun/staprun.c10
-rw-r--r--runtime/staprun/staprun.h22
-rw-r--r--runtime/staprun/staprun_funcs.c85
3 files changed, 81 insertions, 36 deletions
diff --git a/runtime/staprun/staprun.c b/runtime/staprun/staprun.c
index c5651d9a..078be4cf 100644
--- a/runtime/staprun/staprun.c
+++ b/runtime/staprun/staprun.c
@@ -129,14 +129,12 @@ static int enable_uprobes(void)
if (run_as(0, 0, 0, argv[0], argv) == 0)
return 0;
+ /* This module may be signed, so use insert_module to load it. */
snprintf (runtimeko, sizeof(runtimeko), "%s/uprobes/uprobes.ko",
(getenv("SYSTEMTAP_RUNTIME") ?: PKGDATADIR "/runtime"));
dbug(2, "Inserting uprobes module from SystemTap runtime %s.\n", runtimeko);
- i = 0;
- argv[i++] = "/sbin/insmod";
- argv[i++] = runtimeko;
- argv[i] = NULL;
- if (run_as(0, 0, 0, argv[0], argv) == 0)
+ argv[0] = NULL;
+ if (insert_module(runtimeko, NULL, argv, assert_uprobes_module_permissions) == 0)
return 0;
return 1; /* failure */
@@ -150,7 +148,7 @@ static int insert_stap_module(void)
if (snprintf_chk(special_options, sizeof (special_options), "_stp_bufsize=%d", buffer_size))
return -1;
- return insert_module(modpath, special_options, modoptions);
+ return insert_module(modpath, special_options, modoptions, assert_stap_module_permissions);
}
static int remove_module(const char *name, int verb);
diff --git a/runtime/staprun/staprun.h b/runtime/staprun/staprun.h
index 9cdbc861..91761bde 100644
--- a/runtime/staprun/staprun.h
+++ b/runtime/staprun/staprun.h
@@ -131,8 +131,28 @@ time_t read_backlog(int cpu, int fnum);
/* staprun_funcs.c */
void setup_staprun_signals(void);
const char *moderror(int err);
+
+/* insert_module helper functions. */
+typedef void (*assert_permissions_func) (
+ const char *module_path __attribute__ ((unused)),
+ const void *module_data __attribute__ ((unused)),
+ off_t module_size __attribute__ ((unused))
+);
+
+void assert_stap_module_permissions (
+ const char *module_path __attribute__ ((unused)),
+ const void *module_data __attribute__ ((unused)),
+ off_t module_size __attribute__ ((unused))
+);
+
+void assert_uprobes_module_permissions (
+ const char *module_path __attribute__ ((unused)),
+ const void *module_data __attribute__ ((unused)),
+ off_t module_size __attribute__ ((unused))
+);
int insert_module(const char *path, const char *special_options,
- char **options);
+ char **options, assert_permissions_func apf);
+
int mountfs(void);
void start_symbol_thread(void);
void stop_symbol_thread(void);
diff --git a/runtime/staprun/staprun_funcs.c b/runtime/staprun/staprun_funcs.c
index aef8a2da..47ad6a19 100644
--- a/runtime/staprun/staprun_funcs.c
+++ b/runtime/staprun/staprun_funcs.c
@@ -23,7 +23,6 @@
#include <assert.h>
extern long init_module(void *, unsigned long, const char *);
-static void assert_permissions(const void *, off_t);
/* Module errors get translated. */
const char *moderror(int err)
@@ -42,8 +41,12 @@ const char *moderror(int err)
}
}
-int insert_module(const char *path, const char *special_options, char **options)
-{
+int insert_module(
+ const char *path,
+ const char *special_options,
+ char **options,
+ assert_permissions_func assert_permissions
+) {
int i;
long ret;
void *file;
@@ -74,23 +77,23 @@ int insert_module(const char *path, const char *special_options, char **options)
dbug(2, "module options: %s\n", opts);
/* Use realpath() to canonicalize the module path. */
- if (realpath(modpath, module_realpath) == NULL) {
- perr("Unable to canonicalize path \"%s\"", modpath);
+ if (realpath(path, module_realpath) == NULL) {
+ perr("Unable to canonicalize path \"%s\"", path);
return -1;
}
- /* Overwrite the modpath with the canonicalized one, to defeat
+ /* Overwrite the path with the canonicalized one, to defeat
a possible race between path and signature checking below and,
somewhat later, module loading. */
- modpath = strdup (module_realpath);
- if (modpath == NULL) {
+ path = strdup (module_realpath);
+ if (path == NULL) {
_perr("allocating memory failed");
exit (1);
}
/* Open the module file. Work with the open file descriptor from this
point on to avoid TOCTOU problems. */
- fd = open(modpath, O_RDONLY);
+ fd = open(path, O_RDONLY);
if (fd < 0) {
perr("Error opening '%s'", path);
return -1;
@@ -114,8 +117,7 @@ int insert_module(const char *path, const char *special_options, char **options)
/* Check whether this module can be loaded by the current user.
* check_permissions will exit(-1) if permissions are insufficient*/
- assert_permissions (file, sbuf.st_size);
-
+ assert_permissions (path, file, sbuf.st_size);
STAP_PROBE1(staprun, insert__module, path);
/* Actually insert the module */
@@ -239,20 +241,20 @@ int mountfs(void)
* Returns: -1 on errors, 0 on failure, 1 on success.
*/
static int
-check_signature(const void *module_data, off_t module_size)
+check_signature(const char *path, const void *module_data, off_t module_size)
{
char signature_realpath[PATH_MAX];
int rc;
- dbug(2, "checking signature for %s\n", modpath);
+ dbug(2, "checking signature for %s\n", path);
/* Add the .sgn suffix to the canonicalized module path to get the signature
file path. */
- if (strlen (modpath) >= PATH_MAX - 4) {
- err("Path \"%s.sgn\" is too long.", modpath);
+ if (strlen (path) >= PATH_MAX - 4) {
+ err("Path \"%s.sgn\" is too long.", path);
return -1;
}
- sprintf (signature_realpath, "%s.sgn", modpath);
+ sprintf (signature_realpath, "%s.sgn", path);
rc = verify_module (signature_realpath, module_data, module_size);
@@ -270,7 +272,7 @@ check_signature(const void *module_data, off_t module_size)
* Returns: -1 on errors, 0 on failure, 1 on success.
*/
static int
-check_path(void)
+check_path(const char *module_path)
{
char staplib_dir_path[PATH_MAX];
char staplib_dir_realpath[PATH_MAX];
@@ -330,18 +332,18 @@ check_path(void)
if (strlen(staplib_dir_realpath) < (PATH_MAX - 1))
strcat(staplib_dir_realpath, "/");
else {
- err("Path \"%s\" is too long.", modpath);
+ err("Path \"%s\" is too long.", staplib_dir_realpath);
return -1;
}
/* Now we've got two canonicalized paths. Make sure
- * modpath starts with staplib_dir_realpath. */
- if (strncmp(staplib_dir_realpath, modpath,
+ * path starts with staplib_dir_realpath. */
+ if (strncmp(staplib_dir_realpath, module_path,
strlen(staplib_dir_realpath)) != 0) {
err("ERROR: Members of the \"stapusr\" group can only use modules within\n"
" the \"%s\" directory.\n"
" Module \"%s\" does not exist within that directory.\n",
- staplib_dir_path, modpath);
+ staplib_dir_path, module_path);
return 0;
}
return 1;
@@ -359,7 +361,7 @@ check_path(void)
* 1 on success
*/
static int
-check_groups (void)
+check_groups (const char *module_path)
{
gid_t gid, gidlist[NGROUPS_MAX];
gid_t stapdev_gid, stapusr_gid;
@@ -430,7 +432,7 @@ check_groups (void)
* group. Members of the 'stapusr' group can only use modules
* in /lib/modules/KVER/systemtap. Make sure the module path
* is in that directory. */
- return check_path();
+ return check_path (module_path);
}
/*
@@ -445,10 +447,9 @@ check_groups (void)
* 4) anyone can load a module which has been signed by a trusted signer
*
* It is only an error if all 4 levels of checking fail
- *
- * Returns: -1 on errors, 0 on failure, 1 on success.
*/
-void assert_permissions(
+void assert_stap_module_permissions(
+ const char *module_path __attribute__ ((unused)),
const void *module_data __attribute__ ((unused)),
off_t module_size __attribute__ ((unused))
) {
@@ -457,7 +458,7 @@ void assert_permissions(
#if HAVE_NSS
/* Attempt to verify the module against its signature. Return failure
if the module has been tampered with (altered). */
- int check_signature_rc = check_signature (module_data, module_size);
+ int check_signature_rc = check_signature (module_path, module_data, module_size);
if (check_signature_rc == MODULE_ALTERED)
exit(-1);
#endif
@@ -480,7 +481,7 @@ void assert_permissions(
}
/* Check permissions for group membership. */
- check_groups_rc = check_groups ();
+ check_groups_rc = check_groups (module_path);
if (check_groups_rc == 1)
return;
@@ -507,6 +508,32 @@ void assert_permissions(
"For more information, please consult the \"SAFETY AND SECURITY\" section of the \"stap(1)\" manpage\n");
#endif
- /* Combine the return codes. They are either 0 or -1. */
exit(-1);
}
+
+/*
+ * For the uprobes.ko module, if we have NSS, then
+ * check the signature. Otherwise go ahead and load it.
+ */
+void assert_uprobes_module_permissions(
+ const char *module_path __attribute__ ((unused)),
+ const void *module_data __attribute__ ((unused)),
+ off_t module_size __attribute__ ((unused))
+) {
+#if HAVE_NSS
+ /* Attempt to verify the module against its signature. Return failure
+ if the module has been tampered with (altered). */
+ int rc = check_signature (module_path, module_data, module_size);
+ if (rc == MODULE_ALTERED)
+ exit(-1);
+ if (rc == MODULE_OK)
+ return;
+ assert (rc == MODULE_UNTRUSTED || rc == MODULE_CHECK_ERROR);
+ err("Signature verification failed for module %s.\n", module_path);
+ if (rc == MODULE_UNTRUSTED) {
+ err("Run '" BINDIR "/stap-sign-module %s' as root and/or\n", module_path);
+ err("run '" BINDIR "/stap-authorize-signing-cert %s' as root\n",
+ SYSCONFDIR "/systemtap/ssl/server/stap.cert");
+ }
+#endif
+}