Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144731838
D53958.id169823.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D53958.id169823.diff
View Options
diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
--- a/sys/kern/kern_jail.c
+++ b/sys/kern/kern_jail.c
@@ -80,6 +80,8 @@
#endif /* DDB */
#include <security/mac/mac_framework.h>
+#include <security/mac/mac_policy.h>
+#include <security/mac/mac_syscalls.h>
#define PRISON0_HOSTUUID_MODULE "hostuuid"
@@ -1027,6 +1029,10 @@
#endif
unsigned long hid;
size_t namelen, onamelen, pnamelen;
+#ifdef MAC
+ void *mac_set_prison_data = NULL;
+ int gotmaclabel;
+#endif
int created, cuflags, descend, drflags, enforce;
int error, errmsg_len, errmsg_pos;
int gotchildmax, gotenforce, gothid, gotrsnum, gotslevel;
@@ -1349,6 +1355,17 @@
pr_flags |= PR_HOST;
}
+#ifdef MAC
+ /* Process the mac.label vfsopt */
+ error = mac_set_prison_prepare(td, opts, &mac_set_prison_data);
+ if (error == ENOENT)
+ gotmaclabel = 0;
+ else if (error != 0)
+ goto done_errmsg;
+ else
+ gotmaclabel = 1;
+#endif
+
#ifdef INET
error = vfs_getopt(opts, "ip4.addr", &op, &ip4s);
if (error == ENOENT)
@@ -2182,6 +2199,17 @@
}
}
pr->pr_flags = (pr->pr_flags & ~ch_flags) | pr_flags;
+
+#ifdef MAC
+ /* Apply any request MAC label before we let modules do their work. */
+ if (gotmaclabel) {
+ error = mac_set_prison_core(td, pr, mac_set_prison_data);
+ if (error) {
+ vfs_opterror(opts, "mac relabel denied");
+ goto done_deref;
+ }
+ }
+#endif
mtx_unlock(&pr->pr_mtx);
drflags &= ~PD_LOCKED;
/*
@@ -2370,6 +2398,10 @@
#endif
#ifdef INET6
prison_ip_free(ip6);
+#endif
+#ifdef MAC
+ if (mac_set_prison_data != NULL)
+ mac_set_prison_finish(td, error == 0, mac_set_prison_data);
#endif
if (jfp_out != NULL)
fdrop(jfp_out, td);
@@ -2835,9 +2867,22 @@
if (error != 0 && error != ENOENT)
goto done;
- /* Get the module parameters. */
+#ifdef MAC
+ /*
+ * We get the MAC label last because we'll let the MAC framework drop
+ * pr_mtx to externalize the label.
+ */
+ error = mac_get_prison(td, pr, opts);
+ mtx_assert(&pr->pr_mtx, MA_NOTOWNED);
+ drflags &= ~PD_LOCKED;
+ if (error != 0 && error != ENOENT)
+ goto done;
+#else
mtx_unlock(&pr->pr_mtx);
drflags &= ~PD_LOCKED;
+#endif
+
+ /* Get the module parameters. */
error = osd_jail_call(pr, PR_METHOD_GET, opts);
if (error)
goto done;
@@ -5107,6 +5152,11 @@
SYSCTL_JAIL_PARAM_NODE(cpuset, "Jail cpuset");
SYSCTL_JAIL_PARAM(_cpuset, id, CTLTYPE_INT | CTLFLAG_RD, "I", "Jail cpuset ID");
+#ifdef MAC
+SYSCTL_JAIL_PARAM_STRUCT(_mac, label, CTLFLAG_RW, sizeof(struct mac),
+ "S,mac", "Jail MAC label");
+#endif
+
#ifdef INET
SYSCTL_JAIL_PARAM_SYS_NODE(ip4, CTLFLAG_RDTUN,
"Jail IPv4 address virtualization");
diff --git a/sys/security/mac/mac_syscalls.h b/sys/security/mac/mac_syscalls.h
--- a/sys/security/mac/mac_syscalls.h
+++ b/sys/security/mac/mac_syscalls.h
@@ -30,4 +30,14 @@
void mac_set_proc_finish(struct thread *const td, bool proc_label_set,
void *const mac_set_proc_data);
+struct vfsoptlist;
+int mac_get_prison(struct thread *const td, struct prison *pr,
+ struct vfsoptlist *opts);
+int mac_set_prison_prepare(struct thread *const td, struct vfsoptlist *opts,
+ void **const mac_set_prison_data);
+int mac_set_prison_core(struct thread *const td, struct prison *pr,
+ void *const mac_set_prison_data);
+void mac_set_prison_finish(struct thread *const td, bool prison_label_set,
+ void *const mac_set_prison_data);
+
#endif /* !_SECURITY_MAC_MAC_SYSCALLS_H_ */
diff --git a/sys/security/mac/mac_syscalls.c b/sys/security/mac/mac_syscalls.c
--- a/sys/security/mac/mac_syscalls.c
+++ b/sys/security/mac/mac_syscalls.c
@@ -302,6 +302,160 @@
mac_cred_label_free(intlabel);
}
+int
+mac_get_prison(struct thread *const td, struct prison *pr,
+ struct vfsoptlist *opts)
+{
+ char *buffer = NULL, *u_buffer;
+ struct label *intlabel = NULL;
+ struct mac mac;
+ int error;
+ bool locked = true;
+
+ mtx_assert(&pr->pr_mtx, MA_OWNED);
+#ifdef COMPAT_FREEBSD32
+ if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
+ struct mac32 mac32;
+
+ error = vfs_copyopt(opts, "mac.label", &mac32, sizeof(mac32));
+ if (error == 0) {
+ CP(mac32, mac, m_buflen);
+ PTRIN_CP(mac32, mac, m_string);
+ }
+ } else
+#endif
+ error = vfs_copyopt(opts, "mac.label", &mac, sizeof(mac));
+ if (error) {
+ if (error != ENOENT)
+ vfs_opterror(opts, "bad mac.label");
+ goto out_nomac;
+ }
+
+ if (!(mac_labeled & MPC_OBJECT_PRISON)) {
+ error = EINVAL;
+ goto out;
+ }
+
+ intlabel = mac_prison_label_alloc(M_NOWAIT);
+ if (intlabel == NULL) {
+ error = ENOMEM;
+ goto out;
+ }
+
+ mac_prison_copy_label(pr->pr_label, intlabel);
+
+ /*
+ * Externalization may want to acquire an rmlock. We already tapped out
+ * a copy of the label from when the jail_get(2) operation started and
+ * we're expected to be called near the end of jail_get(2) when the lock
+ * is about to be dropped anyways, so this is safe.
+ */
+ mtx_unlock(&pr->pr_mtx);
+ locked = false;
+
+ error = mac_label_copyin_string(&mac, &u_buffer, M_WAITOK);
+ if (error) {
+ vfs_opterror(opts, "mac.label: string copy failure");
+ goto out;
+ }
+
+ buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
+ if (buffer == NULL) {
+ error = ENOMEM;
+ goto out;
+ }
+
+ error = mac_prison_externalize_label(intlabel, mac.m_string,
+ buffer, mac.m_buflen);
+
+ if (error == 0)
+ error = copyout(buffer, u_buffer, strlen(buffer)+1);
+
+out:
+ mac_prison_label_free(intlabel);
+ free_copied_label(&mac);
+ free(buffer, M_MACTEMP);
+
+out_nomac:
+ if (locked) {
+ MPASS(error != 0);
+ mtx_unlock(&pr->pr_mtx);
+ }
+
+ return (error);
+}
+
+int
+mac_set_prison_prepare(struct thread *const td, struct vfsoptlist *opts,
+ void **const mac_set_prison_data)
+{
+ struct mac mac;
+ struct label *intlabel;
+ int error;
+
+#ifdef COMPAT_FREEBSD32
+ if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
+ struct mac32 mac32;
+
+ error = vfs_copyopt(opts, "mac.label", &mac32, sizeof(mac32));
+ if (error == 0) {
+ CP(mac32, mac, m_buflen);
+ PTRIN_CP(mac32, mac, m_string);
+ }
+ } else
+#endif
+ error = vfs_copyopt(opts, "mac.label", &mac, sizeof(mac));
+ if (error) {
+ if (error != ENOENT)
+ vfs_opterror(opts, "bad mac.label");
+ return (error);
+ }
+
+ error = mac_label_copyin_string(&mac, NULL, M_WAITOK);
+ if (error) {
+ vfs_opterror(opts, "mac.label: string copy failure");
+ return (error);
+ }
+
+ /*
+ * If the option wasn't set, then we return ENOENT above. If we don't
+ * have any policies applicable to prisons, we can return EINVAL early.
+ */
+ if (!(mac_labeled & MPC_OBJECT_PRISON)) {
+ vfs_opterror(opts, "no labelled jail policies");
+ return (EINVAL);
+ }
+
+ intlabel = mac_prison_label_alloc(M_WAITOK);
+ error = mac_prison_internalize_label(intlabel, mac.m_string);
+ if (error) {
+ mac_prison_label_free(intlabel);
+ vfs_opterror(opts, "internalize_label error");
+ return (error);
+ }
+
+ *mac_set_prison_data = intlabel;
+ return (0);
+}
+
+int
+mac_set_prison_core(struct thread *const td, struct prison *pr,
+ void *const mac_set_prison_data)
+{
+ struct label *const intlabel = mac_set_prison_data;
+
+ return (mac_prison_label_set(td->td_ucred, pr, intlabel));
+}
+
+void
+mac_set_prison_finish(struct thread *const td, bool prison_label_set __unused,
+ void *const mac_set_prison_data)
+{
+ struct label *const intlabel = mac_set_prison_data;
+
+ mac_prison_label_free(intlabel);
+}
+
int
sys___mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
{
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Feb 12, 8:16 PM (13 h, 37 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28669839
Default Alt Text
D53958.id169823.diff (7 KB)
Attached To
Mode
D53958: kern: add a mac.label jail parameter
Attached
Detach File
Event Timeline
Log In to Comment