add appinfo initialization
[platform/framework/native/loader.git] / osp-service-app-loader / serviceapp_loader.c
1 //
2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /**
19 *   @file       serviceapp_loader.c
20 *   @brief              This is the implementation for the osp-service-app-loader.
21 */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <dlfcn.h>
27 #include <unistd.h>
28 #include <limits.h>
29 #include <fcntl.h>
30 #include <linux/capability.h>
31
32 #include <dlog.h>
33 #include <appinfo.h>
34
35 #undef LOG_TAG
36 #define LOG_TAG "LOADER"
37
38 #define MAX_PACKAGEID 10
39 #define MAX_APP_EXECUTABLE_NAME 230
40 #define MAX_APPID (MAX_PACKAGEID + MAX_APP_EXECUTABLE_NAME + 1)
41
42
43 #if 0
44 static void
45 print_args(int argc, char* argv[])
46 {
47         const char* p = NULL;
48         int i = 0;
49         for (; i < argc; i++)
50         {
51                 p = argv[i];
52                 LOGI("%dth arg : [%s]", i, p);
53         }
54 }
55 #endif
56
57 static void
58 adjust_privilege(const char* appid)
59 {
60         void* handle = dlopen("libprivilege-control.so.0", RTLD_LAZY | RTLD_LOCAL);
61         if (!handle)
62         {
63                 fprintf(stderr, "Cannot open libprivilege-control.so.0\n");
64                 return;
65         }
66
67         char* msg = 0;
68         dlerror();
69
70         int (*ppriv_func)(const char*) = NULL;
71
72         ppriv_func = (int (*)(const char*))dlsym(handle, "set_privilege");
73         msg = dlerror();
74         if (msg != NULL)
75         {
76                 fprintf(stderr, "Dlsym error: %s\n", msg);
77
78                 dlclose(handle);
79                 return;
80         }
81
82         int ret = (*ppriv_func)(appid);
83         if (ret < 0)
84         {
85                 fprintf(stderr, "set_privilege() returned %d\n", ret);
86         }
87
88         dlclose(handle);
89 }
90
91 extern int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
92
93 static int
94 adjust_capability(void)
95 {
96         cap_user_header_t   head = 0;
97         cap_user_data_t data = 0;
98
99         head = (cap_user_header_t) malloc(sizeof(*head));
100         if (head == NULL)
101         {
102                 fprintf(stderr, "Memory allocation failure.\n");
103                 return -1;
104         }
105
106         head->version = _LINUX_CAPABILITY_VERSION;
107         head->pid = getpid();
108
109         data = (cap_user_data_t) calloc(sizeof(*data), _LINUX_CAPABILITY_U32S);
110         if (data == NULL)
111         {
112                 fprintf(stderr, "Memory allocation failure.\n");
113
114                 free(head);
115                 return -1;
116         }
117
118         data[CAP_TO_INDEX(CAP_NET_RAW)].effective |= CAP_TO_MASK(CAP_NET_RAW);
119         data[CAP_TO_INDEX(CAP_NET_RAW)].permitted |= CAP_TO_MASK(CAP_NET_RAW);
120
121         if (capset(head, data) < 0)
122         {
123                 fprintf(stderr, "Capability setting error\n");
124
125                 free(data);
126                 free(head);
127                 return -1;
128         }
129
130         free(data);
131         free(head);
132
133         return 0;
134 }
135 static int
136 osp_do_pre_exe(const char* bin_path)
137 {
138         int ret = 0;
139         void* handle = NULL;
140         char* errormsg = 0;
141         int (*do_pre_exec_fn)(const char*, const char*) = NULL;
142
143         handle = dlopen("libosp-env-config.so", RTLD_LAZY | RTLD_LOCAL);
144         if (!handle)
145         {
146                 LOGE("Failed to dlopen osp-env-config.so (%s)", dlerror());
147                 return -1;
148         }
149         LOGI("Tizen::App > dlopen() ok");
150
151         do_pre_exec_fn = (int (*)(const char*, const char*)) dlsym(handle, "do_pre_exec");
152         errormsg = dlerror();
153         if (errormsg != NULL)
154         {
155                 LOGE("Failed to dlsym() (%s)", errormsg);
156                 dlclose(handle);
157                 return -1;
158         }
159         LOGI("dlsym() ok");
160
161         ret = do_pre_exec_fn(NULL, bin_path);
162         if (ret < 0)
163         {
164                 LOGE("Failed to do_pre_exe() (%d)", ret);
165         }
166         LOGI("do_pre_exec() ok");
167
168         dlclose(handle);
169
170         return 0;
171 }
172
173 static int
174 get_packageid_executable_name_from_path(const char path[], char appid[], char executable_name[])
175 {
176         // path is "/opt/apps/[appid]/bin/[executable_name]"
177
178         const char* p = strrchr(path, '/');
179         if (p == NULL)
180         {
181                 LOGI("Improper path %s", path);
182                 return -1;
183         }
184
185         const int path_len = strlen(path);
186         const int exec_len = strlen(p);
187         if (exec_len <= 0 || exec_len > PATH_MAX || path_len <= 0 || path_len > PATH_MAX)
188         {
189                 LOGI("Improper path %s", path);
190                 return -1;
191         }
192
193         strncpy(executable_name, p + 1, exec_len);
194
195 #ifdef _SECURE_LOG
196         LOGI("Exec is %s", executable_name);
197 #endif
198
199         if (path_len < /* '/' */ 1 + 10 + strlen("/bin/") + exec_len)
200         {
201                 LOGI("Improper path %s", path);
202                 return -1;
203         }
204
205         strncpy(appid, p - strlen("bin/") - 10, 10);
206
207         LOGI("appId is %s", appid);
208
209         return 1;
210 }
211
212
213 int
214 main(int argc, char* argv[])
215 {
216         void* real_handle = NULL;
217         char* errormsg = 0;
218         char packageid[MAX_PACKAGEID];
219         char executable_name[MAX_APP_EXECUTABLE_NAME];
220         char appid[MAX_APPID];
221
222         void (*pAppInfoInit)(const char*, const char*, int, char* [], int) = NULL;
223         int (*pRealMain)(int, char* []) = NULL;
224
225         memset(packageid, 0, sizeof(packageid));
226         memset(executable_name, 0, sizeof(executable_name));
227         memset(appid, 0, sizeof(appid));
228
229         LOGI("Initializing : argc %d, argv 0x%x.", argc, argv);
230         //print_args(argc, argv);
231
232         // convert package path to package name
233         get_packageid_executable_name_from_path(argv[0], packageid, executable_name);
234         snprintf(appid, MAX_APPID, "%s.%s", packageid, executable_name);
235
236 #ifdef _SECURE_LOG
237         LOGI("app is %s", appid);
238 #endif
239
240         if (getuid() == 0)
241         {
242                 // self caging
243                 osp_do_pre_exe(argv[0]);
244
245                 // adjust privilege
246                 adjust_privilege(appid);
247         }
248
249
250         adjust_capability();
251
252         // initialize appid
253         appinfo_init(appid, 0);
254         appinfo_set_argv(argc, argv);
255
256         // actual loading
257         char buffer[1024];
258
259         snprintf(buffer, 1024, "%s.exe", argv[0]);
260
261
262         real_handle = dlopen(buffer, RTLD_LAZY);
263         if (!real_handle)
264         {
265                 LOGE("Failed to open %s : %s.", buffer, dlerror());
266                 return -1;
267         }
268
269         pAppInfoInit = (void (*)(const char*, const char*, int, char*[], int)) dlsym(real_handle, "InitAppInfo");
270         errormsg = dlerror();
271         if (errormsg != NULL)
272         {
273                 LOGE("Failed to find InitAppInfo() : %s.", errormsg);
274                 dlclose(real_handle);
275                 fprintf(stderr, "executable does not have proper osp library dependency.\n");
276                 return -1;
277         }
278
279         pRealMain = (int (*)(int, char*[])) dlsym(real_handle, "OspMain");
280         errormsg = dlerror();
281         if (errormsg != NULL)
282         {
283                 LOGE("Failed to find OspMain() : %s.", errormsg);
284                 dlclose(real_handle);
285                 return -1;
286         }
287
288         // actual initialization
289         (*pAppInfoInit)(packageid, executable_name, argc, argv, -1);
290         (*pRealMain)(argc, argv);
291
292         LOGI("Osp application terminates.");
293
294         //dlclose(real_handle);
295         LOGI("Osp cleanup finished for %s.", argv[0]);
296
297         return 0;
298 }
299