From d5a261b8be2035bbf49726eb7ac792ee6d5a22d1 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Tue, 24 Jan 2012 20:03:28 +0100 Subject: [PATCH] Make / mount as rslave instead of bind mounting polydirs. * modules/pam_namespace/pam_namespace.c (protect_dir): Drop the always argument. (check_inst_parent): Drop the always argument from protect_dir(). (create_polydir): Likewise. (ns_setup): Likewise and do not mark the polydir with MS_PRIVATE. (setup_namespace): Mark the / with MS_SLAVE|MS_REC. * modules/pam_namespace/pam_namespace.8.xml: Reflect the change in docs. --- modules/pam_namespace/pam_namespace.8.xml | 10 ++++-- modules/pam_namespace/pam_namespace.c | 40 +++++++++++------------ 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/modules/pam_namespace/pam_namespace.8.xml b/modules/pam_namespace/pam_namespace.8.xml index 48021c80..6ec3ad23 100644 --- a/modules/pam_namespace/pam_namespace.8.xml +++ b/modules/pam_namespace/pam_namespace.8.xml @@ -246,12 +246,18 @@ This option can be used on systems where the / mount point or its submounts are made shared (for example with a mount --make-rshared / command). - The module will make the polyinstantiated directory mount points - private. Normally the pam_namespace will try to detect the + The module will mark the whole directory tree so any mount and + unmount operations in the polyinstantiation namespace are private. + Normally the pam_namespace will try to detect the shared / mount point and make the polyinstantiated directories private automatically. This option has to be used just when only a subtree is shared and / is not. + + Note that mounts and unmounts done in the private namespace will not + affect the parent namespace if this option is used or when the + shared / mount point is autodetected. + diff --git a/modules/pam_namespace/pam_namespace.c b/modules/pam_namespace/pam_namespace.c index f0bffa15..470f493b 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, int always, +static int protect_dir(const char *path, mode_t mode, int do_mkdir, 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, int always, } } - if ((flags & O_NOFOLLOW) || always) { + if (flags & O_NOFOLLOW) { /* 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, 0, idata); + dfd = protect_dir(inst_parent, 0, 1, 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->flags & PAMNS_MOUNT_PRIVATE, idata); + rc = protect_dir(dir, mode, 1, 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->flags & PAMNS_MOUNT_PRIVATE, idata); + retval = protect_dir(polyptr->dir, 0, 0, idata); if (retval < 0 && errno != ENOENT) { pam_syslog(idata->pamh, LOG_ERR, "Polydir %s access error: %m", @@ -1534,22 +1534,6 @@ 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 @@ -1720,6 +1704,20 @@ static int setup_namespace(struct instance_data *idata, enum unmnt_op unmnt) "Unable to unshare from parent namespace, %m"); return PAM_SESSION_ERR; } + if (idata->flags & PAMNS_MOUNT_PRIVATE) { + /* + * Remount / as SLAVE so that nothing mounted in the namespace + * shows up in the parent + */ + if (mount("/", "/", NULL, MS_SLAVE | MS_REC , NULL) < 0) { + pam_syslog(idata->pamh, LOG_ERR, + "Failed to mark / as a slave mount point, %m"); + return PAM_SESSION_ERR; + } + if (idata->flags & PAMNS_DEBUG) + pam_syslog(idata->pamh, LOG_DEBUG, + "The / mount point was marked as slave"); + } } else { del_polydir_list(idata->polydirs_ptr); return PAM_SUCCESS; -- 2.40.0