]> granicus.if.org Git - linux-pam/commitdiff
Relevant BUGIDs: 476990
authorAndrew G. Morgan <morgan@kernel.org>
Sun, 11 Nov 2001 07:25:37 +0000 (07:25 +0000)
committerAndrew G. Morgan <morgan@kernel.org>
Sun, 11 Nov 2001 07:25:37 +0000 (07:25 +0000)
Purpose of commit: new feature

Commit summary:
---------------
support -ve process priorities (and include superuser in this feature)

CHANGELOG
doc/modules/pam_limits.sgml
modules/pam_limits/README
modules/pam_limits/pam_limits.c

index 1d268f9201793ed8250956ddf900bda29dcc889e..fde469939d7902c4abfac16ae9756b21ff8f14d1 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -49,6 +49,9 @@ bug report - outstanding bugs are listed here:
 0.76: please submit patches for this section with actual code/doc
       patches!
 
+* pam_limits can handle negative priority limits now (which can apply
+  to the superuser too) - base on patch from Nalin. (Bug 476990 -
+  agmorgan)
 * db3 is now recognized as a libdb candidate (Bug 435764 - agmorgan)
 * more changes (extracted from redhat version) courtesy of
   Harald Welte (Bugs pam_limits=436061, pam_lastlog=436060,
index 52b8771f6066b30b4caf156b5286a6faa2e128ac..961f0b5564fc6ce7b4a0f81a07853ac048c87dab 100644 (file)
@@ -1,7 +1,7 @@
 <!--
    $Id$
    
-   This file was written by Andrew G. Morgan <morgan@parc.power.net>
+   This file was written by Andrew G. Morgan <morgan@kernel.org>
    from information compiled by Cristian Gafton (author of module)
 -->
 
@@ -140,8 +140,11 @@ together.
 <item><tt/cpu/ - max CPU time (MIN)
 <item><tt/nproc/ - max number of processes
 <item><tt/as/ - address space limit
-<item><tt/maxlogins/ - max number of logins for this user.
-<item><tt/priority/ - the priority to run user process with
+<item><tt/maxlogins/ - max number of logins for this user
+<item><tt/maxsyslogins/ - max number of logins on system
+<item><tt/priority/ - the priority to run user process with (negative
+values boost process priority)
+<item><tt/locks/ - max locked files (Linux 2.4 and higher)
 </itemize>
 
 <p>
index d2998b006d81be6a360eb30925ad9f6963b1df04..c0dba5817e78c9f0b5f20a59d0056cf385c26b3d 100644 (file)
@@ -37,6 +37,7 @@ Where:
        - as - address space limit
        - maxlogins - max number of logins for this user
        - maxsyslogins - max number of logins on the system
+       - priority - lower the priority by given value (value can be -ve)
        - locks - max locked files (Linux 2.4 and higher)
 
 Note, if you specify a type of '-' but neglect to supply the item and
index 99c45626d68356e8fa07bceda68a46b26eeff300..303ed661a916976ece4069e3522328bc05c774d1 100644 (file)
@@ -135,8 +135,9 @@ static int _pam_parse(int argc, const char **argv, struct pam_limit_s *pl)
 # define LIMITS_FILE "/etc/security/limits.conf"
 #endif
 
-#define LIMIT_ERR 1 /* error setting a limit */
-#define LOGIN_ERR 2 /* too many logins err */
+#define LIMITED_OK 0 /* limit setting appeared to work */
+#define LIMIT_ERR  1 /* error setting a limit */
+#define LOGIN_ERR  2 /* too many logins err */
 
 /* checks if a user is on a list of members of the GID 0 group */
 static int is_on_list(char * const *list, const char *member)
@@ -341,6 +342,7 @@ static void process_limit(int source, const char *lim_type,
      */
     limit_value = strtol(lim_value, endptr, 10);
 
+    /* special case value when limiting logins */
     if (limit_value == 0 && value_orig == *endptr) { /* no chars read */
         if (strcmp(lim_value,"-") != 0) {
             _pam_log(LOG_DEBUG,"wrong limit value '%s'", lim_value);
@@ -390,10 +392,9 @@ static void process_limit(int source, const char *lim_type,
             }
        }
     } else {
-       if (limit_item == LIMIT_PRI) {
-               /* additional check */
-               pl->priority = ((limit_value>0)?limit_value:0);
-       } else {
+       /* recent kernels support negative priority limits (=raise priority) */
+
+       if (limit_item != LIMIT_PRI) {
                if (pl->login_limit_def < source) {
                    return;
                } else {
@@ -503,34 +504,53 @@ static int parse_config_file(const char *uname, int ctrl,
     return PAM_SUCCESS;    
 }
 
-static int setup_limits(const char * uname, int ctrl, struct pam_limit_s *pl)
+static int setup_limits(const char * uname, uid_t uid, int ctrl,
+                       struct pam_limit_s *pl)
 {
     int i;
-    int retval = PAM_SUCCESS;
-    
-    for (i=0; i<RLIM_NLIMITS; i++) {
+    int status;
+    int retval = LIMITED_OK;
+
+    if (uid == 0) {
+       /* do not impose limits (+ve limits anyway) on the superuser */
+       if (pl->priority > 0) {
+           if (ctrl & PAM_DEBUG_ARG) {
+               _pam_log(LOG_DEBUG, "user '%s' has UID 0 - no limits imposed",
+                        uname);
+           }
+            pl->priority = 0;
+       }
+    }
+
+    for (i=0, status=LIMITED_OK; i<RLIM_NLIMITS; i++) {
         if (pl->limits[i].limit.rlim_cur > pl->limits[i].limit.rlim_max)
             pl->limits[i].limit.rlim_cur = pl->limits[i].limit.rlim_max;
        if (!pl->supported[i]) {
            /* skip it if its not known to the system */
            continue;
        }
-       retval |= setrlimit(i, &pl->limits[i].limit);
+       status |= setrlimit(i, &pl->limits[i].limit);
     }
     
-    if (retval != PAM_SUCCESS)
+    if (status) {
         retval = LIMIT_ERR;
+    }
 
-    retval=setpriority(PRIO_PROCESS, 0, pl->priority);
-    
-    if (retval != PAM_SUCCESS)
+    status = setpriority(PRIO_PROCESS, 0, pl->priority);
+    if (status != 0) {
         retval = LIMIT_ERR;
+    }
 
-    if (pl->login_limit > 0) {
-        if (check_logins(uname, pl->login_limit, ctrl, pl) == LOGIN_ERR)
+    if (uid == 0) {
+       D(("skip login limit check for uid=0"));
+    } else if (pl->login_limit > 0) {
+        if (check_logins(uname, pl->login_limit, ctrl, pl) == LOGIN_ERR) {
             retval |= LOGIN_ERR;
-    } else if (pl->login_limit == 0)
+       }
+    } else if (pl->login_limit == 0) {
         retval |= LOGIN_ERR;
+    }
+
     return retval;
 }
             
@@ -563,14 +583,6 @@ PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags,
         return PAM_SESSION_ERR;
     }
                      
-    /* do not impose limits on UID 0 accounts */
-    if (!pwd->pw_uid) {
-        if (ctrl & PAM_DEBUG_ARG)
-            _pam_log(LOG_DEBUG, "user '%s' have UID 0 - no limits imposed",
-                                user_name);
-        return PAM_SUCCESS;
-    }
-        
     retval = init_limits(&pl);
     if (retval != PAM_SUCCESS) {
         _pam_log(LOG_WARNING, "cannot initialize");
@@ -587,10 +599,11 @@ PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags,
         return PAM_IGNORE;
     }
 
-    if (ctrl & PAM_DO_SETREUID)
+    if (ctrl & PAM_DO_SETREUID) {
        setreuid(pwd->pw_uid, -1);
-    retval = setup_limits(pwd->pw_name, ctrl, &pl);
-    if (retval & LOGIN_ERR) {
+    }
+    retval = setup_limits(pwd->pw_name, pwd->pw_uid, ctrl, &pl);
+    if (retval != LIMITED_OK) {
         return PAM_PERM_DENIED;
     }