18290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley#include <unistd.h> 28290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley#include <stdio.h> 38290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley#include <stdlib.h> 48290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley#include <errno.h> 58290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley#include <sys/types.h> 68290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley#include <sys/stat.h> 78290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley#include <fts.h> 88290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley#include <selinux/selinux.h> 98290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley#include <selinux/label.h> 108290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley 118290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley#define FCPATH "/file_contexts" 128290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley 138290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalleystatic struct selabel_handle *sehandle; 148290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalleystatic const char *progname; 158290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalleystatic int nochange; 168290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalleystatic int verbose; 178290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley 188290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalleystatic void usage(void) 198290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley{ 208290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley fprintf(stderr, "usage: %s [-f file_contexts] [-nrRv] pathname...\n", progname); 218290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley exit(1); 228290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley} 238290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley 248290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalleystatic int restore(const char *pathname, const struct stat *sb) 258290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley{ 268290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley char *oldcontext, *newcontext; 278290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley 288290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley if (lgetfilecon(pathname, &oldcontext) < 0) { 298290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley fprintf(stderr, "Could not get context of %s: %s\n", 308290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley pathname, strerror(errno)); 318290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley return -1; 328290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley } 338290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley if (selabel_lookup(sehandle, &newcontext, pathname, sb->st_mode) < 0) { 348290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley fprintf(stderr, "Could not lookup context for %s: %s\n", pathname, 358290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley strerror(errno)); 368290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley return -1; 378290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley } 388290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley if (strcmp(newcontext, "<<none>>") && 398290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley strcmp(oldcontext, newcontext)) { 408290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley if (verbose) 418290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley printf("Relabeling %s from %s to %s.\n", pathname, oldcontext, newcontext); 428290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley if (!nochange) { 438290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley if (lsetfilecon(pathname, newcontext) < 0) { 448290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley fprintf(stderr, "Could not label %s with %s: %s\n", 458290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley pathname, newcontext, strerror(errno)); 468290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley return -1; 478290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley } 488290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley } 498290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley } 508290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley freecon(oldcontext); 518290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley freecon(newcontext); 528290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley return 0; 538290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley} 548290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley 558290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalleyint restorecon_main(int argc, char **argv) 568290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley{ 578290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley struct selinux_opt seopts[] = { 588290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley { SELABEL_OPT_PATH, FCPATH } 598290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley }; 608290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley int ch, recurse = 0, ftsflags = FTS_PHYSICAL; 618290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley 628290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley progname = argv[0]; 638290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley 648290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley do { 658290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley ch = getopt(argc, argv, "f:nrRv"); 668290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley if (ch == EOF) 678290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley break; 688290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley switch (ch) { 698290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley case 'f': 708290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley seopts[0].value = optarg; 718290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley break; 728290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley case 'n': 738290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley nochange = 1; 748290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley break; 758290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley case 'r': 768290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley case 'R': 778290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley recurse = 1; 788290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley break; 798290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley case 'v': 808290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley verbose = 1; 818290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley break; 828290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley default: 838290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley usage(); 848290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley } 858290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley } while (1); 868290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley 878290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley argc -= optind; 888290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley argv += optind; 898290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley if (!argc) 908290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley usage(); 918290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley 928290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley sehandle = selabel_open(SELABEL_CTX_FILE, seopts, 1); 938290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley if (!sehandle) { 948290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley fprintf(stderr, "Could not load file contexts from %s: %s\n", seopts[0].value, 958290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley strerror(errno)); 968290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley return -1; 978290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley } 988290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley 998290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley if (recurse) { 1008290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley FTS *fts; 1018290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley FTSENT *ftsent; 1028290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley fts = fts_open(argv, ftsflags, NULL); 1038290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley if (!fts) { 1048290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley fprintf(stderr, "Could not traverse filesystems (first was %s): %s\n", 1058290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley argv[0], strerror(errno)); 1068290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley return -1; 1078290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley } 1088290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley while ((ftsent = fts_read(fts))) { 1098290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley switch (ftsent->fts_info) { 1108290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley case FTS_DP: 1118290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley break; 1128290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley case FTS_DNR: 1138290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley case FTS_ERR: 1148290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley case FTS_NS: 1158290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley fprintf(stderr, "Could not access %s: %s\n", ftsent->fts_path, 1168290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley strerror(errno)); 1178290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley fts_set(fts, ftsent, FTS_SKIP); 1188290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley break; 1198290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley default: 1208290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley if (restore(ftsent->fts_path, ftsent->fts_statp) < 0) 1218290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley fts_set(fts, ftsent, FTS_SKIP); 1228290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley break; 1238290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley } 1248290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley } 1258290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley } else { 1268290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley int i, rc; 1278290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley struct stat sb; 1288290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley 1298290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley for (i = 0; i < argc; i++) { 1308290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley rc = lstat(argv[i], &sb); 1318290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley if (rc < 0) { 1328290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley fprintf(stderr, "Could not stat %s: %s\n", argv[i], 1338290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley strerror(errno)); 1348290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley continue; 1358290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley } 1368290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley restore(argv[i], &sb); 1378290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley } 1388290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley } 1398290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley 1408290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley return 0; 1418290d1083ec7eee3f32265012f5d6be2774c4afcStephen Smalley} 142