00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "postgres.h"
00013
00014 #include "lib/stringinfo.h"
00015
00016 #include "sepgsql.h"
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
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
00601
00602
00603
00604
00605
00606
00607 static int sepgsql_mode = SEPGSQL_MODE_INTERNAL;
00608
00609
00610
00611
00612 bool
00613 sepgsql_is_enabled(void)
00614 {
00615 return (sepgsql_mode != SEPGSQL_MODE_DISABLED ? true : false);
00616 }
00617
00618
00619
00620
00621 int
00622 sepgsql_get_mode(void)
00623 {
00624 return sepgsql_mode;
00625 }
00626
00627
00628
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
00642
00643
00644
00645
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
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
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
00690 Assert(tclass < SEPG_CLASS_MAX);
00691 class_name = selinux_catalog[tclass].class_name;
00692
00693
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
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
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
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
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
00754
00755
00756
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
00768
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
00781
00782
00783
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
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
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
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
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
00855
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
00870
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
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
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
00931
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 }