Header And Logo

PostgreSQL
| The world's most advanced open source database.

Data Structures | Functions | Variables

seclabel.c File Reference

#include "postgres.h"
#include "access/genam.h"
#include "access/heapam.h"
#include "access/htup_details.h"
#include "catalog/catalog.h"
#include "catalog/indexing.h"
#include "catalog/pg_seclabel.h"
#include "catalog/pg_shseclabel.h"
#include "commands/seclabel.h"
#include "miscadmin.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/memutils.h"
#include "utils/rel.h"
#include "utils/tqual.h"
Include dependency graph for seclabel.c:

Go to the source code of this file.

Data Structures

struct  LabelProvider

Functions

Oid ExecSecLabelStmt (SecLabelStmt *stmt)
static char * GetSharedSecurityLabel (const ObjectAddress *object, const char *provider)
char * GetSecurityLabel (const ObjectAddress *object, const char *provider)
static void SetSharedSecurityLabel (const ObjectAddress *object, const char *provider, const char *label)
void SetSecurityLabel (const ObjectAddress *object, const char *provider, const char *label)
void DeleteSharedSecurityLabel (Oid objectId, Oid classId)
void DeleteSecurityLabel (const ObjectAddress *object)
void register_label_provider (const char *provider_name, check_object_relabel_type hook)

Variables

static Listlabel_provider_list = NIL

Function Documentation

void DeleteSecurityLabel ( const ObjectAddress object  ) 

Definition at line 450 of file seclabel.c.

References Anum_pg_seclabel_classoid, Anum_pg_seclabel_objoid, Anum_pg_seclabel_objsubid, Assert, BTEqualStrategyNumber, ObjectAddress::classId, DeleteSharedSecurityLabel(), heap_close, heap_open(), HeapTupleIsValid, Int32GetDatum, IsSharedRelation(), ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, RowExclusiveLock, ScanKeyInit(), SecLabelObjectIndexId, SecLabelRelationId, simple_heap_delete(), SnapshotNow, systable_beginscan(), systable_endscan(), systable_getnext(), and HeapTupleData::t_self.

Referenced by deleteOneObject().

{
    Relation    pg_seclabel;
    ScanKeyData skey[3];
    SysScanDesc scan;
    HeapTuple   oldtup;
    int         nkeys;

    /* Shared objects have their own security label catalog. */
    if (IsSharedRelation(object->classId))
    {
        Assert(object->objectSubId == 0);
        DeleteSharedSecurityLabel(object->objectId, object->classId);
        return;
    }

    ScanKeyInit(&skey[0],
                Anum_pg_seclabel_objoid,
                BTEqualStrategyNumber, F_OIDEQ,
                ObjectIdGetDatum(object->objectId));
    ScanKeyInit(&skey[1],
                Anum_pg_seclabel_classoid,
                BTEqualStrategyNumber, F_OIDEQ,
                ObjectIdGetDatum(object->classId));
    if (object->objectSubId != 0)
    {
        ScanKeyInit(&skey[2],
                    Anum_pg_seclabel_objsubid,
                    BTEqualStrategyNumber, F_INT4EQ,
                    Int32GetDatum(object->objectSubId));
        nkeys = 3;
    }
    else
        nkeys = 2;

    pg_seclabel = heap_open(SecLabelRelationId, RowExclusiveLock);

    scan = systable_beginscan(pg_seclabel, SecLabelObjectIndexId, true,
                              SnapshotNow, nkeys, skey);
    while (HeapTupleIsValid(oldtup = systable_getnext(scan)))
        simple_heap_delete(pg_seclabel, &oldtup->t_self);
    systable_endscan(scan);

    heap_close(pg_seclabel, RowExclusiveLock);
}

void DeleteSharedSecurityLabel ( Oid  objectId,
Oid  classId 
)
Oid ExecSecLabelStmt ( SecLabelStmt stmt  ) 

Definition at line 42 of file seclabel.c.

References check_object_ownership(), ereport, errcode(), errmsg(), ERROR, get_object_address(), GetUserId(), LabelProvider::hook, SecLabelStmt::label, lfirst, linitial, list_head(), lnext, NIL, NoLock, NULL, SecLabelStmt::objargs, OBJECT_COLUMN, ObjectAddress::objectId, SecLabelStmt::objname, SecLabelStmt::objtype, SecLabelStmt::provider, LabelProvider::provider_name, RelationData::rd_rel, relation_close(), RelationGetRelationName, RELKIND_COMPOSITE_TYPE, RELKIND_FOREIGN_TABLE, RELKIND_MATVIEW, RELKIND_RELATION, RELKIND_VIEW, SetSecurityLabel(), and ShareUpdateExclusiveLock.

Referenced by standard_ProcessUtility().

{
    LabelProvider *provider = NULL;
    ObjectAddress address;
    Relation    relation;
    ListCell   *lc;

    /*
     * Find the named label provider, or if none specified, check whether
     * there's exactly one, and if so use it.
     */
    if (stmt->provider == NULL)
    {
        if (label_provider_list == NIL)
            ereport(ERROR,
                    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                     errmsg("no security label providers have been loaded")));
        if (lnext(list_head(label_provider_list)) != NULL)
            ereport(ERROR,
                    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                     errmsg("must specify provider when multiple security label providers have been loaded")));
        provider = (LabelProvider *) linitial(label_provider_list);
    }
    else
    {
        foreach(lc, label_provider_list)
        {
            LabelProvider *lp = lfirst(lc);

            if (strcmp(stmt->provider, lp->provider_name) == 0)
            {
                provider = lp;
                break;
            }
        }
        if (provider == NULL)
            ereport(ERROR,
                    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                     errmsg("security label provider \"%s\" is not loaded",
                            stmt->provider)));
    }

    /*
     * Translate the parser representation which identifies this object into
     * an ObjectAddress. get_object_address() will throw an error if the
     * object does not exist, and will also acquire a lock on the target to
     * guard against concurrent modifications.
     */
    address = get_object_address(stmt->objtype, stmt->objname, stmt->objargs,
                                 &relation, ShareUpdateExclusiveLock, false);

    /* Require ownership of the target object. */
    check_object_ownership(GetUserId(), stmt->objtype, address,
                           stmt->objname, stmt->objargs, relation);

    /* Perform other integrity checks as needed. */
    switch (stmt->objtype)
    {
        case OBJECT_COLUMN:

            /*
             * Allow security labels only on columns of tables, views,
             * materialized views, composite types, and foreign tables (which
             * are the only relkinds for which pg_dump will dump labels).
             */
            if (relation->rd_rel->relkind != RELKIND_RELATION &&
                relation->rd_rel->relkind != RELKIND_VIEW &&
                relation->rd_rel->relkind != RELKIND_MATVIEW &&
                relation->rd_rel->relkind != RELKIND_COMPOSITE_TYPE &&
                relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE)
                ereport(ERROR,
                        (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                         errmsg("\"%s\" is not a table, view, composite type, or foreign table",
                                RelationGetRelationName(relation))));
            break;
        default:
            break;
    }

    /* Provider gets control here, may throw ERROR to veto new label. */
    (*provider->hook) (&address, stmt->label);

    /* Apply new label. */
    SetSecurityLabel(&address, provider->provider_name, stmt->label);

    /*
     * If get_object_address() opened the relation for us, we close it to keep
     * the reference count correct - but we retain any locks acquired by
     * get_object_address() until commit time, to guard against concurrent
     * activity.
     */
    if (relation != NULL)
        relation_close(relation, NoLock);

    return address.objectId;
}

char* GetSecurityLabel ( const ObjectAddress object,
const char *  provider 
)

Definition at line 192 of file seclabel.c.

References AccessShareLock, Anum_pg_seclabel_classoid, Anum_pg_seclabel_label, Anum_pg_seclabel_objoid, Anum_pg_seclabel_objsubid, Anum_pg_seclabel_provider, BTEqualStrategyNumber, ObjectAddress::classId, CStringGetTextDatum, GetSharedSecurityLabel(), heap_close, heap_getattr, heap_open(), HeapTupleIsValid, Int32GetDatum, IsSharedRelation(), ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, RelationGetDescr, ScanKeyInit(), SecLabelObjectIndexId, SecLabelRelationId, SnapshotNow, systable_beginscan(), systable_endscan(), systable_getnext(), and TextDatumGetCString.

Referenced by sepgsql_avc_check_perms(), sepgsql_avc_trusted_proc(), and sepgsql_get_label().

{
    Relation    pg_seclabel;
    ScanKeyData keys[4];
    SysScanDesc scan;
    HeapTuple   tuple;
    Datum       datum;
    bool        isnull;
    char       *seclabel = NULL;

    /* Shared objects have their own security label catalog. */
    if (IsSharedRelation(object->classId))
        return GetSharedSecurityLabel(object, provider);

    /* Must be an unshared object, so examine pg_seclabel. */
    ScanKeyInit(&keys[0],
                Anum_pg_seclabel_objoid,
                BTEqualStrategyNumber, F_OIDEQ,
                ObjectIdGetDatum(object->objectId));
    ScanKeyInit(&keys[1],
                Anum_pg_seclabel_classoid,
                BTEqualStrategyNumber, F_OIDEQ,
                ObjectIdGetDatum(object->classId));
    ScanKeyInit(&keys[2],
                Anum_pg_seclabel_objsubid,
                BTEqualStrategyNumber, F_INT4EQ,
                Int32GetDatum(object->objectSubId));
    ScanKeyInit(&keys[3],
                Anum_pg_seclabel_provider,
                BTEqualStrategyNumber, F_TEXTEQ,
                CStringGetTextDatum(provider));

    pg_seclabel = heap_open(SecLabelRelationId, AccessShareLock);

    scan = systable_beginscan(pg_seclabel, SecLabelObjectIndexId, true,
                              SnapshotNow, 4, keys);

    tuple = systable_getnext(scan);
    if (HeapTupleIsValid(tuple))
    {
        datum = heap_getattr(tuple, Anum_pg_seclabel_label,
                             RelationGetDescr(pg_seclabel), &isnull);
        if (!isnull)
            seclabel = TextDatumGetCString(datum);
    }
    systable_endscan(scan);

    heap_close(pg_seclabel, AccessShareLock);

    return seclabel;
}

static char* GetSharedSecurityLabel ( const ObjectAddress object,
const char *  provider 
) [static]

Definition at line 144 of file seclabel.c.

References AccessShareLock, Anum_pg_shseclabel_classoid, Anum_pg_shseclabel_label, Anum_pg_shseclabel_objoid, Anum_pg_shseclabel_provider, BTEqualStrategyNumber, ObjectAddress::classId, CStringGetTextDatum, heap_close, heap_getattr, heap_open(), HeapTupleIsValid, ObjectAddress::objectId, ObjectIdGetDatum, RelationGetDescr, ScanKeyInit(), SharedSecLabelObjectIndexId, SharedSecLabelRelationId, SnapshotNow, systable_beginscan(), systable_endscan(), systable_getnext(), and TextDatumGetCString.

Referenced by GetSecurityLabel().

{
    Relation    pg_shseclabel;
    ScanKeyData keys[3];
    SysScanDesc scan;
    HeapTuple   tuple;
    Datum       datum;
    bool        isnull;
    char       *seclabel = NULL;

    ScanKeyInit(&keys[0],
                Anum_pg_shseclabel_objoid,
                BTEqualStrategyNumber, F_OIDEQ,
                ObjectIdGetDatum(object->objectId));
    ScanKeyInit(&keys[1],
                Anum_pg_shseclabel_classoid,
                BTEqualStrategyNumber, F_OIDEQ,
                ObjectIdGetDatum(object->classId));
    ScanKeyInit(&keys[2],
                Anum_pg_shseclabel_provider,
                BTEqualStrategyNumber, F_TEXTEQ,
                CStringGetTextDatum(provider));

    pg_shseclabel = heap_open(SharedSecLabelRelationId, AccessShareLock);

    scan = systable_beginscan(pg_shseclabel, SharedSecLabelObjectIndexId, true,
                              SnapshotNow, 3, keys);

    tuple = systable_getnext(scan);
    if (HeapTupleIsValid(tuple))
    {
        datum = heap_getattr(tuple, Anum_pg_shseclabel_label,
                             RelationGetDescr(pg_shseclabel), &isnull);
        if (!isnull)
            seclabel = TextDatumGetCString(datum);
    }
    systable_endscan(scan);

    heap_close(pg_shseclabel, AccessShareLock);

    return seclabel;
}

void register_label_provider ( const char *  provider_name,
check_object_relabel_type  hook 
)

Definition at line 497 of file seclabel.c.

References LabelProvider::hook, lappend(), MemoryContextSwitchTo(), palloc(), LabelProvider::provider_name, pstrdup(), and TopMemoryContext.

Referenced by _PG_init().

{
    LabelProvider *provider;
    MemoryContext oldcxt;

    oldcxt = MemoryContextSwitchTo(TopMemoryContext);
    provider = palloc(sizeof(LabelProvider));
    provider->provider_name = pstrdup(provider_name);
    provider->hook = hook;
    label_provider_list = lappend(label_provider_list, provider);
    MemoryContextSwitchTo(oldcxt);
}

void SetSecurityLabel ( const ObjectAddress object,
const char *  provider,
const char *  label 
)

Definition at line 328 of file seclabel.c.

References Anum_pg_seclabel_classoid, Anum_pg_seclabel_label, Anum_pg_seclabel_objoid, Anum_pg_seclabel_objsubid, Anum_pg_seclabel_provider, BTEqualStrategyNumber, CatalogUpdateIndexes(), ObjectAddress::classId, CStringGetTextDatum, heap_close, heap_form_tuple(), heap_freetuple(), heap_modify_tuple(), heap_open(), HeapTupleIsValid, Int32GetDatum, IsSharedRelation(), NULL, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, RelationGetDescr, RowExclusiveLock, ScanKeyInit(), SecLabelObjectIndexId, SecLabelRelationId, SetSharedSecurityLabel(), simple_heap_delete(), simple_heap_insert(), simple_heap_update(), SnapshotNow, systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, and values.

Referenced by exec_object_restorecon(), ExecSecLabelStmt(), sepgsql_attribute_post_create(), sepgsql_database_post_create(), sepgsql_proc_post_create(), sepgsql_relation_post_create(), and sepgsql_schema_post_create().

{
    Relation    pg_seclabel;
    ScanKeyData keys[4];
    SysScanDesc scan;
    HeapTuple   oldtup;
    HeapTuple   newtup = NULL;
    Datum       values[Natts_pg_seclabel];
    bool        nulls[Natts_pg_seclabel];
    bool        replaces[Natts_pg_seclabel];

    /* Shared objects have their own security label catalog. */
    if (IsSharedRelation(object->classId))
    {
        SetSharedSecurityLabel(object, provider, label);
        return;
    }

    /* Prepare to form or update a tuple, if necessary. */
    memset(nulls, false, sizeof(nulls));
    memset(replaces, false, sizeof(replaces));
    values[Anum_pg_seclabel_objoid - 1] = ObjectIdGetDatum(object->objectId);
    values[Anum_pg_seclabel_classoid - 1] = ObjectIdGetDatum(object->classId);
    values[Anum_pg_seclabel_objsubid - 1] = Int32GetDatum(object->objectSubId);
    values[Anum_pg_seclabel_provider - 1] = CStringGetTextDatum(provider);
    if (label != NULL)
        values[Anum_pg_seclabel_label - 1] = CStringGetTextDatum(label);

    /* Use the index to search for a matching old tuple */
    ScanKeyInit(&keys[0],
                Anum_pg_seclabel_objoid,
                BTEqualStrategyNumber, F_OIDEQ,
                ObjectIdGetDatum(object->objectId));
    ScanKeyInit(&keys[1],
                Anum_pg_seclabel_classoid,
                BTEqualStrategyNumber, F_OIDEQ,
                ObjectIdGetDatum(object->classId));
    ScanKeyInit(&keys[2],
                Anum_pg_seclabel_objsubid,
                BTEqualStrategyNumber, F_INT4EQ,
                Int32GetDatum(object->objectSubId));
    ScanKeyInit(&keys[3],
                Anum_pg_seclabel_provider,
                BTEqualStrategyNumber, F_TEXTEQ,
                CStringGetTextDatum(provider));

    pg_seclabel = heap_open(SecLabelRelationId, RowExclusiveLock);

    scan = systable_beginscan(pg_seclabel, SecLabelObjectIndexId, true,
                              SnapshotNow, 4, keys);

    oldtup = systable_getnext(scan);
    if (HeapTupleIsValid(oldtup))
    {
        if (label == NULL)
            simple_heap_delete(pg_seclabel, &oldtup->t_self);
        else
        {
            replaces[Anum_pg_seclabel_label - 1] = true;
            newtup = heap_modify_tuple(oldtup, RelationGetDescr(pg_seclabel),
                                       values, nulls, replaces);
            simple_heap_update(pg_seclabel, &oldtup->t_self, newtup);
        }
    }
    systable_endscan(scan);

    /* If we didn't find an old tuple, insert a new one */
    if (newtup == NULL && label != NULL)
    {
        newtup = heap_form_tuple(RelationGetDescr(pg_seclabel),
                                 values, nulls);
        simple_heap_insert(pg_seclabel, newtup);
    }

    /* Update indexes, if necessary */
    if (newtup != NULL)
    {
        CatalogUpdateIndexes(pg_seclabel, newtup);
        heap_freetuple(newtup);
    }

    heap_close(pg_seclabel, RowExclusiveLock);
}

static void SetSharedSecurityLabel ( const ObjectAddress object,
const char *  provider,
const char *  label 
) [static]

Definition at line 249 of file seclabel.c.

References Anum_pg_shseclabel_classoid, Anum_pg_shseclabel_label, Anum_pg_shseclabel_objoid, Anum_pg_shseclabel_provider, BTEqualStrategyNumber, CatalogUpdateIndexes(), ObjectAddress::classId, CStringGetTextDatum, heap_close, heap_form_tuple(), heap_freetuple(), heap_modify_tuple(), heap_open(), HeapTupleIsValid, NULL, ObjectAddress::objectId, ObjectIdGetDatum, RelationGetDescr, RowExclusiveLock, ScanKeyInit(), SharedSecLabelObjectIndexId, SharedSecLabelRelationId, simple_heap_delete(), simple_heap_insert(), simple_heap_update(), SnapshotNow, systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, and values.

Referenced by SetSecurityLabel().

{
    Relation    pg_shseclabel;
    ScanKeyData keys[4];
    SysScanDesc scan;
    HeapTuple   oldtup;
    HeapTuple   newtup = NULL;
    Datum       values[Natts_pg_shseclabel];
    bool        nulls[Natts_pg_shseclabel];
    bool        replaces[Natts_pg_shseclabel];

    /* Prepare to form or update a tuple, if necessary. */
    memset(nulls, false, sizeof(nulls));
    memset(replaces, false, sizeof(replaces));
    values[Anum_pg_shseclabel_objoid - 1] = ObjectIdGetDatum(object->objectId);
    values[Anum_pg_shseclabel_classoid - 1] = ObjectIdGetDatum(object->classId);
    values[Anum_pg_shseclabel_provider - 1] = CStringGetTextDatum(provider);
    if (label != NULL)
        values[Anum_pg_shseclabel_label - 1] = CStringGetTextDatum(label);

    /* Use the index to search for a matching old tuple */
    ScanKeyInit(&keys[0],
                Anum_pg_shseclabel_objoid,
                BTEqualStrategyNumber, F_OIDEQ,
                ObjectIdGetDatum(object->objectId));
    ScanKeyInit(&keys[1],
                Anum_pg_shseclabel_classoid,
                BTEqualStrategyNumber, F_OIDEQ,
                ObjectIdGetDatum(object->classId));
    ScanKeyInit(&keys[2],
                Anum_pg_shseclabel_provider,
                BTEqualStrategyNumber, F_TEXTEQ,
                CStringGetTextDatum(provider));

    pg_shseclabel = heap_open(SharedSecLabelRelationId, RowExclusiveLock);

    scan = systable_beginscan(pg_shseclabel, SharedSecLabelObjectIndexId, true,
                              SnapshotNow, 3, keys);

    oldtup = systable_getnext(scan);
    if (HeapTupleIsValid(oldtup))
    {
        if (label == NULL)
            simple_heap_delete(pg_shseclabel, &oldtup->t_self);
        else
        {
            replaces[Anum_pg_shseclabel_label - 1] = true;
            newtup = heap_modify_tuple(oldtup, RelationGetDescr(pg_shseclabel),
                                       values, nulls, replaces);
            simple_heap_update(pg_shseclabel, &oldtup->t_self, newtup);
        }
    }
    systable_endscan(scan);

    /* If we didn't find an old tuple, insert a new one */
    if (newtup == NULL && label != NULL)
    {
        newtup = heap_form_tuple(RelationGetDescr(pg_shseclabel),
                                 values, nulls);
        simple_heap_insert(pg_shseclabel, newtup);
    }

    /* Update indexes, if necessary */
    if (newtup != NULL)
    {
        CatalogUpdateIndexes(pg_shseclabel, newtup);
        heap_freetuple(newtup);
    }

    heap_close(pg_shseclabel, RowExclusiveLock);
}


Variable Documentation

List* label_provider_list = NIL [static]

Definition at line 34 of file seclabel.c.