Print this page
7029 want per-process exploit mitigation features (secflags)
7030 want basic address space layout randomization (aslr)
7031 noexec_user_stack should be a secflag
7032 want a means to forbid mappings around NULL.


 128  * For (1), priv should be set to the specific privilege, and allzone
 129  * should be set to B_FALSE.
 130  * For (2), priv should be set to the specific privilege, and allzone
 131  * should be set to B_TRUE.
 132  * For (3), priv should be set to PRIV_ALL, and allzone should be set
 133  * to B_FALSE.
 134  *
 135  */
 136 
 137 /*
 138  * The privileges are checked against the Effective set for
 139  * ordinary processes and checked against the Limit set
 140  * for euid 0 processes that haven't manipulated their privilege
 141  * sets.
 142  */
 143 #define HAS_ALLPRIVS(cr)        priv_isfullset(&CR_OEPRIV(cr))
 144 #define ZONEPRIVS(cr)           ((cr)->cr_zone->zone_privset)
 145 #define HAS_ALLZONEPRIVS(cr)    priv_issubset(ZONEPRIVS(cr), &CR_OEPRIV(cr))
 146 #define HAS_PRIVILEGE(cr, pr)   ((pr) == PRIV_ALL ? \
 147                                         HAS_ALLPRIVS(cr) : \
 148                                         PRIV_ISASSERT(&CR_OEPRIV(cr), pr))
 149 
 150 #define FAST_BASIC_CHECK(cr, priv)      \
 151         if (PRIV_ISASSERT(&CR_OEPRIV(cr), priv)) { \
 152                 DTRACE_PROBE2(priv__ok, int, priv, boolean_t, B_FALSE); \
 153                 return (0); \
 154         }
 155 
 156 /*
 157  * Policy checking functions.
 158  *
 159  * All of the system's policy should be implemented here.
 160  */
 161 
 162 /*
 163  * Private functions which take an additional va_list argument to
 164  * implement an object specific policy override.
 165  */
 166 static int priv_policy_ap(const cred_t *, int, boolean_t, int,
 167     const char *, va_list);
 168 static int priv_policy_va(const cred_t *, int, boolean_t, int,
 169     const char *, ...);
 170 
 171 /*


 384                 } else {
 385                         ASSERT(!HAS_PRIVILEGE(cr, priv));
 386                         priv_policy_errmsg(cr, priv, msg);
 387                 }
 388         }
 389 }
 390 
 391 /*
 392  * priv_policy_ap()
 393  * return 0 or error.
 394  * See block comment above for a description of "priv" and "allzone" usage.
 395  */
 396 static int
 397 priv_policy_ap(const cred_t *cr, int priv, boolean_t allzone, int err,
 398     const char *msg, va_list ap)
 399 {
 400         if ((HAS_PRIVILEGE(cr, priv) && (!allzone || HAS_ALLZONEPRIVS(cr))) ||
 401             (!servicing_interrupt() &&
 402             priv_policy_override(cr, priv, allzone, ap) == 0)) {
 403                 if ((allzone || priv == PRIV_ALL ||
 404                     !PRIV_ISASSERT(priv_basic, priv)) &&
 405                     !servicing_interrupt()) {
 406                         PTOU(curproc)->u_acflag |= ASU; /* Needed for SVVS */
 407                         if (AU_AUDITING())
 408                                 audit_priv(priv,
 409                                     allzone ? ZONEPRIVS(cr) : NULL, 1);
 410                 }
 411                 err = 0;
 412                 DTRACE_PROBE2(priv__ok, int, priv, boolean_t, allzone);
 413         } else if (!servicing_interrupt()) {
 414                 /* Failure audited in this procedure */
 415                 priv_policy_err(cr, priv, allzone, msg);
 416         }
 417         return (err);
 418 }
 419 
 420 int
 421 priv_policy_va(const cred_t *cr, int priv, boolean_t allzone, int err,
 422     const char *msg, ...)
 423 {
 424         int ret;


 432 }
 433 
 434 int
 435 priv_policy(const cred_t *cr, int priv, boolean_t allzone, int err,
 436     const char *msg)
 437 {
 438         return (priv_policy_va(cr, priv, allzone, err, msg, KLPDARG_NONE));
 439 }
 440 
 441 /*
 442  * Return B_TRUE for sufficient privileges, B_FALSE for insufficient privileges.
 443  */
 444 boolean_t
 445 priv_policy_choice(const cred_t *cr, int priv, boolean_t allzone)
 446 {
 447         boolean_t res = HAS_PRIVILEGE(cr, priv) &&
 448             (!allzone || HAS_ALLZONEPRIVS(cr));
 449 
 450         /* Audit success only */
 451         if (res && AU_AUDITING() &&
 452             (allzone || priv == PRIV_ALL || !PRIV_ISASSERT(priv_basic, priv)) &&
 453             !servicing_interrupt()) {
 454                 audit_priv(priv, allzone ? ZONEPRIVS(cr) : NULL, 1);
 455         }
 456         if (res) {
 457                 DTRACE_PROBE2(priv__ok, int, priv, boolean_t, allzone);
 458         } else {
 459                 DTRACE_PROBE2(priv__err, int, priv, boolean_t, allzone);
 460         }
 461         return (res);
 462 }
 463 
 464 /*
 465  * Non-auditing variant of priv_policy_choice().
 466  */
 467 boolean_t
 468 priv_policy_only(const cred_t *cr, int priv, boolean_t allzone)
 469 {
 470         boolean_t res = HAS_PRIVILEGE(cr, priv) &&
 471             (!allzone || HAS_ALLZONEPRIVS(cr));
 472 


 955                     PRIV_FILE_DAC_EXECUTE;
 956 
 957                 return (priv_policy_va(cr, p, B_FALSE, EACCES, NULL,
 958                     KLPDARG_VNODE, vp, (char *)NULL, KLPDARG_NOMORE));
 959         }
 960         return (0);
 961 }
 962 
 963 /*
 964  * Like secpolicy_vnode_access() but we get the actual wanted mode and the
 965  * current mode of the file, not the missing bits.
 966  */
 967 int
 968 secpolicy_vnode_access2(const cred_t *cr, vnode_t *vp, uid_t owner,
 969     mode_t curmode, mode_t wantmode)
 970 {
 971         mode_t mode;
 972 
 973         /* Inline the basic privileges tests. */
 974         if ((wantmode & VREAD) &&
 975             !PRIV_ISASSERT(&CR_OEPRIV(cr), PRIV_FILE_READ) &&
 976             priv_policy_va(cr, PRIV_FILE_READ, B_FALSE, EACCES, NULL,
 977             KLPDARG_VNODE, vp, (char *)NULL, KLPDARG_NOMORE) != 0) {
 978                 return (EACCES);
 979         }
 980 
 981         if ((wantmode & VWRITE) &&
 982             !PRIV_ISASSERT(&CR_OEPRIV(cr), PRIV_FILE_WRITE) &&
 983             priv_policy_va(cr, PRIV_FILE_WRITE, B_FALSE, EACCES, NULL,
 984             KLPDARG_VNODE, vp, (char *)NULL, KLPDARG_NOMORE) != 0) {
 985                 return (EACCES);
 986         }
 987 
 988         mode = ~curmode & wantmode;
 989 
 990         if (mode == 0)
 991                 return (0);
 992 
 993         if ((mode & VREAD) && priv_policy_va(cr, PRIV_FILE_DAC_READ, B_FALSE,
 994             EACCES, NULL, KLPDARG_VNODE, vp, (char *)NULL,
 995             KLPDARG_NOMORE) != 0) {
 996                 return (EACCES);
 997         }
 998 
 999         if (mode & VWRITE) {
1000                 boolean_t allzone;
1001 
1002                 if (owner == 0 && cr->cr_uid != 0)


1711 secpolicy_kmdb(const cred_t *scr)
1712 {
1713         return (PRIV_POLICY(scr, PRIV_ALL, B_FALSE, EPERM, NULL));
1714 }
1715 
1716 int
1717 secpolicy_error_inject(const cred_t *scr)
1718 {
1719         return (PRIV_POLICY(scr, PRIV_ALL, B_FALSE, EPERM, NULL));
1720 }
1721 
1722 /*
1723  * Processor sets, cpu configuration, resource pools.
1724  */
1725 int
1726 secpolicy_pset(const cred_t *cr)
1727 {
1728         return (PRIV_POLICY(cr, PRIV_SYS_RES_CONFIG, B_FALSE, EPERM, NULL));
1729 }
1730 













1731 /*
1732  * Processor set binding.
1733  */
1734 int
1735 secpolicy_pbind(const cred_t *cr)
1736 {
1737         if (PRIV_POLICY_ONLY(cr, PRIV_SYS_RES_CONFIG, B_FALSE))
1738                 return (secpolicy_pset(cr));
1739         return (PRIV_POLICY(cr, PRIV_SYS_RES_BIND, B_FALSE, EPERM, NULL));
1740 }
1741 
1742 int
1743 secpolicy_ponline(const cred_t *cr)
1744 {
1745         return (PRIV_POLICY(cr, PRIV_SYS_RES_CONFIG, B_FALSE, EPERM, NULL));
1746 }
1747 
1748 int
1749 secpolicy_pool(const cred_t *cr)
1750 {




 128  * For (1), priv should be set to the specific privilege, and allzone
 129  * should be set to B_FALSE.
 130  * For (2), priv should be set to the specific privilege, and allzone
 131  * should be set to B_TRUE.
 132  * For (3), priv should be set to PRIV_ALL, and allzone should be set
 133  * to B_FALSE.
 134  *
 135  */
 136 
 137 /*
 138  * The privileges are checked against the Effective set for
 139  * ordinary processes and checked against the Limit set
 140  * for euid 0 processes that haven't manipulated their privilege
 141  * sets.
 142  */
 143 #define HAS_ALLPRIVS(cr)        priv_isfullset(&CR_OEPRIV(cr))
 144 #define ZONEPRIVS(cr)           ((cr)->cr_zone->zone_privset)
 145 #define HAS_ALLZONEPRIVS(cr)    priv_issubset(ZONEPRIVS(cr), &CR_OEPRIV(cr))
 146 #define HAS_PRIVILEGE(cr, pr)   ((pr) == PRIV_ALL ? \
 147                                         HAS_ALLPRIVS(cr) : \
 148                                         PRIV_ISMEMBER(&CR_OEPRIV(cr), pr))
 149 
 150 #define FAST_BASIC_CHECK(cr, priv)      \
 151         if (PRIV_ISMEMBER(&CR_OEPRIV(cr), priv)) { \
 152                 DTRACE_PROBE2(priv__ok, int, priv, boolean_t, B_FALSE); \
 153                 return (0); \
 154         }
 155 
 156 /*
 157  * Policy checking functions.
 158  *
 159  * All of the system's policy should be implemented here.
 160  */
 161 
 162 /*
 163  * Private functions which take an additional va_list argument to
 164  * implement an object specific policy override.
 165  */
 166 static int priv_policy_ap(const cred_t *, int, boolean_t, int,
 167     const char *, va_list);
 168 static int priv_policy_va(const cred_t *, int, boolean_t, int,
 169     const char *, ...);
 170 
 171 /*


 384                 } else {
 385                         ASSERT(!HAS_PRIVILEGE(cr, priv));
 386                         priv_policy_errmsg(cr, priv, msg);
 387                 }
 388         }
 389 }
 390 
 391 /*
 392  * priv_policy_ap()
 393  * return 0 or error.
 394  * See block comment above for a description of "priv" and "allzone" usage.
 395  */
 396 static int
 397 priv_policy_ap(const cred_t *cr, int priv, boolean_t allzone, int err,
 398     const char *msg, va_list ap)
 399 {
 400         if ((HAS_PRIVILEGE(cr, priv) && (!allzone || HAS_ALLZONEPRIVS(cr))) ||
 401             (!servicing_interrupt() &&
 402             priv_policy_override(cr, priv, allzone, ap) == 0)) {
 403                 if ((allzone || priv == PRIV_ALL ||
 404                     !PRIV_ISMEMBER(priv_basic, priv)) &&
 405                     !servicing_interrupt()) {
 406                         PTOU(curproc)->u_acflag |= ASU; /* Needed for SVVS */
 407                         if (AU_AUDITING())
 408                                 audit_priv(priv,
 409                                     allzone ? ZONEPRIVS(cr) : NULL, 1);
 410                 }
 411                 err = 0;
 412                 DTRACE_PROBE2(priv__ok, int, priv, boolean_t, allzone);
 413         } else if (!servicing_interrupt()) {
 414                 /* Failure audited in this procedure */
 415                 priv_policy_err(cr, priv, allzone, msg);
 416         }
 417         return (err);
 418 }
 419 
 420 int
 421 priv_policy_va(const cred_t *cr, int priv, boolean_t allzone, int err,
 422     const char *msg, ...)
 423 {
 424         int ret;


 432 }
 433 
 434 int
 435 priv_policy(const cred_t *cr, int priv, boolean_t allzone, int err,
 436     const char *msg)
 437 {
 438         return (priv_policy_va(cr, priv, allzone, err, msg, KLPDARG_NONE));
 439 }
 440 
 441 /*
 442  * Return B_TRUE for sufficient privileges, B_FALSE for insufficient privileges.
 443  */
 444 boolean_t
 445 priv_policy_choice(const cred_t *cr, int priv, boolean_t allzone)
 446 {
 447         boolean_t res = HAS_PRIVILEGE(cr, priv) &&
 448             (!allzone || HAS_ALLZONEPRIVS(cr));
 449 
 450         /* Audit success only */
 451         if (res && AU_AUDITING() &&
 452             (allzone || priv == PRIV_ALL || !PRIV_ISMEMBER(priv_basic, priv)) &&
 453             !servicing_interrupt()) {
 454                 audit_priv(priv, allzone ? ZONEPRIVS(cr) : NULL, 1);
 455         }
 456         if (res) {
 457                 DTRACE_PROBE2(priv__ok, int, priv, boolean_t, allzone);
 458         } else {
 459                 DTRACE_PROBE2(priv__err, int, priv, boolean_t, allzone);
 460         }
 461         return (res);
 462 }
 463 
 464 /*
 465  * Non-auditing variant of priv_policy_choice().
 466  */
 467 boolean_t
 468 priv_policy_only(const cred_t *cr, int priv, boolean_t allzone)
 469 {
 470         boolean_t res = HAS_PRIVILEGE(cr, priv) &&
 471             (!allzone || HAS_ALLZONEPRIVS(cr));
 472 


 955                     PRIV_FILE_DAC_EXECUTE;
 956 
 957                 return (priv_policy_va(cr, p, B_FALSE, EACCES, NULL,
 958                     KLPDARG_VNODE, vp, (char *)NULL, KLPDARG_NOMORE));
 959         }
 960         return (0);
 961 }
 962 
 963 /*
 964  * Like secpolicy_vnode_access() but we get the actual wanted mode and the
 965  * current mode of the file, not the missing bits.
 966  */
 967 int
 968 secpolicy_vnode_access2(const cred_t *cr, vnode_t *vp, uid_t owner,
 969     mode_t curmode, mode_t wantmode)
 970 {
 971         mode_t mode;
 972 
 973         /* Inline the basic privileges tests. */
 974         if ((wantmode & VREAD) &&
 975             !PRIV_ISMEMBER(&CR_OEPRIV(cr), PRIV_FILE_READ) &&
 976             priv_policy_va(cr, PRIV_FILE_READ, B_FALSE, EACCES, NULL,
 977             KLPDARG_VNODE, vp, (char *)NULL, KLPDARG_NOMORE) != 0) {
 978                 return (EACCES);
 979         }
 980 
 981         if ((wantmode & VWRITE) &&
 982             !PRIV_ISMEMBER(&CR_OEPRIV(cr), PRIV_FILE_WRITE) &&
 983             priv_policy_va(cr, PRIV_FILE_WRITE, B_FALSE, EACCES, NULL,
 984             KLPDARG_VNODE, vp, (char *)NULL, KLPDARG_NOMORE) != 0) {
 985                 return (EACCES);
 986         }
 987 
 988         mode = ~curmode & wantmode;
 989 
 990         if (mode == 0)
 991                 return (0);
 992 
 993         if ((mode & VREAD) && priv_policy_va(cr, PRIV_FILE_DAC_READ, B_FALSE,
 994             EACCES, NULL, KLPDARG_VNODE, vp, (char *)NULL,
 995             KLPDARG_NOMORE) != 0) {
 996                 return (EACCES);
 997         }
 998 
 999         if (mode & VWRITE) {
1000                 boolean_t allzone;
1001 
1002                 if (owner == 0 && cr->cr_uid != 0)


1711 secpolicy_kmdb(const cred_t *scr)
1712 {
1713         return (PRIV_POLICY(scr, PRIV_ALL, B_FALSE, EPERM, NULL));
1714 }
1715 
1716 int
1717 secpolicy_error_inject(const cred_t *scr)
1718 {
1719         return (PRIV_POLICY(scr, PRIV_ALL, B_FALSE, EPERM, NULL));
1720 }
1721 
1722 /*
1723  * Processor sets, cpu configuration, resource pools.
1724  */
1725 int
1726 secpolicy_pset(const cred_t *cr)
1727 {
1728         return (PRIV_POLICY(cr, PRIV_SYS_RES_CONFIG, B_FALSE, EPERM, NULL));
1729 }
1730 
1731 /* Process security flags */
1732 int
1733 secpolicy_psecflags(const cred_t *cr, proc_t *tp, proc_t *sp)
1734 {
1735         if (PRIV_POLICY(cr, PRIV_PROC_SECFLAGS, B_FALSE, EPERM, NULL) != 0)
1736                 return (EPERM);
1737 
1738         if (!prochasprocperm(tp, sp, cr))
1739                 return (EPERM);
1740 
1741         return (0);
1742 }
1743 
1744 /*
1745  * Processor set binding.
1746  */
1747 int
1748 secpolicy_pbind(const cred_t *cr)
1749 {
1750         if (PRIV_POLICY_ONLY(cr, PRIV_SYS_RES_CONFIG, B_FALSE))
1751                 return (secpolicy_pset(cr));
1752         return (PRIV_POLICY(cr, PRIV_SYS_RES_BIND, B_FALSE, EPERM, NULL));
1753 }
1754 
1755 int
1756 secpolicy_ponline(const cred_t *cr)
1757 {
1758         return (PRIV_POLICY(cr, PRIV_SYS_RES_CONFIG, B_FALSE, EPERM, NULL));
1759 }
1760 
1761 int
1762 secpolicy_pool(const cred_t *cr)
1763 {