[Pkg-shadow-commits] r3160 - in upstream/trunk: . libmisc man

Nicolas FRANÇOIS nekral-guest at alioth.debian.org
Thu Mar 18 23:20:16 UTC 2010


Author: nekral-guest
Date: 2010-03-18 23:20:15 +0000 (Thu, 18 Mar 2010)
New Revision: 3160

Modified:
   upstream/trunk/ChangeLog
   upstream/trunk/NEWS
   upstream/trunk/libmisc/limits.c
   upstream/trunk/man/limits.5.xml
Log:
	* NEWS, libmisc/limits.c: Fix parsing of limits.
	* NEWS, libmisc/limits.c, man/limits.5.xml: Add support for
	infinite limits.
	* NEWS, libmisc/limits.c, man/limits.5.xml: Add support for @group
	syntax.

Modified: upstream/trunk/ChangeLog
===================================================================
--- upstream/trunk/ChangeLog	2010-03-18 19:23:00 UTC (rev 3159)
+++ upstream/trunk/ChangeLog	2010-03-18 23:20:15 UTC (rev 3160)
@@ -1,3 +1,11 @@
+2010-03-18  Thomas Orgis  <thomas at orgis.org>
+
+	* NEWS, libmisc/limits.c: Fix parsing of limits.
+	* NEWS, libmisc/limits.c, man/limits.5.xml: Add support for
+	infinite limits.
+	* NEWS, libmisc/limits.c, man/limits.5.xml: Add support for @group
+	syntax.
+
 2010-03-18  Nicolas François  <nicolas.francois at centraliens.net>
 
 	* lib/tcbfuncs.h: Re-indent.

Modified: upstream/trunk/NEWS
===================================================================
--- upstream/trunk/NEWS	2010-03-18 19:23:00 UTC (rev 3159)
+++ upstream/trunk/NEWS	2010-03-18 23:20:15 UTC (rev 3160)
@@ -13,6 +13,10 @@
     specified.
 - groupmod
   * Fixed groupmod when configured with --enable-account-tools-setuid.
+-login
+  * Fixed limits support (non PAM enabled versions only)
+  * Added support for infinite limits and group based limits (non PAM
+    enabled versions only)
 - su
   * Document the su exit values.
   * When su receives a signal, wait for the child to terminate (after

Modified: upstream/trunk/libmisc/limits.c
===================================================================
--- upstream/trunk/libmisc/limits.c	2010-03-18 19:23:00 UTC (rev 3159)
+++ upstream/trunk/libmisc/limits.c	2010-03-18 23:20:15 UTC (rev 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 at 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);
+				}
 			}
 		}
 	}

Modified: upstream/trunk/man/limits.5.xml
===================================================================
--- upstream/trunk/man/limits.5.xml	2010-03-18 19:23:00 UTC (rev 3159)
+++ upstream/trunk/man/limits.5.xml	2010-03-18 23:20:15 UTC (rev 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 ;)




More information about the Pkg-shadow-commits mailing list