mirror of
git://slackware.nl/current.git
synced 2025-01-15 15:41:54 +01:00
75a4a592e5
Mon Apr 25 13:37:00 UTC 2011 Slackware 13.37 x86_64 stable is released! Thanks to everyone who pitched in on this release: the Slackware team, the folks producing upstream code, and linuxquestions.org for providing a great forum for collaboration and testing. The ISOs are off to be replicated, a 6 CD-ROM 32-bit set and a dual-sided 32-bit/64-bit x86/x86_64 DVD. Please consider supporting the Slackware project by picking up a copy from store.slackware.com. We're taking pre-orders now, and offer a discount if you sign up for a subscription. As always, thanks to the Slackware community for testing, suggestions, and feedback. :-) Have fun!
239 lines
7.5 KiB
Diff
239 lines
7.5 KiB
Diff
Index: libmisc/limits.c
|
|
===================================================================
|
|
--- libmisc/limits.c (revision 3159)
|
|
+++ libmisc/limits.c (revision 3160)
|
|
@@ -33,6 +33,7 @@
|
|
/*
|
|
* Separated from setup.c. --marekm
|
|
* Resource limits thanks to Cristian Gafton.
|
|
+ * Enhancements of resource limit code by Thomas Orgis <thomas@orgis.org> ("thor").
|
|
*/
|
|
|
|
#include <config.h>
|
|
@@ -44,6 +45,7 @@
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <stdio.h>
|
|
+#include <ctype.h>
|
|
#include "prototypes.h"
|
|
#include "defines.h"
|
|
#include <pwd.h>
|
|
@@ -69,17 +71,37 @@
|
|
unsigned int multiplier)
|
|
{
|
|
struct rlimit rlim;
|
|
- long limit;
|
|
+ rlim_t limit;
|
|
|
|
- if (getlong (value, &limit) == 0) {
|
|
- return 0;
|
|
+ /* The "-" is special, not belonging to a strange negative limit.
|
|
+ It is infinity, in a controlled way. --thor */
|
|
+ if(value[0] == '-') {
|
|
+ limit = RLIM_INFINITY;
|
|
}
|
|
- limit *= multiplier;
|
|
- if (limit != (rlim_t) limit) {
|
|
- return 0;
|
|
+ else {
|
|
+ /* We cannot use getlong here because it fails when there
|
|
+ is more to the value than just this number!
|
|
+ Also, we are limited to base 10 here (hex numbers will not
|
|
+ work with the limit string parser as is anyway) --thor */
|
|
+ char *endptr;
|
|
+ long longlimit = strtol(value, &endptr, 10);
|
|
+ if ((0 == longlimit) && (value == endptr)) {
|
|
+ /* No argument at all. No-op.
|
|
+ We could instead throw an error, though. --thor */
|
|
+ return 0;
|
|
+ }
|
|
+ longlimit *= multiplier;
|
|
+ limit = (rlim_t)longlimit;
|
|
+ if(longlimit != limit)
|
|
+ {
|
|
+ /* Again, silent error handling... I left it that way.
|
|
+ Wouldn't screaming make more sense? --thor */
|
|
+ return 0;
|
|
+ }
|
|
}
|
|
- rlim.rlim_cur = (rlim_t) limit;
|
|
- rlim.rlim_max = (rlim_t) limit;
|
|
+
|
|
+ rlim.rlim_cur = limit;
|
|
+ rlim.rlim_max = limit;
|
|
if (setrlimit (resource, &rlim) != 0) {
|
|
return LOGIN_ERROR_RLIMIT;
|
|
}
|
|
@@ -199,6 +221,9 @@
|
|
* [Ii]: i = RLIMIT_NICE max nice value (0..39 translates to 20..-19)
|
|
* [Oo]: o = RLIMIT_RTPRIO max real time priority (linux/sched.h 0..MAX_RT_PRIO)
|
|
*
|
|
+ * Remember to extend the "no-limits" string below when adding a new limit...
|
|
+ * --thor
|
|
+ *
|
|
* Return value:
|
|
* 0 = okay, of course
|
|
* LOGIN_ERROR_RLIMIT = error setting some RLIMIT
|
|
@@ -214,7 +239,20 @@
|
|
bool reported = false;
|
|
|
|
pp = buf;
|
|
+ /* Skip leading whitespace. --thor */
|
|
+ while(*pp == ' ' || *pp == '\t') ++pp;
|
|
|
|
+ /* The special limit string "-" results in no limit for all known limits.
|
|
+ We achieve that by parsing a full limit string, parts of it being ignored
|
|
+ if a limit type is not known to the system.
|
|
+ Though, there will be complaining for unknown limit types. --thor */
|
|
+ if(strcmp(pp, "-") == 0) {
|
|
+ /* Remember to extend this, too, when adding new limits!
|
|
+ Oh... but "unlimited" does not make sense for umask, or does it?
|
|
+ --thor */
|
|
+ pp = "A- C- D- F- M- N- R- S- T- P- I- O-";
|
|
+ }
|
|
+
|
|
while ('\0' != *pp) {
|
|
switch (*pp++) {
|
|
#ifdef RLIMIT_AS
|
|
@@ -316,6 +354,10 @@
|
|
break;
|
|
default:
|
|
/* Only report invalid strings once */
|
|
+ /* Note: A string can be invalid just because a specific (theoretically
|
|
+ valid) setting is not supported by this build.
|
|
+ It is just a warning in syslog anyway. The line is still processed
|
|
+ --thor */
|
|
if (!reported) {
|
|
SYSLOG ((LOG_WARN,
|
|
"Invalid limit string: '%s'",
|
|
@@ -324,13 +366,51 @@
|
|
retval |= LOGIN_ERROR_RLIMIT;
|
|
}
|
|
}
|
|
+ /* After parsing one limit setting (or just complaining about it),
|
|
+ one still needs to skip its argument to prevent a bogus warning on
|
|
+ trying to parse that as limit specification.
|
|
+ So, let's skip all digits, "-" and our limited set of whitespace.
|
|
+ --thor */
|
|
+ while(isdigit(*pp) || *pp == '-' || *pp == ' ' || *pp == '\t') {
|
|
+ ++pp;
|
|
+ }
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
+/* Check if user uname is in the group gname.
|
|
+ * Can I be sure that gr_mem contains no UID as string?
|
|
+ * Returns true when user is in the group, false when not.
|
|
+ * Any error is treated as false. --thor
|
|
+ */
|
|
+static bool user_in_group (const char *uname, const char *gname)
|
|
+{
|
|
+ struct group *groupdata;
|
|
+ char **member;
|
|
+ if(uname == NULL || gname == NULL){
|
|
+ return false;
|
|
+ }
|
|
+ /* We are not claiming to be re-entrant!
|
|
+ * In case of paranoia or a multithreaded login program,
|
|
+ * one needs to add some mess for getgrnam_r. */
|
|
+ groupdata = getgrnam(gname);
|
|
+ if(groupdata == NULL) {
|
|
+ SYSLOG ((LOG_WARN, "Nonexisting group `%s' in limits file.", gname));
|
|
+ return false;
|
|
+ }
|
|
+ /* Now look for our user in the list of members. */
|
|
+ member = groupdata->gr_mem;
|
|
+ while(*member != NULL) {
|
|
+ if(strcmp(*member, uname) == 0) {
|
|
+ return true;
|
|
+ }
|
|
+ ++member;
|
|
+ }
|
|
+ return false;
|
|
+}
|
|
+
|
|
static int setup_user_limits (const char *uname)
|
|
{
|
|
- /* TODO: allow and use @group syntax --cristiang */
|
|
FILE *fil;
|
|
char buf[1024];
|
|
char name[1024];
|
|
@@ -352,7 +432,7 @@
|
|
}
|
|
/* The limits file have the following format:
|
|
* - '#' (comment) chars only as first chars on a line;
|
|
- * - username must start on first column
|
|
+ * - username must start on first column (or *, or @group --thor)
|
|
* A better (smarter) checking should be done --cristiang */
|
|
while (fgets (buf, 1024, fil) != NULL) {
|
|
if (('#' == buf[0]) || ('\n' == buf[0])) {
|
|
@@ -367,6 +447,13 @@
|
|
* Imposing a limit should be done with care, so a wrong
|
|
* entry means no care anyway :-). A '-' as a limits
|
|
* strings means no limits --cristiang */
|
|
+ /* In addition to the handling of * as name which was alrady present,
|
|
+ I added handling of the @group syntax.
|
|
+ To clarify: The first entry with matching user name rules,
|
|
+ everything after it is ignored. If there is no user entry,
|
|
+ the last encountered entry for a matching group rules.
|
|
+ If there is no matching group entry, the default limits rule.
|
|
+ --thor. */
|
|
if (sscanf (buf, "%s%[ACDFMNRSTULPIOacdfmnrstulpio0-9 \t-]",
|
|
name, tempbuf) == 2) {
|
|
if (strcmp (name, uname) == 0) {
|
|
@@ -374,6 +461,12 @@
|
|
break;
|
|
} else if (strcmp (name, "*") == 0) {
|
|
strcpy (deflimits, tempbuf);
|
|
+ } else if (name[0] == '@') {
|
|
+ /* If the user is in the group, the group limits apply unless
|
|
+ later a line for the specific user is found. --thor */
|
|
+ if(user_in_group(uname, name+1)) {
|
|
+ strcpy (limits, tempbuf);
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
Index: man/limits.5.xml
|
|
===================================================================
|
|
--- man/limits.5.xml (revision 3159)
|
|
+++ man/limits.5.xml (revision 3160)
|
|
@@ -64,7 +64,13 @@
|
|
<emphasis remap='I'>user LIMITS_STRING</emphasis>
|
|
</para>
|
|
|
|
+ <para>or in the form:</para>
|
|
+
|
|
<para>
|
|
+ <emphasis remap='I'>@group LIMITS_STRING</emphasis>
|
|
+ </para>
|
|
+
|
|
+ <para>
|
|
The <emphasis>LIMITS_STRING</emphasis> is a string of a concatenated
|
|
list of resource limits. Each limit consists of a letter identifier
|
|
followed by a numerical limit.
|
|
@@ -125,11 +131,23 @@
|
|
</para>
|
|
|
|
<para>
|
|
+ The limits specified in the form "<replaceable>@group</replaceable>"
|
|
+ apply to the members of the specified
|
|
+ <replaceable>group</replaceable>.
|
|
+ </para>
|
|
+
|
|
+ <para>
|
|
To completely disable limits for a user, a single dash
|
|
"<emphasis>-</emphasis>" will do.
|
|
</para>
|
|
|
|
<para>
|
|
+ To disable a limit for a user, a single dash
|
|
+ "<replaceable>-</replaceable>" can be used instead of the numerical
|
|
+ value for this limit.
|
|
+ </para>
|
|
+
|
|
+ <para>
|
|
Also, please note that all limit settings are set PER LOGIN. They are
|
|
not global, nor are they permanent. Perhaps global limits will come,
|
|
but for now this will have to do ;)
|