Projects
openEuler:Mainline
libselinux
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 2
View file
_service:tar_scm:libselinux.spec
Changed
@@ -1,13 +1,15 @@ %global ruby_inc %(pkg-config --cflags ruby) -%global libsepol_version 3.3 +%global libsepol_version 3.4 Name: libselinux -Version: 3.3 +Version: 3.4 Release: 1 License: Public Domain Summary: SELinux library and simple utilities Url: https://github.com/SELinuxProject/selinux/wiki -Source0: https://github.com/SELinuxProject/selinux/releases/download/3.3/libselinux-3.3.tar.gz +Source0: https://github.com/SELinuxProject/selinux/releases/download/%{version}/libselinux-%{version}.tar.gz + +Patch6000: backport-libselinux-restorecon-avoid-printing-NULL-pointer.patch Patch9000: do-malloc-trim-after-load-policy.patch @@ -128,6 +130,12 @@ %{_mandir}/ru/man8/* %changelog +* Mon Jan 30 2023 zhangguangzhi <zhangguangzhi3@huawei.com> - 3.4-1 +- update version to 3.4 + +* Sun Oct 9 2022 lujie <lujie54@huawei.com> - 3.3-2 +- backport upstream patches + * Wed Dec 8 2021 lujie <lujie42@huawei.com> - 3.3-1 - update libselinux-3.1 to libselinux-3.3
View file
_service:tar_scm:backport-libselinux-restorecon-avoid-printing-NULL-pointer.patch
Added
@@ -0,0 +1,36 @@ +From 956bda08f6183078f13b70f6aa27d0529a3ec20a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com> +Date: Tue, 7 Jun 2022 19:00:35 +0200 +Subject: PATCH libselinux: restorecon: avoid printing NULL pointer +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The variable `curcon` is NULL in case the file has no current security +context. Most C standard libraries handle it fine, avoid it nonetheless +for standard conformance. + +Signed-off-by: Christian Göttsche <cgzones@googlemail.com> +Acked-by: Nicolas Iooss <nicolas.iooss@m4x.org> +--- + src/selinux_restorecon.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/selinux_restorecon.c b/src/selinux_restorecon.c +index 66e6a4a2..2d24559f 100644 +--- a/src/selinux_restorecon.c ++++ b/src/selinux_restorecon.c +@@ -744,7 +744,9 @@ static int restorecon_sb(const char *pathname, const struct stat *sb, + selinux_log(SELINUX_INFO, + "%s %s from %s to %s\n", + updated ? "Relabeled" : "Would relabel", +- pathname, curcon, newcon); ++ pathname, ++ curcon ? curcon : "<no context>", ++ newcon); + + if (flags->syslog_changes && !flags->nochange) { + if (curcon) +-- +2.27.0 +
View file
_service
Changed
@@ -2,7 +2,7 @@ <service name="tar_scm"> <param name="scm">git</param> <param name="url">git@gitee.com:src-openeuler/libselinux.git</param> - <param name="revision">a5d9f90711da2a405930479bd2cfbefb3e8c3fe2</param> + <param name="revision">master</param> <param name="exclude">*</param> <param name="extract">*</param> </service>
View file
_service:tar_scm:libselinux-3.3.tar.gz/Makefile -> _service:tar_scm:libselinux-3.4.tar.gz/Makefile
Changed
@@ -23,7 +23,7 @@ endif export DISABLE_SETRANS DISABLE_RPM DISABLE_FLAGS ANDROID_HOST DISABLE_X11 LABEL_BACKEND_ANDROID -USE_PCRE2 ?= n +USE_PCRE2 ?= y ifeq ($(USE_PCRE2),y) PCRE_MODULE := libpcre2-8 PCRE_CFLAGS := -DUSE_PCRE2 -DPCRE2_CODE_UNIT_WIDTH=8
View file
_service:tar_scm:libselinux-3.3.tar.gz/VERSION -> _service:tar_scm:libselinux-3.4.tar.gz/VERSION
Changed
@@ -1,1 +1,1 @@ -3.3 +3.4
View file
_service:tar_scm:libselinux-3.3.tar.gz/include/selinux/restorecon.h -> _service:tar_scm:libselinux-3.4.tar.gz/include/selinux/restorecon.h
Changed
@@ -2,6 +2,7 @@ #define _RESTORECON_H_ #include <sys/types.h> +#include <stddef.h> #include <stdarg.h> #ifdef __cplusplus @@ -23,6 +24,19 @@ */ extern int selinux_restorecon(const char *pathname, unsigned int restorecon_flags); +/** + * selinux_restorecon_parallel - Relabel files, optionally use more threads. + * @pathname: specifies file/directory to relabel. + * @restorecon_flags: specifies the actions to be performed when relabeling. + * @nthreads: specifies the number of threads to use (0 = use number of CPUs + * currently online) + * + * Same as selinux_restorecon(3), but allows to use multiple threads to do + * the work. + */ +extern int selinux_restorecon_parallel(const char *pathname, + unsigned int restorecon_flags, + size_t nthreads); /* * restorecon_flags options */ @@ -107,6 +121,11 @@ */ #define SELINUX_RESTORECON_CONFLICT_ERROR 0x10000 +/* + * Count, but otherwise ignore, errors during the file tree walk. + */ +#define SELINUX_RESTORECON_COUNT_ERRORS 0x20000 + /** * selinux_restorecon_set_sehandle - Set the global fc handle. * @hndl: specifies handle to set as the global fc handle. @@ -191,6 +210,16 @@ /* Do not read /proc/mounts. */ #define SELINUX_RESTORECON_XATTR_IGNORE_MOUNTS 0x0008 +/* selinux_restorecon_get_skipped_errors - Get the number of errors ignored + * during re-labeling. + * + * If SELINUX_RESTORECON_COUNT_ERRORS was passed to selinux_restorecon(3) or + * selinux_restorecon_parallel(3), and that function returned successfully + * (i.e., with a zero return value), then this function returns the number of + * errors ignored during the file tree walk. + */ +extern long unsigned selinux_restorecon_get_skipped_errors(void); + #ifdef __cplusplus } #endif
View file
_service:tar_scm:libselinux-3.3.tar.gz/man/man3/getfilecon.3 -> _service:tar_scm:libselinux-3.4.tar.gz/man/man3/getfilecon.3
Changed
@@ -33,7 +33,9 @@ .BR getfilecon (), only the open file pointed to by filedes (as returned by .BR open (2)) -is interrogated in place of path. +is interrogated in place of path. Since libselinux 3.4 a file opened via +.I O_PATH +is supported. .BR getfilecon_raw (), .BR lgetfilecon_raw ()
View file
_service:tar_scm:libselinux-3.3.tar.gz/man/man3/selabel_open.3 -> _service:tar_scm:libselinux-3.4.tar.gz/man/man3/selabel_open.3
Changed
@@ -10,7 +10,7 @@ .br .B #include <selinux/label.h> .sp -.BI "struct selabel_handle *selabel_open(int " backend , +.BI "struct selabel_handle *selabel_open(unsigned int " backend , .in +\w'struct selabel_handle *selabel_open('u .BI "const struct selinux_opt *" options , .br
View file
_service:tar_scm:libselinux-3.3.tar.gz/man/man3/selinux_restorecon.3 -> _service:tar_scm:libselinux-3.4.tar.gz/man/man3/selinux_restorecon.3
Changed
@@ -11,6 +11,14 @@ .br .BI "unsigned int " restorecon_flags ");" .in +.sp +.BI "int selinux_restorecon_parallel(const char *" pathname , +.in +\w'int selinux_restorecon_parallel('u +.br +.BI "unsigned int " restorecon_flags "," +.br +.BI "size_t " nthreads ");" +.in . .SH "DESCRIPTION" .BR selinux_restorecon () @@ -70,7 +78,10 @@ .IR security.sehash extended attribute once relabeling has been completed successfully provided the .B SELINUX_RESTORECON_NOCHANGE -flag has not been set. +flag has not been set, and no errors have been skipped during the file tree walk +due to the +.B SELINUX_RESTORECON_COUNT_ERRORS +flag. .sp .B SELINUX_RESTORECON_NOCHANGE don't change any file labels (passive check) or update the digest in the @@ -156,6 +167,21 @@ .B SELINUX_RESTORECON_CONFLICT_ERROR to treat conflicting specifications, such as where two hardlinks for the same inode have different contexts, as errors. +.sp +.B SELINUX_RESTORECON_COUNT_ERRORS +Count, but otherwise ignore, errors during the file tree walk. Only makes a +difference if the +.B SELINUX_RESTORECON_ABORT_ON_ERROR +flag is clear. Call +.BR selinux_restorecon_get_skipped_errors (3) +for fetching the ignored (skipped) error count after +.BR selinux_restorecon (3) +or +.BR selinux_restorecon_parallel (3) +completes with success. In case any errors were skipped during the file tree +walk, the specfile entries SHA1 digest will not have been written to the +.IR security.sehash +extended attribute. .RE .sp The behavior regarding the checking and updating of the SHA1 digest described @@ -187,6 +213,27 @@ .B SELINUX_RESTORECON_IGNORE_MOUNTS flag has been set. .RE +.sp +.BR selinux_restorecon_parallel() +is similar to +.BR selinux_restorecon (3), +but accepts another parameter that allows to run relabeling over multiple +threads: +.sp +.RS +.IR nthreads +specifies the number of threads to use during relabeling. When set to 1, +the behavior is the same as calling +.BR selinux_restorecon (3). +When set to 0, the function will try to use as many threads as there are +online CPU cores. When set to any other number, the function will try to use +the given number of threads. +.sp +Note that to use the parallel relabeling capability, the calling process +must be linked with the +.B libpthread +library (either at compile time or dynamically at run time). Otherwise the +function will print a warning and fall back to the single threaded mode. . .SH "RETURN VALUE" On success, zero is returned. On error, \-1 is returned and @@ -250,6 +297,8 @@ .br .BR selinux_restorecon_default_handle (3), .br +.BR selinux_restorecon_get_skipped_errors (3), +.br .BR selinux_restorecon_set_exclude_list (3), .br .BR selinux_restorecon_set_alt_rootpath (3),
View file
_service:tar_scm:libselinux-3.4.tar.gz/man/man3/selinux_restorecon_get_skipped_errors.3
Added
@@ -0,0 +1,28 @@ +.TH "selinux_restorecon_get_skipped_errors" "3" "27 Apr 2022" "Security Enhanced Linux" "SELinux API documentation" + +.SH "NAME" +selinux_restorecon_get_skipped_errors \- get the number of errors ignored by +.BR selinux_restorecon (3) +or +.BR selinux_restorecon_parallel (3) +during the file tree walk +. +.SH "SYNOPSIS" +.B #include <selinux/restorecon.h> +.sp +.BI "long unsigned selinux_restorecon_get_skipped_errors(void);" +.in +\w'long unsigned selinux_restorecon_get_skipped_errors('u +. +.SH "DESCRIPTION" +If +.B SELINUX_RESTORECON_COUNT_ERRORS +was passed to +.BR selinux_restorecon (3) +or +.BR selinux_restorecon_parallel (3) +and that function returned successfully (i.e., with a zero return value), then +.BR selinux_restorecon_get_skipped_errors () +returns the number of errors ignored during the file tree walk. +. +.SH "SEE ALSO" +.BR selinux_restorecon (3)
View file
_service:tar_scm:libselinux-3.4.tar.gz/man/man3/selinux_restorecon_parallel.3
Added
@@ -0,0 +1,1 @@ +.so man3/selinux_restorecon.3
View file
_service:tar_scm:libselinux-3.3.tar.gz/man/man3/setfilecon.3 -> _service:tar_scm:libselinux-3.4.tar.gz/man/man3/setfilecon.3
Changed
@@ -5,17 +5,17 @@ .SH "SYNOPSIS" .B #include <selinux/selinux.h> .sp -.BI "int setfilecon(const char *" path ", char *" con ); +.BI "int setfilecon(const char *" path ", const char *" con ); .sp -.BI "int setfilecon_raw(const char *" path ", char *" con ); +.BI "int setfilecon_raw(const char *" path ", const char *" con ); .sp -.BI "int lsetfilecon(const char *" path ", char *" con ); +.BI "int lsetfilecon(const char *" path ", const char *" con ); .sp -.BI "int lsetfilecon_raw(const char *" path ", char *" con ); +.BI "int lsetfilecon_raw(const char *" path ", const char *" con ); .sp -.BI "int fsetfilecon(int "fd ", char *" con ); +.BI "int fsetfilecon(int "fd ", const char *" con ); .sp -.BI "int fsetfilecon_raw(int "fd ", char *" con ); +.BI "int fsetfilecon_raw(int "fd ", const char *" con ); . .SH "DESCRIPTION" .BR setfilecon () @@ -29,7 +29,9 @@ is identical to setfilecon, only the open file pointed to by filedes (as returned by .BR open (2)) -has it's context set in place of path. +has it's context set in place of path. Since libselinux 3.4 a file opened via +.I O_PATH +is supported. .BR setfilecon_raw (), .BR lsetfilecon_raw (),
View file
_service:tar_scm:libselinux-3.3.tar.gz/src/Makefile -> _service:tar_scm:libselinux-3.4.tar.gz/src/Makefile
Changed
@@ -98,7 +98,6 @@ LD_SONAME_FLAGS=-install_name,$(LIBSO) endif -PCRE_LDLIBS ?= -lpcre # override with -lfts when building on Musl libc to use fts-standalone FTS_LDLIBS ?=
View file
_service:tar_scm:libselinux-3.3.tar.gz/src/callbacks.c -> _service:tar_scm:libselinux-3.4.tar.gz/src/callbacks.c
Changed
@@ -10,6 +10,8 @@ #include <selinux/selinux.h> #include "callbacks.h" +pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER; + /* default implementations */ static int __attribute__ ((format(printf, 2, 3))) default_selinux_log(int type __attribute__((unused)), const char *fmt, ...) @@ -56,7 +58,7 @@ /* callback pointers */ int __attribute__ ((format(printf, 2, 3))) -(*selinux_log)(int, const char *, ...) = +(*selinux_log_direct)(int, const char *, ...) = default_selinux_log; int @@ -81,7 +83,7 @@ { switch (type) { case SELINUX_CB_LOG: - selinux_log = cb.func_log; + selinux_log_direct = cb.func_log; break; case SELINUX_CB_AUDIT: selinux_audit = cb.func_audit; @@ -106,7 +108,7 @@ switch (type) { case SELINUX_CB_LOG: - cb.func_log = selinux_log; + cb.func_log = selinux_log_direct; break; case SELINUX_CB_AUDIT: cb.func_audit = selinux_audit;
View file
_service:tar_scm:libselinux-3.3.tar.gz/src/callbacks.h -> _service:tar_scm:libselinux-3.4.tar.gz/src/callbacks.h
Changed
@@ -5,14 +5,17 @@ #ifndef _SELINUX_CALLBACKS_H_ #define _SELINUX_CALLBACKS_H_ +#include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <selinux/selinux.h> +#include "selinux_internal.h" + /* callback pointers */ extern int __attribute__ ((format(printf, 2, 3))) -(*selinux_log) (int type, const char *, ...) ; +(*selinux_log_direct) (int type, const char *, ...) ; extern int (*selinux_audit) (void *, security_class_t, char *, size_t) ; @@ -26,4 +29,15 @@ extern int (*selinux_netlink_policyload) (int seqno) ; +/* Thread-safe selinux_log() function */ +extern pthread_mutex_t log_mutex; + +#define selinux_log(type, ...) do { \ + int saved_errno__ = errno; \ + __pthread_mutex_lock(&log_mutex); \ + selinux_log_direct(type, __VA_ARGS__); \ + __pthread_mutex_unlock(&log_mutex); \ + errno = saved_errno__; \ +} while(0) + #endif /* _SELINUX_CALLBACKS_H_ */
View file
_service:tar_scm:libselinux-3.3.tar.gz/src/fgetfilecon.c -> _service:tar_scm:libselinux-3.4.tar.gz/src/fgetfilecon.c
Changed
@@ -3,10 +3,32 @@ #include <string.h> #include <stdlib.h> #include <errno.h> +#include <stdio.h> #include <sys/xattr.h> #include "selinux_internal.h" #include "policy.h" +static ssize_t fgetxattr_wrapper(int fd, const char *name, void *value, size_t size) { + char buf40; + int fd_flag, saved_errno = errno; + ssize_t ret; + + ret = fgetxattr(fd, name, value, size); + if (ret != -1 || errno != EBADF) + return ret; + + /* Emulate O_PATH support */ + fd_flag = fcntl(fd, F_GETFL); + if (fd_flag == -1 || (fd_flag & O_PATH) == 0) { + errno = EBADF; + return -1; + } + + snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd); + errno = saved_errno; + return getxattr(buf, name, value, size); +} + int fgetfilecon_raw(int fd, char ** context) { char *buf; @@ -19,11 +41,11 @@ return -1; memset(buf, 0, size); - ret = fgetxattr(fd, XATTR_NAME_SELINUX, buf, size - 1); + ret = fgetxattr_wrapper(fd, XATTR_NAME_SELINUX, buf, size - 1); if (ret < 0 && errno == ERANGE) { char *newbuf; - size = fgetxattr(fd, XATTR_NAME_SELINUX, NULL, 0); + size = fgetxattr_wrapper(fd, XATTR_NAME_SELINUX, NULL, 0); if (size < 0) goto out; @@ -34,7 +56,7 @@ buf = newbuf; memset(buf, 0, size); - ret = fgetxattr(fd, XATTR_NAME_SELINUX, buf, size - 1); + ret = fgetxattr_wrapper(fd, XATTR_NAME_SELINUX, buf, size - 1); } out: if (ret == 0) {
View file
_service:tar_scm:libselinux-3.3.tar.gz/src/fsetfilecon.c -> _service:tar_scm:libselinux-3.4.tar.gz/src/fsetfilecon.c
Changed
@@ -3,13 +3,34 @@ #include <string.h> #include <stdlib.h> #include <errno.h> +#include <stdio.h> #include <sys/xattr.h> #include "selinux_internal.h" #include "policy.h" +static int fsetxattr_wrapper(int fd, const char* name, const void* value, size_t size, int flags) { + char buf40; + int rc, fd_flag, saved_errno = errno; + + rc = fsetxattr(fd, name, value, size, flags); + if (rc == 0 || errno != EBADF) + return rc; + + /* Emulate O_PATH support */ + fd_flag = fcntl(fd, F_GETFL); + if (fd_flag == -1 || (fd_flag & O_PATH) == 0) { + errno = EBADF; + return -1; + } + + snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd); + errno = saved_errno; + return setxattr(buf, name, value, size, flags); +} + int fsetfilecon_raw(int fd, const char * context) { - int rc = fsetxattr(fd, XATTR_NAME_SELINUX, context, strlen(context) + 1, + int rc = fsetxattr_wrapper(fd, XATTR_NAME_SELINUX, context, strlen(context) + 1, 0); if (rc < 0 && errno == ENOTSUP) { char * ccontext = NULL;
View file
_service:tar_scm:libselinux-3.3.tar.gz/src/is_customizable_type.c -> _service:tar_scm:libselinux-3.4.tar.gz/src/is_customizable_type.c
Changed
@@ -9,7 +9,10 @@ #include "selinux_internal.h" #include "context_internal.h" -static int get_customizable_type_list(char *** retlist) +static char **customizable_list = NULL; +static pthread_once_t customizable_once = PTHREAD_ONCE_INIT; + +static void customizable_init(void) { FILE *fp; char *buf; @@ -18,12 +21,12 @@ fp = fopen(selinux_customizable_types_path(), "re"); if (!fp) - return -1; + return; buf = malloc(selinux_page_size); if (!buf) { fclose(fp); - return -1; + return; } while (fgets_unlocked(buf, selinux_page_size, fp) && ctr < UINT_MAX) { ctr++; @@ -54,23 +57,19 @@ fclose(fp); free(buf); if (!list) - return -1; - *retlist = list; - return 0; + return; + customizable_list = list; } -static char **customizable_list = NULL; - int is_context_customizable(const char * scontext) { int i; const char *type; context_t c; - if (!customizable_list) { - if (get_customizable_type_list(&customizable_list) != 0) - return -1; - } + __selinux_once(customizable_once, customizable_init); + if (!customizable_list) + return -1; c = context_new(scontext); if (!c)
View file
_service:tar_scm:libselinux-3.3.tar.gz/src/label.c -> _service:tar_scm:libselinux-3.4.tar.gz/src/label.c
Changed
@@ -226,6 +226,8 @@ rec->digest = selabel_is_digest_set(opts, nopts, rec->digest); if ((*initfuncsbackend)(rec, opts, nopts)) { + if (rec->digest) + selabel_digest_fini(rec->digest); free(rec->spec_file); free(rec); rec = NULL;
View file
_service:tar_scm:libselinux-3.3.tar.gz/src/label_backends_android.c -> _service:tar_scm:libselinux-3.4.tar.gz/src/label_backends_android.c
Changed
@@ -93,7 +93,6 @@ items = read_spec_entries(line_buf, &errbuf, 2, &prop, &context); if (items < 0) { - items = errno; if (errbuf) { selinux_log(SELINUX_ERROR, "%s: line %u error due to: %s\n", path, @@ -103,7 +102,6 @@ "%s: line %u error due to: %m\n", path, lineno); } - errno = items; return -1; }
View file
_service:tar_scm:libselinux-3.3.tar.gz/src/label_file.c -> _service:tar_scm:libselinux-3.4.tar.gz/src/label_file.c
Changed
@@ -951,7 +951,12 @@ rc = regex_match(spec->regex, key, partial); if (rc == REGEX_MATCH || (partial && rc == REGEX_MATCH_PARTIAL)) { if (rc == REGEX_MATCH) { - spec->matches++; +#ifdef __ATOMIC_RELAXED + __atomic_store_n(&spec->any_matches, + true, __ATOMIC_RELAXED); +#else +#error "Please use a compiler that supports __atomic builtins" +#endif } if (strcmp(spec_arri.lr.ctx_raw, "<<none>>") == 0) { @@ -1249,9 +1254,15 @@ struct saved_data *data = (struct saved_data *)rec->data; unsigned int i, nspec = data->nspec; struct spec *spec_arr = data->spec_arr; + bool any_matches; for (i = 0; i < nspec; i++) { - if (spec_arri.matches == 0) { +#ifdef __ATOMIC_RELAXED + any_matches = __atomic_load_n(&spec_arri.any_matches, __ATOMIC_RELAXED); +#else +#error "Please use a compiler that supports __atomic builtins" +#endif + if (!any_matches) { if (spec_arri.type_str) { COMPAT_LOG(SELINUX_WARNING, "Warning! No matches for (%s, %s, %s)\n",
View file
_service:tar_scm:libselinux-3.3.tar.gz/src/label_file.h -> _service:tar_scm:libselinux-3.4.tar.gz/src/label_file.h
Changed
@@ -51,7 +51,7 @@ bool regex_compiled; /* bool to indicate if the regex is compiled */ pthread_mutex_t regex_lock; /* lock for lazy compilation of regex */ mode_t mode; /* mode format value */ - int matches; /* number of matching pathnames */ + bool any_matches; /* did any pathname match? */ int stem_id; /* indicates which stem-compression item */ char hasMetaChars; /* regular expression has meta-chars */ char from_mmap; /* this spec is from an mmap of the data */ @@ -444,7 +444,6 @@ items = read_spec_entries(line_buf, &errbuf, 3, ®ex, &type, &context); if (items < 0) { - rc = errno; if (errbuf) { selinux_log(SELINUX_ERROR, "%s: line %u error due to: %s\n", path, @@ -454,7 +453,6 @@ "%s: line %u error due to: %m\n", path, lineno); } - errno = rc; return -1; }
View file
_service:tar_scm:libselinux-3.3.tar.gz/src/label_media.c -> _service:tar_scm:libselinux-3.4.tar.gz/src/label_media.c
Changed
@@ -95,10 +95,10 @@ __fsetlocking(fp, FSETLOCKING_BYCALLER); if (fstat(fileno(fp), &sb) < 0) - return -1; + goto finish; if (!S_ISREG(sb.st_mode)) { errno = EINVAL; - return -1; + goto finish; } rec->spec_file = strdup(path);
View file
_service:tar_scm:libselinux-3.3.tar.gz/src/label_support.c -> _service:tar_scm:libselinux-3.4.tar.gz/src/label_support.c
Changed
@@ -116,13 +116,25 @@ void digest_gen_hash(struct selabel_digest *digest) { Sha1Context context; + size_t remaining_size; + const unsigned char *ptr; /* If SELABEL_OPT_DIGEST not set then just return */ if (!digest) return; Sha1Initialise(&context); - Sha1Update(&context, digest->hashbuf, digest->hashbuf_size); + + /* Process in blocks of UINT32_MAX bytes */ + remaining_size = digest->hashbuf_size; + ptr = digest->hashbuf; + while (remaining_size > UINT32_MAX) { + Sha1Update(&context, ptr, UINT32_MAX); + remaining_size -= UINT32_MAX; + ptr += UINT32_MAX; + } + Sha1Update(&context, ptr, remaining_size); + Sha1Finalise(&context, (SHA1_HASH *)digest->digest); free(digest->hashbuf); digest->hashbuf = NULL;
View file
_service:tar_scm:libselinux-3.3.tar.gz/src/label_x.c -> _service:tar_scm:libselinux-3.4.tar.gz/src/label_x.c
Changed
@@ -122,10 +122,10 @@ __fsetlocking(fp, FSETLOCKING_BYCALLER); if (fstat(fileno(fp), &sb) < 0) - return -1; + goto finish; if (!S_ISREG(sb.st_mode)) { errno = EINVAL; - return -1; + goto finish; } rec->spec_file = strdup(path);
View file
_service:tar_scm:libselinux-3.3.tar.gz/src/libselinux.map -> _service:tar_scm:libselinux-3.4.tar.gz/src/libselinux.map
Changed
@@ -240,3 +240,9 @@ local: *; }; + +LIBSELINUX_3.4 { + global: + selinux_restorecon_get_skipped_errors; + selinux_restorecon_parallel; +} LIBSELINUX_1.0;
View file
_service:tar_scm:libselinux-3.3.tar.gz/src/matchpathcon.c -> _service:tar_scm:libselinux-3.4.tar.gz/src/matchpathcon.c
Changed
@@ -356,7 +356,7 @@ mycanoncon = default_canoncon; __selinux_once(once, matchpathcon_init_once); - __selinux_setspecific(destructor_key, (void *)1); + __selinux_setspecific(destructor_key, /* some valid address to please GCC */ &selinux_page_size); optionsSELABEL_OPT_SUBSET.type = SELABEL_OPT_SUBSET; optionsSELABEL_OPT_SUBSET.value = subset;
View file
_service:tar_scm:libselinux-3.3.tar.gz/src/procattr.c -> _service:tar_scm:libselinux-3.4.tar.gz/src/procattr.c
Changed
@@ -68,7 +68,7 @@ static inline void init_thread_destructor(void) { if (destructor_initialized == 0) { - __selinux_setspecific(destructor_key, (void *)1); + __selinux_setspecific(destructor_key, /* some valid address to please GCC */ &selinux_page_size); destructor_initialized = 1; } }
View file
_service:tar_scm:libselinux-3.3.tar.gz/src/selinux_config.c -> _service:tar_scm:libselinux-3.4.tar.gz/src/selinux_config.c
Changed
@@ -92,6 +92,7 @@ FILE *cfg = fopen(SELINUXCONFIG, "re"); if (cfg) { char *buf; + char *tag; int len = sizeof(SELINUXTAG) - 1; buf = malloc(selinux_page_size); if (!buf) { @@ -101,21 +102,24 @@ while (fgets_unlocked(buf, selinux_page_size, cfg)) { if (strncmp(buf, SELINUXTAG, len)) continue; + tag = buf+len; + while (isspace(*tag)) + tag++; if (!strncasecmp - (buf + len, "enforcing", sizeof("enforcing") - 1)) { + (tag, "enforcing", sizeof("enforcing") - 1)) { *enforce = 1; ret = 0; break; } else if (!strncasecmp - (buf + len, "permissive", + (tag, "permissive", sizeof("permissive") - 1)) { *enforce = 0; ret = 0; break; } else if (!strncasecmp - (buf + len, "disabled", + (tag, "disabled", sizeof("disabled") - 1)) { *enforce = -1; ret = 0; @@ -176,7 +180,10 @@ if (!strncasecmp(buf_p, SELINUXTYPETAG, sizeof(SELINUXTYPETAG) - 1)) { - type = strdup(buf_p + sizeof(SELINUXTYPETAG) - 1); + buf_p += sizeof(SELINUXTYPETAG) - 1; + while (isspace(*buf_p)) + buf_p++; + type = strdup(buf_p); if (!type) { free(line_buf); fclose(fp); @@ -199,6 +206,8 @@ } else if (!strncmp(buf_p, REQUIRESEUSERS, sizeof(REQUIRESEUSERS) - 1)) { value = buf_p + sizeof(REQUIRESEUSERS) - 1; + while (isspace(*value)) + value++; intptr = &require_seusers; } else { continue;
View file
_service:tar_scm:libselinux-3.3.tar.gz/src/selinux_internal.h -> _service:tar_scm:libselinux-3.4.tar.gz/src/selinux_internal.h
Changed
@@ -69,6 +69,22 @@ pthread_mutex_unlock(LOCK); \ } while (0) +#pragma weak pthread_create +#pragma weak pthread_join +#pragma weak pthread_cond_init +#pragma weak pthread_cond_signal +#pragma weak pthread_cond_destroy +#pragma weak pthread_cond_wait + +/* check if all functions needed to do parallel operations are available */ +#define __pthread_supported ( \ + pthread_create && \ + pthread_join && \ + pthread_cond_init && \ + pthread_cond_destroy && \ + pthread_cond_signal && \ + pthread_cond_wait \ +) #define SELINUXDIR "/etc/selinux/" #define SELINUXCONFIG SELINUXDIR "config"
View file
_service:tar_scm:libselinux-3.3.tar.gz/src/selinux_restorecon.c -> _service:tar_scm:libselinux-3.4.tar.gz/src/selinux_restorecon.c
Changed
@@ -44,7 +44,7 @@ static struct selabel_handle *fc_sehandle = NULL; static bool selabel_no_digest; static char *rootpath = NULL; -static int rootpathlen; +static size_t rootpathlen; /* Information on excluded fs and directories. */ struct edir { @@ -55,16 +55,20 @@ }; #define CALLER_EXCLUDED true static bool ignore_mounts; -static int exclude_non_seclabel_mounts(void); +static uint64_t exclude_non_seclabel_mounts(void); static int exclude_count = 0; static struct edir *exclude_lst = NULL; static uint64_t fc_count = 0; /* Number of files processed so far */ static uint64_t efile_count; /* Estimated total number of files */ +static pthread_mutex_t progress_mutex = PTHREAD_MUTEX_INITIALIZER; /* Store information on directories with xattr's. */ static struct dir_xattr *dir_xattr_list; static struct dir_xattr *dir_xattr_last; +/* Number of errors ignored during the file tree walk. */ +static long unsigned skipped_errors; + /* restorecon_flags for passing to restorecon_sb() */ struct rest_flags { bool nochange; @@ -82,6 +86,7 @@ bool ignore_noent; bool warnonnomatch; bool conflicterror; + bool count_errors; }; static void restorecon_init(void) @@ -164,6 +169,12 @@ return -1; } + if (exclude_count >= INT_MAX - 1) { + selinux_log(SELINUX_ERROR, "Too many directory excludes: %d.\n", exclude_count); + errno = EOVERFLOW; + return -1; + } + tmp_list = realloc(exclude_lst, sizeof(struct edir) * (exclude_count + 1)); if (!tmp_list) @@ -206,10 +217,10 @@ return 0; } -static int file_system_count(char *name) +static uint64_t file_system_count(const char *name) { struct statvfs statvfs_buf; - int nfile = 0; + uint64_t nfile = 0; memset(&statvfs_buf, 0, sizeof(statvfs_buf)); if (!statvfs(name, &statvfs_buf)) @@ -225,12 +236,13 @@ * that support security labels have the seclabel option, return * approximate total file count. */ -static int exclude_non_seclabel_mounts(void) +static uint64_t exclude_non_seclabel_mounts(void) { struct utsname uts; FILE *fp; size_t len; - int index = 0, found = 0, nfile = 0; + int index = 0, found = 0; + uint64_t nfile = 0; char *mount_info4; char *buf = NULL, *item; @@ -295,7 +307,8 @@ { char *sha1_buf = NULL; size_t i, digest_len = 0; - int rc, digest_result; + int rc; + enum digest_result digest_result; bool match; struct dir_xattr *new_entry; uint8_t *xattr_digest = NULL; @@ -411,6 +424,7 @@ } file_spec_t; static file_spec_t *fl_head; +static pthread_mutex_t fl_mutex = PTHREAD_MUTEX_INITIALIZER; /* * Try to add an association between an inode and a context. If there is a @@ -424,11 +438,12 @@ int h, ret; struct stat64 sb; + __pthread_mutex_lock(&fl_mutex); + if (!fl_head) { - fl_head = malloc(sizeof(file_spec_t) * HASH_BUCKETS); + fl_head = calloc(HASH_BUCKETS, sizeof(file_spec_t)); if (!fl_head) goto oom; - memset(fl_head, 0, sizeof(file_spec_t) * HASH_BUCKETS); } h = (ino + (ino >> HASH_BITS)) & HASH_MASK; @@ -445,11 +460,11 @@ fl->con = strdup(con); if (!fl->con) goto oom; - return 1; + goto unlock_1; } if (strcmp(fl->con, con) == 0) - return 1; + goto unlock_1; selinux_log(SELINUX_ERROR, "conflicting specifications for %s and %s, using %s.\n", @@ -458,6 +473,9 @@ fl->file = strdup(file); if (!fl->file) goto oom; + + __pthread_mutex_unlock(&fl_mutex); + if (flags->conflicterror) { selinux_log(SELINUX_ERROR, "treating conflicting specifications as an error.\n"); @@ -479,16 +497,24 @@ goto oom_freefl; fl->file = strdup(file); if (!fl->file) - goto oom_freefl; + goto oom_freeflcon; fl->next = prevfl->next; prevfl->next = fl; + + __pthread_mutex_unlock(&fl_mutex); return 0; +oom_freeflcon: + free(fl->con); oom_freefl: free(fl); oom: + __pthread_mutex_unlock(&fl_mutex); selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __func__); return -1; +unlock_1: + __pthread_mutex_unlock(&fl_mutex); + return 1; } /* @@ -557,7 +583,7 @@ * Called if SELINUX_RESTORECON_SET_SPECFILE_CTX is not set to check if * the type components differ, updating newtypecon if so. */ -static int compare_types(char *curcon, char *newcon, char **newtypecon) +static int compare_types(const char *curcon, const char *newcon, char **newtypecon) { int types_differ = 0; context_t cona; @@ -597,13 +623,13 @@ return rc; } -static int restorecon_sb(const char *pathname, const struct stat *sb, - struct rest_flags *flags) +static int restorecon_sb(const char *pathname, struct rest_flags *flags, bool first) { char *newcon = NULL; char *curcon = NULL; char *newtypecon = NULL; - int rc; + int fd = -1, rc; + struct stat stat_buf; bool updated = false; const char *lookup_path = pathname; float pc; @@ -618,24 +644,37 @@ lookup_path += rootpathlen; } + fd = open(pathname, O_PATH | O_NOFOLLOW | O_EXCL); + if (fd < 0) + goto err; + + rc = fstat(fd, &stat_buf); + if (rc < 0) + goto err; + if (rootpath != NULL && lookup_path0 == '\0') /* this is actually the root dir of the alt root. */ rc = selabel_lookup_raw(fc_sehandle, &newcon, "/", - sb->st_mode); + stat_buf.st_mode); else rc = selabel_lookup_raw(fc_sehandle, &newcon, lookup_path, - sb->st_mode); + stat_buf.st_mode); if (rc < 0) { - if (errno == ENOENT && flags->warnonnomatch) - selinux_log(SELINUX_INFO, - "Warning no default label for %s\n", - lookup_path); + if (errno == ENOENT) { + if (flags->warnonnomatch && first) + selinux_log(SELINUX_INFO, + "Warning no default label for %s\n", + lookup_path); - return 0; /* no match, but not an error */ + goto out; /* no match, but not an error */ + } + + goto err; } if (flags->progress) { + __pthread_mutex_lock(&progress_mutex); fc_count++; if (fc_count % STAR_COUNT == 0) { if (flags->mass_relabel && efile_count > 0) { @@ -647,22 +686,21 @@ } fflush(stdout); } + __pthread_mutex_unlock(&progress_mutex); } if (flags->add_assoc) { - rc = filespec_add(sb->st_ino, newcon, pathname, flags); + rc = filespec_add(stat_buf.st_ino, newcon, pathname, flags); if (rc < 0) { selinux_log(SELINUX_ERROR, "filespec_add error: %s\n", pathname); - freecon(newcon); - return -1; + goto out1; } if (rc > 0) { /* Already an association and it took precedence. */ - freecon(newcon); - return 0; + goto out; } } @@ -670,7 +708,7 @@ selinux_log(SELINUX_INFO, "%s matched by %s\n", pathname, newcon); - if (lgetfilecon_raw(pathname, &curcon) < 0) { + if (fgetfilecon_raw(fd, &curcon) < 0) { if (errno != ENODATA) goto err; @@ -703,7 +741,7 @@ } if (!flags->nochange) { - if (lsetfilecon(pathname, newcon) < 0) + if (fsetfilecon(fd, newcon) < 0) goto err; updated = true; } @@ -728,6 +766,8 @@ out: rc = 0; out1: + if (fd >= 0) + close(fd); freecon(curcon); freecon(newcon); return rc; @@ -800,66 +840,224 @@ goto free; } +struct rest_state { + struct rest_flags flags; + dev_t dev_num; + struct statfs sfsb; + bool ignore_digest; + bool setrestorecondigest; + bool parallel; -/* - * Public API - */ + FTS *fts; + FTSENT *ftsent_first; + struct dir_hash_node *head, *current; + bool abort; + int error; + long unsigned skipped_errors; + int saved_errno; + pthread_mutex_t mutex; +}; -/* selinux_restorecon(3) - Main function that is responsible for labeling */ -int selinux_restorecon(const char *pathname_orig, - unsigned int restorecon_flags) +static void *selinux_restorecon_thread(void *arg) { - struct rest_flags flags; + struct rest_state *state = arg; + FTS *fts = state->fts; + FTSENT *ftsent; + int error; + char ent_pathPATH_MAX; + bool first = false; + + if (state->parallel) + pthread_mutex_lock(&state->mutex); + + if (state->ftsent_first) { + ftsent = state->ftsent_first; + state->ftsent_first = NULL; + first = true; + goto loop_body; + } + + while (((void)(errno = 0), ftsent = fts_read(fts)) != NULL) { +loop_body: + /* If the FTS_XDEV flag is set and the device is different */ + if (state->flags.set_xdev && + ftsent->fts_statp->st_dev != state->dev_num) + continue; - flags.nochange = (restorecon_flags & + switch (ftsent->fts_info) { + case FTS_DC: + selinux_log(SELINUX_ERROR, + "Directory cycle on %s.\n", + ftsent->fts_path); + errno = ELOOP; + state->error = -1; + state->abort = true; + goto finish; + case FTS_DP: + continue; + case FTS_DNR: + error = errno; + errno = ftsent->fts_errno; + selinux_log(SELINUX_ERROR, + "Could not read %s: %m.\n", + ftsent->fts_path); + errno = error; + fts_set(fts, ftsent, FTS_SKIP); + continue; + case FTS_NS: + error = errno; + errno = ftsent->fts_errno; + selinux_log(SELINUX_ERROR, + "Could not stat %s: %m.\n", + ftsent->fts_path); + errno = error; + fts_set(fts, ftsent, FTS_SKIP); + continue; + case FTS_ERR: + error = errno; + errno = ftsent->fts_errno; + selinux_log(SELINUX_ERROR, + "Error on %s: %m.\n", + ftsent->fts_path); + errno = error; + fts_set(fts, ftsent, FTS_SKIP); + continue; + case FTS_D: + if (state->sfsb.f_type == SYSFS_MAGIC && + !selabel_partial_match(fc_sehandle, + ftsent->fts_path)) { + fts_set(fts, ftsent, FTS_SKIP); + continue; + } + + if (check_excluded(ftsent->fts_path)) { + fts_set(fts, ftsent, FTS_SKIP); + continue; + } + + if (state->setrestorecondigest) { + struct dir_hash_node *new_node = NULL; + + if (check_context_match_for_dir(ftsent->fts_path, + &new_node, + state->error) && + !state->ignore_digest) { + selinux_log(SELINUX_INFO, + "Skipping restorecon on directory(%s)\n", + ftsent->fts_path); + fts_set(fts, ftsent, FTS_SKIP); + continue; + } + + if (new_node && !state->error) { + if (!state->current) { + state->current = new_node; + state->head = state->current; + } else { + state->current->next = new_node; + state->current = new_node; + } + } + } + /* fall through */ + default: + strcpy(ent_path, ftsent->fts_path); + + if (state->parallel) + pthread_mutex_unlock(&state->mutex); + + error = restorecon_sb(ent_path, &state->flags, + first); + + if (state->parallel) { + pthread_mutex_lock(&state->mutex); + if (state->abort) + goto unlock; + } + + first = false; + if (error) { + if (state->flags.abort_on_error) { + state->error = error; + state->abort = true; + goto finish; + } + if (state->flags.count_errors) + state->skipped_errors++; + else + state->error = error; + } + break; + } + } + +finish: + if (!state->saved_errno) + state->saved_errno = errno; +unlock: + if (state->parallel) + pthread_mutex_unlock(&state->mutex); + return NULL; +} + +static int selinux_restorecon_common(const char *pathname_orig, + unsigned int restorecon_flags, + size_t nthreads) +{ + struct rest_state state; + + state.flags.nochange = (restorecon_flags & SELINUX_RESTORECON_NOCHANGE) ? true : false; - flags.verbose = (restorecon_flags & + state.flags.verbose = (restorecon_flags & SELINUX_RESTORECON_VERBOSE) ? true : false; - flags.progress = (restorecon_flags & + state.flags.progress = (restorecon_flags & SELINUX_RESTORECON_PROGRESS) ? true : false; - flags.mass_relabel = (restorecon_flags & + state.flags.mass_relabel = (restorecon_flags & SELINUX_RESTORECON_MASS_RELABEL) ? true : false; - flags.recurse = (restorecon_flags & + state.flags.recurse = (restorecon_flags & SELINUX_RESTORECON_RECURSE) ? true : false; - flags.set_specctx = (restorecon_flags & + state.flags.set_specctx = (restorecon_flags & SELINUX_RESTORECON_SET_SPECFILE_CTX) ? true : false; - flags.userealpath = (restorecon_flags & + state.flags.userealpath = (restorecon_flags & SELINUX_RESTORECON_REALPATH) ? true : false; - flags.set_xdev = (restorecon_flags & + state.flags.set_xdev = (restorecon_flags & SELINUX_RESTORECON_XDEV) ? true : false; - flags.add_assoc = (restorecon_flags & + state.flags.add_assoc = (restorecon_flags & SELINUX_RESTORECON_ADD_ASSOC) ? true : false; - flags.abort_on_error = (restorecon_flags & + state.flags.abort_on_error = (restorecon_flags & SELINUX_RESTORECON_ABORT_ON_ERROR) ? true : false; - flags.syslog_changes = (restorecon_flags & + state.flags.syslog_changes = (restorecon_flags & SELINUX_RESTORECON_SYSLOG_CHANGES) ? true : false; - flags.log_matches = (restorecon_flags & + state.flags.log_matches = (restorecon_flags & SELINUX_RESTORECON_LOG_MATCHES) ? true : false; - flags.ignore_noent = (restorecon_flags & + state.flags.ignore_noent = (restorecon_flags & SELINUX_RESTORECON_IGNORE_NOENTRY) ? true : false; - flags.warnonnomatch = true; - flags.conflicterror = (restorecon_flags & + state.flags.warnonnomatch = true; + state.flags.conflicterror = (restorecon_flags & SELINUX_RESTORECON_CONFLICT_ERROR) ? true : false; ignore_mounts = (restorecon_flags & SELINUX_RESTORECON_IGNORE_MOUNTS) ? true : false; - bool ignore_digest = (restorecon_flags & + state.ignore_digest = (restorecon_flags & SELINUX_RESTORECON_IGNORE_DIGEST) ? true : false; - bool setrestorecondigest = true; + state.flags.count_errors = (restorecon_flags & + SELINUX_RESTORECON_COUNT_ERRORS) ? true : false; + state.setrestorecondigest = true; + + state.head = NULL; + state.current = NULL; + state.abort = false; + state.error = 0; + state.skipped_errors = 0; + state.saved_errno = 0; struct stat sb; - struct statfs sfsb; - FTS *fts; - FTSENT *ftsent; char *pathname = NULL, *pathdnamer = NULL, *pathdname, *pathbname; char *paths2 = { NULL, NULL }; - int fts_flags, error, sverrno; - dev_t dev_num = 0; + int fts_flags, error; struct dir_hash_node *current = NULL; - struct dir_hash_node *head = NULL; - int errno_tmp; - if (flags.verbose && flags.progress) - flags.verbose = false; + if (state.flags.verbose && state.flags.progress) + state.flags.verbose = false; __selinux_once(fc_once, restorecon_init); @@ -872,13 +1070,31 @@ */ if (selabel_no_digest || (restorecon_flags & SELINUX_RESTORECON_SKIP_DIGEST)) - setrestorecondigest = false; + state.setrestorecondigest = false; + + if (!__pthread_supported) { + if (nthreads != 1) { + nthreads = 1; + selinux_log(SELINUX_WARNING, + "Threading functionality not available, falling back to 1 thread."); + } + } else if (nthreads == 0) { + long nproc = sysconf(_SC_NPROCESSORS_ONLN); + + if (nproc > 0) { + nthreads = nproc; + } else { + nthreads = 1; + selinux_log(SELINUX_WARNING, + "Unable to detect CPU count, falling back to 1 thread."); + } + } /* * Convert passed-in pathname to canonical pathname by resolving * realpath of containing dir, then appending last component name. */ - if (flags.userealpath) { + if (state.flags.userealpath) { char *basename_cpy = strdup(pathname_orig); if (!basename_cpy) goto realpatherr; @@ -923,7 +1139,7 @@ paths0 = pathname; if (lstat(pathname, &sb) < 0) { - if (flags.ignore_noent && errno == ENOENT) { + if (state.flags.ignore_noent && errno == ENOENT) { free(pathdnamer); free(pathname); return 0; @@ -938,21 +1154,21 @@ /* Skip digest if not a directory */ if (!S_ISDIR(sb.st_mode)) - setrestorecondigest = false; + state.setrestorecondigest = false; - if (!flags.recurse) { + if (!state.flags.recurse) { if (check_excluded(pathname)) { error = 0; goto cleanup; } - error = restorecon_sb(pathname, &sb, &flags); + error = restorecon_sb(pathname, &state.flags, true); goto cleanup; } /* Obtain fs type */ - memset(&sfsb, 0, sizeof sfsb); - if (!S_ISLNK(sb.st_mode) && statfs(pathname, &sfsb) < 0) { + memset(&state.sfsb, 0, sizeof(state.sfsb)); + if (!S_ISLNK(sb.st_mode) && statfs(pathname, &state.sfsb) < 0) { selinux_log(SELINUX_ERROR, "statfs(%s) failed: %m\n", pathname); @@ -961,21 +1177,21 @@ } /* Skip digest on in-memory filesystems and /sys */ - if (sfsb.f_type == RAMFS_MAGIC || sfsb.f_type == TMPFS_MAGIC || - sfsb.f_type == SYSFS_MAGIC) - setrestorecondigest = false; + if (state.sfsb.f_type == RAMFS_MAGIC || state.sfsb.f_type == TMPFS_MAGIC || + state.sfsb.f_type == SYSFS_MAGIC) + state.setrestorecondigest = false; - if (flags.set_xdev) + if (state.flags.set_xdev) fts_flags = FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV; else fts_flags = FTS_PHYSICAL | FTS_NOCHDIR; - fts = fts_open(paths, fts_flags, NULL); - if (!fts) + state.fts = fts_open(paths, fts_flags, NULL); + if (!state.fts) goto fts_err; - ftsent = fts_read(fts); - if (!ftsent) + state.ftsent_first = fts_read(state.fts); + if (!state.ftsent_first) goto fts_err; /* @@ -987,106 +1203,69 @@ * directories with a different device number when the FTS_XDEV flag * is set (from http://marc.info/?l=selinux&m=124688830500777&w=2). */ - dev_num = ftsent->fts_statp->st_dev; + state.dev_num = state.ftsent_first->fts_statp->st_dev; - error = 0; - do { - /* If the FTS_XDEV flag is set and the device is different */ - if (flags.set_xdev && ftsent->fts_statp->st_dev != dev_num) - continue; + if (nthreads == 1) { + state.parallel = false; + selinux_restorecon_thread(&state); + } else { + size_t i; + pthread_t self = pthread_self(); + pthread_t *threads = NULL; - switch (ftsent->fts_info) { - case FTS_DC: - selinux_log(SELINUX_ERROR, - "Directory cycle on %s.\n", - ftsent->fts_path); - errno = ELOOP; - error = -1; - goto out; - case FTS_DP: - continue; - case FTS_DNR: - errno_tmp = errno; - errno = ftsent->fts_errno; - selinux_log(SELINUX_ERROR, - "Could not read %s: %m.\n", - ftsent->fts_path); - errno = errno_tmp; - fts_set(fts, ftsent, FTS_SKIP); - continue; - case FTS_NS: - errno_tmp = errno; - errno = ftsent->fts_errno; - selinux_log(SELINUX_ERROR, - "Could not stat %s: %m.\n", - ftsent->fts_path); - errno = errno_tmp; - fts_set(fts, ftsent, FTS_SKIP); - continue; - case FTS_ERR: - errno_tmp = errno; - errno = ftsent->fts_errno; - selinux_log(SELINUX_ERROR, - "Error on %s: %m.\n", - ftsent->fts_path); - errno = errno_tmp; - fts_set(fts, ftsent, FTS_SKIP); - continue; - case FTS_D: - if (sfsb.f_type == SYSFS_MAGIC && - !selabel_partial_match(fc_sehandle, - ftsent->fts_path)) { - fts_set(fts, ftsent, FTS_SKIP); - continue; - } + pthread_mutex_init(&state.mutex, NULL); - if (check_excluded(ftsent->fts_path)) { - fts_set(fts, ftsent, FTS_SKIP); - continue; - } + threads = calloc(nthreads - 1, sizeof(*threads)); + if (!threads) + goto oom; - if (setrestorecondigest) { - struct dir_hash_node *new_node = NULL; + state.parallel = true; + /* + * Start (nthreads - 1) threads - the main thread is going to + * take part, too. + */ + for (i = 0; i < nthreads - 1; i++) { + if (pthread_create(&threadsi, NULL, + selinux_restorecon_thread, &state)) { + /* + * If any thread fails to be created, just mark + * it as such and let the successfully created + * threads do the job. In the worst case the + * main thread will do everything, but that's + * still better than to give up. + */ + threadsi = self; + } + } - if (check_context_match_for_dir(ftsent->fts_path, - &new_node, - error) && - !ignore_digest) { - selinux_log(SELINUX_INFO, - "Skipping restorecon on directory(%s)\n", - ftsent->fts_path); - fts_set(fts, ftsent, FTS_SKIP); - continue; - } + /* Let's join in on the fun! */ + selinux_restorecon_thread(&state); - if (new_node && !error) { - if (!current) { - current = new_node; - head = current; - } else { - current->next = new_node; - current = current->next; - } - } - } - /* fall through */ - default: - error |= restorecon_sb(ftsent->fts_path, - ftsent->fts_statp, &flags); - if (flags.warnonnomatch) - flags.warnonnomatch = false; - if (error && flags.abort_on_error) - goto out; - break; + /* Now wait for all threads to finish. */ + for (i = 0; i < nthreads - 1; i++) { + /* Skip threads that failed to be created. */ + if (pthread_equal(threadsi, self)) + continue; + pthread_join(threadsi, NULL); } - } while ((ftsent = fts_read(fts)) != NULL); + free(threads); + + pthread_mutex_destroy(&state.mutex); + } + + error = state.error; + if (state.saved_errno) + goto out; /* * Labeling successful. Write partial match digests for subdirectories. * TODO: Write digest upon FTS_DP if no error occurs in its descents. + * Note: we can't ignore errors here that we've masked due to + * SELINUX_RESTORECON_COUNT_ERRORS. */ - if (setrestorecondigest && !flags.nochange && !error) { - current = head; + if (state.setrestorecondigest && !state.flags.nochange && !error && + state.skipped_errors == 0) { + current = state.head; while (current != NULL) { if (setxattr(current->path, RESTORECON_PARTIAL_MATCH_DIGEST, @@ -1100,23 +1279,24 @@ } } + skipped_errors = state.skipped_errors; + out: - if (flags.progress && flags.mass_relabel) + if (state.flags.progress && state.flags.mass_relabel) fprintf(stdout, "\r%s 100.0%%\n", pathname); - sverrno = errno; - (void) fts_close(fts); - errno = sverrno; + (void) fts_close(state.fts); + errno = state.saved_errno; cleanup: - if (flags.add_assoc) { - if (flags.verbose) + if (state.flags.add_assoc) { + if (state.flags.verbose) filespec_eval(); filespec_destroy(); } free(pathdnamer); free(pathname); - current = head; + current = state.head; while (current != NULL) { struct dir_hash_node *next = current->next; @@ -1127,18 +1307,14 @@ return error; oom: - sverrno = errno; selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __func__); - errno = sverrno; error = -1; goto cleanup; realpatherr: - sverrno = errno; selinux_log(SELINUX_ERROR, "SELinux: Could not get canonical path for %s restorecon: %m.\n", pathname_orig); - errno = sverrno; error = -1; goto cleanup; @@ -1150,6 +1326,26 @@ goto cleanup; } + +/* + * Public API + */ + +/* selinux_restorecon(3) - Main function that is responsible for labeling */ +int selinux_restorecon(const char *pathname_orig, + unsigned int restorecon_flags) +{ + return selinux_restorecon_common(pathname_orig, restorecon_flags, 1); +} + +/* selinux_restorecon_parallel(3) - Parallel version of selinux_restorecon(3) */ +int selinux_restorecon_parallel(const char *pathname_orig, + unsigned int restorecon_flags, + size_t nthreads) +{ + return selinux_restorecon_common(pathname_orig, restorecon_flags, nthreads); +} + /* selinux_restorecon_set_sehandle(3) is called to set the global fc handle */ void selinux_restorecon_set_sehandle(struct selabel_handle *hndl) { @@ -1219,7 +1415,7 @@ /* selinux_restorecon_set_alt_rootpath(3) sets an alternate rootpath. */ int selinux_restorecon_set_alt_rootpath(const char *alt_rootpath) { - int len; + size_t len; /* This should be NULL on first use */ if (rootpath) @@ -1360,3 +1556,8 @@ } return -1; } + +long unsigned selinux_restorecon_get_skipped_errors(void) +{ + return skipped_errors; +}
View file
_service:tar_scm:libselinux-3.3.tar.gz/src/selinuxswig_python.i -> _service:tar_scm:libselinux-3.4.tar.gz/src/selinuxswig_python.i
Changed
@@ -20,7 +20,7 @@ PERMISSIVE = 0 ENFORCING = 1 -def restorecon(path, recursive=False, verbose=False, force=False): +def restorecon(path, recursive=False, verbose=False, force=False, nthreads=1): """ Restore SELinux context on a given path Arguments: @@ -32,6 +32,8 @@ force -- Force reset of context to match file_context for customizable files, and the default file context, changing the user, role, range portion as well as the type (default False) + nthreads -- The number of threads to use during relabeling, or 0 to use as many + threads as there are online CPU cores (default 1) """ restorecon_flags = SELINUX_RESTORECON_IGNORE_DIGEST | SELINUX_RESTORECON_REALPATH @@ -41,7 +43,7 @@ restorecon_flags |= SELINUX_RESTORECON_VERBOSE if force: restorecon_flags |= SELINUX_RESTORECON_SET_SPECFILE_CTX - selinux_restorecon(os.path.expanduser(path), restorecon_flags) + selinux_restorecon_parallel(os.path.expanduser(path), restorecon_flags, nthreads) def chcon(path, context, recursive=False): """ Set the SELinux context on a given path """
View file
_service:tar_scm:libselinux-3.3.tar.gz/src/selinuxswig_python_exception.i -> _service:tar_scm:libselinux-3.4.tar.gz/src/selinuxswig_python_exception.i
Changed
@@ -1183,6 +1183,14 @@ } } +%exception selinux_restorecon_parallel { + $action + if (result < 0) { + PyErr_SetFromErrno(PyExc_OSError); + SWIG_fail; + } +} + %exception selinux_restorecon_set_alt_rootpath { $action if (result < 0) {
View file
_service:tar_scm:libselinux-3.3.tar.gz/src/setrans_client.c -> _service:tar_scm:libselinux-3.4.tar.gz/src/setrans_client.c
Changed
@@ -272,7 +272,7 @@ if (!has_setrans) return; if (destructor_initialized == 0) { - __selinux_setspecific(destructor_key, (void *)1); + __selinux_setspecific(destructor_key, /* some valid address to please GCC */ &selinux_page_size); destructor_initialized = 1; } }
View file
_service:tar_scm:libselinux-3.3.tar.gz/src/setup.py -> _service:tar_scm:libselinux-3.4.tar.gz/src/setup.py
Changed
@@ -4,7 +4,7 @@ setup( name="selinux", - version="3.3", + version="3.4", description="SELinux python 3 bindings", author="SELinux Project", author_email="selinux@vger.kernel.org",
View file
_service:tar_scm:libselinux-3.3.tar.gz/utils/Makefile -> _service:tar_scm:libselinux-3.4.tar.gz/utils/Makefile
Changed
@@ -44,7 +44,6 @@ override CFLAGS += -I../include -D_GNU_SOURCE $(DISABLE_FLAGS) $(PCRE_CFLAGS) override LDFLAGS += -L../src override LDLIBS += -lselinux $(FTS_LDLIBS) -PCRE_LDLIBS ?= -lpcre ifeq ($(ANDROID_HOST),y) TARGETS=sefcontext_compile
View file
_service:tar_scm:libselinux-3.3.tar.gz/utils/compute_av.c -> _service:tar_scm:libselinux-3.4.tar.gz/utils/compute_av.c
Changed
@@ -2,6 +2,7 @@ #include <sys/types.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <errno.h> #include <selinux/selinux.h> @@ -17,6 +18,16 @@ exit(1); } + if (security_check_context(argv1)) { + fprintf(stderr, "%s: invalid source context '%s'\n", argv0, argv1); + exit(4); + } + + if (security_check_context(argv2)) { + fprintf(stderr, "%s: invalid target context '%s'\n", argv0, argv2); + exit(5); + } + tclass = string_to_security_class(argv3); if (!tclass) { fprintf(stderr, "%s: invalid class '%s'\n", argv0, argv3); @@ -25,7 +36,7 @@ ret = security_compute_av(argv1, argv2, tclass, 1, &avd); if (ret < 0) { - fprintf(stderr, "%s: security_compute_av failed\n", argv0); + fprintf(stderr, "%s: security_compute_av failed: %s\n", argv0, strerror(errno)); exit(3); }
View file
_service:tar_scm:libselinux-3.3.tar.gz/utils/compute_create.c -> _service:tar_scm:libselinux-3.4.tar.gz/utils/compute_create.c
Changed
@@ -2,6 +2,7 @@ #include <sys/types.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <errno.h> #include <selinux/selinux.h> @@ -17,16 +18,26 @@ exit(1); } + if (security_check_context(argv1)) { + fprintf(stderr, "%s: invalid source context '%s'\n", argv0, argv1); + exit(4); + } + + if (security_check_context(argv2)) { + fprintf(stderr, "%s: invalid target context '%s'\n", argv0, argv2); + exit(5); + } + tclass = string_to_security_class(argv3); if (!tclass) { - fprintf(stderr, "Invalid class '%s'\n", argv3); + fprintf(stderr, "%s: invalid class '%s'\n", argv0, argv3); exit(2); } ret = security_compute_create(argv1, argv2, tclass, &buf); if (ret < 0) { - fprintf(stderr, "%s: security_compute_create failed\n", - argv0); + fprintf(stderr, "%s: security_compute_create failed: %s\n", + argv0, strerror(errno)); exit(3); }
View file
_service:tar_scm:libselinux-3.3.tar.gz/utils/compute_member.c -> _service:tar_scm:libselinux-3.4.tar.gz/utils/compute_member.c
Changed
@@ -2,6 +2,7 @@ #include <sys/types.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <errno.h> #include <selinux/selinux.h> @@ -17,16 +18,26 @@ exit(1); } + if (security_check_context(argv1)) { + fprintf(stderr, "%s: invalid source context '%s'\n", argv0, argv1); + exit(4); + } + + if (security_check_context(argv2)) { + fprintf(stderr, "%s: invalid target context '%s'\n", argv0, argv2); + exit(5); + } + tclass = string_to_security_class(argv3); if (!tclass) { - fprintf(stderr, "Invalid class '%s'\n", argv3); + fprintf(stderr, "%s: invalid class '%s'\n", argv0, argv3); exit(2); } ret = security_compute_member(argv1, argv2, tclass, &buf); if (ret < 0) { - fprintf(stderr, "%s: security_compute_member failed\n", - argv0); + fprintf(stderr, "%s: security_compute_member failed: %s\n", + argv0, strerror(errno)); exit(3); }
View file
_service:tar_scm:libselinux-3.3.tar.gz/utils/compute_relabel.c -> _service:tar_scm:libselinux-3.4.tar.gz/utils/compute_relabel.c
Changed
@@ -2,6 +2,7 @@ #include <sys/types.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <errno.h> #include <selinux/selinux.h> @@ -17,6 +18,16 @@ exit(1); } + if (security_check_context(argv1)) { + fprintf(stderr, "%s: invalid source context '%s'\n", argv0, argv1); + exit(4); + } + + if (security_check_context(argv2)) { + fprintf(stderr, "%s: invalid target context '%s'\n", argv0, argv2); + exit(5); + } + tclass = string_to_security_class(argv3); if (!tclass) { fprintf(stderr, "%s: invalid class '%s'\n", argv0, argv3); @@ -25,8 +36,8 @@ ret = security_compute_relabel(argv1, argv2, tclass, &buf); if (ret < 0) { - fprintf(stderr, "%s: security_compute_relabel failed\n", - argv0); + fprintf(stderr, "%s: security_compute_relabel failed: %s\n", + argv0, strerror(errno)); exit(3); }
View file
_service:tar_scm:libselinux-3.3.tar.gz/utils/getconlist.c -> _service:tar_scm:libselinux-3.4.tar.gz/utils/getconlist.c
Changed
@@ -55,7 +55,7 @@ /* If a context wasn't passed, use the current context. */ if (((argc - optind) < 2)) { if (getcon(&cur_context) < 0) { - fprintf(stderr, "Couldn't get current context.\n"); + fprintf(stderr, "Couldn't get current context: %s\n", strerror(errno)); free(level); return 2; }
View file
_service:tar_scm:libselinux-3.3.tar.gz/utils/getdefaultcon.c -> _service:tar_scm:libselinux-3.4.tar.gz/utils/getdefaultcon.c
Changed
@@ -62,12 +62,17 @@ /* If a context wasn't passed, use the current context. */ if (((argc - optind) < 2)) { if (getcon(&cur_context) < 0) { - fprintf(stderr, "Couldn't get current context.\n"); + fprintf(stderr, "Couldn't get current context: %s\n", strerror(errno)); return 2; } } else cur_context = argvoptind + 1; + if (security_check_context(cur_context)) { + fprintf(stderr, "%s: invalid from context '%s'\n", argv0, cur_context); + return 3; + } + if ((ret = getseuser(user, service, &seuser, &dlevel)) == 0) { if (! level) level=dlevel; if (role != NULL && role0)
View file
_service:tar_scm:libselinux-3.3.tar.gz/utils/getenforce.c -> _service:tar_scm:libselinux-3.4.tar.gz/utils/getenforce.c
Changed
@@ -1,6 +1,8 @@ #include <unistd.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> +#include <errno.h> #include <selinux/selinux.h> int main(int argc __attribute__ ((unused)), @@ -16,7 +18,7 @@ if (rc == 1) { rc = security_getenforce(); if (rc < 0) { - fputs("getenforce: getenforce() failed", stderr); + fprintf(stderr, "getenforce: security_getenforce() failed: %s\n", strerror(errno)); return 2; }
View file
_service:tar_scm:libselinux-3.3.tar.gz/utils/getfilecon.c -> _service:tar_scm:libselinux-3.4.tar.gz/utils/getfilecon.c
Changed
@@ -1,6 +1,8 @@ #include <unistd.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> +#include <errno.h> #include <selinux/selinux.h> int main(int argc, char **argv) @@ -16,8 +18,8 @@ for (i = 1; i < argc; i++) { rc = getfilecon(argvi, &buf); if (rc < 0) { - fprintf(stderr, "%s: getfilecon(%s) failed\n", argv0, - argvi); + fprintf(stderr, "%s: getfilecon(%s) failed: %s\n", argv0, + argvi, strerror(errno)); exit(2); } printf("%s\t%s\n", argvi, buf);
View file
_service:tar_scm:libselinux-3.3.tar.gz/utils/getpidcon.c -> _service:tar_scm:libselinux-3.4.tar.gz/utils/getpidcon.c
Changed
@@ -1,6 +1,8 @@ #include <unistd.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> +#include <errno.h> #include <selinux/selinux.h> int main(int argc, char **argv) @@ -21,7 +23,7 @@ rc = getpidcon(pid, &buf); if (rc < 0) { - fprintf(stderr, "%s: getpidcon() failed\n", argv0); + fprintf(stderr, "%s: getpidcon() failed: %s\n", argv0, strerror(errno)); exit(3); }
View file
_service:tar_scm:libselinux-3.3.tar.gz/utils/policyvers.c -> _service:tar_scm:libselinux-3.4.tar.gz/utils/policyvers.c
Changed
@@ -1,6 +1,8 @@ #include <unistd.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> +#include <errno.h> #include <selinux/selinux.h> int main(int argc __attribute__ ((unused)), char **argv) @@ -9,7 +11,7 @@ rc = security_policyvers(); if (rc < 0) { - fprintf(stderr, "%s: policyvers() failed\n", argv0); + fprintf(stderr, "%s: security_policyvers() failed: %s\n", argv0, strerror(errno)); exit(2); }
View file
_service:tar_scm:libselinux-3.3.tar.gz/utils/selabel_digest.c -> _service:tar_scm:libselinux-3.4.tar.gz/utils/selabel_digest.c
Changed
@@ -34,7 +34,7 @@ fp = popen(cmd, "r"); if (!fp) { - printf("Failed to run command line\n"); + fprintf(stderr, "Failed to run command '%s': %s\n", cmd, strerror(errno)); return -1; }
View file
_service:tar_scm:libselinux-3.3.tar.gz/utils/selabel_get_digests_all_partial_matches.c -> _service:tar_scm:libselinux-3.4.tar.gz/utils/selabel_get_digests_all_partial_matches.c
Changed
@@ -77,7 +77,8 @@ hnd = selabel_open(SELABEL_CTX_FILE, selabel_option, 2); if (!hnd) { fprintf(stderr, "ERROR: selabel_open - Could not obtain " - "handle.\n"); + "handle: %s\n", + strerror(errno)); return -1; }
View file
_service:tar_scm:libselinux-3.3.tar.gz/utils/selabel_lookup.c -> _service:tar_scm:libselinux-3.4.tar.gz/utils/selabel_lookup.c
Changed
@@ -91,7 +91,8 @@ hnd = selabel_open(backend, selabel_option, 2); if (!hnd) { fprintf(stderr, "ERROR: selabel_open - Could not obtain " - "handle.\n"); + "handle: %s\n", + strerror(errno)); return -1; }
View file
_service:tar_scm:libselinux-3.3.tar.gz/utils/selabel_lookup_best_match.c -> _service:tar_scm:libselinux-3.4.tar.gz/utils/selabel_lookup_best_match.c
Changed
@@ -117,7 +117,8 @@ hnd = selabel_open(SELABEL_CTX_FILE, options, 2); if (!hnd) { fprintf(stderr, "ERROR: selabel_open - Could not obtain " - "handle.\n"); + "handle: %s\n", + strerror(errno)); rc = -1; goto out; }
View file
_service:tar_scm:libselinux-3.3.tar.gz/utils/selabel_partial_match.c -> _service:tar_scm:libselinux-3.4.tar.gz/utils/selabel_partial_match.c
Changed
@@ -61,7 +61,8 @@ hnd = selabel_open(SELABEL_CTX_FILE, selabel_option, 2); if (!hnd) { fprintf(stderr, "ERROR: selabel_open - Could not obtain " - "handle.\n"); + "handle: %s\n", + strerror(errno)); return -1; }
View file
_service:tar_scm:libselinux-3.3.tar.gz/utils/selinuxexeccon.c -> _service:tar_scm:libselinux-3.4.tar.gz/utils/selinuxexeccon.c
Changed
@@ -16,7 +16,7 @@ exit(rc); } -static char * get_selinux_proc_context(const char *command, char * execcon) { +static char * get_selinux_proc_context(const char *command, const char * execcon) { char * fcon = NULL, *newcon = NULL; int ret = getfilecon(command, &fcon); @@ -43,6 +43,10 @@ } } else { con = strdup(argv2); + if (security_check_context(con)) { + fprintf(stderr, "%s: invalid from context '%s'\n", argv0, con); + return -1; + } } proccon = get_selinux_proc_context(argv1, con);
View file
_service:tar_scm:libselinux-3.3.tar.gz/utils/setenforce.c -> _service:tar_scm:libselinux-3.4.tar.gz/utils/setenforce.c
Changed
@@ -4,6 +4,7 @@ #include <ctype.h> #include <string.h> #include <strings.h> +#include <errno.h> #include <selinux/selinux.h> static __attribute__ ((__noreturn__)) void usage(const char *progname) @@ -35,7 +36,7 @@ usage(argv0); } if (rc < 0) { - fprintf(stderr, "%s: setenforce() failed\n", argv0); + fprintf(stderr, "%s: security_setenforce() failed: %s\n", argv0, strerror(errno)); return 2; } return 0;
View file
_service:tar_scm:libselinux-3.3.tar.gz/utils/setfilecon.c -> _service:tar_scm:libselinux-3.4.tar.gz/utils/setfilecon.c
Changed
@@ -1,6 +1,8 @@ #include <unistd.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> +#include <errno.h> #include <selinux/selinux.h> int main(int argc, char **argv) @@ -15,8 +17,8 @@ for (i = 2; i < argc; i++) { rc = setfilecon(argvi, argv1); if (rc < 0) { - fprintf(stderr, "%s: setfilecon(%s,%s) failed\n", - argv0, argvi, argv1); + fprintf(stderr, "%s: setfilecon(%s,%s) failed: %s\n", + argv0, argvi, argv1, strerror(errno)); exit(2); } }
View file
_service:tar_scm:libselinux-3.3.tar.gz/utils/validatetrans.c -> _service:tar_scm:libselinux-3.4.tar.gz/utils/validatetrans.c
Changed
@@ -17,12 +17,27 @@ exit(1); } + if (security_check_context(argv1)) { + fprintf(stderr, "%s: invalid source context '%s'\n", argv0, argv1); + exit(4); + } + + if (security_check_context(argv2)) { + fprintf(stderr, "%s: invalid target context '%s'\n", argv0, argv2); + exit(5); + } + tclass = string_to_security_class(argv3); if (!tclass) { fprintf(stderr, "%s: invalid class '%s'\n", argv0, argv3); exit(2); } + if (security_check_context(argv4)) { + fprintf(stderr, "%s: invalid new context '%s'\n", argv0, argv4); + exit(6); + } + ret = security_validatetrans(argv1, argv2, tclass, argv4); printf("security_validatetrans returned %d errno: %s\n", ret, strerror(errno));
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2