Skip to content

Commit 221e289

Browse files
WavyEbuilderstephensmalley
authored andcommitted
libsemanage: semanage_store: recursively create SEMANAGE_ROOT
In package build/install environments, when semodule(8) is passed the `--path` option, it is expected that it creates the entire directory tree for the policy root. Some package managers warn or error if permissions do not align between the tree on the existing system and the build environment about to be merged. To make sure this is a non-issue, create the tree of the policy root with 0755 permissions (in line with standards for `/var/lib`) and then chmod the final path to the more restrictive 0700 permissions. As the contents being placed in the policy root are security sensitive, error instead of warning if we fail to chown the policy root to 0700. Signed-off-by: Rahul Sandhu <[email protected]> Acked-by: Stephen Smalley <[email protected]>
1 parent 0a6b917 commit 221e289

File tree

1 file changed

+53
-6
lines changed

1 file changed

+53
-6
lines changed

libsemanage/src/semanage_store.c

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,45 @@ char *semanage_conf_path(void)
491491
return semanage_conf;
492492
}
493493

494+
/* Recursively create a directory from a path string.
495+
* Returns 0 on success, -errno on failure.
496+
*/
497+
static int mkdir_recursive(const char *path, mode_t mode)
498+
{
499+
if (!path || !*path) {
500+
return -EINVAL;
501+
}
502+
503+
char path_buffer[PATH_MAX] = {0};
504+
size_t len = strlen(path);
505+
/* + 1 for nullterm. */
506+
if (len + 1 > sizeof(path_buffer)) {
507+
return -ENAMETOOLONG;
508+
}
509+
510+
/* + 1 for nullterm. */
511+
memcpy(path_buffer, path, len + 1);
512+
513+
/* trim possible trailing slashes, except if '/' is the entire path. */
514+
while (len > 1 && path_buffer[len - 1] == '/') {
515+
path_buffer[--len] = '\0';
516+
}
517+
518+
for (char *pos = path_buffer + 1, *slash; (slash = strchr(pos, '/')); pos = slash + 1) {
519+
*slash = '\0';
520+
if (mkdir(path_buffer, mode) != 0 && errno != EEXIST) {
521+
return -errno;
522+
}
523+
*slash = '/';
524+
}
525+
526+
if (mkdir(path_buffer, mode) != 0 && errno != EEXIST) {
527+
return -errno;
528+
}
529+
530+
return 0;
531+
}
532+
494533
/**************** functions that create module store ***************/
495534

496535
/* Check that the semanage store exists. If 'create' is non-zero then
@@ -506,14 +545,20 @@ int semanage_create_store(semanage_handle_t * sh, int create)
506545

507546
if (stat(path, &sb) == -1) {
508547
if (errno == ENOENT && create) {
509-
mask = umask(0077);
510-
if (mkdir(path, S_IRWXU) == -1) {
511-
umask(mask);
512-
ERR(sh, "Could not create module store at %s.",
513-
path);
548+
/* First we create directories recursively with standard permissions so that
549+
we don't screw up ownership of toplevel dirs such as `/var` in pkgmgr
550+
environments. */
551+
const int r = mkdir_recursive(path, (mode_t)0755);
552+
if (r != 0) {
553+
ERR(sh, "Could not create module store at %s: %s.", path, strerror(-r));
554+
return -2;
555+
}
556+
/* Now that we've created the directory tree, we set the permissions of the
557+
target path to 0700. */
558+
if (chmod(path, (mode_t)0700) != 0) {
559+
ERR(sh, "Failed to chown module store at %s: %s.", path, strerror(errno));
514560
return -2;
515561
}
516-
umask(mask);
517562
} else {
518563
if (create)
519564
ERR(sh,
@@ -529,6 +574,8 @@ int semanage_create_store(semanage_handle_t * sh, int create)
529574
return -1;
530575
}
531576
}
577+
/* We no longer need to use mkdir_recursive at this point: the toplevel
578+
directory hierarchy has been created by now. */
532579
path = semanage_path(SEMANAGE_ACTIVE, SEMANAGE_TOPLEVEL);
533580
if (stat(path, &sb) == -1) {
534581
if (errno == ENOENT && create) {

0 commit comments

Comments
 (0)