WSL/test/linux/unit_tests/resourcelimits.c
Josh Soref abce91d14b
Spelling (#12954)
* link: Collect WSL logs (recommended method)

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* link: Advanced Authoring Tests in C++

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* link: CMake Documentation and Community

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* link: Collect WSL logs for networking issues

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* link: Collect WSL logs (recommended method)

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: ; otherwise,

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: a

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: access

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: accessible

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: across

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: actively

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: adapters

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: address

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: addresses

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: and

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: appropriate

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: argument

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: associated

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: attach

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: available

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: beginning

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: between

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: binaries

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: bound

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: buffer

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: buffers

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: cannot

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: canonical

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: capabilities

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: case-insensitive

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: case-sensitive

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: certified

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: command

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: committer

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: communication

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: complains

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: configuration

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: consumed

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: continue

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: converted

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: currently

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: customers

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: daemon

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: deferred

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: definitions

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: delimiter

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: delivered

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: dellink

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: derived

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: descriptor

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: destined

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: destruct

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: destructible

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: destructor

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: detach

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: differentiate

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: directories

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: disassociate

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: disposition

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: distribution

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: distro

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: duping

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: emitted

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: empty

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: environment

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: every time

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: exclusive

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: expected

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: expire

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: explicitly

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: fall back

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: false

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: fastfail

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: filesystem

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: first

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: followed

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: for

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: functionality

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: functionally

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: github

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: greater

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: guarantee

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: guaranteed

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: handles

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: hangup

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: hierarchy

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: hogwarts

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: hydrated

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: icrnl

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: implementation

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: implementing

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: initialize

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: instance

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: instantiate

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: instantiations

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: intentionally

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: interpret

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: interpreter

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: irreversibly

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: iteration

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: iterator

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: its

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: kernel

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: kmsg

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: knowledge

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: maximum

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: mirrored

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: msftconnecttest

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: multi

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: multiple

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: mutable

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: namespace

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: nonexistent

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: notifications

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: occurred

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: occurring

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: otherwise,

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: outstanding

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: overridden

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: partition

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: pass through

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: passthrough

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: performs

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: periodically

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: positional

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: precedence

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: preexisting

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: preferring

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: prepopulate

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: previous

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: privileges

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: process

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: processes

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: programmatically

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: protection

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: provided

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: reasonable

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: receive

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: received

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: red hat

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: reentrant

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: registered

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: regularly

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: relay

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: release

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: representing

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: requests

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: response

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: resurrect

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: retention

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: returned

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: security

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: semaphore

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: separate

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: separator

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: service

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: set up

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: setup

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: severely

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: should

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: signal

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: similarly

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: simple

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: simplified

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: single

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: specified

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: splitting

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: standard

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: stress

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: succeed

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: success

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: successfully

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: supplementary

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: synced

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: system

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: take

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: than

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: that opening

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: the

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: threadpool

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: to

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: true

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: truncate

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: tunneling

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: unexpected

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: uninitialize

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: unique

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: unprivileged

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: unregistered

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: untrusted

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: upgrade

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: utility

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: validating

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: variant

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: variation

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: variations

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: verify

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: visible

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: whether

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: winget

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: worker

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: written

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: wslservice

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* format source

---------

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
Co-authored-by: Ben Hillis <benhillis@gmail.com>
Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
2025-07-23 15:19:00 -07:00

702 lines
23 KiB
C

/*++
Copyright (c) Microsoft. All rights reserved.
Module Name:
resourcelimit.c
Abstract:
This file contains unit test for set and get resource limits.
--*/
#include "lxtcommon.h"
#include "unittests.h"
#include <sys/prctl.h>
#include <sys/types.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#if !defined(__amd64__) && !defined(__aarch64__)
#include <sys/capability.h>
#else
#include <sys/cdefs.h>
#include <linux/capability.h>
#define _LINUX_CAPABILITY_VERSION_3 0x20080522
#ifndef O_PATH
#define O_PATH 010000000
#endif
#endif
#define LXT_NAME "resourcelimits"
#define LXT_RESOURCE_LIMIT_TEST_FILE "rlimit_testfile"
#define LXT_RESOURCE_LIMIT_UID 1024
#define LXT_RESOURCE_LIMIT_GID 1024
#define LXT_NOFILE (10)
#define LXT_NR_OPEN (1024 * 1024)
int ResourceLimitTest(PLXT_ARGS Args);
int ResourceLimitNoFile(PLXT_ARGS Args);
int PrlimitTest(PLXT_ARGS Args);
//
// Global constants
//
static const LXT_VARIATION g_LxtVariations[] = {
{"Resource Limit Test", ResourceLimitTest}, {"RLIMIT_NOFILE", ResourceLimitNoFile}, {"prlimit64 test", PrlimitTest}};
int ResourceLimitsTestEntry(int Argc, char* Argv[])
/*++
--*/
{
LXT_ARGS Args;
int Result;
LxtCheckResult(LxtInitialize(Argc, Argv, &Args, LXT_NAME));
LxtCheckResult(LxtRunVariations(&Args, g_LxtVariations, LXT_COUNT_OF(g_LxtVariations)));
ErrorExit:
LxtUninitialize();
return !LXT_SUCCESS(Result);
}
int ResourceLimitTest(PLXT_ARGS Args)
/*++
--*/
{
int Index;
struct rlimit ResourceLimit;
int Result;
int Status;
//
// Get all resource limits.
//
LxtLogInfo("Getting all resource limits:");
for (Index = 0; Index < 16; Index += 1)
{
LxtCheckErrno(getrlimit(Index, &ResourceLimit));
LxtLogInfo("Resource# %d: current %llu, max %llu", Index, ResourceLimit.rlim_cur, ResourceLimit.rlim_max)
}
//
// Set/Get invalid resources.
//
LxtCheckErrnoFailure(setrlimit(17, &ResourceLimit), EINVAL);
LxtCheckErrnoFailure(getrlimit(17, &ResourceLimit), EINVAL);
LxtCheckErrnoFailure(setrlimit(-1, &ResourceLimit), EINVAL);
LxtCheckErrnoFailure(getrlimit(-1, &ResourceLimit), EINVAL);
LxtCheckErrnoFailure(setrlimit(16, NULL), EINVAL);
LxtCheckErrnoFailure(setrlimit(16, (struct rlimit*)-1), EFAULT);
LxtCheckErrnoFailure(getrlimit(16, NULL), EINVAL);
LxtCheckErrnoFailure(getrlimit(16, (struct rlimit*)-1), EINVAL);
LxtCheckErrnoFailure(setrlimit(LXT_NR_OPEN, NULL), EINVAL);
LxtCheckErrnoFailure(setrlimit(LXT_NR_OPEN, (struct rlimit*)-1), EFAULT);
LxtCheckErrnoFailure(getrlimit(LXT_NR_OPEN, NULL), EINVAL);
LxtCheckErrnoFailure(getrlimit(LXT_NR_OPEN, (struct rlimit*)-1), EINVAL);
//
// Set invalid resource limits.
//
ResourceLimit.rlim_cur = 2;
ResourceLimit.rlim_max = 1;
LxtLogInfo("Setting resource limit with soft limit being greater than hard limit");
LxtCheckErrnoFailure(setrlimit(RLIMIT_NPROC, &ResourceLimit), EINVAL);
//
// Set NoFile limit past the WSL max, to NR_OPEN, and past NR_OPEN
//
ResourceLimit.rlim_cur = 2049;
ResourceLimit.rlim_max = 2050;
LxtCheckErrno(setrlimit(RLIMIT_NOFILE, &ResourceLimit));
ResourceLimit.rlim_cur = LXT_NR_OPEN - 1;
ResourceLimit.rlim_max = LXT_NR_OPEN;
LxtCheckErrno(setrlimit(RLIMIT_NOFILE, &ResourceLimit));
ResourceLimit.rlim_cur = LXT_NR_OPEN;
ResourceLimit.rlim_max = LXT_NR_OPEN;
LxtCheckErrno(setrlimit(RLIMIT_NOFILE, &ResourceLimit));
ResourceLimit.rlim_cur = LXT_NR_OPEN + 1;
ResourceLimit.rlim_max = LXT_NR_OPEN + 1;
LxtCheckErrnoFailure(setrlimit(RLIMIT_NOFILE, &ResourceLimit), EPERM);
//
// Test RLIMIT_NPROC.
//
ResourceLimit.rlim_cur = 7823;
ResourceLimit.rlim_max = 7824;
LxtCheckErrno(setrlimit(RLIMIT_NPROC, &ResourceLimit));
ResourceLimit.rlim_cur = 0x7ffffffffffffffe;
ResourceLimit.rlim_max = 0x7fffffffffffffff;
LxtCheckErrno(setrlimit(RLIMIT_NPROC, &ResourceLimit));
LxtCheckErrno(getrlimit(RLIMIT_NPROC, &ResourceLimit));
LxtCheckEqual(ResourceLimit.rlim_cur, 0x7ffffffffffffffe, "%Iu");
LxtCheckEqual(ResourceLimit.rlim_max, 0x7fffffffffffffff, "%Iu");
Result = LXT_RESULT_SUCCESS;
ErrorExit:
return Result;
}
int ResourceLimitNoFile(PLXT_ARGS Args)
{
int ChildPid;
int FileDescriptorCount;
int* FileDescriptors;
int Index;
int InitialFileDescriptorCount;
struct rlimit InitialResourceLimit;
struct rlimit ResourceLimit;
int Result;
struct stat Stat;
ChildPid = -1;
FileDescriptors = NULL;
LxtCheckErrno(getrlimit(RLIMIT_NOFILE, &InitialResourceLimit));
LxtLogInfo("Initial rlim_cur %Iu rlim_max %Iu", InitialResourceLimit.rlim_cur, InitialResourceLimit.rlim_max);
ResourceLimit = InitialResourceLimit;
//
// Lower the current file descriptor limit.
//
ResourceLimit.rlim_cur = LXT_NOFILE;
LxtCheckErrno(setrlimit(RLIMIT_NOFILE, &ResourceLimit));
LxtCheckErrno(getrlimit(RLIMIT_NOFILE, &ResourceLimit));
LxtLogInfo("rlim_cur %Iu rlim_max %Iu", ResourceLimit.rlim_cur, ResourceLimit.rlim_max);
//
// Determine how many file descriptors are already open.
//
InitialFileDescriptorCount = 0;
for (Index = 0; Index < ResourceLimit.rlim_cur; Index += 1)
{
if (fstat(Index, &Stat) == 0)
{
//
// Ensure that the file descriptor number matches the index. This
// is strictly to make the validation later in this test more
// straightforward.
//
LxtCheckEqual(Index, InitialFileDescriptorCount, "%d");
InitialFileDescriptorCount += 1;
}
}
//
// Determine how many file descriptors are already open and allocate an
// array large enough to open the maximum number of file descriptors.
//
LxtLogInfo("%d currently open file descriptors", InitialFileDescriptorCount);
FileDescriptorCount = ResourceLimit.rlim_cur - InitialFileDescriptorCount;
FileDescriptors = malloc(sizeof(int) * FileDescriptorCount);
if (FileDescriptors == NULL)
{
LxtLogError("alloc failed");
Result = LXT_RESULT_FAILURE;
goto ErrorExit;
}
memset(FileDescriptors, -1, sizeof(FileDescriptors));
LxtCheckErrno(FileDescriptors[0] = creat(LXT_RESOURCE_LIMIT_TEST_FILE, 0655));
//
// Ensure that a file descriptor with a value greater than the current
// rlimit cannot be created.
//
LxtCheckErrnoFailure(dup2(FileDescriptors[0], ResourceLimit.rlim_cur), EBADF);
LxtCheckErrnoFailure(dup2(FileDescriptors[0], (ResourceLimit.rlim_cur + 1)), EBADF);
//
// Open enough file descriptors to completely fill the table.
//
for (Index = 1; Index < FileDescriptorCount; Index += 1)
{
LxtCheckErrno(FileDescriptors[Index] = open(LXT_RESOURCE_LIMIT_TEST_FILE, O_RDONLY));
}
LxtLogInfo("Opened %d file descriptors", Index);
//
// Ensure that opening one more file descriptor fails.
//
LxtCheckErrnoFailure(open(LXT_RESOURCE_LIMIT_TEST_FILE, O_RDONLY), EMFILE);
//
// Lower the limit to the initial file descriptor count and close all but
// the highest numbered file descriptor.
//
ResourceLimit.rlim_cur = InitialFileDescriptorCount;
LxtCheckErrno(setrlimit(RLIMIT_NOFILE, &ResourceLimit));
LxtCheckErrno(getrlimit(RLIMIT_NOFILE, &ResourceLimit));
LxtLogInfo("rlim_cur %Iu rlim_max %Iu", ResourceLimit.rlim_cur, ResourceLimit.rlim_max);
for (Index = 0; Index < (FileDescriptorCount - 1); Index += 1)
{
LxtClose(FileDescriptors[Index]);
FileDescriptors[Index] = -1;
}
//
// Try to open file descriptors up to the max value.
//
for (Index = 0; Index < (FileDescriptorCount - 1); Index += 1)
{
LxtCheckErrnoFailure(FileDescriptors[Index] = open(LXT_RESOURCE_LIMIT_TEST_FILE, O_RDONLY), EMFILE);
}
//
// Ensure that a child process inherits the same file descriptor limits.
//
LxtCheckErrno(ChildPid = fork());
if (ChildPid == 0)
{
for (Index = 0; Index < (FileDescriptorCount - 1); Index += 1)
{
LxtCheckErrnoFailure(FileDescriptors[Index] = open(LXT_RESOURCE_LIMIT_TEST_FILE, O_RDONLY), EMFILE);
}
goto ErrorExit;
}
//
// Wait for the child to exit.
//
LxtCheckErrno(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
//
// Increment the rlimit and open a single file descriptor.
//
ResourceLimit.rlim_cur += 1;
LxtCheckErrno(setrlimit(RLIMIT_NOFILE, &ResourceLimit));
LxtCheckErrno(getrlimit(RLIMIT_NOFILE, &ResourceLimit));
LxtLogInfo("rlim_cur %Iu rlim_max %Iu", ResourceLimit.rlim_cur, ResourceLimit.rlim_max);
LxtCheckErrno(FileDescriptors[0] = open(LXT_RESOURCE_LIMIT_TEST_FILE, O_RDONLY));
LxtCheckEqual(InitialFileDescriptorCount, FileDescriptors[0], "%d");
//
// Reset the rlimit to the original value.
//
ResourceLimit.rlim_cur = LXT_NOFILE;
LxtCheckErrno(setrlimit(RLIMIT_NOFILE, &ResourceLimit));
LxtCheckErrno(getrlimit(RLIMIT_NOFILE, &ResourceLimit));
LxtLogInfo("rlim_cur %Iu rlim_max %Iu", ResourceLimit.rlim_cur, ResourceLimit.rlim_max);
//
// Attempt to reopen the rest of the file descriptors now that the limit has
// been increased.
//
for (Index = 1; Index < (FileDescriptorCount - 1); Index += 1)
{
LxtCheckErrno(FileDescriptors[Index] = open(LXT_RESOURCE_LIMIT_TEST_FILE, O_RDONLY));
LxtCheckEqual((Index + InitialFileDescriptorCount), FileDescriptors[Index], "%d");
}
//
// Attempt to open one more file descriptor (should fail).
//
LxtCheckErrnoFailure(open(LXT_RESOURCE_LIMIT_TEST_FILE, O_RDONLY), EMFILE);
//
// Set the current resource limit to the max.
//
ResourceLimit.rlim_cur = ResourceLimit.rlim_max;
LxtCheckErrno(setrlimit(RLIMIT_NOFILE, &ResourceLimit));
LxtCheckErrno(getrlimit(RLIMIT_NOFILE, &ResourceLimit));
LxtLogInfo("rlim_cur %Iu rlim_max %Iu", ResourceLimit.rlim_cur, ResourceLimit.rlim_max);
//
// Make the file descriptor limit very large.
//
ResourceLimit.rlim_max = 0x100000;
LxtCheckErrno(setrlimit(RLIMIT_NOFILE, &ResourceLimit));
LxtCheckErrno(getrlimit(RLIMIT_NOFILE, &ResourceLimit));
LxtLogInfo("rlim_cur %Iu rlim_max %Iu", ResourceLimit.rlim_cur, ResourceLimit.rlim_max);
ResourceLimit.rlim_cur = ResourceLimit.rlim_max;
LxtCheckErrno(setrlimit(RLIMIT_NOFILE, &ResourceLimit));
LxtCheckErrno(getrlimit(RLIMIT_NOFILE, &ResourceLimit));
LxtLogInfo("rlim_cur %Iu rlim_max %Iu", ResourceLimit.rlim_cur, ResourceLimit.rlim_max);
//
// Attempt to set the file descriptor limit larger than the maximum allowed.
//
ResourceLimit.rlim_cur = ResourceLimit.rlim_max;
ResourceLimit.rlim_max += 1;
LxtCheckErrnoFailure(setrlimit(RLIMIT_NOFILE, &ResourceLimit), EPERM);
LxtCheckErrno(getrlimit(RLIMIT_NOFILE, &ResourceLimit));
LxtLogInfo("rlim_cur %Iu rlim_max %Iu", ResourceLimit.rlim_cur, ResourceLimit.rlim_max);
//
// Restore the original rlimit.
//
LxtCheckErrno(setrlimit(RLIMIT_NOFILE, &InitialResourceLimit));
LxtCheckErrno(getrlimit(RLIMIT_NOFILE, &ResourceLimit));
LxtLogInfo("Restored rlim_cur %Iu rlim_max %Iu", ResourceLimit.rlim_cur, ResourceLimit.rlim_max);
Result = LXT_RESULT_SUCCESS;
ErrorExit:
if (FileDescriptors != NULL)
{
for (Index = 0; Index < FileDescriptorCount; Index += 1)
{
if (FileDescriptors[Index] >= 0)
{
LxtClose(FileDescriptors[Index]);
}
}
free(FileDescriptors);
}
if (ChildPid == 0)
{
_exit(Result);
}
else
{
unlink(LXT_RESOURCE_LIMIT_TEST_FILE);
}
}
int PrlimitTest(PLXT_ARGS Args)
{
struct __user_cap_data_struct CapData[2];
struct __user_cap_header_struct CapHeader;
int ChildPid;
int CurrentPid;
int Index;
struct rlimit NewLimit;
struct rlimit OldLimit;
int ParentPid;
int Result;
int Status;
ChildPid = -1;
ParentPid = getpid();
//
// Get and set all resource limits.
//
for (Index = 0; Index < 16; Index += 1)
{
LxtCheckErrno(LxtPrlimit64(0, Index, NULL, &NewLimit));
LxtCheckErrno(LxtPrlimit64(0, Index, &NewLimit, &OldLimit));
LxtCheckEqual(OldLimit.rlim_max, NewLimit.rlim_max, "%Iu");
LxtCheckEqual(OldLimit.rlim_cur, NewLimit.rlim_cur, "%Iu");
LxtCheckErrno(LxtPrlimit64(ParentPid, Index, &NewLimit, &OldLimit));
}
//
// Pid != 0 variations.
//
LxtCheckErrno(ChildPid = fork());
if (ChildPid == 0)
{
CurrentPid = getpid();
LxtCheckErrno(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, NULL, &NewLimit));
LxtCheckErrno(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, &NewLimit, &OldLimit));
LxtCheckErrno(LxtPrlimit64(CurrentPid, RLIMIT_NOFILE, NULL, &NewLimit));
LxtCheckErrno(LxtPrlimit64(CurrentPid, RLIMIT_NOFILE, &NewLimit, &OldLimit));
goto ErrorExit;
}
//
// Wait for the child to exit.
//
LxtCheckErrno(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
//
// UID variations.
//
LxtCheckErrno(ChildPid = fork());
if (ChildPid == 0)
{
memset(&CapData, 0, sizeof(CapData));
memset(&CapHeader, 0, sizeof(CapHeader));
CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
CapData[CAP_TO_INDEX(CAP_SETUID)].permitted |= CAP_TO_MASK(CAP_SETUID);
CapData[0].effective = CapData[0].permitted;
CapData[1].effective = CapData[1].permitted;
LxtCheckErrno(prctl(PR_SET_KEEPCAPS, 1));
LxtCheckErrno(LxtSetresuid(-1, -1, LXT_RESOURCE_LIMIT_UID));
LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
LxtCheckErrno(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, NULL, &NewLimit));
LxtCheckErrno(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, &NewLimit, &OldLimit));
LxtCheckErrno(LxtSetresuid(-1, LXT_RESOURCE_LIMIT_UID, -1));
LxtCheckErrno(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, NULL, &NewLimit));
LxtCheckErrno(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, &NewLimit, &OldLimit));
LxtCheckErrno(LxtSetresuid(LXT_RESOURCE_LIMIT_UID, -1, -1));
LxtCheckErrnoFailure(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, NULL, &NewLimit), EPERM);
LxtCheckErrnoFailure(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, &NewLimit, &OldLimit), EPERM);
CurrentPid = getpid();
LxtCheckErrno(LxtPrlimit64(CurrentPid, RLIMIT_NOFILE, NULL, &NewLimit));
LxtCheckErrno(LxtPrlimit64(CurrentPid, RLIMIT_NOFILE, &NewLimit, &OldLimit));
goto ErrorExit;
}
//
// Wait for the child to exit.
//
LxtCheckErrno(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
LxtCheckErrno(ChildPid = fork());
if (ChildPid == 0)
{
//
// Change the UID and verify that querying the parent's resource limits
// succeeds with the CAP_SYS_RESOURCE capability.
//
memset(&CapData, 0, sizeof(CapData));
memset(&CapHeader, 0, sizeof(CapHeader));
CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
CapData[CAP_TO_INDEX(CAP_SETUID)].permitted |= CAP_TO_MASK(CAP_SETUID);
CapData[CAP_TO_INDEX(CAP_SYS_RESOURCE)].permitted |= CAP_TO_MASK(CAP_SYS_RESOURCE);
CapData[0].effective = CapData[0].permitted;
CapData[1].effective = CapData[1].permitted;
LxtCheckErrno(prctl(PR_SET_KEEPCAPS, 1));
LxtCheckErrno(LxtSetresuid(LXT_RESOURCE_LIMIT_UID, LXT_RESOURCE_LIMIT_UID, LXT_RESOURCE_LIMIT_UID));
LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
LxtCheckErrno(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, NULL, &NewLimit));
LxtCheckErrno(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, &NewLimit, &OldLimit));
//
// Drop the CAP_SYS_RESOURCE capability and verify querying the parents
// resource limits fails.
//
memset(&CapData, 0, sizeof(CapData));
memset(&CapHeader, 0, sizeof(CapHeader));
CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
LxtCheckErrnoFailure(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, NULL, &NewLimit), EPERM);
LxtCheckErrnoFailure(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, &NewLimit, &OldLimit), EPERM);
CurrentPid = getpid();
LxtCheckErrno(LxtPrlimit64(CurrentPid, RLIMIT_NOFILE, NULL, &NewLimit));
LxtCheckErrno(LxtPrlimit64(CurrentPid, RLIMIT_NOFILE, &NewLimit, &OldLimit));
goto ErrorExit;
}
//
// Wait for the child to exit.
//
LxtCheckErrno(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
LxtCheckErrno(ChildPid = fork());
if (ChildPid == 0)
{
goto ErrorExit;
}
LxtCheckErrno(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
//
// GID variations.
//
LxtCheckErrno(ChildPid = fork());
if (ChildPid == 0)
{
memset(&CapData, 0, sizeof(CapData));
memset(&CapHeader, 0, sizeof(CapHeader));
CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
CapData[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID);
CapData[0].effective = CapData[0].permitted;
CapData[1].effective = CapData[1].permitted;
LxtCheckErrno(prctl(PR_SET_KEEPCAPS, 1));
LxtCheckErrno(LxtSetresgid(-1, -1, LXT_RESOURCE_LIMIT_GID));
LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
LxtCheckErrno(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, NULL, &NewLimit));
LxtCheckErrno(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, &NewLimit, &OldLimit));
LxtCheckErrno(LxtSetresgid(-1, LXT_RESOURCE_LIMIT_GID, -1));
LxtCheckErrno(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, NULL, &NewLimit));
LxtCheckErrno(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, &NewLimit, &OldLimit));
LxtCheckErrno(LxtSetresgid(LXT_RESOURCE_LIMIT_GID, -1, -1));
LxtCheckErrnoFailure(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, NULL, &NewLimit), EPERM);
LxtCheckErrnoFailure(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, &NewLimit, &OldLimit), EPERM);
CurrentPid = getpid();
LxtCheckErrno(LxtPrlimit64(CurrentPid, RLIMIT_NOFILE, NULL, &NewLimit));
LxtCheckErrno(LxtPrlimit64(CurrentPid, RLIMIT_NOFILE, &NewLimit, &OldLimit));
goto ErrorExit;
}
//
// Wait for the child to exit.
//
LxtCheckErrno(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
LxtCheckErrno(ChildPid = fork());
if (ChildPid == 0)
{
//
// Change the GID and verify that querying the parent's resource limits
// succeeds with the CAP_SYS_RESOURCE capability.
//
memset(&CapData, 0, sizeof(CapData));
memset(&CapHeader, 0, sizeof(CapHeader));
CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
CapData[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID);
CapData[CAP_TO_INDEX(CAP_SYS_RESOURCE)].permitted |= CAP_TO_MASK(CAP_SYS_RESOURCE);
CapData[0].effective = CapData[0].permitted;
CapData[1].effective = CapData[1].permitted;
LxtCheckErrno(prctl(PR_SET_KEEPCAPS, 1));
LxtCheckErrno(LxtSetresgid(LXT_RESOURCE_LIMIT_GID, LXT_RESOURCE_LIMIT_GID, LXT_RESOURCE_LIMIT_GID));
LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
LxtCheckErrno(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, NULL, &NewLimit));
LxtCheckErrno(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, &NewLimit, &OldLimit));
//
// Drop the CAP_SYS_RESOURCE capability and verify querying the parents
// resource limits fails.
//
memset(&CapData, 0, sizeof(CapData));
memset(&CapHeader, 0, sizeof(CapHeader));
CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
LxtCheckErrnoFailure(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, NULL, &NewLimit), EPERM);
LxtCheckErrnoFailure(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, &NewLimit, &OldLimit), EPERM);
CurrentPid = getpid();
LxtCheckErrno(LxtPrlimit64(CurrentPid, RLIMIT_NOFILE, NULL, &NewLimit));
LxtCheckErrno(LxtPrlimit64(CurrentPid, RLIMIT_NOFILE, &NewLimit, &OldLimit));
goto ErrorExit;
}
//
// Wait for the child to exit.
//
LxtCheckErrno(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
//
// The new limit should still be set even if old limit buffer is invalid.
//
LxtCheckErrno(LxtPrlimit64(0, RLIMIT_NOFILE, NULL, &OldLimit));
NewLimit = OldLimit;
NewLimit.rlim_cur -= 1;
LxtCheckErrnoFailure(LxtPrlimit64(0, RLIMIT_NOFILE, &NewLimit, -1), EFAULT);
LxtCheckErrno(LxtPrlimit64(0, RLIMIT_NOFILE, NULL, &NewLimit));
LxtCheckNotEqual(OldLimit.rlim_cur, NewLimit.rlim_cur, "%Iu");
//
// Verify that if the new limit is invalid, the old limit is not returned.
//
LxtCheckErrno(LxtPrlimit64(0, RLIMIT_NOFILE, NULL, &OldLimit));
NewLimit = OldLimit;
NewLimit.rlim_cur = NewLimit.rlim_max + 1;
memset(&OldLimit, 0, sizeof(OldLimit));
LxtCheckErrnoFailure(LxtPrlimit64(0, RLIMIT_NOFILE, &NewLimit, &OldLimit), EINVAL);
LxtCheckEqual(OldLimit.rlim_max, 0, "%Iu");
LxtCheckEqual(OldLimit.rlim_cur, 0, "%Iu");
LxtCheckErrnoFailure(LxtPrlimit64(0, RLIMIT_NOFILE, -1, &OldLimit), EFAULT);
LxtCheckEqual(OldLimit.rlim_max, 0, "%Iu");
LxtCheckEqual(OldLimit.rlim_cur, 0, "%Iu");
//
// Negative variations.
//
LxtCheckErrno(LxtPrlimit64(0, RLIMIT_NPROC, NULL, NULL));
LxtCheckErrnoFailure(LxtPrlimit64(0, 16, NULL, NULL), EINVAL);
LxtCheckErrnoFailure(LxtPrlimit64(-1, 16, NULL, NULL), ESRCH);
LxtCheckErrnoFailure(LxtPrlimit64(-1, RLIMIT_NPROC, NULL, NULL), ESRCH);
LxtCheckErrnoFailure(LxtPrlimit64(-1, RLIMIT_NPROC, -1, NULL), EFAULT);
LxtCheckErrnoFailure(LxtPrlimit64(-1, RLIMIT_NPROC, NULL, -1), ESRCH);
LxtCheckErrnoFailure(LxtPrlimit64(-1, RLIMIT_NPROC, -1, -1), EFAULT);
LxtCheckErrnoFailure(LxtPrlimit64(0, 16, NULL, &OldLimit), EINVAL);
LxtCheckErrnoFailure(LxtPrlimit64(0, RLIMIT_NPROC, -1, NULL), EFAULT);
LxtCheckErrnoFailure(LxtPrlimit64(0, RLIMIT_NPROC, NULL, -1), EFAULT);
LxtCheckErrnoFailure(LxtPrlimit64(0, RLIMIT_NPROC, -1, -1), EFAULT);
LxtCheckErrnoFailure(LxtPrlimit64(0, 16, -1, -1), EFAULT);
LxtCheckErrnoFailure(LxtPrlimit64(-1, 16, NULL, &OldLimit), ESRCH);
LxtCheckErrnoFailure(LxtPrlimit64(-1, RLIMIT_NPROC, -1, NULL), EFAULT);
LxtCheckErrnoFailure(LxtPrlimit64(-1, RLIMIT_NPROC, NULL, -1), ESRCH);
LxtCheckErrnoFailure(LxtPrlimit64(-1, RLIMIT_NPROC, -1, -1), EFAULT);
LxtCheckErrnoFailure(LxtPrlimit64(-1, 16, -1, -1), EFAULT);
ErrorExit:
if (ChildPid == 0)
{
_exit(Result);
}
return Result;
}