]> granicus.if.org Git - linux-pam/commitdiff
Relevant BUGIDs:
authorTomas Mraz <tm@t8m.info>
Fri, 1 Feb 2008 16:22:23 +0000 (16:22 +0000)
committerTomas Mraz <tm@t8m.info>
Fri, 1 Feb 2008 16:22:23 +0000 (16:22 +0000)
Purpose of commit: new feature

Commit summary:
---------------
2008-02-01  Tomas Mraz  <t8m@centrum.cz>

        * modules/pam_namespace/namespace.conf.5.xml: Add documentation for
        tmpfs and tmpdir polyinst and for ~ user list modifier.
        * modules/pam_namespace/namespace.init: Add documentation for the
        new init parameter. Add home directory initialization script.
        * modules/pam_namespace/pam_namespace.8.xml: Document the new
        init parameter of the namespace.init script.
        * modules/pam_namespace/pam_namespace.c(copy_ent): Copy exclusive flag.
        (cleanup_data): New function.
        (process_line): Set exclusive flag. Add tmpfs and tmpdir methods.
        (ns_override): Change behavior on the exclusive flag.
        (poly_name): Process tmpfs and tmpdir methods.
        (inst_init): Add flag for new directory initialization.
        (create_dirs): Process the tmpdir method, add the new directory
        flag.
        (ns_setup): Remove unused code. Process the tmpfs method.
        (cleanup_tmpdirs): New function.
        (setup_namespace): Set data for proper cleanup. Cleanup the tmpdirs
        on failures.
        (pam_sm_close_session): Instead of parsing the config file again use
        the previously set data for cleanup.
        * modules/pam_namespace/pam_namespace.h: Add TMPFS and TMPDIR methods
        and exclusive flag.

ChangeLog
NEWS
modules/pam_namespace/namespace.conf.5.xml
modules/pam_namespace/namespace.init
modules/pam_namespace/pam_namespace.8.xml
modules/pam_namespace/pam_namespace.c
modules/pam_namespace/pam_namespace.h

index 86adc7314e221f8b4c5dc4413e978bcd096989f2..f42dd1d391ff1ff7d5df63a6f3f4ef326b15e784 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,28 @@
+2008-02-01  Tomas Mraz  <t8m@centrum.cz>
+
+       * modules/pam_namespace/namespace.conf.5.xml: Add documentation for
+       tmpfs and tmpdir polyinst and for ~ user list modifier.
+       * modules/pam_namespace/namespace.init: Add documentation for the
+       new init parameter. Add home directory initialization script.
+       * modules/pam_namespace/pam_namespace.8.xml: Document the new
+       init parameter of the namespace.init script.
+       * modules/pam_namespace/pam_namespace.c(copy_ent): Copy exclusive flag.
+       (cleanup_data): New function.
+       (process_line): Set exclusive flag. Add tmpfs and tmpdir methods.
+       (ns_override): Change behavior on the exclusive flag.
+       (poly_name): Process tmpfs and tmpdir methods.
+       (inst_init): Add flag for new directory initialization.
+       (create_dirs): Process the tmpdir method, add the new directory
+       flag.
+       (ns_setup): Remove unused code. Process the tmpfs method.
+       (cleanup_tmpdirs): New function.
+       (setup_namespace): Set data for proper cleanup. Cleanup the tmpdirs
+       on failures.
+       (pam_sm_close_session): Instead of parsing the config file again use
+       the previously set data for cleanup.
+       * modules/pam_namespace/pam_namespace.h: Add TMPFS and TMPDIR methods
+       and exclusive flag.
+
 2008-01-29  Tomas Mraz  <t8m@centrum.cz>
 
        * configure.in: Test for setkeycreatecon needs libselinux.
diff --git a/NEWS b/NEWS
index edd84e384f208348f6ed68b43282d3e9129bf3c5..6ba96793fba0d5b838ea1edfc6ce237167315946 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -10,6 +10,7 @@ Linux-PAM NEWS -- history of user-visible changes.
   by crypt().
 * New pam_sepermit.so module for allowing/rejecting access based on
   SELinux mode.
+* Improved functionality of pam_namespace.so module.
 
 Release 0.99.9.0
 * misc_conv no longer blocks SIGINT; applications that don't want
index db48cdcb97b6e5009e9b5bd7d7acf2aa1e87a6d4..9fbefc49d010614c2f87299fae532937b126715a 100644 (file)
 
     <para>
       The third field, <replaceable>method</replaceable>, is the method
-      used for polyinstantiation. It can take 3 different values; "user"
+      used for polyinstantiation. It can take these values; "user"
       for polyinstantiation based on user name, "level" for 
-      polyinstantiation based on process MLS level and user name, and "context" for
-      polyinstantiation based on process security context and user name
+      polyinstantiation based on process MLS level and user name, "context" for
+      polyinstantiation based on process security context and user name,
+      "tmpfs" for mounting tmpfs filesystem as an instance dir, and
+      "tmpdir" for creating temporary directory as an instance dir which is
+      removed when the user's session is closed.
       Methods "context" and "level" are only available with SELinux. This
       field cannot be blank.
     </para>
@@ -84,7 +87,8 @@
       The fourth field, <replaceable>list_of_uids</replaceable>, is
       a comma separated list of user names for whom the polyinstantiation
       is not performed. If left blank, polyinstantiation will be performed
-      for all users.
+      for all users. If the list is preceded with a single "~" character,
+      polyinstantiation is performed only for users in the list.
     </para>
 
     <para>
index 0e9be68f9c23529ea6a303e3080b40877088204a..424c6d0ca572e95ef6c3ececdb0dbebce0c0a2e5 100755 (executable)
@@ -1,24 +1,24 @@
 #!/bin/sh -p
-# This is only a boilerplate for the instance initialization script.
-# It receives polydir path as $1 and the instance path as $2.
+# It receives polydir path as $1, the instance path as $2, 
+# a flag whether the instance dir was newly created (0 - no, 1 - yes) in $3,
+# and user name in $4.
 #
-# If you intend to polyinstantiate /tmp and you also want to use the X windows
-# environment, you will have to use this script to bind mount the socket that
-# is used by the X server to communicate with its clients. X server places
-# this socket in /tmp/.X11-unix directory, which will get obscured by
-# polyinstantiation. Uncommenting the following lines will bind mount
-# the relevant directory at an alternative location (/.tmp/.X11-unix) such
-# that the X server, window manager and X clients, can still find the
-# socket X0 at the polyinstanted /tmp/.X11-unix.
-#
-#if [ $1 = /tmp ]; then
-#      if [ ! -f /.tmp/.X11-unix ]; then
-#              mkdir -p /.tmp/.X11-unix
-#      fi
-#      mount --bind /tmp/.X11-unix /.tmp/.X11-unix
-#      cp -fp -- /tmp/.X0-lock "$2/.X0-lock"
-#      mkdir -- "$2/.X11-unix"
-#      ln -fs -- /.tmp/.X11-unix/X0 "$2/.X11-unix/X0"
-#fi
+# The following section will copy the contents of /etc/skel if this is a
+# newly created home directory.
+if [ "$3" = 1 ]; then
+        # This line will fix the labeling on all newly created directories
+        [ -x /sbin/restorecon ] && /sbin/restorecon "$1"
+        user="$4"
+        passwd=$(getent passwd "$user")
+        homedir=$(echo "$passwd" | cut -f6 -d":")
+        if [ "$1" = "$homedir" ]; then
+                gid=$(echo "$passwd" | cut -f4 -d":")
+                cp -rT /etc/skel "$homedir"
+                chown -R "$user":"$gid" "$homedir"
+                mode=$(awk '/^UMASK/{gsub("#.*$", "", $2); printf "%o", and(0777,compl(strtonum("0" $2))); exit}' /etc/login.defs)
+                chmod ${mode:-700} "$homedir"
+                [ -x /sbin/restorecon ] && /sbin/restorecon -R "$homedir"
+        fi
+fi
 
 exit 0
index e1b307ae4120c2e9e9cbba7d3d6e5a07ad80b687..f47bb81b8098267c707f8e28b3a3b49ba3517493 100644 (file)
@@ -60,7 +60,9 @@
       script <filename>/etc/security/namespace.init</filename> exists, it
       is used to initialize the namespace every time a new instance
       directory is setup. The script receives the polyinstantiated
-      directory path and the instance directory path as its arguments.
+      directory path, the instance directory path, flag whether the instance
+      directory was newly created (0 for no, 1 for yes), and the user name
+      as its arguments.
     </para>
 
     <para>
index d3612f59f6cda7db0c2c6033f877490b39b40b49..a47b0698d014b434b51c9bab4a08e7e7061d7d9a 100644 (file)
@@ -43,6 +43,7 @@ static int copy_ent(const struct polydir_s *ent, struct polydir_s *pent)
        strcpy(pent->instance_prefix, ent->instance_prefix);
        pent->method = ent->method;
        pent->num_uids = ent->num_uids;
+       pent->exclusive = ent->exclusive;
        if (ent->num_uids) {
                uid_t *pptr, *eptr;
 
@@ -120,6 +121,10 @@ static void del_polydir_list(struct polydir_s *polydirs_ptr)
        }
 }
 
+static void cleanup_data(pam_handle_t *pamh UNUSED , void *data, int err UNUSED)
+{
+       del_polydir_list(data);
+}
 
 /*
  * Called from parse_config_file, this function processes a single line
@@ -140,6 +145,7 @@ static int process_line(char *line, const char *home,
 
     poly.uid = NULL;
     poly.num_uids = 0;
+    poly.exclusive = 0;
 
     /*
      * skip the leading white space
@@ -222,18 +228,6 @@ static int process_line(char *line, const char *home,
        instance_prefix = expanded;
     }
 
-    /*
-     * Ensure that all pathnames are absolute path names.
-     */
-    if ((dir[0] != '/') || (instance_prefix[0] != '/')) {
-        pam_syslog(idata->pamh, LOG_NOTICE,"Pathnames must start with '/'");
-        goto skipping;
-    }
-    if (strstr(dir, "..") || strstr(instance_prefix, "..")) {
-        pam_syslog(idata->pamh, LOG_NOTICE,"Pathnames must not contain '..'");
-        goto skipping;
-    }
-
     /*
      * Populate polyinstantiated directory structure with appropriate
      * pathnames and the method with which to polyinstantiate.
@@ -241,6 +235,7 @@ static int process_line(char *line, const char *home,
     if (strlen(dir) >= sizeof(poly.dir)
        || strlen(instance_prefix) >= sizeof(poly.instance_prefix)) {
        pam_syslog(idata->pamh, LOG_NOTICE, "Pathnames too long");
+       goto skipping;
     }
     strcpy(poly.dir, dir);
     strcpy(poly.instance_prefix, instance_prefix);
@@ -248,6 +243,18 @@ static int process_line(char *line, const char *home,
     poly.method = NONE;
     if (strcmp(method, "user") == 0) 
            poly.method = USER;
+    
+    if (strcmp(method, "tmpdir") == 0) {
+           poly.method = TMPDIR;
+           if (sizeof(poly.instance_prefix) - strlen(poly.instance_prefix) < 7) {
+               pam_syslog(idata->pamh, LOG_NOTICE, "Pathnames too long");
+               goto skipping;
+           }
+           strcat(poly.instance_prefix, "XXXXXX");
+    }
+    
+    if (strcmp(method, "tmpfs") == 0)
+            poly.method = TMPFS;
 
 #ifdef WITH_SELINUX
     if (strcmp(method, "level") == 0) {
@@ -266,11 +273,23 @@ static int process_line(char *line, const char *home,
 
 #endif
 
-    if ( poly.method == NONE) {
+    if (poly.method == NONE) {
         pam_syslog(idata->pamh, LOG_NOTICE, "Illegal method");
         goto skipping;
     }
 
+    /*
+     * Ensure that all pathnames are absolute path names.
+     */
+    if ((dir[0] != '/') || (poly.method != TMPFS && instance_prefix[0] != '/')) {
+        pam_syslog(idata->pamh, LOG_NOTICE, "Pathnames must start with '/'");
+        goto skipping;
+    }
+    if (strstr(dir, "..") || strstr(instance_prefix, "..")) {
+        pam_syslog(idata->pamh, LOG_NOTICE, "Pathnames must not contain '..'");
+        goto skipping;
+    }
+
     /*
      * If the line in namespace.conf for a directory to polyinstantiate
      * contains a list of override users (users for whom polyinstantiation
@@ -281,7 +300,11 @@ static int process_line(char *line, const char *home,
         uid_t *uidptr;
         const char *ustr, *sstr;
         int count, i;
-
+       
+       if (*uids == '~') {
+               poly.exclusive = 1;
+               uids++;
+       }
         for (count = 0, ustr = sstr = uids; sstr; ustr = sstr + 1, count++)
            sstr = strchr(ustr, ',');
 
@@ -419,6 +442,7 @@ static int parse_config_file(struct instance_data *idata)
  * directory's list of override uids. If the uid is one of the override
  * uids for the polyinstantiated directory, polyinstantiation is not
  * performed for that user for that directory.
+ * If exclusive is set the returned values are opposite.
  */
 static int ns_override(struct polydir_s *polyptr, struct instance_data *idata,
                uid_t uid)
@@ -432,11 +456,11 @@ static int ns_override(struct polydir_s *polyptr, struct instance_data *idata,
 
     for (i = 0; i < polyptr->num_uids; i++) {
         if (uid == polyptr->uid[i]) {
-            return 1;
+            return !polyptr->exclusive;
         }
     }
 
-    return 0;
+    return polyptr->exclusive;
 }
 
 /*
@@ -623,6 +647,12 @@ static int poly_name(const struct polydir_s *polyptr, char **i_name,
 
 #endif /* WITH_SELINUX */
 
+       case TMPDIR:
+       case TMPFS:
+           if ((*i_name=strdup("")) == NULL)
+               goto fail;
+           return PAM_SUCCESS;
+
        default:
            if (idata->flags & PAMNS_DEBUG)
                pam_syslog(idata->pamh, LOG_ERR, "Unknown method");
@@ -643,7 +673,7 @@ static int poly_name(const struct polydir_s *polyptr, char **i_name,
            hash = NULL;
         } else {
            char *newname;
-           if (asprintf(&newname, "%.*s_%s", NAMESPACE_MAX_DIR_LEN-1-strlen(hash),
+           if (asprintf(&newname, "%.*s_%s", NAMESPACE_MAX_DIR_LEN-1-(int)strlen(hash),
                *i_name, hash) < 0) {
                goto fail;
            }
@@ -726,8 +756,8 @@ static int check_inst_parent(char *ipath, struct instance_data *idata)
 * execute it and pass directory to polyinstantiate and instance
 * directory as arguments.
 */
-static int inst_init(const struct polydir_s *polyptr, char *ipath,
-          struct instance_data *idata)
+static int inst_init(const struct polydir_s *polyptr, const char *ipath,
+          struct instance_data *idata, int newdir)
 {
        pid_t rc, pid;
        sighandler_t osighand = NULL;
@@ -757,7 +787,7 @@ static int inst_init(const struct polydir_s *polyptr, char *ipath,
                                }
 #endif
                                if (execl(NAMESPACE_INIT_SCRIPT, NAMESPACE_INIT_SCRIPT,
-                                                       polyptr->dir, ipath, (char *)NULL) < 0)
+                                       polyptr->dir, ipath, newdir?"1":"0", idata->user, (char *)NULL) < 0)
                                        exit(1);
                        } else if (pid > 0) {
                                while (((rc = waitpid(pid, &status, 0)) == (pid_t)-1) &&
@@ -792,16 +822,17 @@ out:
  * Create polyinstantiated instance directory (ipath).
  */
 #ifdef WITH_SELINUX
-static int create_dirs(const struct polydir_s *polyptr, char *ipath,
+static int create_dirs(struct polydir_s *polyptr, char *ipath,
         security_context_t icontext, security_context_t ocontext,
        struct instance_data *idata)
 #else
-static int create_dirs(const struct polydir_s *polyptr, char *ipath,
+static int create_dirs(struct polydir_s *polyptr, char *ipath,
        struct instance_data *idata)
 #endif
 {
        struct stat statbuf, newstatbuf;
        int rc, fd;
+       int newdir = 0;
 
     /*
      * stat the directory to polyinstantiate, so its owner-group-mode
@@ -835,7 +866,17 @@ static int create_dirs(const struct polydir_s *polyptr, char *ipath,
      * attributes to match that of the original directory that is being
      * polyinstantiated.
      */
-    if (mkdir(ipath, S_IRUSR) < 0) {
+    
+    if (polyptr->method == TMPDIR) {
+       if (mkdtemp(polyptr->instance_prefix) == NULL) {
+            pam_syslog(idata->pamh, LOG_ERR, "Error creating temporary instance %s, %m",
+                       polyptr->instance_prefix);
+           polyptr->method = NONE; /* do not clean up! */
+           return PAM_SESSION_ERR;
+       }
+       /* copy the actual directory name to ipath */
+       strcpy(ipath, polyptr->instance_prefix);
+    } else if (mkdir(ipath, S_IRUSR) < 0) {
         if (errno == EEXIST)
             goto inst_init;
         else {
@@ -845,6 +886,7 @@ static int create_dirs(const struct polydir_s *polyptr, char *ipath,
         }
     }
 
+    newdir = 1;
     /* Open a descriptor to it to prevent races */
     fd = open(ipath, O_DIRECTORY | O_RDONLY);
     if (fd < 0) {
@@ -909,7 +951,7 @@ static int create_dirs(const struct polydir_s *polyptr, char *ipath,
      */
 
 inst_init:
-       rc = inst_init(polyptr, ipath, idata);
+    rc = inst_init(polyptr, ipath, idata, newdir);
     return rc;
 }
 
@@ -921,13 +963,12 @@ inst_init:
  * security attributes, and performs bind mount to setup the process
  * namespace.
  */
-static int ns_setup(const struct polydir_s *polyptr,
+static int ns_setup(struct polydir_s *polyptr,
        struct instance_data *idata)
 {
     int retval = 0;
     char *inst_dir = NULL;
     char *instname = NULL;
-    char *dir;
 #ifdef WITH_SELINUX
     security_context_t instcontext = NULL, origcontext = NULL;
 #endif
@@ -936,9 +977,15 @@ static int ns_setup(const struct polydir_s *polyptr,
         pam_syslog(idata->pamh, LOG_DEBUG,
                "Set namespace for directory %s", polyptr->dir);
 
-    dir = strrchr(polyptr->dir, '/');
-    if (dir && strlen(dir) > 1)
-        dir++;
+    if (polyptr->method == TMPFS) {
+       if (mount("tmpfs", polyptr->dir, "tmpfs", 0, NULL) < 0) {
+           pam_syslog(idata->pamh, LOG_ERR, "Error mounting tmpfs on %s, %m",
+               polyptr->dir);
+            return PAM_SESSION_ERR;
+       }
+       /* we must call inst_init after the mount in this case */
+       return inst_init(polyptr, "tmpfs", idata, 1);
+    }
 
     /*
      * Obtain the name of instance pathname based on the
@@ -1044,6 +1091,58 @@ static int cwd_in(char *dir, struct instance_data *idata)
     return retval;
 }
 
+static int cleanup_tmpdirs(struct instance_data *idata)
+{
+    struct polydir_s *pptr;
+    pid_t rc, pid;
+    sighandler_t osighand = NULL;
+    int status;
+
+    osighand = signal(SIGCHLD, SIG_DFL);
+    if (osighand == SIG_ERR) {
+       pam_syslog(idata->pamh, LOG_ERR, "Cannot set signal value");
+       rc = PAM_SESSION_ERR;
+       goto out;
+    }
+
+    for (pptr = idata->polydirs_ptr; pptr; pptr = pptr->next) {
+       if (pptr->method == TMPDIR && access(pptr->instance_prefix, F_OK) == 0) {
+           pid = fork();
+           if (pid == 0) {
+#ifdef WITH_SELINUX
+               if (idata->flags & PAMNS_SELINUX_ENABLED) {
+                   if (setexeccon(NULL) < 0)
+                       exit(1);
+               }
+#endif
+               if (execl("/bin/rm", "/bin/rm", "-rf", pptr->instance_prefix, (char *)NULL) < 0)
+                       exit(1);
+           } else if (pid > 0) {
+               while (((rc = waitpid(pid, &status, 0)) == (pid_t)-1) &&
+                   (errno == EINTR));
+               if (rc == (pid_t)-1) {
+                   pam_syslog(idata->pamh, LOG_ERR, "waitpid failed- %m");
+                   rc = PAM_SESSION_ERR;
+                   goto out;
+               }
+               if (!WIFEXITED(status) || WIFSIGNALED(status) > 0) {
+                   pam_syslog(idata->pamh, LOG_ERR,
+                       "Error removing %s", pptr->instance_prefix);
+               }
+           } else if (pid < 0) {
+               pam_syslog(idata->pamh, LOG_ERR,
+                       "Cannot fork to run namespace init script, %m");
+               rc = PAM_SESSION_ERR;
+               goto out;
+           }
+        }
+    }
+
+    rc = PAM_SUCCESS;
+out:
+    signal(SIGCHLD, osighand);
+    return rc;
+}
 
 /*
  * This function checks to see if polyinstantiation is needed for any
@@ -1112,13 +1211,22 @@ static int setup_namespace(struct instance_data *idata, enum unmnt_op unmnt)
      * disassociate from the parent namespace.
      */
     if (need_poly) {
+       if (pam_set_data(idata->pamh, NAMESPACE_POLYDIR_DATA, idata->polydirs_ptr,
+               cleanup_data) != PAM_SUCCESS) {
+           pam_syslog(idata->pamh, LOG_ERR,
+               "Unable to set namespace data");
+           return PAM_SYSTEM_ERR;
+       }
         if (unshare(CLONE_NEWNS) < 0) {
-            pam_syslog(idata->pamh, LOG_ERR,
+               pam_set_data(idata->pamh, NAMESPACE_POLYDIR_DATA, NULL, NULL);
+               pam_syslog(idata->pamh, LOG_ERR,
                "Unable to unshare from parent namespace, %m");
             return PAM_SESSION_ERR;
         }
-    } else
+    } else {
+       del_polydir_list(idata->polydirs_ptr);
         return PAM_SUCCESS;
+    }
 
     /*
      * Again cycle through all polyinstantiated directories, this time,
@@ -1145,7 +1253,8 @@ static int setup_namespace(struct instance_data *idata, enum unmnt_op unmnt)
                  * umount
                  */
                 if ((changing_dir = cwd_in(pptr->dir, idata)) < 0) {
-                    return PAM_SESSION_ERR;
+                    retval = PAM_SESSION_ERR;
+                    goto out;
                 } else if (changing_dir) {
                     if (idata->flags & PAMNS_DEBUG)
                         pam_syslog(idata->pamh, LOG_DEBUG, "changing cwd");
@@ -1173,8 +1282,10 @@ static int setup_namespace(struct instance_data *idata, enum unmnt_op unmnt)
                    int saved_errno = errno;
                    pam_syslog(idata->pamh, LOG_ERR, "Unmount of %s failed, %m",
                        pptr->dir);
-                   if (saved_errno != EINVAL)
-                       return PAM_SESSION_ERR;
+                   if (saved_errno != EINVAL) {
+                       retval = PAM_SESSION_ERR;
+                       goto out;
+                    }
                 } else if (idata->flags & PAMNS_DEBUG)
                     pam_syslog(idata->pamh, LOG_DEBUG, "Umount succeeded %s",
                                pptr->dir);
@@ -1186,7 +1297,9 @@ static int setup_namespace(struct instance_data *idata, enum unmnt_op unmnt)
                      break;
         }
     }
-
+out:
+    if (retval != PAM_SUCCESS)
+       cleanup_tmpdirs(idata);
     return retval;
 }
 
@@ -1225,8 +1338,10 @@ static int orig_namespace(struct instance_data *idata)
             } else if (idata->flags & PAMNS_DEBUG)
                 pam_syslog(idata->pamh, LOG_DEBUG, "Unmount of %s succeeded",
                        pptr->dir);
-        }
+       }
     }
+
+    cleanup_tmpdirs(idata);
     return 0;
 }
 
@@ -1351,7 +1466,8 @@ PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED,
     } else if (idata.flags & PAMNS_DEBUG)
         pam_syslog(idata.pamh, LOG_DEBUG, "Nothing to polyinstantiate");
 
-    del_polydir_list(idata.polydirs_ptr);
+    if (retval != PAM_SUCCESS)
+       del_polydir_list(idata.polydirs_ptr);
     return retval;
 }
 
@@ -1366,6 +1482,7 @@ PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh, int flags UNUSED,
     struct instance_data idata;
     char *user_name;
     struct passwd *pwd;
+    void *polyptr;
 
     /* init instance data */
     idata.flags = 0;
@@ -1429,16 +1546,12 @@ PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh, int flags UNUSED,
     strncat(idata.user, user_name, sizeof(idata.user) - 1);
     idata.uid = pwd->pw_uid;
 
-    /*
-     * Parse namespace configuration file which lists directories that
-     * are polyinstantiated, directories where instance directories are
-     * created and the method used for polyinstantiation.
-     */
-    retval = parse_config_file(&idata);
-    if ((retval != PAM_SUCCESS) || !idata.polydirs_ptr) {
-       del_polydir_list(idata.polydirs_ptr);
-        return PAM_SESSION_ERR;
-    }
+    retval = pam_get_data(idata.pamh, NAMESPACE_POLYDIR_DATA, (const void **)&polyptr);
+    if (retval != PAM_SUCCESS || polyptr == NULL)
+       /* nothing to reset */
+       return PAM_SUCCESS;
+       
+    idata.polydirs_ptr = polyptr;
 
     if (idata.flags & PAMNS_DEBUG)
         pam_syslog(idata.pamh, LOG_DEBUG, "Resetting namespace for pid %d",
@@ -1453,7 +1566,9 @@ PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh, int flags UNUSED,
             pam_syslog(idata.pamh, LOG_DEBUG,
                "resetting namespace ok for pid %d", getpid());
     }
-    del_polydir_list(idata.polydirs_ptr);
+
+    pam_set_data(idata.pamh, NAMESPACE_POLYDIR_DATA, NULL, NULL);
+    
     return PAM_SUCCESS;
 }
 
index 0847ec0877112fae5e7934fff150daa60b8b744b..4b4388995a869326b8cf778b0c6dd7f29faa280f 100644 (file)
@@ -90,6 +90,7 @@
 #define PAMNS_NO_UNMOUNT_ON_CLOSE  0x00010000 /* no unmount at session close */
 
 #define NAMESPACE_MAX_DIR_LEN 80
+#define NAMESPACE_POLYDIR_DATA "pam_namespace:polydir_data"
 
 /*
  * Polyinstantiation method options, based on user, security context
@@ -100,6 +101,8 @@ enum polymethod {
     USER,
     CONTEXT,
     LEVEL,
+    TMPDIR,
+    TMPFS
 };
 
 /*
@@ -128,6 +131,7 @@ struct polydir_s {
     enum polymethod method;            /* method used to polyinstantiate */
     unsigned int num_uids;             /* number of override uids */
     uid_t *uid;                                /* list of override uids */
+    int exclusive;                     /* polyinstatiate exclusively for override uids */
     struct polydir_s *next;            /* pointer to the next polydir entry */
 };