summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cmds/ntux_cmd_chmod.c285
1 files changed, 275 insertions, 10 deletions
diff --git a/src/cmds/ntux_cmd_chmod.c b/src/cmds/ntux_cmd_chmod.c
index 7be2bc8..773c8ea 100644
--- a/src/cmds/ntux_cmd_chmod.c
+++ b/src/cmds/ntux_cmd_chmod.c
@@ -6,12 +6,14 @@
#include <psxabi/sys_sysapi.h>
#include <psxabi/sys_stat.h>
+#include <psxabi/sys_path.h>
#include <psxabi/sys_errno.h>
#include <psxxfi/xfi_base.h>
#include <psxxfi/xfi_acl.h>
#include <psxxfi/xfi_fs.h>
#include <psxxfi/xfi_ofd.h>
+#include <psxxfi/xfi_path.h>
#include <psxxfi/xfi_unicode.h>
#include <ntapi/nt_object.h>
@@ -32,9 +34,22 @@
#define NTUX_OPT_MODE_PLUS (2)
#define NTUX_OPT_MODE_MINUS (3)
+#define NTUX_BUF_SIZE_64K (64*1024)
+
static const nt_sid sid_system = __SID_SYSTEM;
static const nt_sid_os sid_admins = __SID_ADMINISTRATORS;
+struct ntux_sd_buffer {
+ nt_sd_common_buffer sd;
+ uint32_t exbuf[512];
+};
+
+struct ntux_ace_any {
+ nt_ace_header header;
+ uint32_t mask;
+ uint32_t sid_start;
+};
+
static int ntux_cmd_chmod_ret(int fd, struct __ofd * ofd, void * hasync, int ret)
{
if (hasync)
@@ -67,15 +82,22 @@ int ntux_cmd_chmod(const struct ntux_driver_ctx * dctx, const char * dunit)
int32_t status;
int fdout;
int fdcwd;
+ int finherit;
int optmode;
const char * strmode;
const char * chmode;
const unsigned char * unit;
- nt_sd * srcsd;
- nt_sd_common_buffer dstsd;
+ char * ch;
+ struct ntux_sd_buffer sdbuf;
+ struct ntux_sd_buffer srcsd;
+ struct ntux_sd_buffer cntsd;
+ nt_sd_common_buffer * dstsd;
nt_sd_common_meta meta;
nt_sid * owner;
nt_sid * group;
+ nt_acl * dacl;
+ struct ntux_ace_any * srcace;
+ struct ntux_ace_any * dstace;
uint32_t access_owner;
uint32_t access_group;
uint32_t access_other;
@@ -83,20 +105,34 @@ int ntux_cmd_chmod(const struct ntux_driver_ctx * dctx, const char * dunit)
uint32_t ace_flags;
uint32_t sec_mask;
size_t size;
+ size_t addr;
+ size_t aceaddr;
+ size_t cntbufsize;
+ char * cntpath_utf8;
+ wchar16_t * cntpath_utf16;
+ int exacefilter;
+ size_t exacesize;
+ int exacecount;
+ int idx;
int fd = -1;
+ int cntfd = -1;
struct __ofd * ofd = 0;
+ struct __ofd * cntofd = 0;
+ void * cntbuf = 0;
void * hasync = 0;
- uint32_t buf[0x300] = {0};
+ char dummy = 0;
/* strmode */
- strmode = dctx->cctx->strmode ? dctx->cctx->strmode : (char *)buf;
+ strmode = dctx->cctx->strmode ? dctx->cctx->strmode : &dummy;
optmode = NTUX_OPT_MODE_NEUTRAL;
+ finherit = false;
ace_flags = 0;
for (chmode=strmode; *chmode; chmode++) {
switch (*chmode) {
case '=':
optmode = NTUX_OPT_MODE_EQUAL;
+ finherit = 0;
ace_flags = 0;
break;
@@ -129,6 +165,27 @@ int ntux_cmd_chmod(const struct ntux_driver_ctx * dctx, const char * dunit)
break;
+ case 'P':
+ switch (optmode) {
+ case NTUX_OPT_MODE_EQUAL:
+ case NTUX_OPT_MODE_PLUS:
+ finherit = true;
+ break;
+
+ case NTUX_OPT_MODE_MINUS:
+ finherit = false;
+ break;
+
+ default:
+ return ntux_cmd_chmod_ret(
+ 0,0,0,
+ NTUX_CUSTOM_ERROR(
+ dctx,
+ NTUX_ERR_FLEE_ERROR));
+ }
+
+ break;
+
default:
return ntux_cmd_chmod_ret(
0,0,0,
@@ -203,21 +260,19 @@ int ntux_cmd_chmod(const struct ntux_driver_ctx * dctx, const char * dunit)
NTUX_SYSTEM_ERROR(dctx));
/* srcsd */
- srcsd = (nt_sd *)buf;
-
if ((status = __xfi_query_security_object(
hasync,
NT_OWNER_SECURITY_INFORMATION
| NT_GROUP_SECURITY_INFORMATION
| NT_DACL_SECURITY_INFORMATION,
- srcsd,sizeof(buf),&size)))
+ &srcsd.sd.sd,sizeof(srcsd),&size)))
if (ntux_errno_set(dctx,ENXIO))
return ntux_cmd_chmod_ret(
fd,ofd,hasync,
NTUX_SYSTEM_ERROR(dctx));
if ((status = __xfi_acl_init_common_descriptor_meta(
- &meta,srcsd,
+ &meta,&srcsd.sd.sd,
NT_ACL_INIT_COMMON_DESCRIPTION_META_STRICT_MODE)))
if (ntux_errno_set(dctx,EBADF))
return ntux_cmd_chmod_ret(
@@ -239,8 +294,10 @@ int ntux_cmd_chmod(const struct ntux_driver_ctx * dctx, const char * dunit)
}
/* updated dacl */
+ dstsd = &sdbuf.sd;
+
__xfi_acl_init_common_descriptor(
- &dstsd,
+ dstsd,
owner ? owner : meta.owner,
group ? group : meta.group,
0,0,
@@ -248,11 +305,213 @@ int ntux_cmd_chmod(const struct ntux_driver_ctx * dctx, const char * dunit)
access_admin,meta.system_acc,
ace_flags);
+ if ((dstsd->sd.offset_dacl < dstsd->sd.offset_owner)
+ || (dstsd->sd.offset_dacl < dstsd->sd.offset_group)
+ || (dstsd->sd.offset_dacl < dstsd->sd.offset_sacl))
+ return ntux_cmd_chmod_ret(
+ fd,0,0,
+ NTUX_CUSTOM_ERROR(
+ dctx,
+ NTUX_ERR_FLOW_ERROR));
+
+ /* inherited ace's */
+ if (finherit) {
+ dstsd->sd.control = NT_SE_SELF_RELATIVE
+ | NT_SE_DACL_AUTO_INHERIT_REQ
+ | NT_SE_DACL_AUTO_INHERITED
+ | NT_SE_DACL_PRESENT;
+
+ /* cntofd */
+ cntbuf = 0; cntbufsize = NTUX_BUF_SIZE_64K;
+
+ if (__xfi_allocate_virtual_memory(
+ NT_CURRENT_PROCESS_HANDLE,
+ &cntbuf,
+ 0,
+ &cntbufsize,
+ NT_MEM_COMMIT,
+ NT_PAGE_READWRITE))
+ return ntux_cmd_chmod_ret(
+ fd,ofd,hasync,
+ NTUX_SYSTEM_ERROR(dctx));
+
+ if (__xfi_ofd_is_dir(ofd)) {
+ cntpath_utf16 = (wchar16_t *)cntbuf;
+
+ __xfi_path_conv_ofdat_utf16(
+ ofd,
+ (const wchar16_t[]){'.','.','/',0},
+ PSX_PATH_SYNTAX_ANY,
+ 4*sizeof(wchar16_t),
+ cntpath_utf16,
+ PSX_PATH_SYNTAX_POSIX_STRICT,
+ cntbufsize,
+ 0,0,PSX_PATH_CONV_RESOLVE_ELEMENT,
+ &cntofd);
+ } else {
+ cntpath_utf8 = cntbuf;
+
+ status = __xfi_path_conv_utf8(
+ fdcwd,
+ unit,
+ PSX_PATH_SYNTAX_POSIX_STRICT,
+ ntux_strlen((const char *)unit),
+ cntpath_utf8,
+ PSX_PATH_SYNTAX_POSIX_STRICT,
+ cntbufsize,
+ 0,0,PSX_PATH_CONV_RESOLVE_ELEMENT,
+ 0);
+
+ if (status) {
+ __xfi_free_virtual_memory(
+ NT_CURRENT_PROCESS_HANDLE,
+ &cntbuf,
+ &cntbufsize,
+ NT_MEM_RELEASE);
+
+ return ntux_cmd_chmod_ret(
+ fd,ofd,hasync,
+ NTUX_CUSTOM_ERROR(
+ dctx,
+ NTUX_ERR_FLOW_ERROR));
+ }
+
+ if ((cntpath_utf8[0] == '/') && cntpath_utf8[1]) {
+ for (ch=cntpath_utf8; *ch; ch++)
+ (void)0;
+
+ /* guard against an internal error */
+ if (ch[-1] != '/') {
+ for (--ch; *ch != '/'; ch--)
+ (void)0;
+
+ *ch = 0;
+
+ cntfd = __sys_openat(
+ fdcwd,
+ (const unsigned char *)cntpath_utf8,
+ 0,0);
+
+ if (cntfd >= 0)
+ if (!(cntofd = __xfi_ofd_ref_inc(cntfd)))
+ __sys_close(cntfd);
+ }
+ }
+ }
+
+ __xfi_free_virtual_memory(
+ NT_CURRENT_PROCESS_HANDLE,
+ &cntbuf,
+ &cntbufsize,
+ NT_MEM_RELEASE);
+
+ if (!cntofd)
+ return ntux_cmd_chmod_ret(
+ fd,ofd,hasync,
+ NTUX_CUSTOM_ERROR(
+ dctx,
+ NTUX_ERR_FLOW_ERROR));
+
+ status = __xfi_query_security_object(
+ cntofd->info.hfile,
+ NT_OWNER_SECURITY_INFORMATION
+ | NT_GROUP_SECURITY_INFORMATION
+ | NT_DACL_SECURITY_INFORMATION,
+ &cntsd.sd.sd,sizeof(cntsd),&size);
+
+ if (status) {
+ __xfi_ofd_ref_dec(cntofd);
+ __sys_close(cntfd);
+
+ return ntux_cmd_chmod_ret(
+ fd,ofd,hasync,
+ NTUX_SYSTEM_ERROR(dctx));
+ }
+
+ /* exacefilter */
+ exacefilter = __xfi_ofd_is_dir(ofd)
+ ? NT_ACE_CONTAINER_INHERIT
+ : NT_ACE_OBJECT_INHERIT;
+
+ /* exacecount, exacesize */
+ if (cntsd.sd.sd.offset_dacl) {
+ addr = (size_t)&cntsd.sd.sd;
+ addr += cntsd.sd.sd.offset_dacl;
+ dacl = (nt_acl *)addr;
+
+ addr += sizeof(*dacl);
+
+ exacecount = 0;
+ exacesize = 0;
+
+ for (idx=0; idx<dacl->ace_count; idx++) {
+ srcace = (struct ntux_ace_any *)addr;
+
+ if (srcace->header.ace_flags & exacefilter) {
+ exacecount++;
+ exacesize += srcace->header.ace_size;
+ }
+
+ addr += srcace->header.ace_size;
+ }
+
+
+ /* dstsd::dacl */
+ addr = (size_t)dstsd;
+ addr += dstsd->sd.offset_dacl;
+ dacl = (nt_acl *)addr;
+
+ if (dstsd->sd.offset_dacl + dacl->acl_size + exacesize > sizeof(sdbuf)) {
+ __xfi_ofd_ref_dec(cntofd);
+ __sys_close(cntfd);
+
+ return ntux_cmd_chmod_ret(
+ fd,ofd,hasync,
+ NTUX_BUFFER_ERROR(dctx));
+ }
+
+ dacl->acl_size += exacesize;
+ dacl->ace_count += exacecount;
+
+ /* pointer to dstsd's next ace */
+ aceaddr = addr;
+ aceaddr += sizeof(*dacl);
+
+ for (idx=0; idx<dacl->ace_count; idx++) {
+ dstace = (struct ntux_ace_any *)aceaddr;
+ aceaddr += dstace->header.ace_size;
+ }
+
+ dstace = (struct ntux_ace_any *)aceaddr;
+
+ /* copy container's ace's according to filter */
+ addr = (size_t)&cntsd.sd.sd;
+ addr += cntsd.sd.sd.offset_dacl;
+ dacl = (nt_acl *)addr;
+ addr += sizeof(*dacl);
+
+ for (idx=0; idx<dacl->ace_count; idx++) {
+ srcace = (struct ntux_ace_any *)addr;
+
+ if (srcace->header.ace_flags & exacefilter) {
+ ntux_memcpy(dstace,srcace,srcace->header.ace_size);
+ dstace->header.ace_flags = NT_ACE_INHERITED;
+
+ aceaddr += srcace->header.ace_size;
+ dstace = (struct ntux_ace_any *)aceaddr;
+ }
+
+ addr += srcace->header.ace_size;
+ }
+ }
+ }
+
+ /* finalize */
sec_mask = NT_DACL_SECURITY_INFORMATION;
sec_mask |= owner ? NT_OWNER_SECURITY_INFORMATION : 0;
if ((status = __xfi_set_security_object(
- hasync,sec_mask,&dstsd.sd)))
+ hasync,sec_mask,&dstsd->sd)))
if (ntux_errno_set(dctx,EPERM))
return ntux_cmd_chmod_ret(
fd,ofd,hasync,
@@ -261,6 +520,12 @@ int ntux_cmd_chmod(const struct ntux_driver_ctx * dctx, const char * dunit)
/* changes */
(void)fdout;
+ /* cntofd */
+ if (cntofd) {
+ __xfi_ofd_ref_dec(cntofd);
+ __sys_close(cntfd);
+ }
+
/* all done */
return ntux_cmd_chmod_ret(fd,ofd,hasync,0);
}