All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC] lttngtrace available to non-root
@ 2010-11-19 22:21 Mathieu Desnoyers
  2010-11-20  0:21 ` Mathieu Desnoyers
  0 siblings, 1 reply; 5+ messages in thread
From: Mathieu Desnoyers @ 2010-11-19 22:21 UTC (permalink / raw)
  To: ltt-dev, linux-kernel

Hello!

I just coded a lttngtrace.c program that can spawn a thread from a non-root
user. The idea is to have "lttngtrace" setuid root, executable only by the
"tracing" group. Within lttngtrace, I set the euid and egid back to the original
caller user before executing the command.

I plan to integrate this with the UST userspace tracer as soon as Nils comes
back from vacation and release a new version.

Comments are welcome,

Thanks,

Mathieu


/*
 * lttngtrace.c
 *
 * lttngtrace starts/stop system wide tracing around program execution.
 *
 * Copyright (c) 2010 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
 *
 * 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
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <dirent.h>

#if DEBUG
#define printf_dbg(fmt, args...)	printf(fmt, args)
#else
#define printf_dbg(fmt, ...)
#endif

int recunlink(const char *dirname)
{
	DIR *dir;
	struct dirent *entry;
	char path[PATH_MAX];

	dir = opendir(dirname);
	if (dir == NULL) {
		if (errno == ENOENT)
			return 0;
		perror("Error opendir()");
		return -errno;
	}

	while ((entry = readdir(dir)) != NULL) {
		if (strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..")) {
			snprintf(path, (size_t) PATH_MAX, "%s/%s", dirname,
				 entry->d_name);
			if (entry->d_type == DT_DIR)
				recunlink(path);
			else
				unlink(path);
		}
	}
	closedir(dir);
	rmdir(dirname);

	return 0;
}

int start_tracing(void)
{
	int ret;

	ret = recunlink("/tmp/autotrace1");
	if (ret)
		return ret;
	ret = unlink("/tmp/autotrace1-pid");
	if (ret)
		return ret;

	ret = system("ltt-armall > /dev/null");
	if (ret)
		return ret;
	ret = system("lttctl -C -w /tmp/autotrace1 autotrace1 > /dev/null");
	if (ret)
		return ret;
}

int stop_tracing(void)
{
	int ret;

	ret = system("lttctl -D autotrace1 > /dev/null");
	if (ret)
		return ret;
	ret = system("ltt-disarmall > /dev/null");
	if (ret)
		return ret;
}

int write_child_pid(pid_t pid)
{
	FILE *fp;

	fp = fopen("/tmp/autotrace1-pid", "w");
	if (!fp) {
		perror("Error writing child pid");
		return -errno;
	}
	
	fprintf(fp, "%u", (unsigned int) pid);
	return fclose(fp);
}

int main(int argc, char *argv[])
{
	uid_t euid, uid;
	gid_t egid, gid;
	pid_t pid;
	int gret = 0, ret = 0;

	if (argc < 2)
		return -ENOENT;

	euid = geteuid();
	uid = getuid();
	egid = getegid();
	gid = geteuid();

	if (euid != 0) {
		printf("%s must be setuid root\n", argv[0]);
		return -EPERM;
	}

	printf_dbg("euid: %d\n", euid);
	printf_dbg("uid: %d\n", uid);
	printf_dbg("egid: %d\n", egid);
	printf_dbg("gid: %d\n", gid);

	ret = start_tracing();
	gret = (gret == 0) ? ret : gret;

	pid = fork();
	if (pid > 0) {		/* parent */
		int status;

		pid = wait(&status);
		if (pid == -1)
			gret = (gret == 0) ? -errno : gret;

		ret = stop_tracing();
		gret = (gret == 0) ? ret : gret;
		ret = write_child_pid(pid);
		gret = (gret == 0) ? ret : gret;
	} else if (pid == 0) {	/* child */
		seteuid(uid);
		setegid(gid);
		ret = execvp(argv[1], &argv[1]);
		if (ret)
			perror("Execution error");
		return ret;
	} else {		/* error */
		perror("Error in fork");
		return -errno;
	}
	return ret;
}

-- 
Mathieu Desnoyers
Operating System Efficiency R&D Consultant
EfficiOS Inc.
http://www.efficios.com

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2010-11-20 15:36 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-11-19 22:21 [RFC] lttngtrace available to non-root Mathieu Desnoyers
2010-11-20  0:21 ` Mathieu Desnoyers
2010-11-20  0:28   ` Mathieu Desnoyers
2010-11-20 14:23     ` [RFC] lttngtrace available to non-root (-o option) Mathieu Desnoyers
2010-11-20 15:36       ` [RFC] lttngtrace (signal forwarding) Mathieu Desnoyers

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.