diff --git a/0001-libselinux-declare-return-value-of-context_str-3-con.patch b/0001-libselinux-declare-return-value-of-context_str-3-con.patch new file mode 100644 index 0000000..fdedafa --- /dev/null +++ b/0001-libselinux-declare-return-value-of-context_str-3-con.patch @@ -0,0 +1,111 @@ +From dd98fa322766760c4e1f029cf19d2515a583304f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Fri, 20 May 2022 15:16:10 +0200 +Subject: [PATCH] libselinux: declare return value of context_str(3) const +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Content-type: text/plain + +context_str(3) returns a string representation of the given context. +This string is owned by the context and free'd on context_free(3). +Declare it const, as already done in the man page, since it must not be +free'd by the caller. + +Signed-off-by: Christian Göttsche +Acked-by: Nicolas Iooss +--- + libselinux/include/selinux/context.h | 2 +- + libselinux/src/context.c | 2 +- + libselinux/src/get_context_list.c | 11 ++++++----- + libselinux/src/query_user_context.c | 2 +- + 4 files changed, 9 insertions(+), 8 deletions(-) + +diff --git a/libselinux/include/selinux/context.h b/libselinux/include/selinux/context.h +index 949fb1e14cac..82f4e690faa8 100644 +--- a/libselinux/include/selinux/context.h ++++ b/libselinux/include/selinux/context.h +@@ -25,7 +25,7 @@ extern "C" { + * for the same context_t* + */ + +- extern char *context_str(context_t); ++ extern const char *context_str(context_t); + + /* Free the storage used by a context */ + extern void context_free(context_t); +diff --git a/libselinux/src/context.c b/libselinux/src/context.c +index b2144c7cf76c..9dddbc5aa431 100644 +--- a/libselinux/src/context.c ++++ b/libselinux/src/context.c +@@ -116,7 +116,7 @@ void context_free(context_t context) + /* + * Return a pointer to the string value of the context. + */ +-char *context_str(context_t context) ++const char *context_str(context_t context) + { + context_private_t *n = context->ptr; + int i; +diff --git a/libselinux/src/get_context_list.c b/libselinux/src/get_context_list.c +index cfe38e59b207..d774b9cf604b 100644 +--- a/libselinux/src/get_context_list.c ++++ b/libselinux/src/get_context_list.c +@@ -143,6 +143,7 @@ static int get_context_user(FILE * fp, + char *linerole, *linetype; + char **new_reachable = NULL; + char *usercon_str; ++ const char *usercon_str2; + context_t con; + context_t usercon; + +@@ -257,20 +258,20 @@ static int get_context_user(FILE * fp, + rc = -1; + goto out; + } +- usercon_str = context_str(usercon); +- if (!usercon_str) { ++ usercon_str2 = context_str(usercon); ++ if (!usercon_str2) { + context_free(usercon); + rc = -1; + goto out; + } + + /* check whether usercon is already in reachable */ +- if (is_in_reachable(*reachable, usercon_str)) { ++ if (is_in_reachable(*reachable, usercon_str2)) { + context_free(usercon); + start = end; + continue; + } +- if (security_check_context(usercon_str) == 0) { ++ if (security_check_context(usercon_str2) == 0) { + new_reachable = realloc(*reachable, (*nreachable + 2) * sizeof(char *)); + if (!new_reachable) { + context_free(usercon); +@@ -278,7 +279,7 @@ static int get_context_user(FILE * fp, + goto out; + } + *reachable = new_reachable; +- new_reachable[*nreachable] = strdup(usercon_str); ++ new_reachable[*nreachable] = strdup(usercon_str2); + if (new_reachable[*nreachable] == NULL) { + context_free(usercon); + rc = -1; +diff --git a/libselinux/src/query_user_context.c b/libselinux/src/query_user_context.c +index b8125c96ed81..29a1b360e945 100644 +--- a/libselinux/src/query_user_context.c ++++ b/libselinux/src/query_user_context.c +@@ -115,7 +115,7 @@ int manual_user_enter_context(const char *user, char ** newcon) + int mls_enabled = is_selinux_mls_enabled(); + + context_t new_context; /* The new context chosen by the user */ +- char *user_context = NULL; /* String value of the user's context */ ++ const char *user_context = NULL; /* String value of the user's context */ + int done = 0; /* true if a valid sid has been obtained */ + + /* Initialize the context. How this is done depends on whether +-- +2.38.1 + diff --git a/0002-Revert-libselinux-restorecon-pin-file-to-avoid-TOCTO.patch b/0002-Revert-libselinux-restorecon-pin-file-to-avoid-TOCTO.patch index a10825b..3814ae4 100644 --- a/0002-Revert-libselinux-restorecon-pin-file-to-avoid-TOCTO.patch +++ b/0002-Revert-libselinux-restorecon-pin-file-to-avoid-TOCTO.patch @@ -1,6 +1,6 @@ -From f48635ccd34412a824f9d608326fcd669db9d63b Mon Sep 17 00:00:00 2001 +From de285252a1801397306032e070793889c9466845 Mon Sep 17 00:00:00 2001 From: Petr Lautrbach -Date: Tue, 31 May 2022 13:37:12 +0200 +Date: Tue, 31 May 2022 14:57:51 +0200 Subject: [PATCH] Revert "libselinux: restorecon: pin file to avoid TOCTOU issues" Content-type: text/plain @@ -24,12 +24,13 @@ without /proc mounted, e.g. setfiles: Could not set context for /: No such file or directory Signed-off-by: Petr Lautrbach +Acked-by: James Carter --- libselinux/src/selinux_restorecon.c | 43 ++++++++++++----------------- 1 file changed, 18 insertions(+), 25 deletions(-) diff --git a/libselinux/src/selinux_restorecon.c b/libselinux/src/selinux_restorecon.c -index dc222b425c95..a50005353265 100644 +index 9dd6be817832..9f5b326c19ec 100644 --- a/libselinux/src/selinux_restorecon.c +++ b/libselinux/src/selinux_restorecon.c @@ -623,13 +623,13 @@ out: @@ -168,5 +169,5 @@ index dc222b425c95..a50005353265 100644 } -- -2.36.1 +2.38.1 diff --git a/0003-libselinux-do-not-return-the-cached-prev_current-val.patch b/0003-libselinux-do-not-return-the-cached-prev_current-val.patch new file mode 100644 index 0000000..23ad7db --- /dev/null +++ b/0003-libselinux-do-not-return-the-cached-prev_current-val.patch @@ -0,0 +1,323 @@ +From c8ba7968b3abb1e17edd400bb795d5e452b57935 Mon Sep 17 00:00:00 2001 +From: Nicolas Iooss +Date: Sun, 29 May 2022 20:01:11 +0200 +Subject: [PATCH] libselinux: do not return the cached prev_current value when + using getpidcon() +Content-type: text/plain + +libselinux implements a cache mechanism for get*con() functions, such +that when a thread calls setcon(...) then getcon(...), the context is +directly returned. Unfortunately, getpidcon(pid, &context) uses the same +cached variable, so when a program uses setcon("something"), all later +calls to getpidcon(pid, ...) returns "something". This is a bug. + +Here is a program which illustrates this bug: + + #include + #include + + int main() { + char *context = ""; + if (getpidcon(1, &context) < 0) { + perror("getpidcon(1)"); + } + printf("getpidcon(1) = %s\n", context); + + if (getcon(&context) < 0) { + perror("getcon()"); + } + printf("getcon() = %s\n", context); + if (setcon(context) < 0) { + perror("setcon()"); + } + if (getpidcon(1, &context) < 0) { + perror("getpidcon(1)"); + } + printf("getpidcon(1) = %s\n", context); + + return 0; + } + +On an Arch Linux system using unconfined user, this program displays: + + getpidcon(1) = system_u:system_r:init_t + getcon() = unconfined_u:unconfined_r:unconfined_t + getpidcon(1) = unconfined_u:unconfined_r:unconfined_t + +With this commit, this program displays: + + getpidcon(1) = system_u:system_r:init_t + getcon() = unconfined_u:unconfined_r:unconfined_t + getpidcon(1) = system_u:system_r:init_t + +This bug was present in the first commit of +https://github.com/SELinuxProject/selinux git history. It was reported +in https://lore.kernel.org/selinux/20220121084012.GS7643@suse.com/ and a +patch to fix it was sent in +https://patchwork.kernel.org/project/selinux/patch/20220127130741.31940-1-jsegitz@suse.de/ +without a clear explanation. This patch added pid checks, which made +sense but were difficult to read. Instead, it is possible to change the +way the functions are called so that they directly know which cache +variable to use. + +Moreover, as the code is not clear at all (I spent too much time trying +to understand what the switch did and what the thread-local variable +contained), this commit also reworks libselinux/src/procattr.c to: +- not use hard-to-understand switch/case constructions on strings (they + are replaced by a new argument filled by macros) +- remove getpidattr_def macro (it was only used once, for pidcon, and + the code is clearer with one less macro) +- remove the pid parameter of setprocattrcon() and setprocattrcon_raw() + (it is always zero) + +Signed-off-by: Nicolas Iooss +Cc: Johannes Segitz +--- + libselinux/src/procattr.c | 147 +++++++++++++------------------------- + 1 file changed, 50 insertions(+), 97 deletions(-) + +diff --git a/libselinux/src/procattr.c b/libselinux/src/procattr.c +index 142fbf3a80e0..6f4cfb82479d 100644 +--- a/libselinux/src/procattr.c ++++ b/libselinux/src/procattr.c +@@ -11,11 +11,14 @@ + + #define UNSET (char *) -1 + ++/* Cached values so that when a thread calls set*con() then gen*con(), the value ++ * which was set is directly returned. ++ */ + static __thread char *prev_current = UNSET; +-static __thread char * prev_exec = UNSET; +-static __thread char * prev_fscreate = UNSET; +-static __thread char * prev_keycreate = UNSET; +-static __thread char * prev_sockcreate = UNSET; ++static __thread char *prev_exec = UNSET; ++static __thread char *prev_fscreate = UNSET; ++static __thread char *prev_keycreate = UNSET; ++static __thread char *prev_sockcreate = UNSET; + + static pthread_once_t once = PTHREAD_ONCE_INIT; + static pthread_key_t destructor_key; +@@ -111,43 +114,18 @@ out: + return fd; + } + +-static int getprocattrcon_raw(char ** context, +- pid_t pid, const char *attr) ++static int getprocattrcon_raw(char **context, pid_t pid, const char *attr, ++ const char *prev_context) + { + char *buf; + size_t size; + int fd; + ssize_t ret; + int errno_hold; +- char * prev_context; + + __selinux_once(once, init_procattr); + init_thread_destructor(); + +- switch (attr[0]) { +- case 'c': +- prev_context = prev_current; +- break; +- case 'e': +- prev_context = prev_exec; +- break; +- case 'f': +- prev_context = prev_fscreate; +- break; +- case 'k': +- prev_context = prev_keycreate; +- break; +- case 's': +- prev_context = prev_sockcreate; +- break; +- case 'p': +- prev_context = NULL; +- break; +- default: +- errno = ENOENT; +- return -1; +- } +- + if (prev_context && prev_context != UNSET) { + *context = strdup(prev_context); + if (!(*context)) { +@@ -194,13 +172,13 @@ static int getprocattrcon_raw(char ** context, + return ret; + } + +-static int getprocattrcon(char ** context, +- pid_t pid, const char *attr) ++static int getprocattrcon(char **context, pid_t pid, const char *attr, ++ const char *prev_context) + { + int ret; + char * rcontext; + +- ret = getprocattrcon_raw(&rcontext, pid, attr); ++ ret = getprocattrcon_raw(&rcontext, pid, attr, prev_context); + + if (!ret) { + ret = selinux_raw_to_trans_context(rcontext, context); +@@ -210,45 +188,24 @@ static int getprocattrcon(char ** context, + return ret; + } + +-static int setprocattrcon_raw(const char * context, +- pid_t pid, const char *attr) ++static int setprocattrcon_raw(const char *context, const char *attr, ++ char **prev_context) + { + int fd; + ssize_t ret; + int errno_hold; +- char **prev_context, *context2 = NULL; ++ char *context2 = NULL; + + __selinux_once(once, init_procattr); + init_thread_destructor(); + +- switch (attr[0]) { +- case 'c': +- prev_context = &prev_current; +- break; +- case 'e': +- prev_context = &prev_exec; +- break; +- case 'f': +- prev_context = &prev_fscreate; +- break; +- case 'k': +- prev_context = &prev_keycreate; +- break; +- case 's': +- prev_context = &prev_sockcreate; +- break; +- default: +- errno = ENOENT; +- return -1; +- } +- + if (!context && !*prev_context) + return 0; + if (context && *prev_context && *prev_context != UNSET + && !strcmp(context, *prev_context)) + return 0; + +- fd = openattr(pid, attr, O_RDWR | O_CLOEXEC); ++ fd = openattr(0, attr, O_RDWR | O_CLOEXEC); + if (fd < 0) + return -1; + if (context) { +@@ -279,8 +236,8 @@ out: + } + } + +-static int setprocattrcon(const char * context, +- pid_t pid, const char *attr) ++static int setprocattrcon(const char *context, const char *attr, ++ char **prev_context) + { + int ret; + char * rcontext; +@@ -288,62 +245,58 @@ static int setprocattrcon(const char * context, + if (selinux_trans_to_raw_context(context, &rcontext)) + return -1; + +- ret = setprocattrcon_raw(rcontext, pid, attr); ++ ret = setprocattrcon_raw(rcontext, attr, prev_context); + + freecon(rcontext); + + return ret; + } + +-#define getselfattr_def(fn, attr) \ ++#define getselfattr_def(fn, attr, prev_context) \ + int get##fn##_raw(char **c) \ + { \ +- return getprocattrcon_raw(c, 0, #attr); \ ++ return getprocattrcon_raw(c, 0, attr, prev_context); \ + } \ + int get##fn(char **c) \ + { \ +- return getprocattrcon(c, 0, #attr); \ ++ return getprocattrcon(c, 0, attr, prev_context); \ + } + +-#define setselfattr_def(fn, attr) \ ++#define setselfattr_def(fn, attr, prev_context) \ + int set##fn##_raw(const char * c) \ + { \ +- return setprocattrcon_raw(c, 0, #attr); \ ++ return setprocattrcon_raw(c, attr, &prev_context); \ + } \ + int set##fn(const char * c) \ + { \ +- return setprocattrcon(c, 0, #attr); \ ++ return setprocattrcon(c, attr, &prev_context); \ + } + +-#define all_selfattr_def(fn, attr) \ +- getselfattr_def(fn, attr) \ +- setselfattr_def(fn, attr) ++#define all_selfattr_def(fn, attr, prev_context) \ ++ getselfattr_def(fn, attr, prev_context) \ ++ setselfattr_def(fn, attr, prev_context) + +-#define getpidattr_def(fn, attr) \ +- int get##fn##_raw(pid_t pid, char **c) \ +- { \ +- if (pid <= 0) { \ +- errno = EINVAL; \ +- return -1; \ +- } else { \ +- return getprocattrcon_raw(c, pid, #attr); \ +- } \ +- } \ +- int get##fn(pid_t pid, char **c) \ +- { \ +- if (pid <= 0) { \ +- errno = EINVAL; \ +- return -1; \ +- } else { \ +- return getprocattrcon(c, pid, #attr); \ +- } \ +- } ++all_selfattr_def(con, "current", prev_current) ++ getselfattr_def(prevcon, "prev", NULL) ++ all_selfattr_def(execcon, "exec", prev_exec) ++ all_selfattr_def(fscreatecon, "fscreate", prev_fscreate) ++ all_selfattr_def(sockcreatecon, "sockcreate", prev_sockcreate) ++ all_selfattr_def(keycreatecon, "keycreate", prev_keycreate) + +-all_selfattr_def(con, current) +- getpidattr_def(pidcon, current) +- getselfattr_def(prevcon, prev) +- all_selfattr_def(execcon, exec) +- all_selfattr_def(fscreatecon, fscreate) +- all_selfattr_def(sockcreatecon, sockcreate) +- all_selfattr_def(keycreatecon, keycreate) ++int getpidcon_raw(pid_t pid, char **c) ++{ ++ if (pid <= 0) { ++ errno = EINVAL; ++ return -1; ++ } ++ return getprocattrcon_raw(c, pid, "current", NULL); ++} + ++int getpidcon(pid_t pid, char **c) ++{ ++ if (pid <= 0) { ++ errno = EINVAL; ++ return -1; ++ } ++ return getprocattrcon(c, pid, "current", NULL); ++} +-- +2.38.1 + diff --git a/0004-libselinux-simplify-policy-path-logic-to-avoid-unini.patch b/0004-libselinux-simplify-policy-path-logic-to-avoid-unini.patch new file mode 100644 index 0000000..7f6f82a --- /dev/null +++ b/0004-libselinux-simplify-policy-path-logic-to-avoid-unini.patch @@ -0,0 +1,89 @@ +From 31e3537624ad2d07271d4c02925ebc6cb942e0c6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Tue, 10 May 2022 20:20:36 +0200 +Subject: [PATCH] libselinux: simplify policy path logic to avoid uninitialized + read +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Content-type: text/plain + +In case the function __policy_init() gets called with a NULL pointer, +the stack variable path remains uninitialized (except at its last +index). If parsing the binary policy fails in sepol_policydb_read() the +error branch would access those uninitialized memory. + +Signed-off-by: Christian Göttsche +--- + libselinux/src/audit2why.c | 34 +++++++++++++--------------------- + 1 file changed, 13 insertions(+), 21 deletions(-) + +diff --git a/libselinux/src/audit2why.c b/libselinux/src/audit2why.c +index ca38e13c0eeb..44a9a3419f96 100644 +--- a/libselinux/src/audit2why.c ++++ b/libselinux/src/audit2why.c +@@ -192,25 +192,16 @@ static PyObject *finish(PyObject *self __attribute__((unused)), PyObject *args) + static int __policy_init(const char *init_path) + { + FILE *fp; +- char path[PATH_MAX]; ++ const char *curpolicy; + char errormsg[PATH_MAX+1024+20]; + struct sepol_policy_file *pf = NULL; + int rc; + unsigned int cnt; + +- path[PATH_MAX-1] = '\0'; + if (init_path) { +- strncpy(path, init_path, PATH_MAX-1); +- fp = fopen(path, "re"); +- if (!fp) { +- snprintf(errormsg, sizeof(errormsg), +- "unable to open %s: %m\n", +- path); +- PyErr_SetString( PyExc_ValueError, errormsg); +- return 1; +- } ++ curpolicy = init_path; + } else { +- const char *curpolicy = selinux_current_policy_path(); ++ curpolicy = selinux_current_policy_path(); + if (!curpolicy) { + /* SELinux disabled, must use -p option. */ + snprintf(errormsg, sizeof(errormsg), +@@ -218,14 +209,15 @@ static int __policy_init(const char *init_path) + PyErr_SetString( PyExc_ValueError, errormsg); + return 1; + } +- fp = fopen(curpolicy, "re"); +- if (!fp) { +- snprintf(errormsg, sizeof(errormsg), +- "unable to open %s: %m\n", +- curpolicy); +- PyErr_SetString( PyExc_ValueError, errormsg); +- return 1; +- } ++ } ++ ++ fp = fopen(curpolicy, "re"); ++ if (!fp) { ++ snprintf(errormsg, sizeof(errormsg), ++ "unable to open %s: %m\n", ++ curpolicy); ++ PyErr_SetString( PyExc_ValueError, errormsg); ++ return 1; + } + + avc = calloc(sizeof(struct avc_t), 1); +@@ -249,7 +241,7 @@ static int __policy_init(const char *init_path) + sepol_policy_file_set_fp(pf, fp); + if (sepol_policydb_read(avc->policydb, pf)) { + snprintf(errormsg, sizeof(errormsg), +- "invalid binary policy %s\n", path); ++ "invalid binary policy %s\n", curpolicy); + PyErr_SetString( PyExc_ValueError, errormsg); + fclose(fp); + return 1; +-- +2.38.1 + diff --git a/0005-libselinux-add-header-guard-for-internal-header.patch b/0005-libselinux-add-header-guard-for-internal-header.patch new file mode 100644 index 0000000..680750d --- /dev/null +++ b/0005-libselinux-add-header-guard-for-internal-header.patch @@ -0,0 +1,34 @@ +From 2b7da165955f359eb8200a5b0f15a8c81234c543 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Tue, 10 May 2022 20:20:37 +0200 +Subject: [PATCH] libselinux: add header guard for internal header +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Content-type: text/plain + +Signed-off-by: Christian Göttsche +--- + libselinux/src/selinux_internal.h | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/libselinux/src/selinux_internal.h b/libselinux/src/selinux_internal.h +index 297dcf26dee3..9f4c90739171 100644 +--- a/libselinux/src/selinux_internal.h ++++ b/libselinux/src/selinux_internal.h +@@ -1,3 +1,6 @@ ++#ifndef SELINUX_INTERNAL_H_ ++#define SELINUX_INTERNAL_H_ ++ + #include + #include + +@@ -90,3 +93,5 @@ extern int selinux_page_size ; + #define SELINUXCONFIG SELINUXDIR "config" + + extern int has_selinux_config ; ++ ++#endif /* SELINUX_INTERNAL_H_ */ +-- +2.38.1 + diff --git a/0006-libselinux-introduce-strlcpy.patch b/0006-libselinux-introduce-strlcpy.patch new file mode 100644 index 0000000..4502edc --- /dev/null +++ b/0006-libselinux-introduce-strlcpy.patch @@ -0,0 +1,78 @@ +From 7d5a89314be88b3085cfdf6083837045a5e44aa9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Tue, 10 May 2022 20:20:38 +0200 +Subject: [PATCH] libselinux: introduce strlcpy +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Content-type: text/plain + +To copy string safely, by always NULL-terminating them, and provide an +easy way to check for truncation introduce the nonstandard function +strlcpy(3). Use the system implementation if available. + +Signed-off-by: Christian Göttsche +--- + libselinux/src/Makefile | 6 ++++++ + libselinux/src/selinux_internal.c | 18 ++++++++++++++++++ + libselinux/src/selinux_internal.h | 4 ++++ + 3 files changed, 28 insertions(+) + create mode 100644 libselinux/src/selinux_internal.c + +diff --git a/libselinux/src/Makefile b/libselinux/src/Makefile +index 04bf4f240168..88aa32f80944 100644 +--- a/libselinux/src/Makefile ++++ b/libselinux/src/Makefile +@@ -103,6 +103,12 @@ FTS_LDLIBS ?= + + override CFLAGS += -I../include -D_GNU_SOURCE $(DISABLE_FLAGS) $(PCRE_CFLAGS) + ++# check for strlcpy(3) availability ++H := \# ++ifeq (yes,$(shell printf '${H}include \nint main(void){char*d,*s;strlcpy(d, s, 0);return 0;}' | $(CC) -x c -o /dev/null - >/dev/null 2>&1 && echo yes)) ++override CFLAGS += -DHAVE_STRLCPY ++endif ++ + SWIG_CFLAGS += -Wno-error -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-parameter \ + -Wno-shadow -Wno-uninitialized -Wno-missing-prototypes -Wno-missing-declarations \ + -Wno-deprecated-declarations +diff --git a/libselinux/src/selinux_internal.c b/libselinux/src/selinux_internal.c +new file mode 100644 +index 000000000000..c2be7c0a9128 +--- /dev/null ++++ b/libselinux/src/selinux_internal.c +@@ -0,0 +1,18 @@ ++#include "selinux_internal.h" ++ ++#include ++ ++ ++#ifndef HAVE_STRLCPY ++size_t strlcpy(char *dest, const char *src, size_t size) ++{ ++ size_t ret = strlen(src); ++ ++ if (size) { ++ size_t len = (ret >= size) ? size - 1 : ret; ++ memcpy(dest, src, len); ++ dest[len] = '\0'; ++ } ++ return ret; ++} ++#endif /* HAVE_STRLCPY */ +diff --git a/libselinux/src/selinux_internal.h b/libselinux/src/selinux_internal.h +index 9f4c90739171..06f2c0383bc2 100644 +--- a/libselinux/src/selinux_internal.h ++++ b/libselinux/src/selinux_internal.h +@@ -94,4 +94,8 @@ extern int selinux_page_size ; + + extern int has_selinux_config ; + ++#ifndef HAVE_STRLCPY ++size_t strlcpy(char *dest, const char *src, size_t size); ++#endif ++ + #endif /* SELINUX_INTERNAL_H_ */ +-- +2.38.1 + diff --git a/0007-libselinux-check-for-truncations.patch b/0007-libselinux-check-for-truncations.patch new file mode 100644 index 0000000..48b9af5 --- /dev/null +++ b/0007-libselinux-check-for-truncations.patch @@ -0,0 +1,182 @@ +From 1eb6229a48d2b8ca08a230e7c60176c56c5cb6d5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Tue, 7 Jun 2022 19:14:09 +0200 +Subject: [PATCH] libselinux: check for truncations +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Content-type: text/plain + +Check for truncations when building or copying strings involving user +input. + +Signed-off-by: Christian Göttsche +--- + libselinux/src/canonicalize_context.c | 6 +++++- + libselinux/src/compute_av.c | 8 +++++++- + libselinux/src/compute_create.c | 7 +++++++ + libselinux/src/compute_member.c | 8 +++++++- + libselinux/src/compute_relabel.c | 8 +++++++- + libselinux/src/compute_user.c | 8 +++++++- + libselinux/src/selinux_restorecon.c | 11 ++++++++++- + libselinux/src/setrans_client.c | 8 +++++++- + 8 files changed, 57 insertions(+), 7 deletions(-) + +diff --git a/libselinux/src/canonicalize_context.c b/libselinux/src/canonicalize_context.c +index faab730592c2..6af8491dd4a6 100644 +--- a/libselinux/src/canonicalize_context.c ++++ b/libselinux/src/canonicalize_context.c +@@ -33,7 +33,11 @@ int security_canonicalize_context_raw(const char * con, + ret = -1; + goto out; + } +- strncpy(buf, con, size); ++ if (strlcpy(buf, con, size) >= size) { ++ errno = EOVERFLOW; ++ ret = -1; ++ goto out2; ++ } + + ret = write(fd, buf, strlen(buf) + 1); + if (ret < 0) +diff --git a/libselinux/src/compute_av.c b/libselinux/src/compute_av.c +index 9d17339d1a32..354a19e1051c 100644 +--- a/libselinux/src/compute_av.c ++++ b/libselinux/src/compute_av.c +@@ -40,8 +40,14 @@ int security_compute_av_flags_raw(const char * scon, + } + + kclass = unmap_class(tclass); +- snprintf(buf, len, "%s %s %hu %x", scon, tcon, ++ ++ ret = snprintf(buf, len, "%s %s %hu %x", scon, tcon, + kclass, unmap_perm(tclass, requested)); ++ if (ret < 0 || (size_t)ret >= len) { ++ errno = EOVERFLOW; ++ ret = -1; ++ goto out2; ++ } + + ret = write(fd, buf, strlen(buf)); + if (ret < 0) +diff --git a/libselinux/src/compute_create.c b/libselinux/src/compute_create.c +index 1d75714d852d..e9f3c96a1a6a 100644 +--- a/libselinux/src/compute_create.c ++++ b/libselinux/src/compute_create.c +@@ -75,8 +75,15 @@ int security_compute_create_name_raw(const char * scon, + ret = -1; + goto out; + } ++ + len = snprintf(buf, size, "%s %s %hu", + scon, tcon, unmap_class(tclass)); ++ if (len < 0 || (size_t)len >= size) { ++ errno = EOVERFLOW; ++ ret = -1; ++ goto out2; ++ } ++ + if (objname && + object_name_encode(objname, buf + len, size - len) < 0) { + errno = ENAMETOOLONG; +diff --git a/libselinux/src/compute_member.c b/libselinux/src/compute_member.c +index 16234b7908f2..53d2f55950f6 100644 +--- a/libselinux/src/compute_member.c ++++ b/libselinux/src/compute_member.c +@@ -36,7 +36,13 @@ int security_compute_member_raw(const char * scon, + ret = -1; + goto out; + } +- snprintf(buf, size, "%s %s %hu", scon, tcon, unmap_class(tclass)); ++ ++ ret = snprintf(buf, size, "%s %s %hu", scon, tcon, unmap_class(tclass)); ++ if (ret < 0 || (size_t)ret >= size) { ++ errno = EOVERFLOW; ++ ret = -1; ++ goto out2; ++ } + + ret = write(fd, buf, strlen(buf)); + if (ret < 0) +diff --git a/libselinux/src/compute_relabel.c b/libselinux/src/compute_relabel.c +index dd20d6525993..9c0a2304f356 100644 +--- a/libselinux/src/compute_relabel.c ++++ b/libselinux/src/compute_relabel.c +@@ -36,7 +36,13 @@ int security_compute_relabel_raw(const char * scon, + ret = -1; + goto out; + } +- snprintf(buf, size, "%s %s %hu", scon, tcon, unmap_class(tclass)); ++ ++ ret = snprintf(buf, size, "%s %s %hu", scon, tcon, unmap_class(tclass)); ++ if (ret < 0 || (size_t)ret >= size) { ++ errno = EOVERFLOW; ++ ret = -1; ++ goto out2; ++ } + + ret = write(fd, buf, strlen(buf)); + if (ret < 0) +diff --git a/libselinux/src/compute_user.c b/libselinux/src/compute_user.c +index ae5e7b4a8f68..f55f945a01e0 100644 +--- a/libselinux/src/compute_user.c ++++ b/libselinux/src/compute_user.c +@@ -38,7 +38,13 @@ int security_compute_user_raw(const char * scon, + ret = -1; + goto out; + } +- snprintf(buf, size, "%s %s", scon, user); ++ ++ ret = snprintf(buf, size, "%s %s", scon, user); ++ if (ret < 0 || (size_t)ret >= size) { ++ errno = EOVERFLOW; ++ ret = -1; ++ goto out2; ++ } + + ret = write(fd, buf, strlen(buf)); + if (ret < 0) +diff --git a/libselinux/src/selinux_restorecon.c b/libselinux/src/selinux_restorecon.c +index 9f5b326c19ec..66e6a4a239d1 100644 +--- a/libselinux/src/selinux_restorecon.c ++++ b/libselinux/src/selinux_restorecon.c +@@ -954,7 +954,16 @@ loop_body: + } + /* fall through */ + default: +- strcpy(ent_path, ftsent->fts_path); ++ if (strlcpy(ent_path, ftsent->fts_path, sizeof(ent_path)) >= sizeof(ent_path)) { ++ selinux_log(SELINUX_ERROR, ++ "Path name too long on %s.\n", ++ ftsent->fts_path); ++ errno = ENAMETOOLONG; ++ state->error = -1; ++ state->abort = true; ++ goto finish; ++ } ++ + ent_st = *ftsent->fts_statp; + if (state->parallel) + pthread_mutex_unlock(&state->mutex); +diff --git a/libselinux/src/setrans_client.c b/libselinux/src/setrans_client.c +index faa126813a77..920f9032c3f6 100644 +--- a/libselinux/src/setrans_client.c ++++ b/libselinux/src/setrans_client.c +@@ -66,7 +66,13 @@ static int setransd_open(void) + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; +- strncpy(addr.sun_path, SETRANS_UNIX_SOCKET, sizeof(addr.sun_path)); ++ ++ if (strlcpy(addr.sun_path, SETRANS_UNIX_SOCKET, sizeof(addr.sun_path)) >= sizeof(addr.sun_path)) { ++ close(fd); ++ errno = EOVERFLOW; ++ return -1; ++ } ++ + if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + close(fd); + return -1; +-- +2.38.1 + diff --git a/0008-libselinux-add-man-page-redirections.patch b/0008-libselinux-add-man-page-redirections.patch new file mode 100644 index 0000000..fb280ab --- /dev/null +++ b/0008-libselinux-add-man-page-redirections.patch @@ -0,0 +1,70 @@ +From 90bc03b732f51f7f7011d9bd80e589e64828dce3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Fri, 20 May 2022 15:08:44 +0200 +Subject: [PATCH] libselinux: add man page redirections +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Content-type: text/plain + +The following interfaces are documented but do not have a redirection: + + - context_str(3) + - security_get_checkreqprot(3) + - security_set_boolean_list(3) + - selinux_sepgsql_context_path(3) + - setexecfilecon(3) + +Signed-off-by: Christian Göttsche +Acked-by: James Carter +--- + libselinux/man/man3/context_str.3 | 1 + + libselinux/man/man3/security_get_checkreqprot.3 | 1 + + libselinux/man/man3/security_set_boolean_list.3 | 1 + + libselinux/man/man3/selinux_sepgsql_context_path.3 | 1 + + libselinux/man/man3/setexecfilecon.3 | 1 + + 5 files changed, 5 insertions(+) + create mode 100644 libselinux/man/man3/context_str.3 + create mode 100644 libselinux/man/man3/security_get_checkreqprot.3 + create mode 100644 libselinux/man/man3/security_set_boolean_list.3 + create mode 100644 libselinux/man/man3/selinux_sepgsql_context_path.3 + create mode 100644 libselinux/man/man3/setexecfilecon.3 + +diff --git a/libselinux/man/man3/context_str.3 b/libselinux/man/man3/context_str.3 +new file mode 100644 +index 000000000000..f4f03a6d9cf3 +--- /dev/null ++++ b/libselinux/man/man3/context_str.3 +@@ -0,0 +1 @@ ++.so man3/context_new.3 +diff --git a/libselinux/man/man3/security_get_checkreqprot.3 b/libselinux/man/man3/security_get_checkreqprot.3 +new file mode 100644 +index 000000000000..d59e5c2cc2e7 +--- /dev/null ++++ b/libselinux/man/man3/security_get_checkreqprot.3 +@@ -0,0 +1 @@ ++.so man3/security_getenforce.3 +diff --git a/libselinux/man/man3/security_set_boolean_list.3 b/libselinux/man/man3/security_set_boolean_list.3 +new file mode 100644 +index 000000000000..29731efaecad +--- /dev/null ++++ b/libselinux/man/man3/security_set_boolean_list.3 +@@ -0,0 +1 @@ ++.so man3/security_load_booleans.3 +diff --git a/libselinux/man/man3/selinux_sepgsql_context_path.3 b/libselinux/man/man3/selinux_sepgsql_context_path.3 +new file mode 100644 +index 000000000000..175a611a3ef0 +--- /dev/null ++++ b/libselinux/man/man3/selinux_sepgsql_context_path.3 +@@ -0,0 +1 @@ ++.so man3/selinux_binary_policy_path.3 +diff --git a/libselinux/man/man3/setexecfilecon.3 b/libselinux/man/man3/setexecfilecon.3 +new file mode 100644 +index 000000000000..b2e6ab8141ce +--- /dev/null ++++ b/libselinux/man/man3/setexecfilecon.3 +@@ -0,0 +1 @@ ++.so man3/getexeccon.3 +-- +2.38.1 + diff --git a/0009-libselinux-enclose-macro-definition-in-parenthesis.patch b/0009-libselinux-enclose-macro-definition-in-parenthesis.patch new file mode 100644 index 0000000..941a1d1 --- /dev/null +++ b/0009-libselinux-enclose-macro-definition-in-parenthesis.patch @@ -0,0 +1,33 @@ +From 29e5233d85bb2f0c4ffc973f95faff8885a1c3dc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Fri, 20 May 2022 15:08:45 +0200 +Subject: [PATCH] libselinux: enclose macro definition in parenthesis +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Content-type: text/plain + +Avoid potential precedence issues. + +Signed-off-by: Christian Göttsche +Acked-by: James Carter +--- + libselinux/include/selinux/avc.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libselinux/include/selinux/avc.h b/libselinux/include/selinux/avc.h +index 9b23357ad17f..4bbd2382404b 100644 +--- a/libselinux/include/selinux/avc.h ++++ b/libselinux/include/selinux/avc.h +@@ -24,7 +24,7 @@ struct security_id { + }; + typedef struct security_id *security_id_t; + +-#define SECSID_WILD (security_id_t)NULL /* unspecified SID */ ++#define SECSID_WILD ((security_id_t)NULL) /* unspecified SID */ + + /** + * avc_sid_to_context - get copy of context corresponding to SID. +-- +2.38.1 + diff --git a/0010-libselinux-name-parameters-in-context.h.patch b/0010-libselinux-name-parameters-in-context.h.patch new file mode 100644 index 0000000..9510d51 --- /dev/null +++ b/0010-libselinux-name-parameters-in-context.h.patch @@ -0,0 +1,66 @@ +From a6c572b1af14ae53b692c092fdc8838fe56ab3b3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Tue, 7 Jun 2022 19:16:47 +0200 +Subject: [PATCH] libselinux: name parameters in context.h +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Content-type: text/plain + +Signed-off-by: Christian Göttsche +Acked-by: James Carter +--- + libselinux/include/selinux/context.h | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +diff --git a/libselinux/include/selinux/context.h b/libselinux/include/selinux/context.h +index 82f4e690faa8..59d9bb69ba7d 100644 +--- a/libselinux/include/selinux/context.h ++++ b/libselinux/include/selinux/context.h +@@ -17,7 +17,7 @@ extern "C" { + + /* Return a new context initialized to a context string */ + +- extern context_t context_new(const char *); ++ extern context_t context_new(const char *str); + + /* + * Return a pointer to the string value of the context_t +@@ -25,24 +25,24 @@ extern "C" { + * for the same context_t* + */ + +- extern const char *context_str(context_t); ++ extern const char *context_str(context_t con); + + /* Free the storage used by a context */ +- extern void context_free(context_t); ++ extern void context_free(context_t con); + + /* Get a pointer to the string value of a context component */ + +- extern const char *context_type_get(context_t); +- extern const char *context_range_get(context_t); +- extern const char *context_role_get(context_t); +- extern const char *context_user_get(context_t); ++ extern const char *context_type_get(context_t con); ++ extern const char *context_range_get(context_t con); ++ extern const char *context_role_get(context_t con); ++ extern const char *context_user_get(context_t con); + + /* Set a context component. Returns nonzero if unsuccessful */ + +- extern int context_type_set(context_t, const char *); +- extern int context_range_set(context_t, const char *); +- extern int context_role_set(context_t, const char *); +- extern int context_user_set(context_t, const char *); ++ extern int context_type_set(context_t con, const char *type); ++ extern int context_range_set(context_t con, const char *range); ++ extern int context_role_set(context_t con, const char *role); ++ extern int context_user_set(context_t con, const char *user); + + #ifdef __cplusplus + } +-- +2.38.1 + diff --git a/0011-libselinux-declare-parameter-of-security_load_policy.patch b/0011-libselinux-declare-parameter-of-security_load_policy.patch new file mode 100644 index 0000000..72cc855 --- /dev/null +++ b/0011-libselinux-declare-parameter-of-security_load_policy.patch @@ -0,0 +1,63 @@ +From c760a2bff627da1725fcd3569eacc79431bcdcf7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Fri, 20 May 2022 15:08:47 +0200 +Subject: [PATCH] libselinux: declare parameter of security_load_policy(3) + const +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Content-type: text/plain + +security_load_policy(3) takes a read-only memory address for a binary +policy to be loaded. + +Signed-off-by: Christian Göttsche +Acked-by: James Carter +--- + libselinux/include/selinux/selinux.h | 2 +- + libselinux/man/man3/security_load_policy.3 | 2 +- + libselinux/src/load_policy.c | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/libselinux/include/selinux/selinux.h b/libselinux/include/selinux/selinux.h +index ae98a92e393e..47af99536798 100644 +--- a/libselinux/include/selinux/selinux.h ++++ b/libselinux/include/selinux/selinux.h +@@ -279,7 +279,7 @@ extern int security_validatetrans_raw(const char *scon, + const char *newcon); + + /* Load a policy configuration. */ +-extern int security_load_policy(void *data, size_t len); ++extern int security_load_policy(const void *data, size_t len); + + /* Get the context of an initial kernel security identifier by name. + Caller must free via freecon */ +diff --git a/libselinux/man/man3/security_load_policy.3 b/libselinux/man/man3/security_load_policy.3 +index af5616363692..b2da02560799 100644 +--- a/libselinux/man/man3/security_load_policy.3 ++++ b/libselinux/man/man3/security_load_policy.3 +@@ -5,7 +5,7 @@ security_load_policy \- load a new SELinux policy + .SH "SYNOPSIS" + .B #include + .sp +-.BI "int security_load_policy(void *" data ", size_t "len ); ++.BI "int security_load_policy(const void *" data ", size_t "len ); + .sp + .BI "int selinux_mkload_policy(int " preservebools ");" + .sp +diff --git a/libselinux/src/load_policy.c b/libselinux/src/load_policy.c +index d8c715edb0b6..17918e8be2b0 100644 +--- a/libselinux/src/load_policy.c ++++ b/libselinux/src/load_policy.c +@@ -23,7 +23,7 @@ + #define MNT_DETACH 2 + #endif + +-int security_load_policy(void *data, size_t len) ++int security_load_policy(const void *data, size_t len) + { + char path[PATH_MAX]; + int fd, ret; +-- +2.38.1 + diff --git a/0012-libselinux-restorecon-avoid-printing-NULL-pointer.patch b/0012-libselinux-restorecon-avoid-printing-NULL-pointer.patch new file mode 100644 index 0000000..af892c4 --- /dev/null +++ b/0012-libselinux-restorecon-avoid-printing-NULL-pointer.patch @@ -0,0 +1,37 @@ +From 956bda08f6183078f13b70f6aa27d0529a3ec20a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +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 +Content-type: text/plain + +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 +Acked-by: Nicolas Iooss +--- + libselinux/src/selinux_restorecon.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/libselinux/src/selinux_restorecon.c b/libselinux/src/selinux_restorecon.c +index 66e6a4a239d1..2d24559f2ea5 100644 +--- a/libselinux/src/selinux_restorecon.c ++++ b/libselinux/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 : "", ++ newcon); + + if (flags->syslog_changes && !flags->nochange) { + if (curcon) +-- +2.38.1 + diff --git a/0013-libselinux-set-errno-to-EBADF-on-O_PATH-emulation-EN.patch b/0013-libselinux-set-errno-to-EBADF-on-O_PATH-emulation-EN.patch new file mode 100644 index 0000000..bc893c2 --- /dev/null +++ b/0013-libselinux-set-errno-to-EBADF-on-O_PATH-emulation-EN.patch @@ -0,0 +1,60 @@ +From ba9820a0020d06c7a37b34e771020cef8e9651a2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Wed, 6 Jul 2022 13:38:04 +0200 +Subject: [PATCH] libselinux: set errno to EBADF on O_PATH emulation ENOENT + failure +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Content-type: text/plain + +When the O_PATH emulation fails due to getxattr(2)/setxattr(2) failing +with ENOENT, e.g. because no procfs being available, override the errno +value to EBADF. This avoids confusion to the caller as it would suggest +the target of the operation does not exist, which is not the case: + + setfiles: Could not set context for /: No such file or directory + +Fixes: a782abf2 ("libselinux: emulate O_PATH support in fgetfilecon/fsetfilecon") +Signed-off-by: Christian Göttsche +Acked-by: James Carter +--- + libselinux/src/fgetfilecon.c | 5 ++++- + libselinux/src/fsetfilecon.c | 5 ++++- + 2 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/libselinux/src/fgetfilecon.c b/libselinux/src/fgetfilecon.c +index baf38ec1221f..d7051171cf0d 100644 +--- a/libselinux/src/fgetfilecon.c ++++ b/libselinux/src/fgetfilecon.c +@@ -26,7 +26,10 @@ static ssize_t fgetxattr_wrapper(int fd, const char *name, void *value, size_t s + + snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd); + errno = saved_errno; +- return getxattr(buf, name, value, size); ++ ret = getxattr(buf, name, value, size); ++ if (ret < 0 && errno == ENOENT) ++ errno = EBADF; ++ return ret; + } + + int fgetfilecon_raw(int fd, char ** context) +diff --git a/libselinux/src/fsetfilecon.c b/libselinux/src/fsetfilecon.c +index be821c7a6be2..19ea15b711cc 100644 +--- a/libselinux/src/fsetfilecon.c ++++ b/libselinux/src/fsetfilecon.c +@@ -25,7 +25,10 @@ static int fsetxattr_wrapper(int fd, const char* name, const void* value, size_t + + snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd); + errno = saved_errno; +- return setxattr(buf, name, value, size, flags); ++ rc = setxattr(buf, name, value, size, flags); ++ if (rc < 0 && errno == ENOENT) ++ errno = EBADF; ++ return rc; + } + + int fsetfilecon_raw(int fd, const char * context) +-- +2.38.1 + diff --git a/0014-libselinux-avoid-newline-in-avc-message.patch b/0014-libselinux-avoid-newline-in-avc-message.patch new file mode 100644 index 0000000..f761598 --- /dev/null +++ b/0014-libselinux-avoid-newline-in-avc-message.patch @@ -0,0 +1,63 @@ +From 142372522c7e12752387cc8d6621ee5823dd4a42 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Mon, 8 Aug 2022 19:34:29 +0200 +Subject: [PATCH] libselinux: avoid newline in avc message +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Content-type: text/plain + +Do not add a final newline to the avc log message as it will be treated +as a part of the tclass field in final audit record: + + { + "AUDIT_FIELD_EXE" : "/usr/bin/dbus-broker", + "_UID" : "104", + "_AUDIT_SESSION" : "4294967295", + "_TRANSPORT" : "audit", + "__REALTIME_TIMESTAMP" : "1659975331468531", + "_AUDIT_TYPE" : "1107", + "AUDIT_FIELD_SCONTEXT" : "system_u:system_r:systemd_t:s0", + "_AUDIT_LOGINUID" : "4294967295", + "_SELINUX_CONTEXT" : "system_u:system_r:system_dbusd_t:s0-s0:c0.c1023", + "AUDIT_FIELD_SAUID" : "104", + "MESSAGE" : "USER_AVC pid=1538 uid=104 auid=4294967295 ses=4294967295 subj=system_u:system_r:system_dbusd_t:s0-s0:c0.c1023 msg='avc: granted { send_msg } for scontext=system_u:system_r:systemd_t:s0 tcontext=system_u:system_r:systemd_logind_t:s0 tclass=dbus\n exe=\"/usr/bin/dbus-broker\" sauid=104 hostname=? addr=? terminal=?'", + "AUDIT_FIELD_TCONTEXT" : "system_u:system_r:systemd_logind_t:s0", + "_SOURCE_REALTIME_TIMESTAMP" : "1659975331462000", + "__MONOTONIC_TIMESTAMP" : "207995768", + "AUDIT_FIELD_TCLASS" : "dbus\n", + "AUDIT_FIELD_TERMINAL" : "?", + "_PID" : "1538", + "SYSLOG_FACILITY" : "4", + "_BOOT_ID" : "3921464b65f64fb4a7c037dee97cd6ad", + "SYSLOG_IDENTIFIER" : "audit", + "_MACHINE_ID" : "5d78c28f10d54c0fb7b6fd1acc6af8ff", + "_AUDIT_TYPE_NAME" : "USER_AVC", + "__CURSOR" : "s=84589ce96ff8400189fc515ff892674a;i=c38e;b=3921464b65f64fb4a7c037dee97cd6ad;m=c65c378;t=5e5bd1ff7d4f3;x=c22e610fc9b00b10", + "AUDIT_FIELD_ADDR" : "?", + "AUDIT_FIELD_HOSTNAME" : "?", + "_AUDIT_ID" : "1075", + "_HOSTNAME" : "debianBullseye" + } + +Signed-off-by: Christian Göttsche +Acked-by: James Carter +--- + libselinux/src/avc.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/libselinux/src/avc.c b/libselinux/src/avc.c +index 7493e4b24df2..8d5983a2fe0c 100644 +--- a/libselinux/src/avc.c ++++ b/libselinux/src/avc.c +@@ -725,7 +725,6 @@ void avc_audit(security_id_t ssid, security_id_t tsid, + if (denied) + log_append(avc_audit_buf, " permissive=%u", result ? 0 : 1); + +- log_append(avc_audit_buf, "\n"); + avc_log(SELINUX_AVC, "%s", avc_audit_buf); + + avc_release_lock(avc_log_lock); +-- +2.38.1 + diff --git a/0015-Ignore-egg-info-directories-and-clean-them.patch b/0015-Ignore-egg-info-directories-and-clean-them.patch new file mode 100644 index 0000000..b57ea6a --- /dev/null +++ b/0015-Ignore-egg-info-directories-and-clean-them.patch @@ -0,0 +1,56 @@ +From c2d58b378b3cf350d042a7b657e2b7f5861c5f26 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Mon, 8 Aug 2022 19:36:55 +0200 +Subject: [PATCH] Ignore egg-info directories and clean them +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Content-type: text/plain + + Test .gitignore and make clean distclean + error: missing .gitignore entry for libselinux/src/selinux.egg-info/ + error: missing .gitignore entry for python/sepolicy/sepolicy.egg-info/ + Error: Process completed with exit code 1. + + error: "make clean distclean" did not remove libselinux/src/selinux.egg-info/PKG-INFO + error: "make clean distclean" did not remove libselinux/src/selinux.egg-info/SOURCES.txt + error: "make clean distclean" did not remove libselinux/src/selinux.egg-info/dependency_links.txt + error: "make clean distclean" did not remove libselinux/src/selinux.egg-info/top_level.txt + error: "make clean distclean" did not remove python/sepolicy/sepolicy.egg-info/PKG-INFO + error: "make clean distclean" did not remove python/sepolicy/sepolicy.egg-info/SOURCES.txt + error: "make clean distclean" did not remove python/sepolicy/sepolicy.egg-info/dependency_links.txt + error: "make clean distclean" did not remove python/sepolicy/sepolicy.egg-info/top_level.txt + Error: Process completed with exit code 1. + +Signed-off-by: Christian Göttsche +Acked-by: James Carter +--- + libselinux/src/.gitignore | 1 + + libselinux/src/Makefile | 2 +- + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/libselinux/src/.gitignore b/libselinux/src/.gitignore +index 001f20b01e39..94400e81fb33 100644 +--- a/libselinux/src/.gitignore ++++ b/libselinux/src/.gitignore +@@ -1,3 +1,4 @@ + selinux.py + selinuxswig_python_wrap.c + selinuxswig_ruby_wrap.c ++selinux.egg-info/ +diff --git a/libselinux/src/Makefile b/libselinux/src/Makefile +index 88aa32f80944..49b7d60a1f74 100644 +--- a/libselinux/src/Makefile ++++ b/libselinux/src/Makefile +@@ -201,7 +201,7 @@ relabel: + clean-pywrap: + -rm -f $(SWIGLOBJ) $(SWIGSO) $(AUDIT2WHYLOBJ) $(AUDIT2WHYSO) + $(PYTHON) setup.py clean +- -rm -rf build *~ \#* *pyc .#* ++ -rm -rf build *~ \#* *pyc .#* selinux.egg-info/ + + clean-rubywrap: + -rm -f $(SWIGRUBYLOBJ) $(SWIGRUBYSO) +-- +2.38.1 + diff --git a/0016-libselinux-support-objname-in-compute_create.patch b/0016-libselinux-support-objname-in-compute_create.patch new file mode 100644 index 0000000..d4f744c --- /dev/null +++ b/0016-libselinux-support-objname-in-compute_create.patch @@ -0,0 +1,50 @@ +From fa5b0504d861f569c6c97ab32719cc4a8dca0cd4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Tue, 30 Aug 2022 19:54:55 +0200 +Subject: [PATCH] libselinux: support objname in compute_create +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Content-type: text/plain + +Support passing an optional object name to compute_create for name +based type transitions. + +Signed-off-by: Christian Göttsche +Acked-by: James Carter +--- + libselinux/utils/compute_create.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/libselinux/utils/compute_create.c b/libselinux/utils/compute_create.c +index c6481f4b01c1..5401fe967a53 100644 +--- a/libselinux/utils/compute_create.c ++++ b/libselinux/utils/compute_create.c +@@ -10,10 +10,11 @@ int main(int argc, char **argv) + { + char *buf; + security_class_t tclass; ++ const char *objname; + int ret; + +- if (argc != 4) { +- fprintf(stderr, "usage: %s scontext tcontext tclass\n", ++ if (argc != 4 && argc != 5) { ++ fprintf(stderr, "usage: %s scontext tcontext tclass [objname]\n", + argv[0]); + exit(1); + } +@@ -34,7 +35,9 @@ int main(int argc, char **argv) + exit(2); + } + +- ret = security_compute_create(argv[1], argv[2], tclass, &buf); ++ objname = (argc == 5) ? argv[4] : NULL; ++ ++ ret = security_compute_create_name(argv[1], argv[2], tclass, objname, &buf); + if (ret < 0) { + fprintf(stderr, "%s: security_compute_create failed: %s\n", + argv[0], strerror(errno)); +-- +2.38.1 + diff --git a/0017-libselinux-Remove-dependency-on-the-Python-module-di.patch b/0017-libselinux-Remove-dependency-on-the-Python-module-di.patch new file mode 100644 index 0000000..bbe7d85 --- /dev/null +++ b/0017-libselinux-Remove-dependency-on-the-Python-module-di.patch @@ -0,0 +1,44 @@ +From 94364696c5aed35a9c1f529d96d1930cef37ecda Mon Sep 17 00:00:00 2001 +From: James Carter +Date: Fri, 28 Oct 2022 16:10:39 -0400 +Subject: [PATCH] libselinux: Remove dependency on the Python module distutils +Content-type: text/plain + +The distutils package is deprecated and scheduled to be removed in +Python 3.12. Use the setuptools and sysconfig modules instead. + +Signed-off-by: James Carter +Acked-by: Petr Lautrbach +--- + libselinux/src/Makefile | 2 +- + libselinux/src/setup.py | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/libselinux/src/Makefile b/libselinux/src/Makefile +index 49b7d60a1f74..dc2848322e4d 100644 +--- a/libselinux/src/Makefile ++++ b/libselinux/src/Makefile +@@ -14,7 +14,7 @@ SHLIBDIR ?= /lib + INCLUDEDIR ?= $(PREFIX)/include + PYINC ?= $(shell $(PKG_CONFIG) --cflags $(PYPREFIX)) + PYLIBS ?= $(shell $(PKG_CONFIG) --libs $(PYPREFIX)) +-PYTHONLIBDIR ?= $(shell $(PYTHON) -c "from distutils.sysconfig import *; print(get_python_lib(plat_specific=1, prefix='$(PREFIX)'))") ++PYTHONLIBDIR ?= $(shell $(PYTHON) -c "import sysconfig; print(sysconfig.get_path('platlib', vars={'platbase': '$(PREFIX)', 'base': '$(PREFIX)'}))") + PYCEXT ?= $(shell $(PYTHON) -c 'import importlib.machinery;print(importlib.machinery.EXTENSION_SUFFIXES[0])') + RUBYINC ?= $(shell $(RUBY) -e 'puts "-I" + RbConfig::CONFIG["rubyarchhdrdir"] + " -I" + RbConfig::CONFIG["rubyhdrdir"]') + RUBYLIBS ?= $(shell $(RUBY) -e 'puts "-L" + RbConfig::CONFIG["libdir"] + " -L" + RbConfig::CONFIG["archlibdir"] + " " + RbConfig::CONFIG["LIBRUBYARG_SHARED"]') +diff --git a/libselinux/src/setup.py b/libselinux/src/setup.py +index 71e69a107f01..6cbe3a0e924b 100644 +--- a/libselinux/src/setup.py ++++ b/libselinux/src/setup.py +@@ -1,6 +1,6 @@ + #!/usr/bin/python3 + +-from distutils.core import Extension, setup ++from setuptools import Extension, setup + + setup( + name="selinux", +-- +2.38.1 + diff --git a/0018-libselinux-Ignore-missing-directories-when-i-is-used.patch b/0018-libselinux-Ignore-missing-directories-when-i-is-used.patch new file mode 100644 index 0000000..957ddb2 --- /dev/null +++ b/0018-libselinux-Ignore-missing-directories-when-i-is-used.patch @@ -0,0 +1,48 @@ +From 2f71384f233aa544cf0cf50be7e83c7762ad1c15 Mon Sep 17 00:00:00 2001 +From: Vit Mojzis +Date: Mon, 31 Oct 2022 17:46:17 +0100 +Subject: [PATCH] libselinux: Ignore missing directories when -i is used +Content-type: text/plain + +Currently "-i" only ignores a file whose parent directory exists. Start also +ignoring paths with missing components. + +Fixes: + # restorecon -i -v -R /var/log/missingdir/missingfile; echo $? + 255 + restorecon: SELinux: Could not get canonical path for /var/log/missingdir/missingfile restorecon: No such file or directory. + +Signed-off-by: Vit Mojzis +Acked-by: James Carter +--- + libselinux/src/selinux_restorecon.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/libselinux/src/selinux_restorecon.c b/libselinux/src/selinux_restorecon.c +index 2d24559f2ea5..6b5f6921b82b 100644 +--- a/libselinux/src/selinux_restorecon.c ++++ b/libselinux/src/selinux_restorecon.c +@@ -1108,6 +1108,10 @@ static int selinux_restorecon_common(const char *pathname_orig, + pathname = realpath(pathname_orig, NULL); + if (!pathname) { + free(basename_cpy); ++ /* missing parent directory */ ++ if (state.flags.ignore_noent && errno == ENOENT) { ++ return 0; ++ } + goto realpatherr; + } + } else { +@@ -1121,6 +1125,9 @@ static int selinux_restorecon_common(const char *pathname_orig, + free(dirname_cpy); + if (!pathdnamer) { + free(basename_cpy); ++ if (state.flags.ignore_noent && errno == ENOENT) { ++ return 0; ++ } + goto realpatherr; + } + if (!strcmp(pathdnamer, "/")) +-- +2.38.1 + diff --git a/0019-libselinux-ignore-invalid-class-name-lookup.patch b/0019-libselinux-ignore-invalid-class-name-lookup.patch new file mode 100644 index 0000000..91006b9 --- /dev/null +++ b/0019-libselinux-ignore-invalid-class-name-lookup.patch @@ -0,0 +1,44 @@ +From f56a72ac9e86ddfbefedc41080f33fb06639f96b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Thi=C3=A9baud=20Weksteen?= +Date: Mon, 24 Oct 2022 20:13:54 +1100 +Subject: [PATCH] libselinux: ignore invalid class name lookup +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Content-type: text/plain + +selinux_check_access relies on string_to_security_class to resolve the +class index from its char* argument. There is no input validation done +on the string provided. It is possible to supply an argument containing +trailing backslashes (i.e., "sock_file//////") so that the paths built +in discover_class get truncated. The processing will then reference the +same permission file multiple time (e.g., perms/watch_reads will be +truncated to perms/watch). This will leak the memory allocated when +strdup'ing the permission name. The discover_class_cache will end up in +an invalid state (but not corrupted). + +Ensure that the class provided does not contain any path separator. + +Signed-off-by: Thiébaud Weksteen +Acked-by: James Carter +--- + libselinux/src/stringrep.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/libselinux/src/stringrep.c b/libselinux/src/stringrep.c +index 2fe69f4391ae..592410e55da0 100644 +--- a/libselinux/src/stringrep.c ++++ b/libselinux/src/stringrep.c +@@ -63,6 +63,9 @@ static struct discover_class_node * discover_class(const char *s) + return NULL; + } + ++ if (strchr(s, '/') != NULL) ++ return NULL; ++ + /* allocate a node */ + node = malloc(sizeof(struct discover_class_node)); + if (node == NULL) +-- +2.38.1 + diff --git a/0001-Use-SHA-2-instead-of-SHA-1.patch b/0020-Use-SHA-2-instead-of-SHA-1.patch similarity index 99% rename from 0001-Use-SHA-2-instead-of-SHA-1.patch rename to 0020-Use-SHA-2-instead-of-SHA-1.patch index 5a1c4c1..f81bf0f 100644 --- a/0001-Use-SHA-2-instead-of-SHA-1.patch +++ b/0020-Use-SHA-2-instead-of-SHA-1.patch @@ -1,4 +1,4 @@ -From f2c923b1764cf647570eaf6c904e4a95ff851cb1 Mon Sep 17 00:00:00 2001 +From e5a015f1edd5e7ed87f6f4ec6ddb45637fa178ab Mon Sep 17 00:00:00 2001 From: Petr Lautrbach Date: Fri, 30 Jul 2021 14:14:37 +0200 Subject: [PATCH] Use SHA-2 instead of SHA-1 @@ -185,10 +185,10 @@ index c56326814b94..098c840fc59b 100644 .BR selabel_open (3) must be called specifying the required diff --git a/libselinux/src/Makefile b/libselinux/src/Makefile -index 04bf4f240168..222c3fa2d7c3 100644 +index dc2848322e4d..fbd978237f5a 100644 --- a/libselinux/src/Makefile +++ b/libselinux/src/Makefile -@@ -119,7 +119,7 @@ DISABLE_FLAGS+= -DNO_MEDIA_BACKEND -DNO_DB_BACKEND -DNO_X_BACKEND \ +@@ -125,7 +125,7 @@ DISABLE_FLAGS+= -DNO_MEDIA_BACKEND -DNO_DB_BACKEND -DNO_X_BACKEND \ -DBUILD_HOST SRCS= callbacks.c freecon.c label.c label_file.c \ label_backends_android.c regex.c label_support.c \ @@ -371,7 +371,7 @@ index 54fd49a5b7b9..4003eb8dc7af 100644 digest->hashbuf = NULL; return; diff --git a/libselinux/src/selinux_restorecon.c b/libselinux/src/selinux_restorecon.c -index 9dd6be817832..dc222b425c95 100644 +index 6b5f6921b82b..24604776974e 100644 --- a/libselinux/src/selinux_restorecon.c +++ b/libselinux/src/selinux_restorecon.c @@ -37,7 +37,7 @@ @@ -448,7 +448,7 @@ index 9dd6be817832..dc222b425c95 100644 return 0; oom: -@@ -781,7 +781,7 @@ err: +@@ -775,7 +775,7 @@ err: struct dir_hash_node { char *path; @@ -457,7 +457,7 @@ index 9dd6be817832..dc222b425c95 100644 struct dir_hash_node *next; }; /* -@@ -1270,7 +1270,7 @@ static int selinux_restorecon_common(const char *pathname_orig, +@@ -1281,7 +1281,7 @@ static int selinux_restorecon_common(const char *pathname_orig, if (setxattr(current->path, RESTORECON_PARTIAL_MATCH_DIGEST, current->digest, @@ -1349,5 +1349,5 @@ index c4e0f836b260..80723f714264 100644 } default: -- -2.36.1 +2.38.1 diff --git a/libselinux.spec b/libselinux.spec index 140ab51..4b67cff 100644 --- a/libselinux.spec +++ b/libselinux.spec @@ -1,10 +1,10 @@ %define ruby_inc %(pkg-config --cflags ruby) -%define libsepolver 3.4-1 +%define libsepolver 3.4-4 Summary: SELinux library and simple utilities Name: libselinux Version: 3.4 -Release: 5%{?dist} +Release: 6%{?dist} License: LicenseRef-Fedora-Public-Domain # https://github.com/SELinuxProject/selinux/wiki/Releases Source0: https://github.com/SELinuxProject/selinux/releases/download/3.4/libselinux-3.4.tar.gz @@ -16,12 +16,30 @@ Url: https://github.com/SELinuxProject/selinux/wiki # $ git format-patch -N 3.4 -- libselinux # $ i=1; for j in 00*patch; do printf "Patch%04d: %s\n" $i $j; i=$((i+1));done # Patch list start -Patch0001: 0001-Use-SHA-2-instead-of-SHA-1.patch +Patch0001: 0001-libselinux-declare-return-value-of-context_str-3-con.patch Patch0002: 0002-Revert-libselinux-restorecon-pin-file-to-avoid-TOCTO.patch +Patch0003: 0003-libselinux-do-not-return-the-cached-prev_current-val.patch +Patch0004: 0004-libselinux-simplify-policy-path-logic-to-avoid-unini.patch +Patch0005: 0005-libselinux-add-header-guard-for-internal-header.patch +Patch0006: 0006-libselinux-introduce-strlcpy.patch +Patch0007: 0007-libselinux-check-for-truncations.patch +Patch0008: 0008-libselinux-add-man-page-redirections.patch +Patch0009: 0009-libselinux-enclose-macro-definition-in-parenthesis.patch +Patch0010: 0010-libselinux-name-parameters-in-context.h.patch +Patch0011: 0011-libselinux-declare-parameter-of-security_load_policy.patch +Patch0012: 0012-libselinux-restorecon-avoid-printing-NULL-pointer.patch +Patch0013: 0013-libselinux-set-errno-to-EBADF-on-O_PATH-emulation-EN.patch +Patch0014: 0014-libselinux-avoid-newline-in-avc-message.patch +Patch0015: 0015-Ignore-egg-info-directories-and-clean-them.patch +Patch0016: 0016-libselinux-support-objname-in-compute_create.patch +Patch0017: 0017-libselinux-Remove-dependency-on-the-Python-module-di.patch +Patch0018: 0018-libselinux-Ignore-missing-directories-when-i-is-used.patch +Patch0019: 0019-libselinux-ignore-invalid-class-name-lookup.patch +Patch0020: 0020-Use-SHA-2-instead-of-SHA-1.patch # Patch list end BuildRequires: gcc make BuildRequires: ruby-devel ruby libsepol-static >= %{libsepolver} swig pcre2-devel xz-devel -BuildRequires: python3 python3-devel +BuildRequires: python3 python3-devel python3-setuptools BuildRequires: systemd Requires: libsepol%{?_isa} >= %{libsepolver} pcre2 Conflicts: filesystem < 3, selinux-policy-base < 3.13.1-138 @@ -214,6 +232,9 @@ rm -f %{buildroot}%{_mandir}/man8/togglesebool* %{ruby_vendorarchdir}/selinux.so %changelog +* Mon Nov 21 2022 Petr Lautrbach - 3.4-6 +- Rebase on upstream f56a72ac9e86 + * Thu Jul 21 2022 Fedora Release Engineering - 3.4-5 - Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild