1 #include <unistd.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <errno.h> 5 #include <sys/types.h> 6 #include <sys/stat.h> 7 #include <fts.h> 8 #include <selinux/selinux.h> 9 #include <selinux/label.h> 10 #include <selinux/android.h> 11 12 static struct selabel_handle *sehandle; 13 static const char *progname; 14 static int nochange; 15 static int verbose; 16 17 static void usage(void) 18 { 19 fprintf(stderr, "usage: %s [-nrRv] pathname...\n", progname); 20 exit(1); 21 } 22 23 static int restore(const char *pathname, const struct stat *sb) 24 { 25 char *oldcontext, *newcontext; 26 27 if (lgetfilecon(pathname, &oldcontext) < 0) { 28 fprintf(stderr, "Could not get context of %s: %s\n", 29 pathname, strerror(errno)); 30 return -1; 31 } 32 if (selabel_lookup(sehandle, &newcontext, pathname, sb->st_mode) < 0) { 33 fprintf(stderr, "Could not lookup context for %s: %s\n", pathname, 34 strerror(errno)); 35 return -1; 36 } 37 if (strcmp(newcontext, "<<none>>") && 38 strcmp(oldcontext, newcontext)) { 39 if (verbose) 40 printf("Relabeling %s from %s to %s.\n", pathname, oldcontext, newcontext); 41 if (!nochange) { 42 if (lsetfilecon(pathname, newcontext) < 0) { 43 fprintf(stderr, "Could not label %s with %s: %s\n", 44 pathname, newcontext, strerror(errno)); 45 return -1; 46 } 47 } 48 } 49 freecon(oldcontext); 50 freecon(newcontext); 51 return 0; 52 } 53 54 int restorecon_main(int argc, char **argv) 55 { 56 int ch, recurse = 0, ftsflags = FTS_PHYSICAL; 57 int i = 0; 58 59 progname = argv[0]; 60 61 do { 62 ch = getopt(argc, argv, "nrRv"); 63 if (ch == EOF) 64 break; 65 switch (ch) { 66 case 'n': 67 nochange = 1; 68 break; 69 case 'r': 70 case 'R': 71 recurse = 1; 72 break; 73 case 'v': 74 verbose = 1; 75 break; 76 default: 77 usage(); 78 } 79 } while (1); 80 81 argc -= optind; 82 argv += optind; 83 if (!argc) 84 usage(); 85 86 sehandle = selinux_android_file_context_handle(); 87 88 if (!sehandle) { 89 fprintf(stderr, "Could not load file_contexts: %s\n", 90 strerror(errno)); 91 return -1; 92 } 93 94 if (recurse) { 95 FTS *fts; 96 FTSENT *ftsent; 97 fts = fts_open(argv, ftsflags, NULL); 98 if (!fts) { 99 fprintf(stderr, "Could not traverse filesystems (first was %s): %s\n", 100 argv[0], strerror(errno)); 101 return -1; 102 } 103 while ((ftsent = fts_read(fts))) { 104 switch (ftsent->fts_info) { 105 case FTS_DP: 106 break; 107 case FTS_DNR: 108 case FTS_ERR: 109 case FTS_NS: 110 fprintf(stderr, "Could not access %s: %s\n", ftsent->fts_path, 111 strerror(errno)); 112 fts_set(fts, ftsent, FTS_SKIP); 113 break; 114 default: 115 if (restore(ftsent->fts_path, ftsent->fts_statp) < 0) 116 fts_set(fts, ftsent, FTS_SKIP); 117 break; 118 } 119 } 120 } else { 121 int i, rc; 122 struct stat sb; 123 124 for (i = 0; i < argc; i++) { 125 rc = lstat(argv[i], &sb); 126 if (rc < 0) { 127 fprintf(stderr, "Could not stat %s: %s\n", argv[i], 128 strerror(errno)); 129 continue; 130 } 131 restore(argv[i], &sb); 132 } 133 } 134 135 return 0; 136 } 137