/***********************************************************/ /* ntux: native translation und extension */ /* Copyright (C) 2016--2018 Z. Gilboa */ /* Released under GPLv2 and GPLv3; see COPYING.NTUX. */ /***********************************************************/ #include #include #include #include #include #include #include #include #include "ntux_driver_impl.h" #include "ntux_nolibc_impl.h" #include "ntux_errinfo_impl.h" static int ntux_cmd_chmod_ret(int fd, struct __ofd * ofd, void * hasync, int ret) { if (hasync) ntapi->zw_close(hasync); if (ofd) __xfi_ofd_ref_dec(ofd); if (fd >= 0) __sys_close(fd); return ret; } int ntux_cmd_chmod(const struct ntux_driver_ctx * dctx, const char * dunit) { intptr_t ret; int32_t status; int fdout; int fdcwd; const unsigned char * unit; nt_sd * srcsd; nt_sd_common_buffer dstsd; nt_sd_common_meta meta; uint32_t access_owner; uint32_t access_group; uint32_t access_other; uint32_t access_admin; size_t size; int fd = -1; struct __ofd * ofd = 0; void * hasync = 0; uint32_t buf[0x300]; /* initial version: only support m+p */ if (!dctx->cctx->strmode || strcmp(dctx->cctx->strmode,"m+p")) return ntux_cmd_chmod_ret( 0,0,0, NTUX_CUSTOM_ERROR( dctx, NTUX_ERR_FLEE_ERROR)); /* init */ ntux_driver_set_ectx( dctx,0,dunit); unit = (const unsigned char *)dunit; /* fdctx */ fdout = ntux_driver_fdout(dctx); fdcwd = ntux_driver_fdcwd(dctx); /* fd */ if ((ret = __sys_openat(fdcwd,unit,0,0)) < 0) if (ntux_errno_set(dctx,ret)) return ntux_cmd_chmod_ret( 0,0,0, NTUX_SYSTEM_ERROR(dctx)); fd = ret; /* ofd */ if (!(ofd = __xfi_ofd_ref_inc(fd))) return ntux_cmd_chmod_ret( fd,0,0, NTUX_CUSTOM_ERROR( dctx, NTUX_ERR_FLOW_ERROR)); /* hasync */ if ((status = __xfi_fs_open_async( &hasync, ofd->info.hfile,0, NT_SEC_READ_CONTROL | NT_SEC_WRITE_DAC, NT_FILE_SHARE_READ | NT_FILE_SHARE_WRITE | NT_FILE_SHARE_DELETE))) return ntux_cmd_chmod_ret( fd,ofd,0, NTUX_SYSTEM_ERROR(dctx)); /* srcsd */ srcsd = (nt_sd *)buf; if ((status = ntapi->zw_query_security_object( hasync, NT_OWNER_SECURITY_INFORMATION | NT_GROUP_SECURITY_INFORMATION | NT_DACL_SECURITY_INFORMATION, srcsd,sizeof(buf),&size))) return ntux_cmd_chmod_ret( fd,ofd,hasync, NTUX_SYSTEM_ERROR(dctx)); if ((status = ntapi->acl_init_common_descriptor_meta( &meta,srcsd, NT_ACL_INIT_COMMON_DESCRIPTION_META_STRICT_MODE))) return ntux_cmd_chmod_ret( fd,ofd,hasync, NTUX_SYSTEM_ERROR(dctx)); /* source permissions */ access_owner = meta.owner_ace ? meta.owner_ace->mask : 0; access_group = meta.group_ace ? meta.group_ace->mask : 0; access_other = meta.other_ace ? meta.other_ace->mask : 0; /* initial version: only support m+p */ access_admin = access_owner | NT_SEC_WRITE_DAC; /* updated dacl */ ntapi->acl_init_common_descriptor( &dstsd, meta.owner,meta.group,0,0, access_owner,access_group,access_other, access_admin,meta.system_acc); if ((status = ntapi->zw_set_security_object( hasync, NT_DACL_SECURITY_INFORMATION, &dstsd.sd))) return ntux_cmd_chmod_ret( fd,ofd,hasync, NTUX_SYSTEM_ERROR(dctx)); /* changes */ (void)fdout; /* all done */ return ntux_cmd_chmod_ret(fd,ofd,hasync,0); }