mount, umount: restore environ[] after suid drop

The commands mount and umount sanitize environment variables as it
works with suid permissions by default. Since v2.36 it's possible
that the commands drop the permissions and continue as regular user.
It seems we also need to restore the original environ to keep things
consistent for users (e.g. HOME=).

The implementation is pretty simple -- it keeps in memory removed
variables and use it after switch to non-suid mode.

Addresses: https://github.com/karelzak/util-linux/issues/880
Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
Karel Zak 2020-08-25 10:48:29 +02:00
parent e113093ce9
commit f1f48270c9
2 changed files with 22 additions and 2 deletions

View File

@ -45,6 +45,8 @@
#define OPTUTILS_EXIT_CODE MNT_EX_USAGE
#include "optutils.h"
static struct ul_env_list *envs_removed;
static int mk_exit_code(struct libmnt_context *cxt, int rc);
static void suid_drop(struct libmnt_context *cxt)
@ -65,6 +67,13 @@ static void suid_drop(struct libmnt_context *cxt)
errx(MNT_EX_FAIL, _("drop permissions failed."));
mnt_context_force_unrestricted(cxt);
/* restore "bad" environment variables */
if (envs_removed) {
env_list_setenv(envs_removed);
env_list_free(envs_removed);
envs_removed = NULL;
}
}
static void __attribute__((__noreturn__)) mount_print_version(void)
@ -652,7 +661,7 @@ int main(int argc, char **argv)
};
int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT;
sanitize_env();
__sanitize_env(&envs_removed);
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
@ -991,6 +1000,7 @@ int main(int argc, char **argv)
success_message(cxt);
done:
mnt_free_context(cxt);
env_list_free(envs_removed);
return rc;
}

View File

@ -43,6 +43,7 @@
#include "optutils.h"
static int quiet;
static struct ul_env_list *envs_removed;
static int table_parser_errcb(struct libmnt_table *tb __attribute__((__unused__)),
const char *filename, int line)
@ -130,6 +131,13 @@ static void suid_drop(struct libmnt_context *cxt)
errx(MNT_EX_FAIL, _("drop permissions failed."));
mnt_context_force_unrestricted(cxt);
/* restore "bad" environment variables */
if (envs_removed) {
env_list_setenv(envs_removed);
env_list_free(envs_removed);
envs_removed = NULL;
}
}
static void success_message(struct libmnt_context *cxt)
@ -486,7 +494,7 @@ int main(int argc, char **argv)
};
int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT;
sanitize_env();
__sanitize_env(&envs_removed);
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
@ -621,6 +629,8 @@ int main(int argc, char **argv)
}
mnt_free_context(cxt);
env_list_free(envs_removed);
return (rc < 256) ? rc : 255;
}