[ubuntu-hardened] [PATCH] policycoreutils: preserve mode bits and ownership of /tmp in seunshare

dave w nullcore at gmail.com
Thu Sep 15 17:39:11 UTC 2011


This patch addresses a flaw in seunshare.c that allows unprivileged
users to arbitrarily modify the contents of /tmp.  This bug is further
described in CVE 2011-1011

The seunshare_mount function in sandbox/seunshare.c in seunshare in certain
Red Hat packages of policycoreutils 2.0.83 and earlier in Red Hat
Enterprise Linux (RHEL) 6 and earlier, and Fedora 14 and earlier, mounts a
new directory on top of /tmp without assigning root ownership and the
sticky bit to this new directory, which allows local users to replace or
delete arbitrary /tmp files, and consequently cause a denial of service or
possibly gain privileges, by running a setuid application that relies on
/tmp, as demonstrated by the ksu application

This patch preserves the mode bits, and thus permissions, and
ownership of the destination directory of the bind mount performed by
seunshare.  The permission check in verify_mount() was relaxed for
directories who originally had the sticky bit set, as root ownership
is required for these to ensure that unprivileged users cannot unlink
arbitrary files in the newly bind mounted directory.


 policycoreutils/sandbox/seunshare.c |   23 ++++++++++++++++++++++-
 1 files changed, 22 insertions(+), 1 deletions(-)

diff --git a/policycoreutils/sandbox/seunshare.c
index f9bf12c..82b3cb9 100644
--- a/policycoreutils/sandbox/seunshare.c
+++ b/policycoreutils/sandbox/seunshare.c
@@ -149,7 +149,9 @@ static int verify_mount(const char *mntdir, struct
passwd *pwd) {
        fprintf(stderr, _("Invalid mount point %s: %s\n"), mntdir,
        return -1;
-   if (sb.st_uid != pwd->pw_uid) {
+    /* Owners don't have to match if the sticky bit has been set. */
+   if (sb.st_uid != pwd->pw_uid && !(sb.st_mode && S_ISVTX)) {
        errno = EPERM;
        syslog(LOG_AUTHPRIV | LOG_ALERT, "%s attempted to mount an
invalid directory, %s", pwd->pw_name, mntdir);
        perror(_("Invalid mount point, reporting to administrator"));
@@ -245,8 +247,17 @@ static int verify_shell(const char *shell_name)

 static int seunshare_mount(const char *src, const char *dst, struct
passwd *pwd) {
+    struct stat buf;
    if (verbose)
        printf("Mount %s on %s\n", src, dst);
+    /* Preserve mode bits and ownership */
+    if (stat(dst, &buf) < 0) {
+        fprintf(stderr, _("Failed to stat %s: %s\n"), dst, strerror(errno));
+        return -1;
+    }
    if (mount(dst, dst,  NULL, MS_BIND | MS_REC, NULL) < 0) {
        fprintf(stderr, _("Failed to mount %s on %s: %s\n"), dst, dst,
        return -1;
@@ -262,6 +273,16 @@ static int seunshare_mount(const char *src, const
char *dst, struct passwd *pwd)
        return -1;

+    /* Restore original mode bits and ownership */
+    if (chmod(dst, buf.st_mode) < 0) {
+        fprintf(stderr, _("Failed to set permissions on %s: %s\n"),
dst, strerror(errno));
+        return -1;
+    }
+    if (chown(dst, buf.st_uid, buf.st_gid) < 0) {
+        fprintf(stderr, _("Failed to set ownership on %s: %s\n"),
dst, strerror(errno));
+        return -1;
+    }
    if (verify_mount(dst, pwd) < 0)
        return -1;

More information about the ubuntu-hardened mailing list