diff --git a/test/test-open_tree.c b/test/test-open_tree.c
index 9570f11..3b1b7ea 100644
--- a/test/test-open_tree.c
+++ b/test/test-open_tree.c
@@ -10,6 +10,14 @@
 #define TEST_DIR "test-open-tree-dir"
 #define TEST_FILE "test-open-tree-file"
 
+/*
+ * Older glibc versions (< 2.36) do not provide open_tree().  Declare it
+ * weak so the test still links; at runtime it resolves to glibc's or
+ * libpseudo's open_tree if either provides it, otherwise it is NULL and
+ * the test is skipped.
+ */
+extern int open_tree(int dirfd, const char *path, unsigned int flags) __attribute__((weak));
+
 static int test_no_flags(void) {
     int treefd = -1;
     int fd = -1;
@@ -124,6 +132,23 @@ static void cleanup(void) {
 }
 
 int main(void) {
+    int probefd;
+
+    if (!open_tree) {
+        fprintf(stderr, "open_tree() not available, skipping.\n");
+        return 77;
+    }
+
+    /* pseudo exports open_tree() but returns ENOSYS if libc lacks it */
+    probefd = open_tree(AT_FDCWD, ".", 0);
+    if (probefd == -1 && errno == ENOSYS) {
+        fprintf(stderr, "open_tree() returned ENOSYS, skipping.\n");
+        return 77;
+    }
+    if (probefd != -1) {
+        close(probefd);
+    }
+
     cleanup();
 
     if (mkdir(TEST_DIR, 0777) == -1) {
diff --git a/test/test-open_tree.sh b/test/test-open_tree.sh
index 427d550..274c654 100755
--- a/test/test-open_tree.sh
+++ b/test/test-open_tree.sh
@@ -1,9 +1,20 @@
 #!/bin/sh
 
-./test/test-open_tree
+# rc 77 indicates open_tree() is not available, so report skipped (255).
+# This usually indicates that glibc does not have the open_tree function.
+run_test() {
+	"$@"
+	rc=$?
+	if [ "$rc" -eq 77 ]; then
+		exit 255
+	fi
+	return "$rc"
+}
+
+run_test ./test/test-open_tree
 rc1=$?
 
-PSEUDO_IGNORE_PATHS=/ ./test/test-open_tree
+run_test env PSEUDO_IGNORE_PATHS=/ ./test/test-open_tree
 rc2=$?
 
 exit $((rc1 | rc2))
diff --git a/test/test-open_tree_attr-syscall.c b/test/test-open_tree_attr-syscall.c
index cc38c5f..e4e652e 100644
--- a/test/test-open_tree_attr-syscall.c
+++ b/test/test-open_tree_attr-syscall.c
@@ -150,6 +150,17 @@ static void cleanup(void) {
 }
 
 int main(void) {
+    int probefd;
+
+    probefd = do_open_tree_attr_syscall(AT_FDCWD, ".", 0);
+    if (probefd == -1 && errno == ENOSYS) {
+        fprintf(stderr, "open_tree_attr syscall not supported, skipping.\n");
+        return 77;
+    }
+    if (probefd != -1) {
+        close(probefd);
+    }
+
     cleanup();
 
     if (mkdir(TEST_DIR, 0777) == -1) {
diff --git a/test/test-open_tree_attr-syscall.sh b/test/test-open_tree_attr-syscall.sh
index f6e51f4..d87043e 100755
--- a/test/test-open_tree_attr-syscall.sh
+++ b/test/test-open_tree_attr-syscall.sh
@@ -1,9 +1,20 @@
 #!/bin/sh
 
-./test/test-open_tree_attr-syscall
+# rc 77 indicates the open_tree_attr syscall is not supported (ENOSYS),
+# so report skipped (255).  This usually indicates an older kernel.
+run_test() {
+	"$@"
+	rc=$?
+	if [ "$rc" -eq 77 ]; then
+		exit 255
+	fi
+	return "$rc"
+}
+
+run_test ./test/test-open_tree_attr-syscall
 rc1=$?
 
-PSEUDO_IGNORE_PATHS=/ ./test/test-open_tree_attr-syscall
+run_test env PSEUDO_IGNORE_PATHS=/ ./test/test-open_tree_attr-syscall
 rc2=$?
 
 exit $((rc1 | rc2))
