remove privilege-control build dependency
[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 <aul.h>
33 #include <dlog.h>
34
35 #undef LOG_TAG
36 #define LOG_TAG "LOADER"
37
38 #define MAX_APPID 20
39 #define MAX_APP_EXECUTABLE_NAME 230
40
41 #define MIN(a,b)  ((a) < (b) ? (a) : (b))
42
43
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
56 static void
57 adjust_privilege()
58 {
59         void* handle = dlopen("libprivilege-control.so.0", RTLD_LAZY | RTLD_LOCAL);
60         if (!handle)
61         {
62                 fprintf(stderr, "Cannot open libprivilege-control.so.0\n");
63                 return;
64         }
65
66         char* msg = 0;
67         dlerror();
68
69         int (*ppriv_func)(const char*) = NULL;
70
71         ppriv_func = (int (*)(const char*))dlsym(handle, "set_privilege");
72         msg = dlerror();
73         if (msg != NULL)
74         {
75                 fprintf(stderr, "Dlsym error: %s\n", msg);
76
77                 dlclose(handle);
78                 return;
79         }
80
81         char pkgname[255] = {0, };
82         int ret = aul_app_get_appid_bypid(getpid(), pkgname, 255);
83         if (ret != AUL_R_OK)
84         {
85                 fprintf(stderr, "Cannot acquire app from pid with 0x%x.\n", ret);
86
87                 dlclose(handle);
88                 return;
89         }
90
91         ret = (*ppriv_func)(pkgname);
92         if (ret < 0)
93         {
94                 fprintf(stderr, "set_privilege() returned %d\n", ret);
95         }
96
97         dlclose(handle);
98 }
99
100 extern int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
101
102 static int
103 adjust_capability(void)
104 {
105         cap_user_header_t   head = 0;
106         cap_user_data_t data = 0;
107
108         head = (cap_user_header_t) malloc(sizeof(*head));
109         if (head == NULL)
110         {
111                 fprintf(stderr, "Memory allocation failure.\n");
112                 return -1;
113         }
114
115         head->version = _LINUX_CAPABILITY_VERSION;
116         head->pid = getpid();
117
118         data = (cap_user_data_t) calloc(sizeof(*data), _LINUX_CAPABILITY_U32S);
119         if (data == NULL)
120         {
121                 fprintf(stderr, "Memory allocation failure.\n");
122
123                 free(head);
124                 return -1;
125         }
126
127         data[CAP_TO_INDEX(CAP_NET_RAW)].effective |= CAP_TO_MASK(CAP_NET_RAW);
128         data[CAP_TO_INDEX(CAP_NET_RAW)].permitted |= CAP_TO_MASK(CAP_NET_RAW);
129
130         if (capset(head, data) < 0)
131         {
132                 fprintf(stderr, "Capability setting error\n");
133
134                 free(data);
135                 free(head);
136                 return -1;
137         }
138
139         free(data);
140         free(head);
141
142         return 0;
143 }
144 static int
145 osp_do_pre_exe(const char* bin_path)
146 {
147         int ret = 0;
148         void* handle = NULL;
149         char* errormsg = 0;
150         int (*do_pre_exec_fn)(const char*, const char*) = NULL;
151
152         handle = dlopen("libosp-env-config.so", RTLD_LAZY | RTLD_LOCAL);
153         if (!handle)
154         {
155                 LOGE("Failed to dlopen osp-env-config.so (%s)", dlerror());
156                 return -1;
157         }
158         LOGI("Tizen::App > dlopen() ok");
159
160         do_pre_exec_fn = (int (*)(const char*, const char*)) dlsym(handle, "do_pre_exec");
161         errormsg = dlerror();
162         if (errormsg != NULL)
163         {
164                 LOGE("Failed to dlsym() (%s)", errormsg);
165                 dlclose(handle);
166                 return -1;
167         }
168         LOGI("dlsym() ok");
169
170         ret = do_pre_exec_fn(NULL, bin_path);
171         if (ret < 0)
172         {
173                 LOGE("Failed to do_pre_exe() (%d)", ret);
174         }
175         LOGI("do_pre_exec() ok");
176
177         dlclose(handle);
178
179         return 0;
180 }
181
182 static int
183 get_appid_executable_name_from_path(const char path[], char appid[], char executable_name[])
184 {
185         // path is "/opt/apps/[appid]/bin/[executable_name]"
186
187         const char* p = strrchr(path, '/');
188         if (p == NULL)
189         {
190                 LOGI("Improper path %s", path);
191                 return -1;
192         }
193
194         const int path_len = strlen(path);
195         const int exec_len = strlen(p);
196         if (exec_len <= 0 || exec_len > PATH_MAX || path_len <= 0 || path_len > PATH_MAX)
197         {
198                 LOGI("Improper path %s", path);
199                 return -1;
200         }
201
202         strncpy(executable_name, p + 1, exec_len);
203
204         LOGI("exeName is %s", executable_name);
205
206         if (path_len < /* '/' */ 1 + 10 + strlen("/bin/") + exec_len)
207         {
208                 LOGI("Improper path %s", path);
209                 return -1;
210         }
211
212         strncpy(appid, p - strlen("bin/") - 10, 10);
213
214         LOGI("appId is %s", appid);
215
216         return 1;
217 }
218
219 static int 
220 get_dir_fd_from_path(const char* path)
221 {
222         int i = 0;
223         int count = 0;
224         const int len = strlen(path);
225         char dname[PATH_MAX];
226         memset(dname, 0, PATH_MAX);
227
228         const char* p = path + len;
229         for (i = 0; i < len; i++, p--)
230         {   
231                 if (*p == '/')
232                 {   
233                         count++;
234
235                         if (count == 2)
236                         {   
237                                 goto OUT;
238                         }   
239                 }   
240         }   
241
242         LOGI("Wrong path format : %s.", path);
243
244         return -1; 
245
246 OUT:
247         strncpy(dname, path, p - path);
248
249         const int fd = open(dname, O_RDONLY | O_CLOEXEC | O_DIRECTORY);
250
251         LOGI("Directory path : %s, fd : %d.", dname, fd);
252         return fd; 
253 }
254
255
256 int
257 main(int argc, char* argv[])
258 {
259         void* real_handle = NULL;
260         char* errormsg = 0;
261         char appid[MAX_APPID];
262         char executable_name[MAX_APP_EXECUTABLE_NAME];
263
264         void (*pAppInfoInit)(const char*, const char*, int, char* [], int) = NULL;
265         int (*pRealMain)(int, char* []) = NULL;
266
267         memset(appid, 0, sizeof(appid));
268         memset(executable_name, 0, sizeof(executable_name));
269
270         LOGI("Initializing.");
271         LOGI("argc %d, argv 0x%x.", argc, argv);
272         print_args(argc, argv);
273
274         // convert package path to appId
275         get_appid_executable_name_from_path(argv[0], appid, executable_name);
276         LOGI("Osp appId %s.", appid);
277
278
279         if (getuid() == 0)
280         {
281                 // self caging
282                 osp_do_pre_exe(argv[0]);
283
284                 // adjust privilege
285                 adjust_privilege();
286         }
287
288
289         adjust_capability();
290
291         // actual loading
292         char buffer[1024];
293
294         snprintf(buffer, 1024, "%s.exe", argv[0]);
295
296
297         real_handle = dlopen(buffer, RTLD_LAZY);
298         if (!real_handle)
299         {
300                 LOGE("Failed to open %s : %s.", buffer, dlerror());
301                 return -1;
302         }
303
304         pAppInfoInit = (void (*)(const char*, const char*, int, char*[], int)) dlsym(real_handle, "InitAppInfo");
305         errormsg = dlerror();
306         if (errormsg != NULL)
307         {
308                 LOGE("Failed to find InitAppInfo() : %s.", errormsg);
309                 dlclose(real_handle);
310                 fprintf(stderr, "executable does not have proper osp library dependency.\n");
311                 return -1;
312         }
313
314         int fd = get_dir_fd_from_path(argv[0]);
315         if (fd == -1)
316         {
317                 LOGE("Failed to open path.");
318                 fprintf(stderr, "Failed to open %s.\n", argv[0]);
319                 dlclose(real_handle);
320                 return -1;
321         }
322
323         pRealMain = (int (*)(int, char*[])) dlsym(real_handle, "OspMain");
324         errormsg = dlerror();
325         if (errormsg != NULL)
326         {
327                 LOGE("Failed to find OspMain() : %s.", errormsg);
328                 dlclose(real_handle);
329                 return -1;
330         }
331
332         // actual initialization
333         (*pAppInfoInit)(appid, executable_name, argc, argv, fd);
334         (*pRealMain)(argc, argv);
335
336         LOGI("Osp application terminates.");
337
338         //dlclose(real_handle);
339         LOGI("Osp cleanup finished for %s.", argv[0]);
340
341         return 0;
342 }
343