/memcheck/tests/freebsd/getrlimitusage
/memcheck/tests/freebsd/inlinfo
/memcheck/tests/freebsd/inlinfo_nested.so
+/memcheck/tests/freebsd/kenv
/memcheck/tests/freebsd/kqueue
/memcheck/tests/freebsd/kqueuex
/memcheck/tests/freebsd/linkat
PRE(sys_kenv)
{
PRINT("sys_kenv ( %" FMT_REGWORD "u, %#" FMT_REGWORD "x, %#" FMT_REGWORD "x, %" FMT_REGWORD "u )", ARG1,ARG2,ARG3,ARG4);
- PRE_REG_READ4(int, "kenv",
- int, action, const char *, name, char *, value, int, len);
switch (ARG1) {
case VKI_KENV_GET:
+ // read from arg1, write to arg2
+ PRE_REG_READ4(int, "kenv",
+ int, action, const char *, name, char *, value, int, len);
+ PRE_MEM_RASCIIZ("kenv(name)", ARG2);
+ PRE_MEM_WRITE("kenv(value)", ARG3, ARG4);
+ break;
case VKI_KENV_SET:
+ PRE_REG_READ3(int, "kenv",
+ int, action, const char *, name, char *, value);
+ PRE_MEM_RASCIIZ("kenv(name)", ARG2);
+ PRE_MEM_RASCIIZ("kenv(value)", ARG3);
+ break;
case VKI_KENV_UNSET:
+ PRE_REG_READ2(int, "kenv", int, action, const char *, name);
PRE_MEM_RASCIIZ("kenv(name)", ARG2);
- /* FALLTHROUGH */
+ break;
case VKI_KENV_DUMP:
+ case VKI_KENV_DUMP_LOADER:
+ case VKI_KENV_DUMP_STATIC:
+ PRRSN;
+ PRA1("kenv",int,action);
+ // ARG2 name is ignored
+ PRA3("kenv",char*,value);
+ PRA4("kenv",int,len);
+ if (ARG3) {
+ PRE_MEM_WRITE("kenv(value)", ARG3, ARG4);
+ }
break;
default:
if (VG_(clo_verbosity) >= 1) {
- VG_(umsg)("Warning: unimplemented kenv action: %" FMT_REGWORD "d\n",
+ VG_(umsg)("Warning: bad or unimplemented kenv action: %" FMT_REGWORD "d\n",
ARG1);
}
break;
POST_MEM_WRITE(ARG3, ARG4);
break;
case VKI_KENV_DUMP:
- if (ARG3 != (Addr)NULL) {
+ if (ARG3) {
POST_MEM_WRITE(ARG3, ARG4);
}
break;
//----------------------------------------------------------------------
// From sys/kenv.h
//----------------------------------------------------------------------
-#define VKI_KENV_GET 0
-#define VKI_KENV_SET 1
-#define VKI_KENV_UNSET 2
-#define VKI_KENV_DUMP 3
+#define VKI_KENV_GET 0
+#define VKI_KENV_SET 1
+#define VKI_KENV_UNSET 2
+#define VKI_KENV_DUMP 3
+#define VKI_KENV_DUMP_LOADER 4
+#define VKI_KENV_DUMP_STATIC 5
//----------------------------------------------------------------------
// From sys/sysctl.h (and related)
getfsstat.supp \
getfsstat.stderr.exp-x86 \
getrlimitusage.vgtest getrlimitusage.stderr.exp \
+ kenv.vgtest \
+ kenv.stderr.exp \
kqueue.vgtest \
kqueue.stderr.exp \
kqueue.stdout.exp \
fexecve \
file_locking_wait6 \
get_set_context get_set_login getfh \
+ kenv \
kqueue linkat memalign misc \
openpty \
pdfork_pdkill getfsstat inlinfo inlinfo_nested.so \
get_set_login_CFLAGS = ${AM_CFLAGS} @FLAG_W_NO_USE_AFTER_FREE@
getfh_CFLAGS = ${AM_CFLAGS} @FLAG_W_NO_USE_AFTER_FREE@
getfsstat_CFLAGS = ${AM_CFLAGS} @FLAG_W_NO_UNINITIALIZED@ @FLAG_W_NO_USE_AFTER_FREE@
+kenv_SOURCES = kenv.cpp
linkat_CFLAGS = ${AM_CFLAGS} @FLAG_W_NO_MAYBE_UNINITIALIZED@ @FLAG_W_NO_UNINITIALIZED@ @FLAG_W_NO_USE_AFTER_FREE@
memalign_CFLAGS = ${AM_CFLAGS} @FLAG_W_NO_NON_POWER_OF_TWO_ALIGNMENT@
misc_CFLAGS = ${AM_CFLAGS} @FLAG_W_NO_USE_AFTER_FREE@
--- /dev/null
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <exception>
+#include <cerrno>
+#include <kenv.h>
+#include <unistd.h>
+
+static long x0;
+
+int main(int argc, char** argv)
+{
+ long *px{static_cast<long*>(malloc(2*sizeof(long)))};
+ x0 = px[0];
+ try
+ {
+ const size_t bufSize{1024};
+ auto buf{std::make_unique<char[]>(bufSize)};
+ std::string name{"bootfile"};
+ int res{kenv(KENV_GET, name.c_str(), buf.get(), bufSize)};
+
+ if (res == -1)
+ {
+ throw std::runtime_error("kenv get non-root");
+ }
+
+ if (argc > 1)
+ {
+ std::cout << buf << '\n';
+ }
+
+ res = kenv(42*42, name.c_str(), buf.get(), bufSize);
+ if (res == 0)
+ {
+ throw std::runtime_error("kenv get bogus action succeeded");
+ }
+ if (errno != EINVAL)
+ {
+ std::stringstream ss;
+ ss << "kenv get bogus action wrong errno, expected " << EINVAL << " got " << errno;
+ throw std::runtime_error(ss.str());
+ }
+
+ res = kenv(KENV_GET, "zyxxy", buf.get(), bufSize);
+ if (res == 0)
+ {
+ throw std::runtime_error("kenv get bogus name succeeded");
+ }
+ if (errno != ENOENT)
+ {
+ std::stringstream ss;
+ ss << "kenv get bogus name wrong errno, expected " << ENOENT << " got " << errno;
+ throw std::runtime_error(ss.str());
+ }
+
+ res = kenv(KENV_DUMP, "this does not matter", nullptr, -1);
+ if (res == -1)
+ {
+ throw std::runtime_error("kenv dump to get size non-root");
+ }
+ if (argc > 1)
+ {
+ std::cout << "dump size " << res << '\n';
+ }
+ auto dump_buf{std::make_unique<char[]>(res)};
+ char* uninitCharStar;
+ res = kenv(KENV_DUMP, uninitCharStar, dump_buf.get(), res);
+
+ if (argc > 1)
+ {
+ // the buffer contains nul separated eleements, this will just print the first
+ std::cout << dump_buf << '\n';
+ }
+
+ if (0 == geteuid())
+ {
+ res = kenv(KENV_SET, "this", const_cast<char*>("that"), 5);
+ if (res == -1)
+ {
+ throw std::runtime_error("kenv set root");
+ }
+ res = kenv(KENV_SET, "this", const_cast<char*>("thing"), 6);
+ if (res == -1)
+ {
+ throw std::runtime_error("kenv set root");
+ }
+ res = kenv(KENV_UNSET, "this", const_cast<char*>("yes we have no bananas"), 42);
+ if (res == -1)
+ {
+ throw std::runtime_error("kenv set root");
+ }
+ }
+ else
+ {
+ // now try some things that will fail
+ int uninitInt;
+ res = kenv(KENV_SET, "this", const_cast<char*>("that"), uninitInt);
+ if (res != -1)
+ {
+ throw std::runtime_error("kenv set non-root succeeded");
+ }
+ if (errno != EPERM)
+ {
+ std::stringstream ss;
+ ss << "kenv get bogus action wrong errno, expected " << EPERM << " got " << errno;
+ throw std::runtime_error(ss.str());
+ }
+
+ // checks all the args
+ kenv(KENV_GET+x0, name.c_str()+x0, buf.get()+x0, 1024+x0);
+
+ // now some memory errors
+ char* freeName{new char[32]};
+ sprintf(freeName, "%s", "blah");
+ delete [] freeName;
+ kenv(KENV_GET, freeName, buf.get(), 32);
+ char* freeBuf{new char[32]};
+ delete [] freeBuf;
+ kenv(KENV_GET, name.c_str(), freeBuf, 32);
+ int res{kenv(KENV_GET, name.c_str(), buf.get(), 2*bufSize)};
+ }
+
+ }
+ catch (std::exception& e)
+ {
+ std::cout << "FAILED: " << e.what() << '\n';
+ exit(-1);
+ }
+ free(px);
+}
--- /dev/null
+
+Warning: bad or unimplemented kenv action: 1764
+Syscall param kenv(action) contains uninitialised byte(s)
+ at 0x........: kenv (in /...libc...)
+ by 0x........: main (kenv.cpp:110)
+
+Syscall param kenv(name) contains uninitialised byte(s)
+ at 0x........: kenv (in /...libc...)
+ by 0x........: main (kenv.cpp:110)
+
+Syscall param kenv(value) contains uninitialised byte(s)
+ at 0x........: kenv (in /...libc...)
+ by 0x........: main (kenv.cpp:110)
+
+Syscall param kenv(len) contains uninitialised byte(s)
+ at 0x........: kenv (in /...libc...)
+ by 0x........: main (kenv.cpp:110)
+
+Syscall param kenv(name) points to unaddressable byte(s)
+ at 0x........: kenv (in /...libc...)
+ by 0x........: main (kenv.cpp:116)
+ Address 0x........ is 0 bytes inside a block of size 32 free'd
+ at 0x........: ...operator delete[]... (vg_replace_malloc.c:...)
+ by 0x........: main (kenv.cpp:115)
+ Block was alloc'd at
+ at 0x........: ...operator new[]... (vg_replace_malloc.c:...)
+ by 0x........: main (kenv.cpp:113)
+
+Syscall param kenv(value) points to unaddressable byte(s)
+ at 0x........: kenv (in /...libc...)
+ by 0x........: main (kenv.cpp:119)
+ Address 0x........ is 0 bytes inside a block of size 32 free'd
+ at 0x........: ...operator delete[]... (vg_replace_malloc.c:...)
+ by 0x........: main (kenv.cpp:118)
+ Block was alloc'd at
+ at 0x........: ...operator new[]... (vg_replace_malloc.c:...)
+ by 0x........: main (kenv.cpp:117)
+
+Syscall param kenv(value) points to unaddressable byte(s)
+ at 0x........: kenv (in /...libc...)
+ by 0x........: main (kenv.cpp:120)
+ Address 0x........ is 0 bytes after a block of size 1,024 alloc'd
+ at 0x........: ...operator new[]... (vg_replace_malloc.c:...)
+ by 0x........: main (kenv.cpp:18)
+
+
+HEAP SUMMARY:
+ in use at exit: 0 bytes in 0 blocks
+ total heap usage: 5 allocs, 5 frees, 4,765 bytes allocated
+
+For a detailed leak analysis, rerun with: --leak-check=full
+
+Use --track-origins=yes to see where uninitialised values come from
+For lists of detected and suppressed errors, rerun with: -s
+ERROR SUMMARY: 7 errors from 7 contexts (suppressed: 0 from 0)
--- /dev/null
+prog: kenv
...
Address 0x........ is not stack'd, malloc'd or (recently) free'd
+Syscall param kenv(value) points to unaddressable byte(s)
+ ...
+ Address 0x........ is not stack'd, malloc'd or (recently) free'd
+
---------------------------------------------------------
390: SYS_kenv (KENV_DUMP) 4s 0m
---------------------------------------------------------
Syscall param kenv(action) contains uninitialised byte(s)
...
-Syscall param kenv(name) contains uninitialised byte(s)
- ...
-
Syscall param kenv(value) contains uninitialised byte(s)
...
Syscall param kenv(len) contains uninitialised byte(s)
...
+Syscall param kenv(value) points to unaddressable byte(s)
+ ...
+ Address 0x........ is not stack'd, malloc'd or (recently) free'd
+
---------------------------------------------------------
391: SYS_lchflags 2s 1m
---------------------------------------------------------
...
Address 0x........ is not stack'd, malloc'd or (recently) free'd
+Syscall param kenv(value) points to unaddressable byte(s)
+ ...
+ Address 0x........ is not stack'd, malloc'd or (recently) free'd
+
---------------------------------------------------------
390: SYS_kenv (KENV_DUMP) 4s 0m
---------------------------------------------------------
Syscall param kenv(action) contains uninitialised byte(s)
...
-Syscall param kenv(name) contains uninitialised byte(s)
- ...
-
Syscall param kenv(value) contains uninitialised byte(s)
...
Syscall param kenv(len) contains uninitialised byte(s)
...
+Syscall param kenv(value) points to unaddressable byte(s)
+ ...
+ Address 0x........ is not stack'd, malloc'd or (recently) free'd
+
---------------------------------------------------------
391: SYS_lchflags 2s 1m
---------------------------------------------------------