Skip to content

Commit 6dde17d

Browse files
cpovirkGoogle Java Core Libraries
authored and
Google Java Core Libraries
committed
Fix Files.createTempDir and FileBackedOutputStream under Windows.
Based on [some discussions in GitHub](#6535 (comment)), I'm under the impression that Windows would create the temporary directory/file in a secure location even if our call to `java.nio.file.Files.createTempDirectory`/`createTempFile` passes no ACL attribute. However, in case we are in an unusual situation (Linux with NFS temporary directory???) in which ACLs are supported but the temporary directory is _not_ a secure location, I've arranged for the file to be created with an ACL that grants permissions only to the current user. I set the user's permissions to the ones that I saw on a file created in the temporary directory under Java's default settings, and I didn't do anything to set the additional permissions I was seeing for administrators. The resulting file's permissions look plausibly correct in the Windows property dialog, if slightly different than what I get when creating a file/directory myself through Explorer. Fixes #6535 RELNOTES=`io`: Fixed `Files.createTempDir` and `FileBackedOutputStream` under Windows. PiperOrigin-RevId: 538491548
1 parent e82e2a2 commit 6dde17d

File tree

2 files changed

+186
-10
lines changed

2 files changed

+186
-10
lines changed

android/guava/src/com/google/common/io/TempFileCreator.java

+93-5
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,37 @@
1515
package com.google.common.io;
1616

1717
import static com.google.common.base.StandardSystemProperty.JAVA_IO_TMPDIR;
18+
import static java.nio.file.attribute.AclEntryFlag.DIRECTORY_INHERIT;
19+
import static java.nio.file.attribute.AclEntryFlag.FILE_INHERIT;
20+
import static java.nio.file.attribute.AclEntryPermission.APPEND_DATA;
21+
import static java.nio.file.attribute.AclEntryPermission.DELETE;
22+
import static java.nio.file.attribute.AclEntryPermission.DELETE_CHILD;
23+
import static java.nio.file.attribute.AclEntryPermission.EXECUTE;
24+
import static java.nio.file.attribute.AclEntryPermission.READ_ACL;
25+
import static java.nio.file.attribute.AclEntryPermission.READ_ATTRIBUTES;
26+
import static java.nio.file.attribute.AclEntryPermission.READ_DATA;
27+
import static java.nio.file.attribute.AclEntryPermission.READ_NAMED_ATTRS;
28+
import static java.nio.file.attribute.AclEntryPermission.SYNCHRONIZE;
29+
import static java.nio.file.attribute.AclEntryPermission.WRITE_ACL;
30+
import static java.nio.file.attribute.AclEntryPermission.WRITE_ATTRIBUTES;
31+
import static java.nio.file.attribute.AclEntryPermission.WRITE_NAMED_ATTRS;
32+
import static java.nio.file.attribute.AclEntryPermission.WRITE_OWNER;
33+
import static java.nio.file.attribute.AclEntryType.ALLOW;
1834

1935
import com.google.common.annotations.GwtIncompatible;
2036
import com.google.common.annotations.J2ktIncompatible;
37+
import com.google.common.collect.ImmutableList;
2138
import com.google.j2objc.annotations.J2ObjCIncompatible;
2239
import java.io.File;
2340
import java.io.IOException;
41+
import java.nio.file.FileSystems;
2442
import java.nio.file.Paths;
43+
import java.nio.file.attribute.AclEntry;
2544
import java.nio.file.attribute.FileAttribute;
26-
import java.nio.file.attribute.PosixFilePermission;
2745
import java.nio.file.attribute.PosixFilePermissions;
46+
import java.nio.file.attribute.UserPrincipal;
2847
import java.util.Set;
48+
import javax.annotation.CheckForNull;
2949

3050
/**
3151
* Creates temporary files and directories whose permissions are restricted to the current user or,
@@ -90,16 +110,62 @@ private static TempFileCreator pickSecureCreator() {
90110

91111
@IgnoreJRERequirement // used only when Path is available
92112
private static final class JavaNioCreator extends TempFileCreator {
93-
private static final FileAttribute<Set<PosixFilePermission>> RWX_USER_ONLY =
113+
private static final FileAttribute<?> RWX_USER_ONLY =
94114
PosixFilePermissions.asFileAttribute(PosixFilePermissions.fromString("rwx------"));
95-
private static final FileAttribute<Set<PosixFilePermission>> RW_USER_ONLY =
115+
private static final FileAttribute<?> RW_USER_ONLY =
96116
PosixFilePermissions.asFileAttribute(PosixFilePermissions.fromString("rw-------"));
117+
@CheckForNull private static FileAttribute<?> userOnly;
118+
119+
private static FileAttribute<?> userOnly() throws IOException {
120+
FileAttribute<?> result = userOnly;
121+
if (result != null) {
122+
return result;
123+
}
124+
125+
UserPrincipal user =
126+
FileSystems.getDefault()
127+
.getUserPrincipalLookupService()
128+
.lookupPrincipalByName(System.getProperty("user.name"));
129+
ImmutableList<AclEntry> acl =
130+
ImmutableList.of(
131+
AclEntry.newBuilder()
132+
.setType(ALLOW)
133+
.setPrincipal(user)
134+
.setPermissions(
135+
APPEND_DATA,
136+
DELETE,
137+
DELETE_CHILD,
138+
EXECUTE,
139+
READ_ACL,
140+
READ_ATTRIBUTES,
141+
READ_DATA,
142+
READ_NAMED_ATTRS,
143+
SYNCHRONIZE,
144+
WRITE_ACL,
145+
WRITE_ATTRIBUTES,
146+
WRITE_NAMED_ATTRS,
147+
WRITE_OWNER)
148+
.setFlags(DIRECTORY_INHERIT, FILE_INHERIT)
149+
.build());
150+
return userOnly =
151+
new FileAttribute<ImmutableList<AclEntry>>() {
152+
@Override
153+
public String name() {
154+
return "acl:acl";
155+
}
156+
157+
@Override
158+
public ImmutableList<AclEntry> value() {
159+
return acl;
160+
}
161+
};
162+
}
97163

98164
@Override
99165
File createTempDir() {
100166
try {
101167
return java.nio.file.Files.createTempDirectory(
102-
Paths.get(JAVA_IO_TMPDIR.value()), /* prefix= */ null, RWX_USER_ONLY)
168+
Paths.get(JAVA_IO_TMPDIR.value()), /* prefix= */ null, directoryPermissions())
103169
.toFile();
104170
} catch (IOException e) {
105171
throw new IllegalStateException("Failed to create directory", e);
@@ -112,9 +178,31 @@ File createTempFile(String prefix) throws IOException {
112178
Paths.get(JAVA_IO_TMPDIR.value()),
113179
/* prefix= */ prefix,
114180
/* suffix= */ null,
115-
RW_USER_ONLY)
181+
filePermissions())
116182
.toFile();
117183
}
184+
185+
private static FileAttribute<?> directoryPermissions() throws IOException {
186+
Set<String> views = FileSystems.getDefault().supportedFileAttributeViews();
187+
if (views.contains("posix")) {
188+
return RWX_USER_ONLY;
189+
} else if (views.contains("acl")) {
190+
return userOnly();
191+
} else {
192+
throw new IOException("unrecognized FileSystem type " + FileSystems.getDefault());
193+
}
194+
}
195+
196+
private static FileAttribute<?> filePermissions() throws IOException {
197+
Set<String> views = FileSystems.getDefault().supportedFileAttributeViews();
198+
if (views.contains("posix")) {
199+
return RW_USER_ONLY;
200+
} else if (views.contains("acl")) {
201+
return userOnly();
202+
} else {
203+
throw new IOException("unrecognized FileSystem type " + FileSystems.getDefault());
204+
}
205+
}
118206
}
119207

120208
private static final class JavaIoCreator extends TempFileCreator {

guava/src/com/google/common/io/TempFileCreator.java

+93-5
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,37 @@
1515
package com.google.common.io;
1616

1717
import static com.google.common.base.StandardSystemProperty.JAVA_IO_TMPDIR;
18+
import static java.nio.file.attribute.AclEntryFlag.DIRECTORY_INHERIT;
19+
import static java.nio.file.attribute.AclEntryFlag.FILE_INHERIT;
20+
import static java.nio.file.attribute.AclEntryPermission.APPEND_DATA;
21+
import static java.nio.file.attribute.AclEntryPermission.DELETE;
22+
import static java.nio.file.attribute.AclEntryPermission.DELETE_CHILD;
23+
import static java.nio.file.attribute.AclEntryPermission.EXECUTE;
24+
import static java.nio.file.attribute.AclEntryPermission.READ_ACL;
25+
import static java.nio.file.attribute.AclEntryPermission.READ_ATTRIBUTES;
26+
import static java.nio.file.attribute.AclEntryPermission.READ_DATA;
27+
import static java.nio.file.attribute.AclEntryPermission.READ_NAMED_ATTRS;
28+
import static java.nio.file.attribute.AclEntryPermission.SYNCHRONIZE;
29+
import static java.nio.file.attribute.AclEntryPermission.WRITE_ACL;
30+
import static java.nio.file.attribute.AclEntryPermission.WRITE_ATTRIBUTES;
31+
import static java.nio.file.attribute.AclEntryPermission.WRITE_NAMED_ATTRS;
32+
import static java.nio.file.attribute.AclEntryPermission.WRITE_OWNER;
33+
import static java.nio.file.attribute.AclEntryType.ALLOW;
1834

1935
import com.google.common.annotations.GwtIncompatible;
2036
import com.google.common.annotations.J2ktIncompatible;
37+
import com.google.common.collect.ImmutableList;
2138
import com.google.j2objc.annotations.J2ObjCIncompatible;
2239
import java.io.File;
2340
import java.io.IOException;
41+
import java.nio.file.FileSystems;
2442
import java.nio.file.Paths;
43+
import java.nio.file.attribute.AclEntry;
2544
import java.nio.file.attribute.FileAttribute;
26-
import java.nio.file.attribute.PosixFilePermission;
2745
import java.nio.file.attribute.PosixFilePermissions;
46+
import java.nio.file.attribute.UserPrincipal;
2847
import java.util.Set;
48+
import javax.annotation.CheckForNull;
2949

3050
/**
3151
* Creates temporary files and directories whose permissions are restricted to the current user or,
@@ -90,16 +110,62 @@ private static TempFileCreator pickSecureCreator() {
90110

91111
@IgnoreJRERequirement // used only when Path is available
92112
private static final class JavaNioCreator extends TempFileCreator {
93-
private static final FileAttribute<Set<PosixFilePermission>> RWX_USER_ONLY =
113+
private static final FileAttribute<?> RWX_USER_ONLY =
94114
PosixFilePermissions.asFileAttribute(PosixFilePermissions.fromString("rwx------"));
95-
private static final FileAttribute<Set<PosixFilePermission>> RW_USER_ONLY =
115+
private static final FileAttribute<?> RW_USER_ONLY =
96116
PosixFilePermissions.asFileAttribute(PosixFilePermissions.fromString("rw-------"));
117+
@CheckForNull private static FileAttribute<?> userOnly;
118+
119+
private static FileAttribute<?> userOnly() throws IOException {
120+
FileAttribute<?> result = userOnly;
121+
if (result != null) {
122+
return result;
123+
}
124+
125+
UserPrincipal user =
126+
FileSystems.getDefault()
127+
.getUserPrincipalLookupService()
128+
.lookupPrincipalByName(System.getProperty("user.name"));
129+
ImmutableList<AclEntry> acl =
130+
ImmutableList.of(
131+
AclEntry.newBuilder()
132+
.setType(ALLOW)
133+
.setPrincipal(user)
134+
.setPermissions(
135+
APPEND_DATA,
136+
DELETE,
137+
DELETE_CHILD,
138+
EXECUTE,
139+
READ_ACL,
140+
READ_ATTRIBUTES,
141+
READ_DATA,
142+
READ_NAMED_ATTRS,
143+
SYNCHRONIZE,
144+
WRITE_ACL,
145+
WRITE_ATTRIBUTES,
146+
WRITE_NAMED_ATTRS,
147+
WRITE_OWNER)
148+
.setFlags(DIRECTORY_INHERIT, FILE_INHERIT)
149+
.build());
150+
return userOnly =
151+
new FileAttribute<ImmutableList<AclEntry>>() {
152+
@Override
153+
public String name() {
154+
return "acl:acl";
155+
}
156+
157+
@Override
158+
public ImmutableList<AclEntry> value() {
159+
return acl;
160+
}
161+
};
162+
}
97163

98164
@Override
99165
File createTempDir() {
100166
try {
101167
return java.nio.file.Files.createTempDirectory(
102-
Paths.get(JAVA_IO_TMPDIR.value()), /* prefix= */ null, RWX_USER_ONLY)
168+
Paths.get(JAVA_IO_TMPDIR.value()), /* prefix= */ null, directoryPermissions())
103169
.toFile();
104170
} catch (IOException e) {
105171
throw new IllegalStateException("Failed to create directory", e);
@@ -112,9 +178,31 @@ File createTempFile(String prefix) throws IOException {
112178
Paths.get(JAVA_IO_TMPDIR.value()),
113179
/* prefix= */ prefix,
114180
/* suffix= */ null,
115-
RW_USER_ONLY)
181+
filePermissions())
116182
.toFile();
117183
}
184+
185+
private static FileAttribute<?> directoryPermissions() throws IOException {
186+
Set<String> views = FileSystems.getDefault().supportedFileAttributeViews();
187+
if (views.contains("posix")) {
188+
return RWX_USER_ONLY;
189+
} else if (views.contains("acl")) {
190+
return userOnly();
191+
} else {
192+
throw new IOException("unrecognized FileSystem type " + FileSystems.getDefault());
193+
}
194+
}
195+
196+
private static FileAttribute<?> filePermissions() throws IOException {
197+
Set<String> views = FileSystems.getDefault().supportedFileAttributeViews();
198+
if (views.contains("posix")) {
199+
return RW_USER_ONLY;
200+
} else if (views.contains("acl")) {
201+
return userOnly();
202+
} else {
203+
throw new IOException("unrecognized FileSystem type " + FileSystems.getDefault());
204+
}
205+
}
118206
}
119207

120208
private static final class JavaIoCreator extends TempFileCreator {

0 commit comments

Comments
 (0)