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