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