Bug 433873 - openat2 syscall unimplemented on Linux

This syscall is not exposed via glibc, so there is only an
addition to the scalar test.
This commit is contained in:
Paul Floyd 2023-01-06 21:27:01 +01:00
parent 394ca9b400
commit 2c93baf53a
9 changed files with 193 additions and 24 deletions

1
NEWS
View File

@ -44,6 +44,7 @@ are not entered into bugzilla tend to get forgotten about or ignored.
351857 confusing error message about valid command line option
392331 Spurious lock not held error from inside pthread_cond_timedwait
400793 pthread_rwlock_timedwrlock false positive
433873 openat2 syscall unimplemented on Linux
444110 priv/guest_ppc_toIR.c:36198:31: warning: duplicated 'if' condition.
444488 Use glibc.pthread.stack_cache_size tunable
444568 drd/tests/pth_barrier_thr_cr fails on Fedora 38

View File

@ -322,6 +322,7 @@ DECL_TEMPLATE(linux, sys_io_uring_register);
// Linux-specific (new in Linux 5.9)
DECL_TEMPLATE(linux, sys_close_range);
DECL_TEMPLATE(linux, sys_openat2);
// Linux-specific (new in Linux 5.14)
DECL_TEMPLATE(linux, sys_memfd_secret);

View File

@ -878,6 +878,7 @@ static SyscallTableEntry syscall_table[] = {
GENX_(__NR_clone3, sys_ni_syscall), // 435
LINXY(__NR_close_range, sys_close_range), // 436
LINXY(__NR_openat2, sys_openat2), // 437
LINX_(__NR_faccessat2, sys_faccessat2), // 439

View File

@ -13434,6 +13434,121 @@ POST(sys_close_range)
ML_(record_fd_close)(fd);
}
#define VKI_O_DIRECTORY 00200000
#define VKI___O_TMPFILE 020000000
#define VKI_O_TMPFILE (VKI___O_TMPFILE | VKI_O_DIRECTORY)
// long syscall(SYS_openat2, int dirfd, const char *pathname,
// struct open_how *how, size_t size);
PRE(sys_openat2)
{
HChar name[30]; // large enough
SysRes sres;
struct vki_open_how * how;
PRINT("sys_openat2 ( %ld, %#" FMT_REGWORD "x(%s), %#" FMT_REGWORD "x, %ld )",
SARG1, ARG2, (HChar*)(Addr)ARG2, ARG3, SARG4);
PRE_REG_READ4(long, "openat2",
int, dfd, const char *, filename, struct vki_open_how *, how, vki_size_t, size);
PRE_MEM_RASCIIZ( "openat2(filename)", ARG2 );
PRE_MEM_READ( "openat2(how)", ARG3, sizeof(struct vki_open_how));
/* For absolute filenames, dfd is ignored. If dfd is AT_FDCWD,
filename is relative to cwd. When comparing dfd against AT_FDCWD,
be sure only to compare the bottom 32 bits. */
if (ML_(safe_to_deref)( (void*)(Addr)ARG2, 1 )
&& *(Char *)(Addr)ARG2 != '/'
&& ((Int)ARG1) != ((Int)VKI_AT_FDCWD)
&& !ML_(fd_allowed)(ARG1, "openat2", tid, False))
SET_STATUS_Failure( VKI_EBADF );
how = (struct vki_open_how *)ARG3;
if (how && ML_(safe_to_deref) (how, sizeof(struct vki_open_how))) {
if (how->vki_mode) {
if (!(how->vki_flags & ((vki_uint64_t)VKI_O_CREAT | VKI_O_TMPFILE))) {
SET_STATUS_Failure( VKI_EINVAL );
}
}
if (how->vki_resolve & ~((vki_uint64_t)VKI_RESOLVE_NO_XDEV |
VKI_RESOLVE_NO_MAGICLINKS |
VKI_RESOLVE_NO_SYMLINKS |
VKI_RESOLVE_BENEATH |
VKI_RESOLVE_IN_ROOT |
VKI_RESOLVE_CACHED)) {
SET_STATUS_Failure( VKI_EINVAL );
}
}
/* Handle the case where the open is of /proc/self/cmdline or
/proc/<pid>/cmdline, and just give it a copy of the fd for the
fake file we cooked up at startup (in m_main). Also, seek the
cloned fd back to the start. */
VG_(sprintf)(name, "/proc/%d/cmdline", VG_(getpid)());
if (ML_(safe_to_deref)( (void*)(Addr)ARG2, 1 )
&& (VG_(strcmp)((HChar *)(Addr)ARG2, name) == 0
|| VG_(strcmp)((HChar *)(Addr)ARG2, "/proc/self/cmdline") == 0)) {
sres = VG_(dup)( VG_(cl_cmdline_fd) );
SET_STATUS_from_SysRes( sres );
if (!sr_isError(sres)) {
OffT off = VG_(lseek)( sr_Res(sres), 0, VKI_SEEK_SET );
if (off < 0)
SET_STATUS_Failure( VKI_EMFILE );
}
return;
}
/* Do the same for /proc/self/auxv or /proc/<pid>/auxv case. */
VG_(sprintf)(name, "/proc/%d/auxv", VG_(getpid)());
if (ML_(safe_to_deref)( (void*)(Addr)ARG2, 1 )
&& (VG_(strcmp)((HChar *)(Addr)ARG2, name) == 0
|| VG_(strcmp)((HChar *)(Addr)ARG2, "/proc/self/auxv") == 0)) {
sres = VG_(dup)( VG_(cl_auxv_fd) );
SET_STATUS_from_SysRes( sres );
if (!sr_isError(sres)) {
OffT off = VG_(lseek)( sr_Res(sres), 0, VKI_SEEK_SET );
if (off < 0)
SET_STATUS_Failure( VKI_EMFILE );
}
return;
}
/* And for /proc/self/exe or /proc/<pid>/exe case. */
VG_(sprintf)(name, "/proc/%d/exe", VG_(getpid)());
if (ML_(safe_to_deref)( (void*)(Addr)ARG2, 1 )
&& (VG_(strcmp)((HChar *)(Addr)ARG2, name) == 0
|| VG_(strcmp)((HChar *)(Addr)ARG2, "/proc/self/exe") == 0)) {
sres = VG_(dup)( VG_(cl_exec_fd) );
SET_STATUS_from_SysRes( sres );
if (!sr_isError(sres)) {
OffT off = VG_(lseek)( sr_Res(sres), 0, VKI_SEEK_SET );
if (off < 0)
SET_STATUS_Failure( VKI_EMFILE );
}
return;
}
/* Otherwise handle normally */
*flags |= SfMayBlock;
}
POST(sys_openat2)
{
vg_assert(SUCCESS);
if (!ML_(fd_allowed)(RES, "openat2", tid, True)) {
VG_(close)(RES);
SET_STATUS_Failure( VKI_EMFILE );
} else {
if (VG_(clo_track_fds))
ML_(record_fd_open_with_given_name)(tid, RES, (HChar*)(Addr)ARG2);
}
}
#undef PRE
#undef POST

View File

@ -1649,6 +1649,8 @@ static SyscallTableEntry syscall_table[] = {
GENX_(__NR_clone3, sys_ni_syscall), // 435
LINXY(__NR_close_range, sys_close_range), // 436
LINXY(__NR_openat2, sys_openat2), // 437
LINX_(__NR_faccessat2, sys_faccessat2), // 439

View File

@ -5375,6 +5375,21 @@ struct vki_itimerspec64 {
struct vki_timespec it_value;
};
/* From include/linux/openat2.h */
struct vki_open_how {
vki_uint64_t vki_flags;
vki_uint64_t vki_mode;
vki_uint64_t vki_resolve;
};
#define VKI_RESOLVE_NO_XDEV 0x01
#define VKI_RESOLVE_NO_MAGICLINKS 0x02
#define VKI_RESOLVE_NO_SYMLINKS 0x04
#define VKI_RESOLVE_BENEATH 0x08
#define VKI_RESOLVE_IN_ROOT 0x10
#define VKI_RESOLVE_CACHED 0x20
#ifndef VKI_RLIM_INFINITY
#define VKI_RLIM_INFINITY (~0UL)
#endif

View File

@ -41,6 +41,7 @@
#define __NR_clone3 435
#define __NR_close_range 436
#define __NR_openat2 437
#define __NR_faccessat2 439

View File

@ -1276,6 +1276,10 @@ int main(void)
GO(__NR_epoll_create1, "1s 0m");
SY(__NR_epoll_create1, x0); SUCC_OR_FAIL;
// __NR_openat2 337
GO(__NR_openat2, "4s 2m");
SY(__NR_openat2, x0, x0+1, x0+1, x0); FAIL;
// __NR_process_vm_readv 347
GO(__NR_process_vm_readv, "6s 2m");
SY(__NR_process_vm_readv, x0, x0, x0+1, x0, x0+1, x0); FAIL;

View File

@ -4146,77 +4146,106 @@ Syscall param epoll_create1(flags) contains uninitialised byte(s)
by 0x........: main (scalar.c:1277)
-----------------------------------------------------
347:__NR_process_vm_readv 6s 2m
437: __NR_openat2 4s 2m
-----------------------------------------------------
Syscall param process_vm_readv(pid) contains uninitialised byte(s)
Syscall param openat2(dfd) contains uninitialised byte(s)
...
by 0x........: main (scalar.c:1281)
Syscall param process_vm_readv(lvec) contains uninitialised byte(s)
Syscall param openat2(filename) contains uninitialised byte(s)
...
by 0x........: main (scalar.c:1281)
Syscall param process_vm_readv(liovcnt) contains uninitialised byte(s)
Syscall param openat2(how) contains uninitialised byte(s)
...
by 0x........: main (scalar.c:1281)
Syscall param process_vm_readv(rvec) contains uninitialised byte(s)
Syscall param openat2(size) contains uninitialised byte(s)
...
by 0x........: main (scalar.c:1281)
Syscall param process_vm_readv(riovcnt) contains uninitialised byte(s)
...
by 0x........: main (scalar.c:1281)
Syscall param process_vm_readv(flags) contains uninitialised byte(s)
...
by 0x........: main (scalar.c:1281)
Syscall param process_vm_readv(lvec) points to unaddressable byte(s)
Syscall param openat2(filename) points to unaddressable byte(s)
...
by 0x........: main (scalar.c:1281)
Address 0x........ is not stack'd, malloc'd or (recently) free'd
Syscall param process_vm_readv(rvec) points to unaddressable byte(s)
Syscall param openat2(how) points to unaddressable byte(s)
...
by 0x........: main (scalar.c:1281)
Address 0x........ is not stack'd, malloc'd or (recently) free'd
-----------------------------------------------------
347:__NR_process_vm_readv 6s 2m
-----------------------------------------------------
Syscall param process_vm_readv(pid) contains uninitialised byte(s)
...
by 0x........: main (scalar.c:1285)
Syscall param process_vm_readv(lvec) contains uninitialised byte(s)
...
by 0x........: main (scalar.c:1285)
Syscall param process_vm_readv(liovcnt) contains uninitialised byte(s)
...
by 0x........: main (scalar.c:1285)
Syscall param process_vm_readv(rvec) contains uninitialised byte(s)
...
by 0x........: main (scalar.c:1285)
Syscall param process_vm_readv(riovcnt) contains uninitialised byte(s)
...
by 0x........: main (scalar.c:1285)
Syscall param process_vm_readv(flags) contains uninitialised byte(s)
...
by 0x........: main (scalar.c:1285)
Syscall param process_vm_readv(lvec) points to unaddressable byte(s)
...
by 0x........: main (scalar.c:1285)
Address 0x........ is not stack'd, malloc'd or (recently) free'd
Syscall param process_vm_readv(rvec) points to unaddressable byte(s)
...
by 0x........: main (scalar.c:1285)
Address 0x........ is not stack'd, malloc'd or (recently) free'd
-----------------------------------------------------
348:__NR_process_vm_writev 6s 2m
-----------------------------------------------------
Syscall param process_vm_writev(pid) contains uninitialised byte(s)
...
by 0x........: main (scalar.c:1285)
by 0x........: main (scalar.c:1289)
Syscall param process_vm_writev(lvec) contains uninitialised byte(s)
...
by 0x........: main (scalar.c:1285)
by 0x........: main (scalar.c:1289)
Syscall param process_vm_writev(liovcnt) contains uninitialised byte(s)
...
by 0x........: main (scalar.c:1285)
by 0x........: main (scalar.c:1289)
Syscall param process_vm_writev(rvec) contains uninitialised byte(s)
...
by 0x........: main (scalar.c:1285)
by 0x........: main (scalar.c:1289)
Syscall param process_vm_writev(riovcnt) contains uninitialised byte(s)
...
by 0x........: main (scalar.c:1285)
by 0x........: main (scalar.c:1289)
Syscall param process_vm_writev(flags) contains uninitialised byte(s)
...
by 0x........: main (scalar.c:1285)
by 0x........: main (scalar.c:1289)
Syscall param process_vm_writev(lvec) points to unaddressable byte(s)
...
by 0x........: main (scalar.c:1285)
by 0x........: main (scalar.c:1289)
Address 0x........ is not stack'd, malloc'd or (recently) free'd
Syscall param process_vm_writev(rvec) points to unaddressable byte(s)
...
by 0x........: main (scalar.c:1285)
by 0x........: main (scalar.c:1289)
Address 0x........ is not stack'd, malloc'd or (recently) free'd
-----------------------------------------------------
@ -4232,5 +4261,5 @@ it at http://valgrind.org/support/bug_reports.html.
-----------------------------------------------------
Syscall param exit(status) contains uninitialised byte(s)
...
by 0x........: main (scalar.c:1293)
by 0x........: main (scalar.c:1297)