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

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

 




> -----Original Message-----
> From: Stephen Smalley [mailto:sds@xxxxxxxxxxxxx]
> Sent: Wednesday, January 27, 2010 3:18 PM
> To: Caleb Case
> Cc: selinux@xxxxxxxxxxxxx; Chad Sellers; Karl MacMillan;
> jwcart2@xxxxxxxxxxxxx; Joshua Brindle
> Subject: Re: [PATCH 06/15] [src-policy] libsemanage: compile hll
module
> 
> 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?

Yes, I'll switch it around.

> 
> > +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?

Nope, this is the same problem all over again. I think that the best
option is to switch the interface around to taking a file stream instead
of a file pointer.

> 
> > +
> > +	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.

Oops, will fix.

> 
> > +			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