diff options
author | Dave Brolley <brolley@redhat.com> | 2009-11-24 14:50:28 -0500 |
---|---|---|
committer | Dave Brolley <brolley@redhat.com> | 2009-11-24 14:50:28 -0500 |
commit | 37f1e3c413aee81f7590de431d232a474eb412ee (patch) | |
tree | e63e690e564fa4d424309fc098cc73674a6b633d /runtime | |
parent | f3c4da447c5b8746e2f756f2ed1dd16c7834bdb2 (diff) | |
download | systemtap-steved-37f1e3c413aee81f7590de431d232a474eb412ee.tar.gz systemtap-steved-37f1e3c413aee81f7590de431d232a474eb412ee.tar.xz systemtap-steved-37f1e3c413aee81f7590de431d232a474eb412ee.zip |
PR 10976, 10984. Loading of signed modules (script module and uprobes) limited to members of stapusr.
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/staprun/staprun_funcs.c | 182 |
1 files changed, 121 insertions, 61 deletions
diff --git a/runtime/staprun/staprun_funcs.c b/runtime/staprun/staprun_funcs.c index 4df1992c..b23d7822 100644 --- a/runtime/staprun/staprun_funcs.c +++ b/runtime/staprun/staprun_funcs.c @@ -22,6 +22,8 @@ #include <pwd.h> #include <assert.h> +typedef int (*check_module_path_func)(const char *module_path); + extern long init_module(void *, unsigned long, const char *); /* Module errors get translated. */ @@ -231,10 +233,7 @@ int mountfs(void) #if HAVE_NSS /* - * Modules which have been signed using a certificate and private key - * corresponding to a certificate and public key in the database in - * the '$sysconfdir/systemtap/staprun' directory may be loaded by - * anyone. + * Check the signature of the given module. * * Returns: -1 on errors, 0 on failure, 1 on success. */ @@ -263,14 +262,15 @@ check_signature(const char *path, const void *module_data, off_t module_size) #endif /* HAVE_NSS */ /* - * Members of the 'stapusr' group can only use "blessed" modules - + * For stap modules which have not been signed by a trusted signer, + * members of the 'stapusr' group can only use the "blessed" modules - * ones in the '/lib/modules/KVER/systemtap' directory. Make sure the * module path is in that directory. * - * Returns: -1 on errors, 0 on failure, 1 on success. + * Returns: -1 on errors, 1 on success. */ static int -check_path(const char *module_path) +check_stap_module_path(const char *module_path) { char staplib_dir_path[PATH_MAX]; char staplib_dir_realpath[PATH_MAX]; @@ -288,39 +288,49 @@ check_path(const char *module_path) /* Validate /lib/modules/KVER/systemtap. */ if (stat(staplib_dir_path, &sb) < 0) { - perr("Members of the \"stapusr\" group can only use modules within\n" + perr("Unable to verify the signature for the module %s.\n" + " Members of the \"stapusr\" group can only use untrusted modules within\n" " the \"%s\" directory.\n" - " Error getting information on that directory", staplib_dir_path); + " Error getting information on that directory", + module_path, staplib_dir_path); return -1; } /* Make sure it is a directory. */ if (! S_ISDIR(sb.st_mode)) { - err("ERROR: Members of the \"stapusr\" group can only use modules within\n" + err("ERROR: Unable to verify the signature for the module %s.\n" + " Members of the \"stapusr\" group can only use untrusted modules within\n" " the \"%s\" directory.\n" - " That path must refer to a directory.\n", staplib_dir_path); + " That path must refer to a directory.\n", + module_path, staplib_dir_path); return -1; } /* Make sure it is owned by root. */ if (sb.st_uid != 0) { - err("ERROR: Members of the \"stapusr\" group can only use modules within\n" + err("ERROR: Unable to verify the signature for the module %s.\n" + " Members of the \"stapusr\" group can only use untrusted modules within\n" " the \"%s\" directory.\n" - " That directory should be owned by root.\n", staplib_dir_path); + " That directory should be owned by root.\n", + module_path, staplib_dir_path); return -1; } /* Make sure it isn't world writable. */ if (sb.st_mode & S_IWOTH) { - err("ERROR: Members of the \"stapusr\" group can only use modules within\n" + err("ERROR: Unable to verify the signature for the module %s.\n" + " Members of the \"stapusr\" group can only use untrusted modules within\n" " the \"%s\" directory.\n" - " That directory should not be world writable.\n", staplib_dir_path); + " That directory should not be world writable.\n", + module_path, staplib_dir_path); return -1; } /* Use realpath() to canonicalize the module directory * path. */ if (realpath(staplib_dir_path, staplib_dir_realpath) == NULL) { - perr("Members of the \"stapusr\" group can only use modules within\n" + perr("Unable to verify the signature for the module %s.\n" + " Members of the \"stapusr\" group can only use untrusted modules within\n" " the \"%s\" directory.\n" - " Unable to canonicalize that directory", staplib_dir_path); + " Unable to canonicalize that directory", + module_path, staplib_dir_path); return -1; } @@ -338,20 +348,34 @@ check_path(const char *module_path) * 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" + err("ERROR: Unable to verify the signature for the module %s.\n" + " Members of the \"stapusr\" group can only use untrusted modules within\n" " the \"%s\" directory.\n" " Module \"%s\" does not exist within that directory.\n", - staplib_dir_path, module_path); - return 0; + module_path, staplib_dir_path, module_path); + return -1; } return 1; } /* + * Members of the 'stapusr' group can load the uprobes module freely, + * since it is loaded from a fixed path in the installed runtime. + * + * Returns: -1 on errors, 0 on failure, 1 on success. + */ +static int +check_uprobes_module_path (const char *module_path __attribute__ ((unused))) +{ + return 1; +} + +/* * Check the user's group membership. * * o members of stapdev can do anything - * o members of stapusr can load modules from /lib/modules/KVER/systemtap + * o members of stapusr can load modules from certain module-specific + * paths. * * Returns: -2 if neither group exists * -1 for other errors @@ -359,7 +383,11 @@ check_path(const char *module_path) * 1 on success */ static int -check_groups (const char *module_path) +check_groups ( + const char *module_path, + int module_signature_status, + check_module_path_func check_path +) { gid_t gid, gidlist[NGROUPS_MAX]; gid_t stapdev_gid, stapusr_gid; @@ -428,8 +456,16 @@ check_groups (const char *module_path) /* At this point the user is only a member of the 'stapusr' * group. Members of the 'stapusr' group can only use modules - * in /lib/modules/KVER/systemtap. Make sure the module path - * is in that directory. */ + * which have been signed by a trusted signer or which, in some cases, + * are at approved paths. */ + if (module_signature_status == MODULE_OK) + return 1; + assert (module_signature_status == MODULE_UNTRUSTED || + module_signature_status == MODULE_CHECK_ERROR); + + /* Could not verify the module's signature, so check whether this module + can be loaded based on its path. check_path is a pointer to a + module-specific function which will do this. */ return check_path (module_path); } @@ -441,8 +477,8 @@ check_groups (const char *module_path) * * 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 + * 3) members of stapusr can load a module which has been signed by a trusted signer + * 4) members of stapusr can load untrusted modules from /lib/modules/KVER/systemtap * * It is only an error if all 4 levels of checking fail */ @@ -452,13 +488,17 @@ void assert_stap_module_permissions( off_t module_size __attribute__ ((unused)) ) { int check_groups_rc; + int check_signature_rc; #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_path, module_data, module_size); + /* Attempt to verify the module against its signature. Exit + immediately if the module has been tampered with (altered). */ + check_signature_rc = check_signature (module_path, module_data, module_size); if (check_signature_rc == MODULE_ALTERED) exit(-1); +#else + /* If we don't have NSS, the stap module is considered untrusted */ + check_signature_rc = MODULE_UNTRUSTED; #endif /* If we're root, we can do anything. */ @@ -479,60 +519,80 @@ void assert_stap_module_permissions( } /* Check permissions for group membership. */ - check_groups_rc = check_groups (module_path); + check_groups_rc = check_groups (module_path, check_signature_rc, check_stap_module_path); if (check_groups_rc == 1) return; - /* The user is an ordinary user. If the module has been signed with - * an authorized certificate and private key, then we will load it for - * anyone. */ + /* Are we are an ordinary user?. */ + if (check_groups_rc == 0) { + err("ERROR: You are trying to run systemtap as a normal user.\n" + "You should either be root, or be part of either " + "group \"stapdev\" or group \"stapusr\".\n"); + if (check_groups_rc == -2) + err("Your system doesn't seem to have either group.\n"); #if HAVE_NSS - if (check_signature_rc == MODULE_OK) - return; - assert (check_signature_rc == MODULE_UNTRUSTED || check_signature_rc == MODULE_CHECK_ERROR); + err("If you are part of the group \"stapusr\", the module must be " + "signed by a trusted signer.\n"); #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"); - if (check_groups_rc == -2) { - 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 exit(-1); } /* - * For the uprobes.ko module, if we have NSS, then - * check the signature. Otherwise go ahead and load it. + * Check the user's permissions. Is he allowed to load the uprobes module? + * + * There are several levels of possible permission: + * + * 1) root can do anything + * 2) members of stapdev can do anything + * 3) members of stapusr can load a uprobes module which has been signed by a + * trusted signer + * + * It is only an error if all 3 levels of checking fail */ void assert_uprobes_module_permissions( const char *module_path __attribute__ ((unused)), const void *module_data __attribute__ ((unused)), off_t module_size __attribute__ ((unused)) ) { + int check_groups_rc; + int check_signature_rc; + #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) + check_signature_rc = check_signature (module_path, module_data, module_size); + if (check_signature_rc == MODULE_ALTERED) exit(-1); - if (rc == MODULE_OK) +#else + /* If we don't have NSS, then the uprobes module is considered trusted. + Otherwise a member of the group 'stapusr' will not be able to load it. + */ + check_signature_rc = MODULE_OK; +#endif + + /* root can still load this module. */ + if (getuid() == 0) 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"); + + /* Members of the groups stapdev and stapusr can still load this module. */ + check_groups_rc = check_groups (module_path, check_signature_rc, check_uprobes_module_path); + if (check_groups_rc == 1) + return; + + /* Check permissions for group membership. */ + if (check_groups_rc == 0) { + err("ERROR: You are trying to load the module %s as a normal user.\n" + "You should either be root, or be part of either " + "group \"stapdev\" or group \"stapusr\".\n", module_path); + if (check_groups_rc == -2) + err("Your system doesn't seem to have either group.\n"); +#if HAVE_NSS + err("If you are part of the group \"stapusr\", the module must be " + "signed by a trusted signer.\n"); +#endif } + exit(-1); -#endif } |