Skip to content

"Permission denied" Win32Exception when using Process.Start #274

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
evanverneyfink opened this issue May 15, 2018 · 6 comments
Closed

"Permission denied" Win32Exception when using Process.Start #274

evanverneyfink opened this issue May 15, 2018 · 6 comments

Comments

@evanverneyfink
Copy link

I'm trying to run a third-party exe called MediaInfo through a lambda function written in .NET Core 2.0. There's a good example of this (from about 2 years ago, and written in Python) here:

https://aws.amazon.com/blogs/compute/extracting-video-metadata-using-lambda-and-mediainfo/

I've built the MediaInfo code as instructed and included it in my project. I can see the resulting binary is included in my published .zip file. I've also verified that the same binary runs when invoked from a Node.js lambda function. However, when attempting to run it from my .NET lambda function, I get the following exception:

Exception: System.ComponentModel.Win32Exception (0x80004005): Permission denied
    at Interop.Sys.ForkAndExecProcess(String filename, String[] argv, String[] envp, String cwd, Boolean redirectStdin, Boolean redirectStdout, Boolean redirectStderr, Int32& lpChildPid, Int32& stdinFd, Int32& stdoutFd, Int32& stderrFd)
    at System.Diagnostics.Process.StartCore(ProcessStartInfo startInfo)
    at System.Diagnostics.Process.Start()
    at MediaInfoTest.Function.FunctionHandler(String input, ILambdaContext context) in C:\\Dev\\Research\\MediaInfoTest\\MediaInfoTest\\Function.cs:line 40

After doing some research, I found some Node.js examples where they had similar permission problems, and one of the suggested fixes was to add the following:

process.env["PATH"] = process.env["PATH"] + ":" + process.env["LAMBDA_TASK_ROOT"];

I believe I've done the .NET equivalent with the following line:

Environment.SetEnvironmentVariable("PATH",
        $"{Environment.GetEnvironmentVariable("PATH")}:{Environment.GetEnvironmentVariable("LAMBDA_TASK_ROOT")}");

I've verified once this is done that the LAMBDA_TASK_ROOT path has been added to the PATH variable, but unfortunately this didn't seem to make a difference.

I've provided a sample project that reproduces the issue here:

https://github.com/evanverneyfink/MediaInfoTest

Any ideas on what I might be doing wrong? Would this be considered a bug, or is this not yet expected to work with .NET Core?

@evanverneyfink evanverneyfink changed the title "Permission denied" Win32Exception when using Process.Run "Permission denied" Win32Exception when using Process.Start May 15, 2018
@vellozzi
Copy link
Contributor

The mediainfo file doesn't have execute permission. To complicate matters, files under /var/task are read-only.

So instead of setting the environment variable do this before starting your process:

File.Copy("/var/task/mediainfo", "/tmp/mediainfo", true);
// use the Exec function from https://stackoverflow.com/questions/45132081/file-permissions-on-linux-unix-with-net-core
Exec("chmod +x /tmp/mediainfo");

and change StartInfo.Filename to "/tmp/mediainfo".

We'll have to look into how to give the mediainfo file execute permission and preserve it in the zip file in the dotnet lambda deploy-function tool. That may be difficult to do on windows.
You could also try to create the deployment package manually on Linux so that the execute permission is preserved on mediainfo.

@evanverneyfink
Copy link
Author

I've seen this mentioned elsewhere as a possible problem (along with your suggested solution), but as I said, the same binary works with a Node.js lambda, packaged from the same Windows machine, albeit using a different process to create the zip. The Node.js package is created using a build script that zips up using the npm package "archiver," whereas I've tried zipping the .NET package using both the deploy function tool through Visual Studio and a PowerShell script. Are you saying the zipping process is what really matters here?

@vellozzi
Copy link
Contributor

It seems that way. Let me look into it some more and get back to you.

@evanverneyfink
Copy link
Author

I've spoken with a colleague who's told me that the way Node.js runs the process (via the child_process module) is actually the reason this works with a Node.js lambda function. Supposedly the execFile function used to invoke the executable will set the execute permission bit automatically prior to running it.

So far I've been unable to confirm this, either through documentation or source code, so I may just have to take his word for it. If you (or anyone else with a little more Node.js knowledge?) can corroborate what he's saying, that would be helpful.

@vellozzi
Copy link
Contributor

You can change the file attributes in the deployment package zip and then deploy the altered archive.
Here's a console app that does it:

using System;
using System.IO;
using System.IO.Compression;

namespace ChmodInZipFile
{
    class Program
    {
        // dotnet run <path to deployment package> mediainfo 755
        static void Main(string[] args)
        {
            var zipFilePath = args[0];
            var relativeEntryPath = args[1];
            var attributes = int.Parse(args[2]);

            using (FileStream zipToOpen = new FileStream(zipFilePath, FileMode.Open))
            {
                using (ZipArchive archive = new ZipArchive(zipToOpen, ZipArchiveMode.Update))
                {
                    archive.GetEntry(relativeEntryPath).ExternalAttributes = attributes;
                }
            }
        }
    }
}

We'll look into adding a feature into the tooling to take care of this in the future.

@evanverneyfink
Copy link
Author

evanverneyfink commented May 16, 2018

Turns out my colleague's assertion about the child_process module was incorrect. It appears that in the case of the Node.js lambda I was using as an example, the build process used to do the packaging is handling setting the permissions when creating the zip, exactly as you've suggested doing for the .NET Core case.

Unfortunately it doesn't look like this can be done with PowerShell's Compress-Archive (see open issue here), which I'd been hoping to use in conjunction with the dotnet CLI and Terraform to run a scripted deployment. I'll have to do some variation on what you've suggested.

Thanks so much for the help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants