diff --git a/SOURCES/bz1477461-1-main-Add-option-to-set-priority.patch b/SOURCES/bz1477461-1-main-Add-option-to-set-priority.patch new file mode 100644 index 0000000..52c8171 --- /dev/null +++ b/SOURCES/bz1477461-1-main-Add-option-to-set-priority.patch @@ -0,0 +1,231 @@ +From a008448efb2b1d45c432867caf08f0bcf2b4b9b0 Mon Sep 17 00:00:00 2001 +From: Jan Friesse +Date: Fri, 7 Jul 2017 17:49:46 +0200 +Subject: [PATCH] main: Add option to set priority + +Option -P takes numeric value with same meaning +as nice or values min / max, meaning maximal / minimal priority (so +minimal / maximal nice value). + +Scheduler / priority setting is moved in code so it is now executed +after logsys is configured so errors are logged. + +Setting maximal priority is also used as fallback when realtime +scheduling is requested and sched_setscheduler fails. + +Signed-off-by: Jan Friesse +Reviewed-by: Christine Caulfield +--- + exec/main.c | 71 ++++++++++++++++++++++++++++++++++++++++++++------------ + man/corosync.8 | 22 +++++++++++++---- + 2 files changed, 73 insertions(+), 20 deletions(-) + +diff --git a/exec/main.c b/exec/main.c +index 0d381c2..60c01a4 100644 +--- a/exec/main.c ++++ b/exec/main.c +@@ -862,8 +862,10 @@ static void timer_function_scheduler_timeout (void *data) + } + + +-static void corosync_setscheduler (void) ++static int corosync_set_rr_scheduler (void) + { ++ int ret_val = 0; ++ + #if defined(HAVE_PTHREAD_SETSCHEDPARAM) && defined(HAVE_SCHED_GET_PRIORITY_MAX) && defined(HAVE_SCHED_SETSCHEDULER) + int res; + +@@ -880,6 +882,7 @@ static void corosync_setscheduler (void) + #ifdef HAVE_QB_LOG_THREAD_PRIORITY_SET + qb_log_thread_priority_set (SCHED_OTHER, 0); + #endif ++ ret_val = -1; + } else { + + /* +@@ -901,11 +904,15 @@ static void corosync_setscheduler (void) + LOGSYS_PERROR (errno, LOGSYS_LEVEL_WARNING, + "Could not get maximum scheduler priority"); + sched_priority = 0; ++ ret_val = -1; + } + #else + log_printf(LOGSYS_LEVEL_WARNING, + "The Platform is missing process priority setting features. Leaving at default."); ++ ret_val = -1; + #endif ++ ++ return (ret_val); + } + + +@@ -1132,29 +1139,48 @@ int main (int argc, char **argv, char **envp) + const char *error_string; + struct totem_config totem_config; + int res, ch; +- int background, setprio, testonly; ++ int background, sched_rr, prio, testonly; + struct stat stat_out; + enum e_corosync_done flock_err; + uint64_t totem_config_warnings; + struct scheduler_pause_timeout_data scheduler_pause_timeout_data; ++ long int tmpli; ++ char *ep; + + /* default configuration + */ + background = 1; +- setprio = 1; ++ sched_rr = 1; ++ prio = 0; + testonly = 0; + +- while ((ch = getopt (argc, argv, "fprtv")) != EOF) { ++ while ((ch = getopt (argc, argv, "fP:prtv")) != EOF) { + + switch (ch) { + case 'f': + background = 0; + break; + case 'p': +- setprio = 0; ++ sched_rr = 0; ++ break; ++ case 'P': ++ if (strcmp(optarg, "max") == 0) { ++ prio = INT_MIN; ++ } else if (strcmp(optarg, "min") == 0) { ++ prio = INT_MAX; ++ } else { ++ tmpli = strtol(optarg, &ep, 10); ++ if (errno != 0 || *ep != '\0' || tmpli > INT_MAX || tmpli < INT_MIN) { ++ fprintf(stderr, "Priority value %s is invalid", optarg); ++ logsys_system_fini(); ++ return EXIT_FAILURE; ++ } ++ ++ prio = tmpli; ++ } + break; + case 'r': +- setprio = 1; ++ sched_rr = 1; + break; + case 't': + testonly = 1; +@@ -1170,8 +1196,9 @@ int main (int argc, char **argv, char **envp) + fprintf(stderr, \ + "usage:\n"\ + " -f : Start application in foreground.\n"\ +- " -p : Do not set process priority.\n"\ ++ " -p : Do not set realtime scheduling.\n"\ + " -r : Set round robin realtime scheduling (default).\n"\ ++ " -P num : Set priority of process (no effect when -r is used)\n"\ + " -t : Test configuration and exit.\n"\ + " -v : Display version and SVN revision of Corosync and exit.\n"); + logsys_system_fini(); +@@ -1179,14 +1206,6 @@ int main (int argc, char **argv, char **envp) + } + } + +- /* +- * Set round robin realtime scheduling with priority 99 +- * Lock all memory to avoid page faults which may interrupt +- * application healthchecking +- */ +- if (setprio) { +- corosync_setscheduler (); +- } + + /* + * Other signals are registered later via qb_loop_signal_add +@@ -1293,6 +1312,24 @@ int main (int argc, char **argv, char **envp) + corosync_exit_error (COROSYNC_DONE_EXIT); + } + ++ /* ++ * Set round robin realtime scheduling with priority 99 ++ */ ++ if (sched_rr) { ++ if (corosync_set_rr_scheduler () != 0) { ++ prio = INT_MIN; ++ } else { ++ prio = 0; ++ } ++ } ++ ++ if (prio != 0) { ++ if (setpriority(PRIO_PGRP, 0, prio) != 0) { ++ LOGSYS_PERROR(errno, LOGSYS_LEVEL_WARNING, ++ "Could not set priority %d", prio); ++ } ++ } ++ + ip_version = totem_config.ip_version; + + totem_config.totem_memb_ring_id_create_or_load = corosync_ring_id_create_or_load; +@@ -1319,6 +1356,10 @@ int main (int argc, char **argv, char **envp) + corosync_tty_detach (); + } + ++ /* ++ * Lock all memory to avoid page faults which may interrupt ++ * application healthchecking ++ */ + corosync_mlockall (); + + corosync_poll_handle = qb_loop_create (); +diff --git a/man/corosync.8 b/man/corosync.8 +index 89ab771..dc596d1 100644 +--- a/man/corosync.8 ++++ b/man/corosync.8 +@@ -1,5 +1,5 @@ + .\"/* +-.\" * Copyright (C) 2010 Red Hat, Inc. ++.\" * Copyright (C) 2010-2017 Red Hat, Inc. + .\" * + .\" * All rights reserved. + .\" * +@@ -31,11 +31,11 @@ + .\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + .\" * THE POSSIBILITY OF SUCH DAMAGE. + .\" */ +-.TH COROSYNC 8 2010-05-30 ++.TH COROSYNC 8 2017-07-07 + .SH NAME + corosync \- The Corosync Cluster Engine. + .SH SYNOPSIS +-.B "corosync [\-f] [\-p] [\-r] [\-t] [\-v]" ++.B "corosync [\-f] [\-P num] [\-p] [\-r] [\-t] [\-v]" + .SH DESCRIPTION + .B corosync + Corosync provides clustering infrastructure such as membership, messaging and quorum. +@@ -45,10 +45,22 @@ Corosync provides clustering infrastructure such as membership, messaging and qu + Start application in foreground. + .TP + .B -p +-Do not set process priority. ++Do not set realtime scheduling. + .TP ++.B -P ++Set priority of process. Has effect only when + .B -r +-Set round robin realtime scheduling (default). ++is not used. Can be ether numeric value with similar meaning as ++.BR nice (1) ++or ++.B max ++/ ++.B min ++meaning maximal / minimal priority (so minimal / maximal nice value). ++.TP ++.B -r ++Set round robin realtime scheduling with maximal priority (default). When setting ++of scheduler fails, fallback to set maximal priority. + .TP + .B -t + Test configuration and then exit. +-- +1.7.1 + diff --git a/SOURCES/bz1477461-2-main-Add-support-for-libcgroup.patch b/SOURCES/bz1477461-2-main-Add-support-for-libcgroup.patch new file mode 100644 index 0000000..2a3a362 --- /dev/null +++ b/SOURCES/bz1477461-2-main-Add-support-for-libcgroup.patch @@ -0,0 +1,288 @@ +From c56086c701d08fc17cf6d8ef603caf505a4021b7 Mon Sep 17 00:00:00 2001 +From: Jan Friesse +Date: Fri, 28 Jul 2017 16:32:58 +0200 +Subject: [PATCH] main: Add support for libcgroup + +When corosync is started in environment where it ends in cgroup without +properly set rt_runtime_us it's impossible to get RT priority. + +Already implemented workaround is to use higher non-RT priority. + +This patch implements another solution. It moves corosync into root cpu +cgroup. Root cpu cgroup hopefully has enough RT budget. + +Another solution was mentioned on ML +https://lists.freedesktop.org/archives/systemd-devel/2017-July/039353.html +but this means to generate some "random" values. + +Signed-off-by: Jan Friesse +Reviewed-by: Fabio M. Di Nitto +Reviewed-by: Christine Caulfield +--- + configure.ac | 11 ++++++ + corosync.spec.in | 7 ++++ + exec/Makefile.am | 5 +++ + exec/main.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++- + man/corosync.8 | 6 +++- + 5 files changed, 131 insertions(+), 3 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 81fc91b..e60bf1b 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -416,6 +416,10 @@ AC_ARG_ENABLE([qnetd], + [ --enable-qnetd : Quorum Net Daemon support ],, + [ enable_qnetd="no" ]) + AM_CONDITIONAL(BUILD_QNETD, test x$enable_qnetd = xyes) ++AC_ARG_ENABLE([libcgroup], ++ [ --enable-libcgroup : Enable libcgroup support ],, ++ [ enable_libcgroup="no" ]) ++AM_CONDITIONAL(ENABLE_LIBCGROUP, test x$enable_libcgroup = xyes) + + # *FLAGS handling goes here + +@@ -548,6 +552,13 @@ if test "x${enable_snmp}" = xyes; then + fi + AM_CONDITIONAL(BUILD_SNMP, test "${do_snmp}" = "1") + ++if test "x${enable_libcgroup}" = xyes; then ++ PKG_CHECK_MODULES([libcgroup], [libcgroup]) ++ AC_DEFINE_UNQUOTED([HAVE_LIBCGROUP], 1, [have libcgroup]) ++ PACKAGE_FEATURES="$PACKAGE_FEATURES libcgroup" ++ WITH_LIST="$WITH_LIST --with libcgroup" ++fi ++ + # extra warnings + EXTRA_WARNINGS="" + +diff --git a/corosync.spec.in b/corosync.spec.in +index 97c8e03..49d7b7e 100644 +--- a/corosync.spec.in ++++ b/corosync.spec.in +@@ -17,6 +17,7 @@ + %bcond_with runautogen + %bcond_with qdevices + %bcond_with qnetd ++%bcond_with libcgroup + + %global gitver %{?numcomm:.%{numcomm}}%{?alphatag:.%{alphatag}}%{?dirty:.%{dirty}} + %global gittarver %{?numcomm:.%{numcomm}}%{?alphatag:-%{alphatag}}%{?dirty:-%{dirty}} +@@ -74,6 +75,9 @@ Requires: nss-tools + %if %{with qnetd} + BuildRequires: sed + %endif ++%if %{with libcgroup} ++BuildRequires: libcgroup-devel ++%endif + + BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) + +@@ -125,6 +129,9 @@ export rdmacm_LIBS=-lrdmacm \ + %if %{with qnetd} + --enable-qnetd \ + %endif ++%if %{with libcgroup} ++ --enable-libcgroup \ ++%endif + --with-initddir=%{_initrddir} \ + --with-systemddir=%{_unitdir} \ + --with-upstartdir=%{_sysconfdir}/init \ +diff --git a/exec/Makefile.am b/exec/Makefile.am +index 9ca7720..670daf6 100644 +--- a/exec/Makefile.am ++++ b/exec/Makefile.am +@@ -78,5 +78,10 @@ corosync_LDADD = libtotem_pg.la ../common_lib/libcorosync_common.la \ + + corosync_DEPENDENCIES = libtotem_pg.la ../common_lib/libcorosync_common.la + ++if ENABLE_LIBCGROUP ++corosync_CFLAGS += $(libcgroup_CFLAGS) ++corosync_LDADD += $(libcgroup_LIBS) ++endif ++ + lint: + -splint $(LINT_FLAGS) $(CPPFLAGS) $(CFLAGS) *.c +diff --git a/exec/main.c b/exec/main.c +index 60c01a4..b3e7478 100644 +--- a/exec/main.c ++++ b/exec/main.c +@@ -110,6 +110,10 @@ + #include + #include + ++#ifdef HAVE_LIBCGROUP ++#include ++#endif ++ + #include "quorum.h" + #include "totemsrp.h" + #include "logconfig.h" +@@ -1134,12 +1138,95 @@ error_close: + return (err); + } + ++static int corosync_move_to_root_cgroup(void) { ++ int res = -1; ++#ifdef HAVE_LIBCGROUP ++ int cg_ret; ++ struct cgroup *root_cgroup = NULL; ++ struct cgroup_controller *root_cpu_cgroup_controller = NULL; ++ char *current_cgroup_path = NULL; ++ ++ cg_ret = cgroup_init(); ++ if (cg_ret) { ++ log_printf(LOGSYS_LEVEL_WARNING, "Unable to initialize libcgroup: %s ", ++ cgroup_strerror(cg_ret)); ++ ++ goto exit_res; ++ } ++ ++ cg_ret = cgroup_get_current_controller_path(getpid(), "cpu", ¤t_cgroup_path); ++ if (cg_ret) { ++ log_printf(LOGSYS_LEVEL_WARNING, "Unable to get current cpu cgroup path: %s ", ++ cgroup_strerror(cg_ret)); ++ ++ goto exit_res; ++ } ++ ++ if (strcmp(current_cgroup_path, "/") == 0) { ++ log_printf(LOGSYS_LEVEL_DEBUG, "Corosync is already in root cgroup path"); ++ ++ res = 0; ++ goto exit_res; ++ } ++ ++ root_cgroup = cgroup_new_cgroup("/"); ++ if (root_cgroup == NULL) { ++ log_printf(LOGSYS_LEVEL_WARNING, "Can't create root cgroup"); ++ ++ goto exit_res; ++ } ++ ++ root_cpu_cgroup_controller = cgroup_add_controller(root_cgroup, "cpu"); ++ if (root_cpu_cgroup_controller == NULL) { ++ log_printf(LOGSYS_LEVEL_WARNING, "Can't create root cgroup cpu controller"); ++ ++ goto exit_res; ++ } ++ ++ cg_ret = cgroup_attach_task(root_cgroup); ++ if (cg_ret) { ++ log_printf(LOGSYS_LEVEL_WARNING, "Can't attach task to root cgroup: %s ", ++ cgroup_strerror(cg_ret)); ++ ++ goto exit_res; ++ } ++ ++ cg_ret = cgroup_get_current_controller_path(getpid(), "cpu", ¤t_cgroup_path); ++ if (cg_ret) { ++ log_printf(LOGSYS_LEVEL_WARNING, "Unable to get current cpu cgroup path: %s ", ++ cgroup_strerror(cg_ret)); ++ ++ goto exit_res; ++ } ++ ++ if (strcmp(current_cgroup_path, "/") == 0) { ++ log_printf(LOGSYS_LEVEL_NOTICE, "Corosync sucesfully moved to root cgroup"); ++ res = 0; ++ } else { ++ log_printf(LOGSYS_LEVEL_WARNING, "Can't move Corosync to root cgroup"); ++ } ++ ++exit_res: ++ if (root_cgroup != NULL) { ++ cgroup_free(&root_cgroup); ++ } ++ ++ /* ++ * libcgroup doesn't define something like cgroup_fini so there is no way how to clean ++ * it's cache. It has to be called when libcgroup authors decide to implement it. ++ */ ++ ++#endif ++ return (res); ++} ++ ++ + int main (int argc, char **argv, char **envp) + { + const char *error_string; + struct totem_config totem_config; + int res, ch; +- int background, sched_rr, prio, testonly; ++ int background, sched_rr, prio, testonly, move_to_root_cgroup; + struct stat stat_out; + enum e_corosync_done flock_err; + uint64_t totem_config_warnings; +@@ -1153,8 +1240,9 @@ int main (int argc, char **argv, char **envp) + sched_rr = 1; + prio = 0; + testonly = 0; ++ move_to_root_cgroup = 1; + +- while ((ch = getopt (argc, argv, "fP:prtv")) != EOF) { ++ while ((ch = getopt (argc, argv, "fP:pRrtv")) != EOF) { + + switch (ch) { + case 'f': +@@ -1179,6 +1267,9 @@ int main (int argc, char **argv, char **envp) + prio = tmpli; + } + break; ++ case 'R': ++ move_to_root_cgroup = 0; ++ break; + case 'r': + sched_rr = 1; + break; +@@ -1198,6 +1289,7 @@ int main (int argc, char **argv, char **envp) + " -f : Start application in foreground.\n"\ + " -p : Do not set realtime scheduling.\n"\ + " -r : Set round robin realtime scheduling (default).\n"\ ++ " -R : Do not try move corosync to root cpu cgroup (valid when built with libcgroup)\n" \ + " -P num : Set priority of process (no effect when -r is used)\n"\ + " -t : Test configuration and exit.\n"\ + " -v : Display version and SVN revision of Corosync and exit.\n"); +@@ -1312,6 +1404,15 @@ int main (int argc, char **argv, char **envp) + corosync_exit_error (COROSYNC_DONE_EXIT); + } + ++ ++ /* ++ * Try to move corosync into root cpu cgroup. Failure is not fatal and ++ * error is deliberately ignored. ++ */ ++ if (move_to_root_cgroup) { ++ (void)corosync_move_to_root_cgroup(); ++ } ++ + /* + * Set round robin realtime scheduling with priority 99 + */ +diff --git a/man/corosync.8 b/man/corosync.8 +index dc596d1..7bce65e 100644 +--- a/man/corosync.8 ++++ b/man/corosync.8 +@@ -35,7 +35,7 @@ + .SH NAME + corosync \- The Corosync Cluster Engine. + .SH SYNOPSIS +-.B "corosync [\-f] [\-P num] [\-p] [\-r] [\-t] [\-v]" ++.B "corosync [\-f] [\-P num] [\-p] [\-r] [-R] [\-t] [\-v]" + .SH DESCRIPTION + .B corosync + Corosync provides clustering infrastructure such as membership, messaging and quorum. +@@ -62,6 +62,10 @@ meaning maximal / minimal priority (so minimal / maximal nice value). + Set round robin realtime scheduling with maximal priority (default). When setting + of scheduler fails, fallback to set maximal priority. + .TP ++.B -R ++Do not try to move Corosync to root cpu cgroup. This feature is available only ++for corosync with libcgroup enabled during the build. ++.TP + .B -t + Test configuration and then exit. + .TP +-- +1.7.1 + diff --git a/SOURCES/bz1484264-1-totem-Propagate-totem-initialization-failure.patch b/SOURCES/bz1484264-1-totem-Propagate-totem-initialization-failure.patch new file mode 100644 index 0000000..d240842 --- /dev/null +++ b/SOURCES/bz1484264-1-totem-Propagate-totem-initialization-failure.patch @@ -0,0 +1,117 @@ +From 0413a8f4672352171f0df731b7d9c1fe20acbc4c Mon Sep 17 00:00:00 2001 +From: Jan Friesse +Date: Wed, 14 Jun 2017 16:27:37 +0200 +Subject: [PATCH] totem: Propagate totem initialization failure + +(backported from master 564b4bf7d4c5b3f632a48610761dce58e5809b3a) + +Signed-off-by: Jan Friesse +Reviewed-by: Christine Caulfield +--- + exec/main.c | 8 ++++++-- + exec/totempg.c | 5 +++++ + exec/totemrrp.c | 6 +++++- + exec/totemsrp.c | 6 +++++- + 4 files changed, 21 insertions(+), 4 deletions(-) + +diff --git a/exec/main.c b/exec/main.c +index 5f96c28..0d381c2 100644 +--- a/exec/main.c ++++ b/exec/main.c +@@ -1355,9 +1355,13 @@ int main (int argc, char **argv, char **envp) + * Join multicast group and setup delivery + * and configuration change functions + */ +- totempg_initialize ( ++ if (totempg_initialize ( + corosync_poll_handle, +- &totem_config); ++ &totem_config) != 0) { ++ ++ log_printf (LOGSYS_LEVEL_ERROR, "Can't initialize TOTEM layer"); ++ corosync_exit_error (COROSYNC_DONE_FATAL_ERR); ++ } + + totempg_service_ready_register ( + main_service_ready); +diff --git a/exec/totempg.c b/exec/totempg.c +index 05729be..5cef5e1 100644 +--- a/exec/totempg.c ++++ b/exec/totempg.c +@@ -814,6 +814,10 @@ int totempg_initialize ( + totempg_confchg_fn, + totempg_waiting_trans_ack_cb); + ++ if (res == -1) { ++ goto error_exit; ++ } ++ + totemmrp_callback_token_create ( + &callback_token_received_handle, + TOTEM_CALLBACK_TOKEN_RECEIVED, +@@ -827,6 +831,7 @@ int totempg_initialize ( + + list_init (&totempg_groups_list); + ++error_exit: + return (res); + } + +diff --git a/exec/totemrrp.c b/exec/totemrrp.c +index c6b97bc..f806feb 100644 +--- a/exec/totemrrp.c ++++ b/exec/totemrrp.c +@@ -2150,7 +2150,7 @@ int totemrrp_initialize ( + deliver_fn_context->iface_no = i; + instance->deliver_fn_context[i] = (void *)deliver_fn_context; + +- totemnet_initialize ( ++ res = totemnet_initialize ( + poll_handle, + &instance->net_handles[i], + totem_config, +@@ -2161,6 +2161,10 @@ int totemrrp_initialize ( + rrp_iface_change_fn, + rrp_target_set_completed); + ++ if (res == -1) { ++ goto error_destroy; ++ } ++ + totemnet_net_mtu_adjust (instance->net_handles[i], totem_config); + } + +diff --git a/exec/totemsrp.c b/exec/totemsrp.c +index f80f8e4..91c5423 100644 +--- a/exec/totemsrp.c ++++ b/exec/totemsrp.c +@@ -851,6 +851,7 @@ int totemsrp_initialize ( + int waiting_trans_ack)) + { + struct totemsrp_instance *instance; ++ int res; + + instance = malloc (sizeof (struct totemsrp_instance)); + if (instance == NULL) { +@@ -993,7 +994,7 @@ int totemsrp_initialize ( + } + } + +- totemrrp_initialize ( ++ res = totemrrp_initialize ( + poll_handle, + &instance->totemrrp_context, + totem_config, +@@ -1004,6 +1005,9 @@ int totemsrp_initialize ( + main_token_seqid_get, + main_msgs_missing, + target_set_completed); ++ if (res == -1) { ++ goto error_exit; ++ } + + /* + * Must have net_mtu adjusted by totemrrp_initialize first +-- +1.7.1 + diff --git a/SOURCES/bz1484264-2-totemcrypto-Refactor-symmetric-key-importing.patch b/SOURCES/bz1484264-2-totemcrypto-Refactor-symmetric-key-importing.patch new file mode 100644 index 0000000..f130bfc --- /dev/null +++ b/SOURCES/bz1484264-2-totemcrypto-Refactor-symmetric-key-importing.patch @@ -0,0 +1,156 @@ +From a885868181c07ba9ab5cdfdad1d66d387b2a4428 Mon Sep 17 00:00:00 2001 +From: Jan Friesse +Date: Tue, 20 Jun 2017 15:25:09 +0200 +Subject: [PATCH] totemcrypto: Refactor symmetric key importing + +Signed-off-by: Jan Friesse +Reviewed-by: Fabio M. Di Nitto +Reviewed-by: Christine Caulfield +--- + exec/totemcrypto.c | 96 +++++++++++++++++++++++++++++----------------------- + 1 files changed, 54 insertions(+), 42 deletions(-) + +diff --git a/exec/totemcrypto.c b/exec/totemcrypto.c +index a97ba62..0e98f27 100644 +--- a/exec/totemcrypto.c ++++ b/exec/totemcrypto.c +@@ -206,6 +206,11 @@ do { \ + (const char *)format, ##args); \ + } while (0); + ++enum sym_key_type { ++ SYM_KEY_TYPE_CRYPT, ++ SYM_KEY_TYPE_HASH ++}; ++ + /* + * crypt/decrypt functions + */ +@@ -226,38 +231,65 @@ static int string_to_crypto_cipher_type(const char* crypto_cipher_type) + return CRYPTO_CIPHER_TYPE_AES256; + } + +-static int init_nss_crypto(struct crypto_instance *instance) ++static PK11SymKey *import_symmetric_key(struct crypto_instance *instance, enum sym_key_type key_type) + { +- PK11SlotInfo* crypt_slot = NULL; +- SECItem crypt_param; ++ SECItem key_item; ++ PK11SlotInfo *slot; ++ PK11SymKey *res_key; ++ CK_MECHANISM_TYPE cipher; ++ CK_ATTRIBUTE_TYPE operation; ++ ++ memset(&key_item, 0, sizeof(key_item)); ++ slot = NULL; ++ ++ key_item.type = siBuffer; ++ key_item.data = instance->private_key; ++ ++ switch (key_type) { ++ case SYM_KEY_TYPE_CRYPT: ++ key_item.len = cipher_key_len[instance->crypto_cipher_type]; ++ cipher = cipher_to_nss[instance->crypto_cipher_type]; ++ operation = CKA_ENCRYPT|CKA_DECRYPT; ++ break; ++ case SYM_KEY_TYPE_HASH: ++ key_item.len = instance->private_key_len; ++ cipher = hash_to_nss[instance->crypto_hash_type]; ++ operation = CKA_SIGN; ++ break; ++ } ++ ++ slot = PK11_GetBestSlot(cipher, NULL); ++ if (slot == NULL) { ++ log_printf(instance->log_level_security, "Unable to find security slot (%d): %s", ++ PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT)); ++ return (NULL); ++ } + +- if (!cipher_to_nss[instance->crypto_cipher_type]) { +- return 0; ++ res_key = PK11_ImportSymKey(slot, cipher, PK11_OriginUnwrap, operation, &key_item, NULL); ++ if (res_key == NULL) { ++ log_printf(instance->log_level_security, "Failure to import key into NSS (%d): %s", ++ PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT)); ++ goto exit_err; + } + +- crypt_param.type = siBuffer; +- crypt_param.data = instance->private_key; +- crypt_param.len = cipher_key_len[instance->crypto_cipher_type]; ++exit_err: ++ PK11_FreeSlot(slot); + +- crypt_slot = PK11_GetBestSlot(cipher_to_nss[instance->crypto_cipher_type], NULL); +- if (crypt_slot == NULL) { +- log_printf(instance->log_level_security, "Unable to find security slot (err %d)", +- PR_GetError()); +- return -1; ++ return (res_key); ++} ++ ++static int init_nss_crypto(struct crypto_instance *instance) ++{ ++ ++ if (!cipher_to_nss[instance->crypto_cipher_type]) { ++ return 0; + } + +- instance->nss_sym_key = PK11_ImportSymKey(crypt_slot, +- cipher_to_nss[instance->crypto_cipher_type], +- PK11_OriginUnwrap, CKA_ENCRYPT|CKA_DECRYPT, +- &crypt_param, NULL); ++ instance->nss_sym_key = import_symmetric_key(instance, SYM_KEY_TYPE_CRYPT); + if (instance->nss_sym_key == NULL) { +- log_printf(instance->log_level_security, "Failure to import key into NSS (err %d)", +- PR_GetError()); + return -1; + } + +- PK11_FreeSlot(crypt_slot); +- + return 0; + } + +@@ -447,36 +479,16 @@ static int string_to_crypto_hash_type(const char* crypto_hash_type) + + static int init_nss_hash(struct crypto_instance *instance) + { +- PK11SlotInfo* hash_slot = NULL; +- SECItem hash_param; + + if (!hash_to_nss[instance->crypto_hash_type]) { + return 0; + } + +- hash_param.type = siBuffer; +- hash_param.data = instance->private_key; +- hash_param.len = instance->private_key_len; +- +- hash_slot = PK11_GetBestSlot(hash_to_nss[instance->crypto_hash_type], NULL); +- if (hash_slot == NULL) { +- log_printf(instance->log_level_security, "Unable to find security slot (err %d)", +- PR_GetError()); +- return -1; +- } +- +- instance->nss_sym_key_sign = PK11_ImportSymKey(hash_slot, +- hash_to_nss[instance->crypto_hash_type], +- PK11_OriginUnwrap, CKA_SIGN, +- &hash_param, NULL); ++ instance->nss_sym_key_sign = import_symmetric_key(instance, SYM_KEY_TYPE_HASH); + if (instance->nss_sym_key_sign == NULL) { +- log_printf(instance->log_level_security, "Failure to import key into NSS (err %d)", +- PR_GetError()); + return -1; + } + +- PK11_FreeSlot(hash_slot); +- + return 0; + } + +-- +1.7.1 + diff --git a/SOURCES/bz1484264-3-totemcrypto-Use-different-method-to-import-key.patch b/SOURCES/bz1484264-3-totemcrypto-Use-different-method-to-import-key.patch new file mode 100644 index 0000000..2348633 --- /dev/null +++ b/SOURCES/bz1484264-3-totemcrypto-Use-different-method-to-import-key.patch @@ -0,0 +1,167 @@ +From 5dadebd21862074deaeb9a337fc9e49f5e9f692a Mon Sep 17 00:00:00 2001 +From: Jan Friesse +Date: Tue, 20 Jun 2017 17:37:57 +0200 +Subject: [PATCH] totemcrypto: Use different method to import key + +PK11_ImportSymKey doesn't work when FIPS is enabled because NSS is +targeting to FIPS Level 2 where loading of unencrypted symmetric +key is prohibited. + +FIPS Level 2 is hard to achieve without breaking compatibility so patch +implements "workaround" to make NSS behave like FIPS Level 1 +(where is allowed to load unencrypted symmetric key). + +Workaround is about using temporal key to encrypt corosync authkey in +memory and then to unwrap it into valid NSS key. + +Signed-off-by: Jan Friesse +Reviewed-by: Fabio M. Di Nitto +Reviewed-by: Christine Caulfield +--- + exec/totemcrypto.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++---- + 1 files changed, 91 insertions(+), 7 deletions(-) + +diff --git a/exec/totemcrypto.c b/exec/totemcrypto.c +index 0e98f27..79c4312 100644 +--- a/exec/totemcrypto.c ++++ b/exec/totemcrypto.c +@@ -211,6 +211,8 @@ enum sym_key_type { + SYM_KEY_TYPE_HASH + }; + ++#define MAX_WRAPPED_KEY_LEN 128 ++ + /* + * crypt/decrypt functions + */ +@@ -238,9 +240,20 @@ static PK11SymKey *import_symmetric_key(struct crypto_instance *instance, enum s + PK11SymKey *res_key; + CK_MECHANISM_TYPE cipher; + CK_ATTRIBUTE_TYPE operation; ++ CK_MECHANISM_TYPE wrap_mechanism; ++ int wrap_key_len; ++ PK11SymKey *wrap_key; ++ PK11Context *wrap_key_crypt_context; ++ SECItem tmp_sec_item; ++ SECItem wrapped_key; ++ int wrapped_key_len; ++ unsigned char wrapped_key_data[MAX_WRAPPED_KEY_LEN]; + + memset(&key_item, 0, sizeof(key_item)); + slot = NULL; ++ wrap_key = NULL; ++ res_key = NULL; ++ wrap_key_crypt_context = NULL; + + key_item.type = siBuffer; + key_item.data = instance->private_key; +@@ -262,18 +275,89 @@ static PK11SymKey *import_symmetric_key(struct crypto_instance *instance, enum s + if (slot == NULL) { + log_printf(instance->log_level_security, "Unable to find security slot (%d): %s", + PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT)); +- return (NULL); ++ goto exit_res_key; ++ } ++ ++ /* ++ * Without FIPS it would be possible to just use ++ * res_key = PK11_ImportSymKey(slot, cipher, PK11_OriginUnwrap, operation, &key_item, NULL); ++ * with FIPS NSS Level 2 certification has to be "workarounded" (so it becomes Level 1) by using ++ * following method: ++ * 1. Generate wrap key ++ * 2. Encrypt authkey with wrap key ++ * 3. Unwrap encrypted authkey using wrap key ++ */ ++ ++ /* ++ * Generate wrapping key ++ */ ++ wrap_mechanism = PK11_GetBestWrapMechanism(slot); ++ wrap_key_len = PK11_GetBestKeyLength(slot, wrap_mechanism); ++ wrap_key = PK11_KeyGen(slot, wrap_mechanism, NULL, wrap_key_len, NULL); ++ if (wrap_key == NULL) { ++ log_printf(instance->log_level_security, "Unable to generate wrapping key (%d): %s", ++ PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT)); ++ goto exit_res_key; ++ } ++ ++ /* ++ * Encrypt authkey with wrapping key ++ */ ++ ++ /* ++ * Initialization of IV is not needed because PK11_GetBestWrapMechanism should return ECB mode ++ */ ++ memset(&tmp_sec_item, 0, sizeof(tmp_sec_item)); ++ wrap_key_crypt_context = PK11_CreateContextBySymKey(wrap_mechanism, CKA_ENCRYPT, ++ wrap_key, &tmp_sec_item); ++ if (wrap_key_crypt_context == NULL) { ++ log_printf(instance->log_level_security, "Unable to create encrypt context (%d): %s", ++ PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT)); ++ goto exit_res_key; + } + +- res_key = PK11_ImportSymKey(slot, cipher, PK11_OriginUnwrap, operation, &key_item, NULL); ++ wrapped_key_len = (int)sizeof(wrapped_key_data); ++ ++ if (PK11_CipherOp(wrap_key_crypt_context, wrapped_key_data, &wrapped_key_len, ++ sizeof(wrapped_key_data), key_item.data, key_item.len) != SECSuccess) { ++ log_printf(instance->log_level_security, "Unable to encrypt authkey (%d): %s", ++ PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT)); ++ goto exit_res_key; ++ } ++ ++ if (PK11_Finalize(wrap_key_crypt_context) != SECSuccess) { ++ log_printf(instance->log_level_security, "Unable to finalize encryption of authkey (%d): %s", ++ PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT)); ++ goto exit_res_key; ++ } ++ ++ /* ++ * Finally unwrap sym key ++ */ ++ memset(&tmp_sec_item, 0, sizeof(tmp_sec_item)); ++ wrapped_key.data = wrapped_key_data; ++ wrapped_key.len = wrapped_key_len; ++ ++ res_key = PK11_UnwrapSymKey(wrap_key, wrap_mechanism, &tmp_sec_item, &wrapped_key, ++ cipher, operation, key_item.len); + if (res_key == NULL) { + log_printf(instance->log_level_security, "Failure to import key into NSS (%d): %s", + PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT)); +- goto exit_err; ++ goto exit_res_key; ++ } ++ ++exit_res_key: ++ if (wrap_key_crypt_context != NULL) { ++ PK11_DestroyContext(wrap_key_crypt_context, PR_TRUE); ++ } ++ ++ if (wrap_key != NULL) { ++ PK11_FreeSymKey(wrap_key); + } + +-exit_err: +- PK11_FreeSlot(slot); ++ if (slot != NULL) { ++ PK11_FreeSlot(slot); ++ } + + return (res_key); + } +@@ -344,9 +428,9 @@ static int encrypt_nss( + nss_sec_param); + if (!crypt_context) { + log_printf(instance->log_level_security, +- "PK11_CreateContext failed (encrypt) crypt_type=%d (err %d)", ++ "PK11_CreateContext failed (encrypt) crypt_type=%d (%d): %s", + (int)cipher_to_nss[instance->crypto_cipher_type], +- PR_GetError()); ++ PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT)); + goto out; + } + +-- +1.7.1 + diff --git a/SOURCES/bz1484264-4-totemcrypto-Fix-compiler-warning.patch b/SOURCES/bz1484264-4-totemcrypto-Fix-compiler-warning.patch new file mode 100644 index 0000000..9561822 --- /dev/null +++ b/SOURCES/bz1484264-4-totemcrypto-Fix-compiler-warning.patch @@ -0,0 +1,55 @@ +From fdeed33f514e0056e322a45d9a0a04ca4b9a2709 Mon Sep 17 00:00:00 2001 +From: Jan Friesse +Date: Tue, 1 Aug 2017 14:19:41 +0200 +Subject: [PATCH] totemcrypto: Fix compiler warning + +Signed-off-by: Jan Friesse +--- + exec/totemcrypto.c | 13 +++++++++++++ + 1 files changed, 13 insertions(+), 0 deletions(-) + +diff --git a/exec/totemcrypto.c b/exec/totemcrypto.c +index 79c4312..64246c9 100644 +--- a/exec/totemcrypto.c ++++ b/exec/totemcrypto.c +@@ -248,6 +248,7 @@ static PK11SymKey *import_symmetric_key(struct crypto_instance *instance, enum s + SECItem wrapped_key; + int wrapped_key_len; + unsigned char wrapped_key_data[MAX_WRAPPED_KEY_LEN]; ++ int case_processed; + + memset(&key_item, 0, sizeof(key_item)); + slot = NULL; +@@ -258,17 +259,29 @@ static PK11SymKey *import_symmetric_key(struct crypto_instance *instance, enum s + key_item.type = siBuffer; + key_item.data = instance->private_key; + ++ case_processed = 0; + switch (key_type) { + case SYM_KEY_TYPE_CRYPT: + key_item.len = cipher_key_len[instance->crypto_cipher_type]; + cipher = cipher_to_nss[instance->crypto_cipher_type]; + operation = CKA_ENCRYPT|CKA_DECRYPT; ++ case_processed = 1; + break; + case SYM_KEY_TYPE_HASH: + key_item.len = instance->private_key_len; + cipher = hash_to_nss[instance->crypto_hash_type]; + operation = CKA_SIGN; ++ case_processed = 1; + break; ++ /* ++ * Default is not defined intentionally. Compiler shows warning when ++ * new key_type is added ++ */ ++ } ++ ++ if (!case_processed) { ++ log_printf(instance->log_level_error, "Unknown key_type"); ++ goto exit_res_key; + } + + slot = PK11_GetBestSlot(cipher, NULL); +-- +1.7.1 + diff --git a/SPECS/corosync.spec b/SPECS/corosync.spec index aa7d3b1..eef90da 100644 --- a/SPECS/corosync.spec +++ b/SPECS/corosync.spec @@ -16,6 +16,7 @@ %bcond_without runautogen %bcond_without qdevices %bcond_without qnetd +%bcond_without libcgroup %global gitver %{?numcomm:.%{numcomm}}%{?alphatag:.%{alphatag}}%{?dirty:.%{dirty}} %global gittarver %{?numcomm:.%{numcomm}}%{?alphatag:-%{alphatag}}%{?dirty:-%{dirty}} @@ -23,7 +24,7 @@ Name: corosync Summary: The Corosync Cluster Engine and Application Programming Interfaces Version: 2.4.0 -Release: 9%{?gitver}%{?dist} +Release: 9%{?gitver}%{?dist}.2 License: BSD Group: System Environment/Base URL: http://corosync.github.io/corosync/ @@ -51,6 +52,12 @@ Patch18: bz1434529-8-doc-document-watchdog_device-parameter.patch Patch19: bz1434534-1-Logsys-Change-logsys-syslog_priority-priority.patch Patch20: bz1434534-2-logconfig-Do-not-overwrite-logger_subsys-priority.patch Patch21: bz1445001-1-Main-Call-mlockall-after-fork.patch +Patch22: bz1477461-1-main-Add-option-to-set-priority.patch +Patch23: bz1477461-2-main-Add-support-for-libcgroup.patch +Patch24: bz1484264-1-totem-Propagate-totem-initialization-failure.patch +Patch25: bz1484264-2-totemcrypto-Refactor-symmetric-key-importing.patch +Patch26: bz1484264-3-totemcrypto-Use-different-method-to-import-key.patch +Patch27: bz1484264-4-totemcrypto-Fix-compiler-warning.patch %if 0%{?rhel} ExclusiveArch: i686 x86_64 s390x ppc64le @@ -100,6 +107,9 @@ Requires: nss-tools %if %{with qnetd} BuildRequires: sed %endif +%if %{with libcgroup} +BuildRequires: libcgroup-devel +%endif BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) @@ -127,6 +137,12 @@ BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) %patch19 -p1 -b .bz1434534-1 %patch20 -p1 -b .bz1434534-2 %patch21 -p1 -b .bz1445001-1 +%patch22 -p1 -b .bz1477461-1 +%patch23 -p1 -b .bz1477461-2 +%patch24 -p1 -b .bz1484264-1 +%patch25 -p1 -b .bz1484264-2 +%patch26 -p1 -b .bz1484264-3 +%patch27 -p1 -b .bz1484264-4 %build %if %{with runautogen} @@ -173,6 +189,9 @@ export rdmacm_LIBS=-lrdmacm \ %if %{with qnetd} --enable-qnetd \ %endif +%if %{with libcgroup} + --enable-libcgroup \ +%endif --with-initddir=%{_initrddir} \ --with-systemddir=%{_unitdir} \ --with-upstartdir=%{_sysconfdir}/init \ @@ -555,6 +574,26 @@ fi %endif %changelog +* Thu Aug 24 2017 Jan Friesse 2.4.0-9.2 +- Resolves: rhbz#1484264 + +- totem: Propagate totem initialization failure (rhbz#1484264) +- merge upstream commit 0413a8f4672352171f0df731b7d9c1fe20acbc4c (rhbz#1484264) +- totemcrypto: Refactor symmetric key importing (rhbz#1484264) +- merge upstream commit a885868181c07ba9ab5cdfdad1d66d387b2a4428 (rhbz#1484264) +- totemcrypto: Use different method to import key (rhbz#1484264) +- merge upstream commit 5dadebd21862074deaeb9a337fc9e49f5e9f692a (rhbz#1484264) +- totemcrypto: Fix compiler warning (rhbz#1484264) +- merge upstream commit fdeed33f514e0056e322a45d9a0a04ca4b9a2709 (rhbz#1484264) + +* Wed Aug 02 2017 Jan Friesse 2.4.0-9.1 +- Resolves: rhbz#1477461 + +- main: Add option to set priority (rhbz#1477461) +- merge upstream commit a008448efb2b1d45c432867caf08f0bcf2b4b9b0 (rhbz#1477461) +- main: Add support for libcgroup (rhbz#1477461) +- merge upstream commit c56086c701d08fc17cf6d8ef603caf505a4021b7 (rhbz#1477461) + * Wed Apr 26 2017 Jan Friesse 2.4.0-9 - Resolves: rhbz#1445001