Update deprecated libprivilege-control API functions.
[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 <privilege-control.h>
34 #include <appinfo.h>
35
36 #undef LOG_TAG
37 #define LOG_TAG "LOADER"
38
39 #define MAX_PACKAGEID 10
40 #define MAX_APP_EXECUTABLE_NAME 230
41 #define MAX_APPID (MAX_PACKAGEID + MAX_APP_EXECUTABLE_NAME + 1)
42
43
44 #if 0
45 static void
46 print_args(int argc, char* argv[])
47 {
48         const char* p = NULL;
49         int i = 0;
50         for (; i < argc; i++)
51         {
52                 p = argv[i];
53                 LOGI("%dth arg : [%s]", i, p);
54         }
55 }
56 #endif
57
58 static void
59 adjust_privilege(const char* appid)
60 {
61         perm_app_set_privilege(appid, NULL, NULL);
62 }
63
64 extern int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
65
66 static int
67 adjust_capability(void)
68 {
69         cap_user_header_t   head = 0;
70         cap_user_data_t data = 0;
71
72         head = (cap_user_header_t) malloc(sizeof(*head));
73         if (head == NULL)
74         {
75                 fprintf(stderr, "Memory allocation failure.\n");
76                 return -1;
77         }
78
79         head->version = _LINUX_CAPABILITY_VERSION;
80         head->pid = getpid();
81
82         data = (cap_user_data_t) calloc(sizeof(*data), _LINUX_CAPABILITY_U32S);
83         if (data == NULL)
84         {
85                 fprintf(stderr, "Memory allocation failure.\n");
86
87                 free(head);
88                 return -1;
89         }
90
91         data[CAP_TO_INDEX(CAP_NET_RAW)].effective |= CAP_TO_MASK(CAP_NET_RAW);
92         data[CAP_TO_INDEX(CAP_NET_RAW)].permitted |= CAP_TO_MASK(CAP_NET_RAW);
93
94         if (capset(head, data) < 0)
95         {
96                 fprintf(stderr, "Capability setting error\n");
97
98                 free(data);
99                 free(head);
100                 return -1;
101         }
102
103         free(data);
104         free(head);
105
106         return 0;
107 }
108
109 static int
110 osp_do_pre_exe(const char* app_id, const char* bin_path)
111 {
112         int ret = 0;
113         void* handle = NULL;
114         char* errormsg = 0;
115         int (*do_pre_exec_fn)(const char*, const char*) = NULL;
116
117         handle = dlopen("libosp-env-config.so", RTLD_LAZY | RTLD_LOCAL);
118         if (!handle)
119         {
120                 LOGE("Failed to dlopen osp-env-config.so (%s)", dlerror());
121                 return -1;
122         }
123         LOGI("Tizen::App > dlopen() ok");
124
125         do_pre_exec_fn = (int (*)(const char*, const char*)) dlsym(handle, "do_pre_exec");
126         errormsg = dlerror();
127         if (errormsg != NULL)
128         {
129                 LOGE("Failed to dlsym() (%s)", errormsg);
130                 dlclose(handle);
131                 return -1;
132         }
133         LOGI("dlsym() ok");
134
135         ret = do_pre_exec_fn(app_id, bin_path);
136         if (ret < 0)
137         {
138                 LOGE("Failed to do_pre_exe() (%d)", ret);
139         }
140         LOGI("do_pre_exec() ok");
141
142         dlclose(handle);
143
144         return 0;
145 }
146
147 static int
148 get_packageid_executable_name_from_path(const char path[], char appid[], char executable_name[])
149 {
150         // path is "/opt/apps/[appid]/bin/[executable_name]"
151
152         const char* p = strrchr(path, '/');
153         if (p == NULL)
154         {
155                 LOGI("Improper path %s", path);
156                 return -1;
157         }
158
159         const int path_len = strlen(path);
160         const int exec_len = strlen(p);
161         if (exec_len <= 0 || exec_len > PATH_MAX || path_len <= 0 || path_len > PATH_MAX)
162         {
163                 LOGI("Improper path %s", path);
164                 return -1;
165         }
166
167         strncpy(executable_name, p + 1, exec_len);
168
169 #ifdef _SECURE_LOG
170         LOGI("Exec is %s", executable_name);
171 #endif
172
173         if (path_len < /* '/' */ 1 + 10 + strlen("/bin/") + exec_len)
174         {
175                 LOGI("Improper path %s", path);
176                 return -1;
177         }
178
179         strncpy(appid, p - strlen("bin/") - 10, 10);
180
181         LOGI("appId is %s", appid);
182
183         return 1;
184 }
185
186
187 int
188 main(int argc, char* argv[])
189 {
190         void* real_handle = NULL;
191         char* errormsg = 0;
192         const char* pid = NULL;
193
194         LOGI("Initializing : argc %d, argv 0x%x.", argc, argv);
195         //print_args(argc, argv);
196
197         if (appinfo_is_initialized() == 0)
198         {
199                 // not initialized
200                 char appid[MAX_APPID];
201                 char packageid[MAX_PACKAGEID + 1];
202                 char executable_name[MAX_APP_EXECUTABLE_NAME];
203
204                 memset(appid, 0, sizeof(appid));
205                 memset(packageid, 0, sizeof(packageid));
206                 memset(executable_name, 0, sizeof(executable_name));
207
208                 // convert package path to package name
209                 get_packageid_executable_name_from_path(argv[0], packageid, executable_name);
210                 snprintf(appid, MAX_APPID, "%s.%s", packageid, executable_name);
211
212                 // initialize appid
213                 appinfo_init(appid, 0);
214
215                 LOGI("Non-preloading initialization done.");
216         }
217
218         pid = appinfo_get_appid();
219
220 #ifdef _SECURE_LOG
221         LOGI("app is %s", pid);
222 #endif
223
224         if (getuid() == 0)
225         {
226                 // self caging
227                 osp_do_pre_exe(pid, argv[0]);
228
229                 // adjust privilege
230                 adjust_privilege(pid);
231         }
232
233
234         adjust_capability();
235
236         appinfo_set_argv(argc, argv);
237
238         // actual loading
239         char buffer[1024];
240
241         snprintf(buffer, 1024, "%s.exe", argv[0]);
242
243
244         real_handle = dlopen(buffer, RTLD_LAZY);
245         if (!real_handle)
246         {
247                 LOGE("Failed to open %s : %s.", buffer, dlerror());
248                 return -1;
249         }
250
251         void (*pAppInfoInit)() = NULL;
252         pAppInfoInit = (void (*)()) dlsym(real_handle, "AppInfo_Update");
253         errormsg = dlerror();
254         if (errormsg != NULL)
255         {
256                 LOGE("Failed to find InitAppInfo() : %s.", errormsg);
257                 dlclose(real_handle);
258                 fprintf(stderr, "executable does not have proper osp library dependency.\n");
259                 return -1;
260         }
261
262         int (*pRealMain)(int, char* []) = NULL;
263         pRealMain = (int (*)(int, char*[])) dlsym(real_handle, "OspMain");
264         errormsg = dlerror();
265         if (errormsg != NULL)
266         {
267                 LOGE("Failed to find OspMain() : %s.", errormsg);
268                 dlclose(real_handle);
269                 return -1;
270         }
271
272         // actual initialization
273         (*pAppInfoInit)();
274         (*pRealMain)(argc, argv);
275
276         LOGI("Osp application terminates.");
277
278         //dlclose(real_handle);
279         LOGI("Osp cleanup finished for %s.", argv[0]);
280
281         return 0;
282 }
283