mirror of https://github.com/microsoft/WSL
1323 lines
34 KiB
C
1323 lines
34 KiB
C
/*++
|
|
|
|
Copyright (c) Microsoft. All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
binfmt.c
|
|
|
|
Abstract:
|
|
|
|
This file contains tests for the binfmt file system.
|
|
|
|
--*/
|
|
|
|
#include "lxtcommon.h"
|
|
#include "unittests.h"
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/syscall.h>
|
|
#include <sys/utsname.h>
|
|
#include <unistd.h>
|
|
#include <dirent.h>
|
|
#include <fcntl.h>
|
|
#include <pthread.h>
|
|
|
|
#define LXT_NAME "BinFmt"
|
|
|
|
#define BINFMT_MNT "/proc/sys/fs/binfmt_misc"
|
|
#define BINFMT_TEST_FILE "/data/test/lxt_binfmt_test"
|
|
#define BINFMT_TIMEOUT 60
|
|
|
|
#define BINFMT_DISABLE_STRING "0"
|
|
#define BINFMT_ENABLE_STRING "1"
|
|
#define BINFMT_REMOVE_STRING "-1"
|
|
|
|
#define BINFMT_REGISTER_NAME "Test"
|
|
#define BINFMT_INTERPRETER_SCRIPT "/data/test/lxt_binfmt_interpreter.sh"
|
|
#define BINFMT_REGISTER_SCRIPT_STRING ":" BINFMT_REGISTER_NAME ":M::\\xff\\xff\\xff\\xff::" BINFMT_INTERPRETER_SCRIPT ":"
|
|
|
|
#define BINFMT_INTERPRETER_SCRIPT_CONTENTS \
|
|
"#!/bin/bash\n" \
|
|
"# " BINFMT_INTERPRETER_SCRIPT " - the wrapper for WSL binfmt_misc testing\n" WSL_UNIT_TEST_BINARY " binfmt -a -i \"$@\""
|
|
|
|
#define BINFMT_INTERPRETER_BINARY "/data/test/lxt_binfmt_interpreter_binary"
|
|
#define BINFMT_INTERPRETER_BINARY_SOURCEFILE "/data/test/lxt_binfmt_interpreter_binary.c"
|
|
|
|
//
|
|
// N.B. These UID and GID values must be kept in-sync with the values in the
|
|
// source below.
|
|
//
|
|
|
|
#define BINFMT_CALLER_UID 0
|
|
#define BINFMT_CALLER_GID 0
|
|
#define BINFMT_BINARY_UID 1044
|
|
#define BINFMT_BINARY_GID 1044
|
|
#define BINFMT_P_FLAG_ARG "foo"
|
|
|
|
#define BINFMT_INTERPRETER_BINARY_SOURCE_BEGIN \
|
|
"#define _GNU_SOURCE\n" \
|
|
"#include <stdio.h>\n" \
|
|
"#include <string.h>\n" \
|
|
"#include <stdlib.h>\n" \
|
|
"#include <fcntl.h>\n" \
|
|
"#include <unistd.h>\n" \
|
|
"#include <errno.h>\n" \
|
|
"#include <sys/auxv.h>\n" \
|
|
"#define BINFMT_CALLER_UID 0\n" \
|
|
"#define BINFMT_CALLER_GID 0\n" \
|
|
"#define BINFMT_BINARY_UID 1044\n" \
|
|
"#define BINFMT_BINARY_GID 1044\n" \
|
|
"#define BINFMT_P_FLAG_ARG \"foo\"\n" \
|
|
"#define BINFMT_INTERPRETER_BINARY \"/data/test/lxt_binfmt_interpreter_binary\"\n" \
|
|
"#define BINFMT_TEST_FILE \"/data/test/lxt_binfmt_test\"\n" \
|
|
"\n" \
|
|
"int main(int Argc, char** Argv)\n" \
|
|
"{\n" \
|
|
" struct stat Buffer;\n" \
|
|
" int Fd;\n" \
|
|
" int Index;\n" \
|
|
" uid_t Real, Effective, Saved;\n" \
|
|
" printf(\"Pid = %d\\n\", getpid());\n" \
|
|
" Fd = getauxval(AT_EXECFD);\n" \
|
|
" printf(\"AT_EXECFD = %d errno = %d\\n\", Fd, errno);\n" \
|
|
" getresuid(&Real, &Effective, &Saved);\n" \
|
|
" printf(\"Real %d Effective %d Saved %d\\n\", Real, Effective, Saved);\n" \
|
|
" printf(\"Argc = %d\\n\", Argc);\n" \
|
|
" for (Index = 0; Index < Argc; Index += 1) {\n" \
|
|
" printf(\"Argv[%d] = %s\\n\", Index, Argv[Index]);\n" \
|
|
" }\n"
|
|
|
|
#define BINFMT_INTERPRETER_BINARY_SOURCE_VERIFY_TWO_ARGS \
|
|
" if (Argc != 2) {\n" \
|
|
" return -1;\n" \
|
|
" }\n" \
|
|
" if (strcmp(Argv[0], BINFMT_INTERPRETER_BINARY) != 0) {\n" \
|
|
" return -1;\n" \
|
|
" }\n" \
|
|
" if (strcmp(Argv[1], BINFMT_TEST_FILE) != 0) {\n" \
|
|
" return -1;\n" \
|
|
" }\n"
|
|
|
|
#define BINFMT_INTERPRETER_BINARY_SOURCE_MIDDLE_C_FLAG \
|
|
" if ((Fd == 0) && (errno == ENOENT)) {\n" \
|
|
" return -1;\n" \
|
|
" }\n" \
|
|
" if (fcntl(Fd, F_GETFD) != 0) {\n" \
|
|
" return -1;\n" \
|
|
" }\n" \
|
|
" if ((Real != BINFMT_CALLER_UID) ||\n" \
|
|
" (Effective != BINFMT_BINARY_UID) ||\n" \
|
|
" (Saved != BINFMT_BINARY_UID)) {\n" \
|
|
" return -1;\n" \
|
|
" }\n" BINFMT_INTERPRETER_BINARY_SOURCE_VERIFY_TWO_ARGS
|
|
|
|
#define BINFMT_INTERPRETER_BINARY_SOURCE_MIDDLE_O_FLAG \
|
|
" if ((Fd == 0) && (errno == ENOENT)) {\n" \
|
|
" return -1;\n" \
|
|
" }\n" \
|
|
" if (fcntl(Fd, F_GETFD) != 0) {\n" \
|
|
" return -1;\n" \
|
|
" }\n" \
|
|
" if ((Real != BINFMT_CALLER_UID) ||\n" \
|
|
" (Effective != BINFMT_CALLER_UID) ||\n" \
|
|
" (Saved != BINFMT_CALLER_UID)) {\n" \
|
|
" return -1;\n" \
|
|
" }\n" BINFMT_INTERPRETER_BINARY_SOURCE_VERIFY_TWO_ARGS
|
|
|
|
#define BINFMT_INTERPRETER_BINARY_SOURCE_MIDDLE_P_FLAG \
|
|
" if ((Fd != 0) || (errno != ENOENT)) {\n" \
|
|
" return -1;\n" \
|
|
" }\n" \
|
|
" if (Argc != 4) {\n" \
|
|
" return -1;\n" \
|
|
" }\n" \
|
|
" if (strcmp(Argv[0], BINFMT_INTERPRETER_BINARY) != 0) {\n" \
|
|
" return -1;\n" \
|
|
" }\n" \
|
|
" if (strcmp(Argv[1], BINFMT_TEST_FILE) != 0) {\n" \
|
|
" return -1;\n" \
|
|
" }\n" \
|
|
" if (strcmp(Argv[2], BINFMT_TEST_FILE) != 0) {\n" \
|
|
" return -1;\n" \
|
|
" }\n" \
|
|
" if (strcmp(Argv[3], BINFMT_P_FLAG_ARG) != 0) {\n" \
|
|
" return -1;\n" \
|
|
" }\n"
|
|
|
|
#define BINFMT_INTERPRETER_BINARY_SOURCE_MIDDLE_NO_FLAGS \
|
|
" if ((Fd != 0) || (errno != ENOENT)) {\n" \
|
|
" return -1;\n" \
|
|
" }\n"
|
|
|
|
#define BINFMT_INTERPRETER_BINARY_SOURCE_END \
|
|
" return 0;\n" \
|
|
"}"
|
|
|
|
#define BINFMT_INTERPRETER_BINARY_SOURCE_C_FLAG \
|
|
BINFMT_INTERPRETER_BINARY_SOURCE_BEGIN \
|
|
BINFMT_INTERPRETER_BINARY_SOURCE_MIDDLE_C_FLAG \
|
|
BINFMT_INTERPRETER_BINARY_SOURCE_END
|
|
|
|
#define BINFMT_INTERPRETER_BINARY_SOURCE_O_FLAG \
|
|
BINFMT_INTERPRETER_BINARY_SOURCE_BEGIN \
|
|
BINFMT_INTERPRETER_BINARY_SOURCE_MIDDLE_O_FLAG \
|
|
BINFMT_INTERPRETER_BINARY_SOURCE_END
|
|
|
|
#define BINFMT_INTERPRETER_BINARY_SOURCE_P_FLAG \
|
|
BINFMT_INTERPRETER_BINARY_SOURCE_BEGIN \
|
|
BINFMT_INTERPRETER_BINARY_SOURCE_MIDDLE_P_FLAG \
|
|
BINFMT_INTERPRETER_BINARY_SOURCE_END
|
|
|
|
#define BINFMT_INTERPRETER_BINARY_SOURCE_NO_FLAGS \
|
|
BINFMT_INTERPRETER_BINARY_SOURCE_BEGIN \
|
|
BINFMT_INTERPRETER_BINARY_SOURCE_MIDDLE_NO_FLAGS \
|
|
BINFMT_INTERPRETER_BINARY_SOURCE_END
|
|
|
|
#define BINFMT_OFFSET_TEST "/data/test/binfmt_offset"
|
|
#define BINFMT_OFFSET_TEST_PATTERN "GSH"
|
|
|
|
#define BINFMT_REGISTER_BINARY_STRING ":" BINFMT_REGISTER_NAME ":M::\\xff\\xff\\xff\\xff::" BINFMT_INTERPRETER_BINARY ":"
|
|
#define BINFMT_REGISTER_BINARY_STRING_C BINFMT_REGISTER_BINARY_STRING "C"
|
|
#define BINFMT_REGISTER_BINARY_STRING_O BINFMT_REGISTER_BINARY_STRING "O"
|
|
#define BINFMT_REGISTER_BINARY_STRING_P BINFMT_REGISTER_BINARY_STRING "P"
|
|
|
|
#define BINFMT_STATUS_ENABLED "enabled\n"
|
|
#define BINFMT_STATUS_DISABLED "disabled\n"
|
|
|
|
#define BINFMT_REGISTRATION_ENABLED_STRING \
|
|
BINFMT_STATUS_ENABLED \
|
|
"interpreter " BINFMT_INTERPRETER_SCRIPT \
|
|
"\n" \
|
|
"flags: \n" \
|
|
"offset 0\n" \
|
|
"magic ffffffff\n"
|
|
|
|
#define BINFMT_REGISTRATION_DISABLED_STRING \
|
|
BINFMT_STATUS_DISABLED \
|
|
"interpreter " BINFMT_INTERPRETER_SCRIPT \
|
|
"\n" \
|
|
"flags: \n" \
|
|
"offset 0\n" \
|
|
"magic ffffffff\n"
|
|
|
|
typedef struct _LXT_BINFMT_REGISTRATION
|
|
{
|
|
char* RegistrationString;
|
|
char Magic[4];
|
|
char* TestFile;
|
|
} LXT_BINFMT_REGISTRATION, PLXT_BINFMT_REGISTRATION;
|
|
|
|
LXT_BINFMT_REGISTRATION g_BinfmtRegistrations[] = {
|
|
{":binfmt_1:M::\\x01\x01\x01\x01::/data/test/lxt_binfmt_2:", {0x1, 0x1, 0x1, 0x1}, "/data/test/lxt_binfmt_1"},
|
|
{":binfmt_2:M::\\x02\x02\x02\x02::/data/test/lxt_binfmt_3:", {0x2, 0x2, 0x2, 0x2}, "/data/test/lxt_binfmt_2"},
|
|
{":binfmt_3:M::\\x03\x03\x03\x03::/data/test/lxt_binfmt_4:", {0x3, 0x3, 0x3, 0x3}, "/data/test/lxt_binfmt_3"},
|
|
{":binfmt_4:M::\\x04\x04\x04\x04::/data/test/lxt_binfmt_5:", {0x4, 0x4, 0x4, 0x4}, "/data/test/lxt_binfmt_4"},
|
|
{":binfmt_5:M::\\x05\x05\x05\x05::/data/test/lxt_binfmt_6:", {0x5, 0x5, 0x5, 0x5}, "/data/test/lxt_binfmt_5"},
|
|
{":binfmt_6:M::\\x06\x06\x06\x06::/data/test/lxt_binfmt_7:", {0x6, 0x6, 0x6, 0x6}, "/data/test/lxt_binfmt_6"},
|
|
{":binfmt_7:M::\\x07\x07\x07\x07::/bin/echo:", {0x7, 0x7, 0x7, 0x7}, "/data/test/lxt_binfmt_7"}};
|
|
|
|
void BimFmtCleanup(void);
|
|
|
|
int BinFmtExtension(PLXT_ARGS Args);
|
|
|
|
int BinFmtInvalidParam(PLXT_ARGS Args);
|
|
|
|
int BinFmtOffset(PLXT_ARGS Args);
|
|
|
|
int BinFmtOptions(PLXT_ARGS Args);
|
|
|
|
int BinFmtRegister(PLXT_ARGS Args);
|
|
|
|
int BinFmtRoot(PLXT_ARGS Args);
|
|
|
|
int BinFmtStatus(PLXT_ARGS Args);
|
|
|
|
int BinFmtInterpreterEntry(PLXT_ARGS Args);
|
|
|
|
//
|
|
// Global constants
|
|
//
|
|
|
|
static const LXT_VARIATION g_LxtVariations[] = {
|
|
{"BinFmt - " BINFMT_MNT " root", BinFmtRoot},
|
|
{"BinFmt - " BINFMT_MNT "/register", BinFmtRegister},
|
|
{"BinFmt - " BINFMT_MNT "/status", BinFmtStatus},
|
|
{"BinFmt - Extensions", BinFmtExtension},
|
|
{"BinFmt - Options", BinFmtOptions},
|
|
{"BinFmt - Offset", BinFmtOffset},
|
|
{"BinFmt - Invalid Parameter", BinFmtInvalidParam}};
|
|
|
|
static const LXT_CHILD_INFO g_BinFmtRootChildren[] = {{"register", DT_REG}, {"status", DT_REG}};
|
|
|
|
static const char* g_BinFmtRegisterInvalid[] = {
|
|
"::M::BACON::/usr/bin/test:",
|
|
":Test:B::BACON::/usr/bin/test:",
|
|
":Test:M::BACON:BACONISAWESOME:/usr/bin/test:",
|
|
":Test:M::BACON:\\xff:/usr/bin/test:",
|
|
":Test:M::BACON:\\xff\\xff\\xff\\xff\\xf:/usr/bin/test:",
|
|
":Test:M::BACON:::",
|
|
":Test:M::BACON::/usr/bin/test:B",
|
|
":Test:M::BACON::/usr/bin/test: ",
|
|
":Test:M::BACON::/usr/bin/test:\nO",
|
|
":Test:E::B/ACON::/usr/bin/test:",
|
|
|
|
/*
|
|
":aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:M::BACON::/usr/bin/aaaaaaaaa:",
|
|
":aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:M::BACON::/usr/bin/aaaaaaaaaaaaaaa:",
|
|
":aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:M::BACON::/usr/bin/aaaaaaaaaaaaaaaaaaaaaaaa:",
|
|
":aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:M::BACON::/usr/bin/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:",
|
|
":aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:M::BACON::/usr/bin/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:",
|
|
*/
|
|
|
|
":::::::::::::::::",
|
|
"",
|
|
"\0"};
|
|
|
|
int BinFmtTestEntry(int Argc, char* Argv[])
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is the main entry point for the binfmt tests.
|
|
|
|
Arguments:
|
|
|
|
Argc - Supplies the number of command line arguments.
|
|
|
|
Argv - Supplies the command line arguments.
|
|
|
|
Return Value: LxtCheckResult(LxtInitialize(Argc, Argv, &Args, LXT_NAME));
|
|
|
|
Returns 0 on success, -1 on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
LXT_ARGS Args;
|
|
int Opt;
|
|
int Result;
|
|
|
|
LxtCheckResult(LxtInitialize(Argc, Argv, &Args, LXT_NAME));
|
|
optind = 0;
|
|
opterr = 0;
|
|
while ((Opt = getopt(Argc, Argv, "i")) != -1)
|
|
{
|
|
switch (Opt)
|
|
{
|
|
case 'i':
|
|
Result = BinFmtInterpreterEntry(&Args);
|
|
goto ErrorExit;
|
|
}
|
|
}
|
|
|
|
LxtCheckResult(LxtRunVariations(&Args, g_LxtVariations, LXT_COUNT_OF(g_LxtVariations)));
|
|
|
|
ErrorExit:
|
|
LxtUninitialize();
|
|
return !LXT_SUCCESS(Result);
|
|
}
|
|
|
|
void BimFmtCleanup(void)
|
|
|
|
{
|
|
|
|
int Fd;
|
|
int Result;
|
|
int Size;
|
|
|
|
//
|
|
// Remove the test entry via the registration file.
|
|
//
|
|
|
|
Fd = open(BINFMT_MNT "/" BINFMT_REGISTER_NAME, O_RDWR);
|
|
if (Fd >= 0)
|
|
{
|
|
Size = strlen(BINFMT_REMOVE_STRING);
|
|
LxtCheckErrno(Size = write(Fd, BINFMT_REMOVE_STRING, Size));
|
|
}
|
|
|
|
ErrorExit:
|
|
if (Fd != -1)
|
|
{
|
|
LxtClose(Fd);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
int BinFmtExtension(PLXT_ARGS Args)
|
|
|
|
/*++
|
|
|
|
Description:
|
|
|
|
This routine tests binformat extensions.
|
|
|
|
Arguments:
|
|
|
|
Args - Supplies the command line arguments.
|
|
|
|
Return Value:
|
|
|
|
Returns 0 on success, -1 on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
char Buffer[16];
|
|
size_t BytesWritten;
|
|
int ChildPid;
|
|
char* ExecArgs[2];
|
|
int Fd = -1;
|
|
int Index;
|
|
int RegisterFd;
|
|
LXT_CHILD_INFO Registration;
|
|
int Result;
|
|
ssize_t Size;
|
|
int Status;
|
|
|
|
//
|
|
// Clean any binfmt interpreters from a previous iteration of the test.
|
|
//
|
|
|
|
BimFmtCleanup();
|
|
|
|
//
|
|
// Create the binfmt interpreter.
|
|
//
|
|
|
|
LxtCheckErrno(Fd = creat(BINFMT_INTERPRETER_SCRIPT, 0777));
|
|
LxtCheckErrno(BytesWritten = write(Fd, BINFMT_INTERPRETER_SCRIPT_CONTENTS, (sizeof(BINFMT_INTERPRETER_SCRIPT_CONTENTS) - 1)));
|
|
|
|
LxtClose(Fd);
|
|
Fd = -1;
|
|
|
|
//
|
|
// Register a binfmt extension.
|
|
//
|
|
|
|
LxtCheckErrno(RegisterFd = open(BINFMT_MNT "/register", O_WRONLY));
|
|
Size = strlen(BINFMT_REGISTER_SCRIPT_STRING);
|
|
LxtCheckErrno(Size = write(RegisterFd, BINFMT_REGISTER_SCRIPT_STRING, Size));
|
|
|
|
//
|
|
// Create a file that will be handled by the binfmt extension.
|
|
//
|
|
|
|
LxtCheckErrno(Fd = creat(BINFMT_TEST_FILE, 0777));
|
|
memset(Buffer, 0xff, sizeof(Buffer));
|
|
LxtCheckErrno(BytesWritten = write(Fd, Buffer, sizeof(Buffer)));
|
|
LxtClose(Fd);
|
|
Fd = -1;
|
|
|
|
//
|
|
// Fork and exec the file.
|
|
//
|
|
|
|
LxtCheckResult(ChildPid = fork());
|
|
if (ChildPid == 0)
|
|
{
|
|
ExecArgs[0] = BINFMT_TEST_FILE;
|
|
ExecArgs[1] = NULL;
|
|
LxtCheckErrno(LxtExecve(ExecArgs[0], ExecArgs, NULL));
|
|
|
|
//
|
|
// The parent waits for the child to exit successfully.
|
|
//
|
|
}
|
|
else
|
|
{
|
|
LxtCheckResult(LxtWaitPidPoll(ChildPid, 0));
|
|
}
|
|
|
|
//
|
|
// Remove the new entry via the registration file.
|
|
//
|
|
|
|
LxtCheckErrno(Fd = open(BINFMT_MNT "/" BINFMT_REGISTER_NAME, O_RDWR));
|
|
Size = strlen(BINFMT_REMOVE_STRING);
|
|
LxtCheckErrno(Size = write(Fd, BINFMT_REMOVE_STRING, Size));
|
|
LxtClose(Fd);
|
|
Fd = -1;
|
|
|
|
//
|
|
// Create many registrations and test files.
|
|
//
|
|
|
|
for (Index = 0; Index < LXT_COUNT_OF(g_BinfmtRegistrations); Index += 1)
|
|
{
|
|
Size = strlen(g_BinfmtRegistrations[Index].RegistrationString);
|
|
LxtCheckErrno(Size = write(RegisterFd, g_BinfmtRegistrations[Index].RegistrationString, Size));
|
|
LxtCheckErrno(Fd = creat(g_BinfmtRegistrations[Index].TestFile, 0777));
|
|
LxtCheckErrno(BytesWritten = write(Fd, g_BinfmtRegistrations[Index].Magic, sizeof(g_BinfmtRegistrations[Index].Magic)));
|
|
LxtClose(Fd);
|
|
Fd = -1;
|
|
}
|
|
|
|
//
|
|
// Fork and exec the file to test the interpreter depth.
|
|
//
|
|
|
|
Index = 2;
|
|
LxtCheckResult(ChildPid = fork());
|
|
if (ChildPid == 0)
|
|
{
|
|
ExecArgs[0] = g_BinfmtRegistrations[Index].TestFile;
|
|
ExecArgs[1] = NULL;
|
|
LxtCheckErrno(LxtExecve(ExecArgs[0], ExecArgs, NULL));
|
|
|
|
//
|
|
// The parent waits for the child to exit successfully.
|
|
//
|
|
}
|
|
else
|
|
{
|
|
LxtCheckResult(LxtWaitPidPoll(ChildPid, 0));
|
|
}
|
|
|
|
//
|
|
// Test max interpreter link depth (should fail).
|
|
//
|
|
|
|
Index = 1;
|
|
LxtCheckResult(ChildPid = fork());
|
|
if (ChildPid == 0)
|
|
{
|
|
ExecArgs[0] = g_BinfmtRegistrations[Index].TestFile;
|
|
ExecArgs[1] = NULL;
|
|
LxtCheckErrnoFailure(LxtExecve(ExecArgs[0], ExecArgs, NULL), ELOOP);
|
|
exit(0);
|
|
|
|
//
|
|
// The parent waits for the child to exit.
|
|
//
|
|
}
|
|
else
|
|
{
|
|
LxtCheckResult(LxtWaitPidPoll(ChildPid, 0));
|
|
}
|
|
|
|
//
|
|
// Remove the entries via the status file.
|
|
//
|
|
|
|
LxtCheckErrno(Fd = open(BINFMT_MNT "/status", O_RDWR));
|
|
Size = strlen(BINFMT_REMOVE_STRING);
|
|
LxtCheckErrno(Size = write(Fd, BINFMT_REMOVE_STRING, Size));
|
|
LxtClose(Fd);
|
|
Fd = -1;
|
|
|
|
ErrorExit:
|
|
if (RegisterFd > 0)
|
|
{
|
|
LxtClose(RegisterFd);
|
|
}
|
|
|
|
if (Fd > 0)
|
|
{
|
|
LxtClose(Fd);
|
|
}
|
|
|
|
if (ChildPid == 0)
|
|
{
|
|
_exit(Result);
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
int BinFmtInvalidParam(PLXT_ARGS Args)
|
|
|
|
/*++
|
|
|
|
Description:
|
|
|
|
This routine tests invalid argument handling for the binfmt register file.
|
|
|
|
Arguments:
|
|
|
|
Args - Supplies the command line arguments.
|
|
|
|
Return Value:
|
|
|
|
Returns 0 on success, -1 on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
int Fd;
|
|
int Index;
|
|
int Result;
|
|
ssize_t Size;
|
|
|
|
LxtCheckErrno(Fd = open(BINFMT_MNT "/register", O_WRONLY));
|
|
for (Index = 0; Index < LXT_COUNT_OF(g_BinFmtRegisterInvalid); Index += 1)
|
|
{
|
|
LxtLogInfo("Index[%d] %s", Index, g_BinFmtRegisterInvalid[Index]);
|
|
Size = strlen(g_BinFmtRegisterInvalid[Index]);
|
|
LxtCheckErrnoFailure(Size = write(Fd, g_BinFmtRegisterInvalid[Index], Size), EINVAL);
|
|
}
|
|
|
|
ErrorExit:
|
|
if (Fd > 0)
|
|
{
|
|
LxtClose(Fd);
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
int BinFmtOffset(PLXT_ARGS Args)
|
|
|
|
/*++
|
|
|
|
Description:
|
|
|
|
This routine tests binformat interpreter options.
|
|
|
|
Arguments:
|
|
|
|
Args - Supplies the command line arguments.
|
|
|
|
Return Value:
|
|
|
|
Returns 0 on success, -1 on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
int ChildPid;
|
|
char* ExecArgs[2];
|
|
int Fd;
|
|
char RegisterString[] = ":" BINFMT_REGISTER_NAME ":M:2:" BINFMT_OFFSET_TEST_PATTERN "::/bin/true:";
|
|
int Result;
|
|
ssize_t Size;
|
|
|
|
//
|
|
// Register an interpreter with a known string at a two byte offset.
|
|
//
|
|
|
|
LxtCheckErrno(Fd = open(BINFMT_MNT "/register", O_WRONLY));
|
|
Size = strlen(RegisterString);
|
|
LxtCheckErrno(Size = write(Fd, RegisterString, Size));
|
|
|
|
//
|
|
// Create a test file that matches this pattern.
|
|
//
|
|
|
|
LxtClose(Fd);
|
|
LxtCheckErrno(Fd = creat(BINFMT_OFFSET_TEST, 0777));
|
|
LxtCheckErrno(Size = write(Fd, "00" BINFMT_OFFSET_TEST_PATTERN, sizeof(BINFMT_OFFSET_TEST_PATTERN) + 2));
|
|
LxtClose(Fd);
|
|
Fd = -1;
|
|
|
|
//
|
|
// Fork and exec the file and ensure that the binfmt interpreter is invoked.
|
|
//
|
|
|
|
LxtCheckResult(ChildPid = fork());
|
|
if (ChildPid == 0)
|
|
{
|
|
ExecArgs[0] = BINFMT_OFFSET_TEST;
|
|
ExecArgs[1] = NULL;
|
|
LxtCheckErrno(LxtExecve(ExecArgs[0], ExecArgs, NULL));
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Wait for the child to exit.
|
|
//
|
|
|
|
LxtCheckResult(LxtWaitPidPoll(ChildPid, 0));
|
|
|
|
//
|
|
// Create a test file that does not match the pattern.
|
|
//
|
|
|
|
LxtCheckErrno(Fd = creat(BINFMT_OFFSET_TEST, 0777));
|
|
LxtCheckErrno(Size = write(Fd, BINFMT_OFFSET_TEST_PATTERN, sizeof(BINFMT_OFFSET_TEST_PATTERN)));
|
|
LxtClose(Fd);
|
|
Fd = -1;
|
|
|
|
//
|
|
// Fork and exec the file and ensure that the exec fails.
|
|
//
|
|
|
|
LxtCheckResult(ChildPid = fork());
|
|
if (ChildPid == 0)
|
|
{
|
|
ExecArgs[0] = BINFMT_OFFSET_TEST;
|
|
ExecArgs[1] = NULL;
|
|
LxtCheckErrnoFailure(LxtExecve(ExecArgs[0], ExecArgs, NULL), ENOEXEC);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Wait for the child to exit.
|
|
//
|
|
|
|
LxtCheckResult(LxtWaitPidPoll(ChildPid, 0));
|
|
|
|
Result = LXT_RESULT_SUCCESS;
|
|
|
|
ErrorExit:
|
|
if (Fd > 0)
|
|
{
|
|
LxtClose(Fd);
|
|
}
|
|
|
|
if (ChildPid == 0)
|
|
{
|
|
_exit(Result);
|
|
}
|
|
|
|
//
|
|
// Unregister the interpreter and delete the test file.
|
|
//
|
|
|
|
BimFmtCleanup();
|
|
unlink(BINFMT_OFFSET_TEST);
|
|
|
|
return Result;
|
|
}
|
|
|
|
int BinFmtOptions(PLXT_ARGS Args)
|
|
|
|
/*++
|
|
|
|
Description:
|
|
|
|
This routine tests binformat interpreter options.
|
|
|
|
Arguments:
|
|
|
|
Args - Supplies the command line arguments.
|
|
|
|
Return Value:
|
|
|
|
Returns 0 on success, -1 on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
char* Argv[5];
|
|
char Buffer[16];
|
|
size_t BytesWritten;
|
|
int ChildPid;
|
|
char* ExecArgs[3];
|
|
int Fd = -1;
|
|
int Index;
|
|
int RegisterFd;
|
|
LXT_CHILD_INFO Registration;
|
|
int Result;
|
|
ssize_t Size;
|
|
int Status;
|
|
|
|
//
|
|
// Clean any binfmt interpreters from a previous iteration of the test.
|
|
//
|
|
|
|
BimFmtCleanup();
|
|
|
|
//
|
|
// Create a file that will be handled by the binfmt extension.
|
|
//
|
|
|
|
LxtCheckErrno(Fd = creat(BINFMT_TEST_FILE, 0777));
|
|
memset(Buffer, 0xff, sizeof(Buffer));
|
|
LxtCheckErrno(BytesWritten = write(Fd, Buffer, sizeof(Buffer)));
|
|
LxtCheckErrno(fchown(Fd, BINFMT_BINARY_UID, BINFMT_BINARY_GID));
|
|
LxtCheckErrno(fchmod(Fd, 0777 | S_ISUID));
|
|
LxtClose(Fd);
|
|
Fd = -1;
|
|
|
|
//
|
|
// Create a binfmt interpreter without any flags.
|
|
//
|
|
|
|
LxtLogInfo("Testing no flags");
|
|
LxtCheckErrno(Fd = creat(BINFMT_INTERPRETER_BINARY_SOURCEFILE, 0777));
|
|
LxtCheckErrno(BytesWritten = write(Fd, BINFMT_INTERPRETER_BINARY_SOURCE_NO_FLAGS, (sizeof(BINFMT_INTERPRETER_BINARY_SOURCE_NO_FLAGS) - 1)));
|
|
|
|
LxtClose(Fd);
|
|
Fd = -1;
|
|
|
|
//
|
|
// Compile the binary
|
|
//
|
|
|
|
LxtCheckErrno(ChildPid = fork());
|
|
if (ChildPid == 0)
|
|
{
|
|
Argv[0] = "gcc";
|
|
Argv[1] = BINFMT_INTERPRETER_BINARY_SOURCEFILE;
|
|
Argv[2] = "-o";
|
|
Argv[3] = BINFMT_INTERPRETER_BINARY;
|
|
Argv[4] = NULL;
|
|
LxtCheckErrno(execv("/usr/bin/gcc", Argv));
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Wait for the child to exit.
|
|
//
|
|
|
|
LxtCheckResult(LxtWaitPidPollOptions(ChildPid, LXT_RESULT_SUCCESS, 0, BINFMT_TIMEOUT));
|
|
|
|
//
|
|
// Register a binfmt extension without flags.
|
|
//
|
|
|
|
LxtCheckErrno(RegisterFd = open(BINFMT_MNT "/register", O_WRONLY));
|
|
Size = strlen(BINFMT_REGISTER_BINARY_STRING);
|
|
LxtCheckErrno(Size = write(RegisterFd, BINFMT_REGISTER_BINARY_STRING, Size));
|
|
|
|
//
|
|
// Fork and exec the file.
|
|
//
|
|
|
|
LxtCheckResult(ChildPid = fork());
|
|
if (ChildPid == 0)
|
|
{
|
|
LxtCheckErrno(LxtSetresuid(BINFMT_CALLER_UID, BINFMT_CALLER_UID, BINFMT_CALLER_UID));
|
|
ExecArgs[0] = BINFMT_TEST_FILE;
|
|
ExecArgs[1] = NULL;
|
|
LxtCheckErrno(LxtExecve(ExecArgs[0], ExecArgs, NULL));
|
|
}
|
|
|
|
//
|
|
// Wait for the child to exit.
|
|
//
|
|
|
|
LxtCheckResult(LxtWaitPidPollOptions(ChildPid, 0, 0, BINFMT_TIMEOUT));
|
|
|
|
//
|
|
// Unregister the interpreter.
|
|
//
|
|
|
|
BimFmtCleanup();
|
|
|
|
//
|
|
// Create the binfmt interpreter that handles the 'O' flag.
|
|
//
|
|
|
|
LxtLogInfo("Testing 'O' flag");
|
|
LxtCheckErrno(Fd = creat(BINFMT_INTERPRETER_BINARY_SOURCEFILE, 0777));
|
|
LxtCheckErrno(BytesWritten = write(Fd, BINFMT_INTERPRETER_BINARY_SOURCE_O_FLAG, (sizeof(BINFMT_INTERPRETER_BINARY_SOURCE_O_FLAG) - 1)));
|
|
|
|
LxtClose(Fd);
|
|
Fd = -1;
|
|
|
|
//
|
|
// Compile the binary
|
|
//
|
|
|
|
LxtCheckErrno(ChildPid = fork());
|
|
if (ChildPid == 0)
|
|
{
|
|
Argv[0] = "gcc";
|
|
Argv[1] = BINFMT_INTERPRETER_BINARY_SOURCEFILE;
|
|
Argv[2] = "-o";
|
|
Argv[3] = BINFMT_INTERPRETER_BINARY;
|
|
Argv[4] = NULL;
|
|
LxtCheckErrno(execv("/usr/bin/gcc", Argv));
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Wait for the child to exit.
|
|
//
|
|
|
|
LxtCheckResult(LxtWaitPidPollOptions(ChildPid, LXT_RESULT_SUCCESS, 0, BINFMT_TIMEOUT));
|
|
|
|
//
|
|
// Register a binfmt extension.
|
|
//
|
|
|
|
LxtCheckErrno(RegisterFd = open(BINFMT_MNT "/register", O_WRONLY));
|
|
Size = strlen(BINFMT_REGISTER_BINARY_STRING_O);
|
|
LxtCheckErrno(Size = write(RegisterFd, BINFMT_REGISTER_BINARY_STRING_O, Size));
|
|
|
|
//
|
|
// Fork and exec the file.
|
|
//
|
|
|
|
LxtCheckResult(ChildPid = fork());
|
|
if (ChildPid == 0)
|
|
{
|
|
LxtCheckErrno(LxtSetresuid(BINFMT_CALLER_UID, BINFMT_CALLER_UID, BINFMT_CALLER_UID));
|
|
ExecArgs[0] = BINFMT_TEST_FILE;
|
|
ExecArgs[1] = NULL;
|
|
LxtCheckErrno(LxtExecve(ExecArgs[0], ExecArgs, NULL));
|
|
}
|
|
|
|
//
|
|
// Wait for the child to exit.
|
|
//
|
|
|
|
LxtCheckResult(LxtWaitPidPollOptions(ChildPid, 0, 0, BINFMT_TIMEOUT));
|
|
|
|
//
|
|
// Unregister the interpreter.
|
|
//
|
|
|
|
BimFmtCleanup();
|
|
|
|
//
|
|
// Create the binfmt interpreter that handles the 'C' flag.
|
|
//
|
|
|
|
LxtLogInfo("Testing 'C' flag");
|
|
LxtCheckErrno(Fd = creat(BINFMT_INTERPRETER_BINARY_SOURCEFILE, 0777));
|
|
LxtCheckErrno(BytesWritten = write(Fd, BINFMT_INTERPRETER_BINARY_SOURCE_C_FLAG, (sizeof(BINFMT_INTERPRETER_BINARY_SOURCE_C_FLAG) - 1)));
|
|
|
|
LxtClose(Fd);
|
|
Fd = -1;
|
|
|
|
//
|
|
// Compile the binary
|
|
//
|
|
|
|
LxtCheckErrno(ChildPid = fork());
|
|
if (ChildPid == 0)
|
|
{
|
|
Argv[0] = "gcc";
|
|
Argv[1] = BINFMT_INTERPRETER_BINARY_SOURCEFILE;
|
|
Argv[2] = "-o";
|
|
Argv[3] = BINFMT_INTERPRETER_BINARY;
|
|
Argv[4] = NULL;
|
|
LxtCheckErrno(execv("/usr/bin/gcc", Argv));
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Wait for the child to exit.
|
|
//
|
|
|
|
LxtCheckResult(LxtWaitPidPollOptions(ChildPid, LXT_RESULT_SUCCESS, 0, BINFMT_TIMEOUT));
|
|
|
|
//
|
|
// Register a binfmt extension.
|
|
//
|
|
|
|
LxtCheckErrno(RegisterFd = open(BINFMT_MNT "/register", O_WRONLY));
|
|
Size = strlen(BINFMT_REGISTER_BINARY_STRING_C);
|
|
LxtCheckErrno(Size = write(RegisterFd, BINFMT_REGISTER_BINARY_STRING_C, Size));
|
|
|
|
//
|
|
// Fork and exec the file.
|
|
//
|
|
|
|
LxtCheckResult(ChildPid = fork());
|
|
if (ChildPid == 0)
|
|
{
|
|
LxtCheckErrno(LxtSetresuid(BINFMT_CALLER_UID, BINFMT_CALLER_UID, BINFMT_CALLER_UID));
|
|
ExecArgs[0] = BINFMT_TEST_FILE;
|
|
ExecArgs[1] = NULL;
|
|
LxtCheckErrno(LxtExecve(ExecArgs[0], ExecArgs, NULL));
|
|
}
|
|
|
|
//
|
|
// Wait for the child to exit.
|
|
//
|
|
|
|
LxtCheckResult(LxtWaitPidPollOptions(ChildPid, 0, 0, BINFMT_TIMEOUT));
|
|
|
|
//
|
|
// Unregister the interpreter.
|
|
//
|
|
|
|
BimFmtCleanup();
|
|
|
|
//
|
|
// Create the binfmt interpreter that handles the 'P' flag.
|
|
//
|
|
|
|
LxtLogInfo("Testing 'P' flag");
|
|
LxtCheckErrno(Fd = creat(BINFMT_INTERPRETER_BINARY_SOURCEFILE, 0777));
|
|
LxtCheckErrno(BytesWritten = write(Fd, BINFMT_INTERPRETER_BINARY_SOURCE_P_FLAG, (sizeof(BINFMT_INTERPRETER_BINARY_SOURCE_P_FLAG) - 1)));
|
|
|
|
LxtClose(Fd);
|
|
Fd = -1;
|
|
|
|
//
|
|
// Compile the binary
|
|
//
|
|
|
|
LxtCheckErrno(ChildPid = fork());
|
|
if (ChildPid == 0)
|
|
{
|
|
Argv[0] = "gcc";
|
|
Argv[1] = BINFMT_INTERPRETER_BINARY_SOURCEFILE;
|
|
Argv[2] = "-o";
|
|
Argv[3] = BINFMT_INTERPRETER_BINARY;
|
|
Argv[4] = NULL;
|
|
LxtCheckErrno(execv("/usr/bin/gcc", Argv));
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Wait for the child to exit.
|
|
//
|
|
|
|
LxtCheckResult(LxtWaitPidPollOptions(ChildPid, LXT_RESULT_SUCCESS, 0, BINFMT_TIMEOUT));
|
|
|
|
//
|
|
// Register a binfmt extension.
|
|
//
|
|
|
|
LxtCheckErrno(RegisterFd = open(BINFMT_MNT "/register", O_WRONLY));
|
|
Size = strlen(BINFMT_REGISTER_BINARY_STRING_P);
|
|
LxtCheckErrno(Size = write(RegisterFd, BINFMT_REGISTER_BINARY_STRING_P, Size));
|
|
|
|
//
|
|
// Fork and exec the file.
|
|
//
|
|
|
|
LxtCheckResult(ChildPid = fork());
|
|
if (ChildPid == 0)
|
|
{
|
|
ExecArgs[0] = BINFMT_TEST_FILE;
|
|
ExecArgs[1] = BINFMT_P_FLAG_ARG;
|
|
ExecArgs[2] = NULL;
|
|
LxtCheckErrno(LxtExecve(ExecArgs[0], ExecArgs, NULL));
|
|
}
|
|
|
|
//
|
|
// Wait for the child to exit.
|
|
//
|
|
|
|
LxtCheckResult(LxtWaitPidPollOptions(ChildPid, 0, 0, BINFMT_TIMEOUT));
|
|
|
|
//
|
|
// Unregister the interpreter.
|
|
//
|
|
|
|
BimFmtCleanup();
|
|
|
|
ErrorExit:
|
|
if (RegisterFd > 0)
|
|
{
|
|
LxtClose(RegisterFd);
|
|
}
|
|
|
|
if (Fd > 0)
|
|
{
|
|
LxtClose(Fd);
|
|
}
|
|
|
|
if (ChildPid == 0)
|
|
{
|
|
_exit(Result);
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
int BinFmtRoot(PLXT_ARGS Args)
|
|
|
|
/*++
|
|
|
|
Description:
|
|
|
|
This routine tests the contents of the binfmt directory.
|
|
|
|
Arguments:
|
|
|
|
Args - Supplies the command line arguments.
|
|
|
|
Return Value:
|
|
|
|
Returns 0 on success, -1 on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
int Result;
|
|
|
|
// LxtCheckResult(LxtCheckStat(BINFMT_MNT, 1, DT_DIR));
|
|
LxtCheckResult(LxtCheckDirectoryContents(BINFMT_MNT, g_BinFmtRootChildren, LXT_COUNT_OF(g_BinFmtRootChildren)));
|
|
|
|
ErrorExit:
|
|
return Result;
|
|
}
|
|
|
|
int BinFmtRegister(PLXT_ARGS Args)
|
|
|
|
/*++
|
|
|
|
Description:
|
|
|
|
This routine tests the binfmt register file.
|
|
|
|
Arguments:
|
|
|
|
Args - Supplies the command line arguments.
|
|
|
|
Return Value:
|
|
|
|
Returns 0 on success, -1 on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
char Buffer[128];
|
|
int Fd;
|
|
LXT_CHILD_INFO Registration;
|
|
int Result;
|
|
ssize_t Size;
|
|
|
|
//
|
|
// Clean up any previously registered interpreters.
|
|
//
|
|
|
|
BimFmtCleanup();
|
|
|
|
//
|
|
// Open the register file and verify that binfmt registrations are able to be registered.
|
|
//
|
|
|
|
LxtCheckErrno(Fd = open(BINFMT_MNT "/register", O_WRONLY));
|
|
|
|
Size = strlen(BINFMT_REGISTER_SCRIPT_STRING);
|
|
LxtCheckErrno(Size = write(Fd, BINFMT_REGISTER_SCRIPT_STRING, Size));
|
|
LxtClose(Fd);
|
|
Fd = -1;
|
|
|
|
Registration.Name = BINFMT_REGISTER_NAME;
|
|
Registration.FileType = DT_REG;
|
|
|
|
LxtCheckResult(LxtCheckDirectoryContents(BINFMT_MNT, &Registration, 1));
|
|
|
|
//
|
|
// Open the registration file and verify that it behaves as expected.
|
|
// Status should initially be enabled.
|
|
//
|
|
|
|
LxtCheckErrno(Fd = open(BINFMT_MNT "/" BINFMT_REGISTER_NAME, O_RDWR));
|
|
LxtCheckErrno(Size = read(Fd, Buffer, sizeof(Buffer) - 1));
|
|
Buffer[Size] = '\0';
|
|
LxtClose(Fd);
|
|
Fd = -1;
|
|
|
|
LxtCheckStringEqual(Buffer, BINFMT_REGISTRATION_ENABLED_STRING);
|
|
|
|
//
|
|
// Disable the registration and verify the string changes.
|
|
//
|
|
|
|
LxtCheckErrno(Fd = open(BINFMT_MNT "/" BINFMT_REGISTER_NAME, O_RDWR));
|
|
Size = strlen(BINFMT_DISABLE_STRING);
|
|
LxtCheckErrno(Size = write(Fd, BINFMT_DISABLE_STRING, Size));
|
|
LxtClose(Fd);
|
|
Fd = -1;
|
|
|
|
LxtCheckErrno(Fd = open(BINFMT_MNT "/" BINFMT_REGISTER_NAME, O_RDWR));
|
|
LxtCheckErrno(Size = read(Fd, Buffer, sizeof(Buffer) - 1));
|
|
Buffer[Size] = '\0';
|
|
LxtClose(Fd);
|
|
Fd = -1;
|
|
|
|
LxtCheckStringEqual(Buffer, BINFMT_REGISTRATION_DISABLED_STRING);
|
|
|
|
//
|
|
// Enable and verify the string changes.
|
|
//
|
|
|
|
LxtCheckErrno(Fd = open(BINFMT_MNT "/" BINFMT_REGISTER_NAME, O_RDWR));
|
|
Size = strlen(BINFMT_ENABLE_STRING);
|
|
LxtCheckErrno(Size = write(Fd, BINFMT_ENABLE_STRING, Size));
|
|
LxtClose(Fd);
|
|
Fd = -1;
|
|
|
|
LxtCheckErrno(Fd = open(BINFMT_MNT "/" BINFMT_REGISTER_NAME, O_RDWR));
|
|
LxtCheckErrno(Size = read(Fd, Buffer, sizeof(Buffer) - 1));
|
|
Buffer[Size] = '\0';
|
|
LxtClose(Fd);
|
|
Fd = -1;
|
|
|
|
LxtCheckStringEqual(Buffer, BINFMT_REGISTRATION_ENABLED_STRING);
|
|
|
|
//
|
|
// Remove the new entry via the registration file.
|
|
//
|
|
|
|
LxtCheckErrno(Fd = open(BINFMT_MNT "/" BINFMT_REGISTER_NAME, O_RDWR));
|
|
Size = strlen(BINFMT_REMOVE_STRING);
|
|
LxtCheckErrno(Size = write(Fd, BINFMT_REMOVE_STRING, Size));
|
|
LxtClose(Fd);
|
|
Fd = -1;
|
|
|
|
//
|
|
// Attempt to open the file (should fail);
|
|
//
|
|
|
|
LxtCheckErrnoFailure(Fd = open(BINFMT_MNT "/" BINFMT_REGISTER_NAME, O_RDWR), ENOENT);
|
|
|
|
ErrorExit:
|
|
if (Fd > 0)
|
|
{
|
|
LxtClose(Fd);
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
int BinFmtStatus(PLXT_ARGS Args)
|
|
|
|
/*++
|
|
|
|
Description:
|
|
|
|
This routine tests the binfmt status file.
|
|
|
|
Arguments:
|
|
|
|
Args - Supplies the command line arguments.
|
|
|
|
Return Value:
|
|
|
|
Returns 0 on success, -1 on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
char Buffer[64];
|
|
int Fd;
|
|
LXT_CHILD_INFO Registration;
|
|
int Result;
|
|
ssize_t Size;
|
|
|
|
//
|
|
// Open the status file and verify that status behaves as expected.
|
|
// Status should initially be enabled.
|
|
//
|
|
|
|
LxtCheckErrno(Fd = open(BINFMT_MNT "/status", O_RDWR));
|
|
LxtCheckErrno(Size = read(Fd, Buffer, sizeof(Buffer) - 1));
|
|
Buffer[Size] = '\0';
|
|
LxtClose(Fd);
|
|
Fd = -1;
|
|
|
|
LxtCheckStringEqual(Buffer, BINFMT_STATUS_ENABLED);
|
|
|
|
//
|
|
// Disable status and verify the string changes.
|
|
//
|
|
|
|
LxtCheckErrno(Fd = open(BINFMT_MNT "/status", O_RDWR));
|
|
Size = strlen(BINFMT_DISABLE_STRING);
|
|
LxtCheckErrno(Size = write(Fd, BINFMT_DISABLE_STRING, Size));
|
|
LxtClose(Fd);
|
|
Fd = -1;
|
|
|
|
LxtCheckErrno(Fd = open(BINFMT_MNT "/status", O_RDWR));
|
|
LxtCheckErrno(Size = read(Fd, Buffer, sizeof(Buffer) - 1));
|
|
Buffer[Size] = '\0';
|
|
LxtClose(Fd);
|
|
Fd = -1;
|
|
|
|
LxtCheckStringEqual(Buffer, BINFMT_STATUS_DISABLED);
|
|
|
|
//
|
|
// Enable and verify the string changes.
|
|
//
|
|
|
|
LxtCheckErrno(Fd = open(BINFMT_MNT "/status", O_RDWR));
|
|
Size = strlen(BINFMT_ENABLE_STRING);
|
|
LxtCheckErrno(Size = write(Fd, BINFMT_ENABLE_STRING, Size));
|
|
LxtClose(Fd);
|
|
Fd = -1;
|
|
|
|
LxtCheckErrno(Fd = open(BINFMT_MNT "/status", O_RDWR));
|
|
LxtCheckErrno(Size = read(Fd, Buffer, sizeof(Buffer) - 1));
|
|
Buffer[Size] = '\0';
|
|
LxtClose(Fd);
|
|
Fd = -1;
|
|
|
|
LxtCheckStringEqual(Buffer, BINFMT_STATUS_ENABLED);
|
|
|
|
//
|
|
// Register a binfmt extension and verify that it is removed when
|
|
// -1 is written to the status file.
|
|
//
|
|
|
|
LxtCheckErrno(Fd = open(BINFMT_MNT "/register", O_RDWR));
|
|
Size = strlen(BINFMT_REGISTER_SCRIPT_STRING);
|
|
LxtCheckErrno(Size = write(Fd, BINFMT_REGISTER_SCRIPT_STRING, Size));
|
|
LxtClose(Fd);
|
|
Fd = -1;
|
|
|
|
Registration.Name = BINFMT_REGISTER_NAME;
|
|
Registration.FileType = DT_REG;
|
|
|
|
LxtCheckResult(LxtCheckDirectoryContents(BINFMT_MNT, &Registration, 1));
|
|
|
|
//
|
|
// Remove the new entry via the status file.
|
|
//
|
|
|
|
LxtCheckErrno(Fd = open(BINFMT_MNT "/status", O_RDWR));
|
|
Size = strlen(BINFMT_REMOVE_STRING);
|
|
LxtCheckErrno(Size = write(Fd, BINFMT_REMOVE_STRING, Size));
|
|
LxtClose(Fd);
|
|
Fd = -1;
|
|
|
|
//
|
|
// Attempt to open the file (should fail);
|
|
//
|
|
|
|
LxtCheckErrnoFailure(Fd = open(BINFMT_MNT "/" BINFMT_REGISTER_NAME, O_RDWR), ENOENT);
|
|
|
|
ErrorExit:
|
|
if (Fd > 0)
|
|
{
|
|
LxtClose(Fd);
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
int BinFmtInterpreterEntry(PLXT_ARGS Args)
|
|
|
|
/*++
|
|
|
|
Description:
|
|
|
|
This routine implements the entry point for the test binfmt interpreter.
|
|
|
|
Arguments:
|
|
|
|
Args - Supplies the command line arguments.
|
|
|
|
Return Value:
|
|
|
|
Returns 0 on success, -1 on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
int Index;
|
|
int Result;
|
|
printf("Pid = %d\n", getpid());
|
|
for (Index = 0; Index < Args->Argc; Index += 1)
|
|
{
|
|
printf("Argv[%d]: %s\n", Index, Args->Argv[Index]);
|
|
}
|
|
|
|
return 0;
|
|
}
|