Skip to content

Commit

Permalink
xnu-2782.40.9
Browse files Browse the repository at this point in the history
  • Loading branch information
Darwin authored and das committed Jun 4, 2017
1 parent 9df3d7b commit b1bb36c
Show file tree
Hide file tree
Showing 41 changed files with 709 additions and 350 deletions.
3 changes: 2 additions & 1 deletion bsd/dev/dtrace/fasttrap.c
Original file line number Diff line number Diff line change
Expand Up @@ -2230,7 +2230,8 @@ fasttrap_ioctl(dev_t dev, u_long cmd, user_addr_t arg, int md, cred_t *cr, int *
if ((p = proc_find(pid)) == PROC_NULL || p->p_stat == SIDL) {
if (p != PROC_NULL)
proc_rele(p);
return (ESRCH);
ret = ESRCH;
goto err;
}
// proc_lock(p);
// FIXME! How is this done on OS X?
Expand Down
6 changes: 6 additions & 0 deletions bsd/dev/i386/kern_machdep.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,9 @@ md_prepare_for_shutdown(
__unused char * command)
{
}

boolean_t
pie_required(cpu_type_t exectype __unused, cpu_subtype_t execsubtype __unused)
{
return FALSE;
}
2 changes: 2 additions & 0 deletions bsd/hfs/hfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -786,6 +786,8 @@ OSErr hfs_MountHFSVolume(struct hfsmount *hfsmp, HFSMasterDirectoryBlock *mdb,
OSErr hfs_MountHFSPlusVolume(struct hfsmount *hfsmp, HFSPlusVolumeHeader *vhp,
off_t embeddedOffset, u_int64_t disksize, struct proc *p, void *args, kauth_cred_t cred);

OSErr hfs_ValidateHFSPlusVolumeHeader(struct hfsmount *hfsmp, HFSPlusVolumeHeader *vhp);

extern int hfsUnmount(struct hfsmount *hfsmp, struct proc *p);

extern bool overflow_extents(struct filefork *fp);
Expand Down
40 changes: 40 additions & 0 deletions bsd/hfs/hfs_vfsops.c
Original file line number Diff line number Diff line change
Expand Up @@ -1620,6 +1620,12 @@ hfs_mountfs(struct vnode *devvp, struct mount *mp, struct hfs_mount_args *args,
hfsmp->hfs_logical_bytes = (uint64_t) hfsmp->hfs_logical_block_count * (uint64_t) hfsmp->hfs_logical_block_size;

mdb_offset = (daddr64_t)((embeddedOffset / log_blksize) + HFS_PRI_SECTOR(log_blksize));

if (bp) {
buf_markinvalid(bp);
buf_brelse(bp);
bp = NULL;
}
retval = (int)buf_meta_bread(devvp, HFS_PHYSBLK_ROUNDDOWN(mdb_offset, hfsmp->hfs_log_per_phys),
phys_blksize, cred, &bp);
if (retval) {
Expand All @@ -1639,6 +1645,40 @@ hfs_mountfs(struct vnode *devvp, struct mount *mp, struct hfs_mount_args *args,
vhp = (HFSPlusVolumeHeader*) mdbp;
}

retval = hfs_ValidateHFSPlusVolumeHeader(hfsmp, vhp);
if (retval)
goto error_exit;

/*
* If allocation block size is less than the physical block size,
* invalidate the buffer read in using native physical block size
* to ensure data consistency.
*
* HFS Plus reserves one allocation block for the Volume Header.
* If the physical size is larger, then when we read the volume header,
* we will also end up reading in the next allocation block(s).
* If those other allocation block(s) is/are modified, and then the volume
* header is modified, the write of the volume header's buffer will write
* out the old contents of the other allocation blocks.
*
* We assume that the physical block size is same as logical block size.
* The physical block size value is used to round down the offsets for
* reading and writing the primary and alternate volume headers.
*
* The same logic is also in hfs_MountHFSPlusVolume to ensure that
* hfs_mountfs, hfs_MountHFSPlusVolume and later are doing the I/Os
* using same block size.
*/
if (SWAP_BE32(vhp->blockSize) < hfsmp->hfs_physical_block_size) {
phys_blksize = hfsmp->hfs_logical_block_size;
hfsmp->hfs_physical_block_size = hfsmp->hfs_logical_block_size;
hfsmp->hfs_log_per_phys = 1;
// There should be one bp associated with devvp in buffer cache.
retval = buf_invalidateblks(devvp, 0, 0, 0);
if (retval)
goto error_exit;
}

if (isroot) {
hfs_root_unmounted_cleanly = ((SWAP_BE32(vhp->attributes) & kHFSVolumeUnmountedMask) != 0);
}
Expand Down
119 changes: 82 additions & 37 deletions bsd/hfs/hfs_vfsutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,62 @@ OSErr hfs_MountHFSVolume(struct hfsmount *hfsmp, HFSMasterDirectoryBlock *mdb,

#endif

//*******************************************************************************
//
// Sanity check Volume Header Block:
// Input argument *vhp is a pointer to a HFSPlusVolumeHeader block that has
// not been endian-swapped and represents the on-disk contents of this sector.
// This routine will not change the endianness of vhp block.
//
//*******************************************************************************
OSErr hfs_ValidateHFSPlusVolumeHeader(struct hfsmount *hfsmp, HFSPlusVolumeHeader *vhp)
{
u_int16_t signature;
u_int16_t hfs_version;
u_int32_t blockSize;

signature = SWAP_BE16(vhp->signature);
hfs_version = SWAP_BE16(vhp->version);

if (signature == kHFSPlusSigWord) {
if (hfs_version != kHFSPlusVersion) {
printf("hfs_ValidateHFSPlusVolumeHeader: invalid HFS+ version: %x\n", hfs_version);
return (EINVAL);
}
} else if (signature == kHFSXSigWord) {
if (hfs_version != kHFSXVersion) {
printf("hfs_ValidateHFSPlusVolumeHeader: invalid HFSX version: %x\n", hfs_version);
return (EINVAL);
}
} else {
/* Removed printf for invalid HFS+ signature because it gives
* false error for UFS root volume
*/
if (HFS_MOUNT_DEBUG) {
printf("hfs_ValidateHFSPlusVolumeHeader: unknown Volume Signature : %x\n", signature);
}
return (EINVAL);
}

/* Block size must be at least 512 and a power of 2 */
blockSize = SWAP_BE32(vhp->blockSize);
if (blockSize < 512 || !powerof2(blockSize)) {
if (HFS_MOUNT_DEBUG) {
printf("hfs_ValidateHFSPlusVolumeHeader: invalid blocksize (%d) \n", blockSize);
}
return (EINVAL);
}

if (blockSize < hfsmp->hfs_logical_block_size) {
if (HFS_MOUNT_DEBUG) {
printf("hfs_ValidateHFSPlusVolumeHeader: invalid physical blocksize (%d), hfs_logical_blocksize (%d) \n",
blockSize, hfsmp->hfs_logical_block_size);
}
return (EINVAL);
}
return 0;
}

//*******************************************************************************
// Routine: hfs_MountHFSPlusVolume
//
Expand Down Expand Up @@ -348,38 +404,17 @@ OSErr hfs_MountHFSPlusVolume(struct hfsmount *hfsmp, HFSPlusVolumeHeader *vhp,
signature = SWAP_BE16(vhp->signature);
hfs_version = SWAP_BE16(vhp->version);

if (signature == kHFSPlusSigWord) {
if (hfs_version != kHFSPlusVersion) {
printf("hfs_mount: invalid HFS+ version: %x\n", hfs_version);
return (EINVAL);
}
} else if (signature == kHFSXSigWord) {
if (hfs_version != kHFSXVersion) {
printf("hfs_mount: invalid HFSX version: %x\n", hfs_version);
return (EINVAL);
}
retval = hfs_ValidateHFSPlusVolumeHeader(hfsmp, vhp);
if (retval)
return retval;

if (signature == kHFSXSigWord) {
/* The in-memory signature is always 'H+'. */
signature = kHFSPlusSigWord;
hfsmp->hfs_flags |= HFS_X;
} else {
/* Removed printf for invalid HFS+ signature because it gives
* false error for UFS root volume
*/
if (HFS_MOUNT_DEBUG) {
printf("hfs_mounthfsplus: unknown Volume Signature : %x\n", signature);
}
return (EINVAL);
}

/* Block size must be at least 512 and a power of 2 */
blockSize = SWAP_BE32(vhp->blockSize);
if (blockSize < 512 || !powerof2(blockSize)) {
if (HFS_MOUNT_DEBUG) {
printf("hfs_mounthfsplus: invalid blocksize (%d) \n", blockSize);
}
return (EINVAL);
}

/* don't mount a writable volume if its dirty, it must be cleaned by fsck_hfs */
if ((hfsmp->hfs_flags & HFS_READ_ONLY) == 0 && hfsmp->jnl == NULL &&
(SWAP_BE32(vhp->attributes) & kHFSVolumeUnmountedMask) == 0) {
Expand All @@ -391,22 +426,32 @@ OSErr hfs_MountHFSPlusVolume(struct hfsmount *hfsmp, HFSPlusVolumeHeader *vhp,

/* Make sure we can live with the physical block size. */
if ((disksize & (hfsmp->hfs_logical_block_size - 1)) ||
(embeddedOffset & (hfsmp->hfs_logical_block_size - 1)) ||
(blockSize < hfsmp->hfs_logical_block_size)) {
(embeddedOffset & (hfsmp->hfs_logical_block_size - 1))) {
if (HFS_MOUNT_DEBUG) {
printf("hfs_mounthfsplus: invalid physical blocksize (%d), hfs_logical_blocksize (%d) \n",
blockSize, hfsmp->hfs_logical_block_size);
printf("hfs_mounthfsplus: hfs_logical_blocksize (%d) \n",
hfsmp->hfs_logical_block_size);
}
return (ENXIO);
}

/* If allocation block size is less than the physical
* block size, we assume that the physical block size
* is same as logical block size. The physical block
* size value is used to round down the offsets for
* reading and writing the primary and alternate volume
* headers at physical block boundary and will cause
* problems if it is less than the block size.
/*
* If allocation block size is less than the physical block size,
* same data could be cached in two places and leads to corruption.
*
* HFS Plus reserves one allocation block for the Volume Header.
* If the physical size is larger, then when we read the volume header,
* we will also end up reading in the next allocation block(s).
* If those other allocation block(s) is/are modified, and then the volume
* header is modified, the write of the volume header's buffer will write
* out the old contents of the other allocation blocks.
*
* We assume that the physical block size is same as logical block size.
* The physical block size value is used to round down the offsets for
* reading and writing the primary and alternate volume headers.
*
* The same logic to ensure good hfs_physical_block_size is also in
* hfs_mountfs so that hfs_mountfs, hfs_MountHFSPlusVolume and
* later are doing the I/Os using same block size.
*/
if (blockSize < hfsmp->hfs_physical_block_size) {
hfsmp->hfs_physical_block_size = hfsmp->hfs_logical_block_size;
Expand Down
39 changes: 29 additions & 10 deletions bsd/kern/kern_descrip.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ void fileport_releasefg(struct fileglob *fg);
/* We don't want these exported */

__private_extern__
int unlink1(vfs_context_t, struct nameidata *, int);
int unlink1(vfs_context_t, vnode_t, user_addr_t, enum uio_seg, int);

static void _fdrelse(struct proc * p, int fd);

Expand Down Expand Up @@ -1579,7 +1579,6 @@ fcntl_nocancel(proc_t p, struct fcntl_nocancel_args *uap, int32_t *retval)
* SPI (private) for unlinking a file starting from a dir fd
*/
case F_UNLINKFROM: {
struct nameidata nd;
user_addr_t pathname;

/* Check if this isn't a valid file descriptor */
Expand Down Expand Up @@ -1611,11 +1610,7 @@ fcntl_nocancel(proc_t p, struct fcntl_nocancel_args *uap, int32_t *retval)
}

/* Start the lookup relative to the file descriptor's vnode. */
NDINIT(&nd, DELETE, OP_UNLINK, USEDVP | AUDITVNPATH1, UIO_USERSPACE,
pathname, &context);
nd.ni_dvp = vp;

error = unlink1(&context, &nd, 0);
error = unlink1(&context, vp, pathname, UIO_USERSPACE, 0);

vnode_put(vp);
break;
Expand All @@ -1624,18 +1619,30 @@ fcntl_nocancel(proc_t p, struct fcntl_nocancel_args *uap, int32_t *retval)

case F_ADDSIGS:
case F_ADDFILESIGS:
case F_ADDFILESIGS_FOR_DYLD_SIM:
{
struct user_fsignatures fs;
kern_return_t kr;
vm_offset_t kernel_blob_addr;
vm_size_t kernel_blob_size;
int blob_add_flags = 0;

if (fp->f_type != DTYPE_VNODE) {
error = EBADF;
goto out;
}
vp = (struct vnode *)fp->f_data;
proc_fdunlock(p);

if (uap->cmd == F_ADDFILESIGS_FOR_DYLD_SIM) {
blob_add_flags |= MAC_VNODE_CHECK_DYLD_SIM;
if ((p->p_csflags & CS_KILL) == 0) {
proc_lock(p);
p->p_csflags |= CS_KILL;
proc_unlock(p);
}
}

error = vnode_getwithref(vp);
if (error)
goto outdrop;
Expand All @@ -1656,8 +1663,13 @@ fcntl_nocancel(proc_t p, struct fcntl_nocancel_args *uap, int32_t *retval)
goto outdrop;
}

if(ubc_cs_blob_get(vp, CPU_TYPE_ANY, fs.fs_file_start))
struct cs_blob * existing_blob = ubc_cs_blob_get(vp, CPU_TYPE_ANY, fs.fs_file_start);
if (existing_blob != NULL)
{
/* If this is for dyld_sim revalidate the blob */
if (uap->cmd == F_ADDFILESIGS_FOR_DYLD_SIM) {
error = ubc_cs_blob_revalidate(vp, existing_blob, blob_add_flags);
}
vnode_put(vp);
goto outdrop;
}
Expand Down Expand Up @@ -1690,6 +1702,8 @@ fcntl_nocancel(proc_t p, struct fcntl_nocancel_args *uap, int32_t *retval)
(void *) kernel_blob_addr,
kernel_blob_size);
} else /* F_ADDFILESIGS */ {
int resid;

error = vn_rdwr(UIO_READ,
vp,
(caddr_t) kernel_blob_addr,
Expand All @@ -1698,8 +1712,12 @@ fcntl_nocancel(proc_t p, struct fcntl_nocancel_args *uap, int32_t *retval)
UIO_SYSSPACE,
0,
kauth_cred_get(),
0,
&resid,
p);
if ((error == 0) && resid) {
/* kernel_blob_size rounded to a page size, but signature may be at end of file */
memset((void *)(kernel_blob_addr + (kernel_blob_size - resid)), 0x0, resid);
}
}

if (error) {
Expand All @@ -1714,7 +1732,8 @@ fcntl_nocancel(proc_t p, struct fcntl_nocancel_args *uap, int32_t *retval)
CPU_TYPE_ANY, /* not for a specific architecture */
fs.fs_file_start,
kernel_blob_addr,
kernel_blob_size);
kernel_blob_size,
blob_add_flags);
if (error) {
ubc_cs_blob_deallocate(kernel_blob_addr,
kernel_blob_size);
Expand Down
Loading

0 comments on commit b1bb36c

Please sign in to comment.