Skip to content

Commit 2452ea5

Browse files
do not apply POSIX file attributes through symbolic links (#4229)
* do not apply POSIX file attributes through symbolic links * address review: keep FileUtils following links, gate visitor skip on followLinks * restore plain symlink guard and cover dangling links * fix: skip symbolic links in PosixViewAttribute unless followLinks is true --------- Co-authored-by: Ramanathan <ramanathan@apache.org>
1 parent 89db25a commit 2452ea5

3 files changed

Lines changed: 141 additions & 0 deletions

File tree

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to you under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.logging.log4j.core.appender.rolling.action;
18+
19+
import static org.junit.jupiter.api.Assertions.assertEquals;
20+
import static org.junit.jupiter.api.Assumptions.assumeTrue;
21+
22+
import java.nio.charset.StandardCharsets;
23+
import java.nio.file.Files;
24+
import java.nio.file.Path;
25+
import java.nio.file.attribute.PosixFilePermissions;
26+
import org.apache.logging.log4j.core.config.Configuration;
27+
import org.apache.logging.log4j.core.test.BasicConfigurationFactory;
28+
import org.apache.logging.log4j.core.util.FileUtils;
29+
import org.junit.jupiter.api.BeforeAll;
30+
import org.junit.jupiter.api.Test;
31+
import org.junit.jupiter.api.io.TempDir;
32+
33+
/**
34+
* Tests the {@code PosixViewAttributeAction} class.
35+
*/
36+
class PosixViewAttributeActionTest {
37+
38+
@BeforeAll
39+
static void beforeClass() {
40+
assumeTrue(FileUtils.isFilePosixAttributeViewSupported());
41+
}
42+
43+
@Test
44+
void testSymbolicLinksAreNotFollowed(@TempDir final Path tempDir) throws Exception {
45+
final Path outsider = tempDir.resolve("outsider.txt");
46+
Files.write(outsider, "secret".getBytes(StandardCharsets.UTF_8));
47+
Files.setPosixFilePermissions(outsider, PosixFilePermissions.fromString("rw-------"));
48+
49+
final Path baseDir = Files.createDirectory(tempDir.resolve("logs"));
50+
final Path regularFile = baseDir.resolve("app-1.log");
51+
Files.write(regularFile, "log".getBytes(StandardCharsets.UTF_8));
52+
Files.setPosixFilePermissions(regularFile, PosixFilePermissions.fromString("rw-------"));
53+
Files.createSymbolicLink(baseDir.resolve("app-2.log"), outsider);
54+
55+
final Configuration config = new BasicConfigurationFactory().new BasicConfiguration();
56+
final PosixViewAttributeAction action = PosixViewAttributeAction.newBuilder()
57+
.setBasePath(baseDir.toString())
58+
.setFollowLinks(false)
59+
.setMaxDepth(1)
60+
.setPathConditions(PathCondition.EMPTY_ARRAY)
61+
.setConfiguration(config)
62+
.setFilePermissionsString("rw-rw-rw-")
63+
.build();
64+
65+
action.execute();
66+
67+
assertEquals(
68+
"rw-rw-rw-",
69+
PosixFilePermissions.toString(Files.getPosixFilePermissions(regularFile)),
70+
"regular file should have been updated");
71+
assertEquals(
72+
"rw-------",
73+
PosixFilePermissions.toString(Files.getPosixFilePermissions(outsider)),
74+
"symbolic link target should have been left alone");
75+
}
76+
77+
@Test
78+
void testSymbolicLinksAreFollowedWhenConfigured(@TempDir final Path tempDir) throws Exception {
79+
final Path outsider = tempDir.resolve("outsider.txt");
80+
Files.write(outsider, "secret".getBytes(StandardCharsets.UTF_8));
81+
Files.setPosixFilePermissions(outsider, PosixFilePermissions.fromString("rw-------"));
82+
83+
final Path baseDir = Files.createDirectory(tempDir.resolve("logs"));
84+
Files.createSymbolicLink(baseDir.resolve("app-2.log"), outsider);
85+
86+
final Configuration config = new BasicConfigurationFactory().new BasicConfiguration();
87+
final PosixViewAttributeAction action = PosixViewAttributeAction.newBuilder()
88+
.setBasePath(baseDir.toString())
89+
.setFollowLinks(true)
90+
.setMaxDepth(1)
91+
.setPathConditions(PathCondition.EMPTY_ARRAY)
92+
.setConfiguration(config)
93+
.setFilePermissionsString("rw-rw-rw-")
94+
.build();
95+
96+
action.execute();
97+
98+
assertEquals(
99+
"rw-rw-rw-",
100+
PosixFilePermissions.toString(Files.getPosixFilePermissions(outsider)),
101+
"followLinks=\"true\" should still follow the link");
102+
}
103+
104+
@Test
105+
void testBrokenSymbolicLinkDoesNotAbortTheScan(@TempDir final Path tempDir) throws Exception {
106+
final Path baseDir = Files.createDirectory(tempDir.resolve("logs"));
107+
final Path regularFile = baseDir.resolve("app-1.log");
108+
Files.write(regularFile, "log".getBytes(StandardCharsets.UTF_8));
109+
Files.setPosixFilePermissions(regularFile, PosixFilePermissions.fromString("rw-------"));
110+
Files.createSymbolicLink(baseDir.resolve("app-0-broken.log"), tempDir.resolve("gone.txt"));
111+
112+
final Configuration config = new BasicConfigurationFactory().new BasicConfiguration();
113+
final PosixViewAttributeAction action = PosixViewAttributeAction.newBuilder()
114+
.setBasePath(baseDir.toString())
115+
.setFollowLinks(true)
116+
.setMaxDepth(1)
117+
.setPathConditions(PathCondition.EMPTY_ARRAY)
118+
.setConfiguration(config)
119+
.setFilePermissionsString("rw-rw-rw-")
120+
.build();
121+
122+
action.execute();
123+
124+
assertEquals(
125+
"rw-rw-rw-",
126+
PosixFilePermissions.toString(Files.getPosixFilePermissions(regularFile)),
127+
"a dangling link must not stop the scan");
128+
}
129+
}

log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/PosixViewAttributeAction.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,10 @@ protected FileVisitor<Path> createFileVisitor(final Path basePath, final List<Pa
369369
return new SimpleFileVisitor<Path>() {
370370
@Override
371371
public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException {
372+
if (attrs.isSymbolicLink()) {
373+
LOGGER.trace("Not defining POSIX attribute on symbolic link {}", file);
374+
return FileVisitResult.CONTINUE;
375+
}
372376
for (final PathCondition pathFilter : conditions) {
373377
final Path relative = basePath.relativize(file);
374378
if (!pathFilter.accept(basePath, relative, attrs)) {
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<entry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xmlns="https://logging.apache.org/xml/ns"
4+
xsi:schemaLocation="https://logging.apache.org/xml/ns https://logging.apache.org/xml/ns/log4j-changelog-0.xsd"
5+
type="fixed">
6+
<issue id="4229" link="https://github.com/apache/logging-log4j2/pull/4229"/>
7+
<description format="asciidoc">Skip symbolic links in `PosixViewAttribute` unless `followLinks` is `true`</description>
8+
</entry>

0 commit comments

Comments
 (0)