diff mbox series

[V3,09/10] Accept selections from IPC if configured at startup

Message ID 20201116091445.797119-10-sbabic@denx.de
State Accepted
Headers show
Series Rework and extend IPC for install | expand

Commit Message

Stefano Babic Nov. 16, 2020, 9:14 a.m. UTC
If selection can be set via IPC, it could be possible to activate a
selection that can damage the board. For example, the IPC selects to
install into the running rootfs instead of the stand-by copy.

Do not accept any incoming selection, but verify it with a list that is
configured at the startup via command line parameter. The list is set
using --accepted-select, that can be issued multiple times.

The behavior is compatible with the past because if no --accepted-select
is issued, the feature is completely disabled and no selection can be
set via IPC.

Signed-off-by: Stefano Babic <sbabic@denx.de>
---
 core/network_thread.c   | 62 ++++++++++++++++++++++++++++++++++-------
 core/swupdate.c         | 11 +++++++-
 doc/source/swupdate.rst |  7 +++++
 include/swupdate.h      |  1 +
 4 files changed, 70 insertions(+), 11 deletions(-)
diff mbox series

Patch

diff --git a/core/network_thread.c b/core/network_thread.c
index 6757cc4..0e6080d 100644
--- a/core/network_thread.c
+++ b/core/network_thread.c
@@ -56,6 +56,43 @@  static unsigned long nrmsgs = 0;
 
 static pthread_mutex_t msglock = PTHREAD_MUTEX_INITIALIZER;
 
+static bool is_selection_allowed(const char *software_set, char *running_mode,
+				 struct dict const *acceptedlist)
+{
+	char *swset = NULL;
+	struct dict_list *sets;
+	struct dict_list_elem *selection;
+	bool allowed = false;
+
+	/*
+	 * No attempt to change software set
+	 */
+	if (!strlen(software_set) || !strlen(running_mode))
+		return true;
+
+	if (ENOMEM_ASPRINTF ==
+		asprintf(&swset, "%s,%s", software_set, running_mode)) {
+			 ERROR("OOM generating selection string");
+			 return false;
+	}
+	sets = dict_get_list((struct dict *)acceptedlist, "accepted");
+	if (sets && swset) {
+		LIST_FOREACH(selection, sets, next) {
+			if (!strcmp(swset, selection->value)) {
+				allowed = true;
+			}
+		}
+		free(swset);
+	}
+
+	if (allowed) {
+		INFO("Accepted selection %s,%s", software_set, running_mode);
+	}else 
+		ERROR("Selection %s,%s is not allowed, rejected !",
+		      software_set, running_mode); 
+	return allowed;
+}
+
 static void clean_msg(char *msg, char drop)
 {
 	char *lfpos;
@@ -349,17 +386,22 @@  void *network_thread (void *data)
 				if (instp->status == IDLE) {
 					instp->fd = ctrlconnfd;
 					instp->req = msg.data.instmsg.req;
+					if (is_selection_allowed(instp->req.software_set,
+								 instp->req.running_mode,
+								 &instp->software->accepted_set)) {
+						/*
+						 * Prepare answer
+						 */
+						msg.type = ACK;
+
+						/* Drop all old notification from last run */
+						cleanum_msg_list();
+
+						/* Wake-up the installer */
+						pthread_cond_signal(&stream_wkup);
+					} else
+						msg.type = NACK;
 
-					/*
-					 * Prepare answer
-					 */
-					msg.type = ACK;
-
-					/* Drop all old notification from last run */
-					cleanum_msg_list();
-
-					/* Wake-up the installer */
-					pthread_cond_signal(&stream_wkup);
 				} else {
 					msg.type = NACK;
 					sprintf(msg.data.msg, "Installation in progress");
diff --git a/core/swupdate.c b/core/swupdate.c
index b746d8c..ba3656a 100644
--- a/core/swupdate.c
+++ b/core/swupdate.c
@@ -76,6 +76,7 @@  static struct option long_options[] = {
 	{"loglevel", required_argument, NULL, 'l'},
 	{"syslog", no_argument, NULL, 'L' },
 	{"select", required_argument, NULL, 'e'},
+	{"accepted-select", required_argument, NULL, 'q'},
 	{"output", required_argument, NULL, 'o'},
 	{"dry-run", no_argument, NULL, 'n'},
 	{"no-downgrading", required_argument, NULL, 'N'},
@@ -128,6 +129,11 @@  static void usage(char *programname)
 		" -P, --preupdate                : execute pre-update command\n"
 		" -e, --select <software>,<mode> : Select software images set and source\n"
 		"                                  Ex.: stable,main\n"
+		" --accepted-select\n"
+		"            <software>,<mode>   : List for software images set and source\n"
+		"                                  that are accepted via IPC\n"
+		"                                  Ex.: stable,main\n"
+		"                                  it can be set multiple times\n"
 		" -i, --image <filename>         : Software to be installed\n"
 		" -l, --loglevel <level>         : logging level\n"
 		" -L, --syslog                   : enable syslog logger\n"
@@ -661,7 +667,7 @@  int main(int argc, char **argv)
 #endif
 	memset(main_options, 0, sizeof(main_options));
 	memset(image_url, 0, sizeof(image_url));
-	strcpy(main_options, "vhni:e:l:Lcf:p:P:o:N:R:M");
+	strcpy(main_options, "vhni:e:q:l:Lcf:p:P:o:N:R:M");
 #ifdef CONFIG_MTD
 	strcat(main_options, "b:");
 #endif
@@ -858,6 +864,9 @@  int main(int argc, char **argv)
 			if (opt_to_hwrev(optarg, &swcfg.hw) < 0)
 				exit(EXIT_FAILURE);
 			break;
+		case 'q':
+			dict_insert_value(&swcfg.accepted_set, "accepted", optarg);
+			break;
 #ifdef CONFIG_SURICATTA
 		case 'u':
 			if (asprintf(&suricattaoptions,"%s %s", argv[0], optarg) ==
diff --git a/doc/source/swupdate.rst b/doc/source/swupdate.rst
index 306f2ac..fadc62b 100644
--- a/doc/source/swupdate.rst
+++ b/doc/source/swupdate.rst
@@ -442,6 +442,13 @@  Command line parameters
 |             |          | -e "stable, copy1"  ==> install on copy1   |
 |             |          | -e "stable, copy2"  ==> install on copy2   |
 +-------------+----------+--------------------------------------------+
+| --excluded  | string   | ``sel`` is in the format <software>,<mode>.|
+|  <sel>      |          | It sets a blacklist of selections that     |
+|             |          | cannot be used for an update.              |
+|             |          | Selections can be activated not only with  |
+|             |          | -e, but also via IPC.                      |
+|             |          | Multiple --excluded are allowed            |
++-------------+----------+--------------------------------------------+
 | -h          |    -     | Run usage with help.                       |
 +-------------+----------+--------------------------------------------+
 | -k <file>   | string   | Available if CONFIG_SIGNED is set.         |
diff --git a/include/swupdate.h b/include/swupdate.h
index 4ae0b43..2b554b6 100644
--- a/include/swupdate.h
+++ b/include/swupdate.h
@@ -158,6 +158,7 @@  struct swupdate_cfg {
 	struct imglist scripts;
 	struct imglist bootscripts;
 	struct dict bootloader;
+	struct dict accepted_set;
 	struct proclist extprocs;
 	void *dgst;	/* Structure for signed images */
 	struct swupdate_global_cfg globals;