diff options
author | Frank Ch. Eigler <fche@elastic.org> | 2008-09-05 13:02:56 -0400 |
---|---|---|
committer | Frank Ch. Eigler <fche@elastic.org> | 2008-09-05 13:02:56 -0400 |
commit | 337cd273963410c9a1fa46b10287e72c146df054 (patch) | |
tree | a4973f13e83e241ed6c045eeb41bfd5e3a615a95 /runtime/staprun | |
parent | 6fa7bd6e70f8f6d783395399c92a9a13d24ce997 (diff) | |
download | systemtap-steved-337cd273963410c9a1fa46b10287e72c146df054.tar.gz systemtap-steved-337cd273963410c9a1fa46b10287e72c146df054.tar.xz systemtap-steved-337cd273963410c9a1fa46b10287e72c146df054.zip |
remove capabilities logic, cont'd
Diffstat (limited to 'runtime/staprun')
-rw-r--r-- | runtime/staprun/ChangeLog | 8 | ||||
-rw-r--r-- | runtime/staprun/staprun.c | 106 | ||||
-rw-r--r-- | runtime/staprun/staprun.h | 20 | ||||
-rw-r--r-- | runtime/staprun/staprun_funcs.c | 30 |
4 files changed, 73 insertions, 91 deletions
diff --git a/runtime/staprun/ChangeLog b/runtime/staprun/ChangeLog index a4f47880..8b7a116d 100644 --- a/runtime/staprun/ChangeLog +++ b/runtime/staprun/ChangeLog @@ -1,3 +1,11 @@ +2008-09-05 Frank Ch. Eigler <fche@elastic.org> + + * staprun.c (run_as): Teach it to exec too. Update callers. + Always do set[ug]id as dictated. + * staprun.h (do_cap): Remove. Update all callers. + * staprun_funcs.c: Ditto. + * cap.c: Removed. Update headers. + 2008-07-10 Frank Ch. Eigler <fche@elastic.org> PR 6736. diff --git a/runtime/staprun/staprun.c b/runtime/staprun/staprun.c index 664b75ee..f8a08876 100644 --- a/runtime/staprun/staprun.c +++ b/runtime/staprun/staprun.c @@ -1,6 +1,6 @@ /* -*- linux-c -*- * - * staprun.c - SystemTap module loader + * staprun.c - SystemTap module loader * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -34,14 +34,14 @@ extern long delete_module(const char *, unsigned int); int send_relocations (); -static int run_as(uid_t uid, gid_t gid, const char *path, char *const argv[]) +static int run_as(int exec_p, uid_t uid, gid_t gid, const char *path, char *const argv[]) { pid_t pid; int rstatus; if (verbose >= 2) { int i = 0; - err("execing: "); + err(exec_p ? "execing: ": "spawning: "); while (argv[i]) { err("%s ", argv[i]); i++; @@ -49,36 +49,43 @@ static int run_as(uid_t uid, gid_t gid, const char *path, char *const argv[]) err("\n"); } - if ((pid = fork()) < 0) { - _perr("fork"); - return -1; - } else if (pid == 0) { - /* Make sure we run as the full user. If we're - * switching to a non-root user, this won't allow - * that process to switch back to root (since the - * original process is setuid). */ - if (uid != getuid()) { - if (do_cap(CAP_SETGID, setresgid, gid, gid, gid) < 0) { - _perr("setresgid"); - exit(1); - } - if (do_cap(CAP_SETUID, setresuid, uid, uid, uid) < 0) { - _perr("setresuid"); - exit(1); - } - } + if (exec_p) + pid = 0; + else + pid = fork(); + + if (pid < 0) + { + _perr("fork"); + return -1; + } + + if (pid == 0) /* child process, or exec_p */ + { + /* Make sure we run as the full user. If we're + * switching to a non-root user, this won't allow + * that process to switch back to root (since the + * original process is setuid). */ + if (setresgid (gid, gid, gid) < 0) { + _perr("setresgid"); + exit(1); + } + if (setresuid (uid, uid, uid) < 0) { + _perr("setresuid"); + exit(1); + } - /* Actually run the command. */ - if (execv(path, argv) < 0) - perror(path); - _exit(1); - } + /* Actually run the command. */ + if (execv(path, argv) < 0) + perror(path); + _exit(1); + } if (waitpid(pid, &rstatus, 0) < 0) - return -1; + return -1; if (WIFEXITED(rstatus)) - return WEXITSTATUS(rstatus); + return WEXITSTATUS(rstatus); return -1; } @@ -104,14 +111,13 @@ static int enable_uprobes(void) argv[i++] = "unregister_uprobe"; argv[i++] = "/proc/kallsyms"; argv[i] = NULL; - if (run_as(uid, gid, argv[0], argv) == 0) + if (run_as(0, uid, gid, argv[0], argv) == 0) return 0; /* * TODO: If user can't setresuid to root here, staprun will exit. * Is there a situation where that would fail but the subsequent - * attempt to use CAP_SYS_MODULE privileges (in insert_module()) - * would succeed? + * attempt to insert_module() would succeed? */ dbug(2, "Inserting uprobes module from /lib/modules, if any.\n"); i = 0; @@ -119,7 +125,7 @@ static int enable_uprobes(void) argv[i++] = "-q"; argv[i++] = "uprobes"; argv[i] = NULL; - if (run_as(0, 0, argv[0], argv) == 0) + if (run_as(0, 0, 0, argv[0], argv) == 0) return 0; dbug(2, "Inserting uprobes module from SystemTap runtime.\n"); @@ -169,9 +175,9 @@ static int remove_module(const char *name, int verb) } /* Call init_ctl_channel() which actually attempts an open() - * of the control channel. This is better than using access() because + * of the control channel. This is better than using access() because * an open on an already open channel will fail, preventing us from attempting - * to remove an in-use module. + * to remove an in-use module. */ if (init_ctl_channel(name, 0) < 0) { if (verb) @@ -186,7 +192,7 @@ static int remove_module(const char *name, int verb) if (setpriority(PRIO_PROCESS, 0, 0) < 0) _perr("setpriority"); - ret = do_cap(CAP_SYS_MODULE, delete_module, name, 0); + ret = delete_module (name, 0); if (ret != 0) { err("Error removing module '%s': %s.\n", name, strerror(errno)); return 1; @@ -203,9 +209,6 @@ int init_staprun(void) if (mountfs() < 0) return -1; - /* We're done with CAP_SYS_ADMIN. */ - drop_cap(CAP_SYS_ADMIN); - if (delete_mod) exit(remove_module(modname, 1)); else if (!attach_mod) { @@ -269,25 +272,14 @@ int main(int argc, char **argv) exit(1); } - init_cap(); - if (check_permissions() != 1) usage(argv[0]); - /* now bump the priority */ - rc = do_cap(CAP_SYS_NICE, setpriority, PRIO_PROCESS, 0, -10); - /* failure is not fatal in this case */ - if (rc < 0) - _perr("setpriority"); - - /* We're done with CAP_SYS_NICE. */ - drop_cap(CAP_SYS_NICE); - if (init_staprun()) exit(1); argv[0] = PKGLIBDIR "/stapio"; - if (execv(argv[0], argv) < 0) { + if (run_as (1, getuid(), getgid(), argv[0], argv) < 0) { perror(argv[0]); goto err; } @@ -337,7 +329,7 @@ int send_relocation_kernel () FILE* kallsyms = fopen ("/proc/kallsyms", "r"); if (kallsyms == NULL) { - perror("cannot open /proc/kallsyms"); + perror("cannot open /proc/kallsyms"); // ... and the kernel module will almost certainly fail to initialize. } else @@ -404,18 +396,18 @@ void send_relocation_modules () module_section_file = globbuf.gl_pathv[i]; - /* Tokenize the file name. + /* Tokenize the file name. Sample gl_pathv[]: /sys/modules/zlib_deflate/sections/.text Pieces: ^^^^^^^^^^^^ ^^^^^ */ - section_name = rindex (module_section_file, '/'); + section_name = rindex (module_section_file, '/'); if (! section_name) continue; section_name ++; if (!strcmp (section_name, ".")) continue; if (!strcmp (section_name, "..")) continue; - - module_name = index (module_section_file, '/'); + + module_name = index (module_section_file, '/'); if (! module_name) continue; module_name ++; module_name = index (module_name, '/'); @@ -436,7 +428,7 @@ void send_relocation_modules () /* Now we destructively modify the string, but by now the file is open so we won't need the full name again. */ *module_name_end = '\0'; - + send_a_relocation (module_name, section_name, section_address); } @@ -454,7 +446,7 @@ void send_relocation_modules () same time that a probeworthy module is being unloaded. */ } } - + globfree (& globbuf); } diff --git a/runtime/staprun/staprun.h b/runtime/staprun/staprun.h index 0a35fee6..2014ce5b 100644 --- a/runtime/staprun/staprun.h +++ b/runtime/staprun/staprun.h @@ -33,7 +33,6 @@ #include <sys/wait.h> #include <sys/statfs.h> #include <linux/version.h> -#include <sys/capability.h> #define dbug(level, args...) {if (verbose>=level) {fprintf(stderr,"%s:%s:%d ",__name__,__FUNCTION__, __LINE__); fprintf(stderr,args);}} @@ -58,17 +57,6 @@ extern char *__name__; fprintf(stderr, ": %s\n", strerror(_errno)); \ } while (0) #define overflow_error() _err("Internal buffer overflow. Please file a bug report.\n") - -#define do_cap(cap,func,args...) ({ \ - int _rc, _saved_errno; \ - add_cap(cap); \ - _rc = func(args); \ - _saved_errno = errno; \ - del_cap(cap); \ - errno = _saved_errno; \ - _rc; \ - }) \ - /* Error checking version of sprintf() - returns 1 if overflow error */ #define sprintf_chk(str, args...) ({ \ @@ -123,12 +111,6 @@ void close_relayfs(void); int init_oldrelayfs(void); void close_oldrelayfs(int); void setup_signals(void); -/* cap.c */ -void print_cap(char *text); -void init_cap(void); -void add_cap(cap_value_t cap); -void del_cap(cap_value_t cap); -void drop_cap(cap_value_t cap); /* staprun_funcs.c */ void setup_staprun_signals(void); const char *moderror(int err); @@ -147,7 +129,7 @@ void setup_signals(void); int set_clexec(int fd); /* - * variables + * variables */ extern int control_channel; extern int ncpus; diff --git a/runtime/staprun/staprun_funcs.c b/runtime/staprun/staprun_funcs.c index c1cb92b7..8fa95e45 100644 --- a/runtime/staprun/staprun_funcs.c +++ b/runtime/staprun/staprun_funcs.c @@ -43,7 +43,7 @@ int insert_module(const char *path, const char *special_options, char **options) char *opts; int fd, saved_errno; struct stat sbuf; - + dbug(2, "inserting module\n"); if (special_options) @@ -71,7 +71,7 @@ int insert_module(const char *path, const char *special_options, char **options) perr("Error opening '%s'", path); return -1; } - + /* Now that the file is open, figure out how big it is. */ if (fstat(fd, &sbuf) < 0) { _perr("Error stat'ing '%s'", path); @@ -87,9 +87,9 @@ int insert_module(const char *path, const char *special_options, char **options) free(opts); return -1; } - + /* Actually insert the module */ - ret = do_cap(CAP_SYS_MODULE, init_module, file, sbuf.st_size, opts); + ret = init_module(file, sbuf.st_size, opts); saved_errno = errno; /* Cleanup. */ @@ -99,7 +99,7 @@ int insert_module(const char *path, const char *special_options, char **options) if (ret != 0) { err("Error inserting module '%s': %s\n", path, moderror(saved_errno)); - return -1; + return -1; } return 0; } @@ -120,8 +120,7 @@ int mountfs(void) rc = stat(DEBUGFSDIR, &sb); if (rc == 0 && S_ISDIR(sb.st_mode)) { /* If we can mount the debugfs dir correctly, we're done. */ - rc = do_cap(CAP_SYS_ADMIN, mount, "debugfs", DEBUGFSDIR, - "debugfs", 0, NULL); + rc = mount ("debugfs", DEBUGFSDIR, "debugfs", 0, NULL); if (rc == 0) return 0; /* If we got ENODEV, that means that debugfs isn't @@ -132,7 +131,7 @@ int mountfs(void) return -1; } } - + /* DEBUGFSDIR couldn't be mounted. So, try RELAYFSDIR. */ /* If the relayfs dir is already mounted correctly, we're done. */ @@ -159,11 +158,12 @@ int mountfs(void) /* To ensure the directory gets created with the * proper group, we'll have to temporarily switch to * root. */ - if (do_cap(CAP_SETUID, setuid, 0) < 0) { + /* XXX: Why not just chown() the thing? */ + if (setuid (0) < 0) { _perr("Couldn't change user while creating %s", RELAYFSDIR); return -1; } - if (do_cap(CAP_SETGID, setgid, 0) < 0) { + if (setgid (0) < 0) { _perr("Couldn't change group while creating %s", RELAYFSDIR); return -1; } @@ -174,11 +174,11 @@ int mountfs(void) saved_errno = errno; /* Restore everything we changed. */ - if (do_cap(CAP_SETGID, setgid, gid) < 0) { + if (setgid (gid) < 0) { _perr("Couldn't restore group while creating %s", RELAYFSDIR); return -1; } - if (do_cap(CAP_SETUID, setuid, uid) < 0) { + if (setuid (uid) < 0) { _perr("Couldn't restore user while creating %s", RELAYFSDIR); return -1; } @@ -192,7 +192,7 @@ int mountfs(void) } /* Now that we're sure the directory exists, try mounting RELAYFSDIR. */ - if (do_cap(CAP_SYS_ADMIN, mount, "relayfs", RELAYFSDIR, "relayfs", 0, NULL) < 0) { + if (mount ("relayfs", RELAYFSDIR, "relayfs", 0, NULL) < 0) { perr("Couldn't mount %s", RELAYFSDIR); return -1; } @@ -262,13 +262,13 @@ check_path(void) " Unable to canonicalize that directory", staplib_dir_path); return -1; } - + /* Use realpath() to canonicalize the module path. */ if (realpath(modpath, module_realpath) == NULL) { perr("Unable to canonicalize path \"%s\"", modpath); return -1; } - + /* To make sure the user can't specify something like * /lib/modules/`uname -r`/systemtapmod.ko, put a '/' on the * end of staplib_dir_realpath. */ |