This is an automated email from the ASF dual-hosted git repository.

anmolnar pushed a commit to branch branch-3.8
in repository https://gitbox.apache.org/repos/asf/zookeeper.git

commit 0cd1cd023cff5e0b3b5a19050e544196ac2340b4
Author: Andor Molnar <[email protected]>
AuthorDate: Tue Aug 25 16:18:14 2026 -0500

    Missing ACL check on deleteContainer opcode
---
 .../apache/zookeeper/server/ZooKeeperServer.java   | 10 ++++++
 .../zookeeper/server/CreateContainerTest.java      | 39 ++++++++++++++++++++++
 2 files changed, 49 insertions(+)

diff --git 
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/ZooKeeperServer.java
 
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/ZooKeeperServer.java
index d017d295a..f1cc6752c 100644
--- 
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/ZooKeeperServer.java
+++ 
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/ZooKeeperServer.java
@@ -1680,6 +1680,16 @@ public void processPacket(ServerCnxn cnxn, ByteBuffer 
incomingBuffer) throws IOE
                 // Already sent response to user about failure and closed the 
session, lets return
                 return;
             } else {
+                // Internal opcodes should not be submitted via client 
connections
+                if (h.getType() == OpCode.deleteContainer) {
+                    LOG.warn("Received deleteContainer opcode from client 
session 0x{}, rejecting.",
+                        Long.toHexString(cnxn.getSessionId()));
+                    // close connection
+                    cnxn.sendBuffer(ServerCnxnFactory.closeConn);
+                    cnxn.disableRecv();
+                    return;
+                }
+
                 Request si = new Request(cnxn, cnxn.getSessionId(), 
h.getXid(), h.getType(), incomingBuffer, cnxn.getAuthInfo());
                 int length = incomingBuffer.limit();
                 if (isLargeRequest(length)) {
diff --git 
a/zookeeper-server/src/test/java/org/apache/zookeeper/server/CreateContainerTest.java
 
b/zookeeper-server/src/test/java/org/apache/zookeeper/server/CreateContainerTest.java
index 6722473f2..0229581c7 100644
--- 
a/zookeeper-server/src/test/java/org/apache/zookeeper/server/CreateContainerTest.java
+++ 
b/zookeeper-server/src/test/java/org/apache/zookeeper/server/CreateContainerTest.java
@@ -23,6 +23,8 @@
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
@@ -35,13 +37,19 @@
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
+import org.apache.jute.InputArchive;
+import org.apache.jute.OutputArchive;
+import org.apache.jute.Record;
 import org.apache.zookeeper.AsyncCallback;
 import org.apache.zookeeper.CreateMode;
 import org.apache.zookeeper.KeeperException;
 import org.apache.zookeeper.Op;
+import org.apache.zookeeper.TestableZooKeeper;
 import org.apache.zookeeper.ZooDefs;
 import org.apache.zookeeper.ZooKeeper;
 import org.apache.zookeeper.data.Stat;
+import org.apache.zookeeper.proto.ReplyHeader;
+import org.apache.zookeeper.proto.RequestHeader;
 import org.apache.zookeeper.test.ClientBase;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
@@ -339,4 +347,35 @@ private void validateCreateStat(Stat stat, String name) {
         assertEquals(0, stat.getNumChildren());
     }
 
+    @Test
+    @Timeout(value = 30)
+    public void testDeleteContainerShouldBeRejected() throws Exception {
+        zk.create("/some", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, 
CreateMode.PERSISTENT);
+        zk.create("/some/child", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, 
CreateMode.PERSISTENT);
+
+        TestableZooKeeper zk = createClient();
+
+        RequestHeader h = new RequestHeader();
+        h.setType(ZooDefs.OpCode.deleteContainer);
+        Record request = new Record() {
+            private String path = "/some/child";
+
+            @Override
+            public void serialize(OutputArchive archive, String tag) throws 
IOException {
+                archive.writeBuffer(path.getBytes(StandardCharsets.UTF_8), 
"path");
+            }
+
+            @Override
+            public void deserialize(InputArchive archive, String tag) throws 
IOException {
+                byte[] bytes = archive.readBuffer("path");
+                path = new String(bytes, StandardCharsets.UTF_8);
+            }
+        };
+        ReplyHeader reply = zk.submitRequest(h, request, null, null);
+        assertEquals(KeeperException.Code.CONNECTIONLOSS.intValue(), 
reply.getErr(),
+                "deleteContainer opcode should be rejected from client 
connections");
+
+        zk.close();
+    }
+
 }

Reply via email to