static void cleanup(void) { if (global_state.sepolicy.file) { fclose(global_state.sepolicy.file); } if (global_state.sepolicy.sdb) { sepol_policydb_free(global_state.sepolicy.sdb); } if (global_state.sepolicy.pf) { sepol_policy_file_free(global_state.sepolicy.pf); } if (global_state.sepolicy.handle) { sepol_handle_destroy(global_state.sepolicy.handle); } ebitmap_destroy(&global_state.assert.set); int i; for (i = 0; i < SEHANDLE_CNT; i++) { struct selabel_handle *sehnd = global_state.sepolicy.sehnd[i]; if (sehnd) { selabel_close(sehnd); } } }
void label_finish(void) { #ifdef HAVE_SELINUX if (use_selinux() && label_hnd) selabel_close(label_hnd); #endif }
static void sehandle_fini(int close_status) { if (sehandle) { selabel_close(sehandle); sehandle = NULL; } if (close_status) { selinux_status_close(); } }
void mac_selinux_finish(void) { #ifdef HAVE_SELINUX if (!label_hnd) return; selabel_close(label_hnd); label_hnd = NULL; #endif }
int selinux_reload_policy(void) { if (!selinux_enabled) { return -1; } INFO("SELinux: Attempting to reload policy files\n"); if (selinux_android_reload_policy() == -1) { return -1; } if (sehandle) selabel_close(sehandle); if (sehandle_prop) selabel_close(sehandle_prop); selinux_init_all_handles(); return 0; }
void dpkg_selabel_close(void) { #ifdef WITH_LIBSELINUX if (sehandle == NULL) return; selinux_status_close(); selabel_close(sehandle); sehandle = NULL; #endif }
/* * Close the label handle * returns 1 on success, 0 if no selinux, negative on error */ int selinux_util_close(void) { int retval = 0; retval = is_selinux_enabled(); if (retval <= 0) return retval; if (hnd) { selabel_close(hnd); hnd = NULL; } return 0; }
/* Set fcon to the appropriate label for path and mode, or return -1. */ static int getContext(const char *newpath, mode_t mode, security_context_t *fcon) { #if HAVE_SELINUX_LABEL_H struct selabel_handle *handle = selabel_open(SELABEL_CTX_FILE, NULL, 0); int ret; if (handle == NULL) return -1; ret = selabel_lookup(handle, fcon, newpath, mode); selabel_close(handle); return ret; #else return matchpathcon(newpath, mode, fcon); #endif }
static int format_ext4(char *fs_blkdev, char *fs_mnt_point, bool crypt_footer) { uint64_t dev_sz; int fd, rc = 0; if ((fd = open(fs_blkdev, O_WRONLY)) < 0) { PERROR << "Cannot open block device"; return -1; } if ((ioctl(fd, BLKGETSIZE64, &dev_sz)) == -1) { PERROR << "Cannot get block device size"; close(fd); return -1; } struct selabel_handle *sehandle = selinux_android_file_context_handle(); if (!sehandle) { /* libselinux logs specific error */ LERROR << "Cannot initialize android file_contexts"; close(fd); return -1; } /* Format the partition using the calculated length */ reset_ext4fs_info(); info.len = (off64_t)dev_sz; if (crypt_footer) { info.len -= CRYPT_FOOTER_OFFSET; } /* Use make_ext4fs_internal to avoid wiping an already-wiped partition. */ rc = make_ext4fs_internal(fd, NULL, NULL, fs_mnt_point, 0, 0, 0, 0, 0, 0, sehandle, 0, 0, NULL, NULL, NULL); if (rc) { LERROR << "make_ext4fs returned " << rc; } close(fd); if (sehandle) { selabel_close(sehandle); } return rc; }
void dpkg_selabel_load(void) { #ifdef WITH_LIBSELINUX static int selinux_enabled = -1; if (selinux_enabled < 0) { int rc; /* Set selinux_enabled if it is not already set (singleton). */ selinux_enabled = (in_force(FORCE_SECURITY_MAC) && is_selinux_enabled() > 0); if (!selinux_enabled) return; /* Open the SELinux status notification channel, with fallback * enabled for older kernels. */ rc = selinux_status_open(1); if (rc < 0) ohshit(_("cannot open security status notification channel")); /* XXX: We could use selinux_set_callback() to redirect the * errors from the other SELinux calls, but that does not seem * worth it right now. */ } else if (selinux_enabled && selinux_status_updated()) { /* The SELinux policy got updated in the kernel, usually after * upgrading the package shipping it, we need to reload. */ selabel_close(sehandle); } else { /* SELinux is either disabled or it does not need a reload. */ return; } sehandle = selabel_open(SELABEL_CTX_FILE, NULL, 0); if (sehandle == NULL && security_getenforce() == 1) ohshite(_("cannot get security labeling handle")); #endif }
int main(int argc, char **argv) { int backend = 0, rc, opt, validate = 0; char *baseonly = NULL, *file = NULL, *digest = (char *)1; char **specfiles = NULL; unsigned char *sha1_digest = NULL; size_t i, num_specfiles; char cmd_buf[4096]; char *cmd_ptr; char *sha1_buf; struct selabel_handle *hnd; struct selinux_opt selabel_option[] = { { SELABEL_OPT_PATH, file }, { SELABEL_OPT_BASEONLY, baseonly }, { SELABEL_OPT_DIGEST, digest } }; if (argc < 3) usage(argv[0]); while ((opt = getopt(argc, argv, "ib:Bvf:")) > 0) { switch (opt) { case 'b': if (!strcasecmp(optarg, "file")) { backend = SELABEL_CTX_FILE; } else if (!strcmp(optarg, "media")) { backend = SELABEL_CTX_MEDIA; } else if (!strcmp(optarg, "x")) { backend = SELABEL_CTX_X; } else if (!strcmp(optarg, "db")) { backend = SELABEL_CTX_DB; } else if (!strcmp(optarg, "prop")) { backend = SELABEL_CTX_ANDROID_PROP; } else if (!strcmp(optarg, "service")) { backend = SELABEL_CTX_ANDROID_SERVICE; } else { fprintf(stderr, "Unknown backend: %s\n", optarg); usage(argv[0]); } break; case 'B': baseonly = (char *)1; break; case 'v': validate = 1; break; case 'i': digest = NULL; break; case 'f': file = optarg; break; default: usage(argv[0]); } } memset(cmd_buf, 0, sizeof(cmd_buf)); selabel_option[0].value = file; selabel_option[1].value = baseonly; selabel_option[2].value = digest; hnd = selabel_open(backend, selabel_option, 3); if (!hnd) { switch (errno) { case EOVERFLOW: fprintf(stderr, "ERROR Number of specfiles or specfile" " buffer caused an overflow.\n"); break; default: fprintf(stderr, "ERROR: selabel_open: %s\n", strerror(errno)); } return -1; } rc = selabel_digest(hnd, &sha1_digest, &digest_len, &specfiles, &num_specfiles); if (rc) { switch (errno) { case EINVAL: fprintf(stderr, "No digest available.\n"); break; default: fprintf(stderr, "selabel_digest ERROR: %s\n", strerror(errno)); } goto err; } sha1_buf = malloc(digest_len * 2 + 1); if (!sha1_buf) { fprintf(stderr, "Could not malloc buffer ERROR: %s\n", strerror(errno)); rc = -1; goto err; } printf("SHA1 digest: "); for (i = 0; i < digest_len; i++) sprintf(&(sha1_buf[i * 2]), "%02x", sha1_digest[i]); printf("%s\n", sha1_buf); printf("calculated using the following specfile(s):\n"); if (specfiles) { cmd_ptr = &cmd_buf[0]; sprintf(cmd_ptr, "/usr/bin/cat "); cmd_ptr = &cmd_buf[0] + strlen(cmd_buf); for (i = 0; i < num_specfiles; i++) { sprintf(cmd_ptr, "%s ", specfiles[i]); cmd_ptr += strlen(specfiles[i]) + 1; printf("%s\n", specfiles[i]); } sprintf(cmd_ptr, "| /usr/bin/openssl dgst -sha1 -hex"); if (validate) rc = run_check_digest(cmd_buf, sha1_buf); } free(sha1_buf); err: selabel_close(hnd); return rc; }
int svcmgr_handler(struct binder_state *bs, struct binder_transaction_data *txn, struct binder_io *msg, struct binder_io *reply) { struct svcinfo *si; uint16_t *s; size_t len; uint32_t handle; uint32_t strict_policy; int allow_isolated; //ALOGI("target=%p code=%d pid=%d uid=%d\n", // (void*) txn->target.ptr, txn->code, txn->sender_pid, txn->sender_euid); if (txn->target.ptr != BINDER_SERVICE_MANAGER) return -1; if (txn->code == PING_TRANSACTION) return 0; // Equivalent to Parcel::enforceInterface(), reading the RPC // header with the strict mode policy mask and the interface name. // Note that we ignore the strict_policy and don't propagate it // further (since we do no outbound RPCs anyway). strict_policy = bio_get_uint32(msg); s = bio_get_string16(msg, &len); if (s == NULL) { return -1; } if ((len != (sizeof(svcmgr_id) / 2)) || memcmp(svcmgr_id, s, sizeof(svcmgr_id))) { fprintf(stderr,"invalid id %s\n", str8(s, len)); return -1; } if (sehandle && selinux_status_updated() > 0) { struct selabel_handle *tmp_sehandle = selinux_android_service_context_handle(); if (tmp_sehandle) { selabel_close(sehandle); sehandle = tmp_sehandle; } } switch(txn->code) { case SVC_MGR_GET_SERVICE: case SVC_MGR_CHECK_SERVICE: s = bio_get_string16(msg, &len); if (s == NULL) { return -1; } handle = do_find_service(bs, s, len, txn->sender_euid, txn->sender_pid); if (!handle) break; bio_put_ref(reply, handle); return 0; case SVC_MGR_ADD_SERVICE: s = bio_get_string16(msg, &len); if (s == NULL) { return -1; } handle = bio_get_ref(msg); allow_isolated = bio_get_uint32(msg) ? 1 : 0; if (do_add_service(bs, s, len, handle, txn->sender_euid, allow_isolated, txn->sender_pid)) return -1; break; case SVC_MGR_LIST_SERVICES: { uint32_t n = bio_get_uint32(msg); if (!svc_can_list(txn->sender_pid, txn->sender_euid)) { ALOGE("list_service() uid=%d - PERMISSION DENIED\n", txn->sender_euid); return -1; } si = svclist; while ((n-- > 0) && si) si = si->next; if (si) { bio_put_string16(reply, si->name); return 0; } return -1; } default: ALOGE("unknown code %d\n", txn->code); return -1; } bio_put_uint32(reply, 0); return 0; }
Datum sepgsql_restorecon(PG_FUNCTION_ARGS) { struct selabel_handle *sehnd; struct selinux_opt seopts; /* * SELinux has to be enabled on the running platform. */ if (!sepgsql_is_enabled()) ereport(ERROR, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("sepgsql is not currently enabled"))); /* * Check DAC permission. Only superuser can set up initial * security labels, like root-user in filesystems */ if (!superuser()) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("SELinux: must be superuser to restore initial contexts"))); /* * Open selabel_lookup(3) stuff. It provides a set of mapping * between an initial security label and object class/name due * to the system setting. */ if (PG_ARGISNULL(0)) { seopts.type = SELABEL_OPT_UNUSED; seopts.value = NULL; } else { seopts.type = SELABEL_OPT_PATH; seopts.value = TextDatumGetCString(PG_GETARG_DATUM(0)); } sehnd = selabel_open(SELABEL_CTX_DB, &seopts, 1); if (!sehnd) ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), errmsg("SELinux: failed to initialize labeling handle: %m"))); PG_TRY(); { /* * Right now, we have no support labeling on the shared * database objects, such as database, role, or tablespace. */ exec_object_restorecon(sehnd, NamespaceRelationId); exec_object_restorecon(sehnd, RelationRelationId); exec_object_restorecon(sehnd, AttributeRelationId); exec_object_restorecon(sehnd, ProcedureRelationId); } PG_CATCH(); { selabel_close(sehnd); PG_RE_THROW(); } PG_END_TRY(); selabel_close(sehnd); PG_RETURN_BOOL(true); }
int main(int argc, char **argv) { struct stat sb; int opt, i = 0; const char *input_filename = NULL; int use_input_file = 0; char *buf = NULL; size_t buf_len; int recurse; /* Recursive descent. */ const char *base; int mass_relabel = 0, errors = 0; const char *ropts = "e:f:hilno:pqrsvFRW0"; const char *sopts = "c:de:f:hilno:pqr:svFR:W0"; const char *opts; memset(&r_opts, 0, sizeof(r_opts)); /* Initialize variables */ r_opts.progress = 0; r_opts.count = 0; r_opts.nfile = 0; r_opts.debug = 0; r_opts.change = 1; r_opts.verbose = 0; r_opts.logging = 0; r_opts.rootpath = NULL; r_opts.rootpathlen = 0; r_opts.outfile = NULL; r_opts.force = 0; r_opts.hard_links = 1; altpath = NULL; r_opts.progname = strdup(argv[0]); if (!r_opts.progname) { fprintf(stderr, "%s: Out of memory!\n", argv[0]); exit(-1); } base = basename(r_opts.progname); if (!strcmp(base, SETFILES)) { /* * setfiles: * Recursive descent, * Does not expand paths via realpath, * Aborts on errors during the file tree walk, * Try to track inode associations for conflict detection, * Does not follow mounts, * Validates all file contexts at init time. */ iamrestorecon = 0; recurse = 1; r_opts.expand_realpath = 0; r_opts.abort_on_error = 1; r_opts.add_assoc = 1; r_opts.fts_flags = FTS_PHYSICAL | FTS_XDEV; ctx_validate = 1; opts = sopts; } else { /* * restorecon: * No recursive descent unless -r/-R, * Expands paths via realpath, * Do not abort on errors during the file tree walk, * Do not try to track inode associations for conflict detection, * Follows mounts, * Does lazy validation of contexts upon use. */ if (strcmp(base, RESTORECON) && !r_opts.quiet) printf("Executed with an unrecognized name (%s), defaulting to %s behavior.\n", base, RESTORECON); iamrestorecon = 1; recurse = 0; r_opts.expand_realpath = 1; r_opts.abort_on_error = 0; r_opts.add_assoc = 0; r_opts.fts_flags = FTS_PHYSICAL; ctx_validate = 0; opts = ropts; /* restorecon only: silent exit if no SELinux. Allows unconditional execution by scripts. */ if (is_selinux_enabled() <= 0) exit(0); } /* This must happen before getopt. */ r_opts.nfile = exclude_non_seclabel_mounts(); if (iamrestorecon) opts = ropts; else opts = sopts; /* Process any options. */ while ((opt = getopt(argc, argv, opts)) > 0) { switch (opt) { case 'c': { FILE *policystream; if (iamrestorecon) usage(argv[0]); policyfile = optarg; policystream = fopen(policyfile, "r"); if (!policystream) { fprintf(stderr, "Error opening %s: %s\n", policyfile, strerror(errno)); exit(-1); } __fsetlocking(policystream, FSETLOCKING_BYCALLER); if (sepol_set_policydb_from_file(policystream) < 0) { fprintf(stderr, "Error reading policy %s: %s\n", policyfile, strerror(errno)); exit(-1); } fclose(policystream); ctx_validate = 1; break; } case 'e': remove_exclude(optarg); if (lstat(optarg, &sb) < 0 && errno != EACCES) { fprintf(stderr, "Can't stat exclude path \"%s\", %s - ignoring.\n", optarg, strerror(errno)); break; } if (add_exclude(optarg)) exit(-1); break; case 'f': use_input_file = 1; input_filename = optarg; break; case 'd': if (iamrestorecon) usage(argv[0]); r_opts.debug = 1; break; case 'i': r_opts.ignore_enoent = 1; break; case 'l': r_opts.logging = 1; break; case 'F': r_opts.force = 1; break; case 'n': r_opts.change = 0; break; case 'o': if (strcmp(optarg, "-") == 0) { r_opts.outfile = stdout; break; } r_opts.outfile = fopen(optarg, "w"); if (!r_opts.outfile) { fprintf(stderr, "Error opening %s: %s\n", optarg, strerror(errno)); usage(argv[0]); } __fsetlocking(r_opts.outfile, FSETLOCKING_BYCALLER); break; case 'q': r_opts.quiet = 1; break; case 'R': case 'r': if (iamrestorecon) { recurse = 1; break; } if (NULL != r_opts.rootpath) { fprintf(stderr, "%s: only one -r can be specified\n", argv[0]); exit(-1); } set_rootpath(optarg); break; case 's': use_input_file = 1; input_filename = "-"; r_opts.add_assoc = 0; break; case 'v': if (r_opts.progress) { fprintf(stderr, "Progress and Verbose mutually exclusive\n"); usage(argv[0]); } r_opts.verbose++; break; case 'p': if (r_opts.verbose) { fprintf(stderr, "Progress and Verbose mutually exclusive\n"); usage(argv[0]); } r_opts.progress++; break; case 'W': warn_no_match = 1; break; case '0': null_terminated = 1; break; case 'h': case '?': usage(argv[0]); } } for (i = optind; i < argc; i++) { if (!strcmp(argv[i], "/")) { mass_relabel = 1; if (r_opts.progress) r_opts.progress++; } } if (!iamrestorecon) { if (policyfile) { if (optind != (argc - 1)) usage(argv[0]); } else if (use_input_file) { if (optind != (argc - 1)) { /* Cannot mix with pathname arguments. */ usage(argv[0]); } } else { if (optind > (argc - 2)) usage(argv[0]); } /* Use our own invalid context checking function so that we can support either checking against the active policy or checking against a binary policy file. */ selinux_set_callback(SELINUX_CB_VALIDATE, (union selinux_callback)&canoncon); if (stat(argv[optind], &sb) < 0) { perror(argv[optind]); exit(-1); } if (!S_ISREG(sb.st_mode)) { fprintf(stderr, "%s: spec file %s is not a regular file.\n", argv[0], argv[optind]); exit(-1); } altpath = argv[optind]; optind++; } else if (argc == 1) usage(argv[0]); /* Load the file contexts configuration and check it. */ r_opts.selabel_opt_validate = (ctx_validate ? (char *)1 : NULL); r_opts.selabel_opt_path = altpath; if (nerr) exit(-1); restore_init(&r_opts); if (use_input_file) { FILE *f = stdin; ssize_t len; int delim; if (strcmp(input_filename, "-") != 0) f = fopen(input_filename, "r"); if (f == NULL) { fprintf(stderr, "Unable to open %s: %s\n", input_filename, strerror(errno)); usage(argv[0]); } __fsetlocking(f, FSETLOCKING_BYCALLER); delim = (null_terminated != 0) ? '\0' : '\n'; while ((len = getdelim(&buf, &buf_len, delim, f)) > 0) { buf[len - 1] = 0; if (!strcmp(buf, "/")) mass_relabel = 1; errors |= process_glob(buf, recurse) < 0; } if (strcmp(input_filename, "-") != 0) fclose(f); } else { for (i = optind; i < argc; i++) errors |= process_glob(argv[i], recurse) < 0; } maybe_audit_mass_relabel(mass_relabel, errors); if (warn_no_match) selabel_stats(r_opts.hnd); selabel_close(r_opts.hnd); restore_finish(); if (r_opts.outfile) fclose(r_opts.outfile); if (r_opts.progress && r_opts.count >= STAR_COUNT) printf("\n"); exit(errors ? -1: 0); }