microsoft / win32-app-isolation

Tools and documentation for Win32 app isolation
MIT License
1.26k stars 33 forks source link

[Inquiry]: How to grant access to NUL device within AppContainer #73

Open wfjsw opened 1 month ago

wfjsw commented 1 month ago

Description

I am trying to get a sandbox running with currently available AppContainer primitives. When running applications inside the AppContainer, I noticed that it is impossible to write to NUL device:

D:\>echo a > NUL
Access is denied.
Traceback (most recent call last):
  File "D:\ComfyUI\env\lib\site-packages\dill\_dill.py", line 156, in get_file_type
    f = open(os.devnull, *args, **kwargs)
PermissionError: [Errno 13] Permission denied: 'nul'

What ACL / capabilities should I adjust to fix this?

cchavez-msft commented 2 weeks ago

Hi, @wfjsw

Thank you so much for opening this issue. We currently don't have a way to fix this. Nevertheless, to better assist you, may I please ask for more details to better understand the scenario? Like what is the purpose of doing this? Please let us know.

wfjsw commented 2 weeks ago

I want to run some Python application and Git binary inside a AppContainer, and they frequently use NUL as a replacement for /dev/null. Permission wise this seems to be overlooked, and I'm not exactly sure why they need this exact thing, but they are pretty required everywhere.

Anyway, I figured out a way to grant access to ALL APPLICATION PACKAGES to NUL with elevated process:

var strAllAppPackage = "ALL APPLICATION PACKAGES\0";

var status = Pinvoke.GetNamedSecurityInfo(
    "\\\\.\\NUL", SeObjectType.FileObject,
    SecurityInformation.Dacl,
    out _, out _,
    out var oldAcl, out _,
    out var secDesc);
if (status != 0) {
    throw new InvalidOperationException($"Failed to get security info: {status}");
}

IntPtr newAcl;
unsafe {
    fixed (char* strAllAppPackagePtr = strAllAppPackage) {
        var explicitAccess = new ExplicitAccess {
            grfAccessPermissions = AccessMask.GenericRead | AccessMask.GenericWrite,
            grfAccessMode = AccessMode.Grant,
            grfInheritance = InheritanceType.NoInheritance,
            Trustee = new Trustee {
                pMultipleTrustee = IntPtr.Zero,
                MultipleTrusteeOperation = MultipleTrusteeOperation.NoMultipleTrustee,
                TrusteeForm = TrusteeForm.TrusteeIsName,
                TrusteeType = TrusteeType.WellKnownGroup,
                ptstrName = (IntPtr) strAllAppPackagePtr,
            }
        };

        var explicitAccessList = new ExplicitAccess[] { explicitAccess };

        status = Pinvoke.SetEntriesInAcl(
            1, explicitAccessList, oldAcl, out newAcl);
        if (status != 0) {
            throw new InvalidOperationException($"Failed to set entries in ACL: {status}");
        }
    }
}

status = Pinvoke.SetNamedSecurityInfo(
    "\\\\.\\NUL", SeObjectType.FileObject,
    SecurityInformation.Dacl,
    IntPtr.Zero, IntPtr.Zero,
    newAcl, IntPtr.Zero);
if (status == 5) {
    // Access denied
    return 5;
} else if (status != 0) {
    throw new InvalidOperationException($"Failed to set security info: {status}");
}