Bug 65212 - Apache Ant 1.10.9 version generating temp folders which are prefixed by Ant
Summary: Apache Ant 1.10.9 version generating temp folders which are prefixed by Ant
Status: NEW
Alias: None
Product: Ant
Classification: Unclassified
Component: Core (show other bugs)
Version: 1.10.9
Hardware: PC Linux
: P2 normal (vote)
Target Milestone: ---
Assignee: Ant Notifications List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-03-31 05:58 UTC by Rajesh Putta
Modified: 2021-04-05 13:16 UTC (History)
0 users



Attachments
Screenshot showing temp folders created by Ant (491.46 KB, image/png)
2021-03-31 05:58 UTC, Rajesh Putta
Details
Attachment showing temp folders (416.70 KB, image/png)
2021-03-31 06:11 UTC, Rajesh Putta
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Rajesh Putta 2021-03-31 05:58:31 UTC
Created attachment 37791 [details]
Screenshot showing temp folders created by Ant

We are using Apache Ant 1.10.9 under our project. What we noticed is Ant is creating too many empty folders with name prefixed with ant. Please find attached screenshot.

All of them are deleted on JVM exit. Strangely there are no files created under those folders. Instead of using one temp folder for storing files, Ant is creating too many empty folders as shown in attachment.

This was noticed on Linux. Tested on both Ubuntu and AIX and replicable on them. Earlier we were using Apache Ant 1.10.8 and this problem was not noticed. Problem is with Apache Ant 1.10.9 version.


try {
                        final File projectTempDir = Files.createTempDirectory(systemTempDirPath,
                            "ant", TMPDIR_ATTRIBUTES)
                            .toFile();
                        projectTempDir.deleteOnExit();
                        p = projectTempDir.getAbsolutePath();
                        project.setProperty(MagicNames.AUTO_TMPDIR, p);
                    } catch (IOException ex) {
                        // silently fall back to system temp directory
                    }



{
        File result;
        String p = null;
        if (parentDir != null) {
            p = parentDir.getPath();
        } else if (project != null && project.getProperty(MagicNames.TMPDIR) != null) {
            p = project.getProperty(MagicNames.TMPDIR);
        } else if (project != null && deleteOnExit) {
            if (project.getProperty(MagicNames.AUTO_TMPDIR) != null) {
                p = project.getProperty(MagicNames.AUTO_TMPDIR);
            } else {
                final Path systemTempDirPath =
                    new File(System.getProperty("java.io.tmpdir")).toPath();
                final PosixFileAttributeView systemTempDirPosixAttributes =
                    Files.getFileAttributeView(systemTempDirPath, PosixFileAttributeView.class);
                if (systemTempDirPosixAttributes != null) {
                    // no reason to create an extra temp dir if we cannot set permissions
                    try {
                        final File projectTempDir = Files.createTempDirectory(systemTempDirPath,
                            "ant", TMPDIR_ATTRIBUTES)
                            .toFile();
                        projectTempDir.deleteOnExit();
                        p = projectTempDir.getAbsolutePath();
                        project.setProperty(MagicNames.AUTO_TMPDIR, p);
                    } catch (IOException ex) {
                        // silently fall back to system temp directory
                    }
                }
            }
        }
        final String parent = p != null ? p : System.getProperty("java.io.tmpdir");
        if (prefix == null) {
            prefix = NULL_PLACEHOLDER;
        }
        if (suffix == null) {
            suffix = NULL_PLACEHOLDER;
        }

        if (createFile) {
            try {
                final Path parentPath = new File(parent).toPath();
                final PosixFileAttributeView parentPosixAttributes =
                    Files.getFileAttributeView(parentPath, PosixFileAttributeView.class);
                result = Files.createTempFile(parentPath, prefix, suffix,
                    parentPosixAttributes != null ? TMPFILE_ATTRIBUTES : NO_TMPFILE_ATTRIBUTES)
                    .toFile();
            } catch (IOException e) {
                throw new BuildException("Could not create tempfile in "
                        + parent, e);
            }
        } else {
            DecimalFormat fmt = new DecimalFormat("#####");
            synchronized (rand) {
                do {
                    result = new File(parent, prefix
                            + fmt.format(rand.nextInt(Integer.MAX_VALUE)) + suffix);
                } while (result.exists());
            }
        }

        if (deleteOnExit) {
            result.deleteOnExit();
        }
        return result;
    }

Please look into it and let us know your thoughts here
Comment 1 Rajesh Putta 2021-03-31 06:11:57 UTC
Created attachment 37792 [details]
Attachment showing temp folders
Comment 2 Jaikiran Pai 2021-04-02 03:43:45 UTC
Hello Rajesh,

Are all those directories created in one single run of an Ant build? Or does each run create one and leave it behind? Would you be able to attach a simple build script which reproduces this issue?
Comment 3 Jaikiran Pai 2021-04-02 03:46:07 UTC
> Or does each run create one and leave it behind?

I think your original post already answers that:

> All of them are deleted on JVM exit.

So it looks like one single run of Ant creates all these directories.
Comment 4 Rajesh Putta 2021-04-05 05:00:46 UTC
Hi Jaikiran,

We have a component based on java which executes custom scripts on scheduled interval to collect metrics and reports them to a centralised controller where end users can view those metrics on UI. Component based on java doesn't exit until some one kills it. Java based component internally uses Apache Ant and as a result we end up seeing too many temp directories with name prefixed ant.

Can you help us fix the Apache Ant library issue so that such temp folders are not created on aggressive basis. 

Thanks
Rajesh
Comment 5 Jaikiran Pai 2021-04-05 08:21:22 UTC
Hello Rajesh,

Thank you for those details. A few additional questions:

> Java based component internally uses Apache Ant and as
a result we end up seeing too many temp directories with name prefixed ant.

So if I understand correctly, you have a Java program which internally launches Ant programatically. The main Java program can/will launch Ant "N" number of times during its lifetime. You are seeing that these N launches are causing N such temporary directories which stay around till the main program exits. Is that correct?

I think we (Ant project) need to handle this case better.
Comment 6 Rajesh Putta 2021-04-05 09:09:00 UTC
Hi Jaikiran,

Thanks for the update. Yes you got it right and that is what we are experiencing at the moment. 

Can this issue be fixed. With our frequency with which we are running these Ant folders are created 2 per each minute. As a result till the java component is killed, there are many such ant folders being created.

Thanks
Rajesh
Comment 7 Stefan Bodewig 2021-04-05 12:26:06 UTC
We have changed Ant to use a temporary directory of its own whenever it needs to create a temporary file. Likely those temporary files get removed quickly, so you never see them showing up.

More details can be found here https://ant.apache.org/manual/running.html#tmpdir

If you were using a single Project instance, Ant would only use a single temporary directory as it caches the name.

In your case I recommend you explicitly set the property ant.tmpdir and make it point to a temporary directory under your control. This could be a Java system property or a "plain" property you set on the Project instances you create.
Comment 8 Rajesh Putta 2021-04-05 12:41:05 UTC
Hi Stefan,

Thanks for the update. At the moment we have changed our code to reflect as shown here which is exactly as you mentioned.

 public void executeFixCrlf() throws IllegalOperationException {
        if (isOsWindows()) {
            //If operating system is Windows, then we should not execute FixCRLF
            return;
        }
        String originalPermissions = getPermissions(executable);

        Path systemTempDirPath = new File(System.getProperty("java.io.tmpdir")).toPath();

        Project project = new Project();
        project.setProperty(MagicNames.TMPDIR, String.valueOf(systemTempDirPath));

        fixCRLF.setProject(project);
        fixCRLF.setFile(executable);
        fixCRLF.execute();

        // The CRLF adjustment may mess up the file permissions on the executed file
        // Apply the original permissions, which were retrieved previously.
        if (log.isDebugEnabled()) {
            String newPermissions = getPermissions(executable);
            log.debug("Permissions after fixcrlf.execute() are " + newPermissions);
        }

        applyPermissions(originalPermissions);
    }


Can we expect a fix from Ant team to address such issues as the current Ant version 1.10.9 version creates too many temp directories whose names are prefixed with ant.

Thanks
Rajesh
Comment 9 Stefan Bodewig 2021-04-05 12:43:52 UTC
what you see is the expected bahvior that we may need to document more clearly. I wouldn't expect any code change in Ant as your way of using Ant really is an edge case (creating mutltiple instances of Ant Projects, that is).
Comment 10 Rajesh Putta 2021-04-05 13:05:19 UTC
Thanks Stefan. We do not see such temp folder creation issues with Ant version of 1.10.8. 

Only after we upgraded our component to use Ant 1.10.9, we started noticing the temp folder issues.

I am not sure the reason behind such change across the versions. 
This aggressive temp folders creation is hurting us as we notice 2 empty folders per minute with the frequency with which we are executing and as mentioned earlier

Reiterating which was mentioned earlier

We have a component based on java which executes custom scripts on scheduled interval to collect metrics and reports them to a centralised controller where end users can view those metrics on UI. Component based on java doesn't exit until some one kills it. Java based component internally uses Apache Ant and as a result we end up seeing too many temp directories with name prefixed ant.


I am sure who ever has such use case runs into such issues. 

Can you please re look into it


Thanks
Rajesh
Comment 11 Stefan Bodewig 2021-04-05 13:16:43 UTC
The reason is that Ant needs to ensure full control over the permissions for the temporary directory in order to deal with CVE-2020-11979

The release notes of 1.10.9 hint at it

 * If the magic property ant.tmpdir hasn't been set and Ant can
   control the permissions of directories it creates it will create an
   owner-owned temporary directory unaccessible to others as default
   tempdir as soon as a temporary file is created for the first time,

Ant knows it has set up such a directory by storing the information inside of a project property, the only "global variable" Ant knows. So if you were creating only a single instance of an Ant project, only a single temporary directory would have been created.

I believe to understand what you are doing but don't see any way to avoid what you see without opening up for supply chain attacks. The way you properly deal with it is by explicitly providing Ant with a secure temporary directory via ant.tmpdir. This is the way you tell Ant you are taking care of securing tempfile creation yourself.

Please note that fixcrlf has been the real trigger of the CVE. fixcrlf works by creating a temporary file for each file it processes, streaming data from the original file to the temporary file (normalizing CRLF on the way) and then moving the temporary file over the original file. An attacker can replace the temporary file before it is moved and so inject arbitrary files into your process.