From 13f09cc5150bda7b8d9aa2aaa0a0756a4bb091eb Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Fri, 30 Aug 2013 23:55:09 +0200 Subject: [PATCH] Add prlimit(2). --- libc/Makefile | 1 + libc/include/sys/resource.h | 2 ++ libc/sys/resource/prlimit.cpp | 41 ++++++++++++++++++++++++++ sortix/include/sortix/kernel/process.h | 5 ++++ sortix/include/sortix/resource.h | 26 ++++++++++++++++ sortix/include/sortix/syscallnum.h | 3 +- sortix/process.cpp | 12 ++++++++ sortix/resource.cpp | 36 ++++++++++++++++++++++ 8 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 libc/sys/resource/prlimit.cpp diff --git a/libc/Makefile b/libc/Makefile index 38354c9e..7cba2125 100644 --- a/libc/Makefile +++ b/libc/Makefile @@ -309,6 +309,7 @@ sys/mman/mprotect.o \ sys/mman/munmap.o \ sys/readdirents/readdirents.o \ sys/resource/getpriority.o \ +sys/resource/prlimit.o \ sys/resource/setpriority.o \ sys/select/select.o \ sys/socket/accept4.o \ diff --git a/libc/include/sys/resource.h b/libc/include/sys/resource.h index e14dc32e..d2502187 100644 --- a/libc/include/sys/resource.h +++ b/libc/include/sys/resource.h @@ -31,8 +31,10 @@ __BEGIN_DECLS @include(id_t.h) +@include(pid_t.h) int getpriority(int, id_t); +int prlimit(pid_t, int, const struct rlimit*, struct rlimit*); int setpriority(int, id_t, int); __END_DECLS diff --git a/libc/sys/resource/prlimit.cpp b/libc/sys/resource/prlimit.cpp new file mode 100644 index 00000000..30ec0b2c --- /dev/null +++ b/libc/sys/resource/prlimit.cpp @@ -0,0 +1,41 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + sys/resource/prlimit.cpp + Access and modify the resource limits of the given process. + +*******************************************************************************/ + +#include +#include + +DEFN_SYSCALL4(int, sys_prlimit, SYSCALL_PRLIMIT, + pid_t, + int, + const struct rlimit*, + struct rlimit*); + +extern "C" +int prlimit(pid_t pid, + int resource, + const struct rlimit* new_limit, + struct rlimit* old_limit) +{ + return sys_prlimit(pid, resource, new_limit, old_limit); +} diff --git a/sortix/include/sortix/kernel/process.h b/sortix/include/sortix/kernel/process.h index e8403d41..a38536dd 100644 --- a/sortix/include/sortix/kernel/process.h +++ b/sortix/include/sortix/kernel/process.h @@ -26,6 +26,7 @@ #define INCLUDE_SORTIX_KERNEL_PROCESS_H #include +#include #include #include @@ -91,6 +92,10 @@ private: Ref mtable; Ref dtable; +public: + kthread_mutex_t resource_limits_lock; + struct rlimit resource_limits[RLIMIT_NUM_DECLARED]; + public: void BootstrapTables(Ref dtable, Ref mtable); void BootstrapDirectories(Ref root); diff --git a/sortix/include/sortix/resource.h b/sortix/include/sortix/resource.h index 9adc821f..b6556077 100644 --- a/sortix/include/sortix/resource.h +++ b/sortix/include/sortix/resource.h @@ -26,6 +26,7 @@ #define INCLUDE_SORTIX_RESOURCE_H #include +#include <__/stdint.h> __BEGIN_DECLS @@ -33,6 +34,31 @@ __BEGIN_DECLS #define PRIO_PGRP 1 #define PRIO_USER 2 +typedef __uintmax_t rlim_t; + +#define RLIM_INFINITY __UINTMAX_MAX +#define RLIM_SAVED_CUR RLIM_INFINITY +#define RLIM_SAVED_MAX RLIM_INFINITY + +struct rlimit +{ + rlim_t rlim_cur; + rlim_t rlim_max; +}; + +#define RLIMIT_AS 0 +#define RLIMIT_CORE 1 +#define RLIMIT_CPU 2 +#define RLIMIT_DATA 3 +#define RLIMIT_FSIZE 4 +#define RLIMIT_NOFILE 5 +#define RLIMIT_STACK 6 +#define __RLIMIT_NUM_DECLARED 7 /* index of highest constant plus 1. */ + +#if !__STDC_HOSTED__ && defined(SORTIX_KERNEL) +#define RLIMIT_NUM_DECLARED __RLIMIT_NUM_DECLARED +#endif + __END_DECLS #endif diff --git a/sortix/include/sortix/syscallnum.h b/sortix/include/sortix/syscallnum.h index 3dbc5f07..2e27189e 100644 --- a/sortix/include/sortix/syscallnum.h +++ b/sortix/include/sortix/syscallnum.h @@ -142,6 +142,7 @@ #define SYSCALL_MUNMAP 118 #define SYSCALL_GETPRIORITY 119 #define SYSCALL_SETPRIORITY 120 -#define SYSCALL_MAX_NUM 121 /* index of highest constant + 1 */ +#define SYSCALL_PRLIMIT 121 +#define SYSCALL_MAX_NUM 122 /* index of highest constant + 1 */ #endif diff --git a/sortix/process.cpp b/sortix/process.cpp index 9106aba2..7965fb37 100644 --- a/sortix/process.cpp +++ b/sortix/process.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -105,6 +106,12 @@ Process::Process() umask = 0022; nicelock = KTHREAD_MUTEX_INITIALIZER; nice = 0; + resource_limits_lock = KTHREAD_MUTEX_INITIALIZER; + for ( size_t i = 0; i < RLIMIT_NUM_DECLARED; i++ ) + { + resource_limits[i].rlim_cur = RLIM_INFINITY; + resource_limits[i].rlim_max = RLIM_INFINITY; + } Time::InitializeProcessClocks(this); alarm_timer.Attach(Time::GetClock(CLOCK_MONOTONIC)); Put(this); @@ -649,6 +656,11 @@ Process* Process::Fork() kthread_mutex_unlock(&groupchildlock); // Initialize everything that is safe and can't fail. + kthread_mutex_lock(&resource_limits_lock); + for ( size_t i = 0; i < RLIMIT_NUM_DECLARED; i++ ) + clone->resource_limits[i] = resource_limits[i]; + kthread_mutex_unlock(&resource_limits_lock); + kthread_mutex_lock(&nicelock); clone->nice = nice; kthread_mutex_unlock(&nicelock); diff --git a/sortix/resource.cpp b/sortix/resource.cpp index 3b264032..08865936 100644 --- a/sortix/resource.cpp +++ b/sortix/resource.cpp @@ -29,6 +29,7 @@ #include +#include #include #include #include @@ -148,9 +149,44 @@ static int sys_setpriority(int which, id_t who, int prio) } } +static +int sys_prlimit(pid_t pid, + int resource, + const struct rlimit* user_new_limit, + struct rlimit* user_old_limit) +{ + if ( pid < 0 ) + return errno = EINVAL, -1; + if ( resource < 0 || RLIMIT_NUM_DECLARED <= resource ) + return errno = EINVAL, -1; + // TODO: If pid isn't the current process, then it could self-destruct at + // any time while we use it; there is no safe way to do this yet. + Process* process = pid ? Process::Get(pid) : CurrentProcess(); + if ( !process ) + return errno = ESRCH, -1; + ScopedLock lock(&process->resource_limits_lock); + struct rlimit* limit = &process->resource_limits[resource]; + if ( user_old_limit ) + { + if ( !CopyToUser(user_old_limit, limit, sizeof(struct rlimit)) ) + return -1; + } + if ( user_new_limit ) + { + struct rlimit new_limit; + if ( !CopyFromUser(&new_limit, user_new_limit, sizeof(struct rlimit)) ) + return -1; + if ( new_limit.rlim_max < new_limit.rlim_cur ) + return errno = EINVAL, -1; + *limit = new_limit; + } + return 0; +} + void Init() { Syscall::Register(SYSCALL_GETPRIORITY, (void*) sys_getpriority); + Syscall::Register(SYSCALL_PRLIMIT, (void*) sys_prlimit); Syscall::Register(SYSCALL_SETPRIORITY, (void*) sys_setpriority); }