Package: pam
Version: 1.1.2-2
Severity: normal
Tags: patch
User: ubuntu-de...@lists.ubuntu.com
Usertags: origin-ubuntu natty ubuntu-patch

Currently PAM has hardcoded rlimit defaults. It should be loading these
from the kernel so that when the kernel changes, PAM does not need any
modification.

Attached is a potential fix, against the Ubuntu packaging...

Thanks,

-Kees

-- 
Kees Cook                                            @debian.org
diff -u pam-1.1.2/debian/changelog pam-1.1.2/debian/changelog
--- pam-1.1.2/debian/changelog
+++ pam-1.1.2/debian/changelog
@@ -1,3 +1,11 @@
+pam (1.1.2-2ubuntu7~kees1) natty; urgency=low
+
+  * debian/patches-applied/parse-kernel-rlimits.patch: actually parse the
+    kernel default rlimits instead of using internal defaults. Fall back
+    to internals for unknown rlimits. (LP: #746655, #391761)
+
+ -- Kees Cook <k...@ubuntu.com>  Thu, 31 Mar 2011 12:27:38 -0700
+
 pam (1.1.2-2ubuntu6) natty; urgency=low
 
   * debian/libpam0g.postinst: according to Kubuntu developers, kdm no longer
diff -u pam-1.1.2/debian/control pam-1.1.2/debian/control
--- pam-1.1.2/debian/control
+++ pam-1.1.2/debian/control
@@ -2,7 +2,7 @@
 Section: libs
 Priority: optional
 Uploaders: Sam Hartman <hartm...@debian.org>, Roger Leigh <rle...@debian.org>
-Maintainer: Ubuntu Core Developers <ubuntu-devel-disc...@lists.ubuntu.com>
+Maintainer: Ubuntu Developers <ubuntu-devel-disc...@lists.ubuntu.com>
 XSBC-Original-Maintainer: Steve Langasek <vor...@debian.org>
 Standards-Version: 3.9.1
 Build-Depends: libcrack2-dev (>= 2.8), bzip2, debhelper (>= 8.1.2ubuntu3), 
quilt (>= 0.48-1), flex, libdb-dev, libselinux1-dev [!hurd-i386 !kfreebsd-i386 
!kfreebsd-amd64 !netbsd-i386], po-debconf
diff -u pam-1.1.2/debian/patches-applied/series 
pam-1.1.2/debian/patches-applied/series
--- pam-1.1.2/debian/patches-applied/series
+++ pam-1.1.2/debian/patches-applied/series
@@ -27,0 +28 @@
+parse-kernel-rlimits.patch
only in patch2:
unchanged:
--- pam-1.1.2.orig/debian/patches-applied/parse-kernel-rlimits.patch
+++ pam-1.1.2/debian/patches-applied/parse-kernel-rlimits.patch
@@ -0,0 +1,206 @@
+Description: Since the kernel sets a number of dynamic rlimits based on the
+ system properities (e.g. physical memory for nproc), these rlimits should
+ be respected by PAM. Parse /proc/1/limits for the kernel-defined rlimits.
+Author: Kees Cook <k...@ubuntu.com>
+Bug-Ubuntu: https://launchpad.net/bugs/746655
+
+Index: pam-1.1.2/modules/pam_limits/pam_limits.c
+===================================================================
+--- pam-1.1.2.orig/modules/pam_limits/pam_limits.c     2011-03-31 
12:33:35.965260935 -0700
++++ pam-1.1.2/modules/pam_limits/pam_limits.c  2011-03-31 12:35:50.057084000 
-0700
+@@ -55,9 +55,10 @@
+ #define LIMITS_DEF_USER     0 /* limit was set by an user entry */
+ #define LIMITS_DEF_GROUP    1 /* limit was set by a group entry */
+ #define LIMITS_DEF_ALLGROUP 2 /* limit was set by a group entry */
+-#define LIMITS_DEF_ALL      3 /* limit was set by an default entry */
+-#define LIMITS_DEF_DEFAULT  4 /* limit was set by an default entry */
+-#define LIMITS_DEF_NONE     5 /* this limit was not set yet */
++#define LIMITS_DEF_ALL      3 /* limit was set by an all entry */
++#define LIMITS_DEF_DEFAULT  4 /* limit was set by an internal default entry */
++#define LIMITS_DEF_KERNEL   5 /* limit was set from /proc/1/limits */
++#define LIMITS_DEF_NONE     6 /* this limit was not set yet */
+ 
+ static const char *limits_def_names[] = {
+        "USER",
+@@ -65,6 +66,7 @@
+        "ALLGROUP",
+        "ALL",
+        "DEFAULT",
++       "KERNEL",
+        "NONE",
+        NULL
+ };
+@@ -296,7 +298,139 @@
+     return 0;
+ }
+ 
+-static int init_limits(struct pam_limit_s *pl)
++static const char * lnames[RLIM_NLIMITS] = {
++        [RLIMIT_CPU] = "Max cpu time",
++        [RLIMIT_FSIZE] = "Max file size",
++        [RLIMIT_DATA] = "Max data size",
++        [RLIMIT_STACK] = "Max stack size",
++        [RLIMIT_CORE] = "Max core file size",
++        [RLIMIT_RSS] = "Max resident set",
++        [RLIMIT_NPROC] = "Max processes",
++        [RLIMIT_NOFILE] = "Max open files",
++        [RLIMIT_MEMLOCK] = "Max locked memory",
++#ifdef RLIMIT_AS
++        [RLIMIT_AS] = "Max address space",
++#endif
++#ifdef RLIMIT_LOCKS
++        [RLIMIT_LOCKS] = "Max file locks",
++#endif
++#ifdef RLIMIT_SIGPENDING
++        [RLIMIT_SIGPENDING] = "Max pending signals",
++#endif
++#ifdef RLIMIT_MSGQUEUE
++        [RLIMIT_MSGQUEUE] = "Max msgqueue size",
++#endif
++#ifdef RLIMIT_NICE
++        [RLIMIT_NICE] = "Max nice priority",
++#endif
++#ifdef RLIMIT_RTPRIO
++        [RLIMIT_RTPRIO] = "Max realtime priority",
++#endif
++#ifdef RLIMIT_RTTIME
++        [RLIMIT_RTTIME] = "Max realtime timeout",
++#endif
++};
++
++static int str2rlimit(char *name) {
++    int i;
++    if (!name || *name == '\0')
++        return -1;
++    for(i = 0; i < RLIM_NLIMITS; i++) {
++        if (strcmp(name, lnames[i]) == 0) return i;
++    }
++    return -1;
++}
++
++static rlim_t str2rlim_t(char *value) {
++    unsigned long long rlimit = 0;
++
++    if (!value) return (rlim_t)rlimit;
++    if (strcmp(value, "unlimited") == 0) {
++        return RLIM_INFINITY;
++    }
++    rlimit = strtoull(value, NULL, 10);
++    return (rlim_t)rlimit;
++}
++
++#define LIMITS_SKIP_WHITESPACE { \
++        /* step backwards over spaces */ \
++        pos--; \
++        while (pos && line[pos] == ' ') pos--; \
++        if (!pos) continue; \
++        line[pos+1] = '\0'; \
++}
++#define LIMITS_MARK_ITEM(item) { \
++        /* step backwards over non-spaces */ \
++        pos--; \
++        while (pos && line[pos] != ' ') pos--; \
++        if (!pos) continue; \
++        item = line + pos + 1; \
++}
++
++static void parse_kernel_limits(pam_handle_t *pamh, struct pam_limit_s *pl)
++{
++    int i, maxlen = 0;
++    FILE *limitsfile;
++    const char *proclimits = "/proc/1/limits";
++    char line[256];
++    char *units, *hard, *soft, *name;
++
++    if (!(limitsfile = fopen(proclimits, "r"))) {
++        pam_syslog(pamh, LOG_WARNING, "Could not read %s (%s), using PAM 
internal defaults", proclimits, strerror(errno));
++        return;
++    }
++
++    while (fgets(line, 256, limitsfile)) {
++        int pos = strlen(line);
++        if (pos < 2) continue;
++
++        /* drop trailing newline */
++        if (line[pos-1] == '\n') {
++            pos--;
++            line[pos] = '\0';
++        }
++
++        /* determine formatting boundry of limits report */
++        if (!maxlen && strncmp(line, "Limit", 5) == 0) {
++            maxlen = pos;
++            continue;
++        }
++
++        if (pos == maxlen) {
++            /* step backwards over "Units" name */
++            LIMITS_SKIP_WHITESPACE;
++            LIMITS_MARK_ITEM(units);
++        }
++        else {
++            units = "";
++        }
++
++        /* step backwards over "Hard Limit" value */
++        LIMITS_SKIP_WHITESPACE;
++        LIMITS_MARK_ITEM(hard);
++
++        /* step backwards over "Soft Limit" value */
++        LIMITS_SKIP_WHITESPACE;
++        LIMITS_MARK_ITEM(soft);
++
++        /* step backwards over name of limit */
++        LIMITS_SKIP_WHITESPACE;
++        name = line;
++
++        i = str2rlimit(name);
++        if (i < 0 || i >= RLIM_NLIMITS) {
++            pam_syslog(pamh, LOG_DEBUG, "Unknown kernel rlimit '%s' ignored", 
name);
++            continue;
++        }
++        pl->limits[i].limit.rlim_cur = str2rlim_t(soft);
++        pl->limits[i].limit.rlim_max = str2rlim_t(hard);
++        pl->limits[i].src_soft = LIMITS_DEF_KERNEL;
++        pl->limits[i].src_hard = LIMITS_DEF_KERNEL;
++    }
++    fclose(limitsfile);
++}
++
++static int init_limits(pam_handle_t *pamh, struct pam_limit_s *pl)
+ {
+     int i;
+     int retval = PAM_SUCCESS;
+@@ -321,6 +455,23 @@
+           }
+       } else {
+           pl->limits[i].supported = 1;
++          pl->limits[i].src_soft = LIMITS_DEF_NONE;
++          pl->limits[i].src_hard = LIMITS_DEF_NONE;
++      }
++    }
++
++#ifdef __linux__
++    parse_kernel_limits(pamh, pl);
++#endif
++
++    for(i = 0; i < RLIM_NLIMITS; i++) {
++      if (pl->limits[i].supported &&
++          (pl->limits[i].src_soft == LIMITS_DEF_NONE ||
++           pl->limits[i].src_hard == LIMITS_DEF_NONE)) {
++#ifdef __linux__
++          pam_syslog(pamh, LOG_WARNING, "Did not find kernel RLIMIT for %s, 
using PAM internal default", rlimit2str(i));
++#endif
++
+           pl->limits[i].src_soft = LIMITS_DEF_DEFAULT;
+           pl->limits[i].src_hard = LIMITS_DEF_DEFAULT;
+           switch(i) {
+@@ -829,7 +980,7 @@
+         return PAM_USER_UNKNOWN;
+     }
+ 
+-    retval = init_limits(pl);
++    retval = init_limits(pamh, pl);
+     if (retval != PAM_SUCCESS) {
+         pam_syslog(pamh, LOG_WARNING, "cannot initialize");
+         return PAM_ABORT;

Reply via email to