summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Brolley <brolley@redhat.com>2009-11-20 17:10:06 -0500
committerDave Brolley <brolley@redhat.com>2009-11-20 17:10:06 -0500
commitbaba4e15bf291b698986f703c9ec89742012922c (patch)
treea778df0c15576e30e468d0c28a497e2037fca7c3
parente16e0c563bf44a234396dbcfd2d0b6cfaac91078 (diff)
downloadsystemtap-steved-baba4e15bf291b698986f703c9ec89742012922c.tar.gz
systemtap-steved-baba4e15bf291b698986f703c9ec89742012922c.tar.xz
systemtap-steved-baba4e15bf291b698986f703c9ec89742012922c.zip
Allow members of the group stap-server to build the uprobes module.
-rw-r--r--buildrun.cxx16
-rw-r--r--runtime/uprobes/Makefile12
-rw-r--r--util.cxx43
-rw-r--r--util.h1
4 files changed, 62 insertions, 10 deletions
diff --git a/buildrun.cxx b/buildrun.cxx
index b6063e36..6774b536 100644
--- a/buildrun.cxx
+++ b/buildrun.cxx
@@ -277,7 +277,8 @@ verify_uprobes_uptodate (systemtap_session& s)
int rc = run_make_cmd(s, make_cmd);
if (rc) {
clog << "SystemTap's version of uprobes is out of date." << endl;
- clog << "As root, run \"make -C " << uprobes_home << "\"." << endl;
+ clog << "As root, or a member of the 'stap-server' group, run" << endl;
+ clog << "\"make -C " << uprobes_home << "\"." << endl;
}
return rc;
@@ -322,17 +323,18 @@ uprobes_pass (systemtap_session& s)
/*
* We need to use the version of uprobes that comes with SystemTap, so
* we may need to rebuild uprobes.ko there. Unfortunately, this is
- * never a no-op; e.g., the modpost step gets run every time. We don't
- * want non-root users modifying uprobes, so we keep the uprobes
- * directory writable only by root. But that means a non-root member
- * of group stapdev can't run the make even if everything's up to date.
+ * never a no-op; e.g., the modpost step gets run every time. We
+ * only want root and members of the 'stap-server' group
+ * modifying uprobes, so we keep the uprobes directory writable only by
+ * those users. But that means that other users can't run the make
+ * even if everything's up to date.
*
- * So for non-root users, we just use "make -q" with a fake target to
+ * So for the other users, we just use "make -q" with a fake target to
* verify that uprobes doesn't need to be rebuilt. If that's not so,
* stap must fail.
*/
int rc;
- if (geteuid() == 0)
+ if (geteuid() == 0 || egid_in ("stap-server"))
rc = make_uprobes(s);
else
rc = verify_uprobes_uptodate(s);
diff --git a/runtime/uprobes/Makefile b/runtime/uprobes/Makefile
index bc0fd6a9..e58373af 100644
--- a/runtime/uprobes/Makefile
+++ b/runtime/uprobes/Makefile
@@ -5,6 +5,10 @@ DEPENDENCIES := $(shell echo uprobes.[ch] uprobes_*.[ch])
DEPENDENCIES += $(shell echo ../uprobes2/uprobes.[ch] ../uprobes2/uprobes_*.[ch])
DEPENDENCIES += Makefile
+CLEAN_FILES := $(shell echo *.mod.c *.ko *.o .*.cmd *~ *.sgn)
+CLEAN_FILES += Module.markers modules.order Module.symvers
+CLEAN_DIRS := .tmp_versions
+
default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
if test -f ../../../../bin/stap-sign-module; then \
@@ -14,12 +18,14 @@ default:
fi \
done \
fi
+ chgrp stap-server $(CLEAN_FILES) 2>/dev/null || true
+ chgrp stap-server $(CLEAN_DIRS) 2>/dev/null || true
+ chgrp stap-server $(CLEAN_DIRS)/* 2>/dev/null || true
# This target is used with "make -q" to see whether a "real" build is needed.
uprobes.ko: $(DEPENDENCIES)
@echo uprobes.ko is not a valid target. See Makefile.
clean:
- rm -f *.mod.c *.ko *.o .*.cmd *~ *.sgn
- rm -f Module.markers modules.order Module.symvers
- rm -rf .tmp_versions
+ rm -f $(CLEAN_FILES)
+ rm -rf $(CLEAN_DIRS)
diff --git a/util.cxx b/util.cxx
index b81d37cb..3887fcd1 100644
--- a/util.cxx
+++ b/util.cxx
@@ -22,6 +22,7 @@
extern "C" {
#include <fcntl.h>
+#include <grp.h>
#include <pwd.h>
#include <spawn.h>
#include <stdio.h>
@@ -188,6 +189,48 @@ remove_file_or_dir (const char *name)
return 0;
}
+// Determine whether the current user is in the given group.
+bool
+egid_in (const char *gname)
+{
+ gid_t gid, gidlist[NGROUPS_MAX];
+ gid_t target_gid;
+ int i, ngids;
+ struct group *group;
+
+ // Lookup the gid for the target group
+ errno = 0;
+ group = getgrnam(gname);
+
+ // If we couldn't find the group, then we can't be part of it.
+ if (group == NULL)
+ return false;
+
+ target_gid = group->gr_gid;
+
+ // According to the getgroups() man page, getgroups() may not
+ // return the effective gid, so try to match it first. */
+ gid = getegid();
+ if (gid == target_gid)
+ return true;
+
+ // Get the list of the user's groups.
+ ngids = getgroups(NGROUPS_MAX, gidlist);
+ if (ngids < 0) {
+ cerr << "Unable to retrieve group list" << endl;
+ return false;
+ }
+
+ for (i = 0; i < ngids; i++) {
+ // If the user is a member of the target group, then we're done.
+ if (gidlist[i] == target_gid)
+ return true;
+ }
+
+ // The user is not a member of the target group
+ return false;
+}
+
void
tokenize(const string& str, vector<string>& tokens,
const string& delimiters = " ")
diff --git a/util.h b/util.h
index 1252d559..f498e1d6 100644
--- a/util.h
+++ b/util.h
@@ -12,6 +12,7 @@ bool copy_file(const std::string& src, const std::string& dest,
bool verbose=false);
int create_dir(const char *dir);
int remove_file_or_dir(const char *dir);
+bool egid_in (const char *gname);
void tokenize(const std::string& str, std::vector<std::string>& tokens,
const std::string& delimiters);
std::string find_executable(const std::string& name);