summaryrefslogtreecommitdiffhomepage
path: root/test/syscalls
diff options
context:
space:
mode:
Diffstat (limited to 'test/syscalls')
-rw-r--r--test/syscalls/BUILD494
-rw-r--r--test/syscalls/linux/BUILD5
-rw-r--r--test/syscalls/linux/accept_bind.cc42
-rw-r--r--test/syscalls/linux/inotify.cc430
-rw-r--r--test/syscalls/linux/open.cc23
-rw-r--r--test/syscalls/linux/pty.cc6
-rw-r--r--test/syscalls/linux/socket_unix.cc7
7 files changed, 901 insertions, 106 deletions
diff --git a/test/syscalls/BUILD b/test/syscalls/BUILD
index 9800a0cdf..3406a2de8 100644
--- a/test/syscalls/BUILD
+++ b/test/syscalls/BUILD
@@ -2,22 +2,33 @@ load("//test/runner:defs.bzl", "syscall_test")
package(licenses = ["notice"])
-syscall_test(test = "//test/syscalls/linux:32bit_test")
+syscall_test(
+ test = "//test/syscalls/linux:32bit_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:accept_bind_stream_test")
+syscall_test(
+ test = "//test/syscalls/linux:accept_bind_stream_test",
+ vfs2 = "True",
+)
syscall_test(
size = "large",
shard_count = 50,
test = "//test/syscalls/linux:accept_bind_test",
+ vfs2 = "True",
)
syscall_test(
add_overlay = True,
test = "//test/syscalls/linux:access_test",
+ vfs2 = "True",
)
-syscall_test(test = "//test/syscalls/linux:affinity_test")
+syscall_test(
+ test = "//test/syscalls/linux:affinity_test",
+ vfs2 = "True",
+)
syscall_test(
add_overlay = True,
@@ -28,11 +39,18 @@ syscall_test(
size = "medium",
shard_count = 5,
test = "//test/syscalls/linux:alarm_test",
+ vfs2 = "True",
)
-syscall_test(test = "//test/syscalls/linux:arch_prctl_test")
+syscall_test(
+ test = "//test/syscalls/linux:arch_prctl_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:bad_test")
+syscall_test(
+ test = "//test/syscalls/linux:bad_test",
+ vfs2 = "True",
+)
syscall_test(
size = "large",
@@ -40,9 +58,15 @@ syscall_test(
test = "//test/syscalls/linux:bind_test",
)
-syscall_test(test = "//test/syscalls/linux:brk_test")
+syscall_test(
+ test = "//test/syscalls/linux:brk_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:socket_test")
+syscall_test(
+ test = "//test/syscalls/linux:socket_test",
+ vfs2 = "True",
+)
syscall_test(
size = "large",
@@ -51,16 +75,19 @@ syscall_test(
# involve much concurrency, TSAN's usefulness here is limited anyway.
tags = ["nogotsan"],
test = "//test/syscalls/linux:socket_stress_test",
+ vfs2 = "True",
)
syscall_test(
add_overlay = True,
test = "//test/syscalls/linux:chdir_test",
+ vfs2 = "True",
)
syscall_test(
add_overlay = True,
test = "//test/syscalls/linux:chmod_test",
+ vfs2 = "True",
)
syscall_test(
@@ -68,6 +95,7 @@ syscall_test(
add_overlay = True,
test = "//test/syscalls/linux:chown_test",
use_tmpfs = True, # chwon tests require gofer to be running as root.
+ vfs2 = "True",
)
syscall_test(
@@ -75,45 +103,70 @@ syscall_test(
test = "//test/syscalls/linux:chroot_test",
)
-syscall_test(test = "//test/syscalls/linux:clock_getres_test")
+syscall_test(
+ test = "//test/syscalls/linux:clock_getres_test",
+ vfs2 = "True",
+)
syscall_test(
size = "medium",
test = "//test/syscalls/linux:clock_gettime_test",
+ vfs2 = "True",
)
-syscall_test(test = "//test/syscalls/linux:clock_nanosleep_test")
+syscall_test(
+ test = "//test/syscalls/linux:clock_nanosleep_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:concurrency_test")
+syscall_test(
+ test = "//test/syscalls/linux:concurrency_test",
+ vfs2 = "True",
+)
syscall_test(
add_uds_tree = True,
test = "//test/syscalls/linux:connect_external_test",
use_tmpfs = True,
+ vfs2 = "True",
)
syscall_test(
add_overlay = True,
test = "//test/syscalls/linux:creat_test",
+ vfs2 = "True",
)
-syscall_test(test = "//test/syscalls/linux:dev_test")
+syscall_test(
+ test = "//test/syscalls/linux:dev_test",
+)
syscall_test(
add_overlay = True,
test = "//test/syscalls/linux:dup_test",
+ vfs2 = "True",
)
-syscall_test(test = "//test/syscalls/linux:epoll_test")
+syscall_test(
+ test = "//test/syscalls/linux:epoll_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:eventfd_test")
+syscall_test(
+ test = "//test/syscalls/linux:eventfd_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:exceptions_test")
+syscall_test(
+ test = "//test/syscalls/linux:exceptions_test",
+ vfs2 = "True",
+)
syscall_test(
size = "medium",
add_overlay = True,
test = "//test/syscalls/linux:exec_test",
+ vfs2 = "True",
)
syscall_test(
@@ -122,7 +175,10 @@ syscall_test(
test = "//test/syscalls/linux:exec_binary_test",
)
-syscall_test(test = "//test/syscalls/linux:exit_test")
+syscall_test(
+ test = "//test/syscalls/linux:exit_test",
+ vfs2 = "True",
+)
syscall_test(
add_overlay = True,
@@ -134,11 +190,15 @@ syscall_test(
test = "//test/syscalls/linux:fallocate_test",
)
-syscall_test(test = "//test/syscalls/linux:fault_test")
+syscall_test(
+ test = "//test/syscalls/linux:fault_test",
+ vfs2 = "True",
+)
syscall_test(
add_overlay = True,
test = "//test/syscalls/linux:fchdir_test",
+ vfs2 = "True",
)
syscall_test(
@@ -152,11 +212,20 @@ syscall_test(
test = "//test/syscalls/linux:flock_test",
)
-syscall_test(test = "//test/syscalls/linux:fork_test")
+syscall_test(
+ test = "//test/syscalls/linux:fork_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:fpsig_fork_test")
+syscall_test(
+ test = "//test/syscalls/linux:fpsig_fork_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:fpsig_nested_test")
+syscall_test(
+ test = "//test/syscalls/linux:fpsig_nested_test",
+ vfs2 = "True",
+)
syscall_test(
add_overlay = True,
@@ -167,20 +236,33 @@ syscall_test(
size = "medium",
shard_count = 5,
test = "//test/syscalls/linux:futex_test",
+ vfs2 = "True",
)
-syscall_test(test = "//test/syscalls/linux:getcpu_host_test")
+syscall_test(
+ test = "//test/syscalls/linux:getcpu_host_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:getcpu_test")
+syscall_test(
+ test = "//test/syscalls/linux:getcpu_test",
+ vfs2 = "True",
+)
syscall_test(
add_overlay = True,
test = "//test/syscalls/linux:getdents_test",
)
-syscall_test(test = "//test/syscalls/linux:getrandom_test")
+syscall_test(
+ test = "//test/syscalls/linux:getrandom_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:getrusage_test")
+syscall_test(
+ test = "//test/syscalls/linux:getrusage_test",
+ vfs2 = "True",
+)
syscall_test(
size = "medium",
@@ -196,15 +278,20 @@ syscall_test(
syscall_test(
test = "//test/syscalls/linux:iptables_test",
+ vfs2 = "True",
)
syscall_test(
size = "large",
shard_count = 5,
test = "//test/syscalls/linux:itimer_test",
+ vfs2 = "True",
)
-syscall_test(test = "//test/syscalls/linux:kill_test")
+syscall_test(
+ test = "//test/syscalls/linux:kill_test",
+ vfs2 = "True",
+)
syscall_test(
add_overlay = True,
@@ -215,19 +302,33 @@ syscall_test(
syscall_test(
add_overlay = True,
test = "//test/syscalls/linux:lseek_test",
+ vfs2 = "True",
)
-syscall_test(test = "//test/syscalls/linux:madvise_test")
+syscall_test(
+ test = "//test/syscalls/linux:madvise_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:memory_accounting_test")
+syscall_test(
+ test = "//test/syscalls/linux:memory_accounting_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:mempolicy_test")
+syscall_test(
+ test = "//test/syscalls/linux:mempolicy_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:mincore_test")
+syscall_test(
+ test = "//test/syscalls/linux:mincore_test",
+ vfs2 = "True",
+)
syscall_test(
add_overlay = True,
test = "//test/syscalls/linux:mkdir_test",
+ vfs2 = "True",
)
syscall_test(
@@ -249,20 +350,29 @@ syscall_test(
syscall_test(
size = "medium",
test = "//test/syscalls/linux:mremap_test",
+ vfs2 = "True",
)
syscall_test(
size = "medium",
test = "//test/syscalls/linux:msync_test",
+ vfs2 = "True",
)
-syscall_test(test = "//test/syscalls/linux:munmap_test")
+syscall_test(
+ test = "//test/syscalls/linux:munmap_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:network_namespace_test")
+syscall_test(
+ test = "//test/syscalls/linux:network_namespace_test",
+ vfs2 = "True",
+)
syscall_test(
add_overlay = True,
test = "//test/syscalls/linux:open_create_test",
+ vfs2 = "True",
)
syscall_test(
@@ -270,40 +380,65 @@ syscall_test(
test = "//test/syscalls/linux:open_test",
)
-syscall_test(test = "//test/syscalls/linux:packet_socket_raw_test")
+syscall_test(
+ test = "//test/syscalls/linux:packet_socket_raw_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:packet_socket_test")
+syscall_test(
+ test = "//test/syscalls/linux:packet_socket_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:partial_bad_buffer_test")
+syscall_test(
+ test = "//test/syscalls/linux:partial_bad_buffer_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:pause_test")
+syscall_test(
+ test = "//test/syscalls/linux:pause_test",
+ vfs2 = "True",
+)
syscall_test(
size = "large",
add_overlay = True,
shard_count = 5,
test = "//test/syscalls/linux:pipe_test",
+ vfs2 = "True",
)
-syscall_test(test = "//test/syscalls/linux:poll_test")
+syscall_test(
+ test = "//test/syscalls/linux:poll_test",
+ vfs2 = "True",
+)
syscall_test(
size = "medium",
test = "//test/syscalls/linux:ppoll_test",
+ vfs2 = "True",
)
-syscall_test(test = "//test/syscalls/linux:prctl_setuid_test")
+syscall_test(
+ test = "//test/syscalls/linux:prctl_setuid_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:prctl_test")
+syscall_test(
+ test = "//test/syscalls/linux:prctl_test",
+ vfs2 = "True",
+)
syscall_test(
add_overlay = True,
test = "//test/syscalls/linux:pread64_test",
+ vfs2 = "True",
)
syscall_test(
add_overlay = True,
test = "//test/syscalls/linux:preadv_test",
+ vfs2 = "True",
)
syscall_test(
@@ -311,36 +446,56 @@ syscall_test(
test = "//test/syscalls/linux:preadv2_test",
)
-syscall_test(test = "//test/syscalls/linux:priority_test")
+syscall_test(
+ test = "//test/syscalls/linux:priority_test",
+ vfs2 = "True",
+)
syscall_test(
size = "medium",
test = "//test/syscalls/linux:proc_test",
)
-syscall_test(test = "//test/syscalls/linux:proc_net_test")
+syscall_test(
+ test = "//test/syscalls/linux:proc_net_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:proc_pid_oomscore_test")
+syscall_test(
+ test = "//test/syscalls/linux:proc_pid_oomscore_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:proc_pid_smaps_test")
+syscall_test(
+ test = "//test/syscalls/linux:proc_pid_smaps_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:proc_pid_uid_gid_map_test")
+syscall_test(
+ test = "//test/syscalls/linux:proc_pid_uid_gid_map_test",
+)
syscall_test(
size = "medium",
test = "//test/syscalls/linux:pselect_test",
+ vfs2 = "True",
)
-syscall_test(test = "//test/syscalls/linux:ptrace_test")
+syscall_test(
+ test = "//test/syscalls/linux:ptrace_test",
+ vfs2 = "True",
+)
syscall_test(
size = "medium",
shard_count = 5,
test = "//test/syscalls/linux:pty_test",
+ vfs2 = "True",
)
syscall_test(
test = "//test/syscalls/linux:pty_root_test",
+ vfs2 = "True",
)
syscall_test(
@@ -351,17 +506,28 @@ syscall_test(
syscall_test(
add_overlay = True,
test = "//test/syscalls/linux:pwrite64_test",
+ vfs2 = "True",
)
-syscall_test(test = "//test/syscalls/linux:raw_socket_hdrincl_test")
+syscall_test(
+ test = "//test/syscalls/linux:raw_socket_hdrincl_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:raw_socket_icmp_test")
+syscall_test(
+ test = "//test/syscalls/linux:raw_socket_icmp_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:raw_socket_ipv4_test")
+syscall_test(
+ test = "//test/syscalls/linux:raw_socket_ipv4_test",
+ vfs2 = "True",
+)
syscall_test(
add_overlay = True,
test = "//test/syscalls/linux:read_test",
+ vfs2 = "True",
)
syscall_test(
@@ -373,12 +539,14 @@ syscall_test(
size = "medium",
shard_count = 5,
test = "//test/syscalls/linux:readv_socket_test",
+ vfs2 = "True",
)
syscall_test(
size = "medium",
add_overlay = True,
test = "//test/syscalls/linux:readv_test",
+ vfs2 = "True",
)
syscall_test(
@@ -387,25 +555,50 @@ syscall_test(
test = "//test/syscalls/linux:rename_test",
)
-syscall_test(test = "//test/syscalls/linux:rlimits_test")
+syscall_test(
+ test = "//test/syscalls/linux:rlimits_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:rseq_test")
+syscall_test(
+ test = "//test/syscalls/linux:rseq_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:rtsignal_test")
+syscall_test(
+ test = "//test/syscalls/linux:rtsignal_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:signalfd_test")
+syscall_test(
+ test = "//test/syscalls/linux:signalfd_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:sched_test")
+syscall_test(
+ test = "//test/syscalls/linux:sched_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:sched_yield_test")
+syscall_test(
+ test = "//test/syscalls/linux:sched_yield_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:seccomp_test")
+syscall_test(
+ test = "//test/syscalls/linux:seccomp_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:select_test")
+syscall_test(
+ test = "//test/syscalls/linux:select_test",
+ vfs2 = "True",
+)
syscall_test(
shard_count = 20,
test = "//test/syscalls/linux:semaphore_test",
+ vfs2 = "True",
)
syscall_test(
@@ -421,49 +614,68 @@ syscall_test(
syscall_test(
add_overlay = True,
test = "//test/syscalls/linux:splice_test",
+ vfs2 = "True",
)
-syscall_test(test = "//test/syscalls/linux:sigaction_test")
+syscall_test(
+ test = "//test/syscalls/linux:sigaction_test",
+ vfs2 = "True",
+)
# TODO(b/119826902): Enable once the test passes in runsc.
-# syscall_test(test = "//test/syscalls/linux:sigaltstack_test")
+# syscall_test(vfs2="True",test = "//test/syscalls/linux:sigaltstack_test")
-syscall_test(test = "//test/syscalls/linux:sigiret_test")
+syscall_test(
+ test = "//test/syscalls/linux:sigiret_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:sigprocmask_test")
+syscall_test(
+ test = "//test/syscalls/linux:sigprocmask_test",
+ vfs2 = "True",
+)
syscall_test(
size = "medium",
test = "//test/syscalls/linux:sigstop_test",
+ vfs2 = "True",
)
-syscall_test(test = "//test/syscalls/linux:sigtimedwait_test")
+syscall_test(
+ test = "//test/syscalls/linux:sigtimedwait_test",
+ vfs2 = "True",
+)
syscall_test(
size = "medium",
test = "//test/syscalls/linux:shm_test",
+ vfs2 = "True",
)
syscall_test(
size = "medium",
test = "//test/syscalls/linux:socket_abstract_non_blocking_test",
+ vfs2 = "True",
)
syscall_test(
size = "large",
shard_count = 50,
test = "//test/syscalls/linux:socket_abstract_test",
+ vfs2 = "True",
)
syscall_test(
size = "medium",
test = "//test/syscalls/linux:socket_domain_non_blocking_test",
+ vfs2 = "True",
)
syscall_test(
size = "large",
shard_count = 50,
test = "//test/syscalls/linux:socket_domain_test",
+ vfs2 = "True",
)
syscall_test(
@@ -489,58 +701,90 @@ syscall_test(
size = "large",
shard_count = 50,
test = "//test/syscalls/linux:socket_ip_tcp_generic_loopback_test",
+ vfs2 = "True",
)
syscall_test(
size = "medium",
test = "//test/syscalls/linux:socket_ip_tcp_loopback_non_blocking_test",
+ vfs2 = "True",
)
syscall_test(
size = "large",
shard_count = 50,
test = "//test/syscalls/linux:socket_ip_tcp_loopback_test",
+ vfs2 = "True",
)
syscall_test(
size = "medium",
shard_count = 50,
test = "//test/syscalls/linux:socket_ip_tcp_udp_generic_loopback_test",
+ vfs2 = "True",
)
syscall_test(
size = "medium",
test = "//test/syscalls/linux:socket_ip_udp_loopback_non_blocking_test",
+ vfs2 = "True",
)
syscall_test(
size = "large",
shard_count = 50,
test = "//test/syscalls/linux:socket_ip_udp_loopback_test",
+ vfs2 = "True",
)
syscall_test(
size = "medium",
test = "//test/syscalls/linux:socket_ipv4_udp_unbound_loopback_test",
+ vfs2 = "True",
)
-syscall_test(test = "//test/syscalls/linux:socket_ip_unbound_test")
+syscall_test(
+ test = "//test/syscalls/linux:socket_ip_unbound_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:socket_netdevice_test")
+syscall_test(
+ test = "//test/syscalls/linux:socket_netdevice_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:socket_netlink_test")
+syscall_test(
+ test = "//test/syscalls/linux:socket_netlink_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:socket_netlink_route_test")
+syscall_test(
+ test = "//test/syscalls/linux:socket_netlink_route_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:socket_netlink_uevent_test")
+syscall_test(
+ test = "//test/syscalls/linux:socket_netlink_uevent_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:socket_blocking_local_test")
+syscall_test(
+ test = "//test/syscalls/linux:socket_blocking_local_test",
+)
-syscall_test(test = "//test/syscalls/linux:socket_blocking_ip_test")
+syscall_test(
+ test = "//test/syscalls/linux:socket_blocking_ip_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:socket_non_stream_blocking_local_test")
+syscall_test(
+ test = "//test/syscalls/linux:socket_non_stream_blocking_local_test",
+)
-syscall_test(test = "//test/syscalls/linux:socket_non_stream_blocking_udp_test")
+syscall_test(
+ test = "//test/syscalls/linux:socket_non_stream_blocking_udp_test",
+ vfs2 = "True",
+)
syscall_test(
size = "large",
@@ -550,6 +794,7 @@ syscall_test(
syscall_test(
size = "large",
test = "//test/syscalls/linux:socket_stream_blocking_tcp_test",
+ vfs2 = "True",
)
syscall_test(
@@ -572,6 +817,7 @@ syscall_test(
syscall_test(
size = "medium",
test = "//test/syscalls/linux:socket_unix_dgram_non_blocking_test",
+ vfs2 = "True",
)
syscall_test(
@@ -579,6 +825,7 @@ syscall_test(
add_overlay = True,
shard_count = 50,
test = "//test/syscalls/linux:socket_unix_pair_test",
+ vfs2 = "True",
)
syscall_test(
@@ -596,11 +843,13 @@ syscall_test(
syscall_test(
size = "medium",
test = "//test/syscalls/linux:socket_unix_unbound_abstract_test",
+ vfs2 = "True",
)
syscall_test(
size = "medium",
test = "//test/syscalls/linux:socket_unix_unbound_dgram_test",
+ vfs2 = "True",
)
syscall_test(
@@ -612,6 +861,7 @@ syscall_test(
size = "medium",
shard_count = 10,
test = "//test/syscalls/linux:socket_unix_unbound_seqpacket_test",
+ vfs2 = "True",
)
syscall_test(
@@ -623,6 +873,7 @@ syscall_test(
syscall_test(
add_overlay = True,
test = "//test/syscalls/linux:statfs_test",
+ vfs2 = "True",
)
syscall_test(
@@ -633,6 +884,7 @@ syscall_test(
syscall_test(
add_overlay = True,
test = "//test/syscalls/linux:stat_times_test",
+ vfs2 = "True",
)
syscall_test(
@@ -648,6 +900,7 @@ syscall_test(
syscall_test(
add_overlay = True,
test = "//test/syscalls/linux:sync_test",
+ vfs2 = "True",
)
syscall_test(
@@ -655,86 +908,151 @@ syscall_test(
test = "//test/syscalls/linux:sync_file_range_test",
)
-syscall_test(test = "//test/syscalls/linux:sysinfo_test")
+syscall_test(
+ test = "//test/syscalls/linux:sysinfo_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:syslog_test")
+syscall_test(
+ test = "//test/syscalls/linux:syslog_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:sysret_test")
+syscall_test(
+ test = "//test/syscalls/linux:sysret_test",
+ vfs2 = "True",
+)
syscall_test(
size = "medium",
shard_count = 10,
test = "//test/syscalls/linux:tcp_socket_test",
+ vfs2 = "True",
)
-syscall_test(test = "//test/syscalls/linux:tgkill_test")
+syscall_test(
+ test = "//test/syscalls/linux:tgkill_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:timerfd_test")
+syscall_test(
+ test = "//test/syscalls/linux:timerfd_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:timers_test")
+syscall_test(
+ test = "//test/syscalls/linux:timers_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:time_test")
+syscall_test(
+ test = "//test/syscalls/linux:time_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:tkill_test")
+syscall_test(
+ test = "//test/syscalls/linux:tkill_test",
+ vfs2 = "True",
+)
syscall_test(
add_overlay = True,
test = "//test/syscalls/linux:truncate_test",
)
-syscall_test(test = "//test/syscalls/linux:tuntap_test")
+syscall_test(
+ test = "//test/syscalls/linux:tuntap_test",
+)
syscall_test(
add_hostinet = True,
test = "//test/syscalls/linux:tuntap_hostinet_test",
+ vfs2 = "True",
)
-syscall_test(test = "//test/syscalls/linux:udp_bind_test")
+syscall_test(
+ test = "//test/syscalls/linux:udp_bind_test",
+ vfs2 = "True",
+)
syscall_test(
size = "medium",
add_hostinet = True,
shard_count = 10,
test = "//test/syscalls/linux:udp_socket_test",
+ vfs2 = "True",
)
-syscall_test(test = "//test/syscalls/linux:uidgid_test")
+syscall_test(
+ test = "//test/syscalls/linux:uidgid_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:uname_test")
+syscall_test(
+ test = "//test/syscalls/linux:uname_test",
+ vfs2 = "True",
+)
syscall_test(
add_overlay = True,
test = "//test/syscalls/linux:unlink_test",
+ vfs2 = "True",
)
-syscall_test(test = "//test/syscalls/linux:unshare_test")
+syscall_test(
+ test = "//test/syscalls/linux:unshare_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:utimes_test")
+syscall_test(
+ test = "//test/syscalls/linux:utimes_test",
+ vfs2 = "True",
+)
syscall_test(
size = "medium",
test = "//test/syscalls/linux:vdso_clock_gettime_test",
+ vfs2 = "True",
)
-syscall_test(test = "//test/syscalls/linux:vdso_test")
+syscall_test(
+ test = "//test/syscalls/linux:vdso_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:vsyscall_test")
+syscall_test(
+ test = "//test/syscalls/linux:vsyscall_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:vfork_test")
+syscall_test(
+ test = "//test/syscalls/linux:vfork_test",
+ vfs2 = "True",
+)
syscall_test(
size = "medium",
shard_count = 5,
test = "//test/syscalls/linux:wait_test",
+ vfs2 = "True",
)
syscall_test(
add_overlay = True,
test = "//test/syscalls/linux:write_test",
+ vfs2 = "True",
)
-syscall_test(test = "//test/syscalls/linux:proc_net_unix_test")
+syscall_test(
+ test = "//test/syscalls/linux:proc_net_unix_test",
+)
-syscall_test(test = "//test/syscalls/linux:proc_net_tcp_test")
+syscall_test(
+ test = "//test/syscalls/linux:proc_net_tcp_test",
+ vfs2 = "True",
+)
-syscall_test(test = "//test/syscalls/linux:proc_net_udp_test")
+syscall_test(
+ test = "//test/syscalls/linux:proc_net_udp_test",
+ vfs2 = "True",
+)
diff --git a/test/syscalls/linux/BUILD b/test/syscalls/linux/BUILD
index 5acdb8438..f4b5de18d 100644
--- a/test/syscalls/linux/BUILD
+++ b/test/syscalls/linux/BUILD
@@ -951,6 +951,7 @@ cc_binary(
"//test/util:epoll_util",
"//test/util:file_descriptor",
"//test/util:fs_util",
+ "//test/util:posix_error",
"//test/util:temp_path",
"//test/util:test_main",
"//test/util:test_util",
@@ -1382,7 +1383,7 @@ cc_binary(
srcs = ["partial_bad_buffer.cc"],
linkstatic = 1,
deps = [
- "//test/syscalls/linux:socket_test_util",
+ ":socket_test_util",
"//test/util:file_descriptor",
"//test/util:fs_util",
"@com_google_absl//absl/time",
@@ -3461,7 +3462,7 @@ cc_binary(
deps = [
":socket_test_util",
gtest,
- "//test/syscalls/linux:socket_netlink_route_util",
+ ":socket_netlink_route_util",
"//test/util:capability_util",
"//test/util:file_descriptor",
"//test/util:fs_util",
diff --git a/test/syscalls/linux/accept_bind.cc b/test/syscalls/linux/accept_bind.cc
index e08c578f0..f65a14fb8 100644
--- a/test/syscalls/linux/accept_bind.cc
+++ b/test/syscalls/linux/accept_bind.cc
@@ -13,6 +13,7 @@
// limitations under the License.
#include <stdio.h>
+#include <sys/socket.h>
#include <sys/un.h>
#include <algorithm>
@@ -141,6 +142,47 @@ TEST_P(AllSocketPairTest, Connect) {
SyscallSucceeds());
}
+TEST_P(AllSocketPairTest, ConnectWithWrongType) {
+ auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
+
+ int type;
+ socklen_t typelen = sizeof(type);
+ EXPECT_THAT(
+ getsockopt(sockets->first_fd(), SOL_SOCKET, SO_TYPE, &type, &typelen),
+ SyscallSucceeds());
+ switch (type) {
+ case SOCK_STREAM:
+ type = SOCK_SEQPACKET;
+ break;
+ case SOCK_SEQPACKET:
+ type = SOCK_STREAM;
+ break;
+ }
+
+ const FileDescriptor another_socket =
+ ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_UNIX, type, 0));
+
+ ASSERT_THAT(bind(sockets->first_fd(), sockets->first_addr(),
+ sockets->first_addr_size()),
+ SyscallSucceeds());
+
+ ASSERT_THAT(listen(sockets->first_fd(), 5), SyscallSucceeds());
+
+ if (sockets->first_addr()->sa_data[0] != 0) {
+ ASSERT_THAT(connect(another_socket.get(), sockets->first_addr(),
+ sockets->first_addr_size()),
+ SyscallFailsWithErrno(EPROTOTYPE));
+ } else {
+ ASSERT_THAT(connect(another_socket.get(), sockets->first_addr(),
+ sockets->first_addr_size()),
+ SyscallFailsWithErrno(ECONNREFUSED));
+ }
+
+ ASSERT_THAT(connect(sockets->second_fd(), sockets->first_addr(),
+ sockets->first_addr_size()),
+ SyscallSucceeds());
+}
+
TEST_P(AllSocketPairTest, ConnectNonListening) {
auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
diff --git a/test/syscalls/linux/inotify.cc b/test/syscalls/linux/inotify.cc
index 0e13ad190..1d1a7171d 100644
--- a/test/syscalls/linux/inotify.cc
+++ b/test/syscalls/linux/inotify.cc
@@ -19,6 +19,7 @@
#include <sys/inotify.h>
#include <sys/ioctl.h>
#include <sys/time.h>
+#include <sys/xattr.h>
#include <atomic>
#include <list>
@@ -33,6 +34,7 @@
#include "test/util/epoll_util.h"
#include "test/util/file_descriptor.h"
#include "test/util/fs_util.h"
+#include "test/util/posix_error.h"
#include "test/util/temp_path.h"
#include "test/util/test_util.h"
#include "test/util/thread_util.h"
@@ -335,6 +337,11 @@ TEST(Inotify, InotifyFdNotWritable) {
EXPECT_THAT(write(fd.get(), "x", 1), SyscallFailsWithErrno(EBADF));
}
+TEST(Inotify, InitFlags) {
+ EXPECT_THAT(inotify_init1(IN_NONBLOCK | IN_CLOEXEC), SyscallSucceeds());
+ EXPECT_THAT(inotify_init1(12345), SyscallFailsWithErrno(EINVAL));
+}
+
TEST(Inotify, NonBlockingReadReturnsEagain) {
const FileDescriptor fd =
ASSERT_NO_ERRNO_AND_VALUE(InotifyInit1(IN_NONBLOCK));
@@ -395,7 +402,7 @@ TEST(Inotify, CanDeleteFileAfterRemovingWatch) {
file1.reset();
}
-TEST(Inotify, CanRemoveWatchAfterDeletingFile) {
+TEST(Inotify, RemoveWatchAfterDeletingFileFails) {
const TempPath root = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
TempPath file1 =
ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileIn(root.path()));
@@ -491,17 +498,23 @@ TEST(Inotify, DeletingChildGeneratesEvents) {
Event(IN_DELETE, root_wd, Basename(file1_path))}));
}
+// Creating a file in "parent/child" should generate events for child, but not
+// parent.
TEST(Inotify, CreatingFileGeneratesEvents) {
- const TempPath root = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
+ const TempPath parent = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
+ const TempPath child =
+ ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(parent.path()));
const FileDescriptor fd =
ASSERT_NO_ERRNO_AND_VALUE(InotifyInit1(IN_NONBLOCK));
+ ASSERT_NO_ERRNO_AND_VALUE(
+ InotifyAddWatch(fd.get(), parent.path(), IN_ALL_EVENTS));
const int wd = ASSERT_NO_ERRNO_AND_VALUE(
- InotifyAddWatch(fd.get(), root.path(), IN_ALL_EVENTS));
+ InotifyAddWatch(fd.get(), child.path(), IN_ALL_EVENTS));
// Create a new file in the directory.
const TempPath file1 =
- ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileIn(root.path()));
+ ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileIn(child.path()));
const std::vector<Event> events =
ASSERT_NO_ERRNO_AND_VALUE(DrainEvents(fd.get()));
@@ -554,6 +567,47 @@ TEST(Inotify, WritingFileGeneratesModifyEvent) {
ASSERT_THAT(events, Are({Event(IN_MODIFY, wd, Basename(file1.path()))}));
}
+TEST(Inotify, SizeZeroReadWriteGeneratesNothing) {
+ const TempPath root = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
+ const FileDescriptor fd =
+ ASSERT_NO_ERRNO_AND_VALUE(InotifyInit1(IN_NONBLOCK));
+ const TempPath file1 =
+ ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileIn(root.path()));
+
+ const FileDescriptor file1_fd =
+ ASSERT_NO_ERRNO_AND_VALUE(Open(file1.path(), O_RDWR));
+ ASSERT_NO_ERRNO_AND_VALUE(
+ InotifyAddWatch(fd.get(), root.path(), IN_ALL_EVENTS));
+
+ // Read from the empty file.
+ int val;
+ ASSERT_THAT(read(file1_fd.get(), &val, sizeof(val)),
+ SyscallSucceedsWithValue(0));
+
+ // Write zero bytes.
+ ASSERT_THAT(write(file1_fd.get(), "", 0), SyscallSucceedsWithValue(0));
+
+ const std::vector<Event> events =
+ ASSERT_NO_ERRNO_AND_VALUE(DrainEvents(fd.get()));
+ ASSERT_THAT(events, Are({}));
+}
+
+TEST(Inotify, FailedFileCreationGeneratesNoEvents) {
+ const TempPath dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
+ const std::string dir_path = dir.path();
+ const FileDescriptor fd =
+ ASSERT_NO_ERRNO_AND_VALUE(InotifyInit1(IN_NONBLOCK));
+ ASSERT_NO_ERRNO_AND_VALUE(InotifyAddWatch(fd.get(), dir_path, IN_ALL_EVENTS));
+
+ const char* p = dir_path.c_str();
+ ASSERT_THAT(mkdir(p, 0777), SyscallFails());
+ ASSERT_THAT(mknod(p, S_IFIFO, 0777), SyscallFails());
+ ASSERT_THAT(symlink(p, p), SyscallFails());
+ ASSERT_THAT(link(p, p), SyscallFails());
+ std::vector<Event> events = ASSERT_NO_ERRNO_AND_VALUE(DrainEvents(fd.get()));
+ ASSERT_THAT(events, Are({}));
+}
+
TEST(Inotify, WatchSetAfterOpenReportsCloseFdEvent) {
const TempPath root = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
const FileDescriptor fd =
@@ -602,7 +656,7 @@ TEST(Inotify, ChildrenDeletionInWatchedDirGeneratesEvent) {
Event(IN_DELETE | IN_ISDIR, wd, Basename(dir1_path))}));
}
-TEST(Inotify, WatchTargetDeletionGeneratesEvent) {
+TEST(Inotify, RmdirOnWatchedTargetGeneratesEvent) {
const TempPath root = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
const FileDescriptor fd =
ASSERT_NO_ERRNO_AND_VALUE(InotifyInit1(IN_NONBLOCK));
@@ -1228,7 +1282,7 @@ TEST(Inotify, LinkGeneratesAttribAndCreateEvents) {
InotifyAddWatch(fd.get(), file1.path(), IN_ALL_EVENTS));
const int rc = link(file1.path().c_str(), link1.path().c_str());
- // link(2) is only supported on tmpfs in the sandbox.
+ // NOTE(b/34861058): link(2) is only supported on tmpfs in the sandbox.
SKIP_IF(IsRunningOnGvisor() && rc != 0 &&
(errno == EPERM || errno == ENOENT));
ASSERT_THAT(rc, SyscallSucceeds());
@@ -1322,21 +1376,27 @@ TEST(Inotify, HardlinksReuseSameWatch) {
Event(IN_DELETE, root_wd, Basename(file1_path))}));
}
+// Calling mkdir within "parent/child" should generate an event for child, but
+// not parent.
TEST(Inotify, MkdirGeneratesCreateEventWithDirFlag) {
- const TempPath root = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
+ const TempPath parent = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
+ const TempPath child =
+ ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(parent.path()));
const FileDescriptor fd =
ASSERT_NO_ERRNO_AND_VALUE(InotifyInit1(IN_NONBLOCK));
- const int root_wd = ASSERT_NO_ERRNO_AND_VALUE(
- InotifyAddWatch(fd.get(), root.path(), IN_ALL_EVENTS));
+ ASSERT_NO_ERRNO_AND_VALUE(
+ InotifyAddWatch(fd.get(), parent.path(), IN_ALL_EVENTS));
+ const int child_wd = ASSERT_NO_ERRNO_AND_VALUE(
+ InotifyAddWatch(fd.get(), child.path(), IN_ALL_EVENTS));
- const TempPath dir1(NewTempAbsPathInDir(root.path()));
+ const TempPath dir1(NewTempAbsPathInDir(child.path()));
ASSERT_THAT(mkdir(dir1.path().c_str(), 0777), SyscallSucceeds());
const std::vector<Event> events =
ASSERT_NO_ERRNO_AND_VALUE(DrainEvents(fd.get()));
ASSERT_THAT(
events,
- Are({Event(IN_CREATE | IN_ISDIR, root_wd, Basename(dir1.path()))}));
+ Are({Event(IN_CREATE | IN_ISDIR, child_wd, Basename(dir1.path()))}));
}
TEST(Inotify, MultipleInotifyInstancesAndWatchesAllGetEvents) {
@@ -1596,7 +1656,44 @@ TEST(Inotify, EpollNoDeadlock) {
}
}
-TEST(Inotify, SpliceEvent) {
+// On Linux, inotify behavior is not very consistent with splice(2). We try our
+// best to emulate Linux for very basic calls to splice.
+TEST(Inotify, SpliceOnWatchTarget) {
+ int pipes[2];
+ ASSERT_THAT(pipe2(pipes, O_NONBLOCK), SyscallSucceeds());
+
+ const TempPath dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
+ const FileDescriptor inotify_fd =
+ ASSERT_NO_ERRNO_AND_VALUE(InotifyInit1(IN_NONBLOCK));
+ const TempPath file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith(
+ dir.path(), "some content", TempPath::kDefaultFileMode));
+
+ const FileDescriptor fd =
+ ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR));
+ const int dir_wd = ASSERT_NO_ERRNO_AND_VALUE(
+ InotifyAddWatch(inotify_fd.get(), dir.path(), IN_ALL_EVENTS));
+ const int file_wd = ASSERT_NO_ERRNO_AND_VALUE(
+ InotifyAddWatch(inotify_fd.get(), file.path(), IN_ALL_EVENTS));
+
+ EXPECT_THAT(splice(fd.get(), nullptr, pipes[1], nullptr, 1, /*flags=*/0),
+ SyscallSucceedsWithValue(1));
+
+ // Surprisingly, events are not generated in Linux if we read from a file.
+ std::vector<Event> events =
+ ASSERT_NO_ERRNO_AND_VALUE(DrainEvents(inotify_fd.get()));
+ ASSERT_THAT(events, Are({}));
+
+ EXPECT_THAT(splice(pipes[0], nullptr, fd.get(), nullptr, 1, /*flags=*/0),
+ SyscallSucceedsWithValue(1));
+
+ events = ASSERT_NO_ERRNO_AND_VALUE(DrainEvents(inotify_fd.get()));
+ ASSERT_THAT(events, Are({
+ Event(IN_MODIFY, dir_wd, Basename(file.path())),
+ Event(IN_MODIFY, file_wd),
+ }));
+}
+
+TEST(Inotify, SpliceOnInotifyFD) {
int pipes[2];
ASSERT_THAT(pipe2(pipes, O_NONBLOCK), SyscallSucceeds());
@@ -1624,6 +1721,315 @@ TEST(Inotify, SpliceEvent) {
ASSERT_THAT(events, Are({Event(IN_ACCESS, watcher)}));
}
+// Watches on a parent should not be triggered by actions on a hard link to one
+// of its children that has a different parent.
+TEST(Inotify, LinkOnOtherParent) {
+ const TempPath dir1 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
+ const TempPath dir2 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
+ const TempPath file =
+ ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileIn(dir1.path()));
+ std::string link_path = NewTempAbsPathInDir(dir2.path());
+
+ const int rc = link(file.path().c_str(), link_path.c_str());
+ // NOTE(b/34861058): link(2) is only supported on tmpfs in the sandbox.
+ SKIP_IF(IsRunningOnGvisor() && rc != 0 &&
+ (errno == EPERM || errno == ENOENT));
+ ASSERT_THAT(rc, SyscallSucceeds());
+
+ const FileDescriptor inotify_fd =
+ ASSERT_NO_ERRNO_AND_VALUE(InotifyInit1(IN_NONBLOCK));
+ ASSERT_NO_ERRNO_AND_VALUE(
+ InotifyAddWatch(inotify_fd.get(), dir1.path(), IN_ALL_EVENTS));
+
+ // Perform various actions on the link outside of dir1, which should trigger
+ // no inotify events.
+ const FileDescriptor fd =
+ ASSERT_NO_ERRNO_AND_VALUE(Open(link_path.c_str(), O_RDWR));
+ int val = 0;
+ ASSERT_THAT(write(fd.get(), &val, sizeof(val)), SyscallSucceeds());
+ ASSERT_THAT(read(fd.get(), &val, sizeof(val)), SyscallSucceeds());
+ ASSERT_THAT(ftruncate(fd.get(), 12345), SyscallSucceeds());
+ ASSERT_THAT(unlink(link_path.c_str()), SyscallSucceeds());
+ const std::vector<Event> events =
+ ASSERT_NO_ERRNO_AND_VALUE(DrainEvents(inotify_fd.get()));
+ EXPECT_THAT(events, Are({}));
+}
+
+TEST(Inotify, Xattr) {
+ // TODO(gvisor.dev/issue/1636): Support extended attributes in runsc gofer.
+ SKIP_IF(IsRunningOnGvisor());
+
+ const TempPath file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile());
+ const std::string path = file.path();
+ const FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(path, O_RDWR));
+ const FileDescriptor inotify_fd =
+ ASSERT_NO_ERRNO_AND_VALUE(InotifyInit1(IN_NONBLOCK));
+ const int wd = ASSERT_NO_ERRNO_AND_VALUE(
+ InotifyAddWatch(inotify_fd.get(), path, IN_ALL_EVENTS));
+
+ const char* cpath = path.c_str();
+ const char* name = "user.test";
+ int val = 123;
+ ASSERT_THAT(setxattr(cpath, name, &val, sizeof(val), /*flags=*/0),
+ SyscallSucceeds());
+ std::vector<Event> events =
+ ASSERT_NO_ERRNO_AND_VALUE(DrainEvents(inotify_fd.get()));
+ EXPECT_THAT(events, Are({Event(IN_ATTRIB, wd)}));
+
+ ASSERT_THAT(getxattr(cpath, name, &val, sizeof(val)), SyscallSucceeds());
+ events = ASSERT_NO_ERRNO_AND_VALUE(DrainEvents(inotify_fd.get()));
+ EXPECT_THAT(events, Are({}));
+
+ char list[100];
+ ASSERT_THAT(listxattr(cpath, list, sizeof(list)), SyscallSucceeds());
+ events = ASSERT_NO_ERRNO_AND_VALUE(DrainEvents(inotify_fd.get()));
+ EXPECT_THAT(events, Are({}));
+
+ ASSERT_THAT(removexattr(cpath, name), SyscallSucceeds());
+ events = ASSERT_NO_ERRNO_AND_VALUE(DrainEvents(inotify_fd.get()));
+ EXPECT_THAT(events, Are({Event(IN_ATTRIB, wd)}));
+
+ ASSERT_THAT(fsetxattr(fd.get(), name, &val, sizeof(val), /*flags=*/0),
+ SyscallSucceeds());
+ events = ASSERT_NO_ERRNO_AND_VALUE(DrainEvents(inotify_fd.get()));
+ EXPECT_THAT(events, Are({Event(IN_ATTRIB, wd)}));
+
+ ASSERT_THAT(fgetxattr(fd.get(), name, &val, sizeof(val)), SyscallSucceeds());
+ events = ASSERT_NO_ERRNO_AND_VALUE(DrainEvents(inotify_fd.get()));
+ EXPECT_THAT(events, Are({}));
+
+ ASSERT_THAT(flistxattr(fd.get(), list, sizeof(list)), SyscallSucceeds());
+ events = ASSERT_NO_ERRNO_AND_VALUE(DrainEvents(inotify_fd.get()));
+ EXPECT_THAT(events, Are({}));
+
+ ASSERT_THAT(fremovexattr(fd.get(), name), SyscallSucceeds());
+ events = ASSERT_NO_ERRNO_AND_VALUE(DrainEvents(inotify_fd.get()));
+ EXPECT_THAT(events, Are({Event(IN_ATTRIB, wd)}));
+}
+
+TEST(Inotify, Exec) {
+ const TempPath dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
+ const TempPath bin = ASSERT_NO_ERRNO_AND_VALUE(
+ TempPath::CreateSymlinkTo(dir.path(), "/bin/true"));
+
+ const FileDescriptor fd =
+ ASSERT_NO_ERRNO_AND_VALUE(InotifyInit1(IN_NONBLOCK));
+ const int wd = ASSERT_NO_ERRNO_AND_VALUE(
+ InotifyAddWatch(fd.get(), bin.path(), IN_ALL_EVENTS));
+
+ // Perform exec.
+ ScopedThread t([&bin]() {
+ ASSERT_THAT(execl(bin.path().c_str(), bin.path().c_str(), (char*)nullptr),
+ SyscallSucceeds());
+ });
+ t.Join();
+
+ std::vector<Event> events = ASSERT_NO_ERRNO_AND_VALUE(DrainEvents(fd.get()));
+ EXPECT_THAT(events, Are({Event(IN_OPEN, wd), Event(IN_ACCESS, wd)}));
+}
+
+// Watches without IN_EXCL_UNLINK, should continue to emit events for file
+// descriptors after their corresponding files have been unlinked.
+//
+// We need to disable S/R because there are filesystems where we cannot re-open
+// fds to an unlinked file across S/R, e.g. gofer-backed filesytems.
+TEST(Inotify, IncludeUnlinkedFile_NoRandomSave) {
+ const DisableSave ds;
+
+ const TempPath dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
+ const TempPath file = ASSERT_NO_ERRNO_AND_VALUE(
+ TempPath::CreateFileWith(dir.path(), "123", TempPath::kDefaultFileMode));
+
+ const FileDescriptor fd =
+ ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR));
+
+ const FileDescriptor inotify_fd =
+ ASSERT_NO_ERRNO_AND_VALUE(InotifyInit1(IN_NONBLOCK));
+ const int dir_wd = ASSERT_NO_ERRNO_AND_VALUE(
+ InotifyAddWatch(inotify_fd.get(), dir.path(), IN_ALL_EVENTS));
+ const int file_wd = ASSERT_NO_ERRNO_AND_VALUE(
+ InotifyAddWatch(inotify_fd.get(), file.path(), IN_ALL_EVENTS));
+
+ ASSERT_THAT(unlink(file.path().c_str()), SyscallSucceeds());
+ int val = 0;
+ ASSERT_THAT(read(fd.get(), &val, sizeof(val)), SyscallSucceeds());
+ ASSERT_THAT(write(fd.get(), &val, sizeof(val)), SyscallSucceeds());
+ const std::vector<Event> events =
+ ASSERT_NO_ERRNO_AND_VALUE(DrainEvents(inotify_fd.get()));
+ EXPECT_THAT(events, Are({
+ Event(IN_ATTRIB, file_wd),
+ Event(IN_DELETE, dir_wd, Basename(file.path())),
+ Event(IN_ACCESS, dir_wd, Basename(file.path())),
+ Event(IN_ACCESS, file_wd),
+ Event(IN_MODIFY, dir_wd, Basename(file.path())),
+ Event(IN_MODIFY, file_wd),
+ }));
+}
+
+// Watches created with IN_EXCL_UNLINK will stop emitting events on fds for
+// children that have already been unlinked.
+//
+// We need to disable S/R because there are filesystems where we cannot re-open
+// fds to an unlinked file across S/R, e.g. gofer-backed filesytems.
+TEST(Inotify, ExcludeUnlink_NoRandomSave) {
+ const DisableSave ds;
+ // TODO(gvisor.dev/issue/1624): This test fails on VFS1.
+ SKIP_IF(IsRunningWithVFS1());
+
+ const TempPath dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
+ const TempPath file =
+ ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileIn(dir.path()));
+
+ const FileDescriptor fd =
+ ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR));
+
+ const FileDescriptor inotify_fd =
+ ASSERT_NO_ERRNO_AND_VALUE(InotifyInit1(IN_NONBLOCK));
+ const int wd = ASSERT_NO_ERRNO_AND_VALUE(InotifyAddWatch(
+ inotify_fd.get(), dir.path(), IN_ALL_EVENTS | IN_EXCL_UNLINK));
+
+ // Unlink the child, which should cause further operations on the open file
+ // descriptor to be ignored.
+ ASSERT_THAT(unlink(file.path().c_str()), SyscallSucceeds());
+ int val = 0;
+ ASSERT_THAT(write(fd.get(), &val, sizeof(val)), SyscallSucceeds());
+ ASSERT_THAT(read(fd.get(), &val, sizeof(val)), SyscallSucceeds());
+ const std::vector<Event> events =
+ ASSERT_NO_ERRNO_AND_VALUE(DrainEvents(inotify_fd.get()));
+ EXPECT_THAT(events, Are({Event(IN_DELETE, wd, Basename(file.path()))}));
+}
+
+// We need to disable S/R because there are filesystems where we cannot re-open
+// fds to an unlinked file across S/R, e.g. gofer-backed filesytems.
+TEST(Inotify, ExcludeUnlinkDirectory_NoRandomSave) {
+ const DisableSave ds;
+
+ const TempPath parent = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
+ TempPath dir =
+ ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(parent.path()));
+ std::string dirPath = dir.path();
+ const FileDescriptor inotify_fd =
+ ASSERT_NO_ERRNO_AND_VALUE(InotifyInit1(IN_NONBLOCK));
+
+ const FileDescriptor fd =
+ ASSERT_NO_ERRNO_AND_VALUE(Open(dirPath.c_str(), O_RDONLY | O_DIRECTORY));
+ const int wd = ASSERT_NO_ERRNO_AND_VALUE(InotifyAddWatch(
+ inotify_fd.get(), parent.path(), IN_ALL_EVENTS | IN_EXCL_UNLINK));
+
+ // Unlink the dir, and then close the open fd.
+ ASSERT_THAT(rmdir(dirPath.c_str()), SyscallSucceeds());
+ dir.reset();
+
+ const std::vector<Event> events =
+ ASSERT_NO_ERRNO_AND_VALUE(DrainEvents(inotify_fd.get()));
+ // No close event should appear.
+ ASSERT_THAT(events,
+ Are({Event(IN_DELETE | IN_ISDIR, wd, Basename(dirPath))}));
+}
+
+// If "dir/child" and "dir/child2" are links to the same file, and "dir/child"
+// is unlinked, a watch on "dir" with IN_EXCL_UNLINK will exclude future events
+// for fds on "dir/child" but not "dir/child2".
+//
+// We need to disable S/R because there are filesystems where we cannot re-open
+// fds to an unlinked file across S/R, e.g. gofer-backed filesytems.
+TEST(Inotify, ExcludeUnlinkMultipleChildren_NoRandomSave) {
+ const DisableSave ds;
+ // TODO(gvisor.dev/issue/1624): This test fails on VFS1.
+ SKIP_IF(IsRunningWithVFS1());
+
+ const TempPath dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
+ const TempPath file =
+ ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileIn(dir.path()));
+ std::string path1 = file.path();
+ std::string path2 = NewTempAbsPathInDir(dir.path());
+
+ const int rc = link(path1.c_str(), path2.c_str());
+ // NOTE(b/34861058): link(2) is only supported on tmpfs in the sandbox.
+ SKIP_IF(IsRunningOnGvisor() && rc != 0 &&
+ (errno == EPERM || errno == ENOENT));
+ ASSERT_THAT(rc, SyscallSucceeds());
+ const FileDescriptor fd1 =
+ ASSERT_NO_ERRNO_AND_VALUE(Open(path1.c_str(), O_RDWR));
+ const FileDescriptor fd2 =
+ ASSERT_NO_ERRNO_AND_VALUE(Open(path2.c_str(), O_RDWR));
+
+ const FileDescriptor inotify_fd =
+ ASSERT_NO_ERRNO_AND_VALUE(InotifyInit1(IN_NONBLOCK));
+ const int wd = ASSERT_NO_ERRNO_AND_VALUE(InotifyAddWatch(
+ inotify_fd.get(), dir.path(), IN_ALL_EVENTS | IN_EXCL_UNLINK));
+
+ // After unlinking path1, only events on the fd for path2 should be generated.
+ ASSERT_THAT(unlink(path1.c_str()), SyscallSucceeds());
+ ASSERT_THAT(write(fd1.get(), "x", 1), SyscallSucceeds());
+ ASSERT_THAT(write(fd2.get(), "x", 1), SyscallSucceeds());
+
+ const std::vector<Event> events =
+ ASSERT_NO_ERRNO_AND_VALUE(DrainEvents(inotify_fd.get()));
+ EXPECT_THAT(events, Are({
+ Event(IN_DELETE, wd, Basename(path1)),
+ Event(IN_MODIFY, wd, Basename(path2)),
+ }));
+}
+
+// On native Linux, actions of data type FSNOTIFY_EVENT_INODE are not affected
+// by IN_EXCL_UNLINK (see
+// fs/notify/inotify/inotify_fsnotify.c:inotify_handle_event). Inode-level
+// events include changes to metadata and extended attributes.
+//
+// We need to disable S/R because there are filesystems where we cannot re-open
+// fds to an unlinked file across S/R, e.g. gofer-backed filesytems.
+TEST(Inotify, ExcludeUnlinkInodeEvents_NoRandomSave) {
+ const DisableSave ds;
+
+ const TempPath dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
+ const TempPath file =
+ ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileIn(dir.path()));
+
+ const FileDescriptor fd =
+ ASSERT_NO_ERRNO_AND_VALUE(Open(file.path().c_str(), O_RDWR));
+ const FileDescriptor inotify_fd =
+ ASSERT_NO_ERRNO_AND_VALUE(InotifyInit1(IN_NONBLOCK));
+ const int wd = ASSERT_NO_ERRNO_AND_VALUE(InotifyAddWatch(
+ inotify_fd.get(), dir.path(), IN_ALL_EVENTS | IN_EXCL_UNLINK));
+
+ // NOTE(b/157163751): Create another link before unlinking. This is needed for
+ // the gofer filesystem in gVisor, where open fds will not work once the link
+ // count hits zero. In VFS2, we end up skipping the gofer test anyway, because
+ // hard links are not supported for gofer fs.
+ if (IsRunningOnGvisor()) {
+ std::string link_path = NewTempAbsPath();
+ const int rc = link(file.path().c_str(), link_path.c_str());
+ // NOTE(b/34861058): link(2) is only supported on tmpfs in the sandbox.
+ SKIP_IF(rc != 0 && (errno == EPERM || errno == ENOENT));
+ ASSERT_THAT(rc, SyscallSucceeds());
+ }
+
+ // Even after unlinking, inode-level operations will trigger events regardless
+ // of IN_EXCL_UNLINK.
+ ASSERT_THAT(unlink(file.path().c_str()), SyscallSucceeds());
+
+ // Perform various actions on fd.
+ ASSERT_THAT(ftruncate(fd.get(), 12345), SyscallSucceeds());
+ std::vector<Event> events =
+ ASSERT_NO_ERRNO_AND_VALUE(DrainEvents(inotify_fd.get()));
+ EXPECT_THAT(events, Are({
+ Event(IN_DELETE, wd, Basename(file.path())),
+ Event(IN_MODIFY, wd, Basename(file.path())),
+ }));
+
+ struct timeval times[2] = {{1, 0}, {2, 0}};
+ ASSERT_THAT(futimes(fd.get(), times), SyscallSucceeds());
+ events = ASSERT_NO_ERRNO_AND_VALUE(DrainEvents(inotify_fd.get()));
+ EXPECT_THAT(events, Are({Event(IN_ATTRIB, wd, Basename(file.path()))}));
+
+ // S/R is disabled on this entire test due to behavior with unlink; it must
+ // also be disabled after this point because of fchmod.
+ ASSERT_THAT(fchmod(fd.get(), 0777), SyscallSucceeds());
+ events = ASSERT_NO_ERRNO_AND_VALUE(DrainEvents(inotify_fd.get()));
+ EXPECT_THAT(events, Are({Event(IN_ATTRIB, wd, Basename(file.path()))}));
+}
+
} // namespace
} // namespace testing
} // namespace gvisor
diff --git a/test/syscalls/linux/open.cc b/test/syscalls/linux/open.cc
index 640fe6bfc..670c0284b 100644
--- a/test/syscalls/linux/open.cc
+++ b/test/syscalls/linux/open.cc
@@ -416,6 +416,29 @@ TEST_F(OpenTest, CanTruncateWriteOnlyNoReadPermission_NoRandomSave) {
EXPECT_EQ(stat.st_size, 0);
}
+TEST_F(OpenTest, CanTruncateWithStrangePermissions) {
+ ASSERT_NO_ERRNO(SetCapability(CAP_DAC_OVERRIDE, false));
+ ASSERT_NO_ERRNO(SetCapability(CAP_DAC_READ_SEARCH, false));
+ const DisableSave ds; // Permissions are dropped.
+ std::string path = NewTempAbsPath();
+ int fd;
+ // Create a file without user permissions.
+ EXPECT_THAT( // SAVE_BELOW
+ fd = open(path.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 055),
+ SyscallSucceeds());
+ EXPECT_THAT(close(fd), SyscallSucceeds());
+
+ // Cannot open file because we are owner and have no permissions set.
+ EXPECT_THAT(open(path.c_str(), O_RDONLY), SyscallFailsWithErrno(EACCES));
+
+ // We *can* chmod the file, because we are the owner.
+ EXPECT_THAT(chmod(path.c_str(), 0755), SyscallSucceeds());
+
+ // Now we can open the file again.
+ EXPECT_THAT(fd = open(path.c_str(), O_RDWR), SyscallSucceeds());
+ EXPECT_THAT(close(fd), SyscallSucceeds());
+}
+
} // namespace
} // namespace testing
diff --git a/test/syscalls/linux/pty.cc b/test/syscalls/linux/pty.cc
index b8a0159ba..aabfa6955 100644
--- a/test/syscalls/linux/pty.cc
+++ b/test/syscalls/linux/pty.cc
@@ -364,6 +364,12 @@ PosixErrorOr<size_t> PollAndReadFd(int fd, void* buf, size_t count,
ssize_t n =
ReadFd(fd, static_cast<char*>(buf) + completed, count - completed);
if (n < 0) {
+ if (errno == EAGAIN) {
+ // Linux sometimes returns EAGAIN from this read, despite the fact that
+ // poll returned success. Let's just do what do as we are told and try
+ // again.
+ continue;
+ }
return PosixError(errno, "read failed");
}
completed += n;
diff --git a/test/syscalls/linux/socket_unix.cc b/test/syscalls/linux/socket_unix.cc
index 8bf663e8b..591cab3fd 100644
--- a/test/syscalls/linux/socket_unix.cc
+++ b/test/syscalls/linux/socket_unix.cc
@@ -256,10 +256,9 @@ TEST_P(UnixSocketPairTest, ShutdownWrite) {
}
TEST_P(UnixSocketPairTest, SocketReopenFromProcfs) {
- // TODO(b/122310852): We should be returning ENXIO and NOT EIO.
- // TODO(github.dev/issue/1624): This should be resolved in VFS2. Verify
- // that this is the case and delete the SKIP_IF once we delete VFS1.
- SKIP_IF(IsRunningOnGvisor());
+ // TODO(gvisor.dev/issue/1624): In VFS1, we return EIO instead of ENXIO (see
+ // b/122310852). Remove this skip once VFS1 is deleted.
+ SKIP_IF(IsRunningWithVFS1());
auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
// Opening a socket pair via /proc/self/fd/X is a ENXIO.