aboutsummaryrefslogtreecommitdiff
path: root/sys/security
diff options
context:
space:
mode:
Diffstat (limited to 'sys/security')
-rw-r--r--sys/security/audit/audit_bsm.c28
-rw-r--r--sys/security/mac/mac_framework.c1
-rw-r--r--sys/security/mac/mac_framework.h18
-rw-r--r--sys/security/mac/mac_internal.h32
-rw-r--r--sys/security/mac/mac_policy.h51
-rw-r--r--sys/security/mac/mac_prison.c258
-rw-r--r--sys/security/mac/mac_syscalls.c242
-rw-r--r--sys/security/mac/mac_syscalls.h10
-rw-r--r--sys/security/mac_stub/mac_stub.c91
-rw-r--r--sys/security/mac_test/mac_test.c181
10 files changed, 889 insertions, 23 deletions
diff --git a/sys/security/audit/audit_bsm.c b/sys/security/audit/audit_bsm.c
index 2cd1511b2296..6cd96ebe092f 100644
--- a/sys/security/audit/audit_bsm.c
+++ b/sys/security/audit/audit_bsm.c
@@ -1115,6 +1115,16 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
}
break;
+ case AUE_PDWAIT:
+ if (ARG_IS_VALID(kar, ARG_FFLAGS)) {
+ tok = au_to_arg32(1, "flags", ar->ar_arg_fflags);
+ kau_write(rec, tok);
+ }
+ if (ARG_IS_VALID(kar, ARG_FD)) {
+ tok = au_to_arg32(1, "fd", ar->ar_arg_fd);
+ kau_write(rec, tok);
+ }
+
case AUE_IOCTL:
if (ARG_IS_VALID(kar, ARG_CMD)) {
tok = au_to_arg32(2, "cmd", ar->ar_arg_cmd);
@@ -1365,6 +1375,24 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
kau_write(rec, tok);
}
break;
+ case AUE_PDRFORK:
+ if (ARG_IS_VALID(kar, ARG_PID)) {
+ tok = au_to_arg32(0, "child PID", ar->ar_arg_pid);
+ kau_write(rec, tok);
+ }
+ if (ARG_IS_VALID(kar, ARG_CMD)) {
+ tok = au_to_arg32(2, "fflags", ar->ar_arg_cmd);
+ kau_write(rec, tok);
+ }
+ if (ARG_IS_VALID(kar, ARG_FFLAGS)) {
+ tok = au_to_arg32(2, "flags", ar->ar_arg_fflags);
+ kau_write(rec, tok);
+ }
+ if (ARG_IS_VALID(kar, ARG_FD)) {
+ tok = au_to_arg32(1, "fd", ar->ar_arg_fd);
+ kau_write(rec, tok);
+ }
+ break;
case AUE_PDGETPID:
if (ARG_IS_VALID(kar, ARG_FD)) {
tok = au_to_arg32(1, "fd", ar->ar_arg_fd);
diff --git a/sys/security/mac/mac_framework.c b/sys/security/mac/mac_framework.c
index b0776160cc74..fec63b99c0e0 100644
--- a/sys/security/mac/mac_framework.c
+++ b/sys/security/mac/mac_framework.c
@@ -374,6 +374,7 @@ mac_policy_getlabeled(struct mac_policy_conf *mpc)
MPC_FLAG(mount_init_label, MPC_OBJECT_MOUNT);
MPC_FLAG(posixsem_init_label, MPC_OBJECT_POSIXSEM);
MPC_FLAG(posixshm_init_label, MPC_OBJECT_POSIXSHM);
+ MPC_FLAG(prison_init_label, MPC_OBJECT_PRISON);
MPC_FLAG(sysvmsg_init_label, MPC_OBJECT_SYSVMSG);
MPC_FLAG(sysvmsq_init_label, MPC_OBJECT_SYSVMSQ);
MPC_FLAG(sysvsem_init_label, MPC_OBJECT_SYSVSEM);
diff --git a/sys/security/mac/mac_framework.h b/sys/security/mac/mac_framework.h
index 1233cd30f211..5e13434e5ecc 100644
--- a/sys/security/mac/mac_framework.h
+++ b/sys/security/mac/mac_framework.h
@@ -73,6 +73,7 @@ struct mount;
struct msg;
struct msqid_kernel;
struct pipepair;
+struct prison;
struct proc;
struct semid_kernel;
struct shmfd;
@@ -85,6 +86,7 @@ struct thread;
struct timespec;
struct ucred;
struct vattr;
+struct vfsoptlist;
struct vnode;
struct vop_setlabel_args;
@@ -346,6 +348,22 @@ void mac_posixshm_create(struct ucred *cred, struct shmfd *shmfd);
void mac_posixshm_destroy(struct shmfd *);
void mac_posixshm_init(struct shmfd *);
+int mac_prison_init(struct prison *pr, int flag);
+void mac_prison_relabel(struct ucred *cred, struct prison *pr,
+ struct label *newlabel);
+void mac_prison_destroy(struct prison *pr);
+int mac_prison_check_attach(struct ucred *cred, struct prison *pr);
+int mac_prison_check_create(struct ucred *cred, struct vfsoptlist *opts,
+ int flags);
+int mac_prison_check_get(struct ucred *cred, struct prison *pr,
+ struct vfsoptlist *opts, int flags);
+int mac_prison_check_set(struct ucred *cred, struct prison *pr,
+ struct vfsoptlist *opts, int flags);
+int mac_prison_check_remove(struct ucred *cred, struct prison *pr);
+void mac_prison_created(struct ucred *cred, struct prison *pr);
+void mac_prison_attached(struct ucred *cred, struct prison *pr,
+ struct proc *p);
+
int mac_priv_check_impl(struct ucred *cred, int priv);
#ifdef MAC
extern bool mac_priv_check_fp_flag;
diff --git a/sys/security/mac/mac_internal.h b/sys/security/mac/mac_internal.h
index aeef59017d18..3f032ed3934a 100644
--- a/sys/security/mac/mac_internal.h
+++ b/sys/security/mac/mac_internal.h
@@ -64,6 +64,12 @@
SDT_PROVIDER_DECLARE(mac); /* MAC Framework-level events. */
SDT_PROVIDER_DECLARE(mac_framework); /* Entry points to MAC. */
+#define MAC_CHECK_PROBE_DEFINE5(name, arg0, arg1, arg2, arg3, arg4) \
+ SDT_PROBE_DEFINE6(mac_framework, , name, mac__check__err, \
+ "int", arg0, arg1, arg2, arg3, arg4); \
+ SDT_PROBE_DEFINE6(mac_framework, , name, mac__check__ok, \
+ "int", arg0, arg1, arg2, arg3, arg4);
+
#define MAC_CHECK_PROBE_DEFINE4(name, arg0, arg1, arg2, arg3) \
SDT_PROBE_DEFINE5(mac_framework, , name, mac__check__err, \
"int", arg0, arg1, arg2, arg3); \
@@ -88,18 +94,20 @@ SDT_PROVIDER_DECLARE(mac_framework); /* Entry points to MAC. */
SDT_PROBE_DEFINE2(mac_framework, , name, mac__check__ok, \
"int", arg0);
-#define MAC_CHECK_PROBE4(name, error, arg0, arg1, arg2, arg3) do { \
+#define MAC_CHECK_PROBE5(name, error, arg0, arg1, arg2, arg3, arg4) do { \
if (SDT_PROBES_ENABLED()) { \
if (error) { \
- SDT_PROBE5(mac_framework, , name, mac__check__err,\
- error, arg0, arg1, arg2, arg3); \
+ SDT_PROBE6(mac_framework, , name, mac__check__err,\
+ error, arg0, arg1, arg2, arg3, arg4); \
} else { \
- SDT_PROBE5(mac_framework, , name, mac__check__ok,\
- 0, arg0, arg1, arg2, arg3); \
+ SDT_PROBE6(mac_framework, , name, mac__check__ok,\
+ 0, arg0, arg1, arg2, arg3, arg4); \
} \
} \
} while (0)
+#define MAC_CHECK_PROBE4(name, error, arg0, arg1, arg2, arg3) \
+ MAC_CHECK_PROBE5(name, error, arg0, arg1, arg2, arg3, 0)
#define MAC_CHECK_PROBE3(name, error, arg0, arg1, arg2) \
MAC_CHECK_PROBE4(name, error, arg0, arg1, arg2, 0)
#define MAC_CHECK_PROBE2(name, error, arg0, arg1) \
@@ -177,6 +185,7 @@ struct label {
#define MPC_OBJECT_SYSVSHM 0x0000000000020000
#define MPC_OBJECT_SYNCACHE 0x0000000000040000
#define MPC_OBJECT_IP6Q 0x0000000000080000
+#define MPC_OBJECT_PRISON 0x0000000000100000
/*
* MAC Framework global variables.
@@ -233,6 +242,8 @@ struct label *mac_cred_label_alloc(void);
void mac_cred_label_free(struct label *label);
struct label *mac_pipe_label_alloc(void);
void mac_pipe_label_free(struct label *label);
+struct label *mac_prison_label_alloc(int flags);
+void mac_prison_label_free(struct label *label);
struct label *mac_socket_label_alloc(int flag);
void mac_socket_label_free(struct label *label);
void mac_socketpeer_label_free(struct label *label);
@@ -252,6 +263,17 @@ int mac_pipe_externalize_label(struct label *label, char *elements,
char *outbuf, size_t outbuflen);
int mac_pipe_internalize_label(struct label *label, char *string);
+int mac_prison_label_set(struct ucred *cred, struct prison *pr,
+ struct label *label);
+int mac_prison_check_relabel(struct ucred *cred, struct prison *pr,
+ struct label *newlabel);
+void mac_prison_copy_label(struct label *src, struct label *dest);
+int mac_prison_externalize_label(struct label *label, char *elements,
+ char *outbuf, size_t outbuflen);
+int mac_prison_internalize_label(struct label *label, char *string);
+void mac_prison_relabel(struct ucred *cred, struct prison *pr,
+ struct label *newlabel);
+
int mac_socket_label_set(struct ucred *cred, struct socket *so,
struct label *label);
void mac_socket_copy_label(struct label *src, struct label *dest);
diff --git a/sys/security/mac/mac_policy.h b/sys/security/mac/mac_policy.h
index f0a1f0863c96..a080d8cc4b8b 100644
--- a/sys/security/mac/mac_policy.h
+++ b/sys/security/mac/mac_policy.h
@@ -88,6 +88,7 @@ struct mount;
struct msg;
struct msqid_kernel;
struct pipepair;
+struct prison;
struct proc;
struct sbuf;
struct semid_kernel;
@@ -100,6 +101,7 @@ struct sysctl_req;
struct thread;
struct ucred;
struct vattr;
+struct vfsoptlist;
struct vnode;
struct in_addr;
@@ -407,6 +409,39 @@ typedef void (*mpo_posixshm_create_t)(struct ucred *cred,
typedef void (*mpo_posixshm_destroy_label_t)(struct label *label);
typedef void (*mpo_posixshm_init_label_t)(struct label *label);
+typedef int (*mpo_prison_init_label_t)(struct label *label, int flag);
+typedef int (*mpo_prison_check_relabel_t)(struct ucred *cred,
+ struct prison *pr, struct label *prlabel,
+ struct label *newlabel);
+typedef void (*mpo_prison_destroy_label_t)(struct label *label);
+typedef void (*mpo_prison_copy_label_t)(struct label *src,
+ struct label *dest);
+typedef int (*mpo_prison_externalize_label_t)(struct label *label,
+ char *element_name, struct sbuf *sb, int *claimed);
+typedef int (*mpo_prison_internalize_label_t)(struct label *label,
+ char *element_name, char *element_data, int *claimed);
+typedef void (*mpo_prison_relabel_t)(struct ucred *cred, struct prison *pr,
+ struct label *prlabel, struct label *newlabel);
+typedef int (*mpo_prison_check_attach_t)(struct ucred *cred,
+ struct prison *pr, struct label *prlabel);
+typedef int (*mpo_prison_check_create_t)(struct ucred *cred,
+ struct vfsoptlist *opts, int flags);
+typedef int (*mpo_prison_check_get_t)(struct ucred *cred,
+ struct prison *pr, struct label *prlabel,
+ struct vfsoptlist *opts, int flags);
+typedef int (*mpo_prison_check_set_t)(struct ucred *cred,
+ struct prison *pr, struct label *prlabel,
+ struct vfsoptlist *opts, int flags);
+typedef int (*mpo_prison_check_remove_t)(struct ucred *cred,
+ struct prison *pr, struct label *prlabel);
+typedef void (*mpo_prison_created_t)(struct ucred *cred,
+ struct prison *pr, struct label *prlabel);
+typedef void (*mpo_prison_cleanup_t)(struct ucred *cred,
+ struct prison *pr);
+typedef void (*mpo_prison_attached_t)(struct ucred *cred,
+ struct prison *pr, struct label *prlabel, struct proc *p,
+ struct label *proclabel);
+
typedef int (*mpo_priv_check_t)(struct ucred *cred, int priv);
typedef int (*mpo_priv_grant_t)(struct ucred *cred, int priv);
@@ -863,6 +898,22 @@ struct mac_policy_ops {
mpo_posixshm_destroy_label_t mpo_posixshm_destroy_label;
mpo_posixshm_init_label_t mpo_posixshm_init_label;
+ mpo_prison_init_label_t mpo_prison_init_label;
+ mpo_prison_check_relabel_t mpo_prison_check_relabel;
+ mpo_prison_destroy_label_t mpo_prison_destroy_label;
+ mpo_prison_copy_label_t mpo_prison_copy_label;
+ mpo_prison_externalize_label_t mpo_prison_externalize_label;
+ mpo_prison_internalize_label_t mpo_prison_internalize_label;
+ mpo_prison_relabel_t mpo_prison_relabel;
+ mpo_prison_check_attach_t mpo_prison_check_attach;
+ mpo_prison_check_create_t mpo_prison_check_create;
+ mpo_prison_check_get_t mpo_prison_check_get;
+ mpo_prison_check_set_t mpo_prison_check_set;
+ mpo_prison_check_remove_t mpo_prison_check_remove;
+ mpo_prison_created_t mpo_prison_created;
+ mpo_prison_cleanup_t mpo_prison_cleanup;
+ mpo_prison_attached_t mpo_prison_attached;
+
mpo_priv_check_t mpo_priv_check;
mpo_priv_grant_t mpo_priv_grant;
diff --git a/sys/security/mac/mac_prison.c b/sys/security/mac/mac_prison.c
new file mode 100644
index 000000000000..810160994f7b
--- /dev/null
+++ b/sys/security/mac/mac_prison.c
@@ -0,0 +1,258 @@
+/*-
+ * Copyright (c) 2025 Kyle Evans <kevans@FreeBSD.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sys/cdefs.h>
+#include "opt_mac.h"
+
+#include <sys/param.h>
+#include <sys/condvar.h>
+#include <sys/imgact.h>
+#include <sys/jail.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/mac.h>
+#include <sys/proc.h>
+#include <sys/sbuf.h>
+#include <sys/sdt.h>
+#include <sys/systm.h>
+#include <sys/vnode.h>
+#include <sys/mount.h>
+#include <sys/file.h>
+#include <sys/namei.h>
+#include <sys/sysctl.h>
+
+#include <security/mac/mac_framework.h>
+#include <security/mac/mac_internal.h>
+#include <security/mac/mac_policy.h>
+
+void
+mac_prison_label_free(struct label *label)
+{
+ if (label == NULL)
+ return;
+
+ MAC_POLICY_PERFORM_NOSLEEP(prison_destroy_label, label);
+ mac_labelzone_free(label);
+}
+
+struct label *
+mac_prison_label_alloc(int flag)
+{
+ struct label *label;
+ int error;
+
+ label = mac_labelzone_alloc(flag);
+ if (label == NULL)
+ return (NULL);
+
+ if (flag & M_WAITOK)
+ MAC_POLICY_CHECK(prison_init_label, label, flag);
+ else
+ MAC_POLICY_CHECK_NOSLEEP(prison_init_label, label, flag);
+ if (error) {
+ mac_prison_label_free(label);
+ return (NULL);
+ }
+ return (label);
+}
+
+/*
+ * The caller's expecting us to return with the prison locked if we were
+ * successful, since we're also setting pr->pr_label. On error, it remains
+ * unlocked.
+ */
+int
+mac_prison_init(struct prison *pr, int flag)
+{
+ struct label *prlabel;
+
+ mtx_assert(&pr->pr_mtx, MA_NOTOWNED);
+ if ((mac_labeled & MPC_OBJECT_PRISON) == 0) {
+ mtx_lock(&pr->pr_mtx);
+ pr->pr_label = NULL;
+ return (0);
+ }
+
+ prlabel = mac_prison_label_alloc(flag);
+ if (prlabel == NULL) {
+ KASSERT((flag & M_WAITOK) == 0,
+ ("MAC policy prison_init_label failed under M_WAITOK"));
+ return (ENOMEM);
+ }
+
+ mtx_lock(&pr->pr_mtx);
+ pr->pr_label = prlabel;
+ return (0);
+}
+
+void
+mac_prison_destroy(struct prison *pr)
+{
+ mtx_assert(&pr->pr_mtx, MA_OWNED);
+
+ /* Symmetry with prison_created */
+ MAC_POLICY_PERFORM_NOSLEEP(prison_cleanup, curthread->td_ucred, pr);
+ mac_prison_label_free(pr->pr_label);
+ pr->pr_label = NULL;
+}
+
+void
+mac_prison_copy_label(struct label *src, struct label *dest)
+{
+
+ MAC_POLICY_PERFORM_NOSLEEP(prison_copy_label, src, dest);
+}
+
+int
+mac_prison_externalize_label(struct label *label, char *elements,
+ char *outbuf, size_t outbuflen)
+{
+ int error;
+
+ MAC_POLICY_EXTERNALIZE(prison, label, elements, outbuf, outbuflen);
+ return (error);
+}
+
+int
+mac_prison_internalize_label(struct label *label, char *string)
+{
+ int error;
+
+ MAC_POLICY_INTERNALIZE(prison, label, string);
+ return (error);
+}
+
+void
+mac_prison_relabel(struct ucred *cred, struct prison *pr,
+ struct label *newlabel)
+{
+ mtx_assert(&pr->pr_mtx, MA_OWNED);
+ MAC_POLICY_PERFORM_NOSLEEP(prison_relabel, cred, pr, pr->pr_label,
+ newlabel);
+}
+
+int
+mac_prison_label_set(struct ucred *cred, struct prison *pr,
+ struct label *label)
+{
+ int error;
+
+ mtx_assert(&pr->pr_mtx, MA_OWNED);
+
+ error = mac_prison_check_relabel(cred, pr, label);
+ if (error)
+ return (error);
+
+ mac_prison_relabel(cred, pr, label);
+
+ return (0);
+}
+
+MAC_CHECK_PROBE_DEFINE4(prison_check_relabel, "struct ucred *",
+ "struct prison *", "struct label *", "struct label *");
+int
+mac_prison_check_relabel(struct ucred *cred, struct prison *pr,
+ struct label *newlabel)
+{
+ int error;
+
+ mtx_assert(&pr->pr_mtx, MA_OWNED);
+ MAC_POLICY_CHECK_NOSLEEP(prison_check_relabel, cred, pr,
+ pr->pr_label, newlabel);
+ MAC_CHECK_PROBE4(prison_check_relabel, error, cred, pr,
+ pr->pr_label, newlabel);
+
+ return (error);
+}
+
+MAC_CHECK_PROBE_DEFINE3(prison_check_attach, "struct ucred *",
+ "struct prison *", "struct label *");
+int
+mac_prison_check_attach(struct ucred *cred, struct prison *pr)
+{
+ int error;
+
+ MAC_POLICY_CHECK_NOSLEEP(prison_check_attach, cred, pr, pr->pr_label);
+ MAC_CHECK_PROBE3(prison_check_attach, error, cred, pr, pr->pr_label);
+
+ return (error);
+}
+
+MAC_CHECK_PROBE_DEFINE3(prison_check_create, "struct ucred *",
+ "struct vfsoptlist *", "int");
+int
+mac_prison_check_create(struct ucred *cred, struct vfsoptlist *opts,
+ int flags)
+{
+ int error;
+
+ MAC_POLICY_CHECK_NOSLEEP(prison_check_create, cred, opts, flags);
+ MAC_CHECK_PROBE3(prison_check_create, error, cred, opts, flags);
+
+ return (error);
+}
+
+MAC_CHECK_PROBE_DEFINE5(prison_check_get, "struct ucred *",
+ "struct prison *", "struct label *", "struct vfsoptlist *", "int");
+int
+mac_prison_check_get(struct ucred *cred, struct prison *pr,
+ struct vfsoptlist *opts, int flags)
+{
+ int error;
+
+ MAC_POLICY_CHECK_NOSLEEP(prison_check_get, cred, pr, pr->pr_label,
+ opts, flags);
+ MAC_CHECK_PROBE5(prison_check_get, error, cred, pr, pr->pr_label, opts,
+ flags);
+
+ return (error);
+}
+
+MAC_CHECK_PROBE_DEFINE5(prison_check_set, "struct ucred *",
+ "struct prison *", "struct label *", "struct vfsoptlist *", "int");
+int
+mac_prison_check_set(struct ucred *cred, struct prison *pr,
+ struct vfsoptlist *opts, int flags)
+{
+ int error;
+
+ MAC_POLICY_CHECK_NOSLEEP(prison_check_set, cred, pr, pr->pr_label,
+ opts, flags);
+ MAC_CHECK_PROBE5(prison_check_set, error, cred, pr, pr->pr_label, opts,
+ flags);
+
+ return (error);
+}
+
+MAC_CHECK_PROBE_DEFINE3(prison_check_remove, "struct ucred *",
+ "struct prison *", "struct label *");
+int
+mac_prison_check_remove(struct ucred *cred, struct prison *pr)
+{
+ int error;
+
+ MAC_POLICY_CHECK_NOSLEEP(prison_check_remove, cred, pr, pr->pr_label);
+ MAC_CHECK_PROBE3(prison_check_remove, error, cred, pr, pr->pr_label);
+
+ return (error);
+}
+
+void
+mac_prison_created(struct ucred *cred, struct prison *pr)
+{
+
+ MAC_POLICY_PERFORM(prison_created, cred, pr, pr->pr_label);
+}
+
+void
+mac_prison_attached(struct ucred *cred, struct prison *pr, struct proc *p)
+{
+
+ MAC_POLICY_PERFORM(prison_attached, cred, pr, pr->pr_label, p,
+ p->p_label);
+}
diff --git a/sys/security/mac/mac_syscalls.c b/sys/security/mac/mac_syscalls.c
index 13c7998041f9..9bafa6d30c36 100644
--- a/sys/security/mac/mac_syscalls.c
+++ b/sys/security/mac/mac_syscalls.c
@@ -49,6 +49,8 @@
#include <sys/abi_compat.h>
#include <sys/capsicum.h>
#include <sys/fcntl.h>
+#include <sys/jail.h>
+#include <sys/jaildesc.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/malloc.h>
@@ -88,6 +90,35 @@ struct mac32 {
};
#endif
+static int
+mac_label_copyin_string(struct mac *const mac, char **const u_string,
+ int flag)
+{
+ char *buffer;
+ int error;
+
+ error = mac_check_structmac_consistent(mac);
+ if (error != 0)
+ return (error);
+
+ /* 'm_buflen' not too big checked by function call above. */
+ buffer = malloc(mac->m_buflen, M_MACTEMP, flag);
+ if (buffer == NULL)
+ return (ENOMEM);
+
+ error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL);
+ if (error != 0) {
+ free(buffer, M_MACTEMP);
+ return (error);
+ }
+
+ MPASS(error == 0);
+ if (u_string != NULL)
+ *u_string = mac->m_string;
+ mac->m_string = buffer;
+ return (0);
+}
+
/*
* Copyin a 'struct mac', including the string pointed to by 'm_string'.
*
@@ -99,7 +130,6 @@ int
mac_label_copyin(const void *const u_mac, struct mac *const mac,
char **const u_string)
{
- char *buffer;
int error;
#ifdef COMPAT_FREEBSD32
@@ -120,23 +150,7 @@ mac_label_copyin(const void *const u_mac, struct mac *const mac,
return (error);
}
- error = mac_check_structmac_consistent(mac);
- if (error != 0)
- return (error);
-
- /* 'm_buflen' not too big checked by function call above. */
- buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
- error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL);
- if (error != 0) {
- free(buffer, M_MACTEMP);
- return (error);
- }
-
- MPASS(error == 0);
- if (u_string != NULL)
- *u_string = mac->m_string;
- mac->m_string = buffer;
- return (0);
+ return (mac_label_copyin_string(mac, u_string, M_WAITOK));
}
void
@@ -289,6 +303,156 @@ mac_set_proc_finish(struct thread *const td, bool proc_label_set,
}
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;
+ }
+
+ intlabel = mac_prison_label_alloc(M_NOWAIT);
+ if (intlabel == NULL) {
+ error = ENOMEM;
+ goto out;
+ }
+
+ if ((mac_labeled & MPC_OBJECT_PRISON) != 0)
+ 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)
{
struct ucred *newcred, *oldcred;
@@ -339,6 +503,7 @@ sys___mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
struct mac mac;
struct vnode *vp;
struct pipe *pipe;
+ struct prison *pr;
struct socket *so;
cap_rights_t rights;
int error;
@@ -400,6 +565,25 @@ sys___mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
mac_socket_label_free(intlabel);
break;
+ case DTYPE_JAILDESC:
+ if (!(mac_labeled & MPC_OBJECT_PRISON)) {
+ error = EINVAL;
+ goto out_fdrop;
+ }
+
+ error = jaildesc_get_prison(fp, &pr);
+ if (error != 0)
+ goto out_fdrop;
+
+ intlabel = mac_prison_label_alloc(M_WAITOK);
+ mac_prison_copy_label(pr->pr_label, intlabel);
+ prison_free(pr);
+
+ error = mac_prison_externalize_label(intlabel, mac.m_string,
+ buffer, mac.m_buflen);
+ mac_prison_label_free(intlabel);
+ break;
+
default:
error = EINVAL;
}
@@ -473,6 +657,7 @@ sys___mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
{
struct label *intlabel;
struct pipe *pipe;
+ struct prison *pr;
struct socket *so;
struct file *fp;
struct mount *mp;
@@ -548,6 +733,27 @@ sys___mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
mac_socket_label_free(intlabel);
break;
+ case DTYPE_JAILDESC:
+ if (!(mac_labeled & MPC_OBJECT_PRISON)) {
+ error = EINVAL;
+ goto out_fdrop;
+ }
+
+ pr = NULL;
+ intlabel = mac_prison_label_alloc(M_WAITOK);
+ error = mac_prison_internalize_label(intlabel, mac.m_string);
+ if (error == 0)
+ error = jaildesc_get_prison(fp, &pr);
+ if (error == 0) {
+ prison_lock(pr);
+ error = mac_prison_label_set(td->td_ucred, pr,
+ intlabel);
+ prison_free_locked(pr);
+ }
+
+ mac_prison_label_free(intlabel);
+ break;
+
default:
error = EINVAL;
}
diff --git a/sys/security/mac/mac_syscalls.h b/sys/security/mac/mac_syscalls.h
index f95ff3ef1264..76c8e6d188bb 100644
--- a/sys/security/mac/mac_syscalls.h
+++ b/sys/security/mac/mac_syscalls.h
@@ -30,4 +30,14 @@ int mac_set_proc_core(struct thread *const td, struct ucred *const newcred,
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_stub/mac_stub.c b/sys/security/mac_stub/mac_stub.c
index ac5d5b58e5db..1e1220300259 100644
--- a/sys/security/mac_stub/mac_stub.c
+++ b/sys/security/mac_stub/mac_stub.c
@@ -52,6 +52,7 @@
#include <sys/acl.h>
#include <sys/conf.h>
#include <sys/extattr.h>
+#include <sys/jail.h>
#include <sys/kdb.h>
#include <sys/kernel.h>
#include <sys/ksem.h>
@@ -852,6 +853,80 @@ stub_posixshm_create(struct ucred *cred, struct shmfd *shmfd,
}
+static void
+stub_prison_relabel(struct ucred *cred, struct prison *pr,
+ struct label *prlabel, struct label *newlabel)
+{
+
+}
+
+static int
+stub_prison_check_relabel(struct ucred *cred, struct prison *pr,
+ struct label *prlabel, struct label *newlabel)
+{
+
+ return (0);
+}
+
+static int
+stub_prison_check_attach(struct ucred *cred, struct prison *pr,
+ struct label *prlabel)
+{
+
+ return (0);
+}
+
+static int
+stub_prison_check_create(struct ucred *cred, struct vfsoptlist *opts, int flags)
+{
+
+ return (0);
+}
+
+static int
+stub_prison_check_get(struct ucred *cred, struct prison *pr,
+ struct label *prlabel, struct vfsoptlist *opts, int flags)
+{
+
+ return (0);
+}
+
+static int
+stub_prison_check_set(struct ucred *cred, struct prison *pr,
+ struct label *prlabel, struct vfsoptlist *opts, int flags)
+{
+
+ return (0);
+}
+
+static int
+stub_prison_check_remove(struct ucred *cred, struct prison *pr,
+ struct label *prlabel)
+{
+
+ return (0);
+}
+
+static void
+stub_prison_created(struct ucred *cred, struct prison *pr,
+ struct label *prlabel)
+{
+
+}
+
+static void
+stub_prison_cleanup(struct ucred *cred, struct prison *pr)
+{
+
+}
+
+static void
+stub_prison_attached(struct ucred *cred, struct prison *pr,
+ struct label *prlabel, struct proc *p, struct label *proclabel)
+{
+
+}
+
static int
stub_priv_check(struct ucred *cred, int priv)
{
@@ -1841,6 +1916,22 @@ static struct mac_policy_ops stub_ops =
.mpo_posixshm_destroy_label = stub_destroy_label,
.mpo_posixshm_init_label = stub_init_label,
+ .mpo_prison_init_label = stub_init_label_waitcheck,
+ .mpo_prison_destroy_label = stub_destroy_label,
+ .mpo_prison_copy_label = stub_copy_label,
+ .mpo_prison_externalize_label = stub_externalize_label,
+ .mpo_prison_internalize_label = stub_internalize_label,
+ .mpo_prison_relabel = stub_prison_relabel,
+ .mpo_prison_check_relabel = stub_prison_check_relabel,
+ .mpo_prison_check_attach = stub_prison_check_attach,
+ .mpo_prison_check_create = stub_prison_check_create,
+ .mpo_prison_check_get = stub_prison_check_get,
+ .mpo_prison_check_set = stub_prison_check_set,
+ .mpo_prison_check_remove = stub_prison_check_remove,
+ .mpo_prison_created = stub_prison_created,
+ .mpo_prison_cleanup = stub_prison_cleanup,
+ .mpo_prison_attached = stub_prison_attached,
+
.mpo_priv_check = stub_priv_check,
.mpo_priv_grant = stub_priv_grant,
diff --git a/sys/security/mac_test/mac_test.c b/sys/security/mac_test/mac_test.c
index c447eeef010d..f16073cfdf72 100644
--- a/sys/security/mac_test/mac_test.c
+++ b/sys/security/mac_test/mac_test.c
@@ -51,6 +51,7 @@
#include <sys/param.h>
#include <sys/acl.h>
+#include <sys/jail.h>
#include <sys/kdb.h>
#include <sys/kernel.h>
#include <sys/ksem.h>
@@ -99,6 +100,7 @@ static SYSCTL_NODE(_security_mac, OID_AUTO, test,
#define MAGIC_PIPE 0xdc6c9919
#define MAGIC_POSIX_SEM 0x78ae980c
#define MAGIC_POSIX_SHM 0x4e853fc9
+#define MAGIC_PRISON 0x9639acdb
#define MAGIC_PROC 0x3b4be98f
#define MAGIC_CRED 0x9a5a4987
#define MAGIC_VNODE 0x1a67a45c
@@ -1591,6 +1593,169 @@ test_posixshm_init_label(struct label *label)
COUNTER_INC(posixshm_init_label);
}
+COUNTER_DECL(prison_init_label);
+static int
+test_prison_init_label(struct label *label, int flag)
+{
+
+ if (flag & M_WAITOK)
+ WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
+ "test_prison_init_label() at %s:%d", __FILE__,
+ __LINE__);
+
+ LABEL_INIT(label, MAGIC_PRISON);
+ COUNTER_INC(prison_init_label);
+ return (0);
+}
+
+COUNTER_DECL(prison_destroy_label);
+static void
+test_prison_destroy_label(struct label *label)
+{
+
+ LABEL_DESTROY(label, MAGIC_PRISON);
+ COUNTER_INC(prison_destroy_label);
+}
+
+COUNTER_DECL(prison_copy_label);
+static void
+test_prison_copy_label(struct label *src, struct label *dest)
+{
+
+ LABEL_CHECK(src, MAGIC_PRISON);
+ LABEL_CHECK(dest, MAGIC_PRISON);
+ COUNTER_INC(prison_copy_label);
+}
+
+COUNTER_DECL(prison_externalize_label);
+static int
+test_prison_externalize_label(struct label *label, char *element_name,
+ struct sbuf *sb, int *claimed)
+{
+
+ LABEL_CHECK(label, MAGIC_PRISON);
+ COUNTER_INC(prison_externalize_label);
+
+ return (0);
+}
+
+COUNTER_DECL(prison_internalize_label);
+static int
+test_prison_internalize_label(struct label *label, char *element_name,
+ char *element_data, int *claimed)
+{
+
+ LABEL_CHECK(label, MAGIC_PRISON);
+ COUNTER_INC(prison_internalize_label);
+
+ return (0);
+}
+
+COUNTER_DECL(prison_relabel);
+static void
+test_prison_relabel(struct ucred *cred, struct prison *pr,
+ struct label *prlabel, struct label *newlabel)
+{
+
+ LABEL_CHECK(prlabel, MAGIC_PRISON);
+ LABEL_CHECK(newlabel, MAGIC_PRISON);
+ COUNTER_INC(prison_relabel);
+}
+
+COUNTER_DECL(prison_check_relabel);
+static int
+test_prison_check_relabel(struct ucred *cred, struct prison *pr,
+ struct label *prlabel, struct label *newlabel)
+{
+
+ LABEL_CHECK(prlabel, MAGIC_PRISON);
+ LABEL_CHECK(newlabel, MAGIC_PRISON);
+ COUNTER_INC(prison_check_relabel);
+ return (0);
+}
+
+COUNTER_DECL(prison_check_attach);
+static int
+test_prison_check_attach(struct ucred *cred, struct prison *pr,
+ struct label *prlabel)
+{
+
+ LABEL_CHECK(prlabel, MAGIC_PRISON);
+ COUNTER_INC(prison_check_attach);
+ return (0);
+}
+
+COUNTER_DECL(prison_check_create);
+static int
+test_prison_check_create(struct ucred *cred, struct vfsoptlist *opts, int flags)
+{
+
+ COUNTER_INC(prison_check_create);
+ return (0);
+}
+
+COUNTER_DECL(prison_check_get);
+static int
+test_prison_check_get(struct ucred *cred, struct prison *pr,
+ struct label *prlabel, struct vfsoptlist *opts, int flags)
+{
+
+ LABEL_CHECK(prlabel, MAGIC_PRISON);
+ COUNTER_INC(prison_check_get);
+ return (0);
+}
+
+COUNTER_DECL(prison_check_set);
+static int
+test_prison_check_set(struct ucred *cred, struct prison *pr,
+ struct label *prlabel, struct vfsoptlist *opts, int flags)
+{
+
+ LABEL_CHECK(prlabel, MAGIC_PRISON);
+ COUNTER_INC(prison_check_set);
+ return (0);
+}
+
+COUNTER_DECL(prison_check_remove);
+static int
+test_prison_check_remove(struct ucred *cred, struct prison *pr,
+ struct label *prlabel)
+{
+
+ LABEL_CHECK(prlabel, MAGIC_PRISON);
+ COUNTER_INC(prison_check_remove);
+ return (0);
+}
+
+COUNTER_DECL(prison_created);
+static void
+test_prison_created(struct ucred *cred, struct prison *pr,
+ struct label *prlabel)
+{
+
+ LABEL_CHECK(prlabel, MAGIC_PRISON);
+ COUNTER_INC(prison_created);
+}
+
+COUNTER_DECL(prison_cleanup);
+static void
+test_prison_cleanup(struct ucred *cred, struct prison *pr)
+{
+
+ COUNTER_INC(prison_cleanup);
+}
+
+COUNTER_DECL(prison_attached);
+static void
+test_prison_attached(struct ucred *cred, struct prison *pr,
+ struct label *prlabel, struct proc *p, struct label *proclabel)
+{
+
+ LABEL_CHECK(prlabel, MAGIC_PRISON);
+ LABEL_CHECK(proclabel, MAGIC_PROC);
+ COUNTER_INC(prison_attached);
+}
+
COUNTER_DECL(proc_check_debug);
static int
test_proc_check_debug(struct ucred *cred, struct proc *p)
@@ -3208,6 +3373,22 @@ static struct mac_policy_ops test_ops =
.mpo_posixshm_destroy_label = test_posixshm_destroy_label,
.mpo_posixshm_init_label = test_posixshm_init_label,
+ .mpo_prison_init_label = test_prison_init_label,
+ .mpo_prison_destroy_label = test_prison_destroy_label,
+ .mpo_prison_copy_label = test_prison_copy_label,
+ .mpo_prison_externalize_label = test_prison_externalize_label,
+ .mpo_prison_internalize_label = test_prison_internalize_label,
+ .mpo_prison_relabel = test_prison_relabel,
+ .mpo_prison_check_relabel = test_prison_check_relabel,
+ .mpo_prison_check_attach = test_prison_check_attach,
+ .mpo_prison_check_create = test_prison_check_create,
+ .mpo_prison_check_get = test_prison_check_get,
+ .mpo_prison_check_set = test_prison_check_set,
+ .mpo_prison_check_remove = test_prison_check_remove,
+ .mpo_prison_created = test_prison_created,
+ .mpo_prison_cleanup = test_prison_cleanup,
+ .mpo_prison_attached = test_prison_attached,
+
.mpo_proc_check_debug = test_proc_check_debug,
.mpo_proc_check_sched = test_proc_check_sched,
.mpo_proc_check_signal = test_proc_check_signal,