1*2d543d20SAndroid Build Coastguard Worker #include <ctype.h>
2*2d543d20SAndroid Build Coastguard Worker #include <errno.h>
3*2d543d20SAndroid Build Coastguard Worker #include <fcntl.h>
4*2d543d20SAndroid Build Coastguard Worker #include <fnmatch.h>
5*2d543d20SAndroid Build Coastguard Worker #include <fts.h>
6*2d543d20SAndroid Build Coastguard Worker #include <libgen.h>
7*2d543d20SAndroid Build Coastguard Worker #include <limits.h>
8*2d543d20SAndroid Build Coastguard Worker #include <linux/magic.h>
9*2d543d20SAndroid Build Coastguard Worker #include <stdbool.h>
10*2d543d20SAndroid Build Coastguard Worker #include <stdio.h>
11*2d543d20SAndroid Build Coastguard Worker #include <stdlib.h>
12*2d543d20SAndroid Build Coastguard Worker #include <string.h>
13*2d543d20SAndroid Build Coastguard Worker #include <sys/stat.h>
14*2d543d20SAndroid Build Coastguard Worker #include <sys/system_properties.h>
15*2d543d20SAndroid Build Coastguard Worker #include <sys/types.h>
16*2d543d20SAndroid Build Coastguard Worker #include <sys/vfs.h>
17*2d543d20SAndroid Build Coastguard Worker #include <sys/xattr.h>
18*2d543d20SAndroid Build Coastguard Worker #include <unistd.h>
19*2d543d20SAndroid Build Coastguard Worker
20*2d543d20SAndroid Build Coastguard Worker #include <log/log.h>
21*2d543d20SAndroid Build Coastguard Worker #include <packagelistparser/packagelistparser.h>
22*2d543d20SAndroid Build Coastguard Worker #include <private/android_filesystem_config.h>
23*2d543d20SAndroid Build Coastguard Worker #include <selinux/android.h>
24*2d543d20SAndroid Build Coastguard Worker #include <selinux/context.h>
25*2d543d20SAndroid Build Coastguard Worker #include <selinux/selinux.h>
26*2d543d20SAndroid Build Coastguard Worker
27*2d543d20SAndroid Build Coastguard Worker #include "android_internal.h"
28*2d543d20SAndroid Build Coastguard Worker #include "callbacks.h"
29*2d543d20SAndroid Build Coastguard Worker #include "label_internal.h"
30*2d543d20SAndroid Build Coastguard Worker #include "selinux_internal.h"
31*2d543d20SAndroid Build Coastguard Worker
selinux_android_context_with_level(const char * context,char ** newContext,uid_t userid,uid_t appid)32*2d543d20SAndroid Build Coastguard Worker int selinux_android_context_with_level(const char * context,
33*2d543d20SAndroid Build Coastguard Worker char ** newContext,
34*2d543d20SAndroid Build Coastguard Worker uid_t userid,
35*2d543d20SAndroid Build Coastguard Worker uid_t appid)
36*2d543d20SAndroid Build Coastguard Worker {
37*2d543d20SAndroid Build Coastguard Worker int rc = -2;
38*2d543d20SAndroid Build Coastguard Worker
39*2d543d20SAndroid Build Coastguard Worker enum levelFrom levelFrom;
40*2d543d20SAndroid Build Coastguard Worker if (userid == (uid_t) -1) {
41*2d543d20SAndroid Build Coastguard Worker levelFrom = (appid == (uid_t) -1) ? LEVELFROM_NONE : LEVELFROM_APP;
42*2d543d20SAndroid Build Coastguard Worker } else {
43*2d543d20SAndroid Build Coastguard Worker levelFrom = (appid == (uid_t) -1) ? LEVELFROM_USER : LEVELFROM_ALL;
44*2d543d20SAndroid Build Coastguard Worker }
45*2d543d20SAndroid Build Coastguard Worker
46*2d543d20SAndroid Build Coastguard Worker context_t ctx = context_new(context);
47*2d543d20SAndroid Build Coastguard Worker if (!ctx) {
48*2d543d20SAndroid Build Coastguard Worker goto out;
49*2d543d20SAndroid Build Coastguard Worker }
50*2d543d20SAndroid Build Coastguard Worker
51*2d543d20SAndroid Build Coastguard Worker int res = set_range_from_level(ctx, levelFrom, userid, appid);
52*2d543d20SAndroid Build Coastguard Worker if (res != 0) {
53*2d543d20SAndroid Build Coastguard Worker rc = res;
54*2d543d20SAndroid Build Coastguard Worker goto out;
55*2d543d20SAndroid Build Coastguard Worker }
56*2d543d20SAndroid Build Coastguard Worker
57*2d543d20SAndroid Build Coastguard Worker const char * newString = context_str(ctx);
58*2d543d20SAndroid Build Coastguard Worker if (!newString) {
59*2d543d20SAndroid Build Coastguard Worker goto out;
60*2d543d20SAndroid Build Coastguard Worker }
61*2d543d20SAndroid Build Coastguard Worker
62*2d543d20SAndroid Build Coastguard Worker char * newCopied = strdup(newString);
63*2d543d20SAndroid Build Coastguard Worker if (!newCopied) {
64*2d543d20SAndroid Build Coastguard Worker goto out;
65*2d543d20SAndroid Build Coastguard Worker }
66*2d543d20SAndroid Build Coastguard Worker
67*2d543d20SAndroid Build Coastguard Worker *newContext = newCopied;
68*2d543d20SAndroid Build Coastguard Worker rc = 0;
69*2d543d20SAndroid Build Coastguard Worker
70*2d543d20SAndroid Build Coastguard Worker out:
71*2d543d20SAndroid Build Coastguard Worker context_free(ctx);
72*2d543d20SAndroid Build Coastguard Worker return rc;
73*2d543d20SAndroid Build Coastguard Worker }
74*2d543d20SAndroid Build Coastguard Worker
selinux_android_setcon(const char * con)75*2d543d20SAndroid Build Coastguard Worker int selinux_android_setcon(const char *con)
76*2d543d20SAndroid Build Coastguard Worker {
77*2d543d20SAndroid Build Coastguard Worker int ret = setcon(con);
78*2d543d20SAndroid Build Coastguard Worker if (ret)
79*2d543d20SAndroid Build Coastguard Worker return ret;
80*2d543d20SAndroid Build Coastguard Worker /*
81*2d543d20SAndroid Build Coastguard Worker System properties must be reinitialized after setcon() otherwise the
82*2d543d20SAndroid Build Coastguard Worker previous property files will be leaked since mmap()'ed regions are not
83*2d543d20SAndroid Build Coastguard Worker closed as a result of setcon().
84*2d543d20SAndroid Build Coastguard Worker */
85*2d543d20SAndroid Build Coastguard Worker return __system_properties_init();
86*2d543d20SAndroid Build Coastguard Worker }
87*2d543d20SAndroid Build Coastguard Worker
selinux_android_setcontext(uid_t uid,bool isSystemServer,const char * seinfo,const char * pkgname)88*2d543d20SAndroid Build Coastguard Worker int selinux_android_setcontext(uid_t uid,
89*2d543d20SAndroid Build Coastguard Worker bool isSystemServer,
90*2d543d20SAndroid Build Coastguard Worker const char *seinfo,
91*2d543d20SAndroid Build Coastguard Worker const char *pkgname)
92*2d543d20SAndroid Build Coastguard Worker {
93*2d543d20SAndroid Build Coastguard Worker char *orig_ctx_str = NULL;
94*2d543d20SAndroid Build Coastguard Worker const char *ctx_str = NULL;
95*2d543d20SAndroid Build Coastguard Worker context_t ctx = NULL;
96*2d543d20SAndroid Build Coastguard Worker int rc = -1;
97*2d543d20SAndroid Build Coastguard Worker
98*2d543d20SAndroid Build Coastguard Worker if (is_selinux_enabled() <= 0)
99*2d543d20SAndroid Build Coastguard Worker return 0;
100*2d543d20SAndroid Build Coastguard Worker
101*2d543d20SAndroid Build Coastguard Worker rc = getcon(&orig_ctx_str);
102*2d543d20SAndroid Build Coastguard Worker if (rc)
103*2d543d20SAndroid Build Coastguard Worker goto err;
104*2d543d20SAndroid Build Coastguard Worker
105*2d543d20SAndroid Build Coastguard Worker ctx = context_new(orig_ctx_str);
106*2d543d20SAndroid Build Coastguard Worker if (!ctx)
107*2d543d20SAndroid Build Coastguard Worker goto oom;
108*2d543d20SAndroid Build Coastguard Worker
109*2d543d20SAndroid Build Coastguard Worker rc = seapp_context_lookup(SEAPP_DOMAIN, uid, isSystemServer, seinfo, pkgname, ctx);
110*2d543d20SAndroid Build Coastguard Worker if (rc == -1)
111*2d543d20SAndroid Build Coastguard Worker goto err;
112*2d543d20SAndroid Build Coastguard Worker else if (rc == -2)
113*2d543d20SAndroid Build Coastguard Worker goto oom;
114*2d543d20SAndroid Build Coastguard Worker
115*2d543d20SAndroid Build Coastguard Worker ctx_str = context_str(ctx);
116*2d543d20SAndroid Build Coastguard Worker if (!ctx_str)
117*2d543d20SAndroid Build Coastguard Worker goto oom;
118*2d543d20SAndroid Build Coastguard Worker
119*2d543d20SAndroid Build Coastguard Worker rc = security_check_context(ctx_str);
120*2d543d20SAndroid Build Coastguard Worker if (rc < 0)
121*2d543d20SAndroid Build Coastguard Worker goto err;
122*2d543d20SAndroid Build Coastguard Worker
123*2d543d20SAndroid Build Coastguard Worker if (strcmp(ctx_str, orig_ctx_str)) {
124*2d543d20SAndroid Build Coastguard Worker rc = selinux_android_setcon(ctx_str);
125*2d543d20SAndroid Build Coastguard Worker if (rc < 0)
126*2d543d20SAndroid Build Coastguard Worker goto err;
127*2d543d20SAndroid Build Coastguard Worker }
128*2d543d20SAndroid Build Coastguard Worker
129*2d543d20SAndroid Build Coastguard Worker rc = 0;
130*2d543d20SAndroid Build Coastguard Worker out:
131*2d543d20SAndroid Build Coastguard Worker freecon(orig_ctx_str);
132*2d543d20SAndroid Build Coastguard Worker context_free(ctx);
133*2d543d20SAndroid Build Coastguard Worker return rc;
134*2d543d20SAndroid Build Coastguard Worker err:
135*2d543d20SAndroid Build Coastguard Worker if (isSystemServer)
136*2d543d20SAndroid Build Coastguard Worker selinux_log(SELINUX_ERROR,
137*2d543d20SAndroid Build Coastguard Worker "%s: Error setting context for system server: %s\n",
138*2d543d20SAndroid Build Coastguard Worker __FUNCTION__, strerror(errno));
139*2d543d20SAndroid Build Coastguard Worker else
140*2d543d20SAndroid Build Coastguard Worker selinux_log(SELINUX_ERROR,
141*2d543d20SAndroid Build Coastguard Worker "%s: Error setting context for app with uid %d, seinfo %s: %s\n",
142*2d543d20SAndroid Build Coastguard Worker __FUNCTION__, uid, seinfo, strerror(errno));
143*2d543d20SAndroid Build Coastguard Worker
144*2d543d20SAndroid Build Coastguard Worker rc = -1;
145*2d543d20SAndroid Build Coastguard Worker goto out;
146*2d543d20SAndroid Build Coastguard Worker oom:
147*2d543d20SAndroid Build Coastguard Worker selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __FUNCTION__);
148*2d543d20SAndroid Build Coastguard Worker rc = -1;
149*2d543d20SAndroid Build Coastguard Worker goto out;
150*2d543d20SAndroid Build Coastguard Worker }
151*2d543d20SAndroid Build Coastguard Worker
152*2d543d20SAndroid Build Coastguard Worker static struct selabel_handle *fc_sehandle = NULL;
153*2d543d20SAndroid Build Coastguard Worker
file_context_init(void)154*2d543d20SAndroid Build Coastguard Worker static void file_context_init(void)
155*2d543d20SAndroid Build Coastguard Worker {
156*2d543d20SAndroid Build Coastguard Worker if (!fc_sehandle)
157*2d543d20SAndroid Build Coastguard Worker fc_sehandle = selinux_android_file_context_handle();
158*2d543d20SAndroid Build Coastguard Worker }
159*2d543d20SAndroid Build Coastguard Worker
160*2d543d20SAndroid Build Coastguard Worker static pthread_once_t fc_once = PTHREAD_ONCE_INIT;
161*2d543d20SAndroid Build Coastguard Worker
162*2d543d20SAndroid Build Coastguard Worker #define PKGTAB_SIZE 256
163*2d543d20SAndroid Build Coastguard Worker /* Hash table for pkg_info. It uses the package name as key. In case of
164*2d543d20SAndroid Build Coastguard Worker * collision, the next entry is the private_data attribute */
165*2d543d20SAndroid Build Coastguard Worker static struct pkg_info *pkgTab[PKGTAB_SIZE];
166*2d543d20SAndroid Build Coastguard Worker
167*2d543d20SAndroid Build Coastguard Worker /* Returns a hash based on the package name */
pkghash(const char * pkgname)168*2d543d20SAndroid Build Coastguard Worker static unsigned int pkghash(const char *pkgname)
169*2d543d20SAndroid Build Coastguard Worker {
170*2d543d20SAndroid Build Coastguard Worker unsigned int h = 7;
171*2d543d20SAndroid Build Coastguard Worker for (; *pkgname; pkgname++) {
172*2d543d20SAndroid Build Coastguard Worker h = h * 31 + *pkgname;
173*2d543d20SAndroid Build Coastguard Worker }
174*2d543d20SAndroid Build Coastguard Worker return h & (PKGTAB_SIZE - 1);
175*2d543d20SAndroid Build Coastguard Worker }
176*2d543d20SAndroid Build Coastguard Worker
177*2d543d20SAndroid Build Coastguard Worker /* Adds the pkg_info entry to the hash table */
pkg_parse_callback(pkg_info * info,void * userdata)178*2d543d20SAndroid Build Coastguard Worker static bool pkg_parse_callback(pkg_info *info, void *userdata) {
179*2d543d20SAndroid Build Coastguard Worker
180*2d543d20SAndroid Build Coastguard Worker (void) userdata;
181*2d543d20SAndroid Build Coastguard Worker
182*2d543d20SAndroid Build Coastguard Worker unsigned int hash = pkghash(info->name);
183*2d543d20SAndroid Build Coastguard Worker if (pkgTab[hash])
184*2d543d20SAndroid Build Coastguard Worker /* Collision. Prepend the entry. */
185*2d543d20SAndroid Build Coastguard Worker info->private_data = pkgTab[hash];
186*2d543d20SAndroid Build Coastguard Worker pkgTab[hash] = info;
187*2d543d20SAndroid Build Coastguard Worker return true;
188*2d543d20SAndroid Build Coastguard Worker }
189*2d543d20SAndroid Build Coastguard Worker
190*2d543d20SAndroid Build Coastguard Worker /* Initialize the pkg_info hash table */
package_info_init(void)191*2d543d20SAndroid Build Coastguard Worker static void package_info_init(void)
192*2d543d20SAndroid Build Coastguard Worker {
193*2d543d20SAndroid Build Coastguard Worker
194*2d543d20SAndroid Build Coastguard Worker bool rc = packagelist_parse(pkg_parse_callback, NULL);
195*2d543d20SAndroid Build Coastguard Worker if (!rc) {
196*2d543d20SAndroid Build Coastguard Worker selinux_log(SELINUX_ERROR, "SELinux: Could NOT parse package list\n");
197*2d543d20SAndroid Build Coastguard Worker return;
198*2d543d20SAndroid Build Coastguard Worker }
199*2d543d20SAndroid Build Coastguard Worker
200*2d543d20SAndroid Build Coastguard Worker #if DEBUG
201*2d543d20SAndroid Build Coastguard Worker {
202*2d543d20SAndroid Build Coastguard Worker unsigned int hash, buckets, entries, chainlen, longestchain;
203*2d543d20SAndroid Build Coastguard Worker struct pkg_info *info = NULL;
204*2d543d20SAndroid Build Coastguard Worker
205*2d543d20SAndroid Build Coastguard Worker buckets = entries = longestchain = 0;
206*2d543d20SAndroid Build Coastguard Worker for (hash = 0; hash < PKGTAB_SIZE; hash++) {
207*2d543d20SAndroid Build Coastguard Worker if (pkgTab[hash]) {
208*2d543d20SAndroid Build Coastguard Worker buckets++;
209*2d543d20SAndroid Build Coastguard Worker chainlen = 0;
210*2d543d20SAndroid Build Coastguard Worker for (info = pkgTab[hash]; info; info = (pkg_info *)info->private_data) {
211*2d543d20SAndroid Build Coastguard Worker chainlen++;
212*2d543d20SAndroid Build Coastguard Worker selinux_log(SELINUX_INFO, "%s: name=%s uid=%u debuggable=%s dataDir=%s seinfo=%s\n",
213*2d543d20SAndroid Build Coastguard Worker __FUNCTION__,
214*2d543d20SAndroid Build Coastguard Worker info->name, info->uid, info->debuggable ? "true" : "false", info->data_dir, info->seinfo);
215*2d543d20SAndroid Build Coastguard Worker }
216*2d543d20SAndroid Build Coastguard Worker entries += chainlen;
217*2d543d20SAndroid Build Coastguard Worker if (longestchain < chainlen)
218*2d543d20SAndroid Build Coastguard Worker longestchain = chainlen;
219*2d543d20SAndroid Build Coastguard Worker }
220*2d543d20SAndroid Build Coastguard Worker }
221*2d543d20SAndroid Build Coastguard Worker selinux_log(SELINUX_INFO, "SELinux: %d pkg entries and %d/%d buckets used, longest chain %d\n", entries, buckets, PKGTAB_SIZE, longestchain);
222*2d543d20SAndroid Build Coastguard Worker }
223*2d543d20SAndroid Build Coastguard Worker #endif
224*2d543d20SAndroid Build Coastguard Worker
225*2d543d20SAndroid Build Coastguard Worker }
226*2d543d20SAndroid Build Coastguard Worker
227*2d543d20SAndroid Build Coastguard Worker static pthread_once_t pkg_once = PTHREAD_ONCE_INIT;
228*2d543d20SAndroid Build Coastguard Worker
229*2d543d20SAndroid Build Coastguard Worker /* Returns the pkg_info for a package with a specific name */
package_info_lookup(const char * name)230*2d543d20SAndroid Build Coastguard Worker struct pkg_info *package_info_lookup(const char *name)
231*2d543d20SAndroid Build Coastguard Worker {
232*2d543d20SAndroid Build Coastguard Worker struct pkg_info *info;
233*2d543d20SAndroid Build Coastguard Worker unsigned int hash;
234*2d543d20SAndroid Build Coastguard Worker
235*2d543d20SAndroid Build Coastguard Worker __selinux_once(pkg_once, package_info_init);
236*2d543d20SAndroid Build Coastguard Worker
237*2d543d20SAndroid Build Coastguard Worker hash = pkghash(name);
238*2d543d20SAndroid Build Coastguard Worker for (info = pkgTab[hash]; info; info = (pkg_info *)info->private_data) {
239*2d543d20SAndroid Build Coastguard Worker if (!strcmp(name, info->name))
240*2d543d20SAndroid Build Coastguard Worker return info;
241*2d543d20SAndroid Build Coastguard Worker }
242*2d543d20SAndroid Build Coastguard Worker return NULL;
243*2d543d20SAndroid Build Coastguard Worker }
244*2d543d20SAndroid Build Coastguard Worker
245*2d543d20SAndroid Build Coastguard Worker #define USER_PROFILE_PATH "/data/misc/profiles/cur/*"
246*2d543d20SAndroid Build Coastguard Worker
pkgdir_selabel_lookup(const char * pathname,const char * seinfo,uid_t uid,char ** secontextp)247*2d543d20SAndroid Build Coastguard Worker static int pkgdir_selabel_lookup(const char *pathname,
248*2d543d20SAndroid Build Coastguard Worker const char *seinfo,
249*2d543d20SAndroid Build Coastguard Worker uid_t uid,
250*2d543d20SAndroid Build Coastguard Worker char **secontextp)
251*2d543d20SAndroid Build Coastguard Worker {
252*2d543d20SAndroid Build Coastguard Worker char *pkgname = NULL;
253*2d543d20SAndroid Build Coastguard Worker struct pkg_info *info = NULL;
254*2d543d20SAndroid Build Coastguard Worker const char *orig_ctx_str = *secontextp;
255*2d543d20SAndroid Build Coastguard Worker const char *ctx_str = NULL;
256*2d543d20SAndroid Build Coastguard Worker context_t ctx = NULL;
257*2d543d20SAndroid Build Coastguard Worker int rc = 0;
258*2d543d20SAndroid Build Coastguard Worker unsigned int userid_from_path = 0;
259*2d543d20SAndroid Build Coastguard Worker
260*2d543d20SAndroid Build Coastguard Worker rc = extract_pkgname_and_userid(pathname, &pkgname, &userid_from_path);
261*2d543d20SAndroid Build Coastguard Worker if (rc) {
262*2d543d20SAndroid Build Coastguard Worker /* Invalid path, we skip it */
263*2d543d20SAndroid Build Coastguard Worker if (rc == -1) {
264*2d543d20SAndroid Build Coastguard Worker return 0;
265*2d543d20SAndroid Build Coastguard Worker }
266*2d543d20SAndroid Build Coastguard Worker return rc;
267*2d543d20SAndroid Build Coastguard Worker }
268*2d543d20SAndroid Build Coastguard Worker
269*2d543d20SAndroid Build Coastguard Worker if (!seinfo) {
270*2d543d20SAndroid Build Coastguard Worker info = package_info_lookup(pkgname);
271*2d543d20SAndroid Build Coastguard Worker if (!info) {
272*2d543d20SAndroid Build Coastguard Worker selinux_log(SELINUX_WARNING, "SELinux: Could not look up information for package %s, cannot restorecon %s.\n",
273*2d543d20SAndroid Build Coastguard Worker pkgname, pathname);
274*2d543d20SAndroid Build Coastguard Worker free(pkgname);
275*2d543d20SAndroid Build Coastguard Worker return -1;
276*2d543d20SAndroid Build Coastguard Worker }
277*2d543d20SAndroid Build Coastguard Worker // info->uid only contains the appid and not the userid.
278*2d543d20SAndroid Build Coastguard Worker info->uid += userid_from_path * AID_USER_OFFSET;
279*2d543d20SAndroid Build Coastguard Worker }
280*2d543d20SAndroid Build Coastguard Worker
281*2d543d20SAndroid Build Coastguard Worker ctx = context_new(orig_ctx_str);
282*2d543d20SAndroid Build Coastguard Worker if (!ctx)
283*2d543d20SAndroid Build Coastguard Worker goto err;
284*2d543d20SAndroid Build Coastguard Worker
285*2d543d20SAndroid Build Coastguard Worker rc = seapp_context_lookup(SEAPP_TYPE, info ? info->uid : uid, 0,
286*2d543d20SAndroid Build Coastguard Worker info ? info->seinfo : seinfo, info ? info->name : pkgname, ctx);
287*2d543d20SAndroid Build Coastguard Worker if (rc < 0)
288*2d543d20SAndroid Build Coastguard Worker goto err;
289*2d543d20SAndroid Build Coastguard Worker
290*2d543d20SAndroid Build Coastguard Worker ctx_str = context_str(ctx);
291*2d543d20SAndroid Build Coastguard Worker if (!ctx_str)
292*2d543d20SAndroid Build Coastguard Worker goto err;
293*2d543d20SAndroid Build Coastguard Worker
294*2d543d20SAndroid Build Coastguard Worker if (!strcmp(ctx_str, orig_ctx_str))
295*2d543d20SAndroid Build Coastguard Worker goto out;
296*2d543d20SAndroid Build Coastguard Worker
297*2d543d20SAndroid Build Coastguard Worker rc = security_check_context(ctx_str);
298*2d543d20SAndroid Build Coastguard Worker if (rc < 0)
299*2d543d20SAndroid Build Coastguard Worker goto err;
300*2d543d20SAndroid Build Coastguard Worker
301*2d543d20SAndroid Build Coastguard Worker freecon(*secontextp);
302*2d543d20SAndroid Build Coastguard Worker *secontextp = strdup(ctx_str);
303*2d543d20SAndroid Build Coastguard Worker if (!(*secontextp))
304*2d543d20SAndroid Build Coastguard Worker goto err;
305*2d543d20SAndroid Build Coastguard Worker
306*2d543d20SAndroid Build Coastguard Worker rc = 0;
307*2d543d20SAndroid Build Coastguard Worker
308*2d543d20SAndroid Build Coastguard Worker out:
309*2d543d20SAndroid Build Coastguard Worker free(pkgname);
310*2d543d20SAndroid Build Coastguard Worker context_free(ctx);
311*2d543d20SAndroid Build Coastguard Worker return rc;
312*2d543d20SAndroid Build Coastguard Worker err:
313*2d543d20SAndroid Build Coastguard Worker selinux_log(SELINUX_ERROR, "%s: Error looking up context for path %s, pkgname %s, seinfo %s, uid %u: %s\n",
314*2d543d20SAndroid Build Coastguard Worker __FUNCTION__, pathname, pkgname, info ? info->seinfo : seinfo,
315*2d543d20SAndroid Build Coastguard Worker info ? info->uid : uid, strerror(errno));
316*2d543d20SAndroid Build Coastguard Worker rc = -1;
317*2d543d20SAndroid Build Coastguard Worker goto out;
318*2d543d20SAndroid Build Coastguard Worker }
319*2d543d20SAndroid Build Coastguard Worker
320*2d543d20SAndroid Build Coastguard Worker #define RESTORECON_PARTIAL_MATCH_DIGEST "security.sehash"
321*2d543d20SAndroid Build Coastguard Worker
restorecon_sb(const char * pathname,const struct stat * sb,bool nochange,bool verbose,const char * seinfo,uid_t uid)322*2d543d20SAndroid Build Coastguard Worker static int restorecon_sb(const char *pathname,
323*2d543d20SAndroid Build Coastguard Worker const struct stat *sb,
324*2d543d20SAndroid Build Coastguard Worker bool nochange,
325*2d543d20SAndroid Build Coastguard Worker bool verbose,
326*2d543d20SAndroid Build Coastguard Worker const char *seinfo,
327*2d543d20SAndroid Build Coastguard Worker uid_t uid)
328*2d543d20SAndroid Build Coastguard Worker {
329*2d543d20SAndroid Build Coastguard Worker char *secontext = NULL;
330*2d543d20SAndroid Build Coastguard Worker char *oldsecontext = NULL;
331*2d543d20SAndroid Build Coastguard Worker int rc = 0;
332*2d543d20SAndroid Build Coastguard Worker
333*2d543d20SAndroid Build Coastguard Worker if (selabel_lookup(fc_sehandle, &secontext, pathname, sb->st_mode) < 0)
334*2d543d20SAndroid Build Coastguard Worker return 0; /* no match, but not an error */
335*2d543d20SAndroid Build Coastguard Worker
336*2d543d20SAndroid Build Coastguard Worker if (lgetfilecon(pathname, &oldsecontext) < 0)
337*2d543d20SAndroid Build Coastguard Worker goto err;
338*2d543d20SAndroid Build Coastguard Worker
339*2d543d20SAndroid Build Coastguard Worker /*
340*2d543d20SAndroid Build Coastguard Worker * For subdirectories of /data/data or /data/user, we ignore selabel_lookup()
341*2d543d20SAndroid Build Coastguard Worker * and use pkgdir_selabel_lookup() instead. Files within those directories
342*2d543d20SAndroid Build Coastguard Worker * have different labeling rules, based off of /seapp_contexts, and
343*2d543d20SAndroid Build Coastguard Worker * installd is responsible for managing these labels instead of init.
344*2d543d20SAndroid Build Coastguard Worker */
345*2d543d20SAndroid Build Coastguard Worker if (is_app_data_path(pathname)) {
346*2d543d20SAndroid Build Coastguard Worker if (pkgdir_selabel_lookup(pathname, seinfo, uid, &secontext) < 0)
347*2d543d20SAndroid Build Coastguard Worker goto err;
348*2d543d20SAndroid Build Coastguard Worker }
349*2d543d20SAndroid Build Coastguard Worker
350*2d543d20SAndroid Build Coastguard Worker if (strcmp(oldsecontext, secontext) != 0) {
351*2d543d20SAndroid Build Coastguard Worker if (verbose)
352*2d543d20SAndroid Build Coastguard Worker selinux_log(SELINUX_INFO,
353*2d543d20SAndroid Build Coastguard Worker "SELinux: Relabeling %s from %s to %s.\n", pathname, oldsecontext, secontext);
354*2d543d20SAndroid Build Coastguard Worker if (!nochange) {
355*2d543d20SAndroid Build Coastguard Worker if (lsetfilecon(pathname, secontext) < 0)
356*2d543d20SAndroid Build Coastguard Worker goto err;
357*2d543d20SAndroid Build Coastguard Worker }
358*2d543d20SAndroid Build Coastguard Worker }
359*2d543d20SAndroid Build Coastguard Worker
360*2d543d20SAndroid Build Coastguard Worker rc = 0;
361*2d543d20SAndroid Build Coastguard Worker
362*2d543d20SAndroid Build Coastguard Worker out:
363*2d543d20SAndroid Build Coastguard Worker freecon(oldsecontext);
364*2d543d20SAndroid Build Coastguard Worker freecon(secontext);
365*2d543d20SAndroid Build Coastguard Worker return rc;
366*2d543d20SAndroid Build Coastguard Worker
367*2d543d20SAndroid Build Coastguard Worker err:
368*2d543d20SAndroid Build Coastguard Worker selinux_log(SELINUX_ERROR,
369*2d543d20SAndroid Build Coastguard Worker "SELinux: Could not set context for %s: %s\n",
370*2d543d20SAndroid Build Coastguard Worker pathname, strerror(errno));
371*2d543d20SAndroid Build Coastguard Worker rc = -1;
372*2d543d20SAndroid Build Coastguard Worker goto out;
373*2d543d20SAndroid Build Coastguard Worker }
374*2d543d20SAndroid Build Coastguard Worker
375*2d543d20SAndroid Build Coastguard Worker #define SYS_PATH "/sys"
376*2d543d20SAndroid Build Coastguard Worker #define SYS_PREFIX SYS_PATH "/"
377*2d543d20SAndroid Build Coastguard Worker
378*2d543d20SAndroid Build Coastguard Worker struct dir_hash_node {
379*2d543d20SAndroid Build Coastguard Worker char* path;
380*2d543d20SAndroid Build Coastguard Worker uint8_t digest[SHA1_HASH_SIZE];
381*2d543d20SAndroid Build Coastguard Worker struct dir_hash_node *next;
382*2d543d20SAndroid Build Coastguard Worker };
383*2d543d20SAndroid Build Coastguard Worker
384*2d543d20SAndroid Build Coastguard Worker // Returns true if the digest of all partial matched contexts is the same as the one
385*2d543d20SAndroid Build Coastguard Worker // saved by setxattr. Otherwise returns false and constructs a dir_hash_node with the
386*2d543d20SAndroid Build Coastguard Worker // newly calculated digest.
check_context_match_for_dir(const char * pathname,struct dir_hash_node ** new_node,bool force,int error)387*2d543d20SAndroid Build Coastguard Worker static bool check_context_match_for_dir(const char *pathname,
388*2d543d20SAndroid Build Coastguard Worker struct dir_hash_node **new_node,
389*2d543d20SAndroid Build Coastguard Worker bool force, int error)
390*2d543d20SAndroid Build Coastguard Worker {
391*2d543d20SAndroid Build Coastguard Worker uint8_t read_digest[SHA1_HASH_SIZE];
392*2d543d20SAndroid Build Coastguard Worker ssize_t read_size = getxattr(pathname, RESTORECON_PARTIAL_MATCH_DIGEST,
393*2d543d20SAndroid Build Coastguard Worker read_digest, SHA1_HASH_SIZE);
394*2d543d20SAndroid Build Coastguard Worker uint8_t calculated_digest[SHA1_HASH_SIZE];
395*2d543d20SAndroid Build Coastguard Worker bool status = selabel_hash_all_partial_matches(fc_sehandle, pathname,
396*2d543d20SAndroid Build Coastguard Worker calculated_digest);
397*2d543d20SAndroid Build Coastguard Worker
398*2d543d20SAndroid Build Coastguard Worker if (!new_node) {
399*2d543d20SAndroid Build Coastguard Worker return false;
400*2d543d20SAndroid Build Coastguard Worker }
401*2d543d20SAndroid Build Coastguard Worker *new_node = NULL;
402*2d543d20SAndroid Build Coastguard Worker if (!force && status && read_size == SHA1_HASH_SIZE &&
403*2d543d20SAndroid Build Coastguard Worker memcmp(read_digest, calculated_digest, SHA1_HASH_SIZE) == 0) {
404*2d543d20SAndroid Build Coastguard Worker return true;
405*2d543d20SAndroid Build Coastguard Worker }
406*2d543d20SAndroid Build Coastguard Worker
407*2d543d20SAndroid Build Coastguard Worker // Save the digest of all matched contexts for the current directory.
408*2d543d20SAndroid Build Coastguard Worker if (!error && status) {
409*2d543d20SAndroid Build Coastguard Worker *new_node = calloc(1, sizeof(struct dir_hash_node));
410*2d543d20SAndroid Build Coastguard Worker if (*new_node == NULL) {
411*2d543d20SAndroid Build Coastguard Worker selinux_log(SELINUX_ERROR,
412*2d543d20SAndroid Build Coastguard Worker "SELinux: %s: Out of memory\n", __func__);
413*2d543d20SAndroid Build Coastguard Worker return false;
414*2d543d20SAndroid Build Coastguard Worker }
415*2d543d20SAndroid Build Coastguard Worker
416*2d543d20SAndroid Build Coastguard Worker (*new_node)->path = strdup(pathname);
417*2d543d20SAndroid Build Coastguard Worker if ((*new_node)->path == NULL) {
418*2d543d20SAndroid Build Coastguard Worker selinux_log(SELINUX_ERROR,
419*2d543d20SAndroid Build Coastguard Worker "SELinux: %s: Out of memory\n", __func__);
420*2d543d20SAndroid Build Coastguard Worker free(*new_node);
421*2d543d20SAndroid Build Coastguard Worker *new_node = NULL;
422*2d543d20SAndroid Build Coastguard Worker return false;
423*2d543d20SAndroid Build Coastguard Worker }
424*2d543d20SAndroid Build Coastguard Worker memcpy((*new_node)->digest, calculated_digest, SHA1_HASH_SIZE);
425*2d543d20SAndroid Build Coastguard Worker (*new_node)->next = NULL;
426*2d543d20SAndroid Build Coastguard Worker }
427*2d543d20SAndroid Build Coastguard Worker
428*2d543d20SAndroid Build Coastguard Worker return false;
429*2d543d20SAndroid Build Coastguard Worker }
430*2d543d20SAndroid Build Coastguard Worker
selinux_android_restorecon_common(const char * pathname_orig,const char * seinfo,uid_t uid,unsigned int flags)431*2d543d20SAndroid Build Coastguard Worker static int selinux_android_restorecon_common(const char* pathname_orig,
432*2d543d20SAndroid Build Coastguard Worker const char *seinfo,
433*2d543d20SAndroid Build Coastguard Worker uid_t uid,
434*2d543d20SAndroid Build Coastguard Worker unsigned int flags)
435*2d543d20SAndroid Build Coastguard Worker {
436*2d543d20SAndroid Build Coastguard Worker bool nochange = (flags & SELINUX_ANDROID_RESTORECON_NOCHANGE) ? true : false;
437*2d543d20SAndroid Build Coastguard Worker bool verbose = (flags & SELINUX_ANDROID_RESTORECON_VERBOSE) ? true : false;
438*2d543d20SAndroid Build Coastguard Worker bool recurse = (flags & SELINUX_ANDROID_RESTORECON_RECURSE) ? true : false;
439*2d543d20SAndroid Build Coastguard Worker bool force = (flags & SELINUX_ANDROID_RESTORECON_FORCE) ? true : false;
440*2d543d20SAndroid Build Coastguard Worker bool datadata = (flags & SELINUX_ANDROID_RESTORECON_DATADATA) ? true : false;
441*2d543d20SAndroid Build Coastguard Worker bool skipce = (flags & SELINUX_ANDROID_RESTORECON_SKIPCE) ? true : false;
442*2d543d20SAndroid Build Coastguard Worker bool cross_filesystems = (flags & SELINUX_ANDROID_RESTORECON_CROSS_FILESYSTEMS) ? true : false;
443*2d543d20SAndroid Build Coastguard Worker bool setrestoreconlast = (flags & SELINUX_ANDROID_RESTORECON_SKIP_SEHASH) ? false : true;
444*2d543d20SAndroid Build Coastguard Worker bool issys;
445*2d543d20SAndroid Build Coastguard Worker struct stat sb;
446*2d543d20SAndroid Build Coastguard Worker struct statfs sfsb;
447*2d543d20SAndroid Build Coastguard Worker FTS *fts;
448*2d543d20SAndroid Build Coastguard Worker FTSENT *ftsent;
449*2d543d20SAndroid Build Coastguard Worker char *pathname = NULL, *pathdnamer = NULL, *pathdname, *pathbname;
450*2d543d20SAndroid Build Coastguard Worker char * paths[2] = { NULL , NULL };
451*2d543d20SAndroid Build Coastguard Worker int ftsflags = FTS_NOCHDIR | FTS_PHYSICAL;
452*2d543d20SAndroid Build Coastguard Worker int error, sverrno;
453*2d543d20SAndroid Build Coastguard Worker struct dir_hash_node *current = NULL;
454*2d543d20SAndroid Build Coastguard Worker struct dir_hash_node *head = NULL;
455*2d543d20SAndroid Build Coastguard Worker
456*2d543d20SAndroid Build Coastguard Worker if (!cross_filesystems) {
457*2d543d20SAndroid Build Coastguard Worker ftsflags |= FTS_XDEV;
458*2d543d20SAndroid Build Coastguard Worker }
459*2d543d20SAndroid Build Coastguard Worker
460*2d543d20SAndroid Build Coastguard Worker if (is_selinux_enabled() <= 0) {
461*2d543d20SAndroid Build Coastguard Worker selinux_log(SELINUX_WARNING, "SELinux: SELinux is disabled, skipping restorecon");
462*2d543d20SAndroid Build Coastguard Worker return 0;
463*2d543d20SAndroid Build Coastguard Worker }
464*2d543d20SAndroid Build Coastguard Worker
465*2d543d20SAndroid Build Coastguard Worker __selinux_once(fc_once, file_context_init);
466*2d543d20SAndroid Build Coastguard Worker
467*2d543d20SAndroid Build Coastguard Worker if (!fc_sehandle)
468*2d543d20SAndroid Build Coastguard Worker return 0;
469*2d543d20SAndroid Build Coastguard Worker
470*2d543d20SAndroid Build Coastguard Worker /*
471*2d543d20SAndroid Build Coastguard Worker * Convert passed-in pathname to canonical pathname by resolving realpath of
472*2d543d20SAndroid Build Coastguard Worker * containing dir, then appending last component name.
473*2d543d20SAndroid Build Coastguard Worker */
474*2d543d20SAndroid Build Coastguard Worker pathbname = basename(pathname_orig);
475*2d543d20SAndroid Build Coastguard Worker if (!strcmp(pathbname, "/") || !strcmp(pathbname, ".") || !strcmp(pathbname, "..")) {
476*2d543d20SAndroid Build Coastguard Worker pathname = realpath(pathname_orig, NULL);
477*2d543d20SAndroid Build Coastguard Worker if (!pathname)
478*2d543d20SAndroid Build Coastguard Worker goto realpatherr;
479*2d543d20SAndroid Build Coastguard Worker } else {
480*2d543d20SAndroid Build Coastguard Worker pathdname = dirname(pathname_orig);
481*2d543d20SAndroid Build Coastguard Worker pathdnamer = realpath(pathdname, NULL);
482*2d543d20SAndroid Build Coastguard Worker if (!pathdnamer)
483*2d543d20SAndroid Build Coastguard Worker goto realpatherr;
484*2d543d20SAndroid Build Coastguard Worker if (!strcmp(pathdnamer, "/"))
485*2d543d20SAndroid Build Coastguard Worker error = asprintf(&pathname, "/%s", pathbname);
486*2d543d20SAndroid Build Coastguard Worker else
487*2d543d20SAndroid Build Coastguard Worker error = asprintf(&pathname, "%s/%s", pathdnamer, pathbname);
488*2d543d20SAndroid Build Coastguard Worker if (error < 0)
489*2d543d20SAndroid Build Coastguard Worker goto oom;
490*2d543d20SAndroid Build Coastguard Worker }
491*2d543d20SAndroid Build Coastguard Worker
492*2d543d20SAndroid Build Coastguard Worker paths[0] = pathname;
493*2d543d20SAndroid Build Coastguard Worker issys = (!strcmp(pathname, SYS_PATH)
494*2d543d20SAndroid Build Coastguard Worker || !strncmp(pathname, SYS_PREFIX, sizeof(SYS_PREFIX)-1)) ? true : false;
495*2d543d20SAndroid Build Coastguard Worker
496*2d543d20SAndroid Build Coastguard Worker if (!recurse) {
497*2d543d20SAndroid Build Coastguard Worker if (lstat(pathname, &sb) < 0) {
498*2d543d20SAndroid Build Coastguard Worker error = -1;
499*2d543d20SAndroid Build Coastguard Worker goto cleanup;
500*2d543d20SAndroid Build Coastguard Worker }
501*2d543d20SAndroid Build Coastguard Worker
502*2d543d20SAndroid Build Coastguard Worker error = restorecon_sb(pathname, &sb, nochange, verbose, seinfo, uid);
503*2d543d20SAndroid Build Coastguard Worker goto cleanup;
504*2d543d20SAndroid Build Coastguard Worker }
505*2d543d20SAndroid Build Coastguard Worker
506*2d543d20SAndroid Build Coastguard Worker /*
507*2d543d20SAndroid Build Coastguard Worker * Ignore saved partial match digest on /data/data or /data/user
508*2d543d20SAndroid Build Coastguard Worker * since their labeling is based on seapp_contexts and seinfo
509*2d543d20SAndroid Build Coastguard Worker * assignments rather than file_contexts and is managed by
510*2d543d20SAndroid Build Coastguard Worker * installd rather than init.
511*2d543d20SAndroid Build Coastguard Worker */
512*2d543d20SAndroid Build Coastguard Worker if (is_app_data_path(pathname))
513*2d543d20SAndroid Build Coastguard Worker setrestoreconlast = false;
514*2d543d20SAndroid Build Coastguard Worker
515*2d543d20SAndroid Build Coastguard Worker /* Also ignore on /sys since it is regenerated on each boot regardless. */
516*2d543d20SAndroid Build Coastguard Worker if (issys)
517*2d543d20SAndroid Build Coastguard Worker setrestoreconlast = false;
518*2d543d20SAndroid Build Coastguard Worker
519*2d543d20SAndroid Build Coastguard Worker /* Ignore files on in-memory filesystems */
520*2d543d20SAndroid Build Coastguard Worker if (statfs(pathname, &sfsb) == 0) {
521*2d543d20SAndroid Build Coastguard Worker if (sfsb.f_type == RAMFS_MAGIC || sfsb.f_type == TMPFS_MAGIC)
522*2d543d20SAndroid Build Coastguard Worker setrestoreconlast = false;
523*2d543d20SAndroid Build Coastguard Worker }
524*2d543d20SAndroid Build Coastguard Worker
525*2d543d20SAndroid Build Coastguard Worker fts = fts_open(paths, ftsflags, NULL);
526*2d543d20SAndroid Build Coastguard Worker if (!fts) {
527*2d543d20SAndroid Build Coastguard Worker error = -1;
528*2d543d20SAndroid Build Coastguard Worker goto cleanup;
529*2d543d20SAndroid Build Coastguard Worker }
530*2d543d20SAndroid Build Coastguard Worker
531*2d543d20SAndroid Build Coastguard Worker error = 0;
532*2d543d20SAndroid Build Coastguard Worker while ((ftsent = fts_read(fts)) != NULL) {
533*2d543d20SAndroid Build Coastguard Worker switch (ftsent->fts_info) {
534*2d543d20SAndroid Build Coastguard Worker case FTS_DC:
535*2d543d20SAndroid Build Coastguard Worker selinux_log(SELINUX_ERROR,
536*2d543d20SAndroid Build Coastguard Worker "SELinux: Directory cycle on %s.\n", ftsent->fts_path);
537*2d543d20SAndroid Build Coastguard Worker errno = ELOOP;
538*2d543d20SAndroid Build Coastguard Worker error = -1;
539*2d543d20SAndroid Build Coastguard Worker goto out;
540*2d543d20SAndroid Build Coastguard Worker case FTS_DP:
541*2d543d20SAndroid Build Coastguard Worker continue;
542*2d543d20SAndroid Build Coastguard Worker case FTS_DNR:
543*2d543d20SAndroid Build Coastguard Worker selinux_log(SELINUX_ERROR,
544*2d543d20SAndroid Build Coastguard Worker "SELinux: Could not read %s: %s.\n", ftsent->fts_path, strerror(errno));
545*2d543d20SAndroid Build Coastguard Worker fts_set(fts, ftsent, FTS_SKIP);
546*2d543d20SAndroid Build Coastguard Worker continue;
547*2d543d20SAndroid Build Coastguard Worker case FTS_NS:
548*2d543d20SAndroid Build Coastguard Worker selinux_log(SELINUX_ERROR,
549*2d543d20SAndroid Build Coastguard Worker "SELinux: Could not stat %s: %s.\n", ftsent->fts_path, strerror(errno));
550*2d543d20SAndroid Build Coastguard Worker fts_set(fts, ftsent, FTS_SKIP);
551*2d543d20SAndroid Build Coastguard Worker continue;
552*2d543d20SAndroid Build Coastguard Worker case FTS_ERR:
553*2d543d20SAndroid Build Coastguard Worker selinux_log(SELINUX_ERROR,
554*2d543d20SAndroid Build Coastguard Worker "SELinux: Error on %s: %s.\n", ftsent->fts_path, strerror(errno));
555*2d543d20SAndroid Build Coastguard Worker fts_set(fts, ftsent, FTS_SKIP);
556*2d543d20SAndroid Build Coastguard Worker continue;
557*2d543d20SAndroid Build Coastguard Worker case FTS_D:
558*2d543d20SAndroid Build Coastguard Worker if (issys && !selabel_partial_match(fc_sehandle, ftsent->fts_path)) {
559*2d543d20SAndroid Build Coastguard Worker fts_set(fts, ftsent, FTS_SKIP);
560*2d543d20SAndroid Build Coastguard Worker continue;
561*2d543d20SAndroid Build Coastguard Worker }
562*2d543d20SAndroid Build Coastguard Worker
563*2d543d20SAndroid Build Coastguard Worker if (!datadata && !fnmatch(USER_PROFILE_PATH, ftsent->fts_path, FNM_PATHNAME)) {
564*2d543d20SAndroid Build Coastguard Worker // Don't label this directory, vold takes care of that, but continue below it.
565*2d543d20SAndroid Build Coastguard Worker continue;
566*2d543d20SAndroid Build Coastguard Worker }
567*2d543d20SAndroid Build Coastguard Worker
568*2d543d20SAndroid Build Coastguard Worker if (setrestoreconlast) {
569*2d543d20SAndroid Build Coastguard Worker struct dir_hash_node* new_node = NULL;
570*2d543d20SAndroid Build Coastguard Worker if (check_context_match_for_dir(ftsent->fts_path, &new_node, force, error)) {
571*2d543d20SAndroid Build Coastguard Worker selinux_log(SELINUX_INFO,
572*2d543d20SAndroid Build Coastguard Worker "SELinux: Skipping restorecon on directory(%s)\n",
573*2d543d20SAndroid Build Coastguard Worker ftsent->fts_path);
574*2d543d20SAndroid Build Coastguard Worker fts_set(fts, ftsent, FTS_SKIP);
575*2d543d20SAndroid Build Coastguard Worker continue;
576*2d543d20SAndroid Build Coastguard Worker }
577*2d543d20SAndroid Build Coastguard Worker if (new_node) {
578*2d543d20SAndroid Build Coastguard Worker if (!current) {
579*2d543d20SAndroid Build Coastguard Worker current = new_node;
580*2d543d20SAndroid Build Coastguard Worker head = current;
581*2d543d20SAndroid Build Coastguard Worker } else {
582*2d543d20SAndroid Build Coastguard Worker current->next = new_node;
583*2d543d20SAndroid Build Coastguard Worker current = current->next;
584*2d543d20SAndroid Build Coastguard Worker }
585*2d543d20SAndroid Build Coastguard Worker }
586*2d543d20SAndroid Build Coastguard Worker }
587*2d543d20SAndroid Build Coastguard Worker
588*2d543d20SAndroid Build Coastguard Worker if (skipce && is_credential_encrypted_path(ftsent->fts_path)) {
589*2d543d20SAndroid Build Coastguard Worker // Don't label anything below this directory.
590*2d543d20SAndroid Build Coastguard Worker fts_set(fts, ftsent, FTS_SKIP);
591*2d543d20SAndroid Build Coastguard Worker // but fall through and make sure we label the directory itself
592*2d543d20SAndroid Build Coastguard Worker }
593*2d543d20SAndroid Build Coastguard Worker
594*2d543d20SAndroid Build Coastguard Worker if (!datadata && is_app_data_path(ftsent->fts_path)) {
595*2d543d20SAndroid Build Coastguard Worker // Don't label anything below this directory.
596*2d543d20SAndroid Build Coastguard Worker fts_set(fts, ftsent, FTS_SKIP);
597*2d543d20SAndroid Build Coastguard Worker // but fall through and make sure we label the directory itself
598*2d543d20SAndroid Build Coastguard Worker }
599*2d543d20SAndroid Build Coastguard Worker /* fall through */
600*2d543d20SAndroid Build Coastguard Worker default:
601*2d543d20SAndroid Build Coastguard Worker error |= restorecon_sb(ftsent->fts_path, ftsent->fts_statp, nochange, verbose, seinfo, uid);
602*2d543d20SAndroid Build Coastguard Worker break;
603*2d543d20SAndroid Build Coastguard Worker }
604*2d543d20SAndroid Build Coastguard Worker }
605*2d543d20SAndroid Build Coastguard Worker
606*2d543d20SAndroid Build Coastguard Worker // Labeling successful. Write the partial match digests for subdirectories.
607*2d543d20SAndroid Build Coastguard Worker // TODO: Write the digest upon FTS_DP if no error occurs in its descents.
608*2d543d20SAndroid Build Coastguard Worker if (setrestoreconlast && !nochange && !error) {
609*2d543d20SAndroid Build Coastguard Worker current = head;
610*2d543d20SAndroid Build Coastguard Worker while (current != NULL) {
611*2d543d20SAndroid Build Coastguard Worker if (setxattr(current->path, RESTORECON_PARTIAL_MATCH_DIGEST, current->digest,
612*2d543d20SAndroid Build Coastguard Worker SHA1_HASH_SIZE, 0) < 0) {
613*2d543d20SAndroid Build Coastguard Worker selinux_log(SELINUX_ERROR,
614*2d543d20SAndroid Build Coastguard Worker "SELinux: setxattr failed: %s: %s\n",
615*2d543d20SAndroid Build Coastguard Worker current->path,
616*2d543d20SAndroid Build Coastguard Worker strerror(errno));
617*2d543d20SAndroid Build Coastguard Worker }
618*2d543d20SAndroid Build Coastguard Worker current = current->next;
619*2d543d20SAndroid Build Coastguard Worker }
620*2d543d20SAndroid Build Coastguard Worker }
621*2d543d20SAndroid Build Coastguard Worker
622*2d543d20SAndroid Build Coastguard Worker out:
623*2d543d20SAndroid Build Coastguard Worker sverrno = errno;
624*2d543d20SAndroid Build Coastguard Worker (void) fts_close(fts);
625*2d543d20SAndroid Build Coastguard Worker errno = sverrno;
626*2d543d20SAndroid Build Coastguard Worker cleanup:
627*2d543d20SAndroid Build Coastguard Worker free(pathdnamer);
628*2d543d20SAndroid Build Coastguard Worker free(pathname);
629*2d543d20SAndroid Build Coastguard Worker current = head;
630*2d543d20SAndroid Build Coastguard Worker while (current != NULL) {
631*2d543d20SAndroid Build Coastguard Worker struct dir_hash_node *next = current->next;
632*2d543d20SAndroid Build Coastguard Worker free(current->path);
633*2d543d20SAndroid Build Coastguard Worker free(current);
634*2d543d20SAndroid Build Coastguard Worker current = next;
635*2d543d20SAndroid Build Coastguard Worker }
636*2d543d20SAndroid Build Coastguard Worker return error;
637*2d543d20SAndroid Build Coastguard Worker oom:
638*2d543d20SAndroid Build Coastguard Worker sverrno = errno;
639*2d543d20SAndroid Build Coastguard Worker selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __FUNCTION__);
640*2d543d20SAndroid Build Coastguard Worker errno = sverrno;
641*2d543d20SAndroid Build Coastguard Worker error = -1;
642*2d543d20SAndroid Build Coastguard Worker goto cleanup;
643*2d543d20SAndroid Build Coastguard Worker realpatherr:
644*2d543d20SAndroid Build Coastguard Worker sverrno = errno;
645*2d543d20SAndroid Build Coastguard Worker selinux_log(SELINUX_ERROR, "SELinux: Could not get canonical path for %s restorecon: %s.\n",
646*2d543d20SAndroid Build Coastguard Worker pathname_orig, strerror(errno));
647*2d543d20SAndroid Build Coastguard Worker errno = sverrno;
648*2d543d20SAndroid Build Coastguard Worker error = -1;
649*2d543d20SAndroid Build Coastguard Worker goto cleanup;
650*2d543d20SAndroid Build Coastguard Worker }
651*2d543d20SAndroid Build Coastguard Worker
selinux_android_restorecon(const char * file,unsigned int flags)652*2d543d20SAndroid Build Coastguard Worker int selinux_android_restorecon(const char *file, unsigned int flags)
653*2d543d20SAndroid Build Coastguard Worker {
654*2d543d20SAndroid Build Coastguard Worker return selinux_android_restorecon_common(file, NULL, -1, flags);
655*2d543d20SAndroid Build Coastguard Worker }
656*2d543d20SAndroid Build Coastguard Worker
selinux_android_restorecon_pkgdir(const char * pkgdir,const char * seinfo,uid_t uid,unsigned int flags)657*2d543d20SAndroid Build Coastguard Worker int selinux_android_restorecon_pkgdir(const char *pkgdir,
658*2d543d20SAndroid Build Coastguard Worker const char *seinfo,
659*2d543d20SAndroid Build Coastguard Worker uid_t uid,
660*2d543d20SAndroid Build Coastguard Worker unsigned int flags)
661*2d543d20SAndroid Build Coastguard Worker {
662*2d543d20SAndroid Build Coastguard Worker return selinux_android_restorecon_common(pkgdir, seinfo, uid, flags | SELINUX_ANDROID_RESTORECON_DATADATA);
663*2d543d20SAndroid Build Coastguard Worker }
664*2d543d20SAndroid Build Coastguard Worker
665*2d543d20SAndroid Build Coastguard Worker
selinux_android_set_sehandle(const struct selabel_handle * hndl)666*2d543d20SAndroid Build Coastguard Worker void selinux_android_set_sehandle(const struct selabel_handle *hndl)
667*2d543d20SAndroid Build Coastguard Worker {
668*2d543d20SAndroid Build Coastguard Worker fc_sehandle = (struct selabel_handle *) hndl;
669*2d543d20SAndroid Build Coastguard Worker }
670*2d543d20SAndroid Build Coastguard Worker
selinux_android_load_policy()671*2d543d20SAndroid Build Coastguard Worker int selinux_android_load_policy()
672*2d543d20SAndroid Build Coastguard Worker {
673*2d543d20SAndroid Build Coastguard Worker selinux_log(SELINUX_ERROR, "selinux_android_load_policy is not implemented\n");
674*2d543d20SAndroid Build Coastguard Worker return -1;
675*2d543d20SAndroid Build Coastguard Worker }
676*2d543d20SAndroid Build Coastguard Worker
selinux_android_load_policy_from_fd(int fd,const char * description)677*2d543d20SAndroid Build Coastguard Worker int selinux_android_load_policy_from_fd(int fd __attribute__((unused)), const char *description __attribute__((unused)))
678*2d543d20SAndroid Build Coastguard Worker {
679*2d543d20SAndroid Build Coastguard Worker selinux_log(SELINUX_ERROR, "selinux_android_load_policy_from_fd is not implemented\n");
680*2d543d20SAndroid Build Coastguard Worker return -1;
681*2d543d20SAndroid Build Coastguard Worker }
682