X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/6601e61aa18bf4f09af135ff61fc7f4771d23b06..0c530ab8987f0ae6a1a3d9284f40182b88852816:/bsd/hfs/hfs_readwrite.c?ds=sidebyside diff --git a/bsd/hfs/hfs_readwrite.c b/bsd/hfs/hfs_readwrite.c index 91cf8b7f7..c3a2de87b 100644 --- a/bsd/hfs/hfs_readwrite.c +++ b/bsd/hfs/hfs_readwrite.c @@ -865,6 +865,18 @@ hfs_vnop_ioctl( struct vnop_ioctl_args /* { switch (ap->a_command) { + case HFS_RESIZE_PROGRESS: { + + vfsp = vfs_statfs(HFSTOVFS(hfsmp)); + if (suser(cred, NULL) && + kauth_cred_getuid(cred) != vfsp->f_owner) { + return (EACCES); /* must be owner of file system */ + } + if (!vnode_isvroot(vp)) { + return (EINVAL); + } + return hfs_resize_progress(hfsmp, (u_int32_t *)ap->a_data); + } case HFS_RESIZE_VOLUME: { u_int64_t newsize; u_int64_t cursize; @@ -1076,7 +1088,7 @@ hfs_vnop_ioctl( struct vnop_ioctl_args /* { dev_t dev = VTOC(vp)->c_dev; short flags; - struct ucred myucred; /* XXX ILLEGAL */ + struct ucred myucred; int num_files; int *file_ids = NULL; short *access = NULL; @@ -1090,6 +1102,9 @@ hfs_vnop_ioctl( struct vnop_ioctl_args /* { struct cnode *skip_cp = VTOC(vp); struct vfs_context my_context; + /* set up front for common exit code */ + my_context.vc_ucred = NOCRED; + /* first, return error if not run as root */ if (cred->cr_ruid != 0) { return EPERM; @@ -1160,6 +1175,12 @@ hfs_vnop_ioctl( struct vnop_ioctl_args /* { check_leaf = false; } + /* + * Create a templated credential; this credential may *NOT* + * be used unless instantiated with a kauth_cred_create(); + * there must be a correcponding kauth_cred_unref() when it + * is no longer in use (i.e. before it goes out of scope). + */ memset(&myucred, 0, sizeof(myucred)); myucred.cr_ref = 1; myucred.cr_uid = myucred.cr_ruid = myucred.cr_svuid = user_access_structp->uid; @@ -1174,7 +1195,7 @@ hfs_vnop_ioctl( struct vnop_ioctl_args /* { myucred.cr_gmuid = myucred.cr_uid; my_context.vc_proc = p; - my_context.vc_ucred = &myucred; + my_context.vc_ucred = kauth_cred_create(&myucred); /* Check access to each file_id passed in */ for (i = 0; i < num_files; i++) { @@ -1182,7 +1203,7 @@ hfs_vnop_ioctl( struct vnop_ioctl_args /* { cnid = (cnid_t) file_ids[i]; /* root always has access */ - if (!suser(&myucred, NULL)) { + if (!suser(my_context.vc_ucred, NULL)) { access[i] = 0; continue; } @@ -1198,7 +1219,7 @@ hfs_vnop_ioctl( struct vnop_ioctl_args /* { /* before calling CheckAccess(), check the target file for read access */ myPerms = DerivePermissionSummary(cnattr.ca_uid, cnattr.ca_gid, - cnattr.ca_mode, hfsmp->hfs_mp, &myucred, p ); + cnattr.ca_mode, hfsmp->hfs_mp, my_context.vc_ucred, p ); /* fail fast if no access */ @@ -1219,7 +1240,7 @@ hfs_vnop_ioctl( struct vnop_ioctl_args /* { } myaccess = do_access_check(hfsmp, &error, &cache, catkey.hfsPlus.parentID, - skip_cp, p, &myucred, dev); + skip_cp, p, my_context.vc_ucred, dev); if ( myaccess ) { access[i] = 0; // have access.. no errors to report @@ -1245,6 +1266,12 @@ hfs_vnop_ioctl( struct vnop_ioctl_args /* { hfs_unlock(VTOC(vp)); if (vnode_vtype(vp) == VDIR) { + /* + * XXX This code assumes that none of the + * XXX callbacks from vnode_authorize() will + * XXX take a persistent ref on the context + * XXX credential, which is a bad assumption. + */ myErr = vnode_authorize(vp, NULL, (KAUTH_VNODE_SEARCH | KAUTH_VNODE_LIST_DIRECTORY), &my_context); } else { myErr = vnode_authorize(vp, NULL, KAUTH_VNODE_READ_DATA, &my_context); @@ -1272,6 +1299,9 @@ hfs_vnop_ioctl( struct vnop_ioctl_args /* { release_pathbuff((char *) cache.haveaccess); release_pathbuff((char *) file_ids); release_pathbuff((char *) access); + /* clean up local context, if needed */ + if (IS_VALID_CRED(my_context.vc_ucred)) + kauth_cred_unref(&my_context.vc_ucred); return (error); } /* HFS_BULKACCESS */ @@ -2157,7 +2187,7 @@ hfs_truncate(struct vnode *vp, off_t length, int flags, int skipsetsize, if (length < filebytes) { while (filebytes > length) { - if ((filebytes - length) > HFS_BIGFILE_SIZE) { + if ((filebytes - length) > HFS_BIGFILE_SIZE && overflow_extents(fp)) { filebytes -= HFS_BIGFILE_SIZE; } else { filebytes = length; @@ -2169,7 +2199,7 @@ hfs_truncate(struct vnode *vp, off_t length, int flags, int skipsetsize, } } else if (length > filebytes) { while (filebytes < length) { - if ((length - filebytes) > HFS_BIGFILE_SIZE) { + if ((length - filebytes) > HFS_BIGFILE_SIZE && overflow_extents(fp)) { filebytes += HFS_BIGFILE_SIZE; } else { filebytes = length; @@ -2566,7 +2596,8 @@ hfs_vnop_bwrite(struct vnop_bwrite_args *ap) /* Trap B-Tree writes */ if ((VTOC(vp)->c_fileid == kHFSExtentsFileID) || (VTOC(vp)->c_fileid == kHFSCatalogFileID) || - (VTOC(vp)->c_fileid == kHFSAttributesFileID)) { + (VTOC(vp)->c_fileid == kHFSAttributesFileID) || + (vp == VTOHFS(vp)->hfc_filevp)) { /* * Swap and validate the node if it is in native byte order. @@ -2835,10 +2866,10 @@ out: lockflags = 0; } - // See comment up above about calls to hfs_fsync() - // - //if (retval == 0) - // retval = hfs_fsync(vp, MNT_WAIT, 0, p); + /* Push cnode's new extent data to disk. */ + if (retval == 0) { + (void) hfs_update(vp, MNT_WAIT); + } if (hfsmp->jnl) { if (cp->c_cnid < kHFSFirstUserCatalogNodeID) @@ -2932,7 +2963,7 @@ hfs_clonefile(struct vnode *vp, int blkstart, int blkcnt, int blksize) filesize = VTOF(vp)->ff_blocks * blksize; /* virtual file size */ writebase = blkstart * blksize; copysize = blkcnt * blksize; - iosize = bufsize = MIN(copysize, 4096 * 16); + iosize = bufsize = MIN(copysize, 128 * 1024); offset = 0; if (kmem_alloc(kernel_map, (vm_offset_t *)&bufp, bufsize)) {