Re: [PATCH 06/15] [src-policy] libsemanage: compile hll module

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, 2010-01-26 at 17:08 -0500, Caleb Case wrote:
> This provides the basic compilation function semanage_compile_hll that
> is called during module installation. semanage_exec is a helper function
> which sets up the redirected io for the child process, executes it,
> waits for the child to exit, and then propagates the child's exit
> status. An additional helper function semanage_fd_to_data reads a given
> file descriptor into a buffer (unzipping it if necessary). The
> compilation messages are stored in
> /var/lib/selinux/.../modules/<priority>/<module>/log.

> diff --git a/libsemanage/src/semanage_store.c b/libsemanage/src/semanage_store.c
> index 2bda1e2..dd96a75 100644
> --- a/libsemanage/src/semanage_store.c
> +++ b/libsemanage/src/semanage_store.c
> @@ -3034,3 +3034,357 @@ int semanage_nc_sort(semanage_handle_t * sh, const char *buf, size_t buf_len,
>  
>  	return 0;
>  }
> +
> +/* Execute @cmd with @args and redirect the @io.
> + *
> + * @io is an array of fd's to redirect. Indices correspond to fds. The fds
> + * are not closed. Indices set to -1 are ignored, otherwise they are
> + * dup2'd.
> + *
> + * Returns:
> + * 	 0	success
> + * 	-1	failure, error outside HLL compiler
> + * 	+N	failure, HLL compiler exit status N
> + */
> +static int semanage_exec(semanage_handle_t *sh,
> +			 const char *cmd,
> +			 char *argv[],
> +			 int io[],
> +			 int io_len)

Can this function be unified with the already existing
semanage_exec_prog()?  Likely by making the latter call this one after
splitting args?

> +int semanage_fd_to_data(semanage_handle_t *sh,
> +			int fd,
> +			char **data,
> +			size_t *data_len)
> +{
> +	assert(sh);
> +	assert(data);
> +	assert(data_len);
> +
> +	int status = 0;
> +	int ret = 0;
> +
> +	*data = NULL;
> +	*data_len = 0;
> +
> +	FILE *fp = NULL;
> +	struct stat sb;
> +	sb.st_size = 0;
> +	ssize_t nread = 0;
> +	char *data_tmp = NULL;
> +
> +	/* Find out how big it is. */
> +	ret = fstat(fd, &sb);
> +	if (ret != 0) {
> +		ERR(sh, "Failed to stat file");
> +		status = -2;
> +		goto cleanup;
> +	}
> +	*data_len = sb.st_size;
> +
> +	/* Allocate a buffer for the file. */
> +	*data = malloc(*data_len + 1);
> +	if (*data == NULL) {
> +		ERR(sh, "Out of memory!");
> +		status = -1;
> +		goto cleanup;
> +	}
> +	(*data)[*data_len] = '\0';

Aren't we going to clobber this shortly?

> +
> +	/* Read into the buffer. */
> +	while((size_t)nread != *data_len) {
> +		nread = read(fd, *data + nread, *data_len - nread);
> +		if (nread < 0) {

We should likely handle EINTR more cleanly throughout.

> +			ERR(sh, "Failed to read the file");
> +			status = -1;
> +			goto cleanup;
> +		}
> +	}
> +
> +	/* Try to bunzip. */
> +	fp = fmemopen(*data, *data_len, "r");
> +	if (fp == NULL) {
> +		ERR(sh, "Failed to open file for reading");
> +		status = -1;
> +		goto cleanup;
> +	}

I have a patch to eliminate use of fmemopen() in libsemanage as it
doesn't handle binary files correctly for glibc < 2.9; see the other
discussion.  Maybe this is ok due to only acting on text files?

> +
> +	nread = bunzip(sh, fp, &data_tmp);
> +	if (nread > 0) {
> +		free(*data);
> +		*data = data_tmp;
> +		*data_len = (size_t)nread;
> +	}
> +
> +cleanup:
> +	if (status != 0) {
> +		free(*data);
> +		*data = NULL;
> +		*data_len = 0;
> +	}
> +
> +	if (fp != NULL) fclose(fp);
> +
> +	return status;
> +}
> +
> +int semanage_compile_hll(semanage_handle_t *sh,
> +			 const semanage_module_info_t *modinfo)
> +{
> +	int status = 0;
> +	int ret = 0;
> +
> +	char hll_path[PATH_MAX];
> +	char cil_path[PATH_MAX];
> +	char ver_path[PATH_MAX];
> +	char log_path[PATH_MAX];
> +
> +	char tmp[] = "/tmp/libsemanage-XXXXXX";
> +	int tmp_fd = -1;
> +	ssize_t nwrite = 0;
> +
> +	int io[4];
> +	int io_len = 4;
> +
> +	const semanage_lang_conf_t *conf = NULL;
> +
> +	int i;
> +
> +	char **argv = NULL;
> +
> +	char *data = NULL;
> +	size_t data_len = 0;
> +
> +	/* determine paths and setup io:
> +	 *
> +	 * 0	hll
> +	 * 1	cil
> +	 * 2	log
> +	 * 3	version
> +	 */
> +
> +	/* 0	hll */
> +	ret = semanage_module_get_path(sh,
> +				       modinfo,
> +				       SEMANAGE_MODULE_PATH_HLL,
> +				       hll_path,
> +				       sizeof(hll_path));
> +	if (ret != 0) {
> +		status = -1;
> +		goto cleanup;
> +	}
> +
> +	/* open hll, read in (which will bunzip if necessary) */
> +	tmp_fd = open(hll_path, O_RDONLY);
> +	if (tmp_fd < 0) {
> +		ERR(sh, "Failed to open %s", hll_path);
> +		status = -1;
> +		goto cleanup;
> +	}
> +
> +	ret = semanage_fd_to_data(sh, tmp_fd, &data, &data_len);
> +	if (ret != 0) {
> +		ERR(sh, "Failed to read %s", hll_path);
> +		status = -1;
> +		goto cleanup;
> +	}
> +
> +	close(tmp_fd);
> +	tmp_fd = mkstemp(tmp);
> +	if (tmp_fd < 0) {
> +		ERR(sh,
> +		    "Failed to create tmp file for module %s.",
> +		    modinfo->name);
> +		status = -1;
> +		goto cleanup;
> +	}
> +
> +	while((size_t)nwrite != data_len) {
> +		nwrite = write(tmp_fd, data + nwrite, data_len - nwrite);
> +		if (nwrite < 0) {

EINTR handling.
Need to check that the expected length was written, not just < 0.
>From the man page:
       If  a  write()  is interrupted by a signal handler before any bytes are
       written, then the call fails with the error EINTR; if it is interrupted
       after  at  least  one  byte  has  been  written, the call succeeds, and
       returns the number of bytes written.

> +			ERR(sh,
> +			    "Failed to write data to tmp file for module %s.",
> +			    modinfo->name);
> +			status = -1;
> +			goto cleanup;
> +		}
> +	}
> +
> +	ret = fsync(tmp_fd);

fdatasync(), maybe?

-- 
Stephen Smalley
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@xxxxxxxxxxxxx with
the words "unsubscribe selinux" without quotes as the message.

[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux