/* * Looks up a name in the selection or property mappings */ static int SELinuxAtomToSIDLookup(Atom atom, SELinuxObjectRec * obj, int map, int polymap) { const char *name = NameForAtom(atom); security_context_t ctx; int rc = Success; obj->poly = 1; /* Look in the mappings of names to contexts */ if (selabel_lookup_raw(label_hnd, &ctx, name, map) == 0) { obj->poly = 0; } else if (errno != ENOENT) { ErrorF("SELinux: a property label lookup failed!\n"); return BadValue; } else if (selabel_lookup_raw(label_hnd, &ctx, name, polymap) < 0) { ErrorF("SELinux: a property label lookup failed!\n"); return BadValue; } /* Get a SID for context */ if (avc_context_to_sid_raw(ctx, &obj->sid) < 0) { ErrorF("SELinux: a context_to_SID_raw call failed!\n"); rc = BadAlloc; } freecon(ctx); return rc; }
int label_mkdir( const char *path, mode_t mode) { /* Creates a directory and labels it according to the SELinux policy */ #ifdef HAVE_SELINUX int r; security_context_t fcon = NULL; if (use_selinux() && label_hnd) { if (path_is_absolute(path)) r = selabel_lookup_raw(label_hnd, &fcon, path, mode); else { char *newpath = NULL; if (!(newpath = path_make_absolute_cwd(path))) return -ENOMEM; r = selabel_lookup_raw(label_hnd, &fcon, newpath, mode); free(newpath); } if (r == 0) r = setfscreatecon(fcon); if (r < 0 && errno != ENOENT) { log_error("Failed to set security context %s for %s: %m", fcon, path); r = -errno; if (security_getenforce() == 1) goto finish; } } if ((r = mkdir(path, mode)) < 0) r = -errno; finish: if (use_selinux() && label_hnd) { setfscreatecon(NULL); freecon(fcon); } return r; #else return mkdir(path, mode); #endif }
void dpkg_selabel_set_context(const char *matchpath, const char *path, mode_t mode) { #ifdef WITH_LIBSELINUX security_context_t scontext = NULL; int ret; /* If SELinux is not enabled just do nothing. */ if (sehandle == NULL) return; /* * We use the _raw function variants here so that no translation * happens from computer to human readable forms, to avoid issues * when mcstransd has disappeared during the unpack process. */ /* Do nothing if we can't figure out what the context is, or if it has * no context; in which case the default context shall be applied. */ ret = selabel_lookup_raw(sehandle, &scontext, matchpath, mode & S_IFMT); if (ret == -1 || (ret == 0 && scontext == NULL)) return; ret = lsetfilecon_raw(path, scontext); if (ret < 0 && errno != ENOTSUP) ohshite(_("cannot set security context for file object '%s'"), path); freecon(scontext); #endif /* WITH_LIBSELINUX */ }
int mac_selinux_create_file_prepare(const char *path, mode_t mode) { #ifdef HAVE_SELINUX _cleanup_freecon_ char *filecon = NULL; int r; assert(path); if (!label_hnd) return 0; if (path_is_absolute(path)) r = selabel_lookup_raw(label_hnd, &filecon, path, mode); else { _cleanup_free_ char *newpath = NULL; r = path_make_absolute_cwd(path, &newpath); if (r < 0) return r; r = selabel_lookup_raw(label_hnd, &filecon, newpath, mode); } if (r < 0) { /* No context specified by the policy? Proceed without setting it. */ if (errno == ENOENT) return 0; log_enforcing("Failed to determine SELinux security context for %s: %m", path); } else { if (setfscreatecon_raw(filecon) >= 0) return 0; /* Success! */ log_enforcing("Failed to set SELinux security context %s for %s: %m", filecon, path); } if (security_getenforce() > 0) return -errno; #endif return 0; }
int mac_selinux_fix(const char *path, bool ignore_enoent, bool ignore_erofs) { #ifdef HAVE_SELINUX struct stat st; int r; assert(path); /* if mac_selinux_init() wasn't called before we are a NOOP */ if (!label_hnd) return 0; r = lstat(path, &st); if (r >= 0) { _cleanup_freecon_ char* fcon = NULL; r = selabel_lookup_raw(label_hnd, &fcon, path, st.st_mode); /* If there's no label to set, then exit without warning */ if (r < 0 && errno == ENOENT) return 0; if (r >= 0) { r = lsetfilecon_raw(path, fcon); /* If the FS doesn't support labels, then exit without warning */ if (r < 0 && errno == EOPNOTSUPP) return 0; } } if (r < 0) { /* Ignore ENOENT in some cases */ if (ignore_enoent && errno == ENOENT) return 0; if (ignore_erofs && errno == EROFS) return 0; log_enforcing("Unable to fix SELinux security context of %s: %m", path); if (security_getenforce() == 1) return -errno; } #endif return 0; }
int SELinuxExtensionToSID(const char *name, security_id_t * sid_rtn) { security_context_t ctx; /* Look in the mappings of extension names to contexts */ if (selabel_lookup_raw(label_hnd, &ctx, name, SELABEL_X_EXT) < 0) { ErrorF("SELinux: a property label lookup failed!\n"); return BadValue; } /* Get a SID for context */ if (avc_context_to_sid_raw(ctx, sid_rtn) < 0) { ErrorF("SELinux: a context_to_SID_raw call failed!\n"); freecon(ctx); return BadAlloc; } freecon(ctx); return Success; }
int selinux_util_label(const char *path) { int retval = 0; int enforce; struct stat st; security_context_t con; enforce = security_getenforce(); if (retval < 0) return retval; if (!hnd) return (enforce) ? -1 : 0; retval = lstat(path, &st); if (retval < 0) { if (errno == ENOENT) return 0; return (enforce) ? -1 : 0; } /* lookup the context */ retval = selabel_lookup_raw(hnd, &con, path, st.st_mode); if (retval < 0) { if (errno == ENOENT) return 0; return (enforce) ? -1 : 0; } /* apply the context */ retval = lsetfilecon(path, con); freecon(con); if (retval < 0) { if (errno == ENOENT) return 0; if (errno == ENOTSUP) return 0; return (enforce) ? -1 : 0; } return 0; }
int label_fix(const char *path, bool ignore_enoent) { int r = 0; #ifdef HAVE_SELINUX struct stat st; security_context_t fcon; if (!use_selinux() || !label_hnd) return 0; r = lstat(path, &st); if (r == 0) { r = selabel_lookup_raw(label_hnd, &fcon, path, st.st_mode); /* If there's no label to set, then exit without warning */ if (r < 0 && errno == ENOENT) return 0; if (r == 0) { r = setfilecon(path, fcon); freecon(fcon); /* If the FS doesn't support labels, then exit without warning */ if (r < 0 && errno == ENOTSUP) return 0; } } if (r < 0) { /* Ignore ENOENT in some cases */ if (ignore_enoent && errno == ENOENT) return 0; log_full(security_getenforce() == 1 ? LOG_ERR : LOG_DEBUG, "Unable to fix label of %s: %m", path); r = security_getenforce() == 1 ? -errno : 0; } #endif return r; }
/* * Looks up the SID corresponding to the given event type */ int SELinuxEventToSID(unsigned type, security_id_t sid_of_window, SELinuxObjectRec * sid_return) { const char *name = LookupEventName(type); security_id_t sid; security_context_t ctx; type &= 127; sid = SELinuxArrayGet(&arr_events, type); if (!sid) { /* Look in the mappings of event names to contexts */ if (selabel_lookup_raw(label_hnd, &ctx, name, SELABEL_X_EVENT) < 0) { ErrorF("SELinux: an event label lookup failed!\n"); return BadValue; } /* Get a SID for context */ if (avc_context_to_sid_raw(ctx, &sid) < 0) { ErrorF("SELinux: a context_to_SID_raw call failed!\n"); freecon(ctx); return BadAlloc; } freecon(ctx); /* Cache the SID value */ if (!SELinuxArraySet(&arr_events, type, sid)) return BadAlloc; } /* Perform a transition to obtain the final SID */ if (avc_compute_create(sid_of_window, sid, SECCLASS_X_EVENT, &sid_return->sid) < 0) { ErrorF("SELinux: a compute_create call failed!\n"); return BadValue; } return Success; }
int label_symlinkfile_set(const char *path) { int r = 0; #ifdef HAVE_SELINUX security_context_t filecon = NULL; if (!use_selinux() || !label_hnd) return 0; if ((r = selabel_lookup_raw(label_hnd, &filecon, path, S_IFLNK)) == 0) { if ((r = setfscreatecon(filecon)) < 0) { log_error("Failed to set SELinux file context on %s: %m", path); r = -errno; } freecon(filecon); } if (r < 0 && security_getenforce() == 0) r = 0; #endif return r; }
/* * exec_object_restorecon * * This routine is a helper called by sepgsql_restorecon; it set up * initial security labels of database objects within the supplied * catalog OID. */ static void exec_object_restorecon(struct selabel_handle *sehnd, Oid catalogId) { Relation rel; SysScanDesc sscan; HeapTuple tuple; char *database_name = get_database_name(MyDatabaseId); char *namespace_name; Oid namespace_id; char *relation_name; /* * Open the target catalog. We don't want to allow writable * accesses by other session during initial labeling. */ rel = heap_open(catalogId, AccessShareLock); sscan = systable_beginscan(rel, InvalidOid, false, SnapshotNow, 0, NULL); while (HeapTupleIsValid(tuple = systable_getnext(sscan))) { Form_pg_namespace nspForm; Form_pg_class relForm; Form_pg_attribute attForm; Form_pg_proc proForm; char *objname; int objtype = 1234; ObjectAddress object; security_context_t context; /* * The way to determine object name depends on object classes. * So, any branches set up `objtype', `objname' and `object' here. */ switch (catalogId) { case NamespaceRelationId: nspForm = (Form_pg_namespace) GETSTRUCT(tuple); objtype = SELABEL_DB_SCHEMA; objname = quote_object_name(database_name, NameStr(nspForm->nspname), NULL, NULL); object.classId = NamespaceRelationId; object.objectId = HeapTupleGetOid(tuple); object.objectSubId = 0; break; case RelationRelationId: relForm = (Form_pg_class) GETSTRUCT(tuple); if (relForm->relkind == RELKIND_RELATION) objtype = SELABEL_DB_TABLE; else if (relForm->relkind == RELKIND_SEQUENCE) objtype = SELABEL_DB_SEQUENCE; else if (relForm->relkind == RELKIND_VIEW) objtype = SELABEL_DB_VIEW; else continue; /* no need to assign security label */ namespace_name = get_namespace_name(relForm->relnamespace); objname = quote_object_name(database_name, namespace_name, NameStr(relForm->relname), NULL); pfree(namespace_name); object.classId = RelationRelationId; object.objectId = HeapTupleGetOid(tuple); object.objectSubId = 0; break; case AttributeRelationId: attForm = (Form_pg_attribute) GETSTRUCT(tuple); if (get_rel_relkind(attForm->attrelid) != RELKIND_RELATION) continue; /* no need to assign security label */ objtype = SELABEL_DB_COLUMN; namespace_id = get_rel_namespace(attForm->attrelid); namespace_name = get_namespace_name(namespace_id); relation_name = get_rel_name(attForm->attrelid); objname = quote_object_name(database_name, namespace_name, relation_name, NameStr(attForm->attname)); pfree(namespace_name); pfree(relation_name); object.classId = RelationRelationId; object.objectId = attForm->attrelid; object.objectSubId = attForm->attnum; break; case ProcedureRelationId: proForm = (Form_pg_proc) GETSTRUCT(tuple); objtype = SELABEL_DB_PROCEDURE; namespace_name = get_namespace_name(proForm->pronamespace); objname = quote_object_name(database_name, namespace_name, NameStr(proForm->proname), NULL); pfree(namespace_name); object.classId = ProcedureRelationId; object.objectId = HeapTupleGetOid(tuple); object.objectSubId = 0; break; default: elog(ERROR, "unexpected catalog id: %u", catalogId); objname = NULL; /* for compiler quiet */ break; } if (selabel_lookup_raw(sehnd, &context, objname, objtype) == 0) { PG_TRY(); { /* * Check SELinux permission to relabel the fetched object, * then do the actual relabeling. */ sepgsql_object_relabel(&object, context); SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, context); } PG_CATCH(); { freecon(context); PG_RE_THROW(); } PG_END_TRY(); freecon(context); } else if (errno == ENOENT) ereport(WARNING, (errmsg("SELinux: no initial label assigned for %s (type=%d), skipping", objname, objtype))); else ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), errmsg("SELinux: could not determine initial security label for %s (type=%d): %m", objname, objtype))); pfree(objname); } systable_endscan(sscan); heap_close(rel, NoLock); }
int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) { /* Binds a socket and label its file system object according to the SELinux policy */ #ifdef HAVE_SELINUX _cleanup_freecon_ char *fcon = NULL; const struct sockaddr_un *un; bool context_changed = false; char *path; int r; assert(fd >= 0); assert(addr); assert(addrlen >= sizeof(sa_family_t)); if (!label_hnd) goto skipped; /* Filter out non-local sockets */ if (addr->sa_family != AF_UNIX) goto skipped; /* Filter out anonymous sockets */ if (addrlen < offsetof(struct sockaddr_un, sun_path) + 1) goto skipped; /* Filter out abstract namespace sockets */ un = (const struct sockaddr_un*) addr; if (un->sun_path[0] == 0) goto skipped; path = strndupa(un->sun_path, addrlen - offsetof(struct sockaddr_un, sun_path)); if (path_is_absolute(path)) r = selabel_lookup_raw(label_hnd, &fcon, path, S_IFSOCK); else { _cleanup_free_ char *newpath = NULL; r = path_make_absolute_cwd(path, &newpath); if (r < 0) return r; r = selabel_lookup_raw(label_hnd, &fcon, newpath, S_IFSOCK); } if (r < 0) { /* No context specified by the policy? Proceed without setting it */ if (errno == ENOENT) goto skipped; log_enforcing("Failed to determine SELinux security context for %s: %m", path); if (security_getenforce() > 0) return -errno; } else { if (setfscreatecon_raw(fcon) < 0) { log_enforcing("Failed to set SELinux security context %s for %s: %m", fcon, path); if (security_getenforce() > 0) return -errno; } else context_changed = true; } r = bind(fd, addr, addrlen) < 0 ? -errno : 0; if (context_changed) setfscreatecon_raw(NULL); return r; skipped: #endif if (bind(fd, addr, addrlen) < 0) return -errno; return 0; }