#include <sys/persona.h>
#include <sys/sysent.h>
#include <sys/reason.h>
+#include <IOKit/IOBSD.h> /* IOTaskHasEntitlement() */
#ifdef CONFIG_32BIT_TELEMETRY
#include <sys/kasl.h>
return current_proc()->p_ppid;
}
-int
+uint64_t
proc_selfcsflags(void)
{
- return current_proc()->p_csflags;
+ return (uint64_t)current_proc()->p_csflags;
+}
+
+int
+proc_csflags(proc_t p, uint64_t *flags)
+{
+ if (p && flags) {
+ *flags = (uint64_t)p->p_csflags;
+ return 0;
+ }
+ return EINVAL;
}
uint32_t
{
proc_t p;
+ if (size <= 0) {
+ return;
+ }
+
+ bzero(buf, size);
+
if ((p = proc_find(pid)) != PROC_NULL) {
strlcpy(buf, &p->p_comm[0], size);
proc_rele(p);
return NULLVP;
}
+int
+proc_gettty(proc_t p, vnode_t *vp)
+{
+ if (!p || !vp) {
+ return EINVAL;
+ }
+
+ struct session *procsp = proc_session(p);
+ int err = EINVAL;
+
+ if (procsp != SESSION_NULL) {
+ session_lock(procsp);
+ vnode_t ttyvp = procsp->s_ttyvp;
+ int ttyvid = procsp->s_ttyvid;
+ session_unlock(procsp);
+
+ if (ttyvp) {
+ if (vnode_getwithvid(ttyvp, ttyvid) == 0) {
+ *vp = ttyvp;
+ err = 0;
+ }
+ } else {
+ err = ENOENT;
+ }
+
+ session_rele(procsp);
+ }
+
+ return err;
+}
+
+int
+proc_gettty_dev(proc_t p, dev_t *dev)
+{
+ struct session *procsp = proc_session(p);
+ boolean_t has_tty = FALSE;
+
+ if (procsp != SESSION_NULL) {
+ session_lock(procsp);
+
+ struct tty * tp = SESSION_TP(procsp);
+ if (tp != TTY_NULL) {
+ *dev = tp->t_dev;
+ has_tty = TRUE;
+ }
+
+ session_unlock(procsp);
+ session_rele(procsp);
+ }
+
+ if (has_tty) {
+ return 0;
+ } else {
+ return EINVAL;
+ }
+}
+
int
proc_selfexecutableargs(uint8_t *buf, size_t *buflen)
{
case CS_OPS_IDENTITY:
case CS_OPS_BLOB:
case CS_OPS_TEAMID:
+ case CS_OPS_CLEAR_LV:
break; /* not restricted to root */
default:
if (forself == 0 && kauth_cred_issuser(kauth_cred_get()) != TRUE) {
case CS_OPS_SET_STATUS:
case CS_OPS_CLEARINSTALLER:
case CS_OPS_CLEARPLATFORM:
+ case CS_OPS_CLEAR_LV:
if ((error = mac_proc_check_set_cs_info(current_proc(), pt, ops))) {
goto out;
}
break;
}
+ case CS_OPS_CLEAR_LV: {
+ /*
+ * This option is used to remove library validation from
+ * a running process. This is used in plugin architectures
+ * when a program needs to load untrusted libraries. This
+ * allows the process to maintain library validation as
+ * long as possible, then drop it only when required.
+ * Once a process has loaded the untrusted library,
+ * relying on library validation in the future will
+ * not be effective. An alternative is to re-exec
+ * your application without library validation, or
+ * fork an untrusted child.
+ */
+#ifdef CONFIG_EMBEDDED
+ // On embedded platforms, we don't support dropping LV
+ error = ENOTSUP;
+#else
+ /*
+ * if we have the flag set, and the caller wants
+ * to remove it, and they're entitled to, then
+ * we remove it from the csflags
+ *
+ * NOTE: We are fine to poke into the task because
+ * we get a ref to pt when we do the proc_find
+ * at the beginning of this function.
+ *
+ * We also only allow altering ourselves.
+ */
+ if (forself == 1 && IOTaskHasEntitlement(pt->task, CLEAR_LV_ENTITLEMENT)) {
+ proc_lock(pt);
+ pt->p_csflags &= (~(CS_REQUIRE_LV | CS_FORCED_LV));
+ proc_unlock(pt);
+ error = 0;
+ } else {
+ error = EPERM;
+ }
+#endif
+ break;
+ }
case CS_OPS_BLOB: {
void *start;
size_t length;
return KERN_SUCCESS;
}
+bool
+proc_is_traced(proc_t p)
+{
+ bool ret = FALSE;
+ assert(p != PROC_NULL);
+ proc_lock(p);
+ if (p->p_lflag & P_LTRACED) {
+ ret = TRUE;
+ }
+ proc_unlock(p);
+ return ret;
+}
+
#ifdef CONFIG_32BIT_TELEMETRY
void
proc_log_32bit_telemetry(proc_t p)
* Get proc name and parent proc name; if the parent execs, we'll get a
* garbled name.
*/
- bytes_printed = snprintf(signature_cur_end,
+ bytes_printed = scnprintf(signature_cur_end,
signature_buf_end - signature_cur_end,
"%s,%s,", p->p_name,
(p->p_pptr ? p->p_pptr->p_name : ""));
identity = "";
}
- bytes_printed = snprintf(signature_cur_end,
+ bytes_printed = scnprintf(signature_cur_end,
signature_buf_end - signature_cur_end,
"%s,%s", teamid, identity);