[redhat-lspp] [PATCH] pam_namespace module patch
JANAK DESAI
janak at us.ibm.com
Fri Feb 17 23:17:32 UTC 2006
[PATCH] pam_namespace V2
This patch applies on top of the latest version available at
http://people.redhat.com/sgrubb/files/
Changes since the -v1 of the patch available at the above location:
- Removed creation and use of "orig" directories where the
original polyinstantiated directory was bind mounted for
use by trusted applications.
- Added user name in the instance directory name if polyinstantiation
is being done with USER or BOTH (both user and security context)
- Added a new option to the namespace module to undo any
previous polyinstantiation. This option may be used by trusted
applications that want to process instance directories on their
own.
Signed-off-by: Janak Desai <janak at us.ibm.com>
---
Linux-PAM-0.99.3.0-ns2/modules/pam_namespace/README | 23
Linux-PAM-0.99.3.0-ns2/modules/pam_namespace/namespace.conf | 12
Linux-PAM-0.99.3.0-ns2/modules/pam_namespace/pam_namespace.c | 454 ++---------
modules/pam_namespace/README | 23
modules/pam_namespace/namespace.conf | 12
modules/pam_namespace/pam_namespace.c | 454 ++---------
6 files changed, 250 insertions(+), 728 deletions(-)
diff -Naurp Linux-PAM-0.99.3.0/modules/pam_namespace/README Linux-PAM-0.99.3.0-ns2/modules/pam_namespace/README
--- Linux-PAM-0.99.3.0/modules/pam_namespace/README 2006-02-17 22:26:41.000000000 +0000
+++ Linux-PAM-0.99.3.0-ns2/modules/pam_namespace/README 2006-02-17 22:36:59.000000000 +0000
@@ -11,7 +11,7 @@ and users' home directory.
Each line describes a limit for a user in the form:
-<polydir> <instance_parent_dir> <orig_dir> <method> <list_of_uids>
+<polydir> <instance_parent_dir> <method> <list_of_uids>
Where:
<polydir> - is the absolute pathname of the directory to polyinstantiate
@@ -26,12 +26,6 @@ Where:
directory and parent of user's home directory. This field cannot
be blank.
-<orig_dir> - is the absolute pathname of the parent directory where the
- original content of the <polydir> is available. The special entry
- $HOME_PARENT is supported to designate parent of user's home
- directory. This field cannot be blank and this directory cannot
- be a subdirectory of <polydir>.
-
<method> - is the method used for polyinstantiation. It can take 3 different
values; "user" for polyinstantiation based on user name, "context"
for polyinstantiation based on process security context, and "both"
@@ -53,25 +47,30 @@ EXAMPLE /etc/security/namespace.conf con
# based on security context only. Polyinstantion will not be performed
# for user root and adm for directory /tmp, where as home directories
# are polyinstantiated for all users.
-/tmp / / both root,adm
+/tmp / both root,adm
$HOME $HOME_PARENT $HOME_PARENT context
ARGUMENTS RECOGNIZED:
debug Verbose logging by syslog
- unmnt_first For programs such as su and newrole, the login
+ unmnt_remnt For programs such as su and newrole, the login
session has already setup a polyinstantiated
namespace. For these programs, polyinstantiation
is performed based on new user id or security
context, however the command first needs to
undo the polyinstantiation performed by login.
- This argument is provide in the command's pam
- configuration file to instruct the command to
+ This argument instructs the command to
first undo previous polyinstantiation before
proceeding with new polyinstantiation based on
new id/context.
+ unmnt_only For trusted programs that want to undo any
+ existing bind mounts and process instance
+ directories on their own, this argument allows
+ them to unmount currently mounted instance
+ directories.
+
require_selinux If selinux is not enabled, return failure.
@@ -83,7 +82,7 @@ USAGE:
the following line in /etc/pam.d/<command> as the last line for
session service:
- session required /lib/security/pam_namespace.so [unmnt_first] [debug]
+ session required /lib/security/pam_namespace.so [unmnt_remnt] [debug]
Replace "/lib/security" path with your real modules path. This module
also depends on pam_selinux.so setting the context.
diff -Naurp Linux-PAM-0.99.3.0/modules/pam_namespace/namespace.conf Linux-PAM-0.99.3.0-ns2/modules/pam_namespace/namespace.conf
--- Linux-PAM-0.99.3.0/modules/pam_namespace/namespace.conf 2006-02-17 22:26:41.000000000 +0000
+++ Linux-PAM-0.99.3.0-ns2/modules/pam_namespace/namespace.conf 2006-02-17 22:37:24.000000000 +0000
@@ -2,7 +2,7 @@
#
# Each line describes a limit for a user in the form:
#
-# <polydir> <instance_parent_dir> <orig_dir> <method> <list_of_uids>
+# <polydir> <instance_parent_dir> <method> <list_of_uids>
#
# Where:
# <polydir> - is the absolute pathname of the directory to polyinstantiate
@@ -16,12 +16,6 @@
# $HOME_PARENT are supported to designate user's home directory and
# parent of user's home directory. This field cannot be blank.
#
-# <orig_dir> - is the absolute pathname of the parent directory where the
-# original content of the <polydir> is available. The special entry
-# $HOME_PARENT is supported to designate parent of user's home
-# directory. This field cannot be blank and this directory cannot
-# be a subdirectory of <polydir>.
-#
# <method> - is the method used for polyinstantiation. It can take 3 different
# values; "user" for polyinstantiation based on user name, "context"
# for polyinstantiation based on process security context, and "both"
@@ -44,7 +38,7 @@
# for user root and adm for directory /tmp, where as home directories
# are polyinstantiated for all users.
#
-# /tmp / / both root,adm
+# /tmp / both root,adm
#
-# $HOME $HOME_PARENT $HOME_PARENT context
+# $HOME $HOME_PARENT context
#
diff -Naurp Linux-PAM-0.99.3.0/modules/pam_namespace/pam_namespace.c Linux-PAM-0.99.3.0-ns2/modules/pam_namespace/pam_namespace.c
--- Linux-PAM-0.99.3.0/modules/pam_namespace/pam_namespace.c 2006-02-17 22:26:41.000000000 +0000
+++ Linux-PAM-0.99.3.0-ns2/modules/pam_namespace/pam_namespace.c 2006-02-17 22:44:37.000000000 +0000
@@ -88,12 +88,28 @@ enum polymethod {
};
/*
+ * Depending on the application using this namespace module, we
+ * may need to unmount priviously bind mounted instance directory.
+ * Applications such as login and sshd, that establish a new
+ * session unmount of instance directory is not needed. For applications
+ * such as su and newrole, that switch the identity, this module
+ * has to unmount previous instance directory first and re-mount
+ * based on the new indentity. For other trusted applications that
+ * just want to undo polyinstantiation, only unmount of previous
+ * instance directory is needed.
+ */
+enum unmnt_op {
+ NO_UNMNT,
+ UNMNT_REMNT,
+ UNMNT_ONLY,
+};
+
+/*
* Structure that holds information about a directory to polyinstantiate
*/
struct polydir_s {
char dir[PATH_MAX]; /* directory to polyinstantiate */
char instance_parent_dir[PATH_MAX]; /* parent dir of instance */
- char orig_dir[PATH_MAX]; /* original dir available at */
enum polymethod method; /* method used to polyinstantiate */
unsigned int num_uids; /* number of override uids */
uid_t *uid; /* list of override uids */
@@ -107,6 +123,7 @@ struct instance_data {
char user[LOGIN_NAME_MAX]; /* User name */
uid_t uid; /* The uid of the user */
int selinux_enabled; /* If selinux is enabled */
+ int cnxt_based_inst; /* If context based instance needed */
};
/*
@@ -133,7 +150,6 @@ static int add_polydir_entry(struct inst
/* Make copy */
strcpy(pent->dir, ent->dir);
strcpy(pent->instance_parent_dir, ent->instance_parent_dir);
- strcpy(pent->orig_dir, ent->orig_dir);
pent->method = ent->method;
pent->num_uids = ent->num_uids;
if (ent->num_uids) {
@@ -170,8 +186,8 @@ static int add_polydir_entry(struct inst
pam_syslog(idata->pamh, LOG_NOTICE, "Poly dirs so far");
while (dptr) {
- pam_syslog(idata->pamh, LOG_NOTICE, "%s %s %s %d", dptr->dir,
- dptr->instance_parent_dir, dptr->orig_dir, dptr->method);
+ pam_syslog(idata->pamh, LOG_NOTICE, "%s %s %d", dptr->dir,
+ dptr->instance_parent_dir, dptr->method);
for (i = 0, iptr = dptr->uid; i < dptr->num_uids; i++, iptr++)
pam_syslog(idata->pamh, LOG_NOTICE, "override user %d ", *iptr);
dptr = dptr->next;
@@ -208,7 +224,7 @@ static void del_polydir_list(struct poly
static int process_line(char *line, const char *home,
struct instance_data *idata)
{
- const char *dir, *instance_parent_dir, *orig_dir;
+ const char *dir, *instance_parent_dir;
const char *method, *uids;
char *tmp = strdupa(home);
const char *parent_home_dir = dirname(tmp); /* parent of homedir */
@@ -259,11 +275,6 @@ static int process_line(char *line, cons
pam_syslog(idata->pamh, LOG_NOTICE, "Invalid line -- skipping");
return 0;
}
- orig_dir = strtok_r(NULL, " \t", &tptr);
- if (orig_dir == NULL) {
- pam_syslog(idata->pamh, LOG_NOTICE, "Invalid line -- skipping");
- return 0;
- }
method = strtok_r(NULL, " \t", &tptr);
if (method == NULL) {
pam_syslog(idata->pamh, LOG_NOTICE, "Invalid line -- skipping");
@@ -294,53 +305,41 @@ static int process_line(char *line, cons
instance_parent_dir = parent_home_dir;
else if (strcmp(instance_parent_dir, "$HOME") == 0)
instance_parent_dir = home;
- if (strcmp(orig_dir, "$HOME_PARENT") == 0)
- orig_dir = parent_home_dir;
- else if (strcmp(orig_dir, "$HOME") == 0)
- orig_dir = home;
}
/*
* Ensure that all pathnames are absolute path names.
*/
- if ((dir[0] != '/') || (instance_parent_dir[0] != '/') ||
- (orig_dir[0] != '/')) {
+ if ((dir[0] != '/') || (instance_parent_dir[0] != '/')) {
pam_syslog(idata->pamh, LOG_NOTICE,"Pathnames must start with '/'");
return 0;
}
- if (strstr(dir, "..") || strstr(instance_parent_dir, "..") ||
- strstr(orig_dir, "..")) {
+ if (strstr(dir, "..") || strstr(instance_parent_dir, "..")) {
pam_syslog(idata->pamh, LOG_NOTICE,"Pathnames must not have '..'");
return 0;
}
/*
- * Ensure that orig dir is not a subdirectory of the
- * directory being polyinstantiated.
- * Example - /abcdef and /abc
- */
- if (strncmp(orig_dir, dir, strlen(dir)) == 0) {
- if (idata->debug)
- pam_syslog(idata->pamh, LOG_NOTICE,
- "orig_dir %s cannot be inside the poly dir %s",
- orig_dir, dir);
- return 0;
- }
-
- /*
* Populate polyinstantiated directory structure with appropriate
* pathnames and the method with which to polyinstantiate.
*/
strcpy(poly.dir, dir);
strcpy(poly.instance_parent_dir, instance_parent_dir);
- strcpy(poly.orig_dir, orig_dir);
if (strcmp(method, "user") == 0)
poly.method = USER;
#ifdef WITH_SELINUX
- else if (strcmp(method, "context") == 0)
- poly.method = CONTEXT;
- else if (strcmp(method, "both") == 0)
- poly.method = BOTH;
+ else if (strcmp(method, "context") == 0) {
+ if (idata->cnxt_based_inst)
+ poly.method = CONTEXT;
+ else
+ poly.method = USER;
+ } else if (strcmp(method, "both") == 0) {
+ if (idata->cnxt_based_inst)
+ poly.method = BOTH;
+ else
+ poly.method = USER;
+ }
+
#endif
else {
pam_syslog(idata->pamh, LOG_NOTICE, "Illegal method - skipping");
@@ -496,7 +495,7 @@ static int ns_override(struct polydir_s
#ifdef WITH_SELINUX
static int poly_name(const struct polydir_s *polyptr, char **i_name,
security_context_t *i_context, security_context_t *origcon,
- struct instance_data *idata)
+ struct instance_data *idata)
#else
static int poly_name(const struct polydir_s *polyptr, char **i_name,
struct instance_data *idata)
@@ -554,8 +553,8 @@ static int poly_name(const struct polydi
} else if (idata->debug)
pam_syslog(idata->pamh, LOG_NOTICE,
"member context returned by policy %s", *i_context);
+ freecon(scon);
}
- freecon(scon);
#endif
rc = PAM_SUCCESS;
@@ -614,17 +613,15 @@ static int poly_name(const struct polydi
/*
- * Create polyinstantiated instance directory (ipath) and orig directory
- * (opath), where the original "un-polyinstantiated" contents would be
- * available to authorized processes.
+ * Create polyinstantiated instance directory (ipath).
*/
#ifdef WITH_SELINUX
-static int create_dirs(const struct polydir_s *polyptr, char *opath,
- char *ipath, security_context_t icontext,
- security_context_t ocontext, struct instance_data *idata)
+static int create_dirs(const 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 *opath,
- char *ipath, struct instance_data *idata)
+static int create_dirs(const struct polydir_s *polyptr, char *ipath,
+ struct instance_data *idata)
#endif
{
struct stat statbuf, newstatbuf;
@@ -632,7 +629,7 @@ static int create_dirs(const struct poly
/*
* stat the directory to polyinstantiate, so its owner-group-mode
- * can be propagated to orig and instance directories
+ * can be propagated to instance directory
*/
if (stat(polyptr->dir, &statbuf) < 0) {
if (idata->debug)
@@ -651,71 +648,6 @@ static int create_dirs(const struct poly
}
/*
- * Create orig directory, set its security context, mode and
- * ownership attributes to match that of the original directory
- * that is being polyinstantiated.
- */
- if (mkdir(opath, S_IRUSR) < 0) { /* Create with no access */
- if (errno != EEXIST) {
- if (idata->debug)
- pam_syslog(idata->pamh, LOG_ERR, "Error creating %s, %s",
- opath, strerror(errno));
- return PAM_SESSION_ERR;
- }
- }
-
- /* Open a descriptor to it to prevent races */
- fd = open(opath, O_DIRECTORY | O_RDONLY);
- if (fd < 0) {
- pam_syslog(idata->pamh, LOG_ERR, "Error opening %s, %s", opath,
- strerror(errno));
- return PAM_SESSION_ERR;
- }
-#ifdef WITH_SELINUX
- /* If SE Linux is disabled, no need to label it */
- if (idata->selinux_enabled > 0) {
- if (fsetfilecon(fd, ocontext) < 0) {
- if (idata->debug)
- pam_syslog(idata->pamh, LOG_ERR,
- "Error setting context of %s to %s", opath, ocontext);
- close(fd);
- return PAM_SESSION_ERR;
- }
- }
-#endif
- /*
- * In case this directory currently exists and someone is logging in
- * for a second session, see if the owner/group is correct. Setting the
- * owner will reset the sticky bit and others. This could cause
- * unexpected and hard to troubleshoot problems.
- */
- if (fstat(fd, &newstatbuf) < 0) {
- if (idata->debug)
- pam_syslog(idata->pamh, LOG_ERR, "Error stating %s, %s",
- opath, strerror(errno));
- return PAM_SESSION_ERR;
- }
- if (newstatbuf.st_uid != statbuf.st_uid ||
- newstatbuf.st_gid != statbuf.st_gid) {
- if (fchown(fd, statbuf.st_uid, statbuf.st_gid) < 0) {
- if (idata->debug)
- pam_syslog(idata->pamh, LOG_ERR,
- "Error changing owner for %s, %s",
- opath, strerror(errno));
- close(fd);
- return PAM_SESSION_ERR;
- }
- }
- if (fchmod(fd, statbuf.st_mode & 07777) < 0) {
- if (idata->debug)
- pam_syslog(idata->pamh, LOG_ERR, "Error changing mode for %s, %s",
- opath, strerror(errno));
- close(fd);
- return PAM_SESSION_ERR;
- }
- close(fd);
-
- /*
* Create instance directory and set its security context to the context
* returned by the security policy. Set its mode and ownership
* attributes to match that of the original directory that is being
@@ -792,24 +724,23 @@ static int create_dirs(const struct poly
/*
* This function performs the namespace setup for a particular directory
- * that is being polyinstantiated. It creates MD5 hashes of orig and
- * instance directories, calls create_dirs to create them with appropriate
- * security attributes, and performs bind mounts to setup the process
+ * that is being polyinstantiated. It creates an MD5 hash of instance
+ * directory, calls create_dirs to create it with appropriate
+ * security attributes, and performs bind mount to setup the process
* namespace.
*/
static int ns_setup(const struct polydir_s *polyptr,
struct instance_data *idata)
{
int i, retval = 0;
- char *origname = NULL, *orig_path = NULL;
char *inst_parent_dir = NULL;
- char *md5orig = NULL, *md5inst = NULL, *instname = NULL;
+ char *md5inst = NULL, *instname = NULL;
char *to, *dir, *lastchr;
#ifdef WITH_SELINUX
security_context_t instcontext = NULL, origcontext = NULL;
#endif
unsigned char inst_digest[MD5_DIGEST_LENGTH];
- unsigned char orig_digest[MD5_DIGEST_LENGTH];
+ int username = (polyptr->method == USER) || (polyptr->method == BOTH);
if (idata->debug)
pam_syslog(idata->pamh, LOG_NOTICE,
@@ -819,25 +750,14 @@ static int ns_setup(const struct polydir
if (dir && strlen(dir) > 1)
dir++;
- if (strcmp(polyptr->orig_dir, "/") == 0) {
- if (asprintf(&origname, "/.%s-poly-orig", dir) < 0)
- goto error_out;
- } else {
- if (asprintf(&origname, "%s/.%s-poly-orig", polyptr->orig_dir, dir) < 0)
- goto error_out;
- }
-
- if (idata->debug)
- pam_syslog(idata->pamh, LOG_NOTICE, "origname %s", origname);
-
/*
- * Obtain names of orig and instance pathnames based on the
+ * Obtain the name of instance pathname based on the
* polyinstantiation method and instance context returned by
* security policy.
*/
#ifdef WITH_SELINUX
retval = poly_name(polyptr, &instname, &instcontext,
- &origcontext, idata);
+ &origcontext, idata);
#else
retval = poly_name(polyptr, &instname, idata);
#endif
@@ -850,21 +770,14 @@ static int ns_setup(const struct polydir
#ifdef WITH_SELINUX
if (idata->debug && idata->selinux_enabled > 0)
pam_syslog(idata->pamh, LOG_ERR,"Inst context %s Orig context %s",
- instcontext, origcontext);
+ instcontext, origcontext);
#endif
}
/*
- * Create MD5 hashes for instance and orig_dir pathnames.
+ * Create MD5 hashes for instance pathname.
*/
- if (MD5((unsigned char*)origname, strlen((char*)origname),
- orig_digest) == NULL) {
- if (idata->debug)
- pam_syslog(idata->pamh, LOG_ERR,
- "Unable to generate hash for origname");
- goto error_out;
- }
if (MD5((unsigned char*)instname, strlen((char*)instname),
inst_digest) == NULL) {
if (idata->debug)
@@ -873,12 +786,6 @@ static int ns_setup(const struct polydir
goto error_out;
}
- if ((md5orig = (char *) malloc(MD5_DIGEST_LENGTH * 2 + 1)) == NULL) {
- if (idata->debug)
- pam_syslog(idata->pamh, LOG_ERR,
- "Unable to allocate buffer");
- goto error_out;
- }
if ((md5inst = (char *) malloc(MD5_DIGEST_LENGTH * 2 + 1)) == NULL) {
if (idata->debug)
pam_syslog(idata->pamh, LOG_ERR,
@@ -886,27 +793,12 @@ static int ns_setup(const struct polydir
goto error_out;
}
- to = md5orig;
- for (i = 0; i < MD5_DIGEST_LENGTH; i++) {
- char c[3];
- snprintf(c, 3, "%02x", (unsigned int)orig_digest[i]);
- to = stpcpy(to, c);
- }
-
/*
- * In the case where orig or instance path is just / or has a trailing
- * /, we should not include an extra / in the asprintfs below. It messes
+ * In the case where instance path is just / or has a trailing,
+ * we should not include an extra / in the asprintfs below. It messes
* up when we are trying to unmount the filesystem based on
* /proc/mounts
*/
- lastchr = polyptr->orig_dir + strlen(polyptr->orig_dir) - 1;
- if (*lastchr == '/') {
- if(asprintf(&orig_path, "%s.poly-%s", polyptr->orig_dir, md5orig) < 0)
- goto error_out;
- } else {
- if(asprintf(&orig_path, "%s/.poly-%s", polyptr->orig_dir, md5orig) < 0)
- goto error_out;
- }
to = md5inst;
for (i = 0; i < MD5_DIGEST_LENGTH; i++) {
@@ -918,46 +810,35 @@ static int ns_setup(const struct polydir
lastchr = polyptr->instance_parent_dir +
strlen(polyptr->instance_parent_dir) - 1;
if (*lastchr == '/') {
- if (asprintf(&inst_parent_dir, "%s.inst-%s",
- polyptr->instance_parent_dir, md5inst) < 0)
+ if (asprintf(&inst_parent_dir, "%s.inst-%s-%s",
+ polyptr->instance_parent_dir, username ? idata->user : "",
+ md5inst) < 0)
goto error_out;
} else {
- if (asprintf(&inst_parent_dir, "%s/.inst-%s",
- polyptr->instance_parent_dir, md5inst) < 0)
+ if (asprintf(&inst_parent_dir, "%s/.inst-%s-%s",
+ polyptr->instance_parent_dir, username ? idata->user : "",
+ md5inst) < 0)
goto error_out;
}
- if (idata->debug) {
- pam_syslog(idata->pamh, LOG_NOTICE, "orig %s", orig_path);
+ if (idata->debug)
pam_syslog(idata->pamh, LOG_NOTICE, "instance_parent_dir %s",
inst_parent_dir);
- }
/*
- * Create orig and instance directories with appropriate security
+ * Create instance directory with appropriate security
* contexts, owner, group and mode bits.
*/
#ifdef WITH_SELINUX
- retval = create_dirs(polyptr, orig_path, inst_parent_dir, instcontext,
- origcontext, idata);
+ retval = create_dirs(polyptr, inst_parent_dir, instcontext,
+ origcontext, idata);
#else
- retval = create_dirs(polyptr, orig_path, inst_parent_dir, idata);
+ retval = create_dirs(polyptr, inst_parent_dir, idata);
#endif
if (retval < 0) {
if (idata->debug)
- pam_syslog(idata->pamh,LOG_ERR,"Error creating instance/orig dirs");
- goto error_out;
- }
-
- /*
- * Bind mount polyinstantiated directory on orig path so it can
- * be available from that alternate location to authorized trusted
- * programs.
- */
- if (mount(polyptr->dir, orig_path, NULL, MS_BIND, NULL) < 0) {
- pam_syslog(idata->pamh, LOG_ERR, "Error mounting %s on %s, %s",
- polyptr->dir, orig_path, strerror(errno));
+ pam_syslog(idata->pamh,LOG_ERR,"Error creating instance dir");
goto error_out;
}
@@ -967,7 +848,6 @@ static int ns_setup(const struct polydir
* based on polyinstantiated method.
*/
if (mount(inst_parent_dir, polyptr->dir, NULL, MS_BIND, NULL) < 0) {
-// FIXME: should an unmount be attempted since above succeeded?
pam_syslog(idata->pamh, LOG_ERR, "Error mounting %s on %s, %s",
inst_parent_dir, polyptr->dir, strerror(errno));
goto error_out;
@@ -984,11 +864,8 @@ error_out:
cleanup:
free(md5inst);
- free(md5orig);
free(inst_parent_dir);
- free(orig_path);
free(instname);
- free(origname);
#ifdef WITH_SELINUX
freecon(instcontext);
freecon(origcontext);
@@ -1027,129 +904,12 @@ static int cwd_in(char *dir, struct inst
/*
- * This function reads /proc/mounts file to obtain names of mount points
- * of all "orig" directories, where original contents of polyinstantiated
- * directories are available to trusted programs. Once the names are read
- * from /proc/mounts, umount system call is invoked for each of these
- * orig directories.
- */
-static int unmount_orig_dirs(struct instance_data *idata)
-{
- int i, retval = PAM_SERVICE_ERR, changing_dir;
- size_t len = 0;
- FILE *procmounts;
- char mntdir[PATH_MAX];
- char *line, *mntpt, *mntpt_name, *mntpt_parent, *fptr, *cptr;
-
- if (idata->debug)
- pam_syslog(idata->pamh, LOG_NOTICE,
- "Attempting unmount of all orig dirs");
-
- /*
- * Open /proc/mounts file, read one line at a time, isolate
- * mount point name (2nd string), and if starts with ".poly-"
- * try and unmount it.
- */
- procmounts = fopen(PROC_MNTS, "r");
- if (procmounts == NULL) {
- pam_syslog(idata->pamh, LOG_ERR, "Error opening %s, %s", PROC_MNTS,
- strerror(errno));
- goto bad_file;
- }
-
- if ((mntpt = (char *) malloc(PATH_MAX)) == NULL) {
- pam_syslog(idata->pamh, LOG_ERR,
- "Error allocating buffer to hold pathname");
- goto bad_alloc_mnt;
- }
- if ((mntpt_parent = (char *) malloc(PATH_MAX)) == NULL) {
- pam_syslog(idata->pamh, LOG_ERR,
- "Error allocating buffer to hold pathname");
- goto bad_alloc_mntparent;
- }
-
- /* Use unlocked IO */
- __fsetlocking(procmounts, FSETLOCKING_BYCALLER);
-
- while (getline(&line, &len, procmounts) > 0) {
- if ((i = sscanf(line, "%s%s", mntdir, mntpt)) != 2) {
- pam_syslog(idata->pamh, LOG_ERR, "Error parsing mount entry %s",
- PROC_MNTS);
- goto bad_umnt;
- }
- if ((mntpt_name = strrchr(mntpt, '/')) != NULL) {
- strcpy(mntpt_parent, mntpt);
- if (strncmp(mntpt_name, "/.poly-", 7) == 0) {
- /*
- * Check to see if process current directory is in the
- * bind mounted orig directory that we are trying to
- * umount
- */
- if ((changing_dir = cwd_in(mntpt, idata)) < 0) {
- goto bad_umnt;
- } else if (changing_dir) {
- if (idata->debug)
- pam_syslog(idata->pamh, LOG_NOTICE, "changing cwd");
-
- /*
- * Change current working directory to the parent of
- * the mount point, that is parent of the orig
- * directory where original contents of the polydir
- * are available from
- */
- strcpy(mntpt_parent, mntpt);
- fptr = strchr(mntpt_parent, '/');
- cptr = strrchr(mntpt_parent, '/');
- if (fptr && cptr && (fptr == cptr))
- strcpy(mntpt_parent, "/");
- else if (cptr)
- *cptr = '\0';
-
- if (chdir(mntpt_parent) < 0) {
- pam_syslog(idata->pamh, LOG_ERR,
- "unable to chdir to %s, %s",
- mntpt_parent, strerror(errno));
- goto bad_umnt;
- }
- }
-
- /*
- * Now try and umount
- */
- if (umount(mntpt) < 0) {
- pam_syslog(idata->pamh, LOG_ERR, "Umount failed for %s, %s",
- mntpt, strerror(errno));
- goto bad_umnt;
- } else {
- if (idata->debug)
- pam_syslog(idata->pamh, LOG_NOTICE,
- "umounted orig dir %s",
- mntpt);
- }
- }
- }
- }
- retval = PAM_SUCCESS;
-
-bad_umnt:
- free(line);
- free(mntpt_parent);
-bad_alloc_mntparent:
- free(mntpt);
-bad_alloc_mnt:
- fclose(procmounts);
-bad_file:
- return retval;
-}
-
-
-/*
* This function checks to see if polyinstantiation is needed for any
* of the directories listed in the configuration file. If needed,
* cycles through all polyinstantiated directory entries and calls
* ns_setup to setup polyinstantiation for each one of them.
*/
-static int setup_namespace(struct instance_data *idata, int unmnt_first)
+static int setup_namespace(struct instance_data *idata, enum unmnt_op unmnt)
{
int retval = 0, need_poly = 0, changing_dir = 0;
char *cptr, *fptr, poly_parent[PATH_MAX];
@@ -1195,20 +955,6 @@ static int setup_namespace(struct instan
return PAM_SUCCESS;
/*
- * If need to unmount previously bind mounted polyinstantiated
- * directories, call unmount_orig_dirs to unmount polyinstantiated
- * directories from their alternate location where they were available
- * to trusted programs.
- */
- if (unmnt_first) {
- if ((retval = unmount_orig_dirs(idata)) < 0) {
- return PAM_SESSION_ERR;
- } else if (idata->debug)
- pam_syslog(idata->pamh, LOG_NOTICE,
- "Unmount of orig directories succeeded");
- }
-
- /*
* Again cycle through all polyinstantiated directories, this time,
* call ns_setup to setup polyinstantiation for a particular entry.
*/
@@ -1221,7 +967,7 @@ static int setup_namespace(struct instan
"Setting poly ns for user %d for dir %s",
idata->uid, pptr->dir);
- if (unmnt_first) {
+ if ((unmnt == UNMNT_REMNT) || (unmnt == UNMNT_ONLY)) {
/*
* Check to see if process current directory is in the
* bind mounted instance_parent directory that we are trying to
@@ -1262,9 +1008,11 @@ static int setup_namespace(struct instan
pptr->dir);
}
- retval = ns_setup(pptr, idata);
- if (retval != PAM_SUCCESS)
- break;
+ if (unmnt != UNMNT_ONLY) {
+ retval = ns_setup(pptr, idata);
+ if (retval != PAM_SUCCESS)
+ break;
+ }
}
}
@@ -1274,12 +1022,10 @@ static int setup_namespace(struct instan
/*
* Orig namespace. This function is called from when closing a pam
- * session. If authorized, it unmounts instance_parent directory and orig
- * directory (where original directory was bind mounted).
+ * session. If authorized, it unmounts instance_parent directory.
*/
static int orig_namespace(struct instance_data *idata)
{
- int retval;
struct polydir_s *pptr;
if (idata->debug)
@@ -1310,19 +1056,34 @@ static int orig_namespace(struct instanc
pptr->dir);
}
}
+ return 0;
+}
- /*
- * Call unmount_orig_dirs to unmount polyinstantiated directories
- * from their alternate location where they were available to trusted
- * programs.
- */
- retval = unmount_orig_dirs(idata);
- if (retval < 0 && idata->debug)
- pam_syslog(idata->pamh, LOG_NOTICE,
- "Unmount of orig directories succeeded");
- return retval;
+#ifdef WITH_SELINUX
+/*
+ * This function checks if the calling program has requested context
+ * change by calling setexeccon(). If context change is not requested
+ * then it does not make sense to polyinstantiate based on context.
+ * The return value from this function is used when selecting the
+ * polyinstantiation method. If context change is not requested then
+ * the polyinstantiation method is set to USER, even if the configuration
+ * file lists the method as "context" or "both".
+ */
+static int cnxt_based_inst_needed(void)
+{
+ security_context_t scon = NULL;
+ int rc = 0;
+
+ rc = getexeccon(&scon);
+ if (rc < 0 || scon == NULL)
+ return 0;
+ else {
+ freecon(scon);
+ return 1;
+ }
}
+#endif
/*
@@ -1331,10 +1092,11 @@ static int orig_namespace(struct instanc
PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags,
int argc, const char **argv)
{
- int i, unmnt_first = 0, retval;
+ int i, retval;
struct instance_data idata;
char *user_name;
struct passwd *pwd;
+ enum unmnt_op unmnt = NO_UNMNT;
/* init instance data */
idata.debug = 0;
@@ -1342,16 +1104,20 @@ PAM_EXTERN int pam_sm_open_session(pam_h
idata.pamh = pamh;
#ifdef WITH_SELINUX
idata.selinux_enabled = is_selinux_enabled();
+ idata.cnxt_based_inst = cnxt_based_inst_needed();
#else
idata.selinux_enabled = 0;
+ idata.cnxt_based_inst = 0;
#endif
/* Parse arguments. */
for (i = 0; i < argc; i++) {
if (strcmp(argv[i], "debug") == 0)
idata.debug = 1;
- if (strcmp(argv[i], "unmnt_first") == 0)
- unmnt_first = 1;
+ if (strcmp(argv[i], "unmnt_remnt") == 0)
+ unmnt = UNMNT_REMNT;
+ if (strcmp(argv[i], "unmnt_only") == 0)
+ unmnt = UNMNT_ONLY;
if (strcmp(argv[i], "require_selinux") == 0) {
if (idata.selinux_enabled != 1) {
pam_syslog(idata.pamh, LOG_ERR,
@@ -1397,7 +1163,7 @@ PAM_EXTERN int pam_sm_open_session(pam_h
}
if (idata.polydirs_ptr) {
- retval = setup_namespace(&idata, unmnt_first);
+ retval = setup_namespace(&idata, unmnt);
if (idata.debug) {
if (retval)
pam_syslog(idata.pamh, LOG_NOTICE,
@@ -1431,8 +1197,10 @@ PAM_EXTERN int pam_sm_close_session(pam_
idata.pamh = pamh;
#ifdef WITH_SELINUX
idata.selinux_enabled = is_selinux_enabled();
+ idata.cnxt_based_inst = cnxt_based_inst_needed();
#else
idata.selinux_enabled = 0;
+ idata.cnxt_based_inst = 0;
#endif
/* Parse arguments. */
More information about the redhat-lspp
mailing list