diff --git a/python/semanage/semanage-fcontext.8 b/python/semanage/semanage-fcontext.8 index 3a96c62fd..a29b74994 100644 --- a/python/semanage/semanage-fcontext.8 +++ b/python/semanage/semanage-fcontext.8 @@ -100,6 +100,10 @@ execute the following commands. # semanage fcontext \-a \-e /home /disk6/home # restorecon \-R \-v /disk6 +Add file-context with MLS range s0:c0.c255 for /secure directory (MLS/MCS systems only) +# semanage fcontext \-a \-t admin_home_t \-r s0:c0.c255 "/secure(/.*)?" +# restorecon \-R \-F \-v /secure + .SH "SEE ALSO" .BR selinux (8), .BR semanage (8), diff --git a/python/semanage/semanage-port.8 b/python/semanage/semanage-port.8 index c6048660c..0df442901 100644 --- a/python/semanage/semanage-port.8 +++ b/python/semanage/semanage-port.8 @@ -61,6 +61,9 @@ Allow Apache to listen on tcp port 81 (i.e. assign tcp port 81 label http_port_t # semanage port \-a \-t http_port_t \-p tcp 81 Allow sshd to listen on tcp port 8991 (i.e. assign tcp port 8991 label ssh_port_t, which sshd is allowed to listen on) # semanage port \-a \-t ssh_port_t \-p tcp 8991 +Add a custom port 9999 with MLS range s0:c0.c255 (MLS/MCS systems only). Verify with seinfo. +# semanage port \-a \-t http_port_t \-p tcp \-r s0:c0.c255 9999 +# seinfo \-\-portcon \-x | grep 9999 .SH "SEE ALSO" .BR selinux (8), diff --git a/sandbox/seunshare.c b/sandbox/seunshare.c index 97430535e..65da46463 100644 --- a/sandbox/seunshare.c +++ b/sandbox/seunshare.c @@ -4,6 +4,7 @@ */ #define _GNU_SOURCE +#include #include #include #include @@ -403,6 +404,66 @@ static int rsynccmd(const char * src, const char *dst, char **cmdbuf) return rc; } +/* + * Recursively delete a directory. + * SAFETY: This function will NOT follow symbolic links (AT_SYMLINK_NOFOLLOW). + * As a result, this function can be run safely on a directory owned by + * a non-root user: symbolic links to root paths (such as /root) will + * not be followed. + */ +static bool rm_rf(int targetfd, const char *path) { + struct stat statbuf; + + if (fstatat(targetfd, path, &statbuf, AT_SYMLINK_NOFOLLOW) < 0) { + if (errno == ENOENT) { + return true; + } + perror("fstatat"); + return false; + } + + if (S_ISDIR(statbuf.st_mode)) { + const int newfd = openat(targetfd, path, O_RDONLY | O_DIRECTORY | O_CLOEXEC); + if (newfd < 0) { + perror("openat"); + return false; + } + + DIR *dir = fdopendir(newfd); + if (!dir) { + perror("fdopendir"); + close(newfd); + return false; + } + + struct dirent *entry; + int rc = true; + while ((entry = readdir(dir)) != NULL) { + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { + continue; + } + + if (!rm_rf(dirfd(dir), entry->d_name)) { + rc = false; + } + } + + closedir(dir); + + if (unlinkat(targetfd, path, AT_REMOVEDIR) < 0) { + perror("unlinkat"); + rc = false; + } + + return rc; + } + if (unlinkat(targetfd, path, 0) < 0) { + perror("unlinkat"); + return false; + } + return true; +} + /** * Clean up runtime temporary directory. Returns 0 if no problem was detected, * >0 if some error was detected, but errors here are treated as non-fatal and @@ -428,24 +489,17 @@ static int cleanup_tmpdir(const char *tmpdir, const char *src, free(cmdbuf); cmdbuf = NULL; } - /* remove files from the runtime temporary directory */ - if (asprintf(&cmdbuf, "/bin/rm -r '%s/' 2>/dev/null", tmpdir) == -1) { - fprintf(stderr, _("Out of memory\n")); - cmdbuf = NULL; + if ((uid_t)setfsuid(0) != 0) { + /* setfsuid does not return error, but this check makes code checkers happy */ rc++; } - /* this may fail if there's root-owned file left in the runtime tmpdir */ - if (cmdbuf && spawn_command(cmdbuf, pwd->pw_uid) != 0) rc++; - free(cmdbuf); cmdbuf = NULL; - /* remove runtime temporary directory */ - if ((uid_t)setfsuid(0) != 0) { - /* setfsuid does not return error, but this check makes code checkers happy */ + /* Recursively remove the runtime temp directory. */ + if (!rm_rf(AT_FDCWD, tmpdir)) { + fprintf(stderr, _("Failed to recursively remove directory %s\n"), tmpdir); rc++; } - if (pwd->pw_uid != 0 && rmdir(tmpdir) == -1) - fprintf(stderr, _("Failed to remove directory %s: %s\n"), tmpdir, strerror(errno)); if ((uid_t)setfsuid(pwd->pw_uid) != 0) { fprintf(stderr, _("unable to switch back to user after clearing tmp dir\n")); rc++;