예제 #1
0
int init_ctl_channel(const char *name, int verb)
{
	char buf[PATH_MAX];
	struct statfs st;
	int old_transport = 0;

	if (statfs("/sys/kernel/debug", &st) == 0 && (int)st.f_type == (int)DEBUGFS_MAGIC) {
		if (sprintf_chk(buf, "/sys/kernel/debug/systemtap/%s/.cmd", name))
			return -1;
	} else {
		old_transport = 1;
		if (sprintf_chk(buf, "/proc/systemtap/%s/.cmd", name))
			return -2;
	}

	control_channel = open(buf, O_RDWR);
	dbug(2, "Opened %s (%d)\n", buf, control_channel);
	if (control_channel < 0) {
		if (verb) {
			if (attach_mod && errno == ENOENT)
				err("ERROR: Can not attach. Module %s not running.\n", name);
			else
				perr("Couldn't open control channel '%s'", buf);
		}
		return -3;
	}
	if (set_clexec(control_channel) < 0)
		return -4;

	return old_transport;
}
예제 #2
0
파일: ctl.c 프로젝트: amitkr/systemtap
int init_ctl_channel(const char *name, int verb)
{
	char buf[PATH_MAX];
	struct statfs st;
	int old_transport = 0;

	if (statfs("/sys/kernel/debug", &st) == 0 && (int)st.f_type == (int)DEBUGFS_MAGIC) {
		if (sprintf_chk(buf, "/sys/kernel/debug/systemtap/%s/.cmd", name))
			return -1;
	} else {
		old_transport = 1;
		if (sprintf_chk(buf, "/proc/systemtap/%s/.cmd", name))
			return -2;
	}

	control_channel = open(buf, O_RDWR);
	dbug(2, "Opened %s (%d)\n", buf, control_channel);

/* It's actually safe to do this check before the open(),
 * as the file we're trying to access connot be modified
 * by a typical user.
 */
	if (access(buf, R_OK|W_OK) != 0){
		close(control_channel);
		return -5;
	}

	if (control_channel < 0) {
		if (verb) {
			if (attach_mod && errno == ENOENT)
				err(_("ERROR: Can not attach. Module %s not running.\n"), name);
			else
				perr(_("Couldn't open control channel '%s'"), buf);
		}
		return -3;
	}
	if (set_clexec(control_channel) < 0)
		return -4;

	return old_transport;
}
예제 #3
0
static int open_oldoutfile(int fnum, int cpu, int remove_file)
{
	char buf[PATH_MAX];
	time_t t;
	if (outfile_name) {
		time(&t);
		if (fnum_max) {
			if (remove_file) {
				 /* remove oldest file */
				if (make_outfile_name(buf, PATH_MAX,
					fnum - fnum_max, cpu,
					read_backlog(cpu, fnum - fnum_max),
					bulkmode) < 0)
					return -1;
				remove(buf); /* don't care */
			}
			write_backlog(cpu, fnum, t);
		}
		if (make_outfile_name(buf, PATH_MAX, fnum, cpu, t, bulkmode) < 0)
			return -1;
	} else if (bulkmode) {
		if (sprintf_chk(buf, "stpd_cpu%d.%d", cpu, fnum))
			return -1;
	} else { /* stream mode */
		percpu_tmpfile[cpu] = stdout;
		return 0;
	}

	if((percpu_tmpfile[cpu] = fopen(buf, "w+")) == NULL) {
		perr("Couldn't open output file %s", buf);
		return -1;
	}
	out_fd[cpu] = fileno(percpu_tmpfile[cpu]);
	if (set_clexec(out_fd[cpu]) < 0) {
		perr("Couldn't clear exec bit of open output file %s", buf);
		return -1;
	}
	return 0;
}
예제 #4
0
/**
 *	open_relayfs_files - open and mmap buffer and open output file.
 *	Returns -1 on unexpected failure, 0 if file not found, 1 on success.
 */
static int open_relayfs_files(int cpu, const char *relay_filebase, const char *proc_filebase)
{
	size_t total_bufsize;
	char tmp[PATH_MAX];

	memset(&status[cpu], 0, sizeof(struct buf_status));
	status[cpu].info.cpu = cpu;

	if (sprintf_chk(tmp, "%s%d", relay_filebase, cpu))
		return -1;
	dbug(2, "Opening %s.\n", tmp); 
	relay_fd[cpu] = open(tmp, O_RDONLY | O_NONBLOCK);
	if (relay_fd[cpu] < 0 || set_clexec(relay_fd[cpu]) < 0) {
		relay_fd[cpu] = 0;
		return 0;
	}

	if (sprintf_chk(tmp, "%s%d", proc_filebase, cpu))
		goto err1;
	dbug(2, "Opening %s.\n", tmp); 
	proc_fd[cpu] = open(tmp, O_RDWR | O_NONBLOCK);
	if (proc_fd[cpu] < 0) {
		perr("Couldn't open proc file %s", tmp);
		goto err1;
	}
	if (set_clexec(relay_fd[cpu]) < 0) {
		relay_fd[cpu] = 0;
		return -1;
	}

	if (fsize_max) {
		if (init_backlog(cpu) < 0)
			goto err2;
		if (open_oldoutfile(0, cpu, 0) < 0)
			goto err2;
		goto opened;
	}
	if (outfile_name) {
		/* special case: for testing we sometimes want to
		 * write to /dev/null */
		if (strcmp(outfile_name, "/dev/null") == 0) {
			strcpy(tmp, "/dev/null");
		} else {
			int len;
			len = stap_strfloctime(tmp, PATH_MAX, outfile_name, time(NULL));
			if (len < 0) {
				err("Invalid FILE name format\n");
				goto err2;
			}
			if (snprintf_chk(&tmp[len], PATH_MAX - len, "_%d", cpu))
				goto err2;
		}
	} else {
		if (sprintf_chk(tmp, "stpd_cpu%d", cpu))
			goto err2;
	}

	if((percpu_tmpfile[cpu] = fopen(tmp, "w+")) == NULL) {
		perr("Couldn't open output file %s", tmp);
		goto err2;
	}
	out_fd[cpu] = fileno(percpu_tmpfile[cpu]);
	if (set_clexec(out_fd[cpu]) < 0) {
		perr("Couldn't open output file %s", tmp);
		goto err2;
	}
opened:

	total_bufsize = subbuf_size * n_subbufs;
	relay_buffer[cpu] = mmap(NULL, total_bufsize, PROT_READ,
				 MAP_PRIVATE | MAP_POPULATE, relay_fd[cpu],
				 0);
	if(relay_buffer[cpu] == MAP_FAILED)
	{
		_perr("Couldn't mmap relay file, total_bufsize (%d)"	\
		     "= subbuf_size (%d) * n_subbufs(%d)",
		     (int)total_bufsize, (int)subbuf_size, (int)n_subbufs);
		goto err3;
	}
	
	return 1;
	
err3:
	fclose(percpu_tmpfile[cpu]);
err2:
	close (proc_fd[cpu]);
err1:
	close (relay_fd[cpu]);
	relay_fd[cpu] = 0;
	return -1;

}
예제 #5
0
int init_ctl_channel(const char *name, int verb)
{
	char buf[PATH_MAX];
	struct statfs st;
	int old_transport = 0;

        (void) verb;
        if (0) goto out; /* just to defeat gcc warnings */

	/* Before trying to open the control channel, make sure it
	 * isn't already open. */
	close_ctl_channel();

#ifdef HAVE_OPENAT
        if (relay_basedir_fd >= 0) {
                strncpy(buf, CTL_CHANNEL_NAME, PATH_MAX);
                control_channel = openat_cloexec(relay_basedir_fd,
						 CTL_CHANNEL_NAME, O_RDWR, 0);
                dbug(2, "Opened %s (%d)\n", CTL_CHANNEL_NAME, control_channel);

                /* NB: Extra real-id access check as below */
                if (faccessat(relay_basedir_fd, CTL_CHANNEL_NAME, R_OK|W_OK, 0) != 0){
                        close(control_channel);
                        return -5;
                }
                if (control_channel >= 0)
                        goto out; /* It's OK to bypass the [f]access[at] check below,
                                     since this would only occur the *second* time 
                                     staprun tries this gig, or within unprivileged stapio. */
        }
        /* PR14245, NB: we fall through to /sys ... /proc searching,
           in case the relay_basedir_fd option wasn't given (i.e., for
           early in staprun), or if errors out for some reason. */
#endif

	if (statfs("/sys/kernel/debug", &st) == 0 && (int)st.f_type == (int)DEBUGFS_MAGIC) {
                /* PR14245: allow subsequent operations, and if
                   necessary, staprun->stapio forks, to reuse an fd for 
                   directory lookups (even if some parent directories have
                   perms 0700. */
#ifdef HAVE_OPENAT
                if (! sprintf_chk(buf, "/sys/kernel/debug/systemtap/%s", name)) {
                        relay_basedir_fd = open (buf, O_DIRECTORY | O_RDONLY);
                        /* If this fails, we don't much care; the
                           negative return value will just keep us
                           looking up by name again next time. */
                        /* NB: we don't plan to close this fd, so that we can pass
                           it across staprun->stapio fork/execs. */
                }
#endif
		if (sprintf_chk(buf, "/sys/kernel/debug/systemtap/%s/%s", 
                                name, CTL_CHANNEL_NAME))
			return -1;
	} else {
		old_transport = 1;
		if (sprintf_chk(buf, "/proc/systemtap/%s/%s", name, CTL_CHANNEL_NAME))
			return -2;
	}

	control_channel = open_cloexec(buf, O_RDWR, 0);
	dbug(2, "Opened %s (%d)\n", buf, control_channel);

	/* NB: Even if open() succeeded with effective-UID permissions, we
	 * need the access() check to make sure real-UID permissions are also
	 * sufficient.  When we run under the setuid staprun, effective and
	 * real UID may not be the same.  Specifically, we want to prevent 
         * a local stapusr from trying to attach to a different stapusr's module.
	 *
	 * The access() is done *after* open() to avoid any TOCTOU-style race
	 * condition.  We believe it's probably safe either way, as the file
	 * we're trying to access connot be modified by a typical user, but
	 * better safe than sorry.
	 */
#ifdef HAVE_OPENAT
        if (control_channel >= 0 && relay_basedir_fd >= 0) {
                if (faccessat (relay_basedir_fd, CTL_CHANNEL_NAME, R_OK|W_OK, 0) == 0)
                        goto out;
                /* else fall through */
        }
#endif
	if (control_channel >= 0 && access(buf, R_OK|W_OK) != 0) {
		close(control_channel);
		return -5;
	}

out:
	if (control_channel < 0) {
                err(_("Cannot attach to module %s control channel; not running?\n"),
                    name);
		return -3;
	}
	return old_transport;
}