From 3b1a9d1f8db031563903a493be755419d7ba6620 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 4 Jan 2011 16:23:21 +0100 Subject: dump_dir: make chown'ing of new files optional - needed for non-root usage Signed-off-by: Denys Vlasenko --- src/include/report/dump_dir.h | 3 + src/lib/create_dump_dir.c | 2 +- src/lib/dump_dir.c | 76 +++++++++++++++----------- src/report-python/dump_dir.c | 4 +- src/report-python/test_dd_create | 2 +- src/report-python/test_run_event_state1 | 2 +- src/report-python/test_setroubleshoot_example2 | 27 +++++++++ 7 files changed, 80 insertions(+), 36 deletions(-) create mode 100755 src/report-python/test_setroubleshoot_example2 diff --git a/src/include/report/dump_dir.h b/src/include/report/dump_dir.h index bf3b120d..4f2914d0 100644 --- a/src/include/report/dump_dir.h +++ b/src/include/report/dump_dir.h @@ -44,6 +44,9 @@ struct dump_dir { void dd_close(struct dump_dir *dd); struct dump_dir *dd_opendir(const char *dir, int flags); +/* Pass uid = (uid_t)-1L to disable chown'ing of newly created files + * (IOW: if you aren't running under root): + */ struct dump_dir *dd_create(const char *dir, uid_t uid); int dd_exist(struct dump_dir *dd, const char *path); DIR *dd_init_next_file(struct dump_dir *dd); diff --git a/src/lib/create_dump_dir.c b/src/lib/create_dump_dir.c index b0f38e1a..652a16c6 100644 --- a/src/lib/create_dump_dir.c +++ b/src/lib/create_dump_dir.c @@ -22,7 +22,7 @@ static struct dump_dir *try_dd_create(const char *base_dir_name, const char *dir_name) { char *path = concat_path_file(base_dir_name, dir_name); - struct dump_dir *dd = dd_create(path, getuid()); + struct dump_dir *dd = dd_create(path, (uid_t)-1L); free(path); return dd; } diff --git a/src/lib/dump_dir.c b/src/lib/dump_dir.c index 878176b9..488bb133 100644 --- a/src/lib/dump_dir.c +++ b/src/lib/dump_dir.c @@ -207,18 +207,23 @@ struct dump_dir *dd_opendir(const char *dir, int flags) } struct stat stat_buf; - if (stat(dir, &stat_buf) != 0 || !S_ISDIR(stat_buf.st_mode)) + + dd->dd_uid = (uid_t)-1L; + dd->dd_gid = (gid_t)-1L; + if (geteuid() == 0) { - if (!(flags & DD_FAIL_QUIETLY)) - error_msg("'%s' does not exist", dir); - dd_close(dd); - return NULL; + /* In case caller would want to create more files, he'll need uid:gid */ + if (stat(dir, &stat_buf) != 0 || !S_ISDIR(stat_buf.st_mode)) + { + if (!(flags & DD_FAIL_QUIETLY)) + error_msg("'%s' does not exist", dir); + dd_close(dd); + return NULL; + } + dd->dd_uid = stat_buf.st_uid; + dd->dd_gid = stat_buf.st_gid; } - /* In case caller would want to create more files, he'll need uid:gid */ - dd->dd_uid = stat_buf.st_uid; - dd->dd_gid = stat_buf.st_gid; - /* Without this check, e.g. abrt-action-print happily prints any current * directory when run without arguments, because its option -d DIR * defaults to "."! Let's require that at least some crash dump dir @@ -300,7 +305,6 @@ struct dump_dir *dd_create(const char *dir, uid_t uid) dd_close(dd); return NULL; } - /* mkdir's mode (above) can be affected by umask, fix it */ if (chmod(dir, 0750) == -1) { @@ -309,26 +313,31 @@ struct dump_dir *dd_create(const char *dir, uid_t uid) return NULL; } - /* Get ABRT's user id */ - /*dd->dd_uid = 0; - dd_init did this already */ - struct passwd *pw = getpwnam("abrt"); - if (pw) - dd->dd_uid = pw->pw_uid; - else - error_msg("user 'abrt' does not exist, using uid 0"); - - /* Get crashed application's group id */ - /*dd->dd_gid = 0; - dd_init did this already */ - pw = getpwuid(uid); - if (pw) - dd->dd_gid = pw->pw_gid; - else - error_msg("User %lu does not exist, using gid 0", (long)uid); - - if (chown(dir, dd->dd_uid, dd->dd_gid) == -1) + dd->dd_uid = (uid_t)-1L; + dd->dd_gid = (gid_t)-1L; + if (uid != (uid_t)-1L) { - perror_msg("can't change '%s' ownership to %lu:%lu", dir, - (long)dd->dd_uid, (long)dd->dd_gid); + /* Get ABRT's user id */ + dd->dd_uid = 0; + struct passwd *pw = getpwnam("abrt"); + if (pw) + dd->dd_uid = pw->pw_uid; + else + error_msg("user 'abrt' does not exist, using uid 0"); + + /* Get crashed application's group id */ + /*dd->dd_gid = 0; - dd_init did this already */ + pw = getpwuid(uid); + if (pw) + dd->dd_gid = pw->pw_gid; + else + error_msg("User %lu does not exist, using gid 0", (long)uid); + + if (chown(dir, dd->dd_uid, dd->dd_gid) == -1) + { + perror_msg("can't change '%s' ownership to %lu:%lu", dir, + (long)dd->dd_uid, (long)dd->dd_gid); + } } char long_str[sizeof(long) * 3 + 2]; @@ -434,10 +443,15 @@ static bool save_binary_file(const char *path, const char* data, unsigned size, perror_msg("Can't open file '%s'", path); return false; } - if (fchown(fd, uid, gid) == -1) + + if (uid != (uid_t)-1L) { - perror_msg("can't change '%s' ownership to %lu:%lu", path, (long)uid, (long)gid); + if (fchown(fd, uid, gid) == -1) + { + perror_msg("can't change '%s' ownership to %lu:%lu", path, (long)uid, (long)gid); + } } + unsigned r = full_write(fd, data, size); close(fd); if (r != size) diff --git a/src/report-python/dump_dir.c b/src/report-python/dump_dir.c index 249a9478..067b905b 100644 --- a/src/report-python/dump_dir.c +++ b/src/report-python/dump_dir.c @@ -243,8 +243,8 @@ PyObject *p_dd_opendir(PyObject *module, PyObject *args) PyObject *p_dd_create(PyObject *module, PyObject *args) { const char *dir; - int uid; - if (!PyArg_ParseTuple(args, "si", &dir, &uid)) + int uid = -1; + if (!PyArg_ParseTuple(args, "s|i", &dir, &uid)) return NULL; p_dump_dir *new_dd = PyObject_New(p_dump_dir, &p_dump_dir_type); if (!new_dd) diff --git a/src/report-python/test_dd_create b/src/report-python/test_dd_create index 2ac97924..4da29b11 100755 --- a/src/report-python/test_dd_create +++ b/src/report-python/test_dd_create @@ -2,7 +2,7 @@ from report import * -dd = dd_create("testdir", 0) +dd = dd_create("testdir") print dd if dd: diff --git a/src/report-python/test_run_event_state1 b/src/report-python/test_run_event_state1 index b30f8b55..6c3584fe 100755 --- a/src/report-python/test_run_event_state1 +++ b/src/report-python/test_run_event_state1 @@ -14,7 +14,7 @@ res = run_event_state() res.post_run_callback = post_run_callback res.logging_callback = logging_callback -dd = dd_create("testdir", 0) +dd = dd_create("testdir") if not dd: sys.exit(1) dd.save_text("analyzer", "foo") diff --git a/src/report-python/test_setroubleshoot_example2 b/src/report-python/test_setroubleshoot_example2 new file mode 100755 index 00000000..8aebcdfe --- /dev/null +++ b/src/report-python/test_setroubleshoot_example2 @@ -0,0 +1,27 @@ +#!/usr/bin/python + +import report +import report.io +import report.io.GTKIO +import report.accountmanager + +accounts = report.accountmanager.AccountManager() + +signature = report.createAlertSignature("selinux-policy", + "setroubleshoot", + "self.siginfo.get_hash()", + "self.summary", + "content") + +# Won't send log anywhere: +#rc = report.report(signature, report.io.GTKIO.GTKIO(accounts)) + +# report.report() + logging: +def logging_callback(line): + print "LOG:", line + return +state = report.run_event_state() +state.logging_callback = logging_callback +rc = state.run_event_on_crash_data(signature, "report") + +print "rc:", rc -- cgit