Add setpriority(2)/getpriority(2)

setpriority(2) is useful for limiting the impact of processes running in
a sandbox. It is also possible to exec the sandbox process using nice:

    alcove:execvp(Drv, Path, "/usr/bin/nice", ["/usr/bin/nice", "-n",
            "19", "sandbox"]).

The advantage of supporting set/getpriority natively in alcove are:

* nice doesn't need to exist in the sandbox chroot
* better error values (nice will return errors as a binary string)
* priorities can apply to fork trees
This commit is contained in:
Michael Santos
2014-12-01 11:20:48 -05:00
parent a6e0c5de49
commit b5f8fd36ff
4 changed files with 117 additions and 1 deletions

View File

@@ -20,6 +20,7 @@ gethostname/0
getopt/1
getpgrp/0
getpid/0
getpriority/2
getresgid/0
getresuid/0
getrlimit/1
@@ -47,6 +48,7 @@ sethostname/1
setns/1
setopt/2
setpgid/2
setpriority/3
setproctitle/1
setresgid/3
setresuid/3

View File

@@ -304,3 +304,103 @@ alcove_sys_setproctitle(alcove_state_t *ap, const char *arg, size_t len,
return alcove_mk_atom(reply, rlen, "ok");
#endif
}
/*
* getpriority(2)
*/
ssize_t
alcove_sys_getpriority(alcove_state_t *ap, const char *arg, size_t len,
char *reply, size_t rlen)
{
int index = 0;
int rindex = 0;
int which = 0;
int who = 0;
int prio = 0;
switch (alcove_decode_define(arg, len, &index, &which,
alcove_prio_constants)) {
case 0:
break;
case 1:
return alcove_mk_errno(reply, rlen, EINVAL);
case -1:
default:
return -1;
}
switch (alcove_decode_define(arg, len, &index, &who,
alcove_prio_constants)) {
case 0:
break;
case 1:
return alcove_mk_errno(reply, rlen, EINVAL);
case -1:
default:
return -1;
}
errno = 0;
prio = getpriority(which, who);
if (errno != 0)
return alcove_mk_errno(reply, rlen, errno);
ALCOVE_OK(reply, &rindex,
alcove_encode_long(reply, rlen, &rindex, prio));
return rindex;
}
/*
* setpriority(2)
*/
ssize_t
alcove_sys_setpriority(alcove_state_t *ap, const char *arg, size_t len,
char *reply, size_t rlen)
{
int index = 0;
int which = 0;
int who = 0;
int prio = 0;
switch (alcove_decode_define(arg, len, &index, &which,
alcove_prio_constants)) {
case 0:
break;
case 1:
return alcove_mk_errno(reply, rlen, EINVAL);
case -1:
default:
return -1;
}
switch (alcove_decode_define(arg, len, &index, &who,
alcove_prio_constants)) {
case 0:
break;
case 1:
return alcove_mk_errno(reply, rlen, EINVAL);
case -1:
default:
return -1;
}
if (alcove_decode_int(arg, len, &index, &prio) < 0)
return -1;
if (setpriority(which, who, prio) < 0)
return alcove_mk_errno(reply, rlen, errno);
return alcove_mk_atom(reply, rlen, "ok");
}

View File

@@ -272,3 +272,17 @@ const alcove_define_t alcove_prctl_constants[] = {
{NULL, 0}
};
const alcove_define_t alcove_prio_constants[] = {
#ifdef PRIO_PROCESS
ALCOVE_DEFINE(PRIO_PROCESS),
#endif
#ifdef PRIO_PPGRP
ALCOVE_DEFINE(PRIO_PGRP),
#endif
#ifdef PRIO_USER
ALCOVE_DEFINE(PRIO_USER),
#endif
{NULL, 0}
};

View File

@@ -1,7 +1,7 @@
{application, alcove,
[
{description, "Erlang application container/sandbox"},
{vsn, "0.14.0"},
{vsn, "0.14.1"},
{registered, []},
{applications, [
kernel,