Commit 947e73dd authored by Oliver Pinter's avatar Oliver Pinter
Browse files

HBSD: as preparation to TOCTOU fix and to hbsdcontrol extend secadm's rules



This change introduces the prefer_acl keyword, to control the order of
rule evaluation.

When the prefer_acl property was set on a specific rule, then it
overrides the settings came from FS-EA based hbsdcontrol.

FYI: by default the hbsdcontrol's settings overrides the secadm rules,
since hbsdcontrol's evaluation is after the MAC framework's check.

Signed-off-by: default avatarOliver Pinter <oliver.pinter@hardenedbsd.org>
parent da70f4cb
...@@ -59,18 +59,30 @@ The flags that can be passed to `secadm add pax` are: ...@@ -59,18 +59,30 @@ The flags that can be passed to `secadm add pax` are:
* M, m: Enable, disable MPROTECT * M, m: Enable, disable MPROTECT
* P, p: Enable, disable PAGEEXEC * P, p: Enable, disable PAGEEXEC
* S, s: Enable, disable SEGVGUARD * S, s: Enable, disable SEGVGUARD
* O, o: Enable, disable hbsdcontrol based FS-EA rules overriding
By default, `secadm show` will show the active ruleset in abbreviated By default, `secadm show` will show the active ruleset in abbreviated
format. secadm now integrates with libxo to provide ruleset output in format. secadm now integrates with libxo to provide ruleset output in
JSON, UCL, or XML formats. Specify a different format by using the -f JSON, UCL, or XML formats. Specify a different format by using the -f
option to `secadm show`. For example, `secadm show -f ucl`. option to `secadm show`. For example, `secadm show -f ucl`.
Order of rule evaluation
========================
When the kernel is compiled with the PAX_CONTROL_EXTATTR kernel option, the
order of the evaluation is secadm then hbsdcontrol. This ensures that
the hbsdcontrol's settings always take precedence. To make secadm's
rules take precedence, use the O flag for that rule (prefer_acl is the
long option).
Requirements Requirements
============ ============
* HardenedBSD version 31 or greater: * HardenedBSD version 1200055 or greater:
- `sysctl hardening.version` should show 31 - `sysctl hardening.version` should show 1200055
* HardenedBSD kernel compiled with options PAX_CONTROL_ACL
* textproc/libucl * textproc/libucl
* textproc/libxo
Installation And Usage Installation And Usage
====================== ======================
...@@ -116,6 +128,8 @@ secadm currently supports toggling ASLR, SEGVGUARD, mprotect(exec) ...@@ -116,6 +128,8 @@ secadm currently supports toggling ASLR, SEGVGUARD, mprotect(exec)
hardening, and on certain HardenedBSD builds, PAGEEXEC hardening. In hardening, and on certain HardenedBSD builds, PAGEEXEC hardening. In
the etc directory, you will find secadm.rules.sample, which shows the etc directory, you will find secadm.rules.sample, which shows
how to write rules. how to write rules.
You can use the prefer_acl keyword, to ensure secadm's rule takes
in effect over the file system extended attributes based settings.
secadm uses libucl for parsing its config file. As it stands right secadm uses libucl for parsing its config file. As it stands right
now, the order of the rules do not matter, but that could change with now, the order of the rules do not matter, but that could change with
...@@ -134,7 +148,8 @@ secadm { ...@@ -134,7 +148,8 @@ secadm {
pax { pax {
path: "/bin/pwd", path: "/bin/pwd",
mprotect: true, mprotect: true,
pageexec: true pageexec: true,
prefer_acl: true
} }
} }
==== End of Example ==== ==== End of Example ====
......
...@@ -47,7 +47,9 @@ static int ...@@ -47,7 +47,9 @@ static int
secadm_pax_elf(struct image_params *imgp, pax_flag_t flags) secadm_pax_elf(struct image_params *imgp, pax_flag_t flags)
{ {
#if (__HardenedBSD_version < 1300000 && __HardenedBSD_version > 1200052) || \ #if (__HardenedBSD_version < 1300000 && __HardenedBSD_version > 1200054)
return pax_control_acl_set_flags(curthread, imgp, flags);
#elif (__HardenedBSD_version < 1300000 && __HardenedBSD_version > 1200052) || \
(__HardenedBSD_version < 1200000 && __HardenedBSD_version > 1100048) || \ (__HardenedBSD_version < 1200000 && __HardenedBSD_version > 1100048) || \
(__HardenedBSD_version < 1100000 && __HardenedBSD_version > 1000048) (__HardenedBSD_version < 1100000 && __HardenedBSD_version > 1000048)
return pax_elf(curthread, imgp, flags); return pax_elf(curthread, imgp, flags);
...@@ -185,6 +187,18 @@ secadm_vnode_check_exec(struct ucred *ucred, struct vnode *vp, ...@@ -185,6 +187,18 @@ secadm_vnode_check_exec(struct ucred *ucred, struct vnode *vp,
PAX_NOTE_NODISALLOWMAP32BIT; PAX_NOTE_NODISALLOWMAP32BIT;
} }
} }
#ifdef PAX_NOTE_PREFER_ACL
if (rule->sr_pax_data->sp_pax_set &
SECADM_PAX_PREFER_ACL) {
if (rule->sr_pax_data->sp_pax &
SECADM_PAX_PREFER_ACL) {
flags |= PAX_NOTE_PREFER_ACL;
} else {
flags &= ~PAX_NOTE_PREFER_ACL;
}
}
#endif
} }
} }
rule_inactive: rule_inactive:
......
...@@ -65,6 +65,7 @@ ...@@ -65,6 +65,7 @@
#define SECADM_PAX_SEGVGUARD_SET 0x00000008 #define SECADM_PAX_SEGVGUARD_SET 0x00000008
#define SECADM_PAX_SHLIBRANDOM_SET 0x00000010 #define SECADM_PAX_SHLIBRANDOM_SET 0x00000010
#define SECADM_PAX_MAP32_SET 0x00000020 #define SECADM_PAX_MAP32_SET 0x00000020
#define SECADM_PAX_PREFER_ACL_SET 0x80000000
#define SECADM_PAX_PAGEEXEC 0x00000001 #define SECADM_PAX_PAGEEXEC 0x00000001
#define SECADM_PAX_MPROTECT 0x00000002 #define SECADM_PAX_MPROTECT 0x00000002
...@@ -72,6 +73,7 @@ ...@@ -72,6 +73,7 @@
#define SECADM_PAX_SEGVGUARD 0x00000008 #define SECADM_PAX_SEGVGUARD 0x00000008
#define SECADM_PAX_SHLIBRANDOM 0x00000010 #define SECADM_PAX_SHLIBRANDOM 0x00000010
#define SECADM_PAX_MAP32 0x00000020 #define SECADM_PAX_MAP32 0x00000020
#define SECADM_PAX_PREFER_ACL 0x80000000
#define SECADM_INTEGRIFORCE_FLAGS_NONE 0x00000000 #define SECADM_INTEGRIFORCE_FLAGS_NONE 0x00000000
#define SECADM_INTEGRIFORCE_FLAGS_WHITELIST 0x00000001 #define SECADM_INTEGRIFORCE_FLAGS_WHITELIST 0x00000001
......
...@@ -334,6 +334,13 @@ show_action(int argc, char **argv) ...@@ -334,6 +334,13 @@ show_action(int argc, char **argv)
SECADM_PAX_SEGVGUARD ? 'S' : 's')); SECADM_PAX_SEGVGUARD ? 'S' : 's'));
} }
if (ruleset[i]->sr_pax_data->sp_pax_set &
SECADM_PAX_PREFER_ACL_SET) {
printf("%c",
(ruleset[i]->sr_pax_data->sp_pax &
SECADM_PAX_PREFER_ACL ? 'O' : 'o'));
}
printf("\n"); printf("\n");
break; break;
...@@ -834,6 +841,20 @@ add_action(int argc, char **argv) ...@@ -834,6 +841,20 @@ add_action(int argc, char **argv)
SECADM_PAX_MPROTECT_SET; SECADM_PAX_MPROTECT_SET;
break; break;
case 'o':
rule->sr_pax_data->sp_pax &=
~(SECADM_PAX_PREFER_ACL);
rule->sr_pax_data->sp_pax_set |=
SECADM_PAX_PREFER_ACL_SET;
break;
case 'O':
rule->sr_pax_data->sp_pax |=
SECADM_PAX_PREFER_ACL;
rule->sr_pax_data->sp_pax_set |=
SECADM_PAX_PREFER_ACL_SET;
break;
case 'p': case 'p':
/* mprotect requires pageexec */ /* mprotect requires pageexec */
rule->sr_pax_data->sp_pax &= rule->sr_pax_data->sp_pax &=
...@@ -1107,6 +1128,13 @@ emit_rules_xo(secadm_rule_t **ruleset, size_t num_rules, int style) ...@@ -1107,6 +1128,13 @@ emit_rules_xo(secadm_rule_t **ruleset, size_t num_rules, int style)
SECADM_PAX_SHLIBRANDOM ? "true" : "false")); SECADM_PAX_SHLIBRANDOM ? "true" : "false"));
} }
if (ruleset[i]->sr_pax_data->sp_pax_set &
SECADM_PAX_PREFER_ACL_SET) {
xo_emit("{:prefer_acl/%s}/",
(ruleset[i]->sr_pax_data->sp_pax &
SECADM_PAX_PREFER_ACL ? "true" : "false"));
}
xo_close_instance_d(); xo_close_instance_d();
} }
} }
...@@ -1195,7 +1223,12 @@ emit_rules_ucl(secadm_rule_t **ruleset, size_t num_rules) ...@@ -1195,7 +1223,12 @@ emit_rules_ucl(secadm_rule_t **ruleset, size_t num_rules)
(ruleset[i]->sr_pax_data->sp_pax & (ruleset[i]->sr_pax_data->sp_pax &
SECADM_PAX_SHLIBRANDOM ? "true" : "false")); SECADM_PAX_SHLIBRANDOM ? "true" : "false"));
} }
if (ruleset[i]->sr_pax_data->sp_pax_set &
SECADM_PAX_PREFER_ACL_SET) {
printf(" prefer_acl = %s;\n",
(ruleset[i]->sr_pax_data->sp_pax &
SECADM_PAX_PREFER_ACL ? "true" : "false"));
}
printf(" }\n"); printf(" }\n");
} }
} }
...@@ -1316,6 +1349,12 @@ parse_pax_object(const ucl_object_t *obj, secadm_rule_t *rule) ...@@ -1316,6 +1349,12 @@ parse_pax_object(const ucl_object_t *obj, secadm_rule_t *rule)
if (ucl_object_toboolean(cur)) if (ucl_object_toboolean(cur))
rule->sr_pax_data->sp_pax |= rule->sr_pax_data->sp_pax |=
SECADM_PAX_MAP32; SECADM_PAX_MAP32;
} else if (!strncmp(key, "prefer_acl", 10)) {
rule->sr_pax_data->sp_pax_set |=
SECADM_PAX_PREFER_ACL_SET;
if (ucl_object_toboolean(cur))
rule->sr_pax_data->sp_pax |=
SECADM_PAX_PREFER_ACL;
} else { } else {
fprintf(stderr, fprintf(stderr,
"Unknown attribute '%s' of PaX rule.\n", key); "Unknown attribute '%s' of PaX rule.\n", key);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment