diff options
author | William Wilgus <wilgus.william@gmail.com> | 2021-10-18 01:23:07 -0400 |
---|---|---|
committer | William Wilgus <me.theuser@yahoo.com> | 2021-10-18 23:30:27 -0400 |
commit | e1553d860dc42a819fe71913d5a68a77fbf64a6e (patch) | |
tree | c29ceec89472e2c249ae3e04ba837de573b6559d /apps | |
parent | 0f68866ae5b02e3e154f31b6da12b090380db4b0 (diff) | |
download | rockbox-e1553d860dc42a819fe71913d5a68a77fbf64a6e.tar.gz rockbox-e1553d860dc42a819fe71913d5a68a77fbf64a6e.zip |
Open_Plugin add checksum on struct offsets
Adding a checksum over the struct offset will allow checking
for compatibility across machines rather than using packed structs
to ensure compability
For any file created by the user from the device this isn't really a concern
But for files between machines, across installs (sim v device),
possibly even across compilers this at least will alert the user
rather than returning junk data
Change-Id: Id0531bbaa7013dce24dece270849f0a10ac99c20
Diffstat (limited to 'apps')
-rw-r--r-- | apps/open_plugin.c | 43 | ||||
-rw-r--r-- | apps/open_plugin.h | 18 | ||||
-rw-r--r-- | apps/plugins/open_plugins.c | 36 |
3 files changed, 73 insertions, 24 deletions
diff --git a/apps/open_plugin.c b/apps/open_plugin.c index 32b5195334..fe18071454 100644 --- a/apps/open_plugin.c +++ b/apps/open_plugin.c | |||
@@ -38,6 +38,8 @@ | |||
38 | 38 | ||
39 | struct open_plugin_entry_t open_plugin_entry = {0}; | 39 | struct open_plugin_entry_t open_plugin_entry = {0}; |
40 | 40 | ||
41 | static const uint32_t open_plugin_csum = OPEN_PLUGIN_CHECKSUM; | ||
42 | |||
41 | static const int op_entry_sz = sizeof(struct open_plugin_entry_t); | 43 | static const int op_entry_sz = sizeof(struct open_plugin_entry_t); |
42 | 44 | ||
43 | static int open_plugin_hash_get_entry(uint32_t hash, | 45 | static int open_plugin_hash_get_entry(uint32_t hash, |
@@ -60,6 +62,13 @@ static inline void op_clear_entry(struct open_plugin_entry_t *entry) | |||
60 | entry->lang_id = -1; | 62 | entry->lang_id = -1; |
61 | } | 63 | } |
62 | 64 | ||
65 | static int op_entry_checksum(struct open_plugin_entry_t *entry) | ||
66 | { | ||
67 | if (!entry || entry->checksum != open_plugin_csum) | ||
68 | return 0; | ||
69 | return 1; | ||
70 | } | ||
71 | |||
63 | static int op_find_entry(int fd, struct open_plugin_entry_t *entry, | 72 | static int op_find_entry(int fd, struct open_plugin_entry_t *entry, |
64 | uint32_t hash, int32_t lang_id) | 73 | uint32_t hash, int32_t lang_id) |
65 | { | 74 | { |
@@ -75,6 +84,13 @@ static int op_find_entry(int fd, struct open_plugin_entry_t *entry, | |||
75 | (entry->hash == hash && hash != 0) || | 84 | (entry->hash == hash && hash != 0) || |
76 | (lang_id == OPEN_PLUGIN_LANG_IGNOREALL))/* return first entry found */ | 85 | (lang_id == OPEN_PLUGIN_LANG_IGNOREALL))/* return first entry found */ |
77 | { | 86 | { |
87 | /* sanity check */ | ||
88 | if (op_entry_checksum(entry) <= 0) | ||
89 | { | ||
90 | splashf(HZ * 2, "OpenPlugin Invalid entry"); | ||
91 | ret = OPEN_PLUGIN_NOT_FOUND; | ||
92 | break; | ||
93 | } | ||
78 | /* NULL terminate fields NOTE -- all are actually +1 larger */ | 94 | /* NULL terminate fields NOTE -- all are actually +1 larger */ |
79 | entry->name[OPEN_PLUGIN_NAMESZ] = '\0'; | 95 | entry->name[OPEN_PLUGIN_NAMESZ] = '\0'; |
80 | /*entry->key[OPEN_PLUGIN_BUFSZ] = '\0';*/ | 96 | /*entry->key[OPEN_PLUGIN_BUFSZ] = '\0';*/ |
@@ -111,24 +127,27 @@ static int op_update_dat(struct open_plugin_entry_t *entry, bool clear) | |||
111 | logf("OP update hash: %x lang_id: %d", hash, lang_id); | 127 | logf("OP update hash: %x lang_id: %d", hash, lang_id); |
112 | logf("OP update name: %s clear: %d", entry->name, (int) clear); | 128 | logf("OP update name: %s clear: %d", entry->name, (int) clear); |
113 | logf("OP update %s %s %s", entry->name, entry->path, entry->param); | 129 | logf("OP update %s %s %s", entry->name, entry->path, entry->param); |
130 | |||
114 | #if (CONFIG_STORAGE & STORAGE_ATA) /* Harddrive -- update existing */ | 131 | #if (CONFIG_STORAGE & STORAGE_ATA) /* Harddrive -- update existing */ |
115 | logf("OP update *Updating entries* %s", OPEN_PLUGIN_DAT); | 132 | logf("OP update *Updating entries* %s", OPEN_PLUGIN_DAT); |
116 | fd = open(OPEN_PLUGIN_DAT, O_RDWR | O_CREAT, 0666); | 133 | fd = open(OPEN_PLUGIN_DAT, O_RDWR | O_CREAT, 0666); |
117 | 134 | ||
118 | if (fd < 0) | 135 | if (fd < 0) |
119 | return OPEN_PLUGIN_NOT_FOUND; | 136 | return OPEN_PLUGIN_NOT_FOUND; |
120 | /* Only read the hash and lang id */ | 137 | /* Only read the hash lang id and checksum */ |
121 | uint32_t hash_langid[2] = {0}; | 138 | uint32_t hash_langid_csum[3] = {0}; |
122 | while (read(fd, &hash_langid, sizeof(hash_langid)) == sizeof(hash_langid)) | 139 | const off_t hlc_sz = sizeof(hash_langid_csum); |
140 | while (read(fd, &hash_langid_csum, hlc_sz) == hlc_sz) | ||
123 | { | 141 | { |
124 | if (hash_langid[0] == hash || (int32_t)hash_langid[1] == lang_id) | 142 | if ((hash_langid_csum[0] == hash || (int32_t)hash_langid_csum[1] == lang_id) && |
143 | hash_langid_csum[2] == open_plugin_csum) | ||
125 | { | 144 | { |
126 | logf("OP update *Entry Exists* hash: %x langid: %d", | 145 | logf("OP update *Entry Exists* hash: %x langid: %d", |
127 | hash_langid[0], (int32_t)hash_langid[1]); | 146 | hash_langid_csum[0], (int32_t)hash_langid[1]); |
128 | lseek(fd, 0-sizeof(hash_langid), SEEK_CUR);/* back to the start of record */ | 147 | lseek(fd, 0-hlc_sz, SEEK_CUR);/* back to the start of record */ |
129 | break; | 148 | break; |
130 | } | 149 | } |
131 | lseek(fd, op_entry_sz - sizeof(hash_langid), SEEK_CUR); /* finish record */ | 150 | lseek(fd, op_entry_sz - hlc_sz, SEEK_CUR); /* finish record */ |
132 | } | 151 | } |
133 | write(fd, entry, op_entry_sz); | 152 | write(fd, entry, op_entry_sz); |
134 | close(fd); | 153 | close(fd); |
@@ -146,7 +165,8 @@ static int op_update_dat(struct open_plugin_entry_t *entry, bool clear) | |||
146 | /* copy non-duplicate entries back from original */ | 165 | /* copy non-duplicate entries back from original */ |
147 | while (read(fd1, entry, op_entry_sz) == op_entry_sz) | 166 | while (read(fd1, entry, op_entry_sz) == op_entry_sz) |
148 | { | 167 | { |
149 | if (entry->hash != hash && entry->lang_id != lang_id) | 168 | if (entry->hash != hash && entry->lang_id != lang_id && |
169 | op_entry_checksum(entry) > 0) | ||
150 | { | 170 | { |
151 | write(fd, entry, op_entry_sz); | 171 | write(fd, entry, op_entry_sz); |
152 | } | 172 | } |
@@ -202,8 +222,9 @@ uint32_t open_plugin_add_path(const char *key, const char *plugin, const char *p | |||
202 | 222 | ||
203 | if (plugin) | 223 | if (plugin) |
204 | { | 224 | { |
205 | open_plugin_entry.hash = hash; | 225 | open_plugin_entry.hash = hash; |
206 | open_plugin_entry.lang_id = lang_id; | 226 | open_plugin_entry.lang_id = lang_id; |
227 | open_plugin_entry.checksum = open_plugin_csum; | ||
207 | /* name */ | 228 | /* name */ |
208 | if (path_basename(plugin, (const char **)&pos) == 0) | 229 | if (path_basename(plugin, (const char **)&pos) == 0) |
209 | pos = "\0"; | 230 | pos = "\0"; |
@@ -242,7 +263,7 @@ retnhash: | |||
242 | 263 | ||
243 | void open_plugin_browse(const char *key) | 264 | void open_plugin_browse(const char *key) |
244 | { | 265 | { |
245 | logf("OP Browse"); | 266 | logf("OP browse"); |
246 | struct browse_context browse; | 267 | struct browse_context browse; |
247 | char tmp_buf[OPEN_PLUGIN_BUFSZ+1]; | 268 | char tmp_buf[OPEN_PLUGIN_BUFSZ+1]; |
248 | open_plugin_get_entry(key, &open_plugin_entry); | 269 | open_plugin_get_entry(key, &open_plugin_entry); |
diff --git a/apps/open_plugin.h b/apps/open_plugin.h index e1d49bf329..adfb9a75bc 100644 --- a/apps/open_plugin.h +++ b/apps/open_plugin.h | |||
@@ -41,19 +41,31 @@ enum { | |||
41 | OPEN_PLUGIN_LANG_IGNORE = (-2), | 41 | OPEN_PLUGIN_LANG_IGNORE = (-2), |
42 | OPEN_PLUGIN_LANG_IGNOREALL = (-3), | 42 | OPEN_PLUGIN_LANG_IGNOREALL = (-3), |
43 | OPEN_PLUGIN_NOT_FOUND = (-1), | 43 | OPEN_PLUGIN_NOT_FOUND = (-1), |
44 | OPEN_PLUGIN_NEEDS_FLUSHED = (-2) | 44 | OPEN_PLUGIN_NEEDS_FLUSHED = (-2), |
45 | }; | 45 | }; |
46 | 46 | ||
47 | struct open_plugin_entry_t | 47 | struct open_plugin_entry_t |
48 | { | 48 | { |
49 | /* hash and lang_id need to be the first items */ | 49 | /* hash lang_id checksum need to be the first items */ |
50 | uint32_t hash; | 50 | uint32_t hash; |
51 | int32_t lang_id; | 51 | int32_t lang_id; |
52 | uint32_t checksum; | ||
52 | char name[OPEN_PLUGIN_NAMESZ+1]; | 53 | char name[OPEN_PLUGIN_NAMESZ+1]; |
53 | /*char key[OPEN_PLUGIN_BUFSZ+1];*/ | 54 | /*char key[OPEN_PLUGIN_BUFSZ+1];*/ |
54 | char path[OPEN_PLUGIN_BUFSZ+1]; | 55 | char path[OPEN_PLUGIN_BUFSZ+1]; |
55 | char param[OPEN_PLUGIN_BUFSZ+1]; | 56 | char param[OPEN_PLUGIN_BUFSZ+1]; |
56 | }__attribute__((packed)); | 57 | }; |
58 | |||
59 | #define OPEN_PLUGIN_CHECKSUM (uint32_t) \ | ||
60 | ( \ | ||
61 | (sizeof(struct open_plugin_entry_t) << 16) + \ | ||
62 | offsetof(struct open_plugin_entry_t, hash) + \ | ||
63 | offsetof(struct open_plugin_entry_t, lang_id) + \ | ||
64 | offsetof(struct open_plugin_entry_t, checksum) + \ | ||
65 | offsetof(struct open_plugin_entry_t, name) + \ | ||
66 | /*offsetof(struct open_plugin_entry_t, key)+*/ \ | ||
67 | offsetof(struct open_plugin_entry_t, path) + \ | ||
68 | offsetof(struct open_plugin_entry_t, param)) | ||
57 | 69 | ||
58 | inline static void open_plugin_get_hash(const char *key, uint32_t *hash) | 70 | inline static void open_plugin_get_hash(const char *key, uint32_t *hash) |
59 | { | 71 | { |
diff --git a/apps/plugins/open_plugins.c b/apps/plugins/open_plugins.c index b8d11d2ae5..3a0c34d8d6 100644 --- a/apps/plugins/open_plugins.c +++ b/apps/plugins/open_plugins.c | |||
@@ -49,7 +49,8 @@ | |||
49 | static int fd_dat; | 49 | static int fd_dat; |
50 | static struct gui_synclist lists; | 50 | static struct gui_synclist lists; |
51 | struct open_plugin_entry_t op_entry; | 51 | struct open_plugin_entry_t op_entry; |
52 | const off_t op_entry_sz = sizeof(struct open_plugin_entry_t); | 52 | static const uint32_t open_plugin_csum = OPEN_PLUGIN_CHECKSUM; |
53 | static const off_t op_entry_sz = sizeof(struct open_plugin_entry_t); | ||
53 | 54 | ||
54 | /* we only need the names for the first menu so don't bother reading paths yet */ | 55 | /* we only need the names for the first menu so don't bother reading paths yet */ |
55 | const off_t op_name_sz = OPEN_PLUGIN_NAMESZ + (op_entry.name - (char*)&op_entry); | 56 | const off_t op_name_sz = OPEN_PLUGIN_NAMESZ + (op_entry.name - (char*)&op_entry); |
@@ -101,6 +102,15 @@ static bool op_entry_read_name(int fd, int selected_item) | |||
101 | return op_entry_read(fd, selected_item, op_name_sz); | 102 | return op_entry_read(fd, selected_item, op_name_sz); |
102 | } | 103 | } |
103 | 104 | ||
105 | static int op_entry_checksum(void) | ||
106 | { | ||
107 | if (op_entry.checksum != open_plugin_csum) | ||
108 | { | ||
109 | return 0; | ||
110 | } | ||
111 | return 1; | ||
112 | } | ||
113 | |||
104 | static int op_entry_read_opx(const char *path) | 114 | static int op_entry_read_opx(const char *path) |
105 | { | 115 | { |
106 | int ret = -1; | 116 | int ret = -1; |
@@ -112,13 +122,14 @@ static int op_entry_read_opx(const char *path) | |||
112 | if(len > OP_LEN && rb->strcasecmp(&((path)[len-OP_LEN]), "." OP_EXT) == 0) | 122 | if(len > OP_LEN && rb->strcasecmp(&((path)[len-OP_LEN]), "." OP_EXT) == 0) |
113 | { | 123 | { |
114 | fd_opx = rb->open(path, O_RDONLY); | 124 | fd_opx = rb->open(path, O_RDONLY); |
115 | if (fd_opx) | 125 | if (fd_opx >= 0) |
116 | { | 126 | { |
117 | filesize = rb->filesize(fd_opx); | 127 | filesize = rb->filesize(fd_opx); |
118 | ret = filesize; | 128 | ret = filesize; |
119 | if (filesize == op_entry_sz && !op_entry_read(fd_opx, 0, op_entry_sz)) | 129 | if (filesize == op_entry_sz && !op_entry_read(fd_opx, 0, op_entry_sz)) |
120 | ret = 0; | 130 | ret = 0; |
121 | 131 | else if (op_entry_checksum() <= 0) | |
132 | ret = 0; | ||
122 | rb->close(fd_opx); | 133 | rb->close(fd_opx); |
123 | } | 134 | } |
124 | } | 135 | } |
@@ -131,7 +142,7 @@ static void op_entry_export(int selection) | |||
131 | int fd = -1; | 142 | int fd = -1; |
132 | char filename [MAX_PATH + 1]; | 143 | char filename [MAX_PATH + 1]; |
133 | 144 | ||
134 | if (!op_entry_read(fd_dat, selection, op_entry_sz)) | 145 | if (!op_entry_read(fd_dat, selection, op_entry_sz) || op_entry_checksum() <= 0) |
135 | goto failure; | 146 | goto failure; |
136 | 147 | ||
137 | rb->snprintf(filename, MAX_PATH, "%s/%s", PLUGIN_APPS_DIR, op_entry.name); | 148 | rb->snprintf(filename, MAX_PATH, "%s/%s", PLUGIN_APPS_DIR, op_entry.name); |
@@ -161,6 +172,11 @@ failure: | |||
161 | 172 | ||
162 | } | 173 | } |
163 | 174 | ||
175 | static void op_entry_set_checksum(void) | ||
176 | { | ||
177 | op_entry.checksum = open_plugin_csum; | ||
178 | } | ||
179 | |||
164 | static void op_entry_set_name(void) | 180 | static void op_entry_set_name(void) |
165 | { | 181 | { |
166 | char tmp_buf[OPEN_PLUGIN_NAMESZ+1]; | 182 | char tmp_buf[OPEN_PLUGIN_NAMESZ+1]; |
@@ -277,12 +293,12 @@ static int op_entry_transfer(int fd, int fd_tmp, | |||
277 | void *data) | 293 | void *data) |
278 | { | 294 | { |
279 | int entries = -1; | 295 | int entries = -1; |
280 | if (fd_tmp && fd && rb->lseek(fd, 0, SEEK_SET) == 0) | 296 | if (fd_tmp >= 0 && fd >= 0 && rb->lseek(fd, 0, SEEK_SET) == 0) |
281 | { | 297 | { |
282 | entries = 0; | 298 | entries = 0; |
283 | while (rb->read(fd, &op_entry, op_entry_sz) == op_entry_sz) | 299 | while (rb->read(fd, &op_entry, op_entry_sz) == op_entry_sz) |
284 | { | 300 | { |
285 | if (compfn && compfn(&op_entry, entries, data) > 0) | 301 | if (compfn && compfn(&op_entry, entries, data) > 0 && op_entry_checksum() > 0) |
286 | { | 302 | { |
287 | rb->write(fd_tmp, &op_entry, op_entry_sz); | 303 | rb->write(fd_tmp, &op_entry, op_entry_sz); |
288 | entries++; | 304 | entries++; |
@@ -359,7 +375,7 @@ static uint32_t op_entry_add_path(const char *key, const char *plugin, const cha | |||
359 | op_entry.hash = newhash; | 375 | op_entry.hash = newhash; |
360 | } | 376 | } |
361 | } | 377 | } |
362 | 378 | op_entry_set_checksum(); | |
363 | rb->write(fd_tmp, &op_entry, op_entry_sz); /* add new entry first */ | 379 | rb->write(fd_tmp, &op_entry, op_entry_sz); /* add new entry first */ |
364 | } | 380 | } |
365 | else if(op_entry_read_opx(plugin) == op_entry_sz) | 381 | else if(op_entry_read_opx(plugin) == op_entry_sz) |
@@ -374,13 +390,13 @@ static uint32_t op_entry_add_path(const char *key, const char *plugin, const cha | |||
374 | open_plugin_get_hash(op_entry.path, &hash); | 390 | open_plugin_get_hash(op_entry.path, &hash); |
375 | 391 | ||
376 | op_entry.hash = hash; | 392 | op_entry.hash = hash; |
377 | 393 | op_entry_set_checksum(); | |
378 | rb->write(fd_tmp, &op_entry, op_entry_sz); /* add new entry first */ | 394 | rb->write(fd_tmp, &op_entry, op_entry_sz); /* add new entry first */ |
379 | } | 395 | } |
380 | else | 396 | else |
381 | { | 397 | { |
382 | if (op_entry.lang_id != LANG_SHORTCUTS) | 398 | if (op_entry.lang_id != LANG_SHORTCUTS) |
383 | rb->splashf(HZ / 2, rb->str(LANG_OPEN_PLUGIN_NOT_A_PLUGIN), pos); | 399 | rb->splashf(HZ * 2, rb->str(LANG_OPEN_PLUGIN_NOT_A_PLUGIN), pos); |
384 | return 0; | 400 | return 0; |
385 | } | 401 | } |
386 | } | 402 | } |
@@ -845,7 +861,7 @@ reopen_datfile: | |||
845 | synclist_set(MENU_ID_MAIN, selection, items, 1); | 861 | synclist_set(MENU_ID_MAIN, selection, items, 1); |
846 | rb->gui_synclist_draw(&lists); | 862 | rb->gui_synclist_draw(&lists); |
847 | 863 | ||
848 | while (!exit) | 864 | while (!exit && fd_dat >= 0) |
849 | { | 865 | { |
850 | action = rb->get_action(CONTEXT_LIST,TIMEOUT_BLOCK); | 866 | action = rb->get_action(CONTEXT_LIST,TIMEOUT_BLOCK); |
851 | 867 | ||