blob: 5ef0ef1fb7bd98720c560f9d1f57282f74978ea2 [file] [log] [blame]
Stephen Smalley8290d102012-01-13 08:53:56 -05001#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}