Message ID | 20230814132025.45364-11-cgzones@googlemail.com (mailing list archive) |
---|---|
State | New, archived |
Delegated to: | Petr Lautrbach |
Headers | show |
Series | libselinux: rework selabel_file(5) database | expand |
On Mon, Aug 14, 2023 at 9:41 AM Christian Göttsche <cgzones@googlemail.com> wrote: > > Introduce a helper to remove SELinux file contexts. > > Mainly for testing label operations and only for SELinux disabled > systems, since removing file contexts is not supported by SELinux. > > Signed-off-by: Christian Göttsche <cgzones@googlemail.com> > --- > libselinux/utils/.gitignore | 1 + > libselinux/utils/selabel_nuke.c | 134 ++++++++++++++++++++++++++++++++ > 2 files changed, 135 insertions(+) > create mode 100644 libselinux/utils/selabel_nuke.c > > diff --git a/libselinux/utils/.gitignore b/libselinux/utils/.gitignore > index b3311360..a92e1e94 100644 > --- a/libselinux/utils/.gitignore > +++ b/libselinux/utils/.gitignore > @@ -20,6 +20,7 @@ selabel_digest > selabel_get_digests_all_partial_matches > selabel_lookup > selabel_lookup_best_match > +selabel_nuke This is not a good name and I am not sure that it should have a "selabel" prefix. It doesn't use any selabel stuff. It seems like this should be in policycoreutils maybe with the name "remove_filecons". Jim > selabel_partial_match > selinux_check_securetty_context > selinuxenabled > diff --git a/libselinux/utils/selabel_nuke.c b/libselinux/utils/selabel_nuke.c > new file mode 100644 > index 00000000..b6a2df66 > --- /dev/null > +++ b/libselinux/utils/selabel_nuke.c > @@ -0,0 +1,134 @@ > +#include <dirent.h> > +#include <errno.h> > +#include <fcntl.h> > +#include <getopt.h> > +#include <linux/magic.h> > +#include <stdbool.h> > +#include <stdio.h> > +#include <stdlib.h> > +#include <string.h> > +#include <sys/types.h> > +#include <sys/xattr.h> > +#include <unistd.h> > + > +#include <selinux/selinux.h> > + > + > +#define XATTR_NAME_SELINUX "security.selinux" > + > + > +static void usage(const char *progname) > +{ > + fprintf(stderr, "usage: %s [-nrv] <path>\n", progname); > +} > + > +static void nuke(int atfd, const char *path, const char *fullpath, bool dry_run, bool recursive, bool verbose) > +{ > + ssize_t ret; > + int fd, rc; > + DIR *dir; > + > + ret = lgetxattr(fullpath, XATTR_NAME_SELINUX, NULL, 0); > + if (ret <= 0) { > + if (errno != ENODATA && errno != ENOTSUP) > + fprintf(stderr, "Failed to get SELinux label of %s: %m\n", fullpath); > + else if (verbose) > + printf("Failed to get SELinux label of %s: %m\n", fullpath); > + } else { > + if (dry_run) { > + printf("Would remove SELinux label of %s\n", fullpath); > + } else { > + if (verbose) > + printf("Removing label of %s\n", fullpath); > + > + rc = lremovexattr(fullpath, XATTR_NAME_SELINUX); > + if (rc < 0) > + fprintf(stderr, "Failed to remove SELinux label of %s: %m\n", fullpath); > + } > + } > + > + if (!recursive) > + return; > + > + fd = openat(atfd, path, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC); > + if (fd < 0) { > + if (errno != ENOTDIR) > + fprintf(stderr, "Failed to open %s: %m\n", fullpath); > + return; > + } > + > + dir = fdopendir(fd); > + if (!dir) { > + fprintf(stderr, "Failed to open directory %s: %m\n", fullpath); > + close(fd); > + return; > + } > + > + while (true) { > + const struct dirent *entry; > + char *nextfullpath; > + > + errno = 0; > + entry = readdir(dir); > + if (!entry) { > + if (errno) > + fprintf(stderr, "Failed to iterate directory %s: %m\n", fullpath); > + break; > + } > + > + if (entry->d_name[0] == '.' && (entry->d_name[1] == '\0' || (entry->d_name[1] == '.' && entry->d_name[2] == '\0'))) > + continue; > + > + rc = asprintf(&nextfullpath, "%s/%s", strcmp(fullpath, "/") == 0 ? "" : fullpath, entry->d_name); > + if (rc < 0) { > + fprintf(stderr, "Out of memory!\n"); > + closedir(dir); > + return; > + } > + > + nuke(dirfd(dir), entry->d_name, nextfullpath, dry_run, recursive, verbose); > + > + free(nextfullpath); > + } > + > + closedir(dir); > +} > + > + > +int main(int argc, char *argv[]) > +{ > + bool dry_run = false, recursive = false, verbose = false; > + int c; > + > + while ((c = getopt(argc, argv, "nrv")) != -1) { > + switch (c) { > + case 'n': > + dry_run = true; > + break; > + case 'r': > + recursive = true; > + break; > + case 'v': > + verbose = true; > + break; > + default: > + usage(argv[0]); > + return EXIT_FAILURE; > + } > + } > + > + if (optind >= argc) { > + usage(argv[0]); > + return EXIT_FAILURE; > + } > + > + if (is_selinux_enabled()) { > + fprintf(stderr, "Removing SELinux attributes on a SELinux enabled system is not supported!\n"); > + return EXIT_FAILURE; > + } > + > + for (int index = optind; index < argc; index++) > + nuke(AT_FDCWD, argv[index], argv[index], dry_run, recursive, verbose); > + > + return EXIT_SUCCESS; > +} > -- > 2.40.1 >
diff --git a/libselinux/utils/.gitignore b/libselinux/utils/.gitignore index b3311360..a92e1e94 100644 --- a/libselinux/utils/.gitignore +++ b/libselinux/utils/.gitignore @@ -20,6 +20,7 @@ selabel_digest selabel_get_digests_all_partial_matches selabel_lookup selabel_lookup_best_match +selabel_nuke selabel_partial_match selinux_check_securetty_context selinuxenabled diff --git a/libselinux/utils/selabel_nuke.c b/libselinux/utils/selabel_nuke.c new file mode 100644 index 00000000..b6a2df66 --- /dev/null +++ b/libselinux/utils/selabel_nuke.c @@ -0,0 +1,134 @@ +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <getopt.h> +#include <linux/magic.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/xattr.h> +#include <unistd.h> + +#include <selinux/selinux.h> + + +#define XATTR_NAME_SELINUX "security.selinux" + + +static void usage(const char *progname) +{ + fprintf(stderr, "usage: %s [-nrv] <path>\n", progname); +} + +static void nuke(int atfd, const char *path, const char *fullpath, bool dry_run, bool recursive, bool verbose) +{ + ssize_t ret; + int fd, rc; + DIR *dir; + + ret = lgetxattr(fullpath, XATTR_NAME_SELINUX, NULL, 0); + if (ret <= 0) { + if (errno != ENODATA && errno != ENOTSUP) + fprintf(stderr, "Failed to get SELinux label of %s: %m\n", fullpath); + else if (verbose) + printf("Failed to get SELinux label of %s: %m\n", fullpath); + } else { + if (dry_run) { + printf("Would remove SELinux label of %s\n", fullpath); + } else { + if (verbose) + printf("Removing label of %s\n", fullpath); + + rc = lremovexattr(fullpath, XATTR_NAME_SELINUX); + if (rc < 0) + fprintf(stderr, "Failed to remove SELinux label of %s: %m\n", fullpath); + } + } + + if (!recursive) + return; + + fd = openat(atfd, path, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC); + if (fd < 0) { + if (errno != ENOTDIR) + fprintf(stderr, "Failed to open %s: %m\n", fullpath); + return; + } + + dir = fdopendir(fd); + if (!dir) { + fprintf(stderr, "Failed to open directory %s: %m\n", fullpath); + close(fd); + return; + } + + while (true) { + const struct dirent *entry; + char *nextfullpath; + + errno = 0; + entry = readdir(dir); + if (!entry) { + if (errno) + fprintf(stderr, "Failed to iterate directory %s: %m\n", fullpath); + break; + } + + if (entry->d_name[0] == '.' && (entry->d_name[1] == '\0' || (entry->d_name[1] == '.' && entry->d_name[2] == '\0'))) + continue; + + rc = asprintf(&nextfullpath, "%s/%s", strcmp(fullpath, "/") == 0 ? "" : fullpath, entry->d_name); + if (rc < 0) { + fprintf(stderr, "Out of memory!\n"); + closedir(dir); + return; + } + + nuke(dirfd(dir), entry->d_name, nextfullpath, dry_run, recursive, verbose); + + free(nextfullpath); + } + + closedir(dir); +} + + +int main(int argc, char *argv[]) +{ + bool dry_run = false, recursive = false, verbose = false; + int c; + + while ((c = getopt(argc, argv, "nrv")) != -1) { + switch (c) { + case 'n': + dry_run = true; + break; + case 'r': + recursive = true; + break; + case 'v': + verbose = true; + break; + default: + usage(argv[0]); + return EXIT_FAILURE; + } + } + + if (optind >= argc) { + usage(argv[0]); + return EXIT_FAILURE; + } + + if (is_selinux_enabled()) { + fprintf(stderr, "Removing SELinux attributes on a SELinux enabled system is not supported!\n"); + return EXIT_FAILURE; + } + + for (int index = optind; index < argc; index++) + nuke(AT_FDCWD, argv[index], argv[index], dry_run, recursive, verbose); + + return EXIT_SUCCESS; +}
Introduce a helper to remove SELinux file contexts. Mainly for testing label operations and only for SELinux disabled systems, since removing file contexts is not supported by SELinux. Signed-off-by: Christian Göttsche <cgzones@googlemail.com> --- libselinux/utils/.gitignore | 1 + libselinux/utils/selabel_nuke.c | 134 ++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+) create mode 100644 libselinux/utils/selabel_nuke.c