jail: handle containers seperately
[oweals/procd.git] / sysupgrade.c
1 /*
2  * Copyright (C) 2013 Felix Fietkau <nbd@openwrt.org>
3  * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
4  * Copyright (C) 2017 Matthias Schiffer <mschiffer@universe-factory.net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License version 2.1
8  * as published by the Free Software Foundation
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  */
15
16
17 #define _GNU_SOURCE
18 #include "watchdog.h"
19 #include "sysupgrade.h"
20
21 #include <ctype.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25
26 #include <libubox/blobmsg.h>
27
28 void sysupgrade_exec_upgraded(const char *prefix, char *path,
29                               const char *backup, char *command,
30                               struct blob_attr *options)
31 {
32         char *wdt_fd = watchdog_fd();
33         char *argv[] = { "/sbin/upgraded", NULL, NULL, NULL};
34         struct blob_attr *option;
35         int rem;
36         int ret;
37
38         ret = chroot(prefix);
39         if (ret < 0) {
40                 fprintf(stderr, "Failed to chroot for upgraded exec.\n");
41                 return;
42         }
43
44         argv[1] = path;
45         argv[2] = command;
46
47         if (wdt_fd) {
48                 watchdog_set_cloexec(false);
49                 setenv("WDTFD", wdt_fd, 1);
50         }
51
52         if (backup)
53                 setenv("UPGRADE_BACKUP", backup, 1);
54
55         blobmsg_for_each_attr(option, options, rem) {
56                 const char *prefix = "UPGRADE_OPT_";
57                 char value[11];
58                 char *name;
59                 char *c;
60                 int tmp;
61
62                 if (asprintf(&name, "%s%s", prefix, blobmsg_name(option)) <= 0)
63                         continue;
64                 for (c = name + strlen(prefix); *c; c++) {
65                         if (isalnum(*c) || *c == '_') {
66                                 *c = toupper(*c);
67                         } else {
68                                 c = NULL;
69                                 break;
70                         }
71                 }
72
73                 if (!c) {
74                         fprintf(stderr, "Option \"%s\" contains invalid characters\n",
75                                 blobmsg_name(option));
76                         free(name);
77                         continue;
78                 }
79
80                 switch (blobmsg_type(option)) {
81                 case BLOBMSG_TYPE_INT32:
82                         tmp = blobmsg_get_u32(option);
83                         break;
84                 case BLOBMSG_TYPE_INT16:
85                         tmp = blobmsg_get_u16(option);
86                         break;
87                 case BLOBMSG_TYPE_INT8:
88                         tmp = blobmsg_get_u8(option);
89                         break;
90                 default:
91                         fprintf(stderr, "Option \"%s\" has unsupported type: %d\n",
92                                 blobmsg_name(option), blobmsg_type(option));
93                         free(name);
94                         continue;
95                 }
96                 snprintf(value, sizeof(value), "%u", tmp);
97
98                 setenv(name, value, 1);
99
100                 free(name);
101         }
102
103         execvp(argv[0], argv);
104
105         /* Cleanup on failure */
106         fprintf(stderr, "Failed to exec upgraded.\n");
107         unsetenv("WDTFD");
108         watchdog_set_cloexec(true);
109         ret = chroot(".");
110         if (ret < 0) {
111                 fprintf(stderr, "Failed to reset chroot, exiting.\n");
112                 exit(EXIT_FAILURE);
113         }
114 }