@@ -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");
@@ -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) ==
@@ -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. |
@@ -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;
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(-)