Header And Logo

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

selinux.c

Go to the documentation of this file.
00001 /* -------------------------------------------------------------------------
00002  *
00003  * contrib/sepgsql/selinux.c
00004  *
00005  * Interactions between userspace and selinux in kernelspace,
00006  * using libselinux api.
00007  *
00008  * Copyright (c) 2010-2013, PostgreSQL Global Development Group
00009  *
00010  * -------------------------------------------------------------------------
00011  */
00012 #include "postgres.h"
00013 
00014 #include "lib/stringinfo.h"
00015 
00016 #include "sepgsql.h"
00017 
00018 /*
00019  * selinux_catalog
00020  *
00021  * This mapping table enables to translate the name of object classes and
00022  * access vectors to/from their own codes.
00023  * When we ask SELinux whether the required privileges are allowed or not,
00024  * we use security_compute_av(3). It needs us to represent object classes
00025  * and access vectors using 'external' codes defined in the security policy.
00026  * It is determinded in the runtime, not build time. So, it needs an internal
00027  * service to translate object class/access vectors which we want to check
00028  * into the code which kernel want to be given.
00029  */
00030 static struct
00031 {
00032     const char *class_name;
00033     uint16      class_code;
00034     struct
00035     {
00036         const char *av_name;
00037         uint32      av_code;
00038     }           av[32];
00039 }   selinux_catalog[] =
00040 
00041 {
00042     {
00043         "process", SEPG_CLASS_PROCESS,
00044         {
00045             {
00046                 "transition", SEPG_PROCESS__TRANSITION
00047             },
00048             {
00049                 "dyntransition", SEPG_PROCESS__DYNTRANSITION
00050             },
00051             {
00052                 "setcurrent", SEPG_PROCESS__SETCURRENT
00053             },
00054             {
00055                 NULL, 0UL
00056             }
00057         }
00058     },
00059     {
00060         "file", SEPG_CLASS_FILE,
00061         {
00062             {
00063                 "read", SEPG_FILE__READ
00064             },
00065             {
00066                 "write", SEPG_FILE__WRITE
00067             },
00068             {
00069                 "create", SEPG_FILE__CREATE
00070             },
00071             {
00072                 "getattr", SEPG_FILE__GETATTR
00073             },
00074             {
00075                 "unlink", SEPG_FILE__UNLINK
00076             },
00077             {
00078                 "rename", SEPG_FILE__RENAME
00079             },
00080             {
00081                 "append", SEPG_FILE__APPEND
00082             },
00083             {
00084                 NULL, 0UL
00085             }
00086         }
00087     },
00088     {
00089         "dir", SEPG_CLASS_DIR,
00090         {
00091             {
00092                 "read", SEPG_DIR__READ
00093             },
00094             {
00095                 "write", SEPG_DIR__WRITE
00096             },
00097             {
00098                 "create", SEPG_DIR__CREATE
00099             },
00100             {
00101                 "getattr", SEPG_DIR__GETATTR
00102             },
00103             {
00104                 "unlink", SEPG_DIR__UNLINK
00105             },
00106             {
00107                 "rename", SEPG_DIR__RENAME
00108             },
00109             {
00110                 "search", SEPG_DIR__SEARCH
00111             },
00112             {
00113                 "add_name", SEPG_DIR__ADD_NAME
00114             },
00115             {
00116                 "remove_name", SEPG_DIR__REMOVE_NAME
00117             },
00118             {
00119                 "rmdir", SEPG_DIR__RMDIR
00120             },
00121             {
00122                 "reparent", SEPG_DIR__REPARENT
00123             },
00124             {
00125                 NULL, 0UL
00126             }
00127         }
00128     },
00129     {
00130         "lnk_file", SEPG_CLASS_LNK_FILE,
00131         {
00132             {
00133                 "read", SEPG_LNK_FILE__READ
00134             },
00135             {
00136                 "write", SEPG_LNK_FILE__WRITE
00137             },
00138             {
00139                 "create", SEPG_LNK_FILE__CREATE
00140             },
00141             {
00142                 "getattr", SEPG_LNK_FILE__GETATTR
00143             },
00144             {
00145                 "unlink", SEPG_LNK_FILE__UNLINK
00146             },
00147             {
00148                 "rename", SEPG_LNK_FILE__RENAME
00149             },
00150             {
00151                 NULL, 0UL
00152             }
00153         }
00154     },
00155     {
00156         "chr_file", SEPG_CLASS_CHR_FILE,
00157         {
00158             {
00159                 "read", SEPG_CHR_FILE__READ
00160             },
00161             {
00162                 "write", SEPG_CHR_FILE__WRITE
00163             },
00164             {
00165                 "create", SEPG_CHR_FILE__CREATE
00166             },
00167             {
00168                 "getattr", SEPG_CHR_FILE__GETATTR
00169             },
00170             {
00171                 "unlink", SEPG_CHR_FILE__UNLINK
00172             },
00173             {
00174                 "rename", SEPG_CHR_FILE__RENAME
00175             },
00176             {
00177                 NULL, 0UL
00178             }
00179         }
00180     },
00181     {
00182         "blk_file", SEPG_CLASS_BLK_FILE,
00183         {
00184             {
00185                 "read", SEPG_BLK_FILE__READ
00186             },
00187             {
00188                 "write", SEPG_BLK_FILE__WRITE
00189             },
00190             {
00191                 "create", SEPG_BLK_FILE__CREATE
00192             },
00193             {
00194                 "getattr", SEPG_BLK_FILE__GETATTR
00195             },
00196             {
00197                 "unlink", SEPG_BLK_FILE__UNLINK
00198             },
00199             {
00200                 "rename", SEPG_BLK_FILE__RENAME
00201             },
00202             {
00203                 NULL, 0UL
00204             }
00205         }
00206     },
00207     {
00208         "sock_file", SEPG_CLASS_SOCK_FILE,
00209         {
00210             {
00211                 "read", SEPG_SOCK_FILE__READ
00212             },
00213             {
00214                 "write", SEPG_SOCK_FILE__WRITE
00215             },
00216             {
00217                 "create", SEPG_SOCK_FILE__CREATE
00218             },
00219             {
00220                 "getattr", SEPG_SOCK_FILE__GETATTR
00221             },
00222             {
00223                 "unlink", SEPG_SOCK_FILE__UNLINK
00224             },
00225             {
00226                 "rename", SEPG_SOCK_FILE__RENAME
00227             },
00228             {
00229                 NULL, 0UL
00230             }
00231         }
00232     },
00233     {
00234         "fifo_file", SEPG_CLASS_FIFO_FILE,
00235         {
00236             {
00237                 "read", SEPG_FIFO_FILE__READ
00238             },
00239             {
00240                 "write", SEPG_FIFO_FILE__WRITE
00241             },
00242             {
00243                 "create", SEPG_FIFO_FILE__CREATE
00244             },
00245             {
00246                 "getattr", SEPG_FIFO_FILE__GETATTR
00247             },
00248             {
00249                 "unlink", SEPG_FIFO_FILE__UNLINK
00250             },
00251             {
00252                 "rename", SEPG_FIFO_FILE__RENAME
00253             },
00254             {
00255                 NULL, 0UL
00256             }
00257         }
00258     },
00259     {
00260         "db_database", SEPG_CLASS_DB_DATABASE,
00261         {
00262             {
00263                 "create", SEPG_DB_DATABASE__CREATE
00264             },
00265             {
00266                 "drop", SEPG_DB_DATABASE__DROP
00267             },
00268             {
00269                 "getattr", SEPG_DB_DATABASE__GETATTR
00270             },
00271             {
00272                 "setattr", SEPG_DB_DATABASE__SETATTR
00273             },
00274             {
00275                 "relabelfrom", SEPG_DB_DATABASE__RELABELFROM
00276             },
00277             {
00278                 "relabelto", SEPG_DB_DATABASE__RELABELTO
00279             },
00280             {
00281                 "access", SEPG_DB_DATABASE__ACCESS
00282             },
00283             {
00284                 "load_module", SEPG_DB_DATABASE__LOAD_MODULE
00285             },
00286             {
00287                 NULL, 0UL
00288             },
00289         }
00290     },
00291     {
00292         "db_schema", SEPG_CLASS_DB_SCHEMA,
00293         {
00294             {
00295                 "create", SEPG_DB_SCHEMA__CREATE
00296             },
00297             {
00298                 "drop", SEPG_DB_SCHEMA__DROP
00299             },
00300             {
00301                 "getattr", SEPG_DB_SCHEMA__GETATTR
00302             },
00303             {
00304                 "setattr", SEPG_DB_SCHEMA__SETATTR
00305             },
00306             {
00307                 "relabelfrom", SEPG_DB_SCHEMA__RELABELFROM
00308             },
00309             {
00310                 "relabelto", SEPG_DB_SCHEMA__RELABELTO
00311             },
00312             {
00313                 "search", SEPG_DB_SCHEMA__SEARCH
00314             },
00315             {
00316                 "add_name", SEPG_DB_SCHEMA__ADD_NAME
00317             },
00318             {
00319                 "remove_name", SEPG_DB_SCHEMA__REMOVE_NAME
00320             },
00321             {
00322                 NULL, 0UL
00323             },
00324         }
00325     },
00326     {
00327         "db_table", SEPG_CLASS_DB_TABLE,
00328         {
00329             {
00330                 "create", SEPG_DB_TABLE__CREATE
00331             },
00332             {
00333                 "drop", SEPG_DB_TABLE__DROP
00334             },
00335             {
00336                 "getattr", SEPG_DB_TABLE__GETATTR
00337             },
00338             {
00339                 "setattr", SEPG_DB_TABLE__SETATTR
00340             },
00341             {
00342                 "relabelfrom", SEPG_DB_TABLE__RELABELFROM
00343             },
00344             {
00345                 "relabelto", SEPG_DB_TABLE__RELABELTO
00346             },
00347             {
00348                 "select", SEPG_DB_TABLE__SELECT
00349             },
00350             {
00351                 "update", SEPG_DB_TABLE__UPDATE
00352             },
00353             {
00354                 "insert", SEPG_DB_TABLE__INSERT
00355             },
00356             {
00357                 "delete", SEPG_DB_TABLE__DELETE
00358             },
00359             {
00360                 "lock", SEPG_DB_TABLE__LOCK
00361             },
00362             {
00363                 NULL, 0UL
00364             },
00365         }
00366     },
00367     {
00368         "db_sequence", SEPG_CLASS_DB_SEQUENCE,
00369         {
00370             {
00371                 "create", SEPG_DB_SEQUENCE__CREATE
00372             },
00373             {
00374                 "drop", SEPG_DB_SEQUENCE__DROP
00375             },
00376             {
00377                 "getattr", SEPG_DB_SEQUENCE__GETATTR
00378             },
00379             {
00380                 "setattr", SEPG_DB_SEQUENCE__SETATTR
00381             },
00382             {
00383                 "relabelfrom", SEPG_DB_SEQUENCE__RELABELFROM
00384             },
00385             {
00386                 "relabelto", SEPG_DB_SEQUENCE__RELABELTO
00387             },
00388             {
00389                 "get_value", SEPG_DB_SEQUENCE__GET_VALUE
00390             },
00391             {
00392                 "next_value", SEPG_DB_SEQUENCE__NEXT_VALUE
00393             },
00394             {
00395                 "set_value", SEPG_DB_SEQUENCE__SET_VALUE
00396             },
00397             {
00398                 NULL, 0UL
00399             },
00400         }
00401     },
00402     {
00403         "db_procedure", SEPG_CLASS_DB_PROCEDURE,
00404         {
00405             {
00406                 "create", SEPG_DB_PROCEDURE__CREATE
00407             },
00408             {
00409                 "drop", SEPG_DB_PROCEDURE__DROP
00410             },
00411             {
00412                 "getattr", SEPG_DB_PROCEDURE__GETATTR
00413             },
00414             {
00415                 "setattr", SEPG_DB_PROCEDURE__SETATTR
00416             },
00417             {
00418                 "relabelfrom", SEPG_DB_PROCEDURE__RELABELFROM
00419             },
00420             {
00421                 "relabelto", SEPG_DB_PROCEDURE__RELABELTO
00422             },
00423             {
00424                 "execute", SEPG_DB_PROCEDURE__EXECUTE
00425             },
00426             {
00427                 "entrypoint", SEPG_DB_PROCEDURE__ENTRYPOINT
00428             },
00429             {
00430                 "install", SEPG_DB_PROCEDURE__INSTALL
00431             },
00432             {
00433                 NULL, 0UL
00434             },
00435         }
00436     },
00437     {
00438         "db_column", SEPG_CLASS_DB_COLUMN,
00439         {
00440             {
00441                 "create", SEPG_DB_COLUMN__CREATE
00442             },
00443             {
00444                 "drop", SEPG_DB_COLUMN__DROP
00445             },
00446             {
00447                 "getattr", SEPG_DB_COLUMN__GETATTR
00448             },
00449             {
00450                 "setattr", SEPG_DB_COLUMN__SETATTR
00451             },
00452             {
00453                 "relabelfrom", SEPG_DB_COLUMN__RELABELFROM
00454             },
00455             {
00456                 "relabelto", SEPG_DB_COLUMN__RELABELTO
00457             },
00458             {
00459                 "select", SEPG_DB_COLUMN__SELECT
00460             },
00461             {
00462                 "update", SEPG_DB_COLUMN__UPDATE
00463             },
00464             {
00465                 "insert", SEPG_DB_COLUMN__INSERT
00466             },
00467             {
00468                 NULL, 0UL
00469             },
00470         }
00471     },
00472     {
00473         "db_tuple", SEPG_CLASS_DB_TUPLE,
00474         {
00475             {
00476                 "relabelfrom", SEPG_DB_TUPLE__RELABELFROM
00477             },
00478             {
00479                 "relabelto", SEPG_DB_TUPLE__RELABELTO
00480             },
00481             {
00482                 "select", SEPG_DB_TUPLE__SELECT
00483             },
00484             {
00485                 "update", SEPG_DB_TUPLE__UPDATE
00486             },
00487             {
00488                 "insert", SEPG_DB_TUPLE__INSERT
00489             },
00490             {
00491                 "delete", SEPG_DB_TUPLE__DELETE
00492             },
00493             {
00494                 NULL, 0UL
00495             },
00496         }
00497     },
00498     {
00499         "db_blob", SEPG_CLASS_DB_BLOB,
00500         {
00501             {
00502                 "create", SEPG_DB_BLOB__CREATE
00503             },
00504             {
00505                 "drop", SEPG_DB_BLOB__DROP
00506             },
00507             {
00508                 "getattr", SEPG_DB_BLOB__GETATTR
00509             },
00510             {
00511                 "setattr", SEPG_DB_BLOB__SETATTR
00512             },
00513             {
00514                 "relabelfrom", SEPG_DB_BLOB__RELABELFROM
00515             },
00516             {
00517                 "relabelto", SEPG_DB_BLOB__RELABELTO
00518             },
00519             {
00520                 "read", SEPG_DB_BLOB__READ
00521             },
00522             {
00523                 "write", SEPG_DB_BLOB__WRITE
00524             },
00525             {
00526                 "import", SEPG_DB_BLOB__IMPORT
00527             },
00528             {
00529                 "export", SEPG_DB_BLOB__EXPORT
00530             },
00531             {
00532                 NULL, 0UL
00533             },
00534         }
00535     },
00536     {
00537         "db_language", SEPG_CLASS_DB_LANGUAGE,
00538         {
00539             {
00540                 "create", SEPG_DB_LANGUAGE__CREATE
00541             },
00542             {
00543                 "drop", SEPG_DB_LANGUAGE__DROP
00544             },
00545             {
00546                 "getattr", SEPG_DB_LANGUAGE__GETATTR
00547             },
00548             {
00549                 "setattr", SEPG_DB_LANGUAGE__SETATTR
00550             },
00551             {
00552                 "relabelfrom", SEPG_DB_LANGUAGE__RELABELFROM
00553             },
00554             {
00555                 "relabelto", SEPG_DB_LANGUAGE__RELABELTO
00556             },
00557             {
00558                 "implement", SEPG_DB_LANGUAGE__IMPLEMENT
00559             },
00560             {
00561                 "execute", SEPG_DB_LANGUAGE__EXECUTE
00562             },
00563             {
00564                 NULL, 0UL
00565             },
00566         }
00567     },
00568     {
00569         "db_view", SEPG_CLASS_DB_VIEW,
00570         {
00571             {
00572                 "create", SEPG_DB_VIEW__CREATE
00573             },
00574             {
00575                 "drop", SEPG_DB_VIEW__DROP
00576             },
00577             {
00578                 "getattr", SEPG_DB_VIEW__GETATTR
00579             },
00580             {
00581                 "setattr", SEPG_DB_VIEW__SETATTR
00582             },
00583             {
00584                 "relabelfrom", SEPG_DB_VIEW__RELABELFROM
00585             },
00586             {
00587                 "relabelto", SEPG_DB_VIEW__RELABELTO
00588             },
00589             {
00590                 "expand", SEPG_DB_VIEW__EXPAND
00591             },
00592             {
00593                 NULL, 0UL
00594             },
00595         }
00596     },
00597 };
00598 
00599 /*
00600  * sepgsql_mode
00601  *
00602  * SEPGSQL_MODE_DISABLED: Disabled on runtime
00603  * SEPGSQL_MODE_DEFAULT: Same as system settings
00604  * SEPGSQL_MODE_PERMISSIVE: Always permissive mode
00605  * SEPGSQL_MODE_INTERNAL: Same as permissive, except for no audit logs
00606  */
00607 static int  sepgsql_mode = SEPGSQL_MODE_INTERNAL;
00608 
00609 /*
00610  * sepgsql_is_enabled
00611  */
00612 bool
00613 sepgsql_is_enabled(void)
00614 {
00615     return (sepgsql_mode != SEPGSQL_MODE_DISABLED ? true : false);
00616 }
00617 
00618 /*
00619  * sepgsql_get_mode
00620  */
00621 int
00622 sepgsql_get_mode(void)
00623 {
00624     return sepgsql_mode;
00625 }
00626 
00627 /*
00628  * sepgsql_set_mode
00629  */
00630 int
00631 sepgsql_set_mode(int new_mode)
00632 {
00633     int         old_mode = sepgsql_mode;
00634 
00635     sepgsql_mode = new_mode;
00636 
00637     return old_mode;
00638 }
00639 
00640 /*
00641  * sepgsql_getenforce
00642  *
00643  * It returns whether the current working mode tries to enforce access
00644  * control decision, or not. It shall be enforced when sepgsql_mode is
00645  * SEPGSQL_MODE_DEFAULT and system is running in enforcing mode.
00646  */
00647 bool
00648 sepgsql_getenforce(void)
00649 {
00650     if (sepgsql_mode == SEPGSQL_MODE_DEFAULT &&
00651         selinux_status_getenforce() > 0)
00652         return true;
00653 
00654     return false;
00655 }
00656 
00657 /*
00658  * sepgsql_audit_log
00659  *
00660  * It generates a security audit record. In the default, it writes out
00661  * audit records into standard PG's logfile. It also allows to set up
00662  * external audit log receiver, such as auditd in Linux, using the
00663  * sepgsql_audit_hook.
00664  *
00665  * SELinux can control what should be audited and should not using
00666  * "auditdeny" and "auditallow" rules in the security policy. In the
00667  * default, all the access violations are audited, and all the access
00668  * allowed are not audited. But we can set up the security policy, so
00669  * we can have exceptions. So, it is necessary to follow the suggestion
00670  * come from the security policy. (av_decision.auditallow and auditdeny)
00671  *
00672  * Security audit is an important feature, because it enables us to check
00673  * what was happen if we have a security incident. In fact, ISO/IEC15408
00674  * defines several security functionalities for audit features.
00675  */
00676 void
00677 sepgsql_audit_log(bool denied,
00678                   const char *scontext,
00679                   const char *tcontext,
00680                   uint16 tclass,
00681                   uint32 audited,
00682                   const char *audit_name)
00683 {
00684     StringInfoData buf;
00685     const char *class_name;
00686     const char *av_name;
00687     int         i;
00688 
00689     /* lookup name of the object class */
00690     Assert(tclass < SEPG_CLASS_MAX);
00691     class_name = selinux_catalog[tclass].class_name;
00692 
00693     /* lookup name of the permissions */
00694     initStringInfo(&buf);
00695     appendStringInfo(&buf, "%s {",
00696                      (denied ? "denied" : "allowed"));
00697     for (i = 0; selinux_catalog[tclass].av[i].av_name; i++)
00698     {
00699         if (audited & (1UL << i))
00700         {
00701             av_name = selinux_catalog[tclass].av[i].av_name;
00702             appendStringInfo(&buf, " %s", av_name);
00703         }
00704     }
00705     appendStringInfo(&buf, " }");
00706 
00707     /*
00708      * Call external audit module, if loaded
00709      */
00710     appendStringInfo(&buf, " scontext=%s tcontext=%s tclass=%s",
00711                      scontext, tcontext, class_name);
00712     if (audit_name)
00713         appendStringInfo(&buf, " name=\"%s\"", audit_name);
00714 
00715     ereport(LOG, (errmsg("SELinux: %s", buf.data)));
00716 }
00717 
00718 /*
00719  * sepgsql_compute_avd
00720  *
00721  * It actually asks SELinux what permissions are allowed on a pair of
00722  * the security contexts and object class. It also returns what permissions
00723  * should be audited on access violation or allowed.
00724  * In most cases, subject's security context (scontext) is a client, and
00725  * target security context (tcontext) is a database object.
00726  *
00727  * The access control decision shall be set on the given av_decision.
00728  * The av_decision.allowed has a bitmask of SEPG_<class>__<perms>
00729  * to suggest a set of allowed actions in this object class.
00730  */
00731 void
00732 sepgsql_compute_avd(const char *scontext,
00733                     const char *tcontext,
00734                     uint16 tclass,
00735                     struct av_decision * avd)
00736 {
00737     const char *tclass_name;
00738     security_class_t tclass_ex;
00739     struct av_decision avd_ex;
00740     int         i,
00741                 deny_unknown = security_deny_unknown();
00742 
00743     /* Get external code of the object class */
00744     Assert(tclass < SEPG_CLASS_MAX);
00745     Assert(tclass == selinux_catalog[tclass].class_code);
00746 
00747     tclass_name = selinux_catalog[tclass].class_name;
00748     tclass_ex = string_to_security_class(tclass_name);
00749 
00750     if (tclass_ex == 0)
00751     {
00752         /*
00753          * If the current security policy does not support permissions
00754          * corresponding to database objects, we fill up them with dummy data.
00755          * If security_deny_unknown() returns positive value, undefined
00756          * permissions should be denied. Otherwise, allowed
00757          */
00758         avd->allowed = (security_deny_unknown() > 0 ? 0 : ~0);
00759         avd->auditallow = 0U;
00760         avd->auditdeny = ~0U;
00761         avd->flags = 0;
00762 
00763         return;
00764     }
00765 
00766     /*
00767      * Ask SELinux what is allowed set of permissions on a pair of the
00768      * security contexts and the given object class.
00769      */
00770     if (security_compute_av_flags_raw((security_context_t) scontext,
00771                                       (security_context_t) tcontext,
00772                                       tclass_ex, 0, &avd_ex) < 0)
00773         ereport(ERROR,
00774                 (errcode(ERRCODE_INTERNAL_ERROR),
00775                  errmsg("SELinux could not compute av_decision: "
00776                         "scontext=%s tcontext=%s tclass=%s: %m",
00777                         scontext, tcontext, tclass_name)));
00778 
00779     /*
00780      * SELinux returns its access control decision as a set of permissions
00781      * represented in external code which depends on run-time environment. So,
00782      * we need to translate it to the internal representation before returning
00783      * results for the caller.
00784      */
00785     memset(avd, 0, sizeof(struct av_decision));
00786 
00787     for (i = 0; selinux_catalog[tclass].av[i].av_name; i++)
00788     {
00789         access_vector_t av_code_ex;
00790         const char *av_name = selinux_catalog[tclass].av[i].av_name;
00791         uint32      av_code = selinux_catalog[tclass].av[i].av_code;
00792 
00793         av_code_ex = string_to_av_perm(tclass_ex, av_name);
00794         if (av_code_ex == 0)
00795         {
00796             /* fill up undefined permissions */
00797             if (!deny_unknown)
00798                 avd->allowed |= av_code;
00799             avd->auditdeny |= av_code;
00800 
00801             continue;
00802         }
00803 
00804         if (avd_ex.allowed & av_code_ex)
00805             avd->allowed |= av_code;
00806         if (avd_ex.auditallow & av_code_ex)
00807             avd->auditallow |= av_code;
00808         if (avd_ex.auditdeny & av_code_ex)
00809             avd->auditdeny |= av_code;
00810     }
00811 
00812     return;
00813 }
00814 
00815 /*
00816  * sepgsql_compute_create
00817  *
00818  * It returns a default security context to be assigned on a new database
00819  * object. SELinux compute it based on a combination of client, upper object
00820  * which owns the new object and object class.
00821  *
00822  * For example, when a client (staff_u:staff_r:staff_t:s0) tries to create
00823  * a new table within a schema (system_u:object_r:sepgsql_schema_t:s0),
00824  * SELinux looks-up its security policy. If it has a special rule on the
00825  * combination of these security contexts and object class (db_table),
00826  * it returns the security context suggested by the special rule.
00827  * Otherwise, it returns the security context of schema, as is.
00828  *
00829  * We expect the caller already applies sanity/validation checks on the
00830  * given security context.
00831  *
00832  * scontext: security context of the subject (mostly, peer process).
00833  * tcontext: security context of the upper database object.
00834  * tclass: class code (SEPG_CLASS_*) of the new object in creation
00835  */
00836 char *
00837 sepgsql_compute_create(const char *scontext,
00838                        const char *tcontext,
00839                        uint16 tclass,
00840                        const char *objname)
00841 {
00842     security_context_t ncontext;
00843     security_class_t tclass_ex;
00844     const char *tclass_name;
00845     char       *result;
00846 
00847     /* Get external code of the object class */
00848     Assert(tclass < SEPG_CLASS_MAX);
00849 
00850     tclass_name = selinux_catalog[tclass].class_name;
00851     tclass_ex = string_to_security_class(tclass_name);
00852 
00853     /*
00854      * Ask SELinux what is the default context for the given object class on a
00855      * pair of security contexts
00856      */
00857     if (security_compute_create_name_raw((security_context_t) scontext,
00858                                          (security_context_t) tcontext,
00859                                          tclass_ex,
00860                                          objname,
00861                                          &ncontext) < 0)
00862         ereport(ERROR,
00863                 (errcode(ERRCODE_INTERNAL_ERROR),
00864                  errmsg("SELinux could not compute a new context: "
00865                         "scontext=%s tcontext=%s tclass=%s: %m",
00866                         scontext, tcontext, tclass_name)));
00867 
00868     /*
00869      * libselinux returns malloc()'ed string, so we need to copy it on the
00870      * palloc()'ed region.
00871      */
00872     PG_TRY();
00873     {
00874         result = pstrdup(ncontext);
00875     }
00876     PG_CATCH();
00877     {
00878         freecon(ncontext);
00879         PG_RE_THROW();
00880     }
00881     PG_END_TRY();
00882     freecon(ncontext);
00883 
00884     return result;
00885 }
00886 
00887 /*
00888  * sepgsql_check_perms
00889  *
00890  * It makes access control decision without userspace caching mechanism.
00891  * If SELinux denied the required accesses on the pair of security labels,
00892  * it raises an error or returns false.
00893  *
00894  * scontext: security label of the subject (mostly, peer process)
00895  * tcontext: security label of the object being referenced
00896  * tclass: class code (SEPG_CLASS_*) of the object being referenced
00897  * required: a mask of required permissions (SEPG_<class>__<perm>)
00898  * audit_name: a human readable object name for audit logs, or NULL.
00899  * abort_on_violation: true, if error shall be raised on access violation
00900  */
00901 bool
00902 sepgsql_check_perms(const char *scontext,
00903                     const char *tcontext,
00904                     uint16 tclass,
00905                     uint32 required,
00906                     const char *audit_name,
00907                     bool abort_on_violation)
00908 {
00909     struct av_decision avd;
00910     uint32      denied;
00911     uint32      audited;
00912     bool        result = true;
00913 
00914     sepgsql_compute_avd(scontext, tcontext, tclass, &avd);
00915 
00916     denied = required & ~avd.allowed;
00917 
00918     if (sepgsql_get_debug_audit())
00919         audited = (denied ? denied : required);
00920     else
00921         audited = (denied ? (denied & avd.auditdeny)
00922                    : (required & avd.auditallow));
00923 
00924     if (denied &&
00925         sepgsql_getenforce() > 0 &&
00926         (avd.flags & SELINUX_AVD_FLAGS_PERMISSIVE) == 0)
00927         result = false;
00928 
00929     /*
00930      * It records a security audit for the request, if needed. But, when
00931      * SE-PgSQL performs 'internal' mode, it needs to keep silent.
00932      */
00933     if (audited && sepgsql_mode != SEPGSQL_MODE_INTERNAL)
00934     {
00935         sepgsql_audit_log(denied,
00936                           scontext,
00937                           tcontext,
00938                           tclass,
00939                           audited,
00940                           audit_name);
00941     }
00942 
00943     if (!result && abort_on_violation)
00944         ereport(ERROR,
00945                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
00946                  errmsg("SELinux: security policy violation")));
00947     return result;
00948 }