From 4d15aeb193b2c68f1d38666c317f8d3734f5f083 Mon Sep 17 00:00:00 2001 From: Apple Date: Tue, 22 Aug 2017 18:28:26 +0000 Subject: [PATCH] xnu-3789.70.16.tar.gz --- bsd/kern/kern_malloc.c | 3 + bsd/kern/posix_sem.c | 2 +- bsd/net/dlil.c | 4 +- bsd/net/if_var.h | 3 + bsd/net/ndrv.c | 1 + bsd/netinet/flow_divert.c | 3 + bsd/netinet/igmp.c | 11 +++ bsd/netinet/igmp.h | 1 + bsd/netinet6/in6.c | 13 +++ bsd/netinet6/in6_mcast.c | 2 + bsd/netinet6/nd6_rtr.c | 6 ++ bsd/netkey/key.c | 180 +++++++++++++++++++--------------- bsd/sys/attr.h | 5 +- bsd/vfs/vfs_attrlist.c | 17 +++- bsd/vm/dp_backing_file.c | 11 --- config/MasterVersion | 2 +- iokit/Kernel/IOUserClient.cpp | 29 +++++- libkern/kxld/kxld_util.c | 20 +++- libkern/os/log_encode.h | 20 +++- 19 files changed, 228 insertions(+), 105 deletions(-) diff --git a/bsd/kern/kern_malloc.c b/bsd/kern/kern_malloc.c index b75284fbd..d33382ec3 100644 --- a/bsd/kern/kern_malloc.c +++ b/bsd/kern/kern_malloc.c @@ -720,6 +720,9 @@ __MALLOC_ZONE( } } + if (elem && (flags & M_ZERO)) + bzero(elem, size); + return (elem); } diff --git a/bsd/kern/posix_sem.c b/bsd/kern/posix_sem.c index 54b92f059..ca7ee4c6a 100644 --- a/bsd/kern/posix_sem.c +++ b/bsd/kern/posix_sem.c @@ -413,7 +413,7 @@ sem_open(proc_t p, struct sem_open_args *uap, user_addr_t *retval) * Preallocate everything we might need up front to avoid taking * and dropping the lock, opening us up to race conditions. */ - MALLOC_ZONE(pnbuf, caddr_t, MAXPATHLEN, M_NAMEI, M_WAITOK); + MALLOC_ZONE(pnbuf, caddr_t, MAXPATHLEN, M_NAMEI, M_WAITOK | M_ZERO); if (pnbuf == NULL) { error = ENOSPC; goto bad; diff --git a/bsd/net/dlil.c b/bsd/net/dlil.c index 84fb0898f..b38d4e597 100644 --- a/bsd/net/dlil.c +++ b/bsd/net/dlil.c @@ -8345,7 +8345,7 @@ sysctl_get_ports_used SYSCTL_HANDLER_ARGS flags = name[2]; ifnet_head_lock_shared(); - if (idx > if_index) { + if (!IF_INDEX_IN_RANGE(idx)) { ifnet_head_done(); error = ENOENT; goto done; @@ -8432,7 +8432,7 @@ sysctl_get_kao_frames SYSCTL_HANDLER_ARGS } ifnet_head_lock_shared(); - if (idx > if_index) { + if (!IF_INDEX_IN_RANGE(idx)) { ifnet_head_done(); error = ENOENT; goto done; diff --git a/bsd/net/if_var.h b/bsd/net/if_var.h index f608157ab..bd3bdeba7 100644 --- a/bsd/net/if_var.h +++ b/bsd/net/if_var.h @@ -1366,6 +1366,9 @@ typedef enum { #define IF_LLADDR(_ifp) \ (LLADDR(SDL(((_ifp)->if_lladdr)->ifa_addr))) +#define IF_INDEX_IN_RANGE(_ind_) ((_ind_) > 0 && \ + (unsigned int)(_ind_) <= (unsigned int)if_index) + __private_extern__ void ifnet_lock_assert(struct ifnet *, ifnet_lock_assert_t); __private_extern__ void ifnet_lock_shared(struct ifnet *ifp); __private_extern__ void ifnet_lock_exclusive(struct ifnet *ifp); diff --git a/bsd/net/ndrv.c b/bsd/net/ndrv.c index e171b48f3..87b6a7749 100644 --- a/bsd/net/ndrv.c +++ b/bsd/net/ndrv.c @@ -337,6 +337,7 @@ ndrv_bind(struct socket *so, struct sockaddr *nam, __unused struct proc *p) return(ENOMEM); bcopy((caddr_t) sa, (caddr_t) np->nd_laddr, sizeof(struct sockaddr_ndrv)); dname = (char *) sa->snd_name; + np->nd_laddr->snd_len = sizeof(struct sockaddr_ndrv); if (*dname == '\0') return(EINVAL); #if NDRV_DEBUG diff --git a/bsd/netinet/flow_divert.c b/bsd/netinet/flow_divert.c index b531933cc..1e46e42c4 100644 --- a/bsd/netinet/flow_divert.c +++ b/bsd/netinet/flow_divert.c @@ -3377,6 +3377,9 @@ flow_divert_token_set(struct socket *so, struct sockopt *sopt) error = flow_divert_packet_get_tlv(token, 0, FLOW_DIVERT_TLV_KEY_UNIT, sizeof(key_unit), (void *)&key_unit, NULL); if (!error) { key_unit = ntohl(key_unit); + if (key_unit >= GROUP_COUNT_MAX) { + key_unit = 0; + } } else if (error != ENOENT) { FDLOG(LOG_ERR, &nil_pcb, "Failed to get the key unit from the token: %d", error); goto done; diff --git a/bsd/netinet/igmp.c b/bsd/netinet/igmp.c index da146da81..f2cd0966e 100644 --- a/bsd/netinet/igmp.c +++ b/bsd/netinet/igmp.c @@ -1737,6 +1737,17 @@ igmp_input(struct mbuf *m, int off) * Validate length based on source count. */ nsrc = ntohs(igmpv3->igmp_numsrc); + /* + * The max vaue of nsrc is limited by the + * MTU of the network on which the datagram + * is received + */ + if (nsrc < 0 || nsrc > IGMP_V3_QUERY_MAX_SRCS) { + IGMPSTAT_INC(igps_rcv_tooshort); + OIGMPSTAT_INC(igps_rcv_tooshort); + m_freem(m); + return; + } srclen = sizeof(struct in_addr) * nsrc; if (igmplen < (IGMP_V3_QUERY_MINLEN + srclen)) { IGMPSTAT_INC(igps_rcv_tooshort); diff --git a/bsd/netinet/igmp.h b/bsd/netinet/igmp.h index 28352317d..271b9855c 100644 --- a/bsd/netinet/igmp.h +++ b/bsd/netinet/igmp.h @@ -105,6 +105,7 @@ struct igmpv3 { /*struct in_addr igmp_sources[1];*/ /* source addresses */ }; #define IGMP_V3_QUERY_MINLEN 12 +#define IGMP_V3_QUERY_MAX_SRCS 366 /* From RFC 3376, section 4.1.8 */ #define IGMP_EXP(x) (((x) >> 4) & 0x07) #define IGMP_MANT(x) ((x) & 0x0f) #define IGMP_QRESV(x) (((x) >> 4) & 0x0f) diff --git a/bsd/netinet6/in6.c b/bsd/netinet6/in6.c index 976839dd1..559815be5 100644 --- a/bsd/netinet6/in6.c +++ b/bsd/netinet6/in6.c @@ -1327,6 +1327,19 @@ in6_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp, bcopy(&ifr->ifr_addr, &sin6, sizeof (sin6)); sa6 = &sin6; break; + case SIOCGIFDSTADDR: + case SIOCSIFDSTADDR: + case SIOCGIFBRDADDR: + case SIOCSIFBRDADDR: + case SIOCGIFNETMASK: + case SIOCSIFNETMASK: + case SIOCGIFADDR: + case SIOCSIFADDR: + case SIOCAIFADDR: + case SIOCDIFADDR: + /* Do not handle these AF_INET commands in AF_INET6 path */ + error = EINVAL; + goto done; } /* diff --git a/bsd/netinet6/in6_mcast.c b/bsd/netinet6/in6_mcast.c index dd27747f7..1fc7aca03 100644 --- a/bsd/netinet6/in6_mcast.c +++ b/bsd/netinet6/in6_mcast.c @@ -2470,6 +2470,8 @@ in6p_leave_group(struct inpcb *inp, struct sockopt *sopt) ip6_sprintf(&gsa->sin6.sin6_addr))); ifp = in6p_lookup_mcast_ifp(inp, &gsa->sin6); } else { + if (!IF_INDEX_IN_RANGE(ifindex)) + return (EADDRNOTAVAIL); ifnet_head_lock_shared(); ifp = ifindex2ifnet[ifindex]; ifnet_head_done(); diff --git a/bsd/netinet6/nd6_rtr.c b/bsd/netinet6/nd6_rtr.c index 0d6c9f044..be938f59e 100644 --- a/bsd/netinet6/nd6_rtr.c +++ b/bsd/netinet6/nd6_rtr.c @@ -1040,6 +1040,12 @@ defrtrlist_ioctl(u_long cmd, caddr_t data) dr0.ifp = dr_ifp; ifnet_head_done(); + if (ND_IFINFO(dr_ifp) == NULL || + !ND_IFINFO(dr_ifp)->initialized) { + error = ENXIO; + break; + } + if (IN6_IS_SCOPE_EMBED(&dr0.rtaddr)) { uint16_t *scope = &dr0.rtaddr.s6_addr16[1]; diff --git a/bsd/netkey/key.c b/bsd/netkey/key.c index 7e1a6061f..a82188ec9 100644 --- a/bsd/netkey/key.c +++ b/bsd/netkey/key.c @@ -9266,6 +9266,82 @@ bzero_keys(const struct sadb_msghdr *mh) } } +static int +key_validate_address_pair(struct sadb_address *src0, + struct sadb_address *dst0) +{ + u_int plen = 0; + + /* check upper layer protocol */ + if (src0->sadb_address_proto != dst0->sadb_address_proto) { + ipseclog((LOG_DEBUG, "key_parse: upper layer protocol mismatched.\n")); + PFKEY_STAT_INCREMENT(pfkeystat.out_invaddr); + return (EINVAL); + } + + /* check family */ + if (PFKEY_ADDR_SADDR(src0)->sa_family != + PFKEY_ADDR_SADDR(dst0)->sa_family) { + ipseclog((LOG_DEBUG, "key_parse: address family mismatched.\n")); + PFKEY_STAT_INCREMENT(pfkeystat.out_invaddr); + return (EINVAL); + } + if (PFKEY_ADDR_SADDR(src0)->sa_len != + PFKEY_ADDR_SADDR(dst0)->sa_len) { + ipseclog((LOG_DEBUG, + "key_parse: address struct size mismatched.\n")); + PFKEY_STAT_INCREMENT(pfkeystat.out_invaddr); + return (EINVAL); + } + + switch (PFKEY_ADDR_SADDR(src0)->sa_family) { + case AF_INET: + if (PFKEY_ADDR_SADDR(src0)->sa_len != sizeof(struct sockaddr_in)) { + PFKEY_STAT_INCREMENT(pfkeystat.out_invaddr); + return (EINVAL); + } + break; + case AF_INET6: + if (PFKEY_ADDR_SADDR(src0)->sa_len != sizeof(struct sockaddr_in6)) { + PFKEY_STAT_INCREMENT(pfkeystat.out_invaddr); + return (EINVAL); + } + break; + default: + ipseclog((LOG_DEBUG, + "key_parse: unsupported address family.\n")); + PFKEY_STAT_INCREMENT(pfkeystat.out_invaddr); + return (EAFNOSUPPORT); + } + + switch (PFKEY_ADDR_SADDR(src0)->sa_family) { + case AF_INET: + plen = sizeof(struct in_addr) << 3; + break; + case AF_INET6: + plen = sizeof(struct in6_addr) << 3; + break; + default: + plen = 0; /*fool gcc*/ + break; + } + + /* check max prefix length */ + if (src0->sadb_address_prefixlen > plen || + dst0->sadb_address_prefixlen > plen) { + ipseclog((LOG_DEBUG, + "key_parse: illegal prefixlen.\n")); + PFKEY_STAT_INCREMENT(pfkeystat.out_invaddr); + return (EINVAL); + } + + /* + * prefixlen == 0 is valid because there can be a case when + * all addresses are matched. + */ + return (0); +} + /* * parse sadb_msg buffer to process PFKEYv2, * and create a data to response if needed. @@ -9438,91 +9514,41 @@ key_parse( goto senderror; } - /* check field of upper layer protocol and address family */ - if (mh.ext[SADB_EXT_ADDRESS_SRC] != NULL - && mh.ext[SADB_EXT_ADDRESS_DST] != NULL) { - struct sadb_address *src0, *dst0; - u_int plen; - - src0 = (struct sadb_address *)(mh.ext[SADB_EXT_ADDRESS_SRC]); - dst0 = (struct sadb_address *)(mh.ext[SADB_EXT_ADDRESS_DST]); - - /* check upper layer protocol */ - if (src0->sadb_address_proto != dst0->sadb_address_proto) { - ipseclog((LOG_DEBUG, "key_parse: upper layer protocol mismatched.\n")); - PFKEY_STAT_INCREMENT(pfkeystat.out_invaddr); - error = EINVAL; + /* Validate address fields for matching families, lengths, etc. */ + void *src0 = mh.ext[SADB_EXT_ADDRESS_SRC]; + void *dst0 = mh.ext[SADB_EXT_ADDRESS_DST]; + if (mh.ext[SADB_X_EXT_ADDR_RANGE_SRC_START] != NULL && + mh.ext[SADB_X_EXT_ADDR_RANGE_SRC_END] != NULL) { + + error = key_validate_address_pair((struct sadb_address *)(mh.ext[SADB_X_EXT_ADDR_RANGE_SRC_START]), + (struct sadb_address *)(mh.ext[SADB_X_EXT_ADDR_RANGE_SRC_END])); + if (error != 0) { goto senderror; } - - /* check family */ - if (PFKEY_ADDR_SADDR(src0)->sa_family != - PFKEY_ADDR_SADDR(dst0)->sa_family) { - ipseclog((LOG_DEBUG, "key_parse: address family mismatched.\n")); - PFKEY_STAT_INCREMENT(pfkeystat.out_invaddr); - error = EINVAL; - goto senderror; + + if (src0 == NULL) { + src0 = mh.ext[SADB_X_EXT_ADDR_RANGE_SRC_START]; } - if (PFKEY_ADDR_SADDR(src0)->sa_len != - PFKEY_ADDR_SADDR(dst0)->sa_len) { - ipseclog((LOG_DEBUG, - "key_parse: address struct size mismatched.\n")); - PFKEY_STAT_INCREMENT(pfkeystat.out_invaddr); - error = EINVAL; + } + if (mh.ext[SADB_X_EXT_ADDR_RANGE_DST_START] != NULL && + mh.ext[SADB_X_EXT_ADDR_RANGE_DST_END] != NULL) { + + error = key_validate_address_pair((struct sadb_address *)(mh.ext[SADB_X_EXT_ADDR_RANGE_DST_START]), + (struct sadb_address *)(mh.ext[SADB_X_EXT_ADDR_RANGE_DST_END])); + if (error != 0) { goto senderror; } - - switch (PFKEY_ADDR_SADDR(src0)->sa_family) { - case AF_INET: - if (PFKEY_ADDR_SADDR(src0)->sa_len != - sizeof(struct sockaddr_in)) { - PFKEY_STAT_INCREMENT(pfkeystat.out_invaddr); - error = EINVAL; - goto senderror; - } - break; - case AF_INET6: - if (PFKEY_ADDR_SADDR(src0)->sa_len != - sizeof(struct sockaddr_in6)) { - PFKEY_STAT_INCREMENT(pfkeystat.out_invaddr); - error = EINVAL; - goto senderror; - } - break; - default: - ipseclog((LOG_DEBUG, - "key_parse: unsupported address family.\n")); - PFKEY_STAT_INCREMENT(pfkeystat.out_invaddr); - error = EAFNOSUPPORT; - goto senderror; - } - - switch (PFKEY_ADDR_SADDR(src0)->sa_family) { - case AF_INET: - plen = sizeof(struct in_addr) << 3; - break; - case AF_INET6: - plen = sizeof(struct in6_addr) << 3; - break; - default: - plen = 0; /*fool gcc*/ - break; + + if (dst0 == NULL) { + dst0 = mh.ext[SADB_X_EXT_ADDR_RANGE_DST_START]; } - - /* check max prefix length */ - if (src0->sadb_address_prefixlen > plen || - dst0->sadb_address_prefixlen > plen) { - ipseclog((LOG_DEBUG, - "key_parse: illegal prefixlen.\n")); - PFKEY_STAT_INCREMENT(pfkeystat.out_invaddr); - error = EINVAL; + } + if (src0 != NULL && dst0 != NULL) { + error = key_validate_address_pair((struct sadb_address *)(src0), + (struct sadb_address *)(dst0)); + if (error != 0) { goto senderror; } - - /* - * prefixlen == 0 is valid because there can be a case when - * all addresses are matched. - */ } if (msg->sadb_msg_type >= sizeof(key_typesw)/sizeof(key_typesw[0]) || diff --git a/bsd/sys/attr.h b/bsd/sys/attr.h index 7f20dd8f7..3437f9cc7 100644 --- a/bsd/sys/attr.h +++ b/bsd/sys/attr.h @@ -506,8 +506,11 @@ typedef struct vol_attributes_attr { /* CMNEXT attributes extend the common attributes, but in the forkattr field */ #define ATTR_CMNEXT_RELPATH 0x00000004 #define ATTR_CMNEXT_PRIVATESIZE 0x00000008 +#ifdef PRIVATE +#define ATTR_CMNEXT_LINKID 0x00000010 +#endif /* PRIVATE */ -#define ATTR_CMNEXT_VALIDMASK 0x0000000c +#define ATTR_CMNEXT_VALIDMASK 0x0000001c #define ATTR_CMNEXT_SETMASK 0x00000000 /* Deprecated fork attributes */ diff --git a/bsd/vfs/vfs_attrlist.c b/bsd/vfs/vfs_attrlist.c index e9f323164..51eb4756f 100644 --- a/bsd/vfs/vfs_attrlist.c +++ b/bsd/vfs/vfs_attrlist.c @@ -536,6 +536,7 @@ static struct getattrlist_attrtab getattrlist_file_tab[] = { static struct getattrlist_attrtab getattrlist_common_extended_tab[] = { {ATTR_CMNEXT_RELPATH, 0, sizeof(struct attrreference), KAUTH_VNODE_READ_ATTRIBUTES}, {ATTR_CMNEXT_PRIVATESIZE, VATTR_BIT(va_private_size), sizeof(off_t), KAUTH_VNODE_READ_ATTRIBUTES}, + {ATTR_CMNEXT_LINKID, VATTR_BIT(va_fileid) | VATTR_BIT(va_linkid), sizeof(uint64_t), KAUTH_VNODE_READ_ATTRIBUTES}, {0, 0, 0, 0} }; @@ -596,7 +597,7 @@ static struct getattrlist_attrtab getattrlistbulk_common_extended_tab[] = { ATTR_CMN_DOCUMENT_ID | ATTR_CMN_GEN_COUNT | \ ATTR_CMN_DATA_PROTECT_FLAGS) -#define VFS_DFLT_ATT_CMN_EXT (ATTR_CMNEXT_PRIVATESIZE) +#define VFS_DFLT_ATTR_CMN_EXT (ATTR_CMNEXT_PRIVATESIZE | ATTR_CMNEXT_LINKID) #define VFS_DFLT_ATTR_DIR (ATTR_DIR_LINKCOUNT | ATTR_DIR_MOUNTSTATUS) @@ -1006,7 +1007,7 @@ getvolattrlist(vfs_context_t ctx, vnode_t vp, struct attrlist *alp, attrp->validattr.volattr = VFS_DFLT_ATTR_VOL; attrp->validattr.dirattr = VFS_DFLT_ATTR_DIR; attrp->validattr.fileattr = VFS_DFLT_ATTR_FILE; - attrp->validattr.forkattr = 0; + attrp->validattr.forkattr = VFS_DFLT_ATTR_CMN_EXT; attrp->nativeattr.commonattr = 0; attrp->nativeattr.volattr = 0; @@ -2183,6 +2184,18 @@ attr_pack_common_extended(struct vnode *vp, struct attrlist *alp, } } + if (alp->forkattr & ATTR_CMNEXT_LINKID) { + uint64_t linkid; + + if (VATTR_IS_SUPPORTED(vap, va_linkid)) + linkid = vap->va_linkid; + else + linkid = vap->va_fileid; + + ATTR_PACK8((*abp), linkid); + abp->actual.forkattr |= ATTR_CMNEXT_LINKID; + } + return 0; } diff --git a/bsd/vm/dp_backing_file.c b/bsd/vm/dp_backing_file.c index 2684c29dd..5548f11fd 100644 --- a/bsd/vm/dp_backing_file.c +++ b/bsd/vm/dp_backing_file.c @@ -61,7 +61,6 @@ #include #include #include -#include #include #include @@ -89,8 +88,6 @@ int macx_backing_store_recovery( __unused struct macx_backing_store_recovery_args *args) { - assert(FALSE); - return ENOTSUP; } @@ -105,8 +102,6 @@ int macx_backing_store_suspend( __unused struct macx_backing_store_suspend_args *args) { - assert(FALSE); - return ENOTSUP; } @@ -165,8 +160,6 @@ macx_triggers( if (flags & (SWAP_COMPACT_DISABLE | SWAP_COMPACT_ENABLE)) return (macx_backing_store_compaction(flags)); - assert(FALSE); - return ENOTSUP; } @@ -175,8 +168,6 @@ int macx_swapon( __unused struct macx_swapon_args *args) { - assert(FALSE); - return ENOTSUP; } @@ -190,8 +181,6 @@ int macx_swapoff( __unused struct macx_swapoff_args *args) { - assert(FALSE); - return ENOTSUP; } diff --git a/config/MasterVersion b/config/MasterVersion index 89b86ecd6..a02b1d1cb 100644 --- a/config/MasterVersion +++ b/config/MasterVersion @@ -1,4 +1,4 @@ -16.6.0 +16.7.0 # The first line of this file contains the master version number for the kernel. # All other instances of the kernel version in xnu are derived from this file. diff --git a/iokit/Kernel/IOUserClient.cpp b/iokit/Kernel/IOUserClient.cpp index d568aaca2..985e3b201 100644 --- a/iokit/Kernel/IOUserClient.cpp +++ b/iokit/Kernel/IOUserClient.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -1617,7 +1618,7 @@ IOMemoryMap * IOUserClient::mapClientMemory64( { IOReturn err; IOOptionBits options = 0; - IOMemoryDescriptor * memory; + IOMemoryDescriptor * memory = 0; IOMemoryMap * map = 0; err = clientMemoryForType( (UInt32) type, &options, &memory ); @@ -3666,7 +3667,7 @@ kern_return_t is_io_connect_unmap_memory_from_task { IOReturn err; IOOptionBits options = 0; - IOMemoryDescriptor * memory; + IOMemoryDescriptor * memory = 0; IOMemoryMap * map; CHECK( IOUserClient, connection, client ); @@ -3793,6 +3794,8 @@ kern_return_t is_io_connect_method_var_output args.structureInput = inband_input; args.structureInputSize = inband_inputCnt; + if (ool_input && (ool_input_size <= sizeof(io_struct_inband_t))) return (kIOReturnIPCError); + if (ool_input) inputMD = IOMemoryDescriptor::withAddressRange(ool_input, ool_input_size, kIODirectionOut | kIOMemoryMapCopyOnWrite, @@ -3888,6 +3891,9 @@ kern_return_t is_io_connect_method args.structureInput = inband_input; args.structureInputSize = inband_inputCnt; + if (ool_input && (ool_input_size <= sizeof(io_struct_inband_t))) return (kIOReturnIPCError); + if (ool_output && (*ool_output_size <= sizeof(io_struct_inband_t))) return (kIOReturnIPCError); + if (ool_input) inputMD = IOMemoryDescriptor::withAddressRange(ool_input, ool_input_size, kIODirectionOut | kIOMemoryMapCopyOnWrite, @@ -3973,6 +3979,9 @@ kern_return_t is_io_connect_async_method args.structureInput = inband_input; args.structureInputSize = inband_inputCnt; + if (ool_input && (ool_input_size <= sizeof(io_struct_inband_t))) return (kIOReturnIPCError); + if (ool_output && (*ool_output_size <= sizeof(io_struct_inband_t))) return (kIOReturnIPCError); + if (ool_input) inputMD = IOMemoryDescriptor::withAddressRange(ool_input, ool_input_size, kIODirectionOut | kIOMemoryMapCopyOnWrite, @@ -4862,6 +4871,9 @@ kern_return_t is_io_catalog_send_data( mach_msg_type_number_t inDataCount, kern_return_t * result) { +#if NO_KEXTD + return kIOReturnNotPrivileged; +#else /* NO_KEXTD */ OSObject * obj = 0; vm_offset_t data; kern_return_t kr = kIOReturnError; @@ -4879,6 +4891,16 @@ kern_return_t is_io_catalog_send_data( return kIOReturnBadArgument; } + if (!IOTaskHasEntitlement(current_task(), "com.apple.rootless.kext-management")) + { + OSString * taskName = IOCopyLogNameForPID(proc_selfpid()); + IOLog("IOCatalogueSendData(%s): Not entitled\n", taskName ? taskName->getCStringNoCopy() : ""); + OSSafeReleaseNULL(taskName); + // For now, fake success to not break applications relying on this function succeeding. + // See for more details. + return kIOReturnSuccess; + } + if (inData) { vm_map_offset_t map_data; @@ -5008,9 +5030,10 @@ kern_return_t is_io_catalog_send_data( } if (obj) obj->release(); - + *result = kr; return( KERN_SUCCESS); +#endif /* NO_KEXTD */ } /* Routine io_catalog_terminate */ diff --git a/libkern/kxld/kxld_util.c b/libkern/kxld/kxld_util.c index dcf39a26b..eee5dee72 100644 --- a/libkern/kxld/kxld_util.c +++ b/libkern/kxld/kxld_util.c @@ -62,7 +62,7 @@ static unsigned long bytes_freed = 0; #endif static KXLDLoggingCallback s_logging_callback = NULL; -static const char *s_callback_name = NULL; +static char s_callback_name[64] = "internal"; static void *s_callback_data = NULL; #if !KERNEL @@ -84,7 +84,18 @@ kxld_set_logging_callback(KXLDLoggingCallback logging_callback) void kxld_set_logging_callback_data(const char *name, void *user_data) { - s_callback_name = name; + if (name) { + (void)strlcpy(s_callback_name, name, sizeof(s_callback_name)); + /* disallow format strings in the kxld logging callback name */ + for (size_t i = 0; i < sizeof(s_callback_name); i++) { + if (s_callback_name[i] == '%') { + s_callback_name[i] = '.'; + } + } + } else { + (void)strlcpy(s_callback_name, "internal", sizeof(s_callback_name)); + } + s_callback_data = user_data; } @@ -97,14 +108,13 @@ kxld_log(KXLDLogSubsystem subsystem, KXLDLogLevel level, char stack_buffer[256]; char *alloc_buffer = NULL; char *format = stack_buffer; - const char *name = (s_callback_name) ? s_callback_name : "internal"; u_int length = 0; va_list ap; if (s_logging_callback) { length = snprintf(stack_buffer, sizeof(stack_buffer), "kxld[%s]: %s", - name, in_format); + s_callback_name, in_format); if (length >= sizeof(stack_buffer)) { length += 1; @@ -112,7 +122,7 @@ kxld_log(KXLDLogSubsystem subsystem, KXLDLogLevel level, if (!alloc_buffer) return; snprintf(alloc_buffer, length, "kxld[%s]: %s", - name, in_format); + s_callback_name, in_format); format = alloc_buffer; } diff --git a/libkern/os/log_encode.h b/libkern/os/log_encode.h index 88839fbd7..4f8afae5c 100644 --- a/libkern/os/log_encode.h +++ b/libkern/os/log_encode.h @@ -27,8 +27,9 @@ #include "log_encode_types.h" #include -#if KERNEL +#ifdef KERNEL #define isdigit(ch) (((ch) >= '0') && ((ch) <= '9')) +extern boolean_t doprnt_hide_pointers; #endif static bool @@ -138,7 +139,7 @@ _os_log_parse_annotated(char *annotated, const char **visibility, const char **l OS_ALWAYS_INLINE static inline bool -_os_log_encode_arg(const void *arg, uint16_t arg_len, os_log_value_type_t ctype, bool is_private, os_log_buffer_context_t context) +_os_log_encode_arg(void *arg, uint16_t arg_len, os_log_value_type_t ctype, bool is_private, os_log_buffer_context_t context) { os_log_buffer_value_t content = (os_log_buffer_value_t) &context->buffer->content[context->content_off]; size_t content_sz = sizeof(*content) + arg_len; @@ -146,6 +147,21 @@ _os_log_encode_arg(const void *arg, uint16_t arg_len, os_log_value_type_t ctype, #ifndef KERNEL bool obj_private = true; #endif + +#ifdef KERNEL + /* scrub kernel pointers */ + if (doprnt_hide_pointers && + ctype == OS_LOG_BUFFER_VALUE_TYPE_SCALAR && + arg_len >= sizeof(void *)) { + unsigned long long value = 0; + memcpy(&value, arg, arg_len); + + if (value >= VM_MIN_KERNEL_AND_KEXT_ADDRESS && value <= VM_MAX_KERNEL_ADDRESS) { + is_private = true; + bzero(arg, arg_len); + } + } +#endif content->type = ctype; content->flags = (is_private ? OS_LOG_CONTENT_FLAG_PRIVATE : 0); -- 2.45.2