diff options
Diffstat (limited to 'source/a/shadow/patches/r3160.diff')
-rw-r--r-- | source/a/shadow/patches/r3160.diff | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/source/a/shadow/patches/r3160.diff b/source/a/shadow/patches/r3160.diff new file mode 100644 index 00000000..5aabbaa9 --- /dev/null +++ b/source/a/shadow/patches/r3160.diff @@ -0,0 +1,239 @@ +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 ;) |