Example #1
0
File: misc.c Project: bioboy/ebbnc2
pid_t daemonise()
{
    pid_t pid = fork();
    if (pid != 0) { return pid; }

    IGNORE_RESULT(freopen("/dev/null", "w", stdout));
    IGNORE_RESULT(freopen("/dev/null", "w", stdin));

    setsid();
    return 0;
}
Example #2
0
static int create_pidfile(void)
{
    /* Note:
     * No O_EXCL: we would happily overwrite stale pidfile from previous boot.
     * No O_TRUNC: we must first try to lock the file, and if lock fails,
     * there is another live abrtd. O_TRUNCing the file in this case
     * would be wrong - it'll erase the pid to empty string!
     */
    int fd = open(VAR_RUN_PIDFILE, O_RDWR|O_CREAT, 0644);
    if (fd >= 0)
    {
        if (lockf(fd, F_TLOCK, 0) < 0)
        {
            perror_msg("Can't lock file '%s'", VAR_RUN_PIDFILE);
            /* should help with problems like rhbz#859724 */
            char pid_str[sizeof(long)*3 + 4];
            int r = full_read(fd, pid_str, sizeof(pid_str));
            close(fd);

            /* File can contain garbage. Be careful interpreting it as PID */
            if (r > 0)
            {
                pid_str[r] = '\0';
                errno = 0;
                long locking_pid = strtol(pid_str, NULL, 10);
                if (!errno && locking_pid > 0 && locking_pid <= INT_MAX)
                {
                    char *cmdline = get_cmdline(locking_pid);
                    if (cmdline)
                    {
                        error_msg("Process %lu '%s' is holding the lock", locking_pid, cmdline);
                        free(cmdline);
                    }
                }
            }

            return -1;
        }
        close_on_exec_on(fd);
        /* write our pid to it */
        char buf[sizeof(long)*3 + 2];
        int len = sprintf(buf, "%lu\n", (long)getpid());
        IGNORE_RESULT(write(fd, buf, len));
        IGNORE_RESULT(ftruncate(fd, len));
        /* we leak opened+locked fd intentionally */
        return 0;
    }

    perror_msg("Can't open '%s'", VAR_RUN_PIDFILE);
    return -1;
}
Example #3
0
static void upload_queue_run(const struct session *session, unsigned const char key[KDF_HASH_LEN])
{
	_cleanup_free_ char *pid = NULL;
	upload_queue_kill();
	pid_t child = fork();
	if (child < 0)
		die_errno("fork(agent)");
	if (child == 0) {
		int null = open("/dev/null", 0);
		if (null >= 0) {
			dup2(null, 0);
			dup2(null, 1);
			dup2(null, 2);
			close(null);
		}
		setsid();
		IGNORE_RESULT(chdir("/"));
		process_set_name("lpass [upload queue]");
		signal(SIGHUP, upload_queue_cleanup);
		signal(SIGINT, upload_queue_cleanup);
		signal(SIGQUIT, upload_queue_cleanup);
		signal(SIGTERM, upload_queue_cleanup);
		signal(SIGALRM, upload_queue_cleanup);
		upload_queue_upload_all(session, key);
		upload_queue_cleanup(0);
		_exit(EXIT_SUCCESS);
	}
	pid = xultostr(child);
	config_write_string("uploader.pid", pid);
}
Example #4
0
int check_recent_crash_file(const char *filename, const char *executable)
{
    int fd = open(filename, O_RDWR | O_CREAT, 0600);
    if (fd < 0)
        return 0;

    int ex_len = strlen(executable);
    struct stat sb;
    int sz;

    fstat(fd, &sb); /* !paranoia. this can't fail. */
    if (sb.st_size != 0 /* if it wasn't created by us just now... */
     && (unsigned)(time(NULL) - sb.st_mtime) < 20 /* and is relatively new [is 20 sec ok?] */
    ) {
        char buf[ex_len + 2];
        sz = read(fd, buf, ex_len + 1);
        if (sz > 0)
        {
            buf[sz] = '\0';
            if (strcmp(executable, buf) == 0)
            {
                error_msg("Not saving repeating crash in '%s'", executable);
                close(fd);
                return 1;
            }
        }
        lseek(fd, 0, SEEK_SET);
    }
    sz = write(fd, executable, ex_len);
    if (sz >= 0)
        IGNORE_RESULT(ftruncate(fd, sz));

    close(fd);
    return 0;
}
Example #5
0
File: ekg.c Project: pawelz/ekg2
/**
 * Notifies plugins, writes the message to stderr, with last_err_message.
 *
 * We are only allowed to call POSIX-defined "async-signal-safe functions" here
 * (see signal(7)), because anything else can result in a "bad thing" such as a
 * deadlock (e.g. if the signal was a result of a malloc()/free()) or a
 * segfault. There were cases of this happening to ekg2.
 *
 * In order to avoid touching the (possibly corrupt) heap, we invoke statically
 * stored set of abort handlers. This is the mechanism we use to notify UI and
 * logs plugins to reset the terminal and sync their output as necessary.
 */
static void handle_fatal_signal(char *message)
{
	const char *err_msg_prefix = "Last error message (if any): ";
	const char *debug_instructions = "If a file called core is be created, try running the following\r\n"
	"command:\r\n"
	"\r\n"
	"    gdb ekg2 core\r\n"
	"\n"
	"note the last few lines, and then note the output from the ,,bt'' command.\r\n"
	"This will help the program authors find the location of the problem\r\n"
	"and most likely will help avoid such crashes in the future.\r\n";

	if (stderr_backup && stderr_backup != -1)
		dup2(stderr_backup, 2);

	/* Notify plugins of impending doom. */
	ekg2_run_all_abort_handlers();

	/* Now that the terminal is (hopefully) back to plain text mode, write messages. */
	/* There is nothing we can do if this fails, so suppress warnings about ignored results. */
	IGNORE_RESULT(write(2, "\r\n\r\n *** ", 9));
	IGNORE_RESULT(write(2, message, strlen(message)));
	IGNORE_RESULT(write(2, " ***\r\n", 6));
	IGNORE_RESULT(write(2, err_msg_prefix, strlen(err_msg_prefix)));
	IGNORE_RESULT(write(2, last_err_message, strlen(last_err_message)));
	IGNORE_RESULT(write(2, "\r\n", 2));
	IGNORE_RESULT(write(2, debug_instructions, strlen(debug_instructions)));
}
Example #6
0
void ShellOpenFolder(const String& dir)
{
	#if defined(PLATFORM_WIN32)
		LaunchWebBrowser(dir);
	#elif __APPLE__
		String tempDir = dir;
		tempDir.Replace(" ", "\\ ");

		IGNORE_RESULT(
			system("open " + tempDir + " &")
		);
	#else
		String tempDir = dir;
		tempDir.Replace(" ", "\\ ");
		
		IGNORE_RESULT(
			system("xdg-open " + tempDir + " &")
		);
	#endif
}
Example #7
0
void LocalSlaveProcess::Write(String s)
{
#ifdef PLATFORM_WIN32
    dword n;
    WriteFile(hInputWrite, s, s.GetLength(), &n, NULL);
#endif
#ifdef PLATFORM_POSIX
    IGNORE_RESULT(
        write(rpipe[1], s, s.GetLength())
    );
#endif
}
Example #8
0
static void
handle_sigint (unused (int sig))
{
    static char msg[] = "Stopping...         \n";

    /* This write is "opportunistic", so it's okay to ignore the
     * result.  It is not required for correctness, and if it does
     * fail or produce a short write, we want to get out of the signal
     * handler as quickly as possible, not retry it. */
    IGNORE_RESULT (write (2, msg, sizeof(msg)-1));
    interrupted = 1;
}
Example #9
0
void Ctrl::PanicMsgBox(const char *title, const char *text)
{
	LLOG("PanicMsgBox " << title << ": " << text);
	if(gdk_pointer_is_grabbed())
		gdk_pointer_ungrab(CurrentTime);
	if(system("which gxmessage") == 0)
		IGNORE_RESULT(system(String().Cat() << "gxmessage -center \"" << title << "\n" << text << "\""));
	else
	if(system("which kdialog") == 0)
		IGNORE_RESULT(system(String().Cat() << "kdialog --error \"" << title << "\n" << text << "\""));
	else
	if(system("which xmessage") == 0)
		IGNORE_RESULT(system(String().Cat() << "xmessage -center \"" << title << "\n" << text << "\""));
	else {
		_DBG_Ungrab();
		GtkWidget *dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR,
		                                           GTK_BUTTONS_CLOSE, "%s: %s", title, text);
		gtk_dialog_run(GTK_DIALOG (dialog));
		gtk_widget_destroy(dialog);
	}
	__BREAK__;
}
Example #10
0
static void upload_queue_run(const struct session *session, unsigned const char key[KDF_HASH_LEN])
{
	_cleanup_free_ char *pid = NULL;
	upload_queue_kill();
	pid_t child = fork();
	if (child < 0)
		die_errno("fork(agent)");
	if (child == 0) {
		_cleanup_free_ char *upload_log_path = NULL;

		int null = open("/dev/null", 0);
		int upload_log = null;

		if (lpass_log_level() >= 0) {
			upload_log_path = config_path("lpass.log");
			upload_log = open(upload_log_path,
					  O_WRONLY | O_CREAT | O_APPEND, 0600);
		}
		if (null >= 0) {
			dup2(null, 0);
			dup2(upload_log, 1);
			dup2(null, 2);
			close(null);
			close(upload_log);
		}
		setsid();
		IGNORE_RESULT(chdir("/"));
		process_set_name("lpass [upload queue]");
		signal(SIGHUP, upload_queue_cleanup);
		signal(SIGINT, upload_queue_cleanup);
		signal(SIGQUIT, upload_queue_cleanup);
		signal(SIGTERM, upload_queue_cleanup);
		signal(SIGALRM, upload_queue_cleanup);
		setvbuf(stdout, NULL, _IOLBF, 0);

		if (http_init()) {
			lpass_log(LOG_ERROR, "UQ: unable to restart curl\n");
			_exit(EXIT_FAILURE);
		}

		lpass_log(LOG_DEBUG, "UQ: starting queue run\n");
		upload_queue_upload_all(session, key);
		lpass_log(LOG_DEBUG, "UQ: queue run complete\n");
		upload_queue_cleanup(0);
		_exit(EXIT_SUCCESS);
	}
	pid = xultostr(child);
	config_write_string("uploader.pid", pid);
}
Example #11
0
void SysImageReleased(const Image& img)
{ // CtrlCore removed handle for img, have to remove paintonly
	Mutex::Lock __(sMakeImage);
	if(sFinished)
		return;
	if(!~img) {
		ImageRemover ir;
		ir.serial_id = img.GetSerialId();
		LLOG("SysImageReleased " << img.GetSerialId() << ", cache size: " << sImageCache().GetSize() << ", count " << sImageCache().GetCount());
		int n = sImageCache().RemoveOne(ir);
		IGNORE_RESULT(n); // suppress warning about unused 'n'
		LLOG("SysImageReleased count: " << n);
		LLOG("SysImageReleased done cache size: " << sImageCache().GetSize() << ", count " << sImageCache().GetCount());
	}
}
Example #12
0
static void handle_signal(int signo)
{
    int save_errno = errno;

    // Enable for debugging only, malloc/printf are unsafe in signal handlers
    //log_debug("Got signal %d", signo);

    uint8_t sig_caught;
    s_sig_caught = sig_caught = signo;
    /* Using local copy of s_sig_caught so that concurrent signal
     * won't change it under us */
    if (s_signal_pipe_write >= 0)
        IGNORE_RESULT(write(s_signal_pipe_write, &sig_caught, 1));

    errno = save_errno;
}
Example #13
0
static void agent_run(unsigned const char key[KDF_HASH_LEN])
{
	_cleanup_free_ char *path;
	char *agent_timeout_str;
	unsigned int agent_timeout;
	struct sockaddr_un sa, listensa;
	struct ucred cred;
	int fd, listenfd;
	socklen_t len;

	signal(SIGHUP, agent_cleanup);
	signal(SIGINT, agent_cleanup);
	signal(SIGQUIT, agent_cleanup);
	signal(SIGTERM, agent_cleanup);
	signal(SIGALRM, agent_cleanup);
	agent_timeout_str = getenv("LPASS_AGENT_TIMEOUT");
	agent_timeout = 60 * 60; /* One hour by default. */
	if (agent_timeout_str && strlen(agent_timeout_str))
		agent_timeout = strtoul(agent_timeout_str, NULL, 10);
	if (agent_timeout)
		alarm(agent_timeout);

	path = agent_socket_path();
	if (strlen(path) >= sizeof(sa.sun_path))
		die("Path too large for agent control socket.");

	fd = socket(AF_UNIX, SOCK_STREAM, 0);

	memset(&sa, 0, sizeof(sa));
	sa.sun_family = AF_UNIX;
	strlcpy(sa.sun_path, path, sizeof(sa.sun_path));

	unlink(path);

	if (bind(fd, (struct sockaddr *)&sa, SUN_LEN(&sa)) < 0 || listen(fd, 16) < 0) {
		listenfd = errno;
		close(fd);
		unlink(path);
		errno = listenfd;
		die_errno("bind|listen");
	}

	for (len = sizeof(listensa); (listenfd = accept(fd, (struct sockaddr *)&listensa, &len)) > 0; len = sizeof(listensa)) {
		if (agent_socket_get_cred(listenfd, &cred) < 0) {
			close(listenfd);
			continue;
		}
		if (cred.uid != getuid() || cred.gid != getgid() || !process_is_same_executable(cred.pid)) {
			close(listenfd);
			continue;
		}

#if SOCKET_SEND_PID == 1
		pid_t pid = getpid();
		IGNORE_RESULT(write(listenfd, &pid, sizeof(pid)));
#endif
		IGNORE_RESULT(write(listenfd, key, KDF_HASH_LEN));
		close(listenfd);
	}

	listenfd = errno;
	close(fd);
	unlink(path);
	errno = listenfd;
	die_errno("accept");
}
Example #14
0
// Write DataVault to Disk
eEsifError DataVault_WriteVault (DataVaultPtr self)
{
	eEsifError rc = ESIF_E_NOT_FOUND;
	DataVaultHeader header;
	struct esif_ccb_file dv_file    = {0};
	struct esif_ccb_file dv_filebak = {0};
	IOStreamPtr vault    = 0;
	IOStreamPtr vaultBak = 0;
	u32 idx;

	if (FLAGS_TEST(self->flags, ESIF_SERVICE_CONFIG_STATIC | ESIF_SERVICE_CONFIG_READONLY)) {
		return ESIF_E_READONLY;
	}

	// TODO: Locking
	vault = IOStream_Create();
	if (!vault) {
		return ESIF_E_NO_MEMORY;
	}

	// If any rows contain NOCACHE PERSIST values, we need to make a copy the original DataVault while creating the new one
	// esif_ccb_sprintf(MAX_PATH, dv_file.filename, "%s%s", esif_build_path(dv_file.filename, MAX_PATH, NULL, self->name), ESIFDV_FILEEXT);
	esif_ccb_sprintf(MAX_PATH, dv_file.filename, "%s%s%s", ESIFDV_DIR, self->name, ESIFDV_FILEEXT);

	for (idx = 0; idx < self->cache->size; idx++)
		if (FLAGS_TESTALL(self->cache->elements[idx].flags, ESIF_SERVICE_CONFIG_NOCACHE | ESIF_SERVICE_CONFIG_PERSIST) &&
			self->cache->elements[idx].value.buf_len == 0) {
			struct stat filebak_stat = {0};
            esif_ccb_sprintf(MAX_PATH, dv_filebak.filename, "%s%s%s", ESIFDV_DIR, self->name, ESIFDV_BAKFILEEXT);

			// Delete BAK file if it exists
			if (esif_ccb_stat(dv_filebak.filename, &filebak_stat) == 0) {
				esif_ccb_unlink(dv_filebak.filename);
			}
			if (esif_ccb_rename(dv_file.filename, dv_filebak.filename) == 0) {
				if ((vaultBak = IOStream_Create()) == NULL) {
					rc = ESIF_E_NO_MEMORY;
				}
				if (!vaultBak || IOStream_OpenFile(vaultBak, dv_filebak.filename, "rb") != 0) {
					IOStream_Destroy(vault);
					IOStream_Destroy(vaultBak);
					return rc;
				}
			}
			break;
		}

	// Create DataVault, Overwrite if necessary
	IOStream_SetFile(vault, self->stream->file.name, "wb");
	if (IOStream_Open(vault) != 0) {
		if (vaultBak) {
			IOStream_Destroy(vaultBak);
			esif_ccb_unlink(dv_filebak.filename);
		}
		IOStream_Destroy(vault);
		return rc;
	}

	// Create File Header
	memset(&header, 0, sizeof(header));
	esif_ccb_memcpy(&header.signature, ESIFDV_SIGNATURE, sizeof(header.signature));
	header.headersize = sizeof(header);
	header.version    = ESIFDV_VERSION(ESIFDV_MAJOR_VERSION, ESIFDV_MINOR_VERSION, ESIFDV_REVISION);
	header.flags = 0;	// TODO: get from self->flags

	// Write File Header
	IOStream_Seek(vault, 0, SEEK_SET);
	IOStream_Write(vault, &header, sizeof(header));
	rc = ESIF_OK;

	// Write All Persisted Rows from Sorted List to DataVault
	for (idx = 0; idx < self->cache->size; idx++) {
		DataCacheEntryPtr keypair = &self->cache->elements[idx];
		if (keypair->flags & ESIF_SERVICE_CONFIG_PERSIST) {
			UInt8 *buffer     = 0;
			UInt32 buffer_len = 0;
			UInt32 byte = 0;

			IOStream_Write(vault, &keypair->flags, sizeof(keypair->flags));
			IOStream_Write(vault, &keypair->key.data_len, sizeof(keypair->key.data_len));
			IOStream_Write(vault, keypair->key.buf_ptr, keypair->key.data_len);

			IOStream_Write(vault, &keypair->value.type, sizeof(keypair->value.type));
			IOStream_Write(vault, &keypair->value.data_len, sizeof(keypair->value.data_len));

			// Read NOCACHE Entries from Backup file
			if (keypair->flags & ESIF_SERVICE_CONFIG_NOCACHE) {
				size_t offset = IOStream_GetOffset(vault);

				// Read Block from BAK file
				if (keypair->value.buf_len == 0) {
					size_t bakoffset = (size_t)keypair->value.buf_ptr;
					buffer     = (UInt8*)esif_ccb_malloc(keypair->value.data_len);
					buffer_len = keypair->value.data_len;
					if (!buffer) {
						rc = ESIF_E_NO_MEMORY;
						break;
					}
					if (IOStream_Seek(vaultBak, bakoffset, SEEK_SET) != 0 || IOStream_Read(vaultBak, buffer, buffer_len) != buffer_len) {
						esif_ccb_free(buffer);
						rc = ESIF_E_UNSPECIFIED;// TODO: ESIF_E_IOERROR;
						break;
					}
					keypair->value.buf_ptr = (void*)offset;
				}
				// Convert internal storage to NOCACHE
				else {
					buffer     = (UInt8*)keypair->value.buf_ptr;
					buffer_len = keypair->value.data_len;
					keypair->value.buf_ptr = (void*)offset;
					keypair->value.buf_len = 0;
				}
			}

			// Encrypt Data?
			if (keypair->flags & ESIF_SERVICE_CONFIG_ENCRYPT) {
				if (!buffer) {
					buffer     = (UInt8*)esif_ccb_malloc(keypair->value.data_len);
					buffer_len = keypair->value.data_len;
					if (!buffer) {
						rc = ESIF_E_NO_MEMORY;
						break;
					}
				}
				for (byte = 0; byte < keypair->value.data_len; byte++)
					buffer[byte] = ~((UInt8*)(keypair->value.buf_ptr))[byte];
			}

			if (buffer) {
				IOStream_Write(vault, buffer, buffer_len);
				esif_ccb_free(buffer);
			} else {
				IOStream_Write(vault, keypair->value.buf_ptr, keypair->value.data_len);
			}
		}
	}

	// Rollback on Error
	if (rc != ESIF_OK) {
		IOStream_Destroy(vaultBak);
		IOStream_Destroy(vault);
		esif_ccb_unlink(dv_file.filename);
		IGNORE_RESULT(esif_ccb_rename(dv_filebak.filename, dv_file.filename));
		return rc;
	}
	// Remove BAK file and Commit
	if (vaultBak) {
		IOStream_Close(vaultBak);
		esif_ccb_unlink(dv_filebak.filename);
		IOStream_Destroy(vaultBak);
	}
	IOStream_Close(vault);
	IOStream_Destroy(vault);
	return rc;
}
/* A binary wrapper is needed around python scripts if we want
 * to run them in sgid/suid mode.
 *
 * This is such a wrapper.
 */
int main(int argc, char **argv)
{
    /* I18n */
    setlocale(LC_ALL, "");
#if ENABLE_NLS
    bindtextdomain(PACKAGE, LOCALEDIR);
    textdomain(PACKAGE);
#endif

    abrt_init(argv);

    /* Can't keep these strings/structs static: _() doesn't support that */
    const char *program_usage_string = _(
                                           "& [-y] [-i BUILD_IDS_FILE|-i -] [-e PATH[:PATH]...]\n"
                                           "\t[-r REPO]\n"
                                           "\n"
                                           "Installs debuginfo packages for all build-ids listed in BUILD_IDS_FILE to\n"
                                           "ABRT system cache."
                                       );

    enum {
        OPT_v = 1 << 0,
        OPT_y = 1 << 1,
        OPT_i = 1 << 2,
        OPT_e = 1 << 3,
        OPT_r = 1 << 4,
        OPT_s = 1 << 5,
    };

    const char *build_ids = "build_ids";
    const char *exact = NULL;
    const char *repo = NULL;
    const char *size_mb = NULL;

    struct options program_options[] = {
        OPT__VERBOSE(&g_verbose),
        OPT_BOOL  ('y', "yes",         NULL,                   _("Noninteractive, assume 'Yes' to all questions")),
        OPT_STRING('i', "ids",   &build_ids, "BUILD_IDS_FILE", _("- means STDIN, default: build_ids")),
        OPT_STRING('e', "exact",     &exact, "EXACT",          _("Download only specified files")),
        OPT_STRING('r', "repo",       &repo, "REPO",           _("Pattern to use when searching for repos, default: *debug*")),
        OPT_STRING('s', "size_mb", &size_mb, "SIZE_MB",        _("Ignored option")),
        OPT_END()
    };
    const unsigned opts = parse_opts(argc, argv, program_options, program_usage_string);

    const gid_t egid = getegid();
    const gid_t rgid = getgid();
    const uid_t euid = geteuid();
    const gid_t ruid = getuid();

    /* We need to open the build ids file under the caller's UID/GID to avoid
     * information disclosures when reading files with changed UID.
     * Unfortunately, we cannot replace STDIN with the new fd because ABRT uses
     * STDIN to communicate with the caller. So, the following code opens a
     * dummy file descriptor to the build ids file and passes the new fd's proc
     * path to the wrapped program in the ids argument.
     * The new fd remains opened, the OS will close it for us. */
    char *build_ids_self_fd = NULL;
    if (strcmp("-", build_ids) != 0)
    {
        if (setregid(egid, rgid) < 0)
            perror_msg_and_die("setregid(egid, rgid)");

        if (setreuid(euid, ruid) < 0)
            perror_msg_and_die("setreuid(euid, ruid)");

        const int build_ids_fd = open(build_ids, O_RDONLY);

        if (setregid(rgid, egid) < 0)
            perror_msg_and_die("setregid(rgid, egid)");

        if (setreuid(ruid, euid) < 0 )
            perror_msg_and_die("setreuid(ruid, euid)");

        if (build_ids_fd < 0)
            perror_msg_and_die("Failed to open file '%s'", build_ids);

        /* We are not going to free this memory. There is no place to do so. */
        build_ids_self_fd = xasprintf("/proc/self/fd/%d", build_ids_fd);
    }

    char tmp_directory[] = LARGE_DATA_TMP_DIR"/abrt-tmp-debuginfo.XXXXXX";
    if (mkdtemp(tmp_directory) == NULL)
        perror_msg_and_die("Failed to create working directory");

    log_info("Created working directory: %s", tmp_directory);

    /* name, -v, --ids, -, -y, -e, EXACT, -r, REPO, -t, PATH, --, NULL */
    const char *args[13];
    {
        const char *verbs[] = { "", "-v", "-vv", "-vvv" };
        unsigned i = 0;
        args[i++] = EXECUTABLE;
        args[i++] = "--ids";
        args[i++] = (build_ids_self_fd != NULL) ? build_ids_self_fd : "-";
        if (g_verbose > 0)
            args[i++] = verbs[g_verbose <= 3 ? g_verbose : 3];
        if ((opts & OPT_y))
            args[i++] = "-y";
        if ((opts & OPT_e))
        {
            args[i++] = "--exact";
            args[i++] = exact;
        }
        if ((opts & OPT_r))
        {
            args[i++] = "--repo";
            args[i++] = repo;
        }
        args[i++] = "--tmpdir";
        args[i++] = tmp_directory;
        args[i++] = "--";
        args[i] = NULL;
    }

    /* Switch real user/group to effective ones.
     * Otherwise yum library gets confused - gets EPERM (why??).
     */
    /* do setregid only if we have to, to not upset selinux needlessly */
    if (egid != rgid)
        IGNORE_RESULT(setregid(egid, egid));
    if (euid != ruid)
    {
        IGNORE_RESULT(setreuid(euid, euid));
        /* We are suid'ed! */
        /* Prevent malicious user from messing up with suid'ed process: */
#if 1
// We forgot to sanitize PYTHONPATH. And who knows what else we forgot
// (especially considering *future* new variables of this kind).
// We switched to clearing entire environment instead:

        // However since we communicate through environment variables
        // we have to keep a whitelist of variables to keep.
        static const char *whitelist[] = {
            "REPORT_CLIENT_SLAVE", //  Check if the app is being run as a slave
            "LANG",
        };
        const size_t wlsize = sizeof(whitelist)/sizeof(char*);
        char *setlist[sizeof(whitelist)/sizeof(char*)] = { 0 };
        char *p = NULL;
        for (size_t i = 0; i < wlsize; i++)
            if ((p = getenv(whitelist[i])) != NULL)
                setlist[i] = xstrdup(p);

        // Now we can clear the environment
        clearenv();

        // And once again set whitelisted variables
        for (size_t i = 0; i < wlsize; i++)
            if (setlist[i] != NULL)
            {
                xsetenv(whitelist[i], setlist[i]);
                free(setlist[i]);
            }
#else
        /* Clear dangerous stuff from env */
        static const char forbid[] =
            "LD_LIBRARY_PATH" "\0"
            "LD_PRELOAD" "\0"
            "LD_TRACE_LOADED_OBJECTS" "\0"
            "LD_BIND_NOW" "\0"
            "LD_AOUT_LIBRARY_PATH" "\0"
            "LD_AOUT_PRELOAD" "\0"
            "LD_NOWARN" "\0"
            "LD_KEEPDIR" "\0"
            ;
        const char *p = forbid;
        do {
            unsetenv(p);
            p += strlen(p) + 1;
        } while (*p);
#endif
        /* Set safe PATH */
        // Adding configure --bindir and --sbindir to the PATH so that
        // abrt-action-install-debuginfo doesn't fail when spawning
        // abrt-action-trim-files
        char path_env[] = "PATH=/usr/sbin:/sbin:/usr/bin:/bin:"BIN_DIR":"SBIN_DIR;
        if (euid != 0)
            strcpy(path_env, "PATH=/usr/bin:/bin:"BIN_DIR);
        putenv(path_env);

        /* Use safe umask */
        umask(0022);
    }

    pid_t pid = fork();
    if (pid < 0)
        perror_msg_and_die("fork");

    if (pid == 0)
    {
        execvp(EXECUTABLE, (char **)args);
        error_msg_and_die("Can't execute %s", EXECUTABLE);
    }

    int status;
    if (safe_waitpid(pid, &status, 0) < 0)
        perror_msg_and_die("waitpid");

    if (rmdir(tmp_directory) >= 0)
        log_info("Removed working directory: %s", tmp_directory);
    else if (errno != ENOENT)
        perror_msg("Failed to remove working directory");

    /* Normal execution should exit here. */
    if (WIFEXITED(status))
        return WEXITSTATUS(status);

    if (WIFSIGNALED(status))
        error_msg_and_die("Child terminated with signal %d", WTERMSIG(status));

    error_msg_and_die("Child exit failed");
}
Example #16
0
/* Called after "Backtrace:" line was read.
 * Example (yes, stray newline before 'B' is real):
[ 86985.879]<space>
Backtrace:
[ 86985.880] 0: /usr/bin/Xorg (xorg_backtrace+0x2f) [0x462d8f]
[ 86985.880] 1: /usr/bin/Xorg (0x400000+0x67b56) [0x467b56]
[ 86985.880] 2: /lib64/libpthread.so.0 (0x30a5800000+0xf4f0) [0x30a580f4f0]
[ 86985.880] 3: /usr/lib64/xorg/modules/extensions/librecord.so (0x7ff6c225e000+0x26c3) [0x7ff6c22606c3]
[ 86985.880] 4: /usr/bin/Xorg (_CallCallbacks+0x3c) [0x43820c]
[ 86985.880] 5: /usr/bin/Xorg (WriteToClient+0x1f5) [0x466315]
[ 86985.880] 6: /usr/lib64/xorg/modules/extensions/libdri2.so (ProcDRI2WaitMSCReply+0x4f) [0x7ff6c1e4feef]
[ 86985.880] 7: /usr/lib64/xorg/modules/extensions/libdri2.so (DRI2WaitMSCComplete+0x52) [0x7ff6c1e4e6d2]
[ 86985.880] 8: /usr/lib64/xorg/modules/drivers/intel_drv.so (0x7ff6c1bfb000+0x25ae4) [0x7ff6c1c20ae4]
[ 86985.880] 9: /usr/lib64/libdrm.so.2 (drmHandleEvent+0xa3) [0x376b407513]
[ 86985.880] 10: /usr/bin/Xorg (WakeupHandler+0x6b) [0x4379db]
[ 86985.880] 11: /usr/bin/Xorg (WaitForSomething+0x1a9) [0x460289]
[ 86985.880] 12: /usr/bin/Xorg (0x400000+0x3379a) [0x43379a]
[ 86985.880] 13: /usr/bin/Xorg (0x400000+0x22dc5) [0x422dc5]
[ 86985.880] 14: /lib64/libc.so.6 (__libc_start_main+0xed) [0x30a542169d]
[ 86985.880] 15: /usr/bin/Xorg (0x400000+0x230b1) [0x4230b1]
[ 86985.880] Segmentation fault at address 0x7ff6bf09e010
 */
static void process_xorg_bt(void)
{
    char *reason = NULL;
    char *exe = NULL;
    GList *list = NULL;
    unsigned cnt = 0;
    char *line;
    while ((line = xmalloc_fgetline(stdin)) != NULL)
    {
        char *p = skip_pfx(line);

        /* xorg-server-1.12.0/os/osinit.c:
         * if (sip->si_code == SI_USER) {
         *     ErrorF("Recieved signal %d sent by process %ld, uid %ld\n",
         *             ^^^^^^^^ yes, typo here! Can't grep for this word! :(
         *            signo, (long) sip->si_pid, (long) sip->si_uid);
         * } else {
         *     switch (signo) {
         *         case SIGSEGV:
         *         case SIGBUS:
         *         case SIGILL:
         *         case SIGFPE:
         *             ErrorF("%s at address %p\n", strsignal(signo), sip->si_addr);
         */
        if (*p < '0' || *p > '9')
        {
            if (strstr(p, " at address ") || strstr(p, " sent by process "))
            {
                overlapping_strcpy(line, p);
                reason = line;
                line = NULL;
            }
            /* TODO: Other cases when we have useful reason string? */
            break;
        }

        errno = 0;
        char *end;
        IGNORE_RESULT(strtoul(p, &end, 10));
        if (errno || end == p || *end != ':')
            break;

        /* This looks like bt line */

        /* Guess Xorg server's executable name from it */
        if (!exe)
        {
            char *filename = skip_whitespace(end + 1);
            char *filename_end = skip_non_whitespace(filename);
            char sv = *filename_end;
            *filename_end = '\0';
            /* Does it look like "[/usr]/[s]bin/Xfoo"? */
            if (strstr(filename, "bin/X"))
                exe = xstrdup(filename);
            *filename_end = sv;
        }

        /* Save it to list */
        overlapping_strcpy(line, p);
        list = g_list_prepend(list, line);
        line = NULL;
        if (++cnt > 255) /* prevent ridiculously large bts */
            break;
    }
    free(line);

    if (list)
    {
        list = g_list_reverse(list);
        char *bt = list2lines(list); /* frees list */
        if (g_opts & OPT_o)
            printf("%s%s%s\n", bt, reason ? reason : "", reason ? "\n" : "");
        if (g_opts & (OPT_d|OPT_D))
            if (g_bt_count <= MAX_DUMPED_DD_COUNT)
                save_bt_to_dump_dir(bt, exe, reason ? reason : "Xorg server crashed");
        free(bt);
    }
    free(reason);
    free(exe);
}
/* A binary wrapper is needed around python scripts if we want
 * to run them in sgid/suid mode.
 *
 * This is such a wrapper.
 */
int main(int argc, char **argv)
{
    /*
     * We disallow passing of arguments which point to writable dirs
     * and other files possibly not accessible to calling user.
     * This way, the script will always use default values for these arguments.
     */
    char **pp = argv;
    char *arg;
    while ((arg = *++pp) != NULL)
    {
        /* Allow taking ids from stdin */
        if (strcmp(arg, "--ids=-") == 0)
            continue;

        if (strncmp(arg, "--exact", 7) == 0)
            continue;

        if (strncmp(arg, "--cache", 7) == 0)
            error_msg_and_die("bad option %s", arg);
        if (strncmp(arg, "--tmpdir", 8) == 0)
            error_msg_and_die("bad option %s", arg);
        if (strncmp(arg, "--ids", 5) == 0)
            error_msg_and_die("bad option %s", arg);
    }

    /* Switch real user/group to effective ones.
     * Otherwise yum library gets confused - gets EPERM (why??).
     */
    gid_t g = getegid();
    /* do setregid only if we have to, to not upset selinux needlessly */
    if (g != getgid())
        IGNORE_RESULT(setregid(g, g));
    uid_t u = geteuid();
    if (u != getuid())
    {
        IGNORE_RESULT(setreuid(u, u));
        /* We are suid'ed! */
        /* Prevent malicious user from messing up with suid'ed process: */
#if 1
// We forgot to sanitize PYTHONPATH. And who knows what else we forgot
// (especially considering *future* new variables of this kind).
// We switched to clearing entire environment instead:

        // However since we communicate through environment variables
        // we have to keep a whitelist of variables to keep.
        static const char *whitelist[] = {
            "REPORT_CLIENT_SLAVE" //  Check if the app is being run as a slave
        };
        const size_t wlsize = sizeof(whitelist)/sizeof(char*);
        char *setlist[sizeof(whitelist)/sizeof(char*)] = { 0 };
        char *p = NULL;
        for (size_t i = 0; i < wlsize; i++)
            if ((p = getenv(whitelist[i])) != NULL)
                setlist[i] = xstrdup(p);

        // Now we can clear the environment
        clearenv();

        // And once again set whitelisted variables
        for (size_t i = 0; i < wlsize; i++)
            if (setlist[i] != NULL)
            {
                xsetenv(whitelist[i], setlist[i]);
                free(setlist[i]);
            }
#else
        /* Clear dangerous stuff from env */
        static const char forbid[] =
            "LD_LIBRARY_PATH" "\0"
            "LD_PRELOAD" "\0"
            "LD_TRACE_LOADED_OBJECTS" "\0"
            "LD_BIND_NOW" "\0"
            "LD_AOUT_LIBRARY_PATH" "\0"
            "LD_AOUT_PRELOAD" "\0"
            "LD_NOWARN" "\0"
            "LD_KEEPDIR" "\0"
        ;
        const char *p = forbid;
        do {
            unsetenv(p);
            p += strlen(p) + 1;
        } while (*p);
#endif
        /* Set safe PATH */
        // Adding configure --bindir and --sbindir to the PATH so that
        // abrt-action-install-debuginfo doesn't fail when spawning
        // abrt-action-trim-files
        char path_env[] = "PATH=/usr/sbin:/sbin:/usr/bin:/bin:"BIN_DIR":"SBIN_DIR;
        if (u != 0)
            strcpy(path_env, "PATH=/usr/bin:/bin:"BIN_DIR);
        putenv(path_env);
    }

    execvp(EXECUTABLE, argv);
    error_msg_and_die("Can't execute %s", EXECUTABLE);
}
Example #18
0
void Ide::LaunchAndroidAVDManager(const AndroidSDK& androidSDK)
{
	One<Host> host = CreateHost(false);
	IGNORE_RESULT(host->Execute(androidSDK.GetLauchAVDManagerCmd()));
}