Skip to content

Commit

Permalink
Add limit subcommand
Browse files Browse the repository at this point in the history
  • Loading branch information
CRKatri committed Jan 17, 2023
1 parent 6b52906 commit b64b4f9
Show file tree
Hide file tree
Showing 8 changed files with 170 additions and 8 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
*.dylib
launchctl
a.out
*.dSYM

compile_commands.json
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ DESTDIR ?=

SRC := launchctl.c xpc_helper.c start_stop.c print.c env.c load.c manager.c
SRC += enable.c reboot.c bootstrap.c error.c remove.c kickstart.c kill.c blame.c
SRC += attach.c plist.c runstats.c userswitch.c
SRC += attach.c plist.c runstats.c userswitch.c limit.c
LDLIBS :=

all: launchctl
Expand Down
2 changes: 1 addition & 1 deletion TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
1. [ ] procinfo
1. [ ] hostinfo
1. [ ] resolveport
1. [ ] limit
1. [x] limit
1. [x] runstats
1. [x] examine
1. [x] config
Expand Down
2 changes: 1 addition & 1 deletion launchctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ static const struct {
{ "procinfo", "Prints port information about a process.", "<pid>", todo_cmd },
{ "hostinfo", "Prints port information about the host.", NULL, todo_cmd },
{ "resolveport", "Resolves a port name from a process to an endpoint in launchd.", "<owner-pid> <port-name>", todo_cmd },
{ "limit", "Reads or modifies launchd's resource limits.", "[<limit-name> [<both-limits> | <soft-limit> <hard-limit>]", todo_cmd },
{ "limit", "Reads or modifies launchd's resource limits.", "[<limit-name> [<both-limits> | <soft-limit> <hard-limit>]", limit_cmd },
{ "runstats", "Prints performance statistics for a service.", "<service-target>", runstats_cmd },
{ "examine", "Runs the specified analysis tool against launchd in a non-reentrant manner.", "[<tool> [arg0, arg1, ... , @PID, ...]]", examine_cmd },
{ "config", "Modifies persistent configuration parameters for launchd domains.", NULL, config_cmd },
Expand Down
3 changes: 3 additions & 0 deletions launchctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ cmd_main runstats_cmd;
// userswitch.c
cmd_main userswitch_cmd;

// limit.c
cmd_main limit_cmd;

void launchctl_xpc_object_print(xpc_object_t, const char *name, int level);
int launchctl_send_xpc_to_launchd(uint64_t routine, xpc_object_t msg, xpc_object_t *reply);
void launchctl_setup_xpc_dict(xpc_object_t dict);
Expand Down
151 changes: 151 additions & 0 deletions limit.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2023 Procursus Team <[email protected]>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <errno.h>

#include <xpc/xpc.h>
#include "xpc_private.h"

#include "launchctl.h"

static int64_t
limit_index(const char *name)
{
const char *limitnames[9] = {
"cpu",
"filesize",
"data",
"stack",
"core",
"rss",
"memlock",
"maxproc",
"maxfiles"
};
for (int i = 0; i < (sizeof(limitnames) / sizeof(limitnames[0])); i++) {
if (strcmp(name, limitnames[i]) == 0) {
return i;
}
}
return -1;
}

static long long
parse_limit(const char *name)
{
long long num;
char *end;

if (strcmp(name, "unlimited") == 0) {
errno = 0;
return -1;
}

num = strtoll(name, &end, 0);

if (end[0] != '\0') {
errno = EINVAL;
return -1;
}

return num;
}

int
limit_cmd(xpc_object_t *msg, int argc, char **argv, char **envp, char **apple)
{
if (argc > 4)
return EUSAGE;

xpc_object_t dict, reply;
int err = 0;
vm_address_t addr;
vm_size_t sz = 0x100000;
long long softlimit, hardlimit, idx;

dict = xpc_dictionary_create(NULL, NULL, 0);
*msg = dict;

launchctl_setup_xpc_dict_for_service_name("system", dict, NULL);

if (argc < 2) {
printlimits:
xpc_dictionary_set_bool(dict, "print", true);

if (__isPlatformVersionAtLeast(2, 15, 0, 0)) {
addr = launchctl_create_shmem(dict, sz);
} else {
xpc_dictionary_set_fd(dict, "file", STDOUT_FILENO);
}

err = launchctl_send_xpc_to_launchd(XPC_ROUTINE_LIMIT, dict, &reply);
if (err != 0) {
fprintf(stderr, "Could not print resource limits: %d: %s\n", err, xpc_strerror(err));
}

if (__isPlatformVersionAtLeast(2, 15, 0, 0)) {
launchctl_print_shmem(reply, addr, sz, stdout);
vm_deallocate(mach_task_self(), addr, sz);
}
} else {
if ((idx = limit_index(argv[1])) == -1) {
fprintf(stderr, "%s is not a valid limit name.\n", argv[1]);
return EUSAGE;
}

xpc_dictionary_set_int64(dict, "which", idx);

if (argc < 3) {
goto printlimits;
}

softlimit = parse_limit(argv[2]);
if (softlimit == -1 && errno != 0) {
fprintf(stderr, "%s is not a valid limit.\n", argv[2]);
return EUSAGE;
}
hardlimit = softlimit;

if (argc > 3) {
hardlimit = parse_limit(argv[3]);
if (hardlimit == -1 && errno != 0) {
fprintf(stderr, "%s is not a valid limit.\n", argv[3]);
return EUSAGE;
}
}

xpc_dictionary_set_int64(dict, "softlimit", softlimit);
xpc_dictionary_set_int64(dict, "hardlimit", hardlimit);

err = launchctl_send_xpc_to_launchd(XPC_ROUTINE_LIMIT, dict, &reply);
if (err != 0) {
fprintf(stderr, "Could not set resource limits: %d: %s\n", err, xpc_strerror(err));
}
}

return err;
}
14 changes: 10 additions & 4 deletions xpc_helper.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2022 Procursus Team <[email protected]>
* Copyright (c) 2022-2023 Procursus Team <[email protected]>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -132,7 +132,9 @@ launchctl_setup_xpc_dict(xpc_object_t dict)
int
launchctl_setup_xpc_dict_for_service_name(char *servicetarget, xpc_object_t dict, const char **name)
{
*name = NULL;
if (name != NULL) {
*name = NULL;
}
const char *split[3] = {NULL, NULL, NULL};
for (int i = 0; i < 3; i++) {
char *var = strsep(&servicetarget, "/");
Expand All @@ -147,7 +149,9 @@ launchctl_setup_xpc_dict_for_service_name(char *servicetarget, xpc_object_t dict
xpc_dictionary_set_uint64(dict, "handle", 0);
if (split[1] != NULL && split[1][0] != '\0') {
xpc_dictionary_set_string(dict, "name", split[1]);
*name = split[1];
if (name != NULL) {
*name = split[1];
}
}
return 0;
} else if (strcmp(split[0], "user") == 0) {
Expand All @@ -164,7 +168,9 @@ launchctl_setup_xpc_dict_for_service_name(char *servicetarget, xpc_object_t dict
xpc_dictionary_set_uint64(dict, "handle", handle);
if (split[2] != NULL && split[2][0] != '\0') {
xpc_dictionary_set_string(dict, "name", split[2]);
*name = split[2];
if (name != NULL) {
*name = split[2];
}
}
return 0;
}
Expand Down
3 changes: 2 additions & 1 deletion xpc_private.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2022 Procursus Team <[email protected]>
* Copyright (c) 2022-2023 Procursus Team <[email protected]>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -50,6 +50,7 @@ enum {
XPC_ROUTINE_REMOVE = 816,
XPC_ROUTINE_SETENV = 819,
XPC_ROUTINE_GETENV = 820,
XPC_ROUTINE_LIMIT = 825,
XPC_ROUTINE_EXAMINE = 826,
XPC_ROUTINE_PRINT = 828,
XPC_ROUTINE_DUMPSTATE = 834,
Expand Down

0 comments on commit b64b4f9

Please sign in to comment.