diff options
-rw-r--r-- | sys/compat/pecoff/imgact_pecoff.c | 1 | ||||
-rw-r--r-- | sys/kern/kern_exec.c | 80 | ||||
-rw-r--r-- | sys/kern/kern_mac.c | 62 | ||||
-rw-r--r-- | sys/security/mac/mac_framework.c | 62 | ||||
-rw-r--r-- | sys/security/mac/mac_framework.h | 16 | ||||
-rw-r--r-- | sys/security/mac/mac_internal.h | 62 | ||||
-rw-r--r-- | sys/security/mac/mac_net.c | 62 | ||||
-rw-r--r-- | sys/security/mac/mac_pipe.c | 62 | ||||
-rw-r--r-- | sys/security/mac/mac_policy.h | 10 | ||||
-rw-r--r-- | sys/security/mac/mac_process.c | 62 | ||||
-rw-r--r-- | sys/security/mac/mac_syscalls.c | 62 | ||||
-rw-r--r-- | sys/security/mac/mac_system.c | 62 | ||||
-rw-r--r-- | sys/security/mac/mac_vfs.c | 62 | ||||
-rw-r--r-- | sys/sys/imgact.h | 2 | ||||
-rw-r--r-- | sys/sys/mac.h | 16 | ||||
-rw-r--r-- | sys/sys/mac_policy.h | 10 |
16 files changed, 617 insertions, 76 deletions
diff --git a/sys/compat/pecoff/imgact_pecoff.c b/sys/compat/pecoff/imgact_pecoff.c index bf05ca8..fd9ab26 100644 --- a/sys/compat/pecoff/imgact_pecoff.c +++ b/sys/compat/pecoff/imgact_pecoff.c @@ -365,6 +365,7 @@ pecoff_load_file(struct thread * td, const char *file, u_long * addr, u_long * e imgp->proc = td->td_proc; imgp->userspace_argv = NULL; imgp->userspace_envv = NULL; + imgp->execlabel = NULL; imgp->attr = &attr; imgp->firstpage = NULL; diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 4586502..d97ed31 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -77,7 +77,7 @@ static MALLOC_DEFINE(M_ATEXEC, "atexec", "atexec callback"); static int sysctl_kern_ps_strings(SYSCTL_HANDLER_ARGS); static int sysctl_kern_usrstack(SYSCTL_HANDLER_ARGS); static int kern_execve(struct thread *td, char *fname, char **argv, - char **envv); + char **envv, struct mac *mac_p); /* * callout list for things to do at exec time @@ -144,11 +144,12 @@ static const struct execsw **execsw; * MPSAFE */ static int -kern_execve(td, fname, argv, envv) +kern_execve(td, fname, argv, envv, mac_p) struct thread *td; char *fname; char **argv; char **envv; + struct mac *mac_p; { struct proc *p = td->td_proc; struct nameidata nd, *ndp; @@ -168,7 +169,9 @@ kern_execve(td, fname, argv, envv) int credential_changing; int textset; #ifdef MAC - int will_transition; + struct label interplabel; /* label of the interpreted vnode */ + struct label execlabel; /* optional label argument */ + int will_transition, interplabelvalid = 0; #endif imgp = &image_params; @@ -205,6 +208,7 @@ kern_execve(td, fname, argv, envv) imgp->proc = p; imgp->userspace_argv = argv; imgp->userspace_envv = envv; + imgp->execlabel = NULL; imgp->attr = &attr; imgp->argc = imgp->envc = 0; imgp->argv0 = NULL; @@ -219,6 +223,14 @@ kern_execve(td, fname, argv, envv) imgp->ps_strings = 0; imgp->auxarg_size = 0; +#ifdef MAC + error = mac_execve_enter(imgp, mac_p, &execlabel); + if (error) { + mtx_lock(&Giant); + goto exec_fail; + } +#endif + /* * Allocate temporary demand zeroed space for argument and * environment strings @@ -325,6 +337,11 @@ interpret: imgp->vp->v_vflag &= ~VV_TEXT; /* free name buffer and old vnode */ NDFREE(ndp, NDF_ONLY_PNBUF); +#ifdef MAC + mac_init_vnode_label(&interplabel); + mac_copy_vnode_label(&ndp->ni_vp->v_label, &interplabel); + interplabelvalid = 1; +#endif vput(ndp->ni_vp); vm_object_deallocate(imgp->object); imgp->object = NULL; @@ -432,6 +449,9 @@ interpret: * * Don't honor setuid/setgid if the filesystem prohibits it or if * the process is being traced. + * + * XXXMAC: For the time being, use NOSUID to also prohibit + * transitions on the file system. */ oldcred = p->p_ucred; credential_changing = 0; @@ -440,7 +460,8 @@ interpret: credential_changing |= (attr.va_mode & VSGID) && oldcred->cr_gid != attr.va_gid; #ifdef MAC - will_transition = mac_execve_will_transition(oldcred, imgp->vp); + will_transition = mac_execve_will_transition(oldcred, imgp->vp, + interplabelvalid ? &interplabel : NULL, imgp); credential_changing |= will_transition; #endif @@ -486,8 +507,10 @@ interpret: if (attr.va_mode & VSGID) change_egid(newcred, attr.va_gid); #ifdef MAC - if (will_transition) - mac_execve_transition(oldcred, newcred, imgp->vp); + if (will_transition) { + mac_execve_transition(oldcred, newcred, imgp->vp, + interplabelvalid ? &interplabel : NULL, imgp); + } #endif /* * Implement correct POSIX saved-id behavior. @@ -628,11 +651,21 @@ exec_fail: if (imgp->vmspace_destroyed) { /* sorry, no more process anymore. exit gracefully */ +#ifdef MAC + mac_execve_exit(imgp); + if (interplabelvalid) + mac_destroy_vnode_label(&interplabel); +#endif exit1(td, W_EXITCODE(0, SIGABRT)); /* NOT REACHED */ error = 0; } done2: +#ifdef MAC + mac_execve_exit(imgp); + if (interplabelvalid) + mac_destroy_vnode_label(&interplabel); +#endif mtx_unlock(&Giant); return (error); } @@ -658,7 +691,38 @@ execve(td, uap) } */ *uap; { - return (kern_execve(td, uap->fname, uap->argv, uap->envv)); +#ifdef MAC + return (kern_execve(td, uap->fname, uap->argv, uap->envv, NULL)); +#else + return (ENOSYS); +#endif +} + +#ifndef _SYS_SYSPROTO_H_ +struct __mac_execve_args { + char *fname; + char **argv; + char **envv; + struct mac *mac_p; +}; +#endif + +/* + * MPSAFE + */ +int +__mac_execve(td, uap) + struct thread *td; + struct __mac_execve_args /* { + syscallarg(char *) fname; + syscallarg(char **) argv; + syscallarg(char **) envv; + syscallarg(struct mac *) mac_p; + } */ *uap; +{ + + return (kern_execve(td, uap->fname, uap->argv, uap->envv, + uap->mac_p)); } int @@ -1022,7 +1086,7 @@ exec_check_permissions(imgp) td = curthread; /* XXXKSE */ #ifdef MAC - error = mac_check_vnode_exec(td->td_ucred, imgp->vp); + error = mac_check_vnode_exec(td->td_ucred, imgp->vp, imgp); if (error) return (error); #endif diff --git a/sys/kern/kern_mac.c b/sys/kern/kern_mac.c index e1f2531..9f76f05 100644 --- a/sys/kern/kern_mac.c +++ b/sys/kern/kern_mac.c @@ -47,6 +47,7 @@ #include <sys/param.h> #include <sys/extattr.h> +#include <sys/imgact.h> #include <sys/kernel.h> #include <sys/lock.h> #include <sys/malloc.h> @@ -1251,8 +1252,53 @@ mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, return (error); } +int +mac_execve_enter(struct image_params *imgp, struct mac *mac_p, + struct label *execlabelstorage) +{ + struct mac mac; + char *buffer; + int error; + + if (mac_p == NULL) + return (0); + + error = copyin(mac_p, &mac, sizeof(mac)); + if (error) + return (error); + + error = mac_check_structmac_consistent(&mac); + if (error) + return (error); + + buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); + error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); + if (error) { + free(buffer, M_MACTEMP); + return (error); + } + + mac_init_cred_label(execlabelstorage); + error = mac_internalize_cred_label(execlabelstorage, buffer); + free(buffer, M_MACTEMP); + if (error) { + mac_destroy_cred_label(execlabelstorage); + return (error); + } + imgp->execlabel = execlabelstorage; + return (0); +} + +void +mac_execve_exit(struct image_params *imgp) +{ + if (imgp->execlabel != NULL) + mac_destroy_cred_label(imgp->execlabel); +} + void -mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp) +mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp, + struct label *interpvnodelabel, struct image_params *imgp) { ASSERT_VOP_LOCKED(vp, "mac_execve_transition"); @@ -1260,11 +1306,13 @@ mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp) if (!mac_enforce_process && !mac_enforce_fs) return; - MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label); + MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label, + interpvnodelabel, imgp); } int -mac_execve_will_transition(struct ucred *old, struct vnode *vp) +mac_execve_will_transition(struct ucred *old, struct vnode *vp, + struct label *interpvnodelabel, struct image_params *imgp) { int result; @@ -1274,7 +1322,8 @@ mac_execve_will_transition(struct ucred *old, struct vnode *vp) return (0); result = 0; - MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label); + MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label, + interpvnodelabel, imgp); return (result); } @@ -1369,7 +1418,8 @@ mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, } int -mac_check_vnode_exec(struct ucred *cred, struct vnode *vp) +mac_check_vnode_exec(struct ucred *cred, struct vnode *vp, + struct image_params *imgp) { int error; @@ -1378,7 +1428,7 @@ mac_check_vnode_exec(struct ucred *cred, struct vnode *vp) if (!mac_enforce_process && !mac_enforce_fs) return (0); - MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label); + MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label, imgp); return (error); } diff --git a/sys/security/mac/mac_framework.c b/sys/security/mac/mac_framework.c index e1f2531..9f76f05 100644 --- a/sys/security/mac/mac_framework.c +++ b/sys/security/mac/mac_framework.c @@ -47,6 +47,7 @@ #include <sys/param.h> #include <sys/extattr.h> +#include <sys/imgact.h> #include <sys/kernel.h> #include <sys/lock.h> #include <sys/malloc.h> @@ -1251,8 +1252,53 @@ mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, return (error); } +int +mac_execve_enter(struct image_params *imgp, struct mac *mac_p, + struct label *execlabelstorage) +{ + struct mac mac; + char *buffer; + int error; + + if (mac_p == NULL) + return (0); + + error = copyin(mac_p, &mac, sizeof(mac)); + if (error) + return (error); + + error = mac_check_structmac_consistent(&mac); + if (error) + return (error); + + buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); + error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); + if (error) { + free(buffer, M_MACTEMP); + return (error); + } + + mac_init_cred_label(execlabelstorage); + error = mac_internalize_cred_label(execlabelstorage, buffer); + free(buffer, M_MACTEMP); + if (error) { + mac_destroy_cred_label(execlabelstorage); + return (error); + } + imgp->execlabel = execlabelstorage; + return (0); +} + +void +mac_execve_exit(struct image_params *imgp) +{ + if (imgp->execlabel != NULL) + mac_destroy_cred_label(imgp->execlabel); +} + void -mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp) +mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp, + struct label *interpvnodelabel, struct image_params *imgp) { ASSERT_VOP_LOCKED(vp, "mac_execve_transition"); @@ -1260,11 +1306,13 @@ mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp) if (!mac_enforce_process && !mac_enforce_fs) return; - MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label); + MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label, + interpvnodelabel, imgp); } int -mac_execve_will_transition(struct ucred *old, struct vnode *vp) +mac_execve_will_transition(struct ucred *old, struct vnode *vp, + struct label *interpvnodelabel, struct image_params *imgp) { int result; @@ -1274,7 +1322,8 @@ mac_execve_will_transition(struct ucred *old, struct vnode *vp) return (0); result = 0; - MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label); + MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label, + interpvnodelabel, imgp); return (result); } @@ -1369,7 +1418,8 @@ mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, } int -mac_check_vnode_exec(struct ucred *cred, struct vnode *vp) +mac_check_vnode_exec(struct ucred *cred, struct vnode *vp, + struct image_params *imgp) { int error; @@ -1378,7 +1428,7 @@ mac_check_vnode_exec(struct ucred *cred, struct vnode *vp) if (!mac_enforce_process && !mac_enforce_fs) return (0); - MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label); + MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label, imgp); return (error); } diff --git a/sys/security/mac/mac_framework.h b/sys/security/mac/mac_framework.h index 904ead3..3d56a17 100644 --- a/sys/security/mac/mac_framework.h +++ b/sys/security/mac/mac_framework.h @@ -84,6 +84,8 @@ typedef struct mac *mac_t; * Extended non-POSIX.1e interfaces that offer additional services * available from the userland and kernel MAC frameworks. */ +int mac_execve(char *fname, char **argv, char **envv, + mac_t _label); int mac_free(mac_t _label); int mac_from_text(mac_t *_label, const char *_text); int mac_get_fd(int _fd, mac_t _label); @@ -113,6 +115,7 @@ struct componentname; struct devfs_dirent; struct ifnet; struct ifreq; +struct image_params; struct ipq; struct mbuf; struct mount; @@ -129,7 +132,6 @@ struct vnode; #include <sys/acl.h> /* XXX acl_type_t */ -struct vop_refreshlabel_args; struct vop_setlabel_args; /* @@ -216,9 +218,14 @@ void mac_update_ipq(struct mbuf *fragment, struct ipq *ipq); * Labeling event operations: processes. */ void mac_create_cred(struct ucred *cred_parent, struct ucred *cred_child); +int mac_execve_enter(struct image_params *imgp, struct mac *mac_p, + struct label *execlabel); +void mac_execve_exit(struct image_params *imgp); void mac_execve_transition(struct ucred *old, struct ucred *new, - struct vnode *vp); -int mac_execve_will_transition(struct ucred *old, struct vnode *vp); + struct vnode *vp, struct label *interpvnodelabel, + struct image_params *imgp); +int mac_execve_will_transition(struct ucred *old, struct vnode *vp, + struct label *interpvnodelabel, struct image_params *imgp); void mac_create_proc0(struct ucred *cred); void mac_create_proc1(struct ucred *cred); void mac_thread_userret(struct thread *td); @@ -269,7 +276,8 @@ int mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp, struct componentname *cnp); int mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, acl_type_t type); -int mac_check_vnode_exec(struct ucred *cred, struct vnode *vp); +int mac_check_vnode_exec(struct ucred *cred, struct vnode *vp, + struct image_params *imgp); int mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type); int mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, diff --git a/sys/security/mac/mac_internal.h b/sys/security/mac/mac_internal.h index e1f2531..9f76f05 100644 --- a/sys/security/mac/mac_internal.h +++ b/sys/security/mac/mac_internal.h @@ -47,6 +47,7 @@ #include <sys/param.h> #include <sys/extattr.h> +#include <sys/imgact.h> #include <sys/kernel.h> #include <sys/lock.h> #include <sys/malloc.h> @@ -1251,8 +1252,53 @@ mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, return (error); } +int +mac_execve_enter(struct image_params *imgp, struct mac *mac_p, + struct label *execlabelstorage) +{ + struct mac mac; + char *buffer; + int error; + + if (mac_p == NULL) + return (0); + + error = copyin(mac_p, &mac, sizeof(mac)); + if (error) + return (error); + + error = mac_check_structmac_consistent(&mac); + if (error) + return (error); + + buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); + error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); + if (error) { + free(buffer, M_MACTEMP); + return (error); + } + + mac_init_cred_label(execlabelstorage); + error = mac_internalize_cred_label(execlabelstorage, buffer); + free(buffer, M_MACTEMP); + if (error) { + mac_destroy_cred_label(execlabelstorage); + return (error); + } + imgp->execlabel = execlabelstorage; + return (0); +} + +void +mac_execve_exit(struct image_params *imgp) +{ + if (imgp->execlabel != NULL) + mac_destroy_cred_label(imgp->execlabel); +} + void -mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp) +mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp, + struct label *interpvnodelabel, struct image_params *imgp) { ASSERT_VOP_LOCKED(vp, "mac_execve_transition"); @@ -1260,11 +1306,13 @@ mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp) if (!mac_enforce_process && !mac_enforce_fs) return; - MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label); + MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label, + interpvnodelabel, imgp); } int -mac_execve_will_transition(struct ucred *old, struct vnode *vp) +mac_execve_will_transition(struct ucred *old, struct vnode *vp, + struct label *interpvnodelabel, struct image_params *imgp) { int result; @@ -1274,7 +1322,8 @@ mac_execve_will_transition(struct ucred *old, struct vnode *vp) return (0); result = 0; - MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label); + MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label, + interpvnodelabel, imgp); return (result); } @@ -1369,7 +1418,8 @@ mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, } int -mac_check_vnode_exec(struct ucred *cred, struct vnode *vp) +mac_check_vnode_exec(struct ucred *cred, struct vnode *vp, + struct image_params *imgp) { int error; @@ -1378,7 +1428,7 @@ mac_check_vnode_exec(struct ucred *cred, struct vnode *vp) if (!mac_enforce_process && !mac_enforce_fs) return (0); - MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label); + MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label, imgp); return (error); } diff --git a/sys/security/mac/mac_net.c b/sys/security/mac/mac_net.c index e1f2531..9f76f05 100644 --- a/sys/security/mac/mac_net.c +++ b/sys/security/mac/mac_net.c @@ -47,6 +47,7 @@ #include <sys/param.h> #include <sys/extattr.h> +#include <sys/imgact.h> #include <sys/kernel.h> #include <sys/lock.h> #include <sys/malloc.h> @@ -1251,8 +1252,53 @@ mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, return (error); } +int +mac_execve_enter(struct image_params *imgp, struct mac *mac_p, + struct label *execlabelstorage) +{ + struct mac mac; + char *buffer; + int error; + + if (mac_p == NULL) + return (0); + + error = copyin(mac_p, &mac, sizeof(mac)); + if (error) + return (error); + + error = mac_check_structmac_consistent(&mac); + if (error) + return (error); + + buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); + error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); + if (error) { + free(buffer, M_MACTEMP); + return (error); + } + + mac_init_cred_label(execlabelstorage); + error = mac_internalize_cred_label(execlabelstorage, buffer); + free(buffer, M_MACTEMP); + if (error) { + mac_destroy_cred_label(execlabelstorage); + return (error); + } + imgp->execlabel = execlabelstorage; + return (0); +} + +void +mac_execve_exit(struct image_params *imgp) +{ + if (imgp->execlabel != NULL) + mac_destroy_cred_label(imgp->execlabel); +} + void -mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp) +mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp, + struct label *interpvnodelabel, struct image_params *imgp) { ASSERT_VOP_LOCKED(vp, "mac_execve_transition"); @@ -1260,11 +1306,13 @@ mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp) if (!mac_enforce_process && !mac_enforce_fs) return; - MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label); + MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label, + interpvnodelabel, imgp); } int -mac_execve_will_transition(struct ucred *old, struct vnode *vp) +mac_execve_will_transition(struct ucred *old, struct vnode *vp, + struct label *interpvnodelabel, struct image_params *imgp) { int result; @@ -1274,7 +1322,8 @@ mac_execve_will_transition(struct ucred *old, struct vnode *vp) return (0); result = 0; - MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label); + MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label, + interpvnodelabel, imgp); return (result); } @@ -1369,7 +1418,8 @@ mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, } int -mac_check_vnode_exec(struct ucred *cred, struct vnode *vp) +mac_check_vnode_exec(struct ucred *cred, struct vnode *vp, + struct image_params *imgp) { int error; @@ -1378,7 +1428,7 @@ mac_check_vnode_exec(struct ucred *cred, struct vnode *vp) if (!mac_enforce_process && !mac_enforce_fs) return (0); - MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label); + MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label, imgp); return (error); } diff --git a/sys/security/mac/mac_pipe.c b/sys/security/mac/mac_pipe.c index e1f2531..9f76f05 100644 --- a/sys/security/mac/mac_pipe.c +++ b/sys/security/mac/mac_pipe.c @@ -47,6 +47,7 @@ #include <sys/param.h> #include <sys/extattr.h> +#include <sys/imgact.h> #include <sys/kernel.h> #include <sys/lock.h> #include <sys/malloc.h> @@ -1251,8 +1252,53 @@ mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, return (error); } +int +mac_execve_enter(struct image_params *imgp, struct mac *mac_p, + struct label *execlabelstorage) +{ + struct mac mac; + char *buffer; + int error; + + if (mac_p == NULL) + return (0); + + error = copyin(mac_p, &mac, sizeof(mac)); + if (error) + return (error); + + error = mac_check_structmac_consistent(&mac); + if (error) + return (error); + + buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); + error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); + if (error) { + free(buffer, M_MACTEMP); + return (error); + } + + mac_init_cred_label(execlabelstorage); + error = mac_internalize_cred_label(execlabelstorage, buffer); + free(buffer, M_MACTEMP); + if (error) { + mac_destroy_cred_label(execlabelstorage); + return (error); + } + imgp->execlabel = execlabelstorage; + return (0); +} + +void +mac_execve_exit(struct image_params *imgp) +{ + if (imgp->execlabel != NULL) + mac_destroy_cred_label(imgp->execlabel); +} + void -mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp) +mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp, + struct label *interpvnodelabel, struct image_params *imgp) { ASSERT_VOP_LOCKED(vp, "mac_execve_transition"); @@ -1260,11 +1306,13 @@ mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp) if (!mac_enforce_process && !mac_enforce_fs) return; - MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label); + MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label, + interpvnodelabel, imgp); } int -mac_execve_will_transition(struct ucred *old, struct vnode *vp) +mac_execve_will_transition(struct ucred *old, struct vnode *vp, + struct label *interpvnodelabel, struct image_params *imgp) { int result; @@ -1274,7 +1322,8 @@ mac_execve_will_transition(struct ucred *old, struct vnode *vp) return (0); result = 0; - MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label); + MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label, + interpvnodelabel, imgp); return (result); } @@ -1369,7 +1418,8 @@ mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, } int -mac_check_vnode_exec(struct ucred *cred, struct vnode *vp) +mac_check_vnode_exec(struct ucred *cred, struct vnode *vp, + struct image_params *imgp) { int error; @@ -1378,7 +1428,7 @@ mac_check_vnode_exec(struct ucred *cred, struct vnode *vp) if (!mac_enforce_process && !mac_enforce_fs) return (0); - MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label); + MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label, imgp); return (error); } diff --git a/sys/security/mac/mac_policy.h b/sys/security/mac/mac_policy.h index fff7845..9bed8ff 100644 --- a/sys/security/mac/mac_policy.h +++ b/sys/security/mac/mac_policy.h @@ -242,9 +242,13 @@ struct mac_policy_ops { void (*mpo_create_cred)(struct ucred *parent_cred, struct ucred *child_cred); void (*mpo_execve_transition)(struct ucred *old, struct ucred *new, - struct vnode *vp, struct label *vnodelabel); + struct vnode *vp, struct label *vnodelabel, + struct label *interpvnodelabel, + struct image_params *imgp); int (*mpo_execve_will_transition)(struct ucred *old, - struct vnode *vp, struct label *vnodelabel); + struct vnode *vp, struct label *vnodelabel, + struct label *interpvnodelabel, + struct image_params *imgp); void (*mpo_create_proc0)(struct ucred *cred); void (*mpo_create_proc1)(struct ucred *cred); void (*mpo_relabel_cred)(struct ucred *cred, @@ -338,7 +342,7 @@ struct mac_policy_ops { int (*mpo_check_vnode_deleteacl)(struct ucred *cred, struct vnode *vp, struct label *label, acl_type_t type); int (*mpo_check_vnode_exec)(struct ucred *cred, struct vnode *vp, - struct label *label); + struct label *label, struct image_params *imgp); int (*mpo_check_vnode_getacl)(struct ucred *cred, struct vnode *vp, struct label *label, acl_type_t type); int (*mpo_check_vnode_getextattr)(struct ucred *cred, diff --git a/sys/security/mac/mac_process.c b/sys/security/mac/mac_process.c index e1f2531..9f76f05 100644 --- a/sys/security/mac/mac_process.c +++ b/sys/security/mac/mac_process.c @@ -47,6 +47,7 @@ #include <sys/param.h> #include <sys/extattr.h> +#include <sys/imgact.h> #include <sys/kernel.h> #include <sys/lock.h> #include <sys/malloc.h> @@ -1251,8 +1252,53 @@ mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, return (error); } +int +mac_execve_enter(struct image_params *imgp, struct mac *mac_p, + struct label *execlabelstorage) +{ + struct mac mac; + char *buffer; + int error; + + if (mac_p == NULL) + return (0); + + error = copyin(mac_p, &mac, sizeof(mac)); + if (error) + return (error); + + error = mac_check_structmac_consistent(&mac); + if (error) + return (error); + + buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); + error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); + if (error) { + free(buffer, M_MACTEMP); + return (error); + } + + mac_init_cred_label(execlabelstorage); + error = mac_internalize_cred_label(execlabelstorage, buffer); + free(buffer, M_MACTEMP); + if (error) { + mac_destroy_cred_label(execlabelstorage); + return (error); + } + imgp->execlabel = execlabelstorage; + return (0); +} + +void +mac_execve_exit(struct image_params *imgp) +{ + if (imgp->execlabel != NULL) + mac_destroy_cred_label(imgp->execlabel); +} + void -mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp) +mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp, + struct label *interpvnodelabel, struct image_params *imgp) { ASSERT_VOP_LOCKED(vp, "mac_execve_transition"); @@ -1260,11 +1306,13 @@ mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp) if (!mac_enforce_process && !mac_enforce_fs) return; - MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label); + MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label, + interpvnodelabel, imgp); } int -mac_execve_will_transition(struct ucred *old, struct vnode *vp) +mac_execve_will_transition(struct ucred *old, struct vnode *vp, + struct label *interpvnodelabel, struct image_params *imgp) { int result; @@ -1274,7 +1322,8 @@ mac_execve_will_transition(struct ucred *old, struct vnode *vp) return (0); result = 0; - MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label); + MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label, + interpvnodelabel, imgp); return (result); } @@ -1369,7 +1418,8 @@ mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, } int -mac_check_vnode_exec(struct ucred *cred, struct vnode *vp) +mac_check_vnode_exec(struct ucred *cred, struct vnode *vp, + struct image_params *imgp) { int error; @@ -1378,7 +1428,7 @@ mac_check_vnode_exec(struct ucred *cred, struct vnode *vp) if (!mac_enforce_process && !mac_enforce_fs) return (0); - MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label); + MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label, imgp); return (error); } diff --git a/sys/security/mac/mac_syscalls.c b/sys/security/mac/mac_syscalls.c index e1f2531..9f76f05 100644 --- a/sys/security/mac/mac_syscalls.c +++ b/sys/security/mac/mac_syscalls.c @@ -47,6 +47,7 @@ #include <sys/param.h> #include <sys/extattr.h> +#include <sys/imgact.h> #include <sys/kernel.h> #include <sys/lock.h> #include <sys/malloc.h> @@ -1251,8 +1252,53 @@ mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, return (error); } +int +mac_execve_enter(struct image_params *imgp, struct mac *mac_p, + struct label *execlabelstorage) +{ + struct mac mac; + char *buffer; + int error; + + if (mac_p == NULL) + return (0); + + error = copyin(mac_p, &mac, sizeof(mac)); + if (error) + return (error); + + error = mac_check_structmac_consistent(&mac); + if (error) + return (error); + + buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); + error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); + if (error) { + free(buffer, M_MACTEMP); + return (error); + } + + mac_init_cred_label(execlabelstorage); + error = mac_internalize_cred_label(execlabelstorage, buffer); + free(buffer, M_MACTEMP); + if (error) { + mac_destroy_cred_label(execlabelstorage); + return (error); + } + imgp->execlabel = execlabelstorage; + return (0); +} + +void +mac_execve_exit(struct image_params *imgp) +{ + if (imgp->execlabel != NULL) + mac_destroy_cred_label(imgp->execlabel); +} + void -mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp) +mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp, + struct label *interpvnodelabel, struct image_params *imgp) { ASSERT_VOP_LOCKED(vp, "mac_execve_transition"); @@ -1260,11 +1306,13 @@ mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp) if (!mac_enforce_process && !mac_enforce_fs) return; - MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label); + MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label, + interpvnodelabel, imgp); } int -mac_execve_will_transition(struct ucred *old, struct vnode *vp) +mac_execve_will_transition(struct ucred *old, struct vnode *vp, + struct label *interpvnodelabel, struct image_params *imgp) { int result; @@ -1274,7 +1322,8 @@ mac_execve_will_transition(struct ucred *old, struct vnode *vp) return (0); result = 0; - MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label); + MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label, + interpvnodelabel, imgp); return (result); } @@ -1369,7 +1418,8 @@ mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, } int -mac_check_vnode_exec(struct ucred *cred, struct vnode *vp) +mac_check_vnode_exec(struct ucred *cred, struct vnode *vp, + struct image_params *imgp) { int error; @@ -1378,7 +1428,7 @@ mac_check_vnode_exec(struct ucred *cred, struct vnode *vp) if (!mac_enforce_process && !mac_enforce_fs) return (0); - MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label); + MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label, imgp); return (error); } diff --git a/sys/security/mac/mac_system.c b/sys/security/mac/mac_system.c index e1f2531..9f76f05 100644 --- a/sys/security/mac/mac_system.c +++ b/sys/security/mac/mac_system.c @@ -47,6 +47,7 @@ #include <sys/param.h> #include <sys/extattr.h> +#include <sys/imgact.h> #include <sys/kernel.h> #include <sys/lock.h> #include <sys/malloc.h> @@ -1251,8 +1252,53 @@ mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, return (error); } +int +mac_execve_enter(struct image_params *imgp, struct mac *mac_p, + struct label *execlabelstorage) +{ + struct mac mac; + char *buffer; + int error; + + if (mac_p == NULL) + return (0); + + error = copyin(mac_p, &mac, sizeof(mac)); + if (error) + return (error); + + error = mac_check_structmac_consistent(&mac); + if (error) + return (error); + + buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); + error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); + if (error) { + free(buffer, M_MACTEMP); + return (error); + } + + mac_init_cred_label(execlabelstorage); + error = mac_internalize_cred_label(execlabelstorage, buffer); + free(buffer, M_MACTEMP); + if (error) { + mac_destroy_cred_label(execlabelstorage); + return (error); + } + imgp->execlabel = execlabelstorage; + return (0); +} + +void +mac_execve_exit(struct image_params *imgp) +{ + if (imgp->execlabel != NULL) + mac_destroy_cred_label(imgp->execlabel); +} + void -mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp) +mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp, + struct label *interpvnodelabel, struct image_params *imgp) { ASSERT_VOP_LOCKED(vp, "mac_execve_transition"); @@ -1260,11 +1306,13 @@ mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp) if (!mac_enforce_process && !mac_enforce_fs) return; - MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label); + MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label, + interpvnodelabel, imgp); } int -mac_execve_will_transition(struct ucred *old, struct vnode *vp) +mac_execve_will_transition(struct ucred *old, struct vnode *vp, + struct label *interpvnodelabel, struct image_params *imgp) { int result; @@ -1274,7 +1322,8 @@ mac_execve_will_transition(struct ucred *old, struct vnode *vp) return (0); result = 0; - MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label); + MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label, + interpvnodelabel, imgp); return (result); } @@ -1369,7 +1418,8 @@ mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, } int -mac_check_vnode_exec(struct ucred *cred, struct vnode *vp) +mac_check_vnode_exec(struct ucred *cred, struct vnode *vp, + struct image_params *imgp) { int error; @@ -1378,7 +1428,7 @@ mac_check_vnode_exec(struct ucred *cred, struct vnode *vp) if (!mac_enforce_process && !mac_enforce_fs) return (0); - MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label); + MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label, imgp); return (error); } diff --git a/sys/security/mac/mac_vfs.c b/sys/security/mac/mac_vfs.c index e1f2531..9f76f05 100644 --- a/sys/security/mac/mac_vfs.c +++ b/sys/security/mac/mac_vfs.c @@ -47,6 +47,7 @@ #include <sys/param.h> #include <sys/extattr.h> +#include <sys/imgact.h> #include <sys/kernel.h> #include <sys/lock.h> #include <sys/malloc.h> @@ -1251,8 +1252,53 @@ mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, return (error); } +int +mac_execve_enter(struct image_params *imgp, struct mac *mac_p, + struct label *execlabelstorage) +{ + struct mac mac; + char *buffer; + int error; + + if (mac_p == NULL) + return (0); + + error = copyin(mac_p, &mac, sizeof(mac)); + if (error) + return (error); + + error = mac_check_structmac_consistent(&mac); + if (error) + return (error); + + buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); + error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); + if (error) { + free(buffer, M_MACTEMP); + return (error); + } + + mac_init_cred_label(execlabelstorage); + error = mac_internalize_cred_label(execlabelstorage, buffer); + free(buffer, M_MACTEMP); + if (error) { + mac_destroy_cred_label(execlabelstorage); + return (error); + } + imgp->execlabel = execlabelstorage; + return (0); +} + +void +mac_execve_exit(struct image_params *imgp) +{ + if (imgp->execlabel != NULL) + mac_destroy_cred_label(imgp->execlabel); +} + void -mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp) +mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp, + struct label *interpvnodelabel, struct image_params *imgp) { ASSERT_VOP_LOCKED(vp, "mac_execve_transition"); @@ -1260,11 +1306,13 @@ mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp) if (!mac_enforce_process && !mac_enforce_fs) return; - MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label); + MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label, + interpvnodelabel, imgp); } int -mac_execve_will_transition(struct ucred *old, struct vnode *vp) +mac_execve_will_transition(struct ucred *old, struct vnode *vp, + struct label *interpvnodelabel, struct image_params *imgp) { int result; @@ -1274,7 +1322,8 @@ mac_execve_will_transition(struct ucred *old, struct vnode *vp) return (0); result = 0; - MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label); + MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label, + interpvnodelabel, imgp); return (result); } @@ -1369,7 +1418,8 @@ mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, } int -mac_check_vnode_exec(struct ucred *cred, struct vnode *vp) +mac_check_vnode_exec(struct ucred *cred, struct vnode *vp, + struct image_params *imgp) { int error; @@ -1378,7 +1428,7 @@ mac_check_vnode_exec(struct ucred *cred, struct vnode *vp) if (!mac_enforce_process && !mac_enforce_fs) return (0); - MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label); + MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label, imgp); return (error); } diff --git a/sys/sys/imgact.h b/sys/sys/imgact.h index 16b6e74..7455f66 100644 --- a/sys/sys/imgact.h +++ b/sys/sys/imgact.h @@ -38,6 +38,7 @@ #define MAXSHELLCMDLEN 128 +struct label; struct sysentvec; struct thread; struct vm_object; @@ -46,6 +47,7 @@ struct image_params { struct proc *proc; /* our process struct */ char **userspace_argv; /* system call argument */ char **userspace_envv; /* system call argument */ + struct label *execlabel; /* optional exec label */ struct vnode *vp; /* pointer to vnode of file to exec */ struct vm_object *object; /* The vm object for this vp */ struct vattr *attr; /* attributes of file */ diff --git a/sys/sys/mac.h b/sys/sys/mac.h index 904ead3..3d56a17 100644 --- a/sys/sys/mac.h +++ b/sys/sys/mac.h @@ -84,6 +84,8 @@ typedef struct mac *mac_t; * Extended non-POSIX.1e interfaces that offer additional services * available from the userland and kernel MAC frameworks. */ +int mac_execve(char *fname, char **argv, char **envv, + mac_t _label); int mac_free(mac_t _label); int mac_from_text(mac_t *_label, const char *_text); int mac_get_fd(int _fd, mac_t _label); @@ -113,6 +115,7 @@ struct componentname; struct devfs_dirent; struct ifnet; struct ifreq; +struct image_params; struct ipq; struct mbuf; struct mount; @@ -129,7 +132,6 @@ struct vnode; #include <sys/acl.h> /* XXX acl_type_t */ -struct vop_refreshlabel_args; struct vop_setlabel_args; /* @@ -216,9 +218,14 @@ void mac_update_ipq(struct mbuf *fragment, struct ipq *ipq); * Labeling event operations: processes. */ void mac_create_cred(struct ucred *cred_parent, struct ucred *cred_child); +int mac_execve_enter(struct image_params *imgp, struct mac *mac_p, + struct label *execlabel); +void mac_execve_exit(struct image_params *imgp); void mac_execve_transition(struct ucred *old, struct ucred *new, - struct vnode *vp); -int mac_execve_will_transition(struct ucred *old, struct vnode *vp); + struct vnode *vp, struct label *interpvnodelabel, + struct image_params *imgp); +int mac_execve_will_transition(struct ucred *old, struct vnode *vp, + struct label *interpvnodelabel, struct image_params *imgp); void mac_create_proc0(struct ucred *cred); void mac_create_proc1(struct ucred *cred); void mac_thread_userret(struct thread *td); @@ -269,7 +276,8 @@ int mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp, struct componentname *cnp); int mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, acl_type_t type); -int mac_check_vnode_exec(struct ucred *cred, struct vnode *vp); +int mac_check_vnode_exec(struct ucred *cred, struct vnode *vp, + struct image_params *imgp); int mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type); int mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, diff --git a/sys/sys/mac_policy.h b/sys/sys/mac_policy.h index fff7845..9bed8ff 100644 --- a/sys/sys/mac_policy.h +++ b/sys/sys/mac_policy.h @@ -242,9 +242,13 @@ struct mac_policy_ops { void (*mpo_create_cred)(struct ucred *parent_cred, struct ucred *child_cred); void (*mpo_execve_transition)(struct ucred *old, struct ucred *new, - struct vnode *vp, struct label *vnodelabel); + struct vnode *vp, struct label *vnodelabel, + struct label *interpvnodelabel, + struct image_params *imgp); int (*mpo_execve_will_transition)(struct ucred *old, - struct vnode *vp, struct label *vnodelabel); + struct vnode *vp, struct label *vnodelabel, + struct label *interpvnodelabel, + struct image_params *imgp); void (*mpo_create_proc0)(struct ucred *cred); void (*mpo_create_proc1)(struct ucred *cred); void (*mpo_relabel_cred)(struct ucred *cred, @@ -338,7 +342,7 @@ struct mac_policy_ops { int (*mpo_check_vnode_deleteacl)(struct ucred *cred, struct vnode *vp, struct label *label, acl_type_t type); int (*mpo_check_vnode_exec)(struct ucred *cred, struct vnode *vp, - struct label *label); + struct label *label, struct image_params *imgp); int (*mpo_check_vnode_getacl)(struct ucred *cred, struct vnode *vp, struct label *label, acl_type_t type); int (*mpo_check_vnode_getextattr)(struct ucred *cred, |