diff --git a/modules/pam_namespace/pam_namespace.8.xml b/modules/pam_namespace/pam_namespace.8.xml index 0433f0f..f0ebe2c 100644 --- a/modules/pam_namespace/pam_namespace.8.xml +++ b/modules/pam_namespace/pam_namespace.8.xml @@ -52,6 +52,9 @@ use_default_context + + mount_private + @@ -234,6 +237,21 @@ + + + + + + + This option should be used on systems where the / mount point and + its submounts are made shared (for example with a + mount --make-rshared / command). + The module will make the polyinstantiated directory mount points + private. + + + + diff --git a/modules/pam_namespace/pam_namespace.c b/modules/pam_namespace/pam_namespace.c index c47599e..d5a2d78 100644 --- a/modules/pam_namespace/pam_namespace.c +++ b/modules/pam_namespace/pam_namespace.c @@ -1003,7 +1003,7 @@ static int protect_mount(int dfd, const char *path, struct instance_data *idata) return 0; } -static int protect_dir(const char *path, mode_t mode, int do_mkdir, +static int protect_dir(const char *path, mode_t mode, int do_mkdir, int always, struct instance_data *idata) { char *p = strdup(path); @@ -1082,7 +1082,7 @@ static int protect_dir(const char *path, mode_t mode, int do_mkdir, } } - if (flags & O_NOFOLLOW) { + if ((flags & O_NOFOLLOW) || always) { /* we are inside user-owned dir - protect */ if (protect_mount(rv, p, idata) == -1) { save_errno = errno; @@ -1124,7 +1124,7 @@ static int check_inst_parent(char *ipath, struct instance_data *idata) if (trailing_slash) *trailing_slash = '\0'; - dfd = protect_dir(inst_parent, 0, 1, idata); + dfd = protect_dir(inst_parent, 0, 1, 0, idata); if (dfd == -1 || fstat(dfd, &instpbuf) < 0) { pam_syslog(idata->pamh, LOG_ERR, @@ -1259,7 +1259,7 @@ static int create_polydir(struct polydir_s *polyptr, } #endif - rc = protect_dir(dir, mode, 1, idata); + rc = protect_dir(dir, mode, 1, idata->flags & PAMNS_MOUNT_PRIVATE, idata); if (rc == -1) { pam_syslog(idata->pamh, LOG_ERR, "Error creating directory %s: %m", dir); @@ -1447,7 +1447,7 @@ static int ns_setup(struct polydir_s *polyptr, pam_syslog(idata->pamh, LOG_DEBUG, "Set namespace for directory %s", polyptr->dir); - retval = protect_dir(polyptr->dir, 0, 0, idata); + retval = protect_dir(polyptr->dir, 0, 0, idata->flags & PAMNS_MOUNT_PRIVATE, idata); if (retval < 0 && errno != ENOENT) { pam_syslog(idata->pamh, LOG_ERR, "Polydir %s access error: %m", @@ -1534,6 +1534,22 @@ static int ns_setup(struct polydir_s *polyptr, goto error_out; } + if (idata->flags & PAMNS_MOUNT_PRIVATE) { + /* + * Make the polyinstantiated dir private mount. This depends + * on making the dir a mount point in the protect_dir call. + */ + if (mount(polyptr->dir, polyptr->dir, NULL, MS_PRIVATE|MS_REC, NULL) < 0) { + pam_syslog(idata->pamh, LOG_ERR, "Error making %s a private mount, %m", + polyptr->dir); + goto error_out; + } + if (idata->flags & PAMNS_DEBUG) + pam_syslog(idata->pamh, LOG_DEBUG, + "Polyinstantiated directory %s made as private mount", polyptr->dir); + + } + /* * Bind mount instance directory on top of the polyinstantiated * directory to provide an instance of polyinstantiated directory @@ -1964,6 +1980,9 @@ PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED, idata.flags |= PAMNS_USE_DEFAULT_CONTEXT; idata.flags |= PAMNS_CTXT_BASED_INST; } + if (strcmp(argv[i], "mount_private") == 0) { + idata.flags |= PAMNS_MOUNT_PRIVATE; + } if (strcmp(argv[i], "unmnt_remnt") == 0) unmnt = UNMNT_REMNT; if (strcmp(argv[i], "unmnt_only") == 0) diff --git a/modules/pam_namespace/pam_namespace.h b/modules/pam_namespace/pam_namespace.h index da21bd7..7b39068 100644 --- a/modules/pam_namespace/pam_namespace.h +++ b/modules/pam_namespace/pam_namespace.h @@ -96,6 +96,7 @@ #define PAMNS_NO_UNMOUNT_ON_CLOSE 0x00010000 /* no unmount at session close */ #define PAMNS_USE_CURRENT_CONTEXT 0x00020000 /* use getcon instead of getexeccon */ #define PAMNS_USE_DEFAULT_CONTEXT 0x00040000 /* use get_default_context instead of getexeccon */ +#define PAMNS_MOUNT_PRIVATE 0x00080000 /* Make the polydir mounts private */ /* polydir flags */ #define POLYDIR_EXCLUSIVE 0x00000001 /* polyinstatiate exclusively for override uids */